Merge branch 'master' into os-125-admin-departments-view

# Conflicts:
#	client/src/data/fixtures/staff-fixtures.js
This commit is contained in:
ivan 2016-12-12 18:05:12 -03:00
commit dbc7f155f4
26 changed files with 992 additions and 38 deletions

View File

@ -58,7 +58,7 @@ class ArticlesList extends React.Component {
editable={this.props.editable}
onChange={this.retrieveArticles.bind(this)}
articlePath={this.props.articlePath} />
<span className="articles-list__topic-separator" />
<span className="separator" />
</div>
);
})}

View File

@ -11,12 +11,4 @@
left: 10px;
margin-top: -4px;
}
&__topic-separator {
background-color: $grey;
display: block;
height: 1px;
margin: 30px 0;
width: 100%;
}
}

View File

@ -13,7 +13,7 @@
margin-bottom: 12px;
position: relative;
height: 105px;
padding-left: 60px;
padding-left: 95px;
font-size: $font-size--md;
&-profile-pic-wrapper {

View File

@ -103,7 +103,7 @@ export default (
<Route path="staff">
<IndexRedirect to="staff-members" />
<Route path="staff-members" component={AdminPanelStaffMembers} />
<Route path="view-staff" component={AdminPanelViewStaff} />
<Route path="view-staff/:staffId" component={AdminPanelViewStaff} />
<Route path="departments" component={AdminPanelDepartments} />
</Route>

View File

@ -1,14 +1,36 @@
import React from 'react';
import {connect} from 'react-redux';
import _ from 'lodash';
import i18n from 'lib-app/i18n';
import API from 'lib-app/api-call';
import SessionActions from 'actions/session-actions';
import StaffEditor from 'app/admin/panel/staff/staff-editor';
import Header from 'core-components/header';
class AdminPanelMyAccount extends React.Component {
render() {
return (
<div>
/admin/panel/my-account
<div className="admin-panel-view-staff">
<Header title={i18n('MY_ACCOUNT')} description={i18n('MY_ACCOUNT_DESCRIPTION')} />
<StaffEditor {...this.getEditorProps()}/>
</div>
);
}
getEditorProps() {
return {
myAccount: true,
name: this.props.userName,
email: this.props.userEmail,
profilePic: this.props.userProfilePic,
level: this.props.userLevel,
departments: this.props.userDepartments,
onChange: () => this.props.dispatch(SessionActions.getUserData(null, null, true))
};
}
}
export default AdminPanelMyAccount;
export default connect((store) => store.session)(AdminPanelMyAccount);

View File

@ -35,9 +35,9 @@ class AddStaffModal extends React.Component {
<FormField name="password" label={i18n('PASSWORD')} fieldProps={{size: 'large', password: true}} validation="PASSWORD" required />
<div className="add-staff-modal__level-selector">
<FormField name="level" label={i18n('LEVEL')} field="select" fieldProps={{
items: [{content: i18n('LEVEL_1')}, {content: i18n('LEVEL_2')}, {content: i18n('LEVEL_3')}],
size: 'large'
}} />
items: [{content: i18n('LEVEL_1')}, {content: i18n('LEVEL_2')}, {content: i18n('LEVEL_3')}],
size: 'large'
}} />
</div>
</div>
<div className="col-md-5">

View File

@ -1,4 +1,5 @@
import React from 'react';
import {Link} from 'react-router';
import _ from 'lodash';
import i18n from 'lib-app/i18n';
@ -65,12 +66,24 @@ class AdminPanelStaffMembers extends React.Component {
}
getStaffList() {
let staffList;
if(!this.state.selectedDepartment) {
return this.state.staffList;
staffList = this.state.staffList;
} else {
staffList = _.filter(this.state.staffList, (o) => {
return _.findIndex(o.departments, {id: this.state.selectedDepartment}) !== -1;
})
}
return _.filter(this.state.staffList, (o) => {
return _.findIndex(o.departments, {id: this.state.selectedDepartment}) !== -1;
return staffList.map(staff => {
return _.extend({}, staff, {
name: (
<Link className="admin-panel-staff-members__link" to={'/admin/panel/staff/view-staff/' + staff.id}>
{staff.name}
</Link>
)
});
});
}

View File

@ -14,4 +14,13 @@
float: right;
margin-top: -5px;
}
&__link {
color: $primary-black;
&:hover {
color: $primary-black;
text-decoration: none;
}
}
}

View File

@ -1,14 +1,51 @@
import React from 'react';
import {connect} from 'react-redux';
import _ from 'lodash';
import i18n from 'lib-app/i18n';
import API from 'lib-app/api-call';
import StaffEditor from 'app/admin/panel/staff/staff-editor';
import Header from 'core-components/header';
import Loading from 'core-components/loading';
class AdminPanelViewStaff extends React.Component {
state = {
loading: true,
userData: {}
};
componentDidMount() {
API.call({
path: '/staff/get',
data: {
staffId: this.props.params.staffId
}
}).then(this.onStaffRetrieved.bind(this));
}
render() {
return (
<div>
/admin/panel/staff/view-staff
<div className="admin-panel-view-staff">
<Header title={i18n('EDIT_STAFF')} description={i18n('EDIT_STAFF_DESCRIPTION')} />
{(this.state.loading) ? <Loading /> : <StaffEditor {...this.getProps()} />}
</div>
);
}
getProps() {
return _.extend({}, this.state.userData, {
staffId: this.props.params.staffId * 1
});
}
onStaffRetrieved(result) {
this.setState({
loading: false,
userData: result.data
});
}
}
export default AdminPanelViewStaff;

View File

@ -0,0 +1,181 @@
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 TicketList from 'app-components/ticket-list';
import Form from 'core-components/form';
import FormField from 'core-components/form-field';
import SubmitButton from 'core-components/submit-button';
class StaffEditor extends React.Component {
static propTypes = {
myAccount: React.PropTypes.bool,
staffId: React.PropTypes.number,
email: React.PropTypes.string.isRequired,
name: React.PropTypes.string.isRequired,
profilePic: React.PropTypes.string.isRequired,
level: React.PropTypes.number.isRequired,
tickets: React.PropTypes.array.isRequired,
departments: React.PropTypes.array.isRequired,
onChange: React.PropTypes.func
};
state = {
email: this.props.email,
level: this.props.level - 1,
departments: this.getUserDepartments()
};
render() {
return (
<div className="staff-editor">
<div className="row">
<div className="col-md-4">
<div className="staff-editor__card">
<div className="staff-editor__card-data">
<div className="staff-editor__card-name">
{this.props.name}
</div>
<div className="staff-editor__card-info">
<div className="staff-editor__card-badge">
<span className="staff-editor__card-badge-blue">
{this.props.level}
</span>
<span className="staff-editor__card-badge-text">{i18n('STAFF_LEVEL')}</span>
</div>
<div className="staff-editor__card-badge">
<span className="staff-editor__card-badge-green">
{_.filter(this.props.tickets, {closed: false}).length}
</span>
<span className="staff-editor__card-badge-text">{i18n('ASSIGNED')}</span>
</div>
<div className="staff-editor__card-badge">
<span className="staff-editor__card-badge-red">
{_.filter(this.props.tickets, {closed: true}).length}
</span>
<span className="staff-editor__card-badge-text">{i18n('CLOSED')}</span>
</div>
</div>
</div>
<div className="staff-editor__card-pic-wrapper">
<img className="staff-editor__card-pic" src={this.props.profilePic} />
</div>
</div>
</div>
<div className="col-md-8">
<div className="staff-editor__form">
<Form className="staff-editor__update-email" values={{email: this.state.email}} onChange={form => this.setState({email: form.email})} onSubmit={this.onSubmit.bind(this)}>
<FormField name="email" validation="EMAIL" required label={i18n('EMAIL')} fieldProps={{size: 'large'}}/>
<SubmitButton size="medium" className="staff-editor__submit-button">{i18n('UPDATE_EMAIL')}</SubmitButton>
</Form>
<span className="separator staff-editor__separator" />
<Form className="staff-editor__update-password" onSubmit={this.onSubmit.bind(this)}>
<FormField name="password" validation="PASSWORD" required label={i18n('PASSWORD')} fieldProps={{size: 'large'}}/>
<FormField name="rpassword" validation="REPEAT_PASSWORD" required label={i18n('REPEAT_PASSWORD')} fieldProps={{size: 'large'}}/>
<SubmitButton size="medium" className="staff-editor__submit-button">{i18n('UPDATE_PASSWORD')}</SubmitButton>
</Form>
{(!this.props.myAccount) ? this.renderLevelForm() : null}
<span className="separator staff-editor__separator" />
</div>
</div>
</div>
<div className="row">
<div className="col-md-4">
<div className="staff-editor__departments">
<div className="staff-editor__departments-title">{i18n('Departments')}</div>
<Form values={{departments: this.state.departments}} onChange={form => this.setState({departments: form.departments})} onSubmit={this.onSubmit.bind(this)}>
<FormField name="departments" field="checkbox-group" fieldProps={{items: this.getDepartments()}} />
<SubmitButton size="medium">{i18n('UPDATE_DEPARTMENTS')}</SubmitButton>
</Form>
</div>
</div>
<div className="col-md-8">
<div className="staff-editor__activity">
ACTIVITY
</div>
</div>
</div>
{(this.props.tickets) ? this.renderTickets() : null}
</div>
);
}
renderLevelForm() {
return (
<div>
<span className="separator staff-editor__separator"/>
<Form className="staff-editor__update-level" values={{level: this.state.level}} onChange={form => this.setState({level: form.level})} onSubmit={this.onSubmit.bind(this)}>
<FormField name="level" label={i18n('LEVEL')} field="select" fieldProps={{
items: [{content: i18n('LEVEL_1')}, {content: i18n('LEVEL_2')}, {content: i18n('LEVEL_3')}],
size: 'large'
}} />
<SubmitButton size="medium" className="staff-editor__submit-button">{i18n('UPDATE_LEVEL')}</SubmitButton>
</Form>
</div>
);
}
renderTickets() {
return (
<div>
<span className="separator"/>
<div className="staff-editor__tickets">
<div className="staff-editor__tickets-title">{i18n('TICKETS')}</div>
<TicketList {...this.getTicketListProps()}/>
</div>
</div>
);
}
getTicketListProps() {
return {
type: 'secondary',
tickets: this.props.tickets,
departments: this.props.departments,
ticketPath: '/admin/panel/tickets/view-ticket/'
};
}
getUserDepartments() {
let userDepartments = this.props.departments.map(department => department.name);
let departmentIndexes = [];
_.forEach(this.getDepartments(), (department, index) => {
if(_.includes(userDepartments, department)) {
departmentIndexes.push(index);
}
});
return departmentIndexes;
}
getDepartments() {
return SessionStore.getDepartments().map(department => department.name);
}
onSubmit(form) {
let departments;
if(form.departments) {
departments = _.filter(SessionStore.getDepartments(), (department, index) => {
return _.includes(form.departments, index);
}).map(department => department.id)
}
API.call({
path: '/staff/edit',
data: {
staffId: this.props.staffId,
email: form.email,
password: form.password,
level: (form.level !== undefined) ? form.level + 1 : null,
departments: departments && JSON.stringify(departments)
}
}).then(this.props.onChange);
}
}
export default StaffEditor;

View File

@ -0,0 +1,125 @@
@import '../../../../scss/vars';
.staff-editor {
&__card {
background-color: $primary-red;
position: relative;
width: 100%;
height: 355px;
text-align: center;
border: 2px solid $grey;
margin-bottom: 20px;
&-pic {
height: 100%;
position: absolute;
left: 50%;
transform: translate(-50%, 0);
&-wrapper {
position: absolute;
top: 20px;
border: 4px solid $grey;
border-radius: 50%;
width: 200px;
height: 200px;
overflow: hidden;
text-align: center;
left: 50%;
transform: translate(-50%, 0);
}
}
&-data {
position: absolute;
background-color: white;
bottom: 0;
width: 100%;
height: 175px;
padding-top: 50px;
}
&-name {
font-size: $font-size--lg;
}
&-info {
padding-top: 30px;
}
&-badge {
display: inline-block;
width: 33%;
&-text {
display: block;
}
&-red,
&-green,
&-blue {
border-radius: 4px;
color: white;
display: inline-block;
width: 70%;
margin-bottom: 5px;
}
&-red {
background-color: $primary-red;
}
&-green {
background-color: $primary-green;
}
&-blue {
background-color: $secondary-blue;
}
}
}
&__form {
}
&__submit-button {
position: absolute;
bottom: 0;
right: 0;
width: 180px;
}
&__update-email,
&__update-password,
&__update-level {
position: relative;
}
&__departments {
border: 1px solid $grey;
padding: 20px 50px;
text-align: left;
}
&__departments-title {
font-size: $font-size--md;
text-align: center;
}
&__tickets {
padding: 0 20px;
margin-top: 20px;
}
&__tickets-title {
font-size: $font-size--md;
text-align: left;
margin-bottom: 20px;
}
&__separator {
margin: 3px 0;
}
}

View File

@ -68,7 +68,7 @@ class AdminPanelViewUser extends React.Component {
<Button onClick={this.onDeleteClick.bind(this)} size="medium">{i18n('DELETE_AND_BAN')}</Button>
</div>
</div>
<span className="admin-panel-view-user__separator" />
<span className="separator" />
<div className="admin-panel-view-user__tickets">
<div className="admin-panel-view-user__tickets-title">{i18n('TICKETS')}</div>
<TicketList {...this.getTicketListProps()}/>

View File

@ -24,14 +24,6 @@
margin-top: 20px;
}
&__separator {
background-color: $grey;
display: block;
margin: 30px 0;
height: 1px;
width: 100%;
}
&__tickets-title {
font-size: $font-size--md;
margin-bottom: 20px;

View File

@ -27,7 +27,7 @@ class CheckboxGroup extends React.Component {
return (
<li className="checkbox-group__item" key={index}>
<Checkbox label={label} checked={checked} onChange={this.onCheckboxChange.bind(this, index)} wrapInLabel/>
<Checkbox label={label} value={checked} onChange={this.onCheckboxChange.bind(this, index)} wrapInLabel/>
</li>
);
}

View File

@ -16,6 +16,389 @@ module.exports = [
departments: [
{id: 1, name: 'Sales Support', owners: 2},
{id: 2, name: 'Technical Issues', owners: 5}
],
tickets: [
{
ticketNumber: '445441',
title: 'Problem with installation',
content: 'I had a problem with the installation of the php server',
department: {
id: 2,
name: 'Technical Issues',
owners: 5
},
date: '20160416',
file: 'http://www.opensupports.com/some_file.zip',
language: 'en',
unread: true,
closed: false,
priority: 'low',
author: {
id: 12,
name: 'Haskell Curry',
email: 'haskell@lambda.com'
},
owner: {
id: 15,
name: 'Steve Jobs',
email: 'steve@jobs.com'
},
events: [
{
type: 'ASSIGN',
date: '20150409',
author: {
name: 'Emilia Clarke',
email: 'jobs@steve.com',
profilePic: 'http://www.opensupports.com/profilepic.jpg',
staff: true
}
},
{
type: 'COMMENT',
date: '20150409',
content: 'Do you have apache installed? It generally happens if you dont have apache.',
author: {
name: 'Emilia Clarke',
email: 'jobs@steve.com',
profilePic: 'http://www.opensupports.com/profilepic.jpg',
staff: true
}
},
{
type: 'UN_ASSIGN',
date: '20150410',
author: {
name: 'Emilia Clarke',
email: 'jobs@steve.com',
profilePic: 'http://www.opensupports.com/profilepic.jpg',
staff: true
}
},
{
type: 'DEPARTMENT_CHANGED',
date: '20150411',
content: 'System support',
author: {
name: 'Emilia Clarke',
email: 'jobs@steve.com',
profilePic: 'http://www.opensupports.com/profilepic.jpg',
staff: true
}
},
{
type: 'COMMENT',
date: '20150412',
content: 'I have already installed apache, but the problem persists',
author: {
name: 'Haskell Curry',
steve: 'haskell@lambda.com',
staff: false
}
},
{
type: 'PRIORITY_CHANGED',
date: '20150413',
content: 'MEDIUM',
author: {
name: 'Emilia Clarke',
email: 'jobs@steve.com',
profilePic: 'http://www.opensupports.com/profilepic.jpg',
staff: true
}
},
{
type: 'COMMENT',
date: '20150511',
content: 'Thanks!, I solved it by myself',
author: {
name: 'Haskell Curry',
steve: 'haskell@lambda.com',
staff: false
}
},
{
type: 'CLOSE',
date: '20150513',
author: {
name: 'Emilia Clarke',
email: 'jobs@steve.com',
profilePic: 'http://www.opensupports.com/profilepic.jpg',
staff: true
}
},
{
type: 'RE_OPEN',
date: '20151018',
author: {
name: 'Haskell Curry',
email: 'haskell@lambda.com',
staff: false
}
}
]
},
{
ticketNumber: '878552',
title: 'Lorem ipsum door',
content: 'I had a problem with the installation of the php server',
department: {
id: 2,
name: 'Technical Issues',
owners: 5
},
date: '20160415',
file: 'http://www.opensupports.com/some_file.zip',
language: 'en',
unread: false,
closed: false,
priority: 'medium',
author: {
name: 'Haskell Curry',
email: 'haskell@lambda.com'
},
owner: {
name: 'Steve Jobs'
},
events: [
{
type: 'ASSIGN',
date: '20150409',
author: {
name: 'Emilia Clarke',
email: 'jobs@steve.com',
profilePic: 'http://www.opensupports.com/profilepic.jpg',
staff: true
}
},
{
type: 'COMMENT',
date: '20150409',
content: 'Do you have apache installed? It generally happens if you dont have apache.',
author: {
name: 'Emilia Clarke',
email: 'jobs@steve.com',
profilePic: 'http://www.opensupports.com/profilepic.jpg',
staff: true
}
},
{
type: 'UN_ASSIGN',
date: '20150410',
author: {
name: 'Emilia Clarke',
email: 'jobs@steve.com',
profilePic: 'http://www.opensupports.com/profilepic.jpg',
staff: true
}
},
{
type: 'DEPARTMENT_CHANGED',
date: '20150411',
content: 'System support',
author: {
name: 'Emilia Clarke',
email: 'jobs@steve.com',
profilePic: 'http://www.opensupports.com/profilepic.jpg',
staff: true
}
},
{
type: 'COMMENT',
date: '20150412',
content: 'I have already installed apache, but the problem persists',
author: {
name: 'Haskell Curry',
steve: 'haskell@lambda.com',
staff: false
}
},
{
type: 'PRIORITY_CHANGED',
date: '20150413',
content: 'MEDIUM',
author: {
name: 'Emilia Clarke',
email: 'jobs@steve.com',
profilePic: 'http://www.opensupports.com/profilepic.jpg',
staff: true
}
},
{
type: 'COMMENT',
date: '20150511',
content: 'Thanks!, I soved it by myself',
author: {
name: 'Haskell Curry',
steve: 'haskell@lambda.com',
staff: false
}
},
{
type: 'CLOSE',
date: '20150513',
author: {
name: 'Emilia Clarke',
email: 'jobs@steve.com',
profilePic: 'http://www.opensupports.com/profilepic.jpg',
staff: true
}
},
{
type: 'RE_OPEN',
date: '20151018',
author: {
name: 'Haskell Curry',
email: 'haskell@lambda.com',
staff: false
}
}
]
},
{
ticketNumber: '118551',
title: 'Lorem ipsum door',
content: 'I had a problem with the installation of the php server',
department: {
id: 2,
name: 'Technical Issues',
owners: 5
},
date: '20150409',
file: 'http://www.opensupports.com/some_file.zip',
language: 'en',
unread: false,
closed: false,
priority: 'high',
author: {
name: 'Haskell Curry',
email: 'haskell@lambda.com'
},
owner: {
name: 'Steve Jobs'
},
events: [
{
type: 'ASSIGN',
date: '20150409',
author: {
name: 'Emilia Clarke',
email: 'jobs@steve.com',
profilePic: 'http://www.opensupports.com/profilepic.jpg',
staff: true
}
},
{
type: 'COMMENT',
date: '20150409',
content: 'Do you have apache installed? It generally happens if you dont have apache.',
author: {
name: 'Emilia Clarke',
email: 'jobs@steve.com',
profilePic: 'http://www.opensupports.com/profilepic.jpg',
staff: true
}
},
{
type: 'UN_ASSIGN',
date: '20150410',
author: {
name: 'Emilia Clarke',
email: 'jobs@steve.com',
profilePic: 'http://www.opensupports.com/profilepic.jpg',
staff: true
}
},
{
type: 'DEPARTMENT_CHANGED',
date: '20150411',
content: 'System support',
author: {
name: 'Emilia Clarke',
email: 'jobs@steve.com',
profilePic: 'http://www.opensupports.com/profilepic.jpg',
staff: true
}
},
{
type: 'COMMENT',
date: '20150412',
content: 'I have already installed apache, but the problem persists',
author: {
name: 'Haskell Curry',
steve: 'haskell@lambda.com',
staff: false
}
},
{
type: 'PRIORITY_CHANGED',
date: '20150413',
content: 'MEDIUM',
author: {
name: 'Emilia Clarke',
email: 'jobs@steve.com',
profilePic: 'http://www.opensupports.com/profilepic.jpg',
staff: true
}
},
{
type: 'COMMENT',
date: '20150511',
content: 'Thanks!, I soved it by myself',
author: {
name: 'Haskell Curry',
steve: 'haskell@lambda.com',
staff: false
}
},
{
type: 'CLOSE',
date: '20150513',
author: {
name: 'Emilia Clarke',
email: 'jobs@steve.com',
profilePic: 'http://www.opensupports.com/profilepic.jpg',
staff: true
}
},
{
type: 'RE_OPEN',
date: '20151018',
author: {
name: 'Haskell Curry',
email: 'haskell@lambda.com',
staff: false
}
}
]
},
{
ticketNumber: '445441',
title: 'Inscription ACM ICPC',
content: 'I had a problem with the installation of the php server',
department: {
id: 1,
name: 'Sales Support',
owners: 2
},
date: '20160416',
file: 'http://www.opensupports.com/some_file.zip',
language: 'en',
unread: false,
closed: false,
priority: 'low',
author: {
id: 12,
name: 'Haskell Curry',
email: 'haskell@lambda.com'
},
owner: {
id: 15,
name: 'Steve Jobs',
email: 'steve@jobs.com'
},
events: []
}
]
}
};
@ -595,6 +978,7 @@ module.exports = [
status: 'success',
data: [
{
id: 22,
profilePic: 'http://www.opensupports.com/profilepic.jpg',
name: 'Emilia Clarke',
departments: [{id: 2, name: 'Technical issues'}],
@ -603,6 +987,7 @@ module.exports = [
lastLogin: 20161212
},
{
id: 22,
profilePic: 'http://www.opensupports.com/profilepic.jpg',
name: 'Yulian A GUI Yermo',
departments: [{id: 2, name: 'Technical issues'}, {id: 1, name: 'Sales Support'}],
@ -611,6 +996,7 @@ module.exports = [
lastLogin: 20161212
},
{
id: 22,
profilePic: 'http://www.opensupports.com/profilepic.jpg',
name: 'Miltona Costa',
departments: [{id: 1, name: 'Sales Support'}],
@ -619,6 +1005,7 @@ module.exports = [
lastLogin: 20160212
},
{
id: 22,
profilePic: 'http://www.opensupports.com/profilepic.jpg',
name: 'Emiliasnikova Rusachestkvuy',
departments: [{id: 1, name: 'Sales Support'}, {id: 3, name: 'System and Administration'}],
@ -627,6 +1014,7 @@ module.exports = [
lastLogin: 20130101
},
{
id: 22,
profilePic: 'http://www.opensupports.com/profilepic.jpg',
name: 'Laurita Morrechaga Rusachestkvuy',
departments: [{id: 3, name: 'System and Administration'}],
@ -650,6 +1038,16 @@ module.exports = [
};
}
},
{
path: '/staff/edit',
time: 100,
response: function () {
return {
status: 'success',
data: {}
};
}
},
{
path: '/staff/add-department',
time: 100,

View File

@ -6,6 +6,7 @@ export default {
'SUBMIT': 'Submit',
'EMAIL': 'Email',
'PASSWORD': 'Password',
'REPEAT_PASSWORD': 'Repeat password',
'LOG_IN': 'Log in',
'SIGN_UP': 'Sign up',
'FORGOT_PASSWORD': 'Forgot your password?',
@ -94,6 +95,8 @@ export default {
'EDIT': 'Edit',
'NO_RESULTS': 'No results',
'DELETE_AND_BAN': 'Delete and ban',
'STAFF_LEVEL': 'Staff Level',
'ASSIGNED': 'Assigned',
'ASSIGNED_TICKETS': '{tickets} assigned tickets',
'CLOSED_TICKETS': '{tickets} closed tickets',
'LAST_LOGIN': 'Last login',
@ -102,7 +105,12 @@ export default {
'LEVEL': 'Level',
'LEVEL_1': 'Level 1 (Tickets)',
'LEVEL_2': 'Level 2 (Tickets + Articles)',
'LEVEL_3': 'Level 2 (Tickets + Articles + Staff)',
'LEVEL_3': 'Level 3 (Tickets + Articles + Staff)',
'UPDATE_EMAIL': 'Update email',
'UPDATE_PASSWORD': 'Update password',
'UPDATE_LEVEL': 'Update level',
'UPDATE_DEPARTMENTS': 'Update departments',
'EDIT_STAFF': 'Edit staff member',
//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.',
@ -126,7 +134,9 @@ export default {
'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.',
'ADD_STAFF_DESCRIPTION': 'Here you can add staff members to your teams',
'ADD_STAFF_DESCRIPTION': 'Here you can add staff members to your teams.',
'EDIT_STAFF_DESCRIPTION': 'Here you can edit information about a staff member.',
'MY_ACCOUNT_DESCRIPTION': 'Here you can edit information about you.',
//ERRORS
'EMAIL_OR_PASSWORD': 'Email or password invalid',

View File

@ -1,8 +1,18 @@
@import "vars";
* {
box-sizing: border-box;
box-sizing: border-box;
}
body {
font-family: Helvetica, sans-serif;
background-color: $light-grey;
font-family: Helvetica, sans-serif;
background-color: $light-grey;
}
.separator {
background-color: $grey;
display: block;
margin: 30px 0;
height: 1px;
width: 100%;
}

View File

@ -38,7 +38,8 @@ class GetStaffController extends Controller {
'profilePic' => $user->profilePic,
'level' => $user->level,
'staff' => true,
'departments' => $parsedDepartmentList
'departments' => $parsedDepartmentList,
'tickets' => $user->sharedTicketList->toArray()
]);
}
}

View File

@ -1,11 +1,18 @@
<?php
require_once 'system/init-settings.php';
require_once 'system/get-settings.php';
require_once 'system/add-department.php';
require_once 'system/edit-department.php';
require_once 'system/delete-department.php';
$systemControllerGroup = new ControllerGroup();
$systemControllerGroup->setGroupPath('/system');
$systemControllerGroup->addController(new InitSettingsController);
$systemControllerGroup->addController(new GetSettingsController);
$systemControllerGroup->addController(new AddDepartmentController);
$systemControllerGroup->addController(new EditDepartmentController);
$systemControllerGroup->addController(new DeleteDepartmentController);
$systemControllerGroup->finalize();

View File

@ -0,0 +1,34 @@
<?php
use Respect\Validation\Validator as DataValidator;
class AddDepartmentController extends Controller {
const PATH = '/add-department';
public function validations() {
return [
'permission' => 'staff_3',
'requestData' => [
'name' => [
'validation' => DataValidator::alnum(),
'error' => ERRORS::INVALID_NAME
]
]
];
}
public function handler() {
$name = Controller::request('name');
$departmentInstance = new Department();
$departmentInstance->setProperties([
'name' => $name,
]);
$departmentInstance->store();
Response::respondSuccess();
}
}

View File

@ -0,0 +1,27 @@
<?php
use Respect\Validation\Validator as DataValidator;
DataValidator::with('CustomValidations', true);
class DeleteDepartmentController extends Controller {
const PATH = '/delete-department';
public function validations() {
return [
'permission' => 'staff_3',
'requestData' => [
'departmentId' => [
'validation' => DataValidator::dataStoreId('department'),
'error' => ERRORS::INVALID_DEPARTMENT
],
]
];
}
public function handler() {
$departmentId = Controller::request('departmentId');
$departmentInstance = Department::getDataStore($departmentId);
$departmentInstance->delete();
Response::respondSuccess();
}
}

View File

@ -0,0 +1,38 @@
<?php
use Respect\Validation\Validator as DataValidator;
DataValidator::with('CustomValidations', true);
class EditDepartmentController extends Controller {
const PATH = '/edit-department';
public function validations() {
return [
'permission' => 'staff_3',
'requestData' => [
'name' => [
'validation' => DataValidator::alnum(),
'error' => ERRORS::INVALID_NAME
],
'departmentId' => [
'validation' => DataValidator::dataStoreId('department'),
'error' => ERRORS::INVALID_DEPARTMENT
]
]
];
}
public function handler() {
$newname = Controller::request('name');
$departmentId = Controller::request('departmentId');
$departmentInstance = Department::getDataStore($departmentId);
$departmentInstance->name = $newname ;
$departmentInstance->store();
Response::respondSuccess();
}
}

View File

@ -43,5 +43,8 @@ require './user/ban.rb'
require './user/get-users-test.rb'
require './user/delete.rb'
require './staff/get-all.rb'
require './system/add-department.rb'
require './system/edit-department.rb'
require './system/delete-department.rb'

View File

@ -0,0 +1,18 @@
describe'system/add-department' do
request('/user/logout')
Scripts.login($staff[:email], $staff[:password], true)
it 'should add department' do
result= request('/system/add-department', {
csrf_userid: $csrf_userid,
csrf_token: $csrf_token,
name: 'new department'
})
(result['status']).should.equal('success')
row = $database.getRow('department', 4, 'id')
(row['name']).should.equal('new department')
end
end

View File

@ -0,0 +1,18 @@
describe'system/delete-department' do
request('/user/logout')
Scripts.login($staff[:email], $staff[:password], true)
it 'should delete department' do
result= request('/system/delete-department', {
csrf_userid: $csrf_userid,
csrf_token: $csrf_token,
departmentId: 4
})
(result['status']).should.equal('success')
row = $database.getRow('department', 4, 'id')
(row).should.equal(nil)
end
end

View File

@ -0,0 +1,19 @@
describe'system/edit-department' do
request('/user/logout')
Scripts.login($staff[:email], $staff[:password], true)
it 'should edit department' do
result= request('/system/edit-department', {
csrf_userid: $csrf_userid,
csrf_token: $csrf_token,
name: 'second name',
departmentId: 4
})
(result['status']).should.equal('success')
row = $database.getRow('department', 4, 'id')
(row['name']).should.equal('second name')
end
end