From e3f50c28c63ddd1dc9670aadbb0f6542a27442e4 Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 12 Dec 2016 17:45:53 -0300 Subject: [PATCH 1/5] Ivan - Add admin departments view [skip ci] --- client/src/actions/config-actions.js | 10 + .../panel/staff/admin-panel-departments.js | 184 +++++++++++++++++- .../panel/staff/admin-panel-departments.scss | 24 +++ client/src/data/fixtures/staff-fixtures.js | 58 +++++- client/src/data/fixtures/system-fixtures.js | 6 +- client/src/reducers/config-reducer.js | 5 +- 6 files changed, 269 insertions(+), 18 deletions(-) create mode 100644 client/src/app/admin/panel/staff/admin-panel-departments.scss diff --git a/client/src/actions/config-actions.js b/client/src/actions/config-actions.js index cbde584c..0c2617e7 100644 --- a/client/src/actions/config-actions.js +++ b/client/src/actions/config-actions.js @@ -26,5 +26,15 @@ export default { type: 'CHANGE_LANGUAGE', payload: newLanguage }; + }, + + updateData() { + return { + type: 'UPDATE_DEPARTMENTS', + payload: API.call({ + path: '/system/get-settings', + data: {} + }) + }; } }; \ No newline at end of file diff --git a/client/src/app/admin/panel/staff/admin-panel-departments.js b/client/src/app/admin/panel/staff/admin-panel-departments.js index 768add5f..ee98e324 100644 --- a/client/src/app/admin/panel/staff/admin-panel-departments.js +++ b/client/src/app/admin/panel/staff/admin-panel-departments.js @@ -1,14 +1,192 @@ 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'; class AdminPanelDepartments extends React.Component { + static defaultProps = { + items: [] + }; + + state = { + formLoading: false, + selectedIndex: -1, + edited: false, + errors: {}, + form: { + title: '', + content: RichTextEditor.createEmptyValue(), + language: 'en' + } + }; render() { return ( -
- /admin/panel/staff/departments +
+
+
+
+ +
+
+
+ + {i18n('UPDATE_NAME')} + + {(this.state.selectedIndex !== -1) ? this.renderOptionalButtons() : null} +
+
); } + + renderOptionalButtons() { + return ( +
+
+ +
+
+ +
+
+ ); + } + + + getListingProps() { + return { + title: i18n('DEPARTMENTS'), + items: this.props.departments.map(department => { + return { + content: ( + + {department.name} + {(!department.owners) ? ( + + + + ) : null} + + ) + }; + }), + 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: { + id: 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() { + AreYouSure.openModal(i18n('WILL_DELETE_DEPARTMENT'), this.deleteDepartment.bind(this)); + } + + deleteDepartment() { + API.call({ + path: '/staff/delete-department', + data: { + id: this.getCurrentDepartment().id + } + }).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]; + } } -export default AdminPanelDepartments; \ No newline at end of file +export default connect((store) => { + return { + departments: store.config.departments + }; +})(AdminPanelDepartments); \ No newline at end of file diff --git a/client/src/app/admin/panel/staff/admin-panel-departments.scss b/client/src/app/admin/panel/staff/admin-panel-departments.scss new file mode 100644 index 00000000..a660ff8c --- /dev/null +++ b/client/src/app/admin/panel/staff/admin-panel-departments.scss @@ -0,0 +1,24 @@ +@import "../../../../scss/vars"; + +.admin-panel-departments { + + &__update-name-button { + + } + + &__optional-buttons { + + } + + &__discard-button { + + } + + &__delete-button { + + } + + &__warning { + + } +} \ No newline at end of file diff --git a/client/src/data/fixtures/staff-fixtures.js b/client/src/data/fixtures/staff-fixtures.js index b0180b7b..1756bb7d 100644 --- a/client/src/data/fixtures/staff-fixtures.js +++ b/client/src/data/fixtures/staff-fixtures.js @@ -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} ] } }; @@ -34,7 +34,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', @@ -153,7 +154,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', @@ -269,7 +271,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', @@ -385,7 +388,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', @@ -422,7 +426,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', @@ -448,7 +453,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', @@ -474,7 +480,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', @@ -512,7 +519,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', @@ -641,5 +649,35 @@ module.exports = [ } }; } + }, + { + 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: {} + }; + } } ]; \ No newline at end of file diff --git a/client/src/data/fixtures/system-fixtures.js b/client/src/data/fixtures/system-fixtures.js index b630d7be..258c2112 100644 --- a/client/src/data/fixtures/system-fixtures.js +++ b/client/src/data/fixtures/system-fixtures.js @@ -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} ] } }; diff --git a/client/src/reducers/config-reducer.js b/client/src/reducers/config-reducer.js index 13abe25d..3526bedf 100644 --- a/client/src/reducers/config-reducer.js +++ b/client/src/reducers/config-reducer.js @@ -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 })); From a45f39adabe5110f6c7bb28a2621c1ef48dd72f9 Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 12 Dec 2016 17:48:48 -0300 Subject: [PATCH 2/5] Ivan - Use departmentId instead of id for edit-department and delete-department [skip ci] --- client/src/app/admin/panel/staff/admin-panel-departments.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/app/admin/panel/staff/admin-panel-departments.js b/client/src/app/admin/panel/staff/admin-panel-departments.js index ee98e324..71e8c9f7 100644 --- a/client/src/app/admin/panel/staff/admin-panel-departments.js +++ b/client/src/app/admin/panel/staff/admin-panel-departments.js @@ -118,7 +118,7 @@ class AdminPanelDepartments extends React.Component { API.call({ path: '/staff/edit-department', data: { - id: this.getCurrentDepartment().id, + departmentId: this.getCurrentDepartment().id, name: form.name } }).then(() => { @@ -150,7 +150,7 @@ class AdminPanelDepartments extends React.Component { API.call({ path: '/staff/delete-department', data: { - id: this.getCurrentDepartment().id + departmentId: this.getCurrentDepartment().id } }).then(() => { this.retrieveDepartments(); From 1b72c238442f4432397bffbe5f621a9ddf057a92 Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 12 Dec 2016 18:02:28 -0300 Subject: [PATCH 3/5] Ivan - Update departments view styling [skip ci] --- .../panel/staff/admin-panel-departments.js | 13 +++++++----- .../panel/staff/admin-panel-departments.scss | 20 +++++++++++-------- client/src/core-components/listing.js | 13 +++++++++++- 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/client/src/app/admin/panel/staff/admin-panel-departments.js b/client/src/app/admin/panel/staff/admin-panel-departments.js index 71e8c9f7..19f80c37 100644 --- a/client/src/app/admin/panel/staff/admin-panel-departments.js +++ b/client/src/app/admin/panel/staff/admin-panel-departments.js @@ -39,13 +39,15 @@ class AdminPanelDepartments extends React.Component {
-
+
-
+
- {i18n('UPDATE_NAME')} + + {i18n((this.state.selectedIndex !== -1) ? 'UPDATE_NAME' : 'ADD_DEPARTMENT')} + {(this.state.selectedIndex !== -1) ? this.renderOptionalButtons() : null}
@@ -58,10 +60,10 @@ class AdminPanelDepartments extends React.Component { return (
- +
- +
); @@ -70,6 +72,7 @@ class AdminPanelDepartments extends React.Component { getListingProps() { return { + className: 'admin-panel-departments__list', title: i18n('DEPARTMENTS'), items: this.props.departments.map(department => { return { diff --git a/client/src/app/admin/panel/staff/admin-panel-departments.scss b/client/src/app/admin/panel/staff/admin-panel-departments.scss index a660ff8c..c36ccefc 100644 --- a/client/src/app/admin/panel/staff/admin-panel-departments.scss +++ b/client/src/app/admin/panel/staff/admin-panel-departments.scss @@ -2,23 +2,27 @@ .admin-panel-departments { - &__update-name-button { + &__list { + position: relative; + } + + &__update-name-button { + float: left; } &__optional-buttons { - - } - - &__discard-button { - + float: right; } + &__discard-button, &__delete-button { - + display: inline-block; + margin-left: 10px; } &__warning { - + position: absolute; + right: 10px; } } \ No newline at end of file diff --git a/client/src/core-components/listing.js b/client/src/core-components/listing.js index b66da124..3211333d 100644 --- a/client/src/core-components/listing.js +++ b/client/src/core-components/listing.js @@ -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 ( -
+
{this.props.title}
@@ -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; \ No newline at end of file From 2d1ad93f3bacc836ea8851ce36743b9989fc17b8 Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 12 Dec 2016 18:15:37 -0300 Subject: [PATCH 4/5] Ivan - Add internationalization for departments view [skip ci] --- client/src/app-components/are-you-sure.js | 2 +- .../src/app/admin/panel/staff/admin-panel-departments.js | 4 ++-- client/src/data/languages/en.js | 7 ++++++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/client/src/app-components/are-you-sure.js b/client/src/app-components/are-you-sure.js index 13c86819..82b569c0 100644 --- a/client/src/app-components/are-you-sure.js +++ b/client/src/app-components/are-you-sure.js @@ -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 }; diff --git a/client/src/app/admin/panel/staff/admin-panel-departments.js b/client/src/app/admin/panel/staff/admin-panel-departments.js index 19f80c37..327b38b6 100644 --- a/client/src/app/admin/panel/staff/admin-panel-departments.js +++ b/client/src/app/admin/panel/staff/admin-panel-departments.js @@ -46,10 +46,10 @@ class AdminPanelDepartments extends React.Component {
- {i18n((this.state.selectedIndex !== -1) ? 'UPDATE_NAME' : 'ADD_DEPARTMENT')} + {i18n((this.state.selectedIndex !== -1) ? 'UPDATE_DEPARTMENT' : 'ADD_DEPARTMENT')} - {(this.state.selectedIndex !== -1) ? this.renderOptionalButtons() : null} + {(this.state.selectedIndex !== -1 && this.props.departments.length) ? this.renderOptionalButtons() : null}
diff --git a/client/src/data/languages/en.js b/client/src/data/languages/en.js index acb99b74..7b515636 100644 --- a/client/src/data/languages/en.js +++ b/client/src/data/languages/en.js @@ -111,6 +111,8 @@ export default { 'UPDATE_LEVEL': 'Update level', 'UPDATE_DEPARTMENTS': 'Update departments', 'EDIT_STAFF': 'Edit staff member', + 'ADD_DEPARTMENT': 'Add department', + 'UPDATE_DEPARTMENT': 'Update department', //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 +139,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 +166,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.' }; From 69de6d57eee1f47e07bca83b8bd67f9ed0d16904 Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 12 Dec 2016 19:36:02 -0300 Subject: [PATCH 5/5] Ivan - Add department transfer dropdown when deleting [skip ci] --- .../panel/staff/admin-panel-departments.js | 30 +++++++++++++++++-- .../panel/staff/admin-panel-departments.scss | 13 ++++++++ client/src/data/languages/en.js | 1 + 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/client/src/app/admin/panel/staff/admin-panel-departments.js b/client/src/app/admin/panel/staff/admin-panel-departments.js index 327b38b6..2b9db331 100644 --- a/client/src/app/admin/panel/staff/admin-panel-departments.js +++ b/client/src/app/admin/panel/staff/admin-panel-departments.js @@ -16,6 +16,7 @@ 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 = { @@ -25,6 +26,7 @@ class AdminPanelDepartments extends React.Component { state = { formLoading: false, selectedIndex: -1, + selectedDropDownIndex: 0, edited: false, errors: {}, form: { @@ -69,6 +71,21 @@ class AdminPanelDepartments extends React.Component { ); } + renderDelete() { + return ( +
+ {i18n('WILL_DELETE_DEPARTMENT')} +
+ {i18n('TRANSFER_TICKETS_TO')} + index !== this.state.selectedIndex).map(department => { + return { + content: department.name + }; + })} onChange={(department, index) => this.setState({selectedDropDownIndex: index})} size="medium"/> +
+
+ ); + } getListingProps() { return { @@ -146,14 +163,19 @@ class AdminPanelDepartments extends React.Component { } onDeleteClick() { - AreYouSure.openModal(i18n('WILL_DELETE_DEPARTMENT'), this.deleteDepartment.bind(this)); + this.setState({ + selectedDropDownIndex: 0 + }); + + AreYouSure.openModal(this.renderDelete(), this.deleteDepartment.bind(this)); } deleteDepartment() { API.call({ path: '/staff/delete-department', data: { - departmentId: this.getCurrentDepartment().id + departmentId: this.getCurrentDepartment().id, + transferDepartmentId: this.getDropDownItemId() } }).then(() => { this.retrieveDepartments(); @@ -186,6 +208,10 @@ class AdminPanelDepartments extends React.Component { 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 connect((store) => { diff --git a/client/src/app/admin/panel/staff/admin-panel-departments.scss b/client/src/app/admin/panel/staff/admin-panel-departments.scss index c36ccefc..05a2441f 100644 --- a/client/src/app/admin/panel/staff/admin-panel-departments.scss +++ b/client/src/app/admin/panel/staff/admin-panel-departments.scss @@ -25,4 +25,17 @@ 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; + } } \ No newline at end of file diff --git a/client/src/data/languages/en.js b/client/src/data/languages/en.js index 7b515636..0805e711 100644 --- a/client/src/data/languages/en.js +++ b/client/src/data/languages/en.js @@ -113,6 +113,7 @@ export default { '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.',