From 8d972a17eefed6f8d52c43a122ba42ffb2e11670 Mon Sep 17 00:00:00 2001 From: Ivan Diaz Date: Sat, 15 Oct 2016 05:06:34 -0300 Subject: [PATCH 1/8] Ivan - Frontend - WIP[skip ci] --- client/src/app-components/ticket-viewer.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/client/src/app-components/ticket-viewer.js b/client/src/app-components/ticket-viewer.js index f561a0b8..f7fbeeea 100644 --- a/client/src/app-components/ticket-viewer.js +++ b/client/src/app-components/ticket-viewer.js @@ -13,10 +13,12 @@ import SubmitButton from 'core-components/submit-button'; class TicketViewer extends React.Component { static propTypes = { - ticket: React.PropTypes.object + ticket: React.PropTypes.object, + editable: React.PropTypes.bool }; static defaultProps = { + editable: false, ticket: { author: {}, department: {}, @@ -52,6 +54,20 @@ class TicketViewer extends React.Component {
{ticket.author.name}
{ticket.date}
+
+
{i18n('PRIORITY')}
+
{i18n('OWNER')}
+
{i18n('STATUS')}
+
+
+
+ {ticket.priority} +
+
+ {i18n((ticket.closed) ? 'CLOSED' : 'OPEN')} +
+
{ticket.date}
+
From 5e25905e3c49c856311ed8d2270a62dc75026b77 Mon Sep 17 00:00:00 2001 From: ivan Date: Sat, 15 Oct 2016 19:37:29 -0300 Subject: [PATCH 2/8] Ivan - wip [skip ci] --- client/src/app-components/ticket-viewer.js | 106 +++++++++++++++---- client/src/app-components/ticket-viewer.scss | 12 +-- client/src/data/languages/en.js | 6 ++ 3 files changed, 94 insertions(+), 30 deletions(-) diff --git a/client/src/app-components/ticket-viewer.js b/client/src/app-components/ticket-viewer.js index f7fbeeea..50d9eb30 100644 --- a/client/src/app-components/ticket-viewer.js +++ b/client/src/app-components/ticket-viewer.js @@ -10,6 +10,8 @@ import TicketAction from 'app-components/ticket-action'; 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'; +import Button from 'core-components/button'; class TicketViewer extends React.Component { static propTypes = { @@ -18,7 +20,7 @@ class TicketViewer extends React.Component { }; static defaultProps = { - editable: false, + editable: true, ticket: { author: {}, department: {}, @@ -44,6 +46,83 @@ class TicketViewer extends React.Component { #{ticket.ticketNumber} {ticket.title} + {this.props.editable ? this.renderEditableHeaders() : this.renderHeaders()} +
+ +
+
+ {ticket.actions && ticket.actions.map(this.renderAction.bind(this))} +
+
+
{i18n('RESPOND')}
+
+
+ + {i18n('RESPOND_TICKET')} + +
+
+ + ); + } + + renderEditableHeaders() { + const ticket = this.props.ticket; + const priorities = { + 'low': 0, + 'medium': 1, + 'high': 2 + }; + const priorityList = [ + {content: i18n('LOW')}, + {content: i18n('MEDIUM')}, + {content: i18n('HIGH')} + ]; + + return ( +
+
+
{i18n('DEPARTMENT')}
+
{i18n('AUTHOR')}
+
{i18n('DATE')}
+
+
+
{ticket.department.name}
+
{ticket.author.name}
+
{ticket.date}
+
+
+
{i18n('PRIORITY')}
+
{i18n('OWNED')}
+
{i18n('STATUS')}
+
+
+
+ +
+
+ +
+
+ {i18n((ticket.closed) ? 'CLOSED' : 'OPEN')} +
+
+
+ ); + } + + renderHeaders() { + const ticket = this.props.ticket; + const priorities = { + 'low': 'LOW', + 'medium': 'MEDIUM', + 'high': 'HIGH' + }; + + return ( +
{i18n('DEPARTMENT')}
{i18n('AUTHOR')}
@@ -60,28 +139,15 @@ class TicketViewer extends React.Component {
{i18n('STATUS')}
-
- {ticket.priority} +
+ {i18n(priorities[this.props.ticket.priority || 'low'])}
-
+
+ {(ticket.owner) ? ticket.owner.name : i18n('NONE')} +
+
{i18n((ticket.closed) ? 'CLOSED' : 'OPEN')}
-
{ticket.date}
-
-
- -
-
- {ticket.actions && ticket.actions.map(this.renderAction.bind(this))} -
-
-
{i18n('RESPOND')}
-
-
- - {i18n('RESPOND_TICKET')} - -
); diff --git a/client/src/app-components/ticket-viewer.scss b/client/src/app-components/ticket-viewer.scss index b382aa34..b6e68e54 100644 --- a/client/src/app-components/ticket-viewer.scss +++ b/client/src/app-components/ticket-viewer.scss @@ -30,16 +30,8 @@ color: $secondary-blue; } - &__date { - - } - - &__author { - - } - - &__department { - + &__editable-dropdown { + margin: auto; } &__content { diff --git a/client/src/data/languages/en.js b/client/src/data/languages/en.js index 733b36e7..9f0d1c59 100644 --- a/client/src/data/languages/en.js +++ b/client/src/data/languages/en.js @@ -60,6 +60,12 @@ export default { 'DISCARD_CHANGES': 'Discard changes', 'DELETE': 'Delete', 'LANGUAGE': 'Language', + 'OWNER': 'Owner', + 'OWNED': 'Owned', + 'STATUS': 'Status', + 'NONE': 'None', + 'OPEN': 'Open', + 'CLOSED': 'Closed', //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.', From 3b8bcc84388279eab0b5bbe31bd20ecf63fe2d0e Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 18 Oct 2016 20:42:49 -0300 Subject: [PATCH 3/8] Ivan - Add editable ticket view [skip ci] --- client/src/app-components/ticket-viewer.js | 81 +++++++++++++++++-- client/src/app-components/ticket-viewer.scss | 5 ++ .../create-ticket-form.js | 6 +- client/src/core-components/button.js | 2 + client/src/core-components/button.scss | 6 ++ client/src/data/fixtures/system-fixtures.js | 6 +- client/src/data/fixtures/user-fixtures.js | 10 +-- client/src/data/languages/en.js | 6 +- 8 files changed, 102 insertions(+), 20 deletions(-) diff --git a/client/src/app-components/ticket-viewer.js b/client/src/app-components/ticket-viewer.js index 50d9eb30..89237ab3 100644 --- a/client/src/app-components/ticket-viewer.js +++ b/client/src/app-components/ticket-viewer.js @@ -4,9 +4,11 @@ import _ from 'lodash'; import i18n from 'lib-app/i18n'; import API from 'lib-app/api-call'; import store from 'app/store'; +import SessionStore from 'lib-app/session-store'; import SessionActions from 'actions/session-actions'; import TicketAction from 'app-components/ticket-action'; +import AreYouSure from 'app-components/are-you-sure'; import Form from 'core-components/form'; import FormField from 'core-components/form-field'; import SubmitButton from 'core-components/submit-button'; @@ -20,7 +22,7 @@ class TicketViewer extends React.Component { }; static defaultProps = { - editable: true, + editable: false, ticket: { author: {}, department: {}, @@ -36,7 +38,6 @@ class TicketViewer extends React.Component { }; } - render() { const ticket = this.props.ticket; @@ -68,6 +69,7 @@ class TicketViewer extends React.Component { renderEditableHeaders() { const ticket = this.props.ticket; + const departments = SessionStore.getDepartments(); const priorities = { 'low': 0, 'medium': 1, @@ -87,7 +89,12 @@ class TicketViewer extends React.Component {
{i18n('DATE')}
-
{ticket.department.name}
+
+ {return {content: department.name}})} + selectedIndex={_.findIndex(departments, {id: this.props.ticket.department.id})} + onChange={this.onDepartmentDropdownChanged.bind(this)} /> +
{ticket.author.name}
{ticket.date}
@@ -98,15 +105,17 @@ class TicketViewer extends React.Component {
- +
-
- {i18n((ticket.closed) ? 'CLOSED' : 'OPEN')} +
@@ -146,7 +155,7 @@ class TicketViewer extends React.Component { {(ticket.owner) ? ticket.owner.name : i18n('NONE')}
- {i18n((ticket.closed) ? 'CLOSED' : 'OPEN')} + {i18n((ticket.closed) ? 'CLOSED' : 'OPENED')}
@@ -159,6 +168,62 @@ class TicketViewer extends React.Component { ); } + onDepartmentDropdownChanged(event) { + AreYouSure.openModal(null, this.changeDepartment.bind(this, event.index)); + } + + onPriorityDropdownChanged(event) { + AreYouSure.openModal(null, this.changePriority.bind(this, event.index)); + } + + onAssignClick() { + API.call({ + path: (this.props.ticket.owner) ? '/staff/un-assign-ticket' : '/staff/assign-ticket', + data: { + ticketNumber: this.props.ticket.ticketNumber + } + }); + } + + onCloseClick() { + AreYouSure.openModal(null, this.toggleClose); + } + + toggleClose() { + API.call({ + path: (this.props.ticket.closed) ? '/ticket/re-open' : '/ticket/close', + data: { + ticketNumber: this.props.ticket.ticketNumber + } + }); + } + + changeDepartment(index) { + API.call({ + path: '/ticket/change-department', + data: { + ticketNumber: this.props.ticket.ticketNumber, + departmentId: SessionStore.getDepartments()[index].id + } + }); + } + + changePriority(index) { + const priorities = [ + 'low', + 'medium', + 'high' + ]; + + API.call({ + path: '/ticket/change-priority', + data: { + ticketNumber: this.props.ticket.ticketNumber, + priority: priorities[index] + } + }); + } + onSubmit(formState) { this.setState({ loading: true diff --git a/client/src/app-components/ticket-viewer.scss b/client/src/app-components/ticket-viewer.scss index b6e68e54..c4ec3865 100644 --- a/client/src/app-components/ticket-viewer.scss +++ b/client/src/app-components/ticket-viewer.scss @@ -28,10 +28,15 @@ &__info-row-values { background-color: $light-grey; color: $secondary-blue; + padding-bottom: 10px; } &__editable-dropdown { margin: auto; + + .drop-down__current-item { + background-color: $very-light-grey; + } } &__content { diff --git a/client/src/app/main/dashboard/dashboard-create-ticket/create-ticket-form.js b/client/src/app/main/dashboard/dashboard-create-ticket/create-ticket-form.js index 17dd484b..ca2543cd 100644 --- a/client/src/app/main/dashboard/dashboard-create-ticket/create-ticket-form.js +++ b/client/src/app/main/dashboard/dashboard-create-ticket/create-ticket-form.js @@ -42,8 +42,8 @@ class CreateTicketForm extends React.Component { {(!this.props.userLogged) ? this.renderEmailAndName() : null}
- {return {content: department}}), + {return {content: department.name}}), size: 'medium' }} />
@@ -92,7 +92,7 @@ class CreateTicketForm extends React.Component { API.call({ path: '/ticket/create', data: _.extend({}, formState, { - departmentId: formState.departmentId + 1 + departmentId: SessionStore.getDepartments()[formState.departmentIndex].id }) }).then(this.onTicketSuccess.bind(this)).catch(this.onTicketFail.bind(this)); } diff --git a/client/src/core-components/button.js b/client/src/core-components/button.js index 222bedab..3b2d52c6 100644 --- a/client/src/core-components/button.js +++ b/client/src/core-components/button.js @@ -18,6 +18,7 @@ class Button extends React.Component { static propTypes = { children: React.PropTypes.node, size: React.PropTypes.oneOf([ + 'extra-small', 'small', 'medium', 'large', @@ -76,6 +77,7 @@ class Button extends React.Component { 'button_clean': (this.props.type === 'clean'), 'button_link': (this.props.type === 'link'), + 'button_extra-small': (this.props.size === 'extra-small'), 'button_small': (this.props.size === 'small'), 'button_medium': (this.props.size === 'medium'), 'button_large': (this.props.size === 'large'), diff --git a/client/src/core-components/button.scss b/client/src/core-components/button.scss index 12ecc71b..33f1cb7b 100644 --- a/client/src/core-components/button.scss +++ b/client/src/core-components/button.scss @@ -47,6 +47,12 @@ } } + &_extra-small { + text-transform: none; + width: 130px; + height: 30px; + } + &_small { width: 100px; height: 47px; diff --git a/client/src/data/fixtures/system-fixtures.js b/client/src/data/fixtures/system-fixtures.js index a0b3b168..b630d7be 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': [ - 'Sales Support', - 'Technical Issues', - 'System and Administration' + {id: 1, name: 'Sales Support'}, + {id: 2, name: 'Technical Issues'}, + {id: 3, name: 'System and Administration'} ] } }; diff --git a/client/src/data/fixtures/user-fixtures.js b/client/src/data/fixtures/user-fixtures.js index bbd87aa0..04cf2cd5 100644 --- a/client/src/data/fixtures/user-fixtures.js +++ b/client/src/data/fixtures/user-fixtures.js @@ -141,7 +141,7 @@ module.exports = [ content: 'I had a problem with the installation of the php server', department: { id: 2, - name: 'Environment Setup' + name: 'Technical Issues' }, date: '15 Apr 2016', file: 'http://www.opensupports.com/some_file.zip', @@ -259,8 +259,8 @@ module.exports = [ title: 'Lorem ipsum door', content: 'I had a problem with the installation of the php server', department: { - id: 2, - name: 'Environment Setup' + id: 1, + name: 'Sales Support' }, date: '15 Apr 2016', file: 'http://www.opensupports.com/some_file.zip', @@ -375,8 +375,8 @@ module.exports = [ title: 'Lorem ipsum door', content: 'I had a problem with the installation of the php server', department: { - id: 2, - name: 'Environment Setup' + id: 1, + name: 'Sales Support' }, date: 20150409, file: 'http://www.opensupports.com/some_file.zip', diff --git a/client/src/data/languages/en.js b/client/src/data/languages/en.js index 9f0d1c59..5f2f4fdd 100644 --- a/client/src/data/languages/en.js +++ b/client/src/data/languages/en.js @@ -64,8 +64,12 @@ export default { 'OWNED': 'Owned', 'STATUS': 'Status', 'NONE': 'None', - 'OPEN': 'Open', + 'OPENED': 'Opened', 'CLOSED': 'Closed', + 'CLOSE': 'Close', + 'RE_OPEN': 'Re open', + 'ASSIGN_TO_ME': 'Assign to me', + 'UN_ASSIGN': 'Unassign', //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.', From a876e83108f05154680734fceb7f10e2776858ae Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 18 Oct 2016 20:47:36 -0300 Subject: [PATCH 4/8] Ivan - Change name TicketAction => TicketEvent [skip ci] --- .../{ticket-action.js => ticket-event.js} | 98 +++++++++---------- .../{ticket-action.scss => ticket-event.scss} | 26 ++--- client/src/app-components/ticket-viewer.js | 10 +- client/src/data/fixtures/user-fixtures.js | 6 +- 4 files changed, 70 insertions(+), 70 deletions(-) rename client/src/app-components/{ticket-action.js => ticket-event.js} (52%) rename client/src/app-components/{ticket-action.scss => ticket-event.scss} (87%) diff --git a/client/src/app-components/ticket-action.js b/client/src/app-components/ticket-event.js similarity index 52% rename from client/src/app-components/ticket-action.js rename to client/src/app-components/ticket-event.js index fb3657db..dd99b24c 100644 --- a/client/src/app-components/ticket-action.js +++ b/client/src/app-components/ticket-event.js @@ -4,7 +4,7 @@ import classNames from 'classnames'; import i18n from 'lib-app/i18n'; import Icon from 'core-components/icon'; -class TicketAction extends React.Component { +class TicketEvent extends React.Component { static propTypes = { type: React.PropTypes.oneOf([ 'COMMENT', @@ -31,12 +31,12 @@ class TicketAction extends React.Component { return (
- +
{iconNode}
- {this.renderActionDescription()} + {this.renderEventDescription()}
); @@ -44,21 +44,21 @@ class TicketAction extends React.Component { renderStaffPic() { return ( -
- +
+
); } renderIcon() { return ( -
+
); } - renderActionDescription() { + renderEventDescription() { const renders = { 'COMMENT': this.renderComment.bind(this), 'ASSIGN': this.renderAssignment.bind(this), @@ -74,14 +74,14 @@ class TicketAction extends React.Component { renderComment() { return ( -
- -
- {this.props.author.name} - ({i18n((this.props.author.staff) ? 'STAFF' : 'CUSTOMER')}) +
+ +
+ {this.props.author.name} + ({i18n((this.props.author.staff) ? 'STAFF' : 'CUSTOMER')})
-
{this.props.date}
-
+
{this.props.date}
+
{this.renderFileRow(this.props.file)}
); @@ -89,62 +89,62 @@ class TicketAction extends React.Component { renderAssignment() { return ( -
- {this.props.author.name} - assigned this ticket - on {this.props.date} +
+ {this.props.author.name} + assigned this ticket + on {this.props.date}
) } renderUnAssignment() { return ( -
- {this.props.author.name} - unassigned this ticket - on {this.props.date} +
+ {this.props.author.name} + unassigned this ticket + on {this.props.date}
) } renderClosed() { return ( -
- {this.props.author.name} - closed this ticket - on {this.props.date} +
+ {this.props.author.name} + closed this ticket + on {this.props.date}
) } renderReOpened() { return ( -
- {this.props.author.name} - reopen this ticket - on {this.props.date} +
+ {this.props.author.name} + reopen this ticket + on {this.props.date}
); } renderDepartmentChange() { return ( -
- {this.props.author.name} - change department to - {this.props.content} - on {this.props.date} +
+ {this.props.author.name} + change department to + {this.props.content} + on {this.props.date}
); } renderPriorityChange() { return ( -
- {this.props.author.name} - change priority to - {this.props.content} - on {this.props.date} +
+ {this.props.author.name} + change priority to + {this.props.content} + on {this.props.date}
); } @@ -177,14 +177,14 @@ class TicketAction extends React.Component { }; const classes = { 'row': true, - 'ticket-action': true, - 'ticket-action_staff': this.props.author && this.props.author.staff, - 'ticket-action_circled': circledTypes[this.props.type], - 'ticket-action_unassignment': this.props.type === 'UN_ASSIGN', - 'ticket-action_close': this.props.type === 'CLOSE', - 'ticket-action_reopen': this.props.type === 'RE_OPEN', - 'ticket-action_department': this.props.type === 'DEPARTMENT_CHANGED', - 'ticket-action_priority': this.props.type === 'PRIORITY_CHANGED' + 'ticket-event': true, + 'ticket-event_staff': this.props.author && this.props.author.staff, + 'ticket-event_circled': circledTypes[this.props.type], + 'ticket-event_unassignment': this.props.type === 'UN_ASSIGN', + 'ticket-event_close': this.props.type === 'CLOSE', + 'ticket-event_reopen': this.props.type === 'RE_OPEN', + 'ticket-event_department': this.props.type === 'DEPARTMENT_CHANGED', + 'ticket-event_priority': this.props.type === 'PRIORITY_CHANGED' }; return classNames(classes); @@ -225,4 +225,4 @@ class TicketAction extends React.Component { } } -export default TicketAction; \ No newline at end of file +export default TicketEvent; \ No newline at end of file diff --git a/client/src/app-components/ticket-action.scss b/client/src/app-components/ticket-event.scss similarity index 87% rename from client/src/app-components/ticket-action.scss rename to client/src/app-components/ticket-event.scss index 0e9eb818..5e36aaa0 100644 --- a/client/src/app-components/ticket-action.scss +++ b/client/src/app-components/ticket-event.scss @@ -1,6 +1,6 @@ @import "../scss/vars"; -.ticket-action { +.ticket-event { margin-top: 20px; text-align: left; position: relative; @@ -91,11 +91,11 @@ } &_staff { - .ticket-action__icon { + .ticket-event__icon { background-color: $primary-blue; } - .ticket-action__comment-author-type { + .ticket-event__comment-author-type { color: $primary-blue; } } @@ -104,11 +104,11 @@ margin-top: 35px; margin-bottom: 30px; - .ticket-action__connector { + .ticket-event__connector { top: 28px; } - .ticket-action__icon { + .ticket-event__icon { background-color: white; color: $primary-black; border: 3px solid $light-grey; @@ -121,48 +121,48 @@ margin-top: -8px; } - .ticket-action__circled { + .ticket-event__circled { color: $primary-black; font-size: $font-size--sm; margin-top: 1px; } - .ticket-action__circled-author { + .ticket-event__circled-author { color: $secondary-blue; } - .ticket-action__circled-indication { + .ticket-event__circled-indication { color: $primary-green; } } &_unassignment { - .ticket-action__icon { + .ticket-event__icon { padding-left: 6px; } } &_close { - .ticket-action__icon { + .ticket-event__icon { padding-left: 9px; } } &_reopen { - .ticket-action__icon { + .ticket-event__icon { padding-left: 9px; padding-top: 5px; } } &_department { - .ticket-action__icon { + .ticket-event__icon { padding-left: 6px; } } &_priority { - .ticket-action__icon { + .ticket-event__icon { padding-left: 11px; padding-top: 5px; } diff --git a/client/src/app-components/ticket-viewer.js b/client/src/app-components/ticket-viewer.js index 89237ab3..4b69e7cb 100644 --- a/client/src/app-components/ticket-viewer.js +++ b/client/src/app-components/ticket-viewer.js @@ -7,7 +7,7 @@ import store from 'app/store'; import SessionStore from 'lib-app/session-store'; import SessionActions from 'actions/session-actions'; -import TicketAction from 'app-components/ticket-action'; +import TicketEvent from 'app-components/ticket-event'; import AreYouSure from 'app-components/are-you-sure'; import Form from 'core-components/form'; import FormField from 'core-components/form-field'; @@ -49,10 +49,10 @@ class TicketViewer extends React.Component {
{this.props.editable ? this.renderEditableHeaders() : this.renderHeaders()}
- +
- {ticket.actions && ticket.actions.map(this.renderAction.bind(this))} + {ticket.events && ticket.events.map(this.renderTicketEvent.bind(this))}
{i18n('RESPOND')}
@@ -162,9 +162,9 @@ class TicketViewer extends React.Component { ); } - renderAction(action, index) { + renderTicketEvent(options, index) { return ( - + ); } diff --git a/client/src/data/fixtures/user-fixtures.js b/client/src/data/fixtures/user-fixtures.js index 04cf2cd5..ead1820c 100644 --- a/client/src/data/fixtures/user-fixtures.js +++ b/client/src/data/fixtures/user-fixtures.js @@ -159,7 +159,7 @@ module.exports = [ name: 'Steve Jobs', email: 'steve@jobs.com' }, - actions: [ + events: [ { type: 'ASSIGN', date: 20150409, @@ -275,7 +275,7 @@ module.exports = [ owner: { name: 'Steve Jobs' }, - actions: [ + events: [ { type: 'ASSIGN', date: 20150409, @@ -391,7 +391,7 @@ module.exports = [ owner: { name: 'Steve Jobs' }, - actions: [ + events: [ { type: 'ASSIGN', date: 20150409, From 2e9aae777b0cc4381dabdecfd5febe7562de769c Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 18 Oct 2016 20:48:25 -0300 Subject: [PATCH 5/8] Ivan - Fix DropDown z-index issue [skip ci] --- client/src/core-components/drop-down.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/core-components/drop-down.scss b/client/src/core-components/drop-down.scss index 12e74a5f..facd5c53 100644 --- a/client/src/core-components/drop-down.scss +++ b/client/src/core-components/drop-down.scss @@ -27,7 +27,7 @@ &__list-container { position: absolute; width: 150px; - z-index: 5; + z-index: 100; } &_closed { From 9b83fde4fc784ae7621c52e9eaccf1d169543dfa Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 20 Oct 2016 15:32:57 -0300 Subject: [PATCH 6/8] Ivan - Add admin panel ticket viewer [skip ci] --- client/src/app-components/ticket-viewer.js | 4 +- client/src/app/Routes.js | 2 +- .../panel/tickets/admin-panel-view-ticket.js | 56 ++++++++++++++++++- .../dashboard-ticket/dashboard-ticket-page.js | 7 ++- client/src/data/fixtures/user-fixtures.js | 2 +- 5 files changed, 66 insertions(+), 5 deletions(-) diff --git a/client/src/app-components/ticket-viewer.js b/client/src/app-components/ticket-viewer.js index 4b69e7cb..919ad429 100644 --- a/client/src/app-components/ticket-viewer.js +++ b/client/src/app-components/ticket-viewer.js @@ -242,7 +242,9 @@ class TicketViewer extends React.Component { loading: false }); - store.dispatch(SessionActions.getUserData()); + if(this.props.onComment) { + this.props.onComment(); + } } onCommentFail() { diff --git a/client/src/app/Routes.js b/client/src/app/Routes.js index 0470cd27..f0fc358a 100644 --- a/client/src/app/Routes.js +++ b/client/src/app/Routes.js @@ -84,7 +84,7 @@ export default ( - + diff --git a/client/src/app/admin/panel/tickets/admin-panel-view-ticket.js b/client/src/app/admin/panel/tickets/admin-panel-view-ticket.js index 620324bb..a1b2b2bc 100644 --- a/client/src/app/admin/panel/tickets/admin-panel-view-ticket.js +++ b/client/src/app/admin/panel/tickets/admin-panel-view-ticket.js @@ -1,14 +1,68 @@ import React from 'react'; +import API from 'lib-app/api-call'; +import TicketViewer from 'app-components/ticket-viewer'; +import Loading from 'core-components/loading'; + class AdminPanelViewTicket extends React.Component { + state = { + loading: true, + ticket: {} + }; + render() { return (
- /admin/panel/tickets/view-ticket + {(this.state.loading) ? this.renderLoading() : this.renderView()}
); } + + renderLoading() { + + }; + + renderView() { + return (this.props.ticket) ? this.renderNotFoundError() : this.renderTicketView(); + } + + renderNotFoundError() { + return ( +
+ +
+ ); + } + + renderTicketView() { + return ( +
+ +
+ ); + } + + retrieveTicket() { + this.setState({ + loading: true, + ticket: {} + }); + + API.call({ + path: '/ticket/get', + date: { + ticketNumber: this.props.params.ticketNumber + } + }).then(this.onRetrieveSuccess.bind(this)) + } + + onRetrieveSuccess(result) { + this.setState({ + loading: false, + ticket: result.data + }); + } } export default AdminPanelViewTicket; \ No newline at end of file diff --git a/client/src/app/main/dashboard/dashboard-ticket/dashboard-ticket-page.js b/client/src/app/main/dashboard/dashboard-ticket/dashboard-ticket-page.js index 602b4e05..57faa0d2 100644 --- a/client/src/app/main/dashboard/dashboard-ticket/dashboard-ticket-page.js +++ b/client/src/app/main/dashboard/dashboard-ticket/dashboard-ticket-page.js @@ -2,6 +2,7 @@ import React from 'react'; import _ from 'lodash'; import {connect} from 'react-redux'; +import SessionActions from 'actions/session-actions'; import TicketViewer from 'app-components/ticket-viewer'; class DashboardTicketPage extends React.Component { @@ -13,7 +14,7 @@ class DashboardTicketPage extends React.Component { render() { return (
- +
); } @@ -21,6 +22,10 @@ class DashboardTicketPage extends React.Component { getTicketData() { return _.find(this.props.tickets, {ticketNumber: this.props.params.ticketNumber}); } + + retrieveUserData() { + this.props.dispatch(SessionActions.getUserData()); + } } export default connect((store) => { diff --git a/client/src/data/fixtures/user-fixtures.js b/client/src/data/fixtures/user-fixtures.js index ead1820c..5411a94d 100644 --- a/client/src/data/fixtures/user-fixtures.js +++ b/client/src/data/fixtures/user-fixtures.js @@ -43,7 +43,7 @@ module.exports = [ return { status: 'success', data: { - sessionActive: false + sessionActive: true } }; } From bcb83e52b64eb38850bfd7f795ba2104317606ea Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 20 Oct 2016 22:33:55 -0300 Subject: [PATCH 7/8] Ivan - Add ticket view to admin dashboard [skip ci] --- client/src/app-components/ticket-viewer.js | 39 ++++-- .../panel/tickets/admin-panel-view-ticket.js | 48 +++++-- .../tickets/admin-panel-view-ticket.scss | 18 +++ .../dashboard-ticket/dashboard-ticket-page.js | 2 +- client/src/data/fixtures/ticket-fixtures.js | 125 ++++++++++++++++++ client/src/data/languages/en.js | 3 + 6 files changed, 214 insertions(+), 21 deletions(-) create mode 100644 client/src/app/admin/panel/tickets/admin-panel-view-ticket.scss diff --git a/client/src/app-components/ticket-viewer.js b/client/src/app-components/ticket-viewer.js index 919ad429..182d4718 100644 --- a/client/src/app-components/ticket-viewer.js +++ b/client/src/app-components/ticket-viewer.js @@ -18,7 +18,9 @@ import Button from 'core-components/button'; class TicketViewer extends React.Component { static propTypes = { ticket: React.PropTypes.object, - editable: React.PropTypes.bool + onChange: React.PropTypes.func, + editable: React.PropTypes.bool, + assignmentAllowed: React.PropTypes.bool }; static defaultProps = { @@ -130,6 +132,17 @@ class TicketViewer extends React.Component { 'high': 'HIGH' }; + let ownerNode = null; + if (this.props.assignmentAllowed && _.isEmpty(ticket.owner)) { + ownerNode = ( + + ); + } else { + ownerNode = i18n((ticket.closed) ? 'CLOSED' : 'OPENED'); + } + return (
@@ -155,7 +168,7 @@ class TicketViewer extends React.Component { {(ticket.owner) ? ticket.owner.name : i18n('NONE')}
- {i18n((ticket.closed) ? 'CLOSED' : 'OPENED')} + {ownerNode}
@@ -182,11 +195,11 @@ class TicketViewer extends React.Component { data: { ticketNumber: this.props.ticket.ticketNumber } - }); + }).then(this.onTicketModification.bind(this)); } onCloseClick() { - AreYouSure.openModal(null, this.toggleClose); + AreYouSure.openModal(null, this.toggleClose.bind(this)); } toggleClose() { @@ -195,7 +208,7 @@ class TicketViewer extends React.Component { data: { ticketNumber: this.props.ticket.ticketNumber } - }); + }).then(this.onTicketModification.bind(this)); } changeDepartment(index) { @@ -205,7 +218,7 @@ class TicketViewer extends React.Component { ticketNumber: this.props.ticket.ticketNumber, departmentId: SessionStore.getDepartments()[index].id } - }); + }).then(this.onTicketModification.bind(this)); } changePriority(index) { @@ -221,7 +234,7 @@ class TicketViewer extends React.Component { ticketNumber: this.props.ticket.ticketNumber, priority: priorities[index] } - }); + }).then(this.onTicketModification.bind(this)); } onSubmit(formState) { @@ -241,10 +254,8 @@ class TicketViewer extends React.Component { this.setState({ loading: false }); - - if(this.props.onComment) { - this.props.onComment(); - } + + this.onTicketModification(); } onCommentFail() { @@ -252,6 +263,12 @@ class TicketViewer extends React.Component { loading: false }); } + + onTicketModification() { + if (this.props.onChange) { + this.props.onChange(); + } + } } export default TicketViewer; \ No newline at end of file diff --git a/client/src/app/admin/panel/tickets/admin-panel-view-ticket.js b/client/src/app/admin/panel/tickets/admin-panel-view-ticket.js index a1b2b2bc..141938f9 100644 --- a/client/src/app/admin/panel/tickets/admin-panel-view-ticket.js +++ b/client/src/app/admin/panel/tickets/admin-panel-view-ticket.js @@ -1,8 +1,13 @@ import React from 'react'; +import _ from 'lodash'; import API from 'lib-app/api-call'; +import i18n from 'lib-app/i18n'; +import SessionStore from 'lib-app/session-store'; + import TicketViewer from 'app-components/ticket-viewer'; import Loading from 'core-components/loading'; +import Header from 'core-components/header'; class AdminPanelViewTicket extends React.Component { @@ -11,38 +16,56 @@ class AdminPanelViewTicket extends React.Component { ticket: {} }; + componentDidMount() { + this.retrieveTicket(); + } + render() { return ( -
+
+
{(this.state.loading) ? this.renderLoading() : this.renderView()}
); } renderLoading() { - + return ( +
+ +
+ ) }; renderView() { - return (this.props.ticket) ? this.renderNotFoundError() : this.renderTicketView(); + return (_.isEmpty(this.state.ticket)) ? this.renderNoPermissionError() : this.renderTicketView(); } - renderNotFoundError() { + renderNoPermissionError() { return ( -
- +
+ {i18n('NO_PERMISSION')}
); } renderTicketView() { return ( -
- +
+
); } + getTicketViewProps() { + return { + ticket: this.state.ticket, + onChange: this.retrieveTicket.bind(this), + assignmentAllowed: true, + editable: _.get(this.state.ticket, 'owner.id') === SessionStore.getUserData().id + }; + } + retrieveTicket() { this.setState({ loading: true, @@ -54,7 +77,7 @@ class AdminPanelViewTicket extends React.Component { date: { ticketNumber: this.props.params.ticketNumber } - }).then(this.onRetrieveSuccess.bind(this)) + }).then(this.onRetrieveSuccess.bind(this)).catch(this.onRetrieveFail.bind(this)) } onRetrieveSuccess(result) { @@ -63,6 +86,13 @@ class AdminPanelViewTicket extends React.Component { ticket: result.data }); } + + onRetrieveFail() { + this.setState({ + loading: false, + ticket: {} + }); + } } export default AdminPanelViewTicket; \ No newline at end of file diff --git a/client/src/app/admin/panel/tickets/admin-panel-view-ticket.scss b/client/src/app/admin/panel/tickets/admin-panel-view-ticket.scss new file mode 100644 index 00000000..bdb36b07 --- /dev/null +++ b/client/src/app/admin/panel/tickets/admin-panel-view-ticket.scss @@ -0,0 +1,18 @@ +@import '../../../../scss/vars'; + +.admin-panel-view-ticket { + margin: 10px; + + &__loading { + background-color: $grey; + height: 400px; + } + + &__error { + + } + + &__ticket-view { + margin: 20px 30px; + } +} \ No newline at end of file diff --git a/client/src/app/main/dashboard/dashboard-ticket/dashboard-ticket-page.js b/client/src/app/main/dashboard/dashboard-ticket/dashboard-ticket-page.js index 57faa0d2..c6ea17bc 100644 --- a/client/src/app/main/dashboard/dashboard-ticket/dashboard-ticket-page.js +++ b/client/src/app/main/dashboard/dashboard-ticket/dashboard-ticket-page.js @@ -14,7 +14,7 @@ class DashboardTicketPage extends React.Component { render() { return (
- +
); } diff --git a/client/src/data/fixtures/ticket-fixtures.js b/client/src/data/fixtures/ticket-fixtures.js index f589dd78..3d64bf2b 100644 --- a/client/src/data/fixtures/ticket-fixtures.js +++ b/client/src/data/fixtures/ticket-fixtures.js @@ -77,5 +77,130 @@ module.exports = [ data: {} }; } + }, + { + path: '/ticket/get', + time: 1000, + response: function () { + return { + status: 'success', + data: { + ticketNumber: '118551', + title: 'Lorem ipsum door', + content: 'I had a problem with the installation of the php server', + department: { + id: 1, + name: 'Sales Support' + }, + 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://i65.tinypic.com/9bep95.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://i65.tinypic.com/9bep95.jpg', + staff: true + } + }, + { + type: 'UN_ASSIGN', + date: 20150410, + author: { + name: 'Emilia Clarke', + email: 'jobs@steve.com', + profilePic: 'http://i65.tinypic.com/9bep95.jpg', + staff: true + } + }, + { + type: 'DEPARTMENT_CHANGED', + date: 20150411, + content: 'System support', + author: { + name: 'Emilia Clarke', + email: 'jobs@steve.com', + profilePic: 'http://i65.tinypic.com/9bep95.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://i65.tinypic.com/9bep95.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://i65.tinypic.com/9bep95.jpg', + staff: true + } + }, + { + type: 'RE_OPEN', + date: 20151018, + author: { + name: 'Haskell Curry', + email: 'haskell@lambda.com', + staff: false + } + } + ] + } + }; + } } ]; \ No newline at end of file diff --git a/client/src/data/languages/en.js b/client/src/data/languages/en.js index 5f2f4fdd..aa7b778f 100644 --- a/client/src/data/languages/en.js +++ b/client/src/data/languages/en.js @@ -70,6 +70,7 @@ export default { 'RE_OPEN': 'Re open', 'ASSIGN_TO_ME': 'Assign to me', 'UN_ASSIGN': 'Unassign', + 'VIEW_TICKET': 'View Ticket', //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.', @@ -79,6 +80,7 @@ export default { 'ACCOUNT_DESCRIPTION': 'All your tickets are stored in your accounts\'s profile. Keep track off all your tickets you send to our staff team.', 'SUPPORT_CENTER_DESCRIPTION': 'Welcome to our support center. You can contact us through a tickets system. Your tickets will be answered by our staff.', 'CUSTOM_RESPONSES_DESCRIPTION': 'Custom responses are automated responses for common problems', + 'TICKET_VIEW_DESCRIPTION': 'This ticket has been sent by a customer. Here you can respond or assign the ticket', //ERRORS 'EMAIL_OR_PASSWORD': 'Email or password invalid', @@ -92,6 +94,7 @@ export default { 'PASSWORD_NOT_MATCH': 'Password does not match', 'INVALID_RECOVER': 'Invalid recover data', 'TICKET_SENT_ERROR': 'An error occurred while trying to create the ticket.', + 'NO_PERMISSION': 'You\'ve no permission to access to this page.', //MESSAGES 'SIGNUP_SUCCESS': 'You have registered successfully in our support system.', From e89283e5d324383e814b3bfa02f832a1c8b6449b Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 20 Oct 2016 22:40:15 -0300 Subject: [PATCH 8/8] Ivan - Ticket viewer Minor tweaks [skip ci] --- client/src/app-components/ticket-viewer.js | 29 ++++++++++++--------- client/src/data/fixtures/ticket-fixtures.js | 24 ++++++++--------- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/client/src/app-components/ticket-viewer.js b/client/src/app-components/ticket-viewer.js index 182d4718..d45dd4b4 100644 --- a/client/src/app-components/ticket-viewer.js +++ b/client/src/app-components/ticket-viewer.js @@ -132,17 +132,6 @@ class TicketViewer extends React.Component { 'high': 'HIGH' }; - let ownerNode = null; - if (this.props.assignmentAllowed && _.isEmpty(ticket.owner)) { - ownerNode = ( - - ); - } else { - ownerNode = i18n((ticket.closed) ? 'CLOSED' : 'OPENED'); - } - return (
@@ -168,13 +157,29 @@ class TicketViewer extends React.Component { {(ticket.owner) ? ticket.owner.name : i18n('NONE')}
- {ownerNode} + {this.renderOwnerNode()}
); } + renderOwnerNode() { + let ownerNode = null; + + if (this.props.assignmentAllowed && _.isEmpty(this.props.ticket.owner)) { + ownerNode = ( + + ); + } else { + ownerNode = i18n((this.props.closed) ? 'CLOSED' : 'OPENED'); + } + + return ownerNode; + } + renderTicketEvent(options, index) { return ( diff --git a/client/src/data/fixtures/ticket-fixtures.js b/client/src/data/fixtures/ticket-fixtures.js index 3d64bf2b..5d05e16c 100644 --- a/client/src/data/fixtures/ticket-fixtures.js +++ b/client/src/data/fixtures/ticket-fixtures.js @@ -85,19 +85,19 @@ module.exports = [ return { status: 'success', data: { - ticketNumber: '118551', + ticketNumber: '878552', title: 'Lorem ipsum door', content: 'I had a problem with the installation of the php server', department: { id: 1, name: 'Sales Support' }, - date: 20150409, + date: '20160415', file: 'http://www.opensupports.com/some_file.zip', language: 'en', unread: false, closed: false, - priority: 'high', + priority: 'medium', author: { name: 'Haskell Curry', email: 'haskell@lambda.com' @@ -108,7 +108,7 @@ module.exports = [ events: [ { type: 'ASSIGN', - date: 20150409, + date: '20150409', author: { name: 'Emilia Clarke', email: 'jobs@steve.com', @@ -118,7 +118,7 @@ module.exports = [ }, { type: 'COMMENT', - date: 20150409, + date: '20150409', content: 'Do you have apache installed? It generally happens if you dont have apache.', author: { name: 'Emilia Clarke', @@ -129,7 +129,7 @@ module.exports = [ }, { type: 'UN_ASSIGN', - date: 20150410, + date: '20150410', author: { name: 'Emilia Clarke', email: 'jobs@steve.com', @@ -139,7 +139,7 @@ module.exports = [ }, { type: 'DEPARTMENT_CHANGED', - date: 20150411, + date: '20150411', content: 'System support', author: { name: 'Emilia Clarke', @@ -150,7 +150,7 @@ module.exports = [ }, { type: 'COMMENT', - date: 20150412, + date: '20150412', content: 'I have already installed apache, but the problem persists', author: { name: 'Haskell Curry', @@ -160,7 +160,7 @@ module.exports = [ }, { type: 'PRIORITY_CHANGED', - date: 20150413, + date: '20150413', content: 'MEDIUM', author: { name: 'Emilia Clarke', @@ -171,7 +171,7 @@ module.exports = [ }, { type: 'COMMENT', - date: 20150511, + date: '20150511', content: 'Thanks!, I soved it by myself', author: { name: 'Haskell Curry', @@ -181,7 +181,7 @@ module.exports = [ }, { type: 'CLOSE', - date: 20150513, + date: '20150513', author: { name: 'Emilia Clarke', email: 'jobs@steve.com', @@ -191,7 +191,7 @@ module.exports = [ }, { type: 'RE_OPEN', - date: 20151018, + date: '20151018', author: { name: 'Haskell Curry', email: 'haskell@lambda.com',