Merged in os-125-admin-departments-view (pull request #94)

Os 125 admin departments view
This commit is contained in:
Ivan Diaz 2016-12-12 21:41:14 -03:00
commit 8b69934d36
9 changed files with 343 additions and 25 deletions

View File

@ -26,5 +26,15 @@ export default {
type: 'CHANGE_LANGUAGE',
payload: newLanguage
};
},
updateData() {
return {
type: 'UPDATE_DEPARTMENTS',
payload: API.call({
path: '/system/get-settings',
data: {}
})
};
}
};

View File

@ -6,7 +6,7 @@ import ModalContainer from 'app-components/modal-container';
class AreYouSure extends React.Component {
static propTypes = {
description: React.PropTypes.string,
description: React.PropTypes.node,
onYes: React.PropTypes.func
};

View File

@ -1,14 +1,221 @@
import React from 'react';
import _ from 'lodash';
import {connect} from 'react-redux';
import RichTextEditor from 'react-rte-browserify';
import i18n from 'lib-app/i18n';
import API from 'lib-app/api-call';
import ConfigActions from 'actions/config-actions';
import AreYouSure from 'app-components/are-you-sure';
import InfoTooltip from 'core-components/info-tooltip';
import Button from 'core-components/button';
import Header from 'core-components/header';
import Listing from 'core-components/listing';
import Form from 'core-components/form';
import FormField from 'core-components/form-field';
import SubmitButton from 'core-components/submit-button';
import DropDown from 'core-components/drop-down';
class AdminPanelDepartments extends React.Component {
static defaultProps = {
items: []
};
state = {
formLoading: false,
selectedIndex: -1,
selectedDropDownIndex: 0,
edited: false,
errors: {},
form: {
title: '',
content: RichTextEditor.createEmptyValue(),
language: 'en'
}
};
render() {
return (
<div>
/admin/panel/staff/departments
<div className="admin-panel-departments">
<Header title={i18n('DEPARTMENTS')} description={i18n('DEPARTMENTS_DESCRIPTION')} />
<div className="row">
<div className="col-md-4">
<Listing {...this.getListingProps()}/>
</div>
<div className="col-md-8">
<Form {...this.getFormProps()}>
<FormField label={i18n('NAME')} name="name" validation="NAME" required fieldProps={{size: 'large'}}/>
<SubmitButton size="medium" className="admin-panel-departments__update-name-button" type="secondary">
{i18n((this.state.selectedIndex !== -1) ? 'UPDATE_DEPARTMENT' : 'ADD_DEPARTMENT')}
</SubmitButton>
</Form>
{(this.state.selectedIndex !== -1 && this.props.departments.length) ? this.renderOptionalButtons() : null}
</div>
</div>
</div>
);
}
renderOptionalButtons() {
return (
<div className="admin-panel-departments__optional-buttons">
<div className="admin-panel-departments__discard-button">
<Button onClick={this.onDiscardChangesClick.bind(this)} size="medium">{i18n('DISCARD_CHANGES')}</Button>
</div>
<div className="admin-panel-departments__delete-button">
<Button onClick={this.onDeleteClick.bind(this)} size="medium">{i18n('DELETE')}</Button>
</div>
</div>
);
}
renderDelete() {
return (
<div>
{i18n('WILL_DELETE_DEPARTMENT')}
<div className="admin-panel-departments__transfer-tickets">
<span className="admin-panel-departments__transfer-tickets-title">{i18n('TRANSFER_TICKETS_TO')}</span>
<DropDown className="admin-panel-departments__transfer-tickets-drop-down" items={this.props.departments.filter((department, index) => index !== this.state.selectedIndex).map(department => {
return {
content: department.name
};
})} onChange={(department, index) => this.setState({selectedDropDownIndex: index})} size="medium"/>
</div>
</div>
);
}
getListingProps() {
return {
className: 'admin-panel-departments__list',
title: i18n('DEPARTMENTS'),
items: this.props.departments.map(department => {
return {
content: (
<span>
{department.name}
{(!department.owners) ? (
<span className="admin-panel-departments__warning">
<InfoTooltip type="warning" text={i18n('NO_STAFF_ASSIGNED')}/>
</span>
) : null}
</span>
)
};
}),
selectedIndex: this.state.selectedIndex,
enableAddNew: true,
onChange: this.onItemChange.bind(this),
onAddClick: this.onItemChange.bind(this, -1)
};
}
getFormProps() {
return {
values: this.state.form,
errors: this.state.errors,
loading: this.state.formLoading,
onChange: (form) => {this.setState({form, edited: true})},
onValidateErrors: (errors) => {this.setState({errors})},
onSubmit: this.onFormSubmit.bind(this)
};
}
onItemChange(index) {
if(this.state.edited) {
AreYouSure.openModal(i18n('WILL_LOSE_CHANGES'), this.updateForm.bind(this, index));
} else {
this.updateForm(index);
}
}
onFormSubmit(form) {
this.setState({formLoading: true, edited: false});
if(this.state.selectedIndex !== -1) {
API.call({
path: '/staff/edit-department',
data: {
departmentId: this.getCurrentDepartment().id,
name: form.name
}
}).then(() => {
this.setState({formLoading: false});
this.retrieveDepartments();
}).catch(this.onItemChange.bind(this, -1));
} else {
API.call({
path: '/staff/add-department',
data: {
name: form.title
}
}).then(() => {
this.retrieveDepartments();
this.onItemChange(-1);
}).catch(this.onItemChange.bind(this, -1));
}
}
onDiscardChangesClick() {
this.onItemChange(this.state.selectedIndex);
}
onDeleteClick() {
this.setState({
selectedDropDownIndex: 0
});
AreYouSure.openModal(this.renderDelete(), this.deleteDepartment.bind(this));
}
deleteDepartment() {
API.call({
path: '/staff/delete-department',
data: {
departmentId: this.getCurrentDepartment().id,
transferDepartmentId: this.getDropDownItemId()
}
}).then(() => {
this.retrieveDepartments();
this.onItemChange(-1);
});
}
updateForm(index) {
let form = _.clone(this.state.form);
let department = this.getCurrentDepartment(index);
form.name = (department && department.name) || '';
this.setState({
selectedIndex: index,
edited: false,
formLoading: false,
form: form,
errors: {}
});
}
retrieveDepartments() {
this.props.dispatch(ConfigActions.updateData());
this.setState({
edited: false
});
}
getCurrentDepartment(index) {
return this.props.departments[(index == undefined) ? this.state.selectedIndex : index];
}
getDropDownItemId() {
return this.props.departments.filter((department, index) => index !== this.state.selectedIndex)[this.state.selectedDropDownIndex].id;
}
}
export default AdminPanelDepartments;
export default connect((store) => {
return {
departments: store.config.departments
};
})(AdminPanelDepartments);

View File

@ -0,0 +1,41 @@
@import "../../../../scss/vars";
.admin-panel-departments {
&__list {
position: relative;
}
&__update-name-button {
float: left;
}
&__optional-buttons {
float: right;
}
&__discard-button,
&__delete-button {
display: inline-block;
margin-left: 10px;
}
&__warning {
position: absolute;
right: 10px;
}
&__transfer-tickets {
margin-top: 40px;
}
&__transfer-tickets-title {
margin-right: 20px;
color: $primary-black;
}
&__transfer-tickets-drop-down {
display: inline-block;
}
}

View File

@ -1,4 +1,5 @@
import React from 'react';
import classNames from 'classnames';
import Menu from 'core-components/menu';
import Button from 'core-components/button';
@ -20,7 +21,7 @@ class Listing extends React.Component {
render() {
return (
<div className="listing">
<div className={this.getClass()}>
<div className="listing__header">
{this.props.title}
</div>
@ -42,6 +43,16 @@ class Listing extends React.Component {
);
}
getClass() {
let classes = {
'listing': true
};
classes[this.props.className] = (this.props.className);
return classNames(classes);
}
}
export default Listing;

View File

@ -14,8 +14,8 @@ module.exports = [
level: 1,
staff: true,
departments: [
{id: 1, name: 'Sales Support'},
{id: 2, name: 'Technical Issues'}
{id: 1, name: 'Sales Support', owners: 2},
{id: 2, name: 'Technical Issues', owners: 5}
],
tickets: [
{
@ -24,7 +24,8 @@ module.exports = [
content: 'I had a problem with the installation of the php server',
department: {
id: 2,
name: 'Technical Issues'
name: 'Technical Issues',
owners: 5
},
date: '20160416',
file: 'http://www.opensupports.com/some_file.zip',
@ -143,7 +144,8 @@ module.exports = [
content: 'I had a problem with the installation of the php server',
department: {
id: 2,
name: 'Technical Issues'
name: 'Technical Issues',
owners: 5
},
date: '20160415',
file: 'http://www.opensupports.com/some_file.zip',
@ -259,7 +261,8 @@ module.exports = [
content: 'I had a problem with the installation of the php server',
department: {
id: 2,
name: 'Technical Issues'
name: 'Technical Issues',
owners: 5
},
date: '20150409',
file: 'http://www.opensupports.com/some_file.zip',
@ -375,7 +378,8 @@ module.exports = [
content: 'I had a problem with the installation of the php server',
department: {
id: 1,
name: 'Sales Support'
name: 'Sales Support',
owners: 2
},
date: '20160416',
file: 'http://www.opensupports.com/some_file.zip',
@ -413,7 +417,8 @@ module.exports = [
content: 'I had a problem with the installation of the php server',
department: {
id: 2,
name: 'Technical Issues'
name: 'Technical Issues',
owners: 5
},
date: '20160416',
file: 'http://www.opensupports.com/some_file.zip',
@ -532,7 +537,8 @@ module.exports = [
content: 'I had a problem with the installation of the php server',
department: {
id: 2,
name: 'Technical Issues'
name: 'Technical Issues',
owners: 5
},
date: '20160415',
file: 'http://www.opensupports.com/some_file.zip',
@ -648,7 +654,8 @@ module.exports = [
content: 'I had a problem with the installation of the php server',
department: {
id: 2,
name: 'Technical Issues'
name: 'Technical Issues',
owners: 5
},
date: '20150409',
file: 'http://www.opensupports.com/some_file.zip',
@ -764,7 +771,8 @@ module.exports = [
content: 'I had a problem with the installation of the php server',
department: {
id: 1,
name: 'Sales Support'
name: 'Sales Support',
owners: 2
},
date: '20160416',
file: 'http://www.opensupports.com/some_file.zip',
@ -801,7 +809,8 @@ module.exports = [
content: 'I had a problem with the installation of the php server',
department: {
id: 1,
name: 'Sales Support'
name: 'Sales Support',
owners: 2
},
date: '20160416',
file: 'http://www.opensupports.com/some_file.zip',
@ -827,7 +836,8 @@ module.exports = [
content: 'I had a problem with the installation of the php server',
department: {
id: 1,
name: 'Sales Support'
name: 'Sales Support',
owners: 2
},
date: '20160416',
file: 'http://www.opensupports.com/some_file.zip',
@ -853,7 +863,8 @@ module.exports = [
content: 'I had a problem with the installation of the php server',
department: {
id: 2,
name: 'Technical Issues'
name: 'Technical Issues',
owners: 2
},
date: '20160416',
file: 'http://www.opensupports.com/some_file.zip',
@ -891,7 +902,8 @@ module.exports = [
content: 'I had a problem with the installation of the php server',
department: {
id: 1,
name: 'Sales Support'
name: 'Sales Support',
owners: 2
},
date: '20160416',
file: 'http://www.opensupports.com/some_file.zip',
@ -1035,5 +1047,35 @@ module.exports = [
data: {}
};
}
},
{
path: '/staff/add-department',
time: 100,
response: function () {
return {
status: 'success',
data: {}
};
}
},
{
path: '/staff/edit-department',
time: 100,
response: function () {
return {
status: 'success',
data: {}
};
}
},
{
path: '/staff/delete-department',
time: 100,
response: function () {
return {
status: 'success',
data: {}
};
}
}
];

View File

@ -9,9 +9,9 @@ module.exports = [
'language': 'en',
'reCaptchaKey': '6LfM5CYTAAAAAGLz6ctpf-hchX2_l0Ge-Bn-n8wS',
'departments': [
{id: 1, name: 'Sales Support'},
{id: 2, name: 'Technical Issues'},
{id: 3, name: 'System and Administration'}
{id: 1, name: 'Sales Support', owners: 2},
{id: 2, name: 'Technical Issues', owners: 5},
{id: 3, name: 'System and Administration', owners: 0}
]
}
};

View File

@ -111,6 +111,9 @@ export default {
'UPDATE_LEVEL': 'Update level',
'UPDATE_DEPARTMENTS': 'Update departments',
'EDIT_STAFF': 'Edit staff member',
'ADD_DEPARTMENT': 'Add department',
'UPDATE_DEPARTMENT': 'Update department',
'TRANSFER_TICKETS_TO': 'Transfer tickets to',
//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.',
@ -137,6 +140,7 @@ export default {
'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.',
'DEPARTMENTS_DESCRIPTION': 'A department is a group where the tickets can go. They are used to categorize the tickets. You can assign them to other staff members.',
//ERRORS
'EMAIL_OR_PASSWORD': 'Email or password invalid',
@ -163,5 +167,7 @@ export default {
'PASSWORD_CHANGED': 'Password has been changed successfully',
'OLD_PASSWORD_INCORRECT': 'Old password is incorrect',
'WILL_LOSE_CHANGES': 'You haven\'t save. Your changes will be lost.',
'WILL_DELETE_CUSTOM_RESPONSE': 'The custom response will be deleted.'
'WILL_DELETE_CUSTOM_RESPONSE': 'The custom response will be deleted.',
'WILL_DELETE_DEPARTMENT': 'The department will be deleted. All the tickets will be transfer to the department selected.',
'NO_STAFF_ASSIGNED': 'No staff member is assigned to this department.'
};

View File

@ -14,7 +14,8 @@ class ConfigReducer extends Reducer {
getTypeHandlers() {
return {
'CHANGE_LANGUAGE': this.onLanguageChange,
'INIT_CONFIGS_FULFILLED': this.onInitConfigs
'INIT_CONFIGS_FULFILLED': this.onInitConfigs,
'UPDATE_DATA_FULFILLED': this.onInitConfigs
};
}
@ -29,7 +30,7 @@ class ConfigReducer extends Reducer {
onInitConfigs(state, payload) {
const currentLanguage = sessionStore.getItem('language');
sessionStore.storeConfigs(_.extend(payload.data, {
sessionStore.storeConfigs(_.extend({}, payload.data, {
language: currentLanguage || payload.language
}));