commit
5f3eb6c00f
|
@ -0,0 +1,117 @@
|
|||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
import {StaggeredMotion, spring} from 'react-motion';
|
||||
import Menu from 'core-components/menu'
|
||||
|
||||
import DateTransformer from 'lib-core/date-transformer';
|
||||
import i18n from 'lib-app/i18n';
|
||||
|
||||
class PeopleList extends React.Component {
|
||||
static propTypes = {
|
||||
list: React.PropTypes.arrayOf(React.PropTypes.shape({
|
||||
profilePic: React.PropTypes.string,
|
||||
name: React.PropTypes.string,
|
||||
assignedTickets: React.PropTypes.number,
|
||||
closedTickets: React.PropTypes.number,
|
||||
lastLogin: React.PropTypes.number
|
||||
})),
|
||||
pageSize: React.PropTypes.number,
|
||||
page: React.PropTypes.number,
|
||||
onPageSelect: React.PropTypes.func
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
pageSize: 4,
|
||||
list: []
|
||||
};
|
||||
|
||||
render() {
|
||||
const pages = _.range(1, this.getPages() + 1).map((index) => {return {content: index};});
|
||||
|
||||
return (
|
||||
<div className="people-list">
|
||||
<div className="people-list__list">
|
||||
<StaggeredMotion defaultStyles={this.getDefaultStyles()} styles={this.getStyles.bind(this)}>
|
||||
{this.renderList.bind(this)}
|
||||
</StaggeredMotion>
|
||||
</div>
|
||||
<div className="people-list__pagination">
|
||||
<Menu type="navigation" items={pages} selectedIndex={this.props.page - 1} onItemClick={this.props.onPageSelect} tabbable/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
getDefaultStyles() {
|
||||
return _.times(this.props.pageSize).map(() => {return {offset: -100, alpha: 0}});
|
||||
}
|
||||
|
||||
getStyles(prevStyles) {
|
||||
return prevStyles.map((_, i) => {
|
||||
return i === 0
|
||||
? {offset: spring(0), alpha: spring(1)}
|
||||
: {offset: spring(prevStyles[i - 1].offset), alpha: spring(prevStyles[i - 1].alpha)}
|
||||
});
|
||||
}
|
||||
|
||||
renderList(styles) {
|
||||
return (
|
||||
<div>
|
||||
{styles.map(this.renderAnimatedItem.bind(this))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderAnimatedItem(style, index) {
|
||||
return (
|
||||
<div style={{transform: 'translateX('+style.offset+'px)', opacity: style.alpha}}>
|
||||
{this.renderItem(index + this.props.pageSize * (this.props.page - 1))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderItem(index) {
|
||||
if(index >= this.props.list.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const item = this.props.list[index];
|
||||
const minIndex = this.props.pageSize * (this.props.page - 1);
|
||||
const maxIndex = this.props.pageSize * this.props.page;
|
||||
|
||||
return (minIndex <= index && index < maxIndex) ? (
|
||||
<div className="people-list__item">
|
||||
<div className="people-list__item-profile-pic-wrapper">
|
||||
<img className="people-list__item-profile-pic" src={item.profilePic} />
|
||||
</div>
|
||||
<div className="people-list__item-block people-list__item-name">{item.name}</div>
|
||||
<div className="people-list__item-block people-list__item-assigned-tickets">
|
||||
{i18n('ASSIGNED_TICKETS', {tickets: item.assignedTickets})}
|
||||
</div>
|
||||
<div className="people-list__item-block people-list__item-closed-tickets">
|
||||
{i18n('CLOSED_TICKETS', {tickets: item.closedTickets})}
|
||||
</div>
|
||||
<div className="people-list__item-block people-list__item-last-login">
|
||||
<div>{i18n('LAST_LOGIN')}</div>
|
||||
<div>{DateTransformer.transformToString(item.lastLogin)}</div>
|
||||
</div>
|
||||
</div>
|
||||
) : null;
|
||||
}
|
||||
|
||||
getRowsQuantity() {
|
||||
if(this.props.page == this.getPages()){
|
||||
return this.props.list.length % this.props.pageSize;
|
||||
}
|
||||
else {
|
||||
return this.props.pageSize;
|
||||
}
|
||||
}
|
||||
|
||||
getPages() {
|
||||
return Math.ceil(this.props.list.length / this.props.pageSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default PeopleList;
|
|
@ -0,0 +1,64 @@
|
|||
@import "../scss/vars";
|
||||
|
||||
.people-list {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
|
||||
&__list {
|
||||
}
|
||||
|
||||
&__item {
|
||||
border: 2px solid $grey;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 12px;
|
||||
position: relative;
|
||||
height: 105px;
|
||||
padding-left: 60px;
|
||||
font-size: $font-size--md;
|
||||
|
||||
&-profile-pic-wrapper {
|
||||
vertical-align: top;
|
||||
background-color: $secondary-blue;
|
||||
color: white;
|
||||
border-radius: 5px;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
top: 20px;
|
||||
left: 20px;
|
||||
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
border: 2px solid $light-grey;
|
||||
}
|
||||
|
||||
&-profile-pic {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, 0)
|
||||
}
|
||||
|
||||
&-block {
|
||||
padding: 30px 0;
|
||||
width: 25%;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
&-assigned-tickets {
|
||||
|
||||
}
|
||||
|
||||
&-closed-tickets {
|
||||
|
||||
}
|
||||
|
||||
&-last-login {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
&__pagination {
|
||||
|
||||
}
|
||||
}
|
|
@ -1,14 +1,92 @@
|
|||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
|
||||
import i18n from 'lib-app/i18n';
|
||||
import API from 'lib-app/api-call';
|
||||
import SessionStore from 'lib-app/session-store';
|
||||
import PeopleList from 'app-components/people-list';
|
||||
|
||||
import Header from 'core-components/header';
|
||||
import DropDown from 'core-components/drop-down';
|
||||
import Button from 'core-components/button';
|
||||
import Icon from 'core-components/icon';
|
||||
import Loading from 'core-components/loading';
|
||||
|
||||
class AdminPanelStaffMembers extends React.Component {
|
||||
|
||||
state = {
|
||||
selectedDepartment: 0,
|
||||
staffList: [],
|
||||
loading: true,
|
||||
page: 1
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
API.call({
|
||||
path: '/staff/get-all',
|
||||
data: {}
|
||||
}).then(this.onStaffRetrieved.bind(this));
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
/admin/panel/staff/staff-members
|
||||
<div className="admin-panel-staff-members">
|
||||
<Header title={i18n('STAFF_MEMBERS')} description={i18n('STAFF_MEMBERS_DESCRIPTION')} />
|
||||
<div className="admin-panel-staff-members__wrapper">
|
||||
<DropDown {...this.getDepartmentDropdownProps()} className="admin-panel-staff-members__dropdown" />
|
||||
<Button size="medium" onClick={() => {}} type="secondary" className="admin-panel-staff-members__button">
|
||||
<Icon name="user-plus" className=""/> {i18n('ADD_NEW_STAFF')}
|
||||
</Button>
|
||||
</div>
|
||||
{(this.state.loading) ? <Loading backgrounded /> : <PeopleList list={this.getStaffList()} page={this.state.page} onPageSelect={(index) => this.setState({page: index+1})} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
getDepartmentDropdownProps() {
|
||||
return {
|
||||
items: this.getDepartments(),
|
||||
onChange: (event) => {
|
||||
let departments = SessionStore.getDepartments();
|
||||
this.setState({
|
||||
selectedDepartment: event.index && departments[event.index - 1].id,
|
||||
page: 1
|
||||
});
|
||||
},
|
||||
size: 'medium'
|
||||
};
|
||||
}
|
||||
|
||||
getStaffList() {
|
||||
if(!this.state.selectedDepartment) {
|
||||
return this.state.staffList;
|
||||
}
|
||||
|
||||
return _.filter(this.state.staffList, (o) => {
|
||||
return _.findIndex(o.departments, {id: this.state.selectedDepartment}) !== -1;
|
||||
});
|
||||
}
|
||||
|
||||
getDepartments() {
|
||||
let departments = SessionStore.getDepartments().map((department) => {
|
||||
return {content: department.name};
|
||||
});
|
||||
|
||||
departments.unshift({
|
||||
content: i18n('ALL_DEPARTMENTS')
|
||||
});
|
||||
|
||||
return departments;
|
||||
}
|
||||
|
||||
onStaffRetrieved(result) {
|
||||
if(result.status == 'success'){
|
||||
this.setState({
|
||||
loading: false,
|
||||
staffList: result.data
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default AdminPanelStaffMembers;
|
|
@ -0,0 +1,17 @@
|
|||
@import "../../../../scss/vars";
|
||||
|
||||
.admin-panel-staff-members {
|
||||
|
||||
&__wrapper {
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
&__dropdown {
|
||||
float: left;
|
||||
}
|
||||
|
||||
&__button {
|
||||
float: right;
|
||||
margin-top: -5px;
|
||||
}
|
||||
}
|
|
@ -13,35 +13,35 @@ module.exports = [
|
|||
iconColor: '#82CA9C',
|
||||
articles: [
|
||||
{
|
||||
id: 1,
|
||||
id: '1',
|
||||
title: 'Mannaging apps for your account',
|
||||
content: 'Curabitur sed dignissim turpis, sed lacinia urna. Vestibulum semper suscipit interdum. Proin sed sem gravida massa tristique rhoncus auctor eu diam. Donec fringilla in ex non dignissim. Praesent sed ultricies eros. Nullam vel augue eget libero volutpat sodales sit amet et orci.',
|
||||
lastEdited: 20160516,
|
||||
position: 1
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
id: '2',
|
||||
title: 'How to assign new task and files',
|
||||
content: 'Aliquam aliquet mi nulla. Nam vel orci diam. Suspendisse euismod orci efficitur nulla mattis eleifend vitae quis neque. Etiam orci dolor, dignissim quis convallis quis, rhoncus eu tellus. Phasellus aliquam ut enim id ultrices. Nunc dolor arcu, viverra vel ullamcorper nec, dignissim a lectus. Praesent fringilla, neque nec suscipit placerat, augue elit suscipit velit, in feugiat leo justo id tortor.',
|
||||
lastEdited: 20150429,
|
||||
position: 2
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
id: '3',
|
||||
title: 'Updating your profile picture',
|
||||
content: 'Aliquam aliquet mi nulla. Nam vel orci diam. Suspendisse euismod orci efficitur nulla mattis eleifend vitae quis neque. Etiam orci dolor, dignissim quis convallis quis, rhoncus eu tellus. Phasellus aliquam ut enim id ultrices. Nunc dolor arcu, viverra vel ullamcorper nec, dignissim a lectus. Praesent fringilla, neque nec suscipit placerat, augue elit suscipit velit, in feugiat leo justo id tortor.',
|
||||
lastEdited: 20150429,
|
||||
position: 3
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
id: '4',
|
||||
title: 'Deleting your account',
|
||||
content: 'Aliquam aliquet mi nulla. Nam vel orci diam. Suspendisse euismod orci efficitur nulla mattis eleifend vitae quis neque. Etiam orci dolor, dignissim quis convallis quis, rhoncus eu tellus. Phasellus aliquam ut enim id ultrices. Nunc dolor arcu, viverra vel ullamcorper nec, dignissim a lectus. Praesent fringilla, neque nec suscipit placerat, augue elit suscipit velit, in feugiat leo justo id tortor.',
|
||||
lastEdited: 20150929,
|
||||
position: 4
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
id: '5',
|
||||
title: 'Upload files to your cloud drive',
|
||||
content: 'Aliquam aliquet mi nulla. Nam vel orci diam. Suspendisse euismod orci efficitur nulla mattis eleifend vitae quis neque. Etiam orci dolor, dignissim quis convallis quis, rhoncus eu tellus. Phasellus aliquam ut enim id ultrices. Nunc dolor arcu, viverra vel ullamcorper nec, dignissim a lectus. Praesent fringilla, neque nec suscipit placerat, augue elit suscipit velit, in feugiat leo justo id tortor.',
|
||||
lastEdited: 20131229,
|
||||
|
@ -56,35 +56,35 @@ module.exports = [
|
|||
iconColor: 'red',
|
||||
articles: [
|
||||
{
|
||||
id: 1,
|
||||
id: '1',
|
||||
title: 'Mannaging apps for your account',
|
||||
content: 'Curabitur sed dignissim turpis, sed lacinia urna. Vestibulum semper suscipit interdum. Proin sed sem gravida massa tristique rhoncus auctor eu diam. Donec fringilla in ex non dignissim. Praesent sed ultricies eros. Nullam vel augue eget libero volutpat sodales sit amet et orci.',
|
||||
lastEdited: 20160516,
|
||||
position: 1
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
id: '2',
|
||||
title: 'How to assign new task and files',
|
||||
content: 'Aliquam aliquet mi nulla. Nam vel orci diam. Suspendisse euismod orci efficitur nulla mattis eleifend vitae quis neque. Etiam orci dolor, dignissim quis convallis quis, rhoncus eu tellus. Phasellus aliquam ut enim id ultrices. Nunc dolor arcu, viverra vel ullamcorper nec, dignissim a lectus. Praesent fringilla, neque nec suscipit placerat, augue elit suscipit velit, in feugiat leo justo id tortor.',
|
||||
lastEdited: 20150429,
|
||||
position: 2
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
id: '3',
|
||||
title: 'Updating your profile picture',
|
||||
content: 'Aliquam aliquet mi nulla. Nam vel orci diam. Suspendisse euismod orci efficitur nulla mattis eleifend vitae quis neque. Etiam orci dolor, dignissim quis convallis quis, rhoncus eu tellus. Phasellus aliquam ut enim id ultrices. Nunc dolor arcu, viverra vel ullamcorper nec, dignissim a lectus. Praesent fringilla, neque nec suscipit placerat, augue elit suscipit velit, in feugiat leo justo id tortor.',
|
||||
lastEdited: 20150429,
|
||||
position: 3
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
id: '4',
|
||||
title: 'Deleting your account',
|
||||
content: 'Aliquam aliquet mi nulla. Nam vel orci diam. Suspendisse euismod orci efficitur nulla mattis eleifend vitae quis neque. Etiam orci dolor, dignissim quis convallis quis, rhoncus eu tellus. Phasellus aliquam ut enim id ultrices. Nunc dolor arcu, viverra vel ullamcorper nec, dignissim a lectus. Praesent fringilla, neque nec suscipit placerat, augue elit suscipit velit, in feugiat leo justo id tortor.',
|
||||
lastEdited: 20150929,
|
||||
position: 4
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
id: '5',
|
||||
title: 'Upload files to your cloud drive',
|
||||
content: 'Aliquam aliquet mi nulla. Nam vel orci diam. Suspendisse euismod orci efficitur nulla mattis eleifend vitae quis neque. Etiam orci dolor, dignissim quis convallis quis, rhoncus eu tellus. Phasellus aliquam ut enim id ultrices. Nunc dolor arcu, viverra vel ullamcorper nec, dignissim a lectus. Praesent fringilla, neque nec suscipit placerat, augue elit suscipit velit, in feugiat leo justo id tortor.',
|
||||
lastEdited: 20131229,
|
||||
|
|
|
@ -578,5 +578,57 @@ module.exports = [
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/staff/get-all',
|
||||
time: 100,
|
||||
response: function() {
|
||||
return {
|
||||
status: 'success',
|
||||
data: [
|
||||
{
|
||||
profilePic: 'http://www.opensupports.com/profilepic.jpg',
|
||||
name: 'Emilia Clarke',
|
||||
departments: [{id: 2, name: 'Technical issues'}],
|
||||
assignedTickets: 4,
|
||||
closedTickets: 21,
|
||||
lastLogin: 20161212
|
||||
},
|
||||
{
|
||||
profilePic: 'http://www.opensupports.com/profilepic.jpg',
|
||||
name: 'Yulian A GUI Yermo',
|
||||
departments: [{id: 2, name: 'Technical issues'}, {id: 1, name: 'Sales Support'}],
|
||||
assignedTickets: 9,
|
||||
closedTickets: 0,
|
||||
lastLogin: 20161212
|
||||
},
|
||||
{
|
||||
profilePic: 'http://www.opensupports.com/profilepic.jpg',
|
||||
name: 'Miltona Costa',
|
||||
departments: [{id: 1, name: 'Sales Support'}],
|
||||
assignedTickets: -1,
|
||||
closedTickets: -1,
|
||||
lastLogin: 20160212
|
||||
},
|
||||
{
|
||||
profilePic: 'http://www.opensupports.com/profilepic.jpg',
|
||||
name: 'Emiliasnikova Rusachestkvuy',
|
||||
departments: [{id: 1, name: 'Sales Support'}, {id: 3, name: 'System and Administration'}],
|
||||
assignedTickets: 100,
|
||||
closedTickets: 21,
|
||||
lastLogin: 20130101
|
||||
},
|
||||
{
|
||||
profilePic: 'http://www.opensupports.com/profilepic.jpg',
|
||||
name: 'Laurita Morrechaga Rusachestkvuy',
|
||||
departments: [{id: 3, name: 'System and Administration'}],
|
||||
assignedTickets: 1,
|
||||
closedTickets: 1,
|
||||
lastLogin: 2012050
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
];
|
|
@ -94,6 +94,11 @@ export default {
|
|||
'EDIT': 'Edit',
|
||||
'NO_RESULTS': 'No results',
|
||||
'DELETE_AND_BAN': 'Delete and ban',
|
||||
'ASSIGNED_TICKETS': '{tickets} assigned tickets',
|
||||
'CLOSED_TICKETS': '{tickets} closed tickets',
|
||||
'LAST_LOGIN': 'Last login',
|
||||
'STAFF_MEMBERS': 'Staff members',
|
||||
'ADD_NEW_STAFF': 'Add new staff',
|
||||
|
||||
//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.',
|
||||
|
@ -116,6 +121,7 @@ export default {
|
|||
'ADD_ARTICLE_DESCRIPTION': 'Here you can add an article that will be available for every user. It will be added inside the category {category}.',
|
||||
'LIST_ARTICLES_DESCRIPTION': 'This is a list of articles that includes information about our services.',
|
||||
'ADD_TOPIC_DESCRIPTION': 'Here you can add a topic that works as a category for articles.',
|
||||
'STAFF_MEMBERS_DESCRIPTION': 'Here you can see who are your staff members.',
|
||||
|
||||
//ERRORS
|
||||
'EMAIL_OR_PASSWORD': 'Email or password invalid',
|
||||
|
|
Loading…
Reference in New Issue