Merged in OS-99-list-users-view (pull request #82)
OS-99 list users view
This commit is contained in:
commit
b2ac69a8ad
|
@ -1,14 +1,162 @@
|
|||
import React from 'react';
|
||||
|
||||
import i18n from 'lib-app/i18n';
|
||||
import API from 'lib-app/api-call';
|
||||
import DateTransformer from 'lib-core/date-transformer';
|
||||
|
||||
import Header from 'core-components/header';
|
||||
import Table from 'core-components/table';
|
||||
import SearchBox from 'core-components/search-box';
|
||||
import Button from 'core-components/button';
|
||||
|
||||
class AdminPanelListUsers extends React.Component {
|
||||
|
||||
state = {
|
||||
loading: true,
|
||||
users: [],
|
||||
orderBy: 'id',
|
||||
desc: true,
|
||||
page: 1,
|
||||
pages: 1
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this.retrieveUsers({
|
||||
page: 1,
|
||||
orderBy: 'id',
|
||||
desc: true,
|
||||
search: ''
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
/admin/panel/users/list-users
|
||||
<div className="admin-panel-list-users">
|
||||
<Header title={i18n('LIST_USERS')} description={i18n('LIST_USERS_DESCRIPTION')} />
|
||||
<SearchBox className="admin-panel-list-users__search-box" placeholder={i18n('SEARCH_USERS')} onSearch={this.onSearch.bind(this)} />
|
||||
<Table {...this.getTableProps()} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
getTableProps() {
|
||||
return {
|
||||
className: 'admin-panel-list-users__table',
|
||||
loading: this.state.loading,
|
||||
headers: this.getTableHeaders(),
|
||||
rows: this.state.users.map(this.getUserRow.bind(this)),
|
||||
pageSize: 10,
|
||||
page: this.state.page,
|
||||
pages: this.state.pages,
|
||||
onPageChange: this.onPageChange.bind(this)
|
||||
};
|
||||
}
|
||||
|
||||
getTableHeaders() {
|
||||
return [
|
||||
{
|
||||
key: 'name',
|
||||
value: i18n('NAME'),
|
||||
className: 'admin-panel-list-users__table-name col-md-3'
|
||||
},
|
||||
{
|
||||
key: 'email',
|
||||
value: i18n('EMAIL'),
|
||||
className: 'admin-panel-list-users__table-email col-md-5'
|
||||
},
|
||||
{
|
||||
key: 'tickets',
|
||||
value: i18n('TICKETS'),
|
||||
className: 'admin-panel-list-users__table-tickets col-md-2',
|
||||
order: true,
|
||||
onOrderUp: this.orderByTickets.bind(this, false),
|
||||
onOrderDown: this.orderByTickets.bind(this, true)
|
||||
},
|
||||
{
|
||||
key: 'signupDate',
|
||||
value: i18n('SIGNUP_DATE'),
|
||||
className: 'admin-panel-list-users__table-date col-md-2',
|
||||
order: true,
|
||||
onOrderUp: this.orderById.bind(this, false),
|
||||
onOrderDown: this.orderById.bind(this, true)
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
getUserRow(user) {
|
||||
return {
|
||||
name: (
|
||||
<Button className="admin-panel-list-users__name-link" type="link" route={{to: '/admin/panel/users/view-user/' + user.id}}>
|
||||
{user.name}
|
||||
</Button>
|
||||
),
|
||||
email: user.email,
|
||||
tickets: (
|
||||
<span className="admin-panel-list-users__tickets-number">
|
||||
{user.tickets}
|
||||
</span>
|
||||
),
|
||||
signupDate: DateTransformer.transformToString(user.signupDate)
|
||||
};
|
||||
}
|
||||
|
||||
onSearch(query) {
|
||||
this.retrieveUsers({
|
||||
page: 1,
|
||||
orderBy: 'id',
|
||||
desc: true,
|
||||
search: query
|
||||
});
|
||||
}
|
||||
|
||||
onPageChange(event) {
|
||||
this.retrieveUsers({
|
||||
page: event.target.value,
|
||||
orderBy: this.state.orderBy,
|
||||
desc: this.state.desc,
|
||||
search: this.state.search
|
||||
});
|
||||
}
|
||||
|
||||
orderByTickets(desc) {
|
||||
this.retrieveUsers({
|
||||
page: 1,
|
||||
orderBy: 'tickets',
|
||||
desc: desc,
|
||||
search: this.state.search
|
||||
});
|
||||
}
|
||||
|
||||
orderById(desc) {
|
||||
this.retrieveUsers({
|
||||
page: 1,
|
||||
orderBy: 'id',
|
||||
desc: desc,
|
||||
search: this.state.search
|
||||
});
|
||||
}
|
||||
|
||||
retrieveUsers(data) {
|
||||
this.setState({
|
||||
loading: true
|
||||
});
|
||||
|
||||
API.call({
|
||||
path: '/user/get-users',
|
||||
data: data
|
||||
}).then(this.onUsersRetrieved.bind(this));
|
||||
}
|
||||
|
||||
onUsersRetrieved(result) {
|
||||
this.setState({
|
||||
page: result.data.page,
|
||||
pages: result.data.pages,
|
||||
users: result.data.users,
|
||||
orderBy: result.data.orderBy,
|
||||
desc: result.data.desc,
|
||||
loading: false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default AdminPanelListUsers;
|
|
@ -0,0 +1,24 @@
|
|||
@import '../../../../scss/vars';
|
||||
|
||||
.admin-panel-list-users {
|
||||
|
||||
&__search-box {
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
&__table {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
&__name-link {
|
||||
color: $secondary-blue;
|
||||
}
|
||||
|
||||
&__tickets-number {
|
||||
background-color: white;
|
||||
border-radius: 10px;
|
||||
width: 70px;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import Input from 'core-components/input';
|
||||
import Icon from 'core-components/icon';
|
||||
|
@ -7,7 +8,8 @@ import keyCode from 'keycode';
|
|||
class SearchBox extends React.Component {
|
||||
|
||||
static propTypes = {
|
||||
onSearch: React.PropTypes.func
|
||||
onSearch: React.PropTypes.func,
|
||||
placeholder: React.PropTypes.string
|
||||
};
|
||||
|
||||
state = {
|
||||
|
@ -16,8 +18,8 @@ class SearchBox extends React.Component {
|
|||
|
||||
render() {
|
||||
return (
|
||||
<div className="search-box">
|
||||
<Input className="search-box__text" value={this.state.value} onChange={this.onChange.bind(this)} onKeyDown={this.onKeyDown.bind(this)} />
|
||||
<div className={this.getClass()}>
|
||||
<Input className="search-box__text" value={this.state.value} placeholder={this.props.placeholder} onChange={this.onChange.bind(this)} onKeyDown={this.onKeyDown.bind(this)} />
|
||||
<span className="search-box__icon">
|
||||
<Icon name="search" />
|
||||
</span>
|
||||
|
@ -25,6 +27,16 @@ class SearchBox extends React.Component {
|
|||
);
|
||||
}
|
||||
|
||||
getClass() {
|
||||
let classes = {
|
||||
'search-box': true
|
||||
};
|
||||
|
||||
classes[this.props.className] = (this.props.className);
|
||||
|
||||
return classNames(classes);
|
||||
}
|
||||
|
||||
onChange(event) {
|
||||
this.setState({
|
||||
value: event.target.value
|
||||
|
|
|
@ -3,6 +3,7 @@ import _ from 'lodash';
|
|||
import classNames from 'classnames';
|
||||
|
||||
import Menu from 'core-components/menu';
|
||||
import Icon from 'core-components/icon';
|
||||
import Loading from 'core-components/loading';
|
||||
|
||||
class Table extends React.Component {
|
||||
|
@ -32,7 +33,7 @@ class Table extends React.Component {
|
|||
|
||||
render() {
|
||||
return (
|
||||
<div className="table__wrapper">
|
||||
<div className={this.getClass()}>
|
||||
<table className="table table-responsive">
|
||||
<thead>
|
||||
<tr className="table__header">
|
||||
|
@ -56,7 +57,23 @@ class Table extends React.Component {
|
|||
};
|
||||
|
||||
return (
|
||||
<th className={classNames(classes)} key={header.key}>{header.value}</th>
|
||||
<th className={classNames(classes)} key={header.key}>
|
||||
{header.value}
|
||||
{(header.order) ? this.renderHeaderArrows(header.onOrderUp, header.onOrderDown) : null}
|
||||
</th>
|
||||
);
|
||||
}
|
||||
|
||||
renderHeaderArrows(onArrowUp, onArrowDown) {
|
||||
return (
|
||||
<span className="table__header-arrows">
|
||||
<span className="table__header-arrow-up" onClick={onArrowUp}>
|
||||
<Icon name="arrow-up"/>
|
||||
</span>
|
||||
<span className="table__header-arrow-down" onClick={onArrowDown}>
|
||||
<Icon name="arrow-down"/>
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -92,7 +109,7 @@ class Table extends React.Component {
|
|||
const items = _.range(1, this.getPages()).map((index) => {return {content: index};});
|
||||
|
||||
return (
|
||||
<Menu className="table__navigation" type="navigation" items={items} selectedIndex={this.getPageNumber() - 1} onItemClick={this.onNavigationItemClick.bind(this)} />
|
||||
<Menu className="table__navigation" type="navigation" items={items} selectedIndex={this.getPageNumber() - 1} onItemClick={this.onNavigationItemClick.bind(this)} tabbable/>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -104,6 +121,16 @@ class Table extends React.Component {
|
|||
)
|
||||
}
|
||||
|
||||
getClass() {
|
||||
let classes = {
|
||||
'table__wrapper': true
|
||||
};
|
||||
|
||||
classes[this.props.className] = (this.props.className);
|
||||
|
||||
return classNames(classes);
|
||||
}
|
||||
|
||||
onNavigationItemClick(index) {
|
||||
this.setState({
|
||||
page: index + 1
|
||||
|
|
|
@ -7,6 +7,18 @@
|
|||
background-color: $primary-blue;
|
||||
color: white;
|
||||
font-weight: normal;
|
||||
|
||||
&-arrow-up {
|
||||
cursor: pointer;
|
||||
font-size: $font-size--xs;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
&-arrow-down {
|
||||
cursor: pointer;
|
||||
font-size: $font-size--xs;
|
||||
margin-left: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
&__header-column {
|
||||
|
|
|
@ -124,6 +124,94 @@ module.exports = [
|
|||
};
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/user/get-users',
|
||||
time: 100,
|
||||
response: function (data) {
|
||||
return {
|
||||
status: 'success',
|
||||
data: {
|
||||
page: data.page,
|
||||
pages: 10,
|
||||
orderBy: 'date',
|
||||
desc: true,
|
||||
search: '',
|
||||
users: [
|
||||
{
|
||||
id: 101,
|
||||
name: 'Haskell Curry',
|
||||
email: 'haskell@currycurrylady.com',
|
||||
tickets: 5,
|
||||
signupDate: 20160415
|
||||
},
|
||||
{
|
||||
id: 97,
|
||||
name: 'Alan Turing',
|
||||
email: 'turing@currycurrylady.com',
|
||||
tickets: 1,
|
||||
signupDate: 20160401
|
||||
},
|
||||
{
|
||||
id: 89,
|
||||
name: 'David Hilbert',
|
||||
email: 'hilbert@currycurrylady.com',
|
||||
tickets: 2,
|
||||
signupDate: 20160208
|
||||
},
|
||||
{
|
||||
id: 83,
|
||||
name: 'Kurt Gödel',
|
||||
email: 'kurt@currycurrylady.com',
|
||||
tickets: 10,
|
||||
signupDate: 20160110
|
||||
},
|
||||
{
|
||||
id: 79,
|
||||
name: 'Mojzesz Presburger',
|
||||
email: 'presburger@currycurrylady.com',
|
||||
tickets: 6,
|
||||
signupDate: 20150415
|
||||
},
|
||||
{
|
||||
id: 73,
|
||||
name: 'Haskell Curry',
|
||||
email: 'haskell@currycurrylady.com',
|
||||
tickets: 5,
|
||||
signupDate: 20160415
|
||||
},
|
||||
{
|
||||
id: 71,
|
||||
name: 'Alan Turing',
|
||||
email: 'turing@currycurrylady.com',
|
||||
tickets: 1,
|
||||
signupDate: 20160401
|
||||
},
|
||||
{
|
||||
id: 67,
|
||||
name: 'David Hilbert',
|
||||
email: 'hilbert@currycurrylady.com',
|
||||
tickets: 2,
|
||||
signupDate: 20160208
|
||||
},
|
||||
{
|
||||
id: 61,
|
||||
name: 'Kurt Gödel',
|
||||
email: 'kurt@currycurrylady.com',
|
||||
tickets: 10,
|
||||
signupDate: 20160110
|
||||
},
|
||||
{
|
||||
id: 59,
|
||||
name: 'Mojzesz Presburger',
|
||||
email: 'presburger@currycurrylady.com',
|
||||
tickets: 6,
|
||||
signupDate: 20150415
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/user/get',
|
||||
time: 100,
|
||||
|
|
|
@ -75,6 +75,9 @@ export default {
|
|||
'WARNING': 'Warning',
|
||||
'INFO': 'Information',
|
||||
'ALL_DEPARTMENTS': 'All Departments',
|
||||
'NAME': 'Name',
|
||||
'SIGNUP_DATE': 'Sign up date',
|
||||
'SEARCH_USERS': 'Search users...',
|
||||
|
||||
//VIEW DESCRIPTIONS
|
||||
'CREATE_TICKET_DESCRIPTION': 'This is a form for creating tickets. Fill the form and send us your issues/doubts/suggestions. Our support system will answer it as soon as possible.',
|
||||
|
@ -88,6 +91,7 @@ export default {
|
|||
'NEW_TICKETS_DESCRIPTION': 'Here you can view all the new tickets that are not assigned by anyone.',
|
||||
'ALL_TICKETS_DESCRIPTION': 'Here you can view the tickets of the departments you are assigned.',
|
||||
'TICKET_VIEW_DESCRIPTION': 'This ticket has been sent by a customer. Here you can respond or assign the ticket',
|
||||
'LIST_USERS_DESCRIPTION': 'This is the list of users that are registered in this platform. You can search for someone in particular, delete it or ban it.',
|
||||
|
||||
//ERRORS
|
||||
'EMAIL_OR_PASSWORD': 'Email or password invalid',
|
||||
|
|
|
@ -2,6 +2,7 @@ let month = ["", "Jan", "Feb", "Mar", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
|
|||
|
||||
export default {
|
||||
transformToString (date) {
|
||||
date += ''; //Transform to string
|
||||
let y = date.substring(0, 4);
|
||||
let m = date.substring(4, 6);
|
||||
let d = date.substring(6, 8);
|
||||
|
|
Loading…
Reference in New Issue