From 3997faae5373f05238b4c2911c5508d83e0b99da Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 20 Oct 2016 16:43:01 -0300 Subject: [PATCH 01/23] Max - Add My Tickets title and description [skip ci] --- client/src/app-components/ticket-list.js | 2 -- .../src/app/admin/panel/tickets/admin-panel-my-tickets.js | 8 +++++--- client/src/data/fixtures/user-fixtures.js | 2 +- client/src/data/languages/en.js | 1 + 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/client/src/app-components/ticket-list.js b/client/src/app-components/ticket-list.js index 14b8a99f..b788083a 100644 --- a/client/src/app-components/ticket-list.js +++ b/client/src/app-components/ticket-list.js @@ -137,8 +137,6 @@ class TicketList extends React.Component { } compareFunction(row1, row2) { - let ans = 0; - if (row1.closed == row2.closed) { if (row1.unread == row2.unread) { let s1 = row1.date; diff --git a/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js b/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js index 03a0ffa2..f717dcc9 100644 --- a/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js +++ b/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js @@ -1,12 +1,14 @@ import React from 'react'; +import i18n from 'lib-app/i18n'; + +import Header from 'core-components/header'; + class AdminPanelMyTickets extends React.Component { render() { return ( -
- /admin/panel/tickets/my-tickets -
+
); } } diff --git a/client/src/data/fixtures/user-fixtures.js b/client/src/data/fixtures/user-fixtures.js index dcb09daf..45277f80 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 } }; } diff --git a/client/src/data/languages/en.js b/client/src/data/languages/en.js index 733b36e7..f922dca0 100644 --- a/client/src/data/languages/en.js +++ b/client/src/data/languages/en.js @@ -69,6 +69,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', + 'MY_TICKETS_DESCRIPTION': 'Here you can view the tickets you are responsible for.', //ERRORS 'EMAIL_OR_PASSWORD': 'Email or password invalid', From 82cb246eeb523e75273211072b7a806386992b0b Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 20 Oct 2016 18:47:35 -0300 Subject: [PATCH 02/23] Max - Add My Tickets List [skip ci] --- client/src/actions/admin-data-actions.js | 10 + client/src/app-components/ticket-list.js | 3 +- .../panel/tickets/admin-panel-my-tickets.js | 36 +- client/src/data/fixtures/staff-fixtures.js | 365 +++++++++++++++++- client/src/reducers/admin-data-reducer.js | 19 +- 5 files changed, 427 insertions(+), 6 deletions(-) diff --git a/client/src/actions/admin-data-actions.js b/client/src/actions/admin-data-actions.js index 624f0b82..d332e0ae 100644 --- a/client/src/actions/admin-data-actions.js +++ b/client/src/actions/admin-data-actions.js @@ -10,5 +10,15 @@ export default { data: {} }) }; + }, + + retrieveMyTickets() { + return { + type: 'MY_TICKETS', + payload: API.call({ + path: '/staff/get-tickets', + data: {} + }) + }; } }; \ No newline at end of file diff --git a/client/src/app-components/ticket-list.js b/client/src/app-components/ticket-list.js index b788083a..7fe0f5d0 100644 --- a/client/src/app-components/ticket-list.js +++ b/client/src/app-components/ticket-list.js @@ -11,6 +11,7 @@ import DateTransformer from 'lib-core/date-transformer'; class TicketList extends React.Component { static propTypes = { + loading: React.PropTypes.bool, tickets: React.PropTypes.arrayOf(React.PropTypes.object), type: React.PropTypes.oneOf([ 'primary', @@ -26,7 +27,7 @@ class TicketList extends React.Component { render() { return (
- +
); } diff --git a/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js b/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js index f717dcc9..02f5fc80 100644 --- a/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js +++ b/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js @@ -1,16 +1,46 @@ import React from 'react'; +import {connect} from 'react-redux'; import i18n from 'lib-app/i18n'; +import AdminDataAction from 'actions/admin-data-actions'; import Header from 'core-components/header'; +import DropDown from 'core-components/drop-down'; +import TicketList from 'app-components/ticket-list'; class AdminPanelMyTickets extends React.Component { - + + componentDidMount() { + this.props.dispatch(AdminDataAction.retrieveMyTickets()); + } + render() { return ( -
+
+
+ + +
); } + + getProps() { + console.log(this.props.tickets); + + return { + items: this.props.departments.map(function (obj) { + return { + content: obj.name + }; + }), + size: 'medium' + }; + } } -export default AdminPanelMyTickets; \ No newline at end of file +export default connect((store) => { + return { + departments: store.session.userDepartments, + tickets: store.adminData.myTickets + }; +})(AdminPanelMyTickets); diff --git a/client/src/data/fixtures/staff-fixtures.js b/client/src/data/fixtures/staff-fixtures.js index ea6afbcd..69272f39 100644 --- a/client/src/data/fixtures/staff-fixtures.js +++ b/client/src/data/fixtures/staff-fixtures.js @@ -14,10 +14,373 @@ module.exports = [ departments: [ {id: 1, name: 'Sales Support'}, {id: 2, name: 'Technical Issues'}, - {id: 3, name: 'System and Administration'} + {id: 3, name: 'System and Administration'}, + {id: 4, name: 'Guillermo\'s department'} ] } }; } + }, + { + path: '/staff/get-tickets', + time: 2000, + response: function () { + return { + status: 'success', + data: [ + { + ticketNumber: '445441', + title: 'Problem with installation', + content: 'I had a problem with the installation of the php server', + department: { + id: 2, + name: 'Environment Setup' + }, + 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' + }, + actions: [ + { + 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 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://i65.tinypic.com/9bep95.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: 'Environment Setup' + }, + 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' + }, + actions: [ + { + 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 + } + } + ] + }, + { + ticketNumber: '118551', + title: 'Lorem ipsum door', + content: 'I had a problem with the installation of the php server', + department: { + id: 2, + name: 'Environment Setup' + }, + 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' + }, + actions: [ + { + 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/reducers/admin-data-reducer.js b/client/src/reducers/admin-data-reducer.js index 60c59d20..ba6418e4 100644 --- a/client/src/reducers/admin-data-reducer.js +++ b/client/src/reducers/admin-data-reducer.js @@ -6,6 +6,8 @@ class AdminDataReducer extends Reducer { getInitialState() { return { + myTickets: [], + myTicketsLoaded: false, customResponses: [], customResponsesLoaded: false }; @@ -13,7 +15,9 @@ class AdminDataReducer extends Reducer { getTypeHandlers() { return { - 'CUSTOM_RESPONSES_FULFILLED': this.onCustomResponses + 'CUSTOM_RESPONSES_FULFILLED': this.onCustomResponses, + 'MY_TICKETS_FULFILLED': this.onMyTicketsRetrieved, + 'MY_TICKETS_PENDING': this.onMyTicketsPending }; } @@ -23,6 +27,19 @@ class AdminDataReducer extends Reducer { customResponsesLoaded: true }); } + + onMyTicketsRetrieved(state, payload) { + return _.extend({}, state, { + myTickets: payload.data, + customResponsesLoaded: true + }) + } + + onMyTicketsPending(state) { + return _.extennd({}, state, { + myTicketsLoaded: true + }) + } } export default AdminDataReducer.getInstance(); \ No newline at end of file From 7693f030f062351d47e97aece1871f301042d359 Mon Sep 17 00:00:00 2001 From: AntonyAntonio Date: Sat, 22 Oct 2016 00:40:56 -0300 Subject: [PATCH 03/23] Guillermo - staff-get-all-tickets[skip ci] --- server/controllers/staff.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/controllers/staff.php b/server/controllers/staff.php index 1dccf0d1..90caca42 100644 --- a/server/controllers/staff.php +++ b/server/controllers/staff.php @@ -4,6 +4,7 @@ require_once 'staff/assign-ticket.php'; require_once 'staff/un-assign-ticket.php'; require_once 'staff/get-tickets.php'; require_once 'staff/get-new-tickets.php'; +require_once 'staff/get-all-tickets.php'; $systemControllerGroup = new ControllerGroup(); $systemControllerGroup->setGroupPath('/staff'); @@ -13,5 +14,7 @@ $systemControllerGroup->addController(new AssignStaffController); $systemControllerGroup->addController(new UnAssignStaffController); $systemControllerGroup->addController(new GetTicketStaffController); $systemControllerGroup->addController(new GetNewTicketsStaffController); +$systemControllerGroup->addController(new GetAllTicketsStaffController); + $systemControllerGroup->finalize(); \ No newline at end of file From 037f004d0cbf50861de2a8afadef13a969704508 Mon Sep 17 00:00:00 2001 From: ivan Date: Wed, 26 Oct 2016 12:46:17 -0300 Subject: [PATCH 04/23] Ivan - Add custom response field [skip ci] --- client/src/actions/session-actions.js | 7 +++-- client/src/app-components/ticket-viewer.js | 26 +++++++++++++++++++ client/src/app-components/ticket-viewer.scss | 6 +++++ .../panel/tickets/admin-panel-view-ticket.js | 13 +++++----- client/src/data/languages/en.js | 1 + client/src/reducers/admin-data-reducer.js | 15 ++++++++++- 6 files changed, 59 insertions(+), 9 deletions(-) diff --git a/client/src/actions/session-actions.js b/client/src/actions/session-actions.js index 08c95be8..2d1b7995 100644 --- a/client/src/actions/session-actions.js +++ b/client/src/actions/session-actions.js @@ -1,9 +1,8 @@ import API from 'lib-app/api-call'; +import AdminDataActions from 'actions/admin-data-actions'; import sessionStore from 'lib-app/session-store'; import store from 'app/store'; -import ConfigActions from 'actions/config-actions'; - export default { login(loginData) { return { @@ -13,6 +12,10 @@ export default { data: loginData }).then((result) => { store.dispatch(this.getUserData(result.data.userId, result.data.token, result.data.staff)); + + if(result.data.staff) { + store.dispatch(AdminDataActions.retrieveCustomResponses()); + } return result; }) diff --git a/client/src/app-components/ticket-viewer.js b/client/src/app-components/ticket-viewer.js index d45dd4b4..c324386a 100644 --- a/client/src/app-components/ticket-viewer.js +++ b/client/src/app-components/ticket-viewer.js @@ -20,6 +20,7 @@ class TicketViewer extends React.Component { ticket: React.PropTypes.object, onChange: React.PropTypes.func, editable: React.PropTypes.bool, + customResponses: React.PropTypes.array, assignmentAllowed: React.PropTypes.bool }; @@ -58,6 +59,7 @@ class TicketViewer extends React.Component {
{i18n('RESPOND')}
+ {this.renderCustomResponses()}
@@ -186,6 +188,30 @@ class TicketViewer extends React.Component { ); } + renderCustomResponses() { + let customResponsesNode = null; + + if (this.props.customResponses && this.props.editable) { + let customResponses = this.props.customResponses.map((customResponse) => { + return { + content: customResponse.name + }; + }); + + customResponses.unshift({ + content: i18n('SELECT_CUSTOM_RESPONSE') + }); + + customResponsesNode = ( +
+ +
+ ); + } + + return customResponsesNode; + } + onDepartmentDropdownChanged(event) { AreYouSure.openModal(null, this.changeDepartment.bind(this, event.index)); } diff --git a/client/src/app-components/ticket-viewer.scss b/client/src/app-components/ticket-viewer.scss index c4ec3865..0b885aa2 100644 --- a/client/src/app-components/ticket-viewer.scss +++ b/client/src/app-components/ticket-viewer.scss @@ -72,5 +72,11 @@ padding: 20px; text-align: left; } + + &-custom { + background-color: $very-light-grey; + padding: 20px 0 0 20px; + text-align: left; + } } } \ 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 141938f9..f9f34b20 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,5 +1,6 @@ import React from 'react'; import _ from 'lodash'; +import {connect} from 'react-redux'; import API from 'lib-app/api-call'; import i18n from 'lib-app/i18n'; @@ -62,16 +63,12 @@ class AdminPanelViewTicket extends React.Component { ticket: this.state.ticket, onChange: this.retrieveTicket.bind(this), assignmentAllowed: true, + customResponses: this.props.customResponses, editable: _.get(this.state.ticket, 'owner.id') === SessionStore.getUserData().id }; } retrieveTicket() { - this.setState({ - loading: true, - ticket: {} - }); - API.call({ path: '/ticket/get', date: { @@ -95,4 +92,8 @@ class AdminPanelViewTicket extends React.Component { } } -export default AdminPanelViewTicket; \ No newline at end of file +export default connect((store) => { + return { + customResponses: store.adminData.customResponses + }; +})(AdminPanelViewTicket); diff --git a/client/src/data/languages/en.js b/client/src/data/languages/en.js index aa7b778f..25e74b18 100644 --- a/client/src/data/languages/en.js +++ b/client/src/data/languages/en.js @@ -71,6 +71,7 @@ export default { 'ASSIGN_TO_ME': 'Assign to me', 'UN_ASSIGN': 'Unassign', 'VIEW_TICKET': 'View Ticket', + 'SELECT_CUSTOM_RESPONSE': 'Select a custom response...', //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.', diff --git a/client/src/reducers/admin-data-reducer.js b/client/src/reducers/admin-data-reducer.js index 60c59d20..2aeb295b 100644 --- a/client/src/reducers/admin-data-reducer.js +++ b/client/src/reducers/admin-data-reducer.js @@ -1,6 +1,7 @@ import _ from 'lodash'; import Reducer from 'reducers/reducer'; +import sessionStore from 'lib-app/session-store'; class AdminDataReducer extends Reducer { @@ -13,16 +14,28 @@ class AdminDataReducer extends Reducer { getTypeHandlers() { return { - 'CUSTOM_RESPONSES_FULFILLED': this.onCustomResponses + 'CUSTOM_RESPONSES_FULFILLED': this.onCustomResponses, + 'SESSION_CHECKED': this.onSessionChecked }; } onCustomResponses(state, payload) { + sessionStore.setItem('customResponses', JSON.stringify(payload.data)); + return _.extend({}, state, { customResponses: payload.data, customResponsesLoaded: true }); } + + onSessionChecked(state) { + const customResponses = sessionStore.getItem('customResponses'); + + return _.extend({}, state, { + customResponses: JSON.parse(customResponses), + customResponsesLoaded: true + }); + } } export default AdminDataReducer.getInstance(); \ No newline at end of file From 93366c02da10edf3da6c6bde4c9a4af83bdc8263 Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 27 Oct 2016 16:34:44 -0300 Subject: [PATCH 05/23] Ivan - Add custom response field [skip ci] --- client/src/app-components/ticket-event.js | 2 +- client/src/app-components/ticket-viewer.js | 48 ++++++++++++++++----- client/src/data/fixtures/ticket-fixtures.js | 10 ++--- 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/client/src/app-components/ticket-event.js b/client/src/app-components/ticket-event.js index dd99b24c..3130b91a 100644 --- a/client/src/app-components/ticket-event.js +++ b/client/src/app-components/ticket-event.js @@ -17,7 +17,7 @@ class TicketEvent extends React.Component { ]), author: React.PropTypes.object, content: React.PropTypes.string, - date: React.PropTypes.number + date: React.PropTypes.string }; render() { diff --git a/client/src/app-components/ticket-viewer.js b/client/src/app-components/ticket-viewer.js index c324386a..536730f3 100644 --- a/client/src/app-components/ticket-viewer.js +++ b/client/src/app-components/ticket-viewer.js @@ -1,11 +1,10 @@ import React from 'react'; import _ from 'lodash'; +import RichTextEditor from 'react-rte-browserify'; 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 TicketEvent from 'app-components/ticket-event'; import AreYouSure from 'app-components/are-you-sure'; @@ -33,13 +32,11 @@ class TicketViewer extends React.Component { } }; - constructor(props) { - super(props); - - this.state = { - loading: false - }; - } + state = { + loading: false, + commentValue: RichTextEditor.createEmptyValue(), + commentEdited: false + }; render() { const ticket = this.props.ticket; @@ -61,7 +58,7 @@ class TicketViewer extends React.Component {
{i18n('RESPOND')}
{this.renderCustomResponses()}
- + {i18n('RESPOND_TICKET')} @@ -204,7 +201,7 @@ class TicketViewer extends React.Component { customResponsesNode = (
- +
); } @@ -212,6 +209,20 @@ class TicketViewer extends React.Component { return customResponsesNode; } + getCommentFormProps() { + return { + onSubmit: this.onSubmit.bind(this), + loading: this.state.loading, + onChange: (formState) => {this.setState({ + commentValue: formState.content, + commentEdited: true + })}, + values: { + 'content': this.state.commentValue + } + }; + } + onDepartmentDropdownChanged(event) { AreYouSure.openModal(null, this.changeDepartment.bind(this, event.index)); } @@ -268,6 +279,21 @@ class TicketViewer extends React.Component { }).then(this.onTicketModification.bind(this)); } + onCustomResponsesChanged({index}) { + let replaceContentWithCustomResponse = () => { + this.setState({ + commentValue: RichTextEditor.createValueFromString(this.props.customResponses[index-1].content || '', 'html'), + commentEdited: false + }); + }; + + if (this.state.commentEdited && index) { + AreYouSure.openModal(null, replaceContentWithCustomResponse); + } else { + replaceContentWithCustomResponse(); + } + } + onSubmit(formState) { this.setState({ loading: true diff --git a/client/src/data/fixtures/ticket-fixtures.js b/client/src/data/fixtures/ticket-fixtures.js index 5d05e16c..573ccd61 100644 --- a/client/src/data/fixtures/ticket-fixtures.js +++ b/client/src/data/fixtures/ticket-fixtures.js @@ -39,11 +39,11 @@ module.exports = [ return { status: 'success', data: [ - {name: 'Common issue #1', language: 'en', content: 'some content'}, - {name: 'Common issue #2', language: 'en', content: 'some content'}, - {name: 'Common issue #3', language: 'en', content: 'some content'}, - {name: 'Häufiges Problem #1', language: 'de', content: 'einige Inhalte'}, - {name: 'Häufiges Problem #2', language: 'de', content: 'einige Inhalte'} + {name: 'Common issue #1', language: 'en', content: 'some content 1'}, + {name: 'Common issue #2', language: 'en', content: 'some content 2'}, + {name: 'Common issue #3', language: 'en', content: 'some content 3'}, + {name: 'Häufiges Problem #1', language: 'de', content: 'einige Inhalte 1'}, + {name: 'Häufiges Problem #2', language: 'de', content: 'einige Inhalte 2'} ] }; } From 3179b29158b51d28cb1915f6e5dc101a90503dd3 Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 28 Oct 2016 03:28:11 -0300 Subject: [PATCH 06/23] Ivan - Add my tickets department dropdown, fix loading, add filter, merge master[skip ci] --- client/src/app-components/ticket-list.js | 4 +- .../panel/tickets/admin-panel-my-tickets.js | 69 ++++++++++++++++--- .../panel/tickets/admin-panel-my-tickets.scss | 6 ++ client/src/app/demo/components-demo-page.js | 2 +- client/src/core-components/table.scss | 2 + client/src/core-components/tooltip.scss | 1 + client/src/data/fixtures/staff-fixtures.js | 44 +++++++++--- client/src/data/languages/en.js | 1 + client/src/reducers/admin-data-reducer.js | 8 +-- 9 files changed, 110 insertions(+), 27 deletions(-) create mode 100644 client/src/app/admin/panel/tickets/admin-panel-my-tickets.scss diff --git a/client/src/app-components/ticket-list.js b/client/src/app-components/ticket-list.js index 7fe0f5d0..e9c140fd 100644 --- a/client/src/app-components/ticket-list.js +++ b/client/src/app-components/ticket-list.js @@ -12,6 +12,7 @@ import DateTransformer from 'lib-core/date-transformer'; class TicketList extends React.Component { static propTypes = { loading: React.PropTypes.bool, + ticketPath: React.PropTypes.string, tickets: React.PropTypes.arrayOf(React.PropTypes.object), type: React.PropTypes.oneOf([ 'primary', @@ -21,6 +22,7 @@ class TicketList extends React.Component { static defaultProps = { tickets: [], + ticketPath: '/dashboard/ticket/', type: 'primary' }; @@ -106,7 +108,7 @@ class TicketList extends React.Component { ), title: ( - ), diff --git a/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js b/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js index 02f5fc80..95e3214f 100644 --- a/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js +++ b/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js @@ -1,4 +1,5 @@ import React from 'react'; +import _ from 'lodash'; import {connect} from 'react-redux'; import i18n from 'lib-app/i18n'; @@ -9,6 +10,15 @@ import DropDown from 'core-components/drop-down'; import TicketList from 'app-components/ticket-list'; class AdminPanelMyTickets extends React.Component { + + static defaultProps = { + departments: [], + tickets: [] + }; + + state = { + selectedDepartment: 0 + }; componentDidMount() { this.props.dispatch(AdminDataAction.retrieveMyTickets()); @@ -16,31 +26,68 @@ class AdminPanelMyTickets extends React.Component { render() { return ( -
+
- - +
+ +
+
); } getProps() { - console.log(this.props.tickets); - return { - items: this.props.departments.map(function (obj) { - return { - content: obj.name - }; - }), + tickets: this.getTickets(), + type: 'secondary', + loading: this.props.loading, + ticketPath: '/admin/panel/tickets/view-ticket/' + }; + } + + getDropdownProps() { + return { + items: this.getDepartments(), + onChange: this.changeSelectedDepartment.bind(this), size: 'medium' }; } + + getTickets() { + return (this.state.selectedDepartment) ? _.filter(this.props.tickets, (ticket) => { + return ticket.department.id == this.state.selectedDepartment + }) : this.props.tickets; + } + + getDepartments() { + let departments = this.props.departments.map((department) => { + return {content: department.name}; + }); + + departments.unshift({ + content: i18n('ALL_DEPARTMENTS') + }); + + return departments; + } + + changeSelectedDepartment(event) { + if(event.index === 0) { + this.setState({ + selectedDepartment: 0 + }); + } else { + this.setState({ + selectedDepartment: this.props.departments[event.index - 1].id + }); + } + } } export default connect((store) => { return { departments: store.session.userDepartments, - tickets: store.adminData.myTickets + tickets: store.adminData.myTickets, + loading: !store.adminData.myTicketsLoaded }; })(AdminPanelMyTickets); diff --git a/client/src/app/admin/panel/tickets/admin-panel-my-tickets.scss b/client/src/app/admin/panel/tickets/admin-panel-my-tickets.scss new file mode 100644 index 00000000..1a79e191 --- /dev/null +++ b/client/src/app/admin/panel/tickets/admin-panel-my-tickets.scss @@ -0,0 +1,6 @@ +.admin-panel-my-tickets { + + &__department-select { + margin-bottom: 25px; + } +} \ No newline at end of file diff --git a/client/src/app/demo/components-demo-page.js b/client/src/app/demo/components-demo-page.js index 1d5da38f..a2dd7b7f 100644 --- a/client/src/app/demo/components-demo-page.js +++ b/client/src/app/demo/components-demo-page.js @@ -166,7 +166,7 @@ let DemoPage = React.createClass({ else if(a.title1 > b.title1) ans = 1; return ans; - }}/> + }} loading/> ) } ], diff --git a/client/src/core-components/table.scss b/client/src/core-components/table.scss index 62dd409c..54a73615 100644 --- a/client/src/core-components/table.scss +++ b/client/src/core-components/table.scss @@ -51,6 +51,8 @@ &__loading-wrapper { min-height: 200px; + position: relative; + background-color: $grey; } &__loading { diff --git a/client/src/core-components/tooltip.scss b/client/src/core-components/tooltip.scss index 50bd126d..bbe42bdb 100644 --- a/client/src/core-components/tooltip.scss +++ b/client/src/core-components/tooltip.scss @@ -17,6 +17,7 @@ background-color: #F7F7F7; color: black; padding: 10px; + z-index: 1000; } &__pointer { diff --git a/client/src/data/fixtures/staff-fixtures.js b/client/src/data/fixtures/staff-fixtures.js index 69272f39..5b94d0b1 100644 --- a/client/src/data/fixtures/staff-fixtures.js +++ b/client/src/data/fixtures/staff-fixtures.js @@ -13,9 +13,7 @@ module.exports = [ staff: true, departments: [ {id: 1, name: 'Sales Support'}, - {id: 2, name: 'Technical Issues'}, - {id: 3, name: 'System and Administration'}, - {id: 4, name: 'Guillermo\'s department'} + {id: 2, name: 'Technical Issues'} ] } }; @@ -23,7 +21,7 @@ module.exports = [ }, { path: '/staff/get-tickets', - time: 2000, + time: 300, response: function () { return { status: 'success', @@ -34,7 +32,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: '20160416', file: 'http://www.opensupports.com/some_file.zip', @@ -52,7 +50,7 @@ module.exports = [ name: 'Steve Jobs', email: 'steve@jobs.com' }, - actions: [ + events: [ { type: 'ASSIGN', date: '20150409', @@ -153,7 +151,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: '20160415', file: 'http://www.opensupports.com/some_file.zip', @@ -168,7 +166,7 @@ module.exports = [ owner: { name: 'Steve Jobs' }, - actions: [ + events: [ { type: 'ASSIGN', date: '20150409', @@ -269,7 +267,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: '20150409', file: 'http://www.opensupports.com/some_file.zip', @@ -284,7 +282,7 @@ module.exports = [ owner: { name: 'Steve Jobs' }, - actions: [ + events: [ { type: 'ASSIGN', date: '20150409', @@ -378,6 +376,32 @@ module.exports = [ } } ] + }, + { + ticketNumber: '445441', + title: 'Inscription ACM ICPC', + content: 'I had a problem with the installation of the php server', + department: { + id: 1, + name: 'Sales Support' + }, + 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: [] } ] } diff --git a/client/src/data/languages/en.js b/client/src/data/languages/en.js index 338452aa..93501689 100644 --- a/client/src/data/languages/en.js +++ b/client/src/data/languages/en.js @@ -72,6 +72,7 @@ export default { 'UN_ASSIGN': 'Unassign', 'VIEW_TICKET': 'View Ticket', 'SELECT_CUSTOM_RESPONSE': 'Select a custom response...', + 'ALL_DEPARTMENTS': 'All Departments', //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.', diff --git a/client/src/reducers/admin-data-reducer.js b/client/src/reducers/admin-data-reducer.js index d0695811..32e2fe24 100644 --- a/client/src/reducers/admin-data-reducer.js +++ b/client/src/reducers/admin-data-reducer.js @@ -17,7 +17,7 @@ class AdminDataReducer extends Reducer { getTypeHandlers() { return { 'CUSTOM_RESPONSES_FULFILLED': this.onCustomResponses, - 'SESSION_CHECKED': this.onSessionChecked + 'SESSION_CHECKED': this.onSessionChecked, 'MY_TICKETS_FULFILLED': this.onMyTicketsRetrieved, 'MY_TICKETS_PENDING': this.onMyTicketsPending }; @@ -44,13 +44,13 @@ class AdminDataReducer extends Reducer { onMyTicketsRetrieved(state, payload) { return _.extend({}, state, { myTickets: payload.data, - customResponsesLoaded: true + myTicketsLoaded: true }) } onMyTicketsPending(state) { - return _.extennd({}, state, { - myTicketsLoaded: true + return _.extend({}, state, { + myTicketsLoaded: false }) } } From 343b455905c7fbfe407d4bb8822050e3f5a7ae5f Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 28 Oct 2016 03:30:04 -0300 Subject: [PATCH 07/23] Ivan - Minor tweak demo[skip ci] --- client/src/app/demo/components-demo-page.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/app/demo/components-demo-page.js b/client/src/app/demo/components-demo-page.js index a2dd7b7f..1d5da38f 100644 --- a/client/src/app/demo/components-demo-page.js +++ b/client/src/app/demo/components-demo-page.js @@ -166,7 +166,7 @@ let DemoPage = React.createClass({ else if(a.title1 > b.title1) ans = 1; return ans; - }} loading/> + }}/> ) } ], From 1966697a218f66e1005829a1c19a11321dbcd34d Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 28 Oct 2016 04:01:03 -0300 Subject: [PATCH 08/23] Ivan - Add all tickets and new tickets[skip ci] --- client/src/actions/admin-data-actions.js | 20 ++ client/src/app-components/ticket-list.js | 54 +++++- client/src/app-components/ticket-list.scss | 5 + .../panel/tickets/admin-panel-all-tickets.js | 39 +++- .../panel/tickets/admin-panel-my-tickets.js | 50 +---- .../panel/tickets/admin-panel-my-tickets.scss | 6 - .../panel/tickets/admin-panel-new-tickets.js | 39 +++- client/src/data/fixtures/staff-fixtures.js | 178 ++++++++++++++++++ client/src/data/languages/en.js | 2 + client/src/reducers/admin-data-reducer.js | 40 +++- 10 files changed, 366 insertions(+), 67 deletions(-) create mode 100644 client/src/app-components/ticket-list.scss delete mode 100644 client/src/app/admin/panel/tickets/admin-panel-my-tickets.scss diff --git a/client/src/actions/admin-data-actions.js b/client/src/actions/admin-data-actions.js index d332e0ae..f9ac73f7 100644 --- a/client/src/actions/admin-data-actions.js +++ b/client/src/actions/admin-data-actions.js @@ -20,5 +20,25 @@ export default { data: {} }) }; + }, + + retrieveNewTickets() { + return { + type: 'NEW_TICKETS', + payload: API.call({ + path: '/staff/get-new-tickets', + data: {} + }) + }; + }, + + retrieveAllTickets() { + return { + type: 'ALL_TICKETS', + payload: API.call({ + path: '/staff/get-all-tickets', + data: {} + }) + }; } }; \ No newline at end of file diff --git a/client/src/app-components/ticket-list.js b/client/src/app-components/ticket-list.js index e9c140fd..4d75493a 100644 --- a/client/src/app-components/ticket-list.js +++ b/client/src/app-components/ticket-list.js @@ -1,16 +1,19 @@ import React from 'react'; +import _ from 'lodash'; import i18n from 'lib-app/i18n'; +import DateTransformer from 'lib-core/date-transformer'; + +import TicketInfo from 'app-components/ticket-info'; import Table from 'core-components/table'; import Button from 'core-components/button'; import Tooltip from 'core-components/tooltip'; -import TicketInfo from 'app-components/ticket-info'; - -import DateTransformer from 'lib-core/date-transformer'; +import DropDown from 'core-components/drop-down'; class TicketList extends React.Component { static propTypes = { + departments: React.PropTypes.array, loading: React.PropTypes.bool, ticketPath: React.PropTypes.string, tickets: React.PropTypes.arrayOf(React.PropTypes.object), @@ -26,14 +29,51 @@ class TicketList extends React.Component { type: 'primary' }; + state = { + selectedDepartment: 0 + }; + render() { return (
+ {(this.props.type === 'secondary') ? this.renderDepartmentsDropDown() : null}
); } + renderDepartmentsDropDown() { + return ( +
+ +
+ ); + } + + getDepartmentDropdownProps() { + return { + items: this.getDepartments(), + onChange: (event) => { + this.setState({ + selectedDepartment: event.index && this.props.departments[event.index - 1].id + }); + }, + size: 'medium' + }; + } + + getDepartments() { + let departments = this.props.departments.map((department) => { + return {content: department.name}; + }); + + departments.unshift({ + content: i18n('ALL_DEPARTMENTS') + }); + + return departments; + } + getTableHeaders() { if (this.props.type == 'primary' ) { return [ @@ -95,7 +135,13 @@ class TicketList extends React.Component { } getTableRows() { - return this.props.tickets.map(this.gerTicketTableObject.bind(this)); + return this.getTickets().map(this.gerTicketTableObject.bind(this)); + } + + getTickets() { + return (this.state.selectedDepartment) ? _.filter(this.props.tickets, (ticket) => { + return ticket.department.id == this.state.selectedDepartment + }) : this.props.tickets; } gerTicketTableObject(ticket) { diff --git a/client/src/app-components/ticket-list.scss b/client/src/app-components/ticket-list.scss new file mode 100644 index 00000000..f6f8d91c --- /dev/null +++ b/client/src/app-components/ticket-list.scss @@ -0,0 +1,5 @@ +.ticket-list { + &__department-selector { + margin-bottom: 25px; + } +} \ No newline at end of file diff --git a/client/src/app/admin/panel/tickets/admin-panel-all-tickets.js b/client/src/app/admin/panel/tickets/admin-panel-all-tickets.js index 93a4f327..58816efe 100644 --- a/client/src/app/admin/panel/tickets/admin-panel-all-tickets.js +++ b/client/src/app/admin/panel/tickets/admin-panel-all-tickets.js @@ -1,14 +1,47 @@ import React from 'react'; +import {connect} from 'react-redux'; + +import i18n from 'lib-app/i18n'; + +import AdminDataAction from 'actions/admin-data-actions'; +import Header from 'core-components/header'; +import TicketList from 'app-components/ticket-list'; class AdminPanelAllTickets extends React.Component { + static defaultProps = { + departments: [], + tickets: [] + }; + + componentDidMount() { + this.props.dispatch(AdminDataAction.retrieveAllTickets()); + } + render() { return ( -
- /admin/panel/tickets/all-tickets +
+
+
); } + + getProps() { + return { + departments: this.props.departments, + tickets: this.props.tickets, + type: 'secondary', + loading: this.props.loading, + ticketPath: '/admin/panel/tickets/view-ticket/' + }; + } } -export default AdminPanelAllTickets; \ No newline at end of file +export default connect((store) => { + return { + departments: store.session.userDepartments, + tickets: store.adminData.newTickets, + loading: !store.adminData.newTicketsLoaded + }; +})(AdminPanelAllTickets); diff --git a/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js b/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js index 95e3214f..512454b1 100644 --- a/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js +++ b/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js @@ -1,12 +1,10 @@ import React from 'react'; -import _ from 'lodash'; import {connect} from 'react-redux'; import i18n from 'lib-app/i18n'; import AdminDataAction from 'actions/admin-data-actions'; import Header from 'core-components/header'; -import DropDown from 'core-components/drop-down'; import TicketList from 'app-components/ticket-list'; class AdminPanelMyTickets extends React.Component { @@ -16,10 +14,6 @@ class AdminPanelMyTickets extends React.Component { tickets: [] }; - state = { - selectedDepartment: 0 - }; - componentDidMount() { this.props.dispatch(AdminDataAction.retrieveMyTickets()); } @@ -28,9 +22,6 @@ class AdminPanelMyTickets extends React.Component { return (
-
- -
); @@ -38,50 +29,13 @@ class AdminPanelMyTickets extends React.Component { getProps() { return { - tickets: this.getTickets(), + departments: this.props.departments, + tickets: this.props.tickets, type: 'secondary', loading: this.props.loading, ticketPath: '/admin/panel/tickets/view-ticket/' }; } - - getDropdownProps() { - return { - items: this.getDepartments(), - onChange: this.changeSelectedDepartment.bind(this), - size: 'medium' - }; - } - - getTickets() { - return (this.state.selectedDepartment) ? _.filter(this.props.tickets, (ticket) => { - return ticket.department.id == this.state.selectedDepartment - }) : this.props.tickets; - } - - getDepartments() { - let departments = this.props.departments.map((department) => { - return {content: department.name}; - }); - - departments.unshift({ - content: i18n('ALL_DEPARTMENTS') - }); - - return departments; - } - - changeSelectedDepartment(event) { - if(event.index === 0) { - this.setState({ - selectedDepartment: 0 - }); - } else { - this.setState({ - selectedDepartment: this.props.departments[event.index - 1].id - }); - } - } } export default connect((store) => { diff --git a/client/src/app/admin/panel/tickets/admin-panel-my-tickets.scss b/client/src/app/admin/panel/tickets/admin-panel-my-tickets.scss deleted file mode 100644 index 1a79e191..00000000 --- a/client/src/app/admin/panel/tickets/admin-panel-my-tickets.scss +++ /dev/null @@ -1,6 +0,0 @@ -.admin-panel-my-tickets { - - &__department-select { - margin-bottom: 25px; - } -} \ No newline at end of file diff --git a/client/src/app/admin/panel/tickets/admin-panel-new-tickets.js b/client/src/app/admin/panel/tickets/admin-panel-new-tickets.js index 42d250a8..819e9b56 100644 --- a/client/src/app/admin/panel/tickets/admin-panel-new-tickets.js +++ b/client/src/app/admin/panel/tickets/admin-panel-new-tickets.js @@ -1,14 +1,47 @@ import React from 'react'; +import {connect} from 'react-redux'; + +import i18n from 'lib-app/i18n'; + +import AdminDataAction from 'actions/admin-data-actions'; +import Header from 'core-components/header'; +import TicketList from 'app-components/ticket-list'; class AdminPanelNewTickets extends React.Component { + static defaultProps = { + departments: [], + tickets: [] + }; + + componentDidMount() { + this.props.dispatch(AdminDataAction.retrieveNewTickets()); + } + render() { return ( -
- /admin/panel/tickets/new-tickets +
+
+
); } + + getProps() { + return { + departments: this.props.departments, + tickets: this.props.tickets, + type: 'secondary', + loading: this.props.loading, + ticketPath: '/admin/panel/tickets/view-ticket/' + }; + } } -export default AdminPanelNewTickets; \ No newline at end of file +export default connect((store) => { + return { + departments: store.session.userDepartments, + tickets: store.adminData.newTickets, + loading: !store.adminData.newTicketsLoaded + }; +})(AdminPanelNewTickets); diff --git a/client/src/data/fixtures/staff-fixtures.js b/client/src/data/fixtures/staff-fixtures.js index 5b94d0b1..4d1686cd 100644 --- a/client/src/data/fixtures/staff-fixtures.js +++ b/client/src/data/fixtures/staff-fixtures.js @@ -406,5 +406,183 @@ module.exports = [ ] } } + }, + { + path: '/staff/get-new-tickets', + time: 300, + response: function () { + return { + status: 'success', + data: [ + { + ticketNumber: '445441', + title: 'Inscription ACM ICPC', + content: 'I had a problem with the installation of the php server', + department: { + id: 1, + name: 'Sales Support' + }, + 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: [] + }, + { + ticketNumber: '445441', + title: 'Inscription ACM ICPC', + content: 'I had a problem with the installation of the php server', + department: { + id: 1, + name: 'Sales Support' + }, + 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: [] + }, + { + ticketNumber: '445441', + title: 'Code jam is awesome', + content: 'I had a problem with the installation of the php server', + department: { + id: 2, + name: 'Technical Issues' + }, + 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: [] + } + ] + } + } + }, + { + path: '/staff/get-all-tickets', + time: 300, + response: function () { + return { + status: 'success', + data: [ + { + ticketNumber: '445441', + title: 'Inscription ACM ICPC', + content: 'I had a problem with the installation of the php server', + department: { + id: 1, + name: 'Sales Support' + }, + 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: [] + }, + { + ticketNumber: '445441', + title: 'Inscription ACM ICPC', + content: 'I had a problem with the installation of the php server', + department: { + id: 1, + name: 'Sales Support' + }, + 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: [] + }, + { + ticketNumber: '445441', + title: 'Code jam is awesome', + content: 'I had a problem with the installation of the php server', + department: { + id: 2, + name: 'Technical Issues' + }, + 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: [] + } + ] + } + } } ]; \ No newline at end of file diff --git a/client/src/data/languages/en.js b/client/src/data/languages/en.js index 93501689..3721809b 100644 --- a/client/src/data/languages/en.js +++ b/client/src/data/languages/en.js @@ -83,6 +83,8 @@ export default { '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', 'MY_TICKETS_DESCRIPTION': 'Here you can view the tickets you are responsible for.', + 'NEW_TICKETS_DESCRIPTION': 'Here you can view all the new tickets that are not assigned by anyone.', + 'ALL_TICKETS_DESCRIPTION': 'Here you can view the tickets of the departments you are assigned.', 'TICKET_VIEW_DESCRIPTION': 'This ticket has been sent by a customer. Here you can respond or assign the ticket', //ERRORS diff --git a/client/src/reducers/admin-data-reducer.js b/client/src/reducers/admin-data-reducer.js index 32e2fe24..6ed135ee 100644 --- a/client/src/reducers/admin-data-reducer.js +++ b/client/src/reducers/admin-data-reducer.js @@ -7,10 +7,14 @@ class AdminDataReducer extends Reducer { getInitialState() { return { + customResponses: [], + customResponsesLoaded: false, myTickets: [], myTicketsLoaded: false, - customResponses: [], - customResponsesLoaded: false + newTickets: [], + newTicketsLoaded: false, + allTickets: [], + allTicketsLoaded: false }; } @@ -19,7 +23,11 @@ class AdminDataReducer extends Reducer { 'CUSTOM_RESPONSES_FULFILLED': this.onCustomResponses, 'SESSION_CHECKED': this.onSessionChecked, 'MY_TICKETS_FULFILLED': this.onMyTicketsRetrieved, - 'MY_TICKETS_PENDING': this.onMyTicketsPending + 'MY_TICKETS_PENDING': this.onMyTicketsPending, + 'NEW_TICKETS_FULFILLED': this.onNewTicketsRetrieved, + 'NEW_TICKETS_PENDING': this.onNewTicketsPending, + 'ALL_TICKETS_FULFILLED': this.onAllTicketsRetrieved, + 'ALL_TICKETS_PENDING': this.onAllTicketsPending }; } @@ -53,6 +61,32 @@ class AdminDataReducer extends Reducer { myTicketsLoaded: false }) } + + onNewTicketsRetrieved(state, payload) { + return _.extend({}, state, { + newTickets: payload.data, + newTicketsLoaded: true + }) + } + + onNewTicketsPending(state) { + return _.extend({}, state, { + newTicketsLoaded: false + }) + } + + onAllTicketsRetrieved(state, payload) { + return _.extend({}, state, { + allTickets: payload.data, + allTicketsLoaded: true + }) + } + + onAllTicketsPending(state) { + return _.extend({}, state, { + allTicketsLoaded: false + }) + } } export default AdminDataReducer.getInstance(); \ No newline at end of file From b712cd645ba9898f96420acd3944750140e24957 Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 28 Oct 2016 04:04:15 -0300 Subject: [PATCH 09/23] Ivan - Fix styling [skip ci] --- client/src/app-components/ticket-list.scss | 46 +++++++++++++++++++++ client/src/app-components/tiket-list.scss | 47 ---------------------- 2 files changed, 46 insertions(+), 47 deletions(-) delete mode 100644 client/src/app-components/tiket-list.scss diff --git a/client/src/app-components/ticket-list.scss b/client/src/app-components/ticket-list.scss index f6f8d91c..416d55c5 100644 --- a/client/src/app-components/ticket-list.scss +++ b/client/src/app-components/ticket-list.scss @@ -1,5 +1,51 @@ +@import "../scss/vars"; + .ticket-list { + &__department-selector { margin-bottom: 25px; } + + &__number { + text-align: left; + } + + &__title { + text-align: left; + } + + &__department { + text-align: right; + } + + &__date { + text-align: right; + } + + &__title-link:hover, + &__title-link:focus { + outline: none; + text-decoration: underline; + } + + &__priority-low, + &__priority-medium, + &__priority-high { + display: inline-block; + border-radius: 10px; + width: 70px; + color: white; + } + + &__priority-low { + background-color: $primary-green; + } + + &__priority-medium { + background-color: $secondary-blue; + } + + &__priority-high { + background-color: $primary-red; + } } \ No newline at end of file diff --git a/client/src/app-components/tiket-list.scss b/client/src/app-components/tiket-list.scss deleted file mode 100644 index 2355c6e4..00000000 --- a/client/src/app-components/tiket-list.scss +++ /dev/null @@ -1,47 +0,0 @@ -@import "../scss/vars"; - -.ticket-list { - - &__number { - text-align: left; - } - - &__title { - text-align: left; - } - - &__department { - text-align: right; - } - - &__date { - text-align: right; - } - - &__title-link:hover, - &__title-link:focus { - outline: none; - text-decoration: underline; - } - - &__priority-low, - &__priority-medium, - &__priority-high { - display: inline-block; - border-radius: 10px; - width: 70px; - color: white; - } - - &__priority-low { - background-color: $primary-green; - } - - &__priority-medium { - background-color: $secondary-blue; - } - - &__priority-high { - background-color: $primary-red; - } -} \ No newline at end of file From 5112aac650532fbd4a9db58b747ea9bf39f8112d Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 28 Oct 2016 13:21:16 -0300 Subject: [PATCH 10/23] Maxi - Minor fixes [skip ci] --- client/src/app-components/ticket-list.js | 2 +- client/src/app/admin/panel/tickets/admin-panel-all-tickets.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/app-components/ticket-list.js b/client/src/app-components/ticket-list.js index 4d75493a..e80d0c6b 100644 --- a/client/src/app-components/ticket-list.js +++ b/client/src/app-components/ticket-list.js @@ -5,7 +5,6 @@ import i18n from 'lib-app/i18n'; import DateTransformer from 'lib-core/date-transformer'; import TicketInfo from 'app-components/ticket-info'; - import Table from 'core-components/table'; import Button from 'core-components/button'; import Tooltip from 'core-components/tooltip'; @@ -24,6 +23,7 @@ class TicketList extends React.Component { }; static defaultProps = { + loading: false, tickets: [], ticketPath: '/dashboard/ticket/', type: 'primary' diff --git a/client/src/app/admin/panel/tickets/admin-panel-all-tickets.js b/client/src/app/admin/panel/tickets/admin-panel-all-tickets.js index 58816efe..490a15cf 100644 --- a/client/src/app/admin/panel/tickets/admin-panel-all-tickets.js +++ b/client/src/app/admin/panel/tickets/admin-panel-all-tickets.js @@ -41,7 +41,7 @@ class AdminPanelAllTickets extends React.Component { export default connect((store) => { return { departments: store.session.userDepartments, - tickets: store.adminData.newTickets, - loading: !store.adminData.newTicketsLoaded + tickets: store.adminData.allTickets, + loading: !store.adminData.allTicketsLoaded }; })(AdminPanelAllTickets); From c17034f182729dc0280923bb174de1fdb82ec026 Mon Sep 17 00:00:00 2001 From: Max Red Date: Fri, 28 Oct 2016 17:59:50 -0300 Subject: [PATCH 11/23] Max - call ticket seen from both admin and client [skip ci] --- .../panel/tickets/admin-panel-view-ticket.js | 11 +++++++- .../dashboard-ticket/dashboard-ticket-page.js | 25 ++++++++++++++++--- client/src/data/fixtures/ticket-fixtures.js | 13 +++++++++- 3 files changed, 44 insertions(+), 5 deletions(-) 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 f9f34b20..f0744670 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 @@ -71,7 +71,7 @@ class AdminPanelViewTicket extends React.Component { retrieveTicket() { API.call({ path: '/ticket/get', - date: { + data: { ticketNumber: this.props.params.ticketNumber } }).then(this.onRetrieveSuccess.bind(this)).catch(this.onRetrieveFail.bind(this)) @@ -82,6 +82,15 @@ class AdminPanelViewTicket extends React.Component { loading: false, ticket: result.data }); + + if(result.data.unreadStaff){ + API.call({ + path: '/ticket/seen', + data: { + ticketNumber: this.props.params.ticketNumber + } + }) + } } onRetrieveFail() { 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 c6ea17bc..cfd74743 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,9 @@ import React from 'react'; import _ from 'lodash'; import {connect} from 'react-redux'; +import i18n from 'lib-app/i18n'; +import API from 'lib-app/api-call'; + import SessionActions from 'actions/session-actions'; import TicketViewer from 'app-components/ticket-viewer'; @@ -11,16 +14,32 @@ class DashboardTicketPage extends React.Component { tickets: React.PropTypes.array }; + componentDidMount() { + let ticket = this.getTicketData(); + if(ticket.unread) { + API.call({ + path: '/ticket/seen', + data: { + ticketNumber: ticket.ticketNumber + } + }) + } + } + render() { + let ticketView = i18n('NO_PERMISSION'); + if(!_.isEmpty(this.getTicketData())) { + ticketView = ; + } return (
- + {ticketView}
); } getTicketData() { - return _.find(this.props.tickets, {ticketNumber: this.props.params.ticketNumber}); + return _.find(this.props.tickets, {ticketNumber: this.props.params.ticketNumber}) || {}; } retrieveUserData() { @@ -32,4 +51,4 @@ export default connect((store) => { return { tickets: store.session.userTickets }; -})(DashboardTicketPage); \ No newline at end of file +})(DashboardTicketPage); diff --git a/client/src/data/fixtures/ticket-fixtures.js b/client/src/data/fixtures/ticket-fixtures.js index 573ccd61..b83a8a76 100644 --- a/client/src/data/fixtures/ticket-fixtures.js +++ b/client/src/data/fixtures/ticket-fixtures.js @@ -78,6 +78,16 @@ module.exports = [ }; } }, + { + path: '/ticket/seen', + time: 200, + response: function () { + return { + status: 'success', + data: {} + }; + } + }, { path: '/ticket/get', time: 1000, @@ -96,6 +106,7 @@ module.exports = [ file: 'http://www.opensupports.com/some_file.zip', language: 'en', unread: false, + unreadStaff: true, closed: false, priority: 'medium', author: { @@ -203,4 +214,4 @@ module.exports = [ }; } } -]; \ No newline at end of file +]; From 0388ba1329b8bbc0ded9a79c303eaca4cffabfeb Mon Sep 17 00:00:00 2001 From: Max Red Date: Fri, 28 Oct 2016 18:08:57 -0300 Subject: [PATCH 12/23] Max - fix typos [skip ci] --- .../src/app/admin/panel/tickets/admin-panel-view-ticket.js | 2 +- .../main/dashboard/dashboard-ticket/dashboard-ticket-page.js | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) 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 f0744670..5d2583ec 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 @@ -83,7 +83,7 @@ class AdminPanelViewTicket extends React.Component { ticket: result.data }); - if(result.data.unreadStaff){ + if(result.data.unreadStaff) { API.call({ path: '/ticket/seen', data: { 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 cfd74743..959fe32f 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 @@ -16,21 +16,24 @@ class DashboardTicketPage extends React.Component { componentDidMount() { let ticket = this.getTicketData(); + if(ticket.unread) { API.call({ path: '/ticket/seen', data: { ticketNumber: ticket.ticketNumber } - }) + }); } } render() { let ticketView = i18n('NO_PERMISSION'); + if(!_.isEmpty(this.getTicketData())) { ticketView = ; } + return (
{ticketView} From af29c62d821fce38640debd6141f2bdaac3e4d60 Mon Sep 17 00:00:00 2001 From: Max Red Date: Fri, 28 Oct 2016 19:21:55 -0300 Subject: [PATCH 13/23] Max - create info tooltip WIP [skip ci] --- client/src/app/demo/components-demo-page.js | 9 +++- client/src/core-components/info-tooltip.js | 51 ++++++++++++++++++++ client/src/core-components/info-tooltip.scss | 17 +++++++ 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 client/src/core-components/info-tooltip.js create mode 100644 client/src/core-components/info-tooltip.scss diff --git a/client/src/app/demo/components-demo-page.js b/client/src/app/demo/components-demo-page.js index 1d5da38f..70a2c2ba 100644 --- a/client/src/app/demo/components-demo-page.js +++ b/client/src/app/demo/components-demo-page.js @@ -15,6 +15,7 @@ const DropDown = require('core-components/drop-down'); const Menu = require('core-components/menu'); const Tooltip = require('core-components/tooltip'); const Table = require('core-components/table'); +const InfoTooltip = require('core-components/info-tooltip'); let dropDownItems = [{content: 'English'}, {content: 'Spanish'}, {content: 'German'}, {content: 'Portuguese'}, {content: 'Japanese'}]; let secondaryMenuItems = [ @@ -168,6 +169,12 @@ let DemoPage = React.createClass({ return ans; }}/> ) + }, + { + title: 'InfoTooltip', + render: ( + + ) } ], @@ -197,4 +204,4 @@ let DemoPage = React.createClass({ } }); -export default DemoPage; \ No newline at end of file +export default DemoPage; diff --git a/client/src/core-components/info-tooltip.js b/client/src/core-components/info-tooltip.js new file mode 100644 index 00000000..a634ab44 --- /dev/null +++ b/client/src/core-components/info-tooltip.js @@ -0,0 +1,51 @@ +import React from 'react'; +import classNames from 'classnames'; + +import Icon from 'core-components/icon'; +import Tooltip from 'core-components/tooltip'; + +class InfoTooltip extends React.Component { + static propTypes = { + type: React.PropTypes.oneOf(['default', 'warning']), + text: React.PropTypes.string.isRequired + }; + + static defaultProps = { + type: 'default' + }; + + render() { + // exclamation-triangle + // question-circle + let name = (this.props.type === 'default') ? 'question-circle' : 'exclamation-triangle'; + + return ( +
+ + + + + +
+ ); + } + + renderText() { + return ( +
+ {this.props.text} +
+ ); + } + + getClass() { + let classes = { + 'info-tooltip': true, + 'info-tooltip_warning': (this.props.type === 'warning') + }; + + return classNames(classes); + } +} + +export default InfoTooltip; diff --git a/client/src/core-components/info-tooltip.scss b/client/src/core-components/info-tooltip.scss new file mode 100644 index 00000000..432b932c --- /dev/null +++ b/client/src/core-components/info-tooltip.scss @@ -0,0 +1,17 @@ +@import "../scss/vars"; + +.info-tooltip { + &__text { + + } + + &__icon { + color: $secondary-blue; + } + + &_warning { + .info-tooltip__icon { + color: $primary-red; + } + } +} From 59bfdf11288163b7f5b18a884d84c9cddd039816 Mon Sep 17 00:00:00 2001 From: Max Red Date: Fri, 28 Oct 2016 20:04:50 -0300 Subject: [PATCH 14/23] Max - add styling to tooltip [skip ci] --- client/src/app/demo/components-demo-page.js | 5 ++++- client/src/core-components/info-tooltip.js | 4 ++++ client/src/core-components/info-tooltip.scss | 11 ++++++++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/client/src/app/demo/components-demo-page.js b/client/src/app/demo/components-demo-page.js index 70a2c2ba..b19470a0 100644 --- a/client/src/app/demo/components-demo-page.js +++ b/client/src/app/demo/components-demo-page.js @@ -173,7 +173,10 @@ let DemoPage = React.createClass({ { title: 'InfoTooltip', render: ( - +
+ + +
) } ], diff --git a/client/src/core-components/info-tooltip.js b/client/src/core-components/info-tooltip.js index a634ab44..6e78f557 100644 --- a/client/src/core-components/info-tooltip.js +++ b/client/src/core-components/info-tooltip.js @@ -31,8 +31,12 @@ class InfoTooltip extends React.Component { } renderText() { + let message = (this.props.type === 'default') ? 'Information' : 'Warning'; return (
+
+ {message} +
{this.props.text}
); diff --git a/client/src/core-components/info-tooltip.scss b/client/src/core-components/info-tooltip.scss index 432b932c..4fc65c39 100644 --- a/client/src/core-components/info-tooltip.scss +++ b/client/src/core-components/info-tooltip.scss @@ -2,7 +2,10 @@ .info-tooltip { &__text { - + &__title { + color: $secondary-blue; + font-size: $font-size--md; + } } &__icon { @@ -13,5 +16,11 @@ .info-tooltip__icon { color: $primary-red; } + + .info-tooltip__text { + &__title { + color: $primary-red; + } + } } } From 940b72bf6fde1ae2fdb75cff1a5194e7d702b35a Mon Sep 17 00:00:00 2001 From: Max Red Date: Fri, 28 Oct 2016 21:21:06 -0300 Subject: [PATCH 15/23] Max - add i18n [skip ci] --- client/src/app/demo/components-demo-page.js | 5 +---- client/src/core-components/info-tooltip.js | 5 +++-- client/src/core-components/info-tooltip.scss | 4 ++-- client/src/data/languages/en.js | 4 +++- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/client/src/app/demo/components-demo-page.js b/client/src/app/demo/components-demo-page.js index b19470a0..ef679cbd 100644 --- a/client/src/app/demo/components-demo-page.js +++ b/client/src/app/demo/components-demo-page.js @@ -173,10 +173,7 @@ let DemoPage = React.createClass({ { title: 'InfoTooltip', render: ( -
- - -
+ ) } ], diff --git a/client/src/core-components/info-tooltip.js b/client/src/core-components/info-tooltip.js index 6e78f557..b2c92f10 100644 --- a/client/src/core-components/info-tooltip.js +++ b/client/src/core-components/info-tooltip.js @@ -1,6 +1,7 @@ import React from 'react'; import classNames from 'classnames'; +import i18n from 'lib-app/i18n'; import Icon from 'core-components/icon'; import Tooltip from 'core-components/tooltip'; @@ -31,10 +32,10 @@ class InfoTooltip extends React.Component { } renderText() { - let message = (this.props.type === 'default') ? 'Information' : 'Warning'; + let message = (this.props.type === 'default') ? i18n('INFO') : i18n('WARNING'); return (
-
+
{message}
{this.props.text} diff --git a/client/src/core-components/info-tooltip.scss b/client/src/core-components/info-tooltip.scss index 4fc65c39..63691bad 100644 --- a/client/src/core-components/info-tooltip.scss +++ b/client/src/core-components/info-tooltip.scss @@ -2,7 +2,7 @@ .info-tooltip { &__text { - &__title { + &-title { color: $secondary-blue; font-size: $font-size--md; } @@ -18,7 +18,7 @@ } .info-tooltip__text { - &__title { + &-title { color: $primary-red; } } diff --git a/client/src/data/languages/en.js b/client/src/data/languages/en.js index 25e74b18..556666fc 100644 --- a/client/src/data/languages/en.js +++ b/client/src/data/languages/en.js @@ -72,6 +72,8 @@ export default { 'UN_ASSIGN': 'Unassign', 'VIEW_TICKET': 'View Ticket', 'SELECT_CUSTOM_RESPONSE': 'Select a custom response...', + 'WARNING': 'Warning', + 'INFO': 'Information', //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.', @@ -108,4 +110,4 @@ export default { '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.' -}; \ No newline at end of file +}; From 32b4775a49dc9f699fc9c211834f2238ce18a142 Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 28 Oct 2016 22:57:58 -0300 Subject: [PATCH 16/23] Ivan - Add test to ticket list[skip ci] --- .../__tests__/ticket-list-test.js | 188 ++++++++++++++++++ client/src/app-components/ticket-list.js | 1 + 2 files changed, 189 insertions(+) create mode 100644 client/src/app-components/__tests__/ticket-list-test.js diff --git a/client/src/app-components/__tests__/ticket-list-test.js b/client/src/app-components/__tests__/ticket-list-test.js new file mode 100644 index 00000000..8e591a48 --- /dev/null +++ b/client/src/app-components/__tests__/ticket-list-test.js @@ -0,0 +1,188 @@ +const _ = require('lodash'); +const TicketInfo = ReactMock(); +const Table = ReactMock(); +const Button = ReactMock(); +const Tooltip = ReactMock(); +const Dropdown = ReactMock(); +const i18n = stub().returnsArg(0); + +const TicketList = requireUnit('app-components/ticket-list', { + 'app-components/ticket-info': TicketInfo, + 'core-components/table': Table, + 'core-components/button': Button, + 'core-components/tooltip': Tooltip, + 'core-components/drop-down': Dropdown, + 'lib-app/i18n': i18n +}); + +describe('TicketList component', function () { + let ticketList, table, dropdown; + let tickets = (function() { + let ticket = { + unread: false, + closed: false, + title: 'This is not working', + ticketNumber: 123124, + date: '20160215', + department: { + id: 1, + name: 'Sales Support' + }, + priority: 'low', + author: { + id: 3, + name: 'Francisco Villegas' + } + }; + let list = _.range(5).map(() => ticket); + + list = list.concat(_.range(5).map(() => { + return _.extend({}, ticket, { + department: { + id: 2, + name: 'Tech Help' + } + }) + })); + + return list; + })(); + + function renderTicketList(props = {}) { + ticketList = TestUtils.renderIntoDocument( + + ); + + table = TestUtils.scryRenderedComponentsWithType(ticketList, Table); + dropdown = TestUtils.scryRenderedComponentsWithType(ticketList, Dropdown); + } + + it('should pass correct props to Table', function () { + renderTicketList(); + expect(table[0].props.loading).to.equal(false); + expect(table[0].props.pageSize).to.equal(10); + expect(table[0].props.headers).to.deep.equal([ + { + key: 'number', + value: i18n('NUMBER'), + className: 'ticket-list__number col-md-1' + }, + { + key: 'title', + value: i18n('TITLE'), + className: 'ticket-list__title col-md-6' + }, + { + key: 'department', + value: i18n('DEPARTMENT'), + className: 'ticket-list__department col-md-3' + }, + { + key: 'date', + value: i18n('DATE'), + className: 'ticket-list__date col-md-2' + } + ]); + }); + + it('should pass loading to Table', function () { + renderTicketList({loading: true}); + expect(table[0].props.loading).to.equal(true); + }); + + it('should pass correct compare function to Table', function () { + let minCompare = table[0].props.comp; + + let row1 = { + closed: false, + unread: false, + date: '20160405' + }; + let row2 = { + closed: false, + unread: false, + date: '20160406' + }; + expect(minCompare(row1, row2)).to.equal(1); + + row1.unread = true; + expect(minCompare(row1, row2)).to.equal(-1); + + row2.unread = true; + expect(minCompare(row1, row2)).to.equal(1); + + row2.date = '20160401'; + expect(minCompare(row1, row2)).to.equal(-1); + }); + + describe('when using secondary type', function () { + beforeEach(function () { + renderTicketList({ + type: 'secondary', + departments: [ + {id: 1, name: 'Sales Support'}, + {id: 2, name: 'Tech Help'} + ] + }); + }); + + it('should pass correct props to Table', function () { + expect(table[0].props.headers).to.deep.equal([ + { + key: 'number', + value: i18n('NUMBER'), + className: 'ticket-list__number col-md-1' + }, + { + key: 'title', + value: i18n('TITLE'), + className: 'ticket-list__title col-md-4' + }, + { + key: 'priority', + value: i18n('PRIORITY'), + className: 'ticket-list__priority col-md-1' + }, + { + key: 'department', + value: i18n('DEPARTMENT'), + className: 'ticket-list__department col-md-2' + }, + { + key: 'author', + value: i18n('AUTHOR'), + className: 'ticket-list__author col-md-2' + }, + { + key: 'date', + value: i18n('DATE'), + className: 'ticket-list__date col-md-2' + } + ]); + }); + + it('should pass correct props to dropdown', function () { + expect(dropdown[0].props.items).to.deep.equal([ + {content: i18n('ALL_DEPARTMENTS')}, + {content: 'Sales Support'}, + {content: 'Tech Help'} + ]); + expect(dropdown[0].props.size).to.equal('medium'); + }); + + it('should filter tickets by department when DropDown changes', function () { + dropdown[0].props.onChange({index: 1}); + _.forEach(table[0].props.rows, function (row) { + expect(row.department).to.equal('Sales Support'); + }); + + dropdown[0].props.onChange({index: 2}); + _.forEach(table[0].props.rows, function (row) { + expect(row.department).to.equal('Tech Help'); + }); + + dropdown[0].props.onChange({index: 0}); + expect(table[0].props.rows.length).to.equal(10); + }); + }); +}); \ No newline at end of file diff --git a/client/src/app-components/ticket-list.js b/client/src/app-components/ticket-list.js index e80d0c6b..3f9b2e61 100644 --- a/client/src/app-components/ticket-list.js +++ b/client/src/app-components/ticket-list.js @@ -25,6 +25,7 @@ class TicketList extends React.Component { static defaultProps = { loading: false, tickets: [], + departments: [], ticketPath: '/dashboard/ticket/', type: 'primary' }; From 5d887e63f400b65ab7276b7d683ddab39f74e4a3 Mon Sep 17 00:00:00 2001 From: maxred Date: Sat, 29 Oct 2016 00:49:06 -0300 Subject: [PATCH 17/23] Max - deletes comments [skip ci] --- client/src/core-components/info-tooltip.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/client/src/core-components/info-tooltip.js b/client/src/core-components/info-tooltip.js index b2c92f10..92c6ca24 100644 --- a/client/src/core-components/info-tooltip.js +++ b/client/src/core-components/info-tooltip.js @@ -16,8 +16,6 @@ class InfoTooltip extends React.Component { }; render() { - // exclamation-triangle - // question-circle let name = (this.props.type === 'default') ? 'question-circle' : 'exclamation-triangle'; return ( From 83e3672f559b2645c0f45cb3bc176b0082483e7c Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 4 Nov 2016 19:10:32 -0300 Subject: [PATCH 18/23] Ivan - Add Get all tickets and search [skip ci] --- server/controllers/staff.php | 3 +- server/controllers/staff/get-all-tickets.php | 54 +++++++++++ server/controllers/staff/search-tickets.php | 74 +++++++++++++++ server/controllers/ticket/create.php | 2 +- server/data/ERRORS.php | 2 + server/models/DataStore.php | 11 ++- server/models/Ticket.php | 4 +- tests/init.rb | 1 + tests/staff/get-all-tickets.rb | 98 ++++++++++++++++++++ tests/ticket/create.rb | 5 +- 10 files changed, 244 insertions(+), 10 deletions(-) create mode 100644 server/controllers/staff/get-all-tickets.php create mode 100644 server/controllers/staff/search-tickets.php create mode 100644 tests/staff/get-all-tickets.rb diff --git a/server/controllers/staff.php b/server/controllers/staff.php index 90caca42..aafedcbd 100644 --- a/server/controllers/staff.php +++ b/server/controllers/staff.php @@ -5,6 +5,7 @@ require_once 'staff/un-assign-ticket.php'; require_once 'staff/get-tickets.php'; require_once 'staff/get-new-tickets.php'; require_once 'staff/get-all-tickets.php'; +require_once 'staff/search-tickets.php'; $systemControllerGroup = new ControllerGroup(); $systemControllerGroup->setGroupPath('/staff'); @@ -15,6 +16,6 @@ $systemControllerGroup->addController(new UnAssignStaffController); $systemControllerGroup->addController(new GetTicketStaffController); $systemControllerGroup->addController(new GetNewTicketsStaffController); $systemControllerGroup->addController(new GetAllTicketsStaffController); - +$systemControllerGroup->addController(new SearchTicketStaffController); $systemControllerGroup->finalize(); \ No newline at end of file diff --git a/server/controllers/staff/get-all-tickets.php b/server/controllers/staff/get-all-tickets.php new file mode 100644 index 00000000..be7641a2 --- /dev/null +++ b/server/controllers/staff/get-all-tickets.php @@ -0,0 +1,54 @@ + 'staff_1', + 'requestData' => [ + 'page' => [ + 'validation' => DataValidator::numeric(), + 'error' => ERRORS::INVALID_PAGE + ] + ] + ]; + } + + public function handler() { + + Response::respondSuccess([ + 'tickets' => $this->getTicketList()->toArray(), + 'pages' => $this->getTotalPages() + ]); + } + + private function getTicketList() { + $page = Controller::request('page'); + + $query = $this->getStaffDepartmentsQueryFilter(); + $query .= 'ORDER BY id DESC LIMIT 10 OFFSET ' . (($page-1)*10); + + return Ticket::find($query); + } + + private function getTotalPages() { + $query = $this->getStaffDepartmentsQueryFilter(); + + return ceil(Ticket::count($query) / 10); + } + + private function getStaffDepartmentsQueryFilter() { + $user = Controller::getLoggedUser(); + + $query = ' ('; + foreach ($user->sharedDepartmentList as $department) { + $query .= 'department_id=' . $department->id . ' OR '; + } + $query = substr($query,0,-3); + $query .= ') '; + + return $query; + } +} \ No newline at end of file diff --git a/server/controllers/staff/search-tickets.php b/server/controllers/staff/search-tickets.php new file mode 100644 index 00000000..e7af0189 --- /dev/null +++ b/server/controllers/staff/search-tickets.php @@ -0,0 +1,74 @@ + 'staff_1', + 'requestData' => [ + 'query' => [ + 'validation' => DataValidator::alpha(), + 'error' => ERRORS::INVALID_QUERY + ], + 'page' => [ + 'validation' => DataValidator::numeric(), + 'error' => ERRORS::INVALID_PAGE + ] + ] + ]; + } + + public function handler() { + Response::respondSuccess([ + 'tickets' => $this->getTicketList()->toArray(), + 'pages' => $this->getTotalPages() + ]); + } + + private function getTicketList() { + $query = $this->getSearchQuery(); + + return Ticket::find($query, [ + Controller::request('query') . '%', + '%' . Controller::request('query') . '%', + Controller::request('query') . '%' + ]); + } + + private function getSearchQuery() { + $page = Controller::request('page'); + + $query = " (title LIKE ? OR title LIKE ?) AND "; + $query .= $this->getStaffDepartmentsQueryFilter(); + $query .= "ORDER BY CASE WHEN (title LIKE ?) THEN 1 ELSE 2 END ASC LIMIT 10 OFFSET " . (($page-1)*10); + + return $query; + } + + private function getTotalPages() { + $query = " (title LIKE ? OR title LIKE ?) AND "; + $query .= $this->getStaffDepartmentsQueryFilter(); + + $ticketQuantity = Ticket::count($query, [ + Controller::request('query') . '%', + '%' . Controller::request('query') . '%' + ]); + + return ceil($ticketQuantity / 10); + } + + private function getStaffDepartmentsQueryFilter() { + $user = Controller::getLoggedUser(); + + $query = ' ('; + foreach ($user->sharedDepartmentList as $department) { + $query .= 'department_id=' . $department->id . ' OR '; + } + $query = substr($query, 0, -3); + $query .= ') '; + + return $query; + } +} \ No newline at end of file diff --git a/server/controllers/ticket/create.php b/server/controllers/ticket/create.php index 4de927f9..8cd3be5e 100644 --- a/server/controllers/ticket/create.php +++ b/server/controllers/ticket/create.php @@ -16,7 +16,7 @@ class CreateController extends Controller { 'permission' => 'user', 'requestData' => [ 'title' => [ - 'validation' => DataValidator::length(3, 30), + 'validation' => DataValidator::length(10, 200), 'error' => ERRORS::INVALID_TITLE ], 'content' => [ diff --git a/server/data/ERRORS.php b/server/data/ERRORS.php index c1478b8e..90f3b0d5 100644 --- a/server/data/ERRORS.php +++ b/server/data/ERRORS.php @@ -19,4 +19,6 @@ class ERRORS { const INVALID_LANGUAGE = 'INVALID_LANGUAGE'; const TICKET_ALREADY_ASSIGNED = 'TICKET_ALREADY_ASSIGNED'; const INVALID_PRIORITY = 'INVALID_PRIORITY'; + const INVALID_PAGE = 'INVALID_PAGE'; + const INVALID_QUERY = 'INVALID_QUERY'; } diff --git a/server/models/DataStore.php b/server/models/DataStore.php index 41b19bf8..d73abfcd 100644 --- a/server/models/DataStore.php +++ b/server/models/DataStore.php @@ -16,8 +16,9 @@ abstract class DataStore { return ($bean) ? new static($bean) : new NullDataStore(); } - public static function count() { - return RedBean::count(static::TABLE); + + public static function count($addSQL = '', $bindings = array()) { + return RedBean::count(static::TABLE, $addSQL, $bindings); } public static function getAll() { @@ -30,10 +31,10 @@ abstract class DataStore { return $dataStoreList; } - public static function find($query) { - $beanList = RedBean::find(static::TABLE,$query); + public static function find($query = '', $matches = []) { + $beanList = RedBean::find(static::TABLE, $query, $matches); - return DataStoreList::getList(ucfirst(static::TABLE),$beanList); + return DataStoreList::getList(ucfirst(static::TABLE), $beanList); } private static function validateProp($propToValidate) { diff --git a/server/models/Ticket.php b/server/models/Ticket.php index 74f166d2..aa44c289 100644 --- a/server/models/Ticket.php +++ b/server/models/Ticket.php @@ -45,7 +45,7 @@ class Ticket extends DataStore { } public function generateUniqueTicketNumber() { - $ticketQuantity = Ticket::count('ticket'); + $ticketQuantity = Ticket::count(); $minValue = 100000; $maxValue = 999999; @@ -53,7 +53,7 @@ class Ticket extends DataStore { $ticketNumber = Hashing::getRandomTicketNumber($minValue, $maxValue); } else { $firstTicketNumber = Ticket::getTicket(1)->ticketNumber; - $gap = 176611; + $gap = 176611; //TODO: USE RANDOM PRIME INSTEAD $ticketNumber = ($firstTicketNumber - $minValue + $ticketQuantity * $gap) % ($maxValue - $minValue + 1) + $minValue; } diff --git a/tests/init.rb b/tests/init.rb index 1ae95b85..23122e39 100644 --- a/tests/init.rb +++ b/tests/init.rb @@ -31,5 +31,6 @@ require './staff/un-assign-ticket.rb' require './staff/get-tickets.rb' require './ticket/change-priority.rb' require './staff/get-new-tickets.rb' +require './staff/get-all-tickets.rb' diff --git a/tests/staff/get-all-tickets.rb b/tests/staff/get-all-tickets.rb new file mode 100644 index 00000000..fdedc865 --- /dev/null +++ b/tests/staff/get-all-tickets.rb @@ -0,0 +1,98 @@ +describe 'Retrieve all tickets' do + describe '/staff/get-all-tickets' do + Scripts.login('login@os4.com', 'loginpass') + + def createTicket(title) + request('/ticket/create',{ + title: title, + content: 'The north remembers', + departmentId: 1, + csrf_userid: $csrf_userid, + csrf_token: $csrf_token + }) + end + + it 'should return last tickets tickets' do + createTicket('Integer sit amet tellus cursus') + createTicket('consequat tortor sed') + createTicket('Fusce lacinia felis quis molestie pellentesque') + createTicket('Aliquam fringilla dapibus lacus') + createTicket('Aenean enim orci') + createTicket('luctus in sagittis non') + createTicket('consectetur at velit') + createTicket('Etiam et maximus quam') + createTicket('Donec facilisis pelleipsumntesque feugiat') + createTicket('Cras gravida bibendum vehicula') + createTicket('Fusce venenatis iaculis commodo') + createTicket('quis vulputate lectus feugiat eu') + createTicket('ipsum Aenean maximus quis leo et eleifend') + createTicket('In vel ex semper nisl sollicitudin') + createTicket('volutpat vel nec enim') + createTicket('Ut semper viverra nulla') + createTicket('Duis consequat nec metus a vestibulum') + createTicket('Vestibulum porta justo id sem bibendum lacinia') + createTicket('Phasellus erat ipsum') + createTicket('imperdiet vel auctor sed') + createTicket('placerat id velit') + createTicket('Quisque egestas ipsum') + + request('/user/logout') + Scripts.login($staff[:email], $staff[:password], true) + response = request('/staff/get-all-tickets', { + page: 1, + csrf_userid: $csrf_userid, + csrf_token: $csrf_token + }) + + (response['status']).should.equal('success') + (response['data']['pages']).should.equal(4) + (response['data']['tickets'].size).should.equal(10) + (response['data']['tickets'][0]['title']).should.equal('Quisque egestas ipsum') + (response['data']['tickets'][1]['title']).should.equal('placerat id velit') + (response['data']['tickets'][2]['title']).should.equal('imperdiet vel auctor sed') + (response['data']['tickets'][3]['title']).should.equal('Phasellus erat ipsum') + (response['data']['tickets'][4]['title']).should.equal('Vestibulum porta justo id sem bibendum lacinia') + (response['data']['tickets'][5]['title']).should.equal('Duis consequat nec metus a vestibulum') + (response['data']['tickets'][6]['title']).should.equal('Ut semper viverra nulla') + (response['data']['tickets'][7]['title']).should.equal('volutpat vel nec enim') + (response['data']['tickets'][8]['title']).should.equal('In vel ex semper nisl sollicitudin') + (response['data']['tickets'][9]['title']).should.equal('ipsum Aenean maximus quis leo et eleifend') + end + + it 'should work with pagination' do + response = request('/staff/get-all-tickets', { + page: 2, + csrf_userid: $csrf_userid, + csrf_token: $csrf_token + }) + + (response['status']).should.equal('success') + (response['data']['pages']).should.equal(4) + (response['data']['tickets'].size).should.equal(10) + (response['data']['tickets'][0]['title']).should.equal('quis vulputate lectus feugiat eu') + (response['data']['tickets'][1]['title']).should.equal('Fusce venenatis iaculis commodo') + (response['data']['tickets'][2]['title']).should.equal('Cras gravida bibendum vehicula') + (response['data']['tickets'][3]['title']).should.equal('Donec facilisis pelleipsumntesque feugiat') + (response['data']['tickets'][4]['title']).should.equal('Etiam et maximus quam') + (response['data']['tickets'][5]['title']).should.equal('consectetur at velit') + (response['data']['tickets'][6]['title']).should.equal('luctus in sagittis non') + (response['data']['tickets'][7]['title']).should.equal('Aenean enim orci') + (response['data']['tickets'][8]['title']).should.equal('Aliquam fringilla dapibus lacus') + (response['data']['tickets'][9]['title']).should.equal('Fusce lacinia felis quis molestie pellentesque') + end + end + + describe '/staff/search-tickets' do + response = request('/staff/search-tickets', { + query: 'ipsum', + page: 1, + csrf_userid: $csrf_userid, + csrf_token: $csrf_token + }) + + (response['status']).should.equal('success') + (response['data']['pages']).should.equal(4) + (response['data']['tickets'].size).should.equal(10) + (response['data']['tickets'][0]['title']).should.equal('ipsum Aenean maximus quis leo et eleifend') + end +end \ No newline at end of file diff --git a/tests/ticket/create.rb b/tests/ticket/create.rb index d670f03d..b1a56d8e 100644 --- a/tests/ticket/create.rb +++ b/tests/ticket/create.rb @@ -29,8 +29,11 @@ describe '/ticket/create' do end it 'should fail if title is very long' do + long_text = '' + 300.times {long_text << 'a'} + result = request('/ticket/create',{ - title: 'I WISH I WAS THE MONSTER YOU THINK I AM. -Tyrion', + title: long_text, departmentId: 1, csrf_userid: $csrf_userid, csrf_token: $csrf_token From faf2544d1d8df036edd347bca13d6267c478347e Mon Sep 17 00:00:00 2001 From: Ivan Diaz Date: Sat, 5 Nov 2016 16:56:33 +0000 Subject: [PATCH 19/23] init-settings.php edited online with Bitbucket --- server/controllers/system/init-settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/controllers/system/init-settings.php b/server/controllers/system/init-settings.php index 8b6050de..10f27aa2 100644 --- a/server/controllers/system/init-settings.php +++ b/server/controllers/system/init-settings.php @@ -88,7 +88,7 @@ class InitSettingsController extends Controller { 'name' => 'Emilia Clarke', 'email' => 'staff@opensupports.com', 'password' => Hashing::hashPassword('staff'), - 'profilePic' => 'http://i65.tinypic.com/9bep95.jpg', + 'profilePic' => 'http://www.opensupports.com/profilepic.jpg', 'level' => 3, 'sharedDepartmentList' => Department::getAll(), 'sharedTicketList' => [] From cef6ccd9e3c936c8aaada54a5a6087ec876d0512 Mon Sep 17 00:00:00 2001 From: Ivan Diaz Date: Sat, 5 Nov 2016 17:01:04 +0000 Subject: [PATCH 20/23] staff-fixtures.js edited online with Bitbucket --- client/src/data/fixtures/staff-fixtures.js | 38 +++++++++++----------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/client/src/data/fixtures/staff-fixtures.js b/client/src/data/fixtures/staff-fixtures.js index 4d1686cd..f84cef51 100644 --- a/client/src/data/fixtures/staff-fixtures.js +++ b/client/src/data/fixtures/staff-fixtures.js @@ -8,7 +8,7 @@ module.exports = [ data: { name: 'Emilia Clarke', email: 'staff@opensupports.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', level: 1, staff: true, departments: [ @@ -57,7 +57,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -68,7 +68,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -78,7 +78,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -89,7 +89,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -110,7 +110,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -130,7 +130,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -173,7 +173,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -184,7 +184,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -194,7 +194,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -205,7 +205,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -226,7 +226,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -246,7 +246,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -289,7 +289,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -300,7 +300,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -310,7 +310,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -321,7 +321,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -342,7 +342,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -362,7 +362,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, From 141197ba738e274fe98889429dba2846ee07b488 Mon Sep 17 00:00:00 2001 From: Ivan Diaz Date: Sat, 5 Nov 2016 17:03:13 +0000 Subject: [PATCH 21/23] ticket-fixtures.js edited online with Bitbucket [skip ci] --- client/src/data/fixtures/ticket-fixtures.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/client/src/data/fixtures/ticket-fixtures.js b/client/src/data/fixtures/ticket-fixtures.js index b83a8a76..aa49a20c 100644 --- a/client/src/data/fixtures/ticket-fixtures.js +++ b/client/src/data/fixtures/ticket-fixtures.js @@ -42,8 +42,8 @@ module.exports = [ {name: 'Common issue #1', language: 'en', content: 'some content 1'}, {name: 'Common issue #2', language: 'en', content: 'some content 2'}, {name: 'Common issue #3', language: 'en', content: 'some content 3'}, - {name: 'Häufiges Problem #1', language: 'de', content: 'einige Inhalte 1'}, - {name: 'Häufiges Problem #2', language: 'de', content: 'einige Inhalte 2'} + {name: 'Häufiges Problem #1', language: 'de', content: 'einige Inhalte 1'}, + {name: 'Häufiges Problem #2', language: 'de', content: 'einige Inhalte 2'} ] }; } @@ -123,7 +123,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -134,7 +134,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -144,7 +144,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -155,7 +155,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -176,7 +176,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -196,7 +196,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, From 761029339811343ab87bf897e42961c7b29c6dca Mon Sep 17 00:00:00 2001 From: Ivan Diaz Date: Sat, 5 Nov 2016 17:05:20 +0000 Subject: [PATCH 22/23] user-fixtures.js edited online with Bitbucket [skip ci] --- client/src/data/fixtures/user-fixtures.js | 36 +++++++++++------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/client/src/data/fixtures/user-fixtures.js b/client/src/data/fixtures/user-fixtures.js index d8798d6a..1177e941 100644 --- a/client/src/data/fixtures/user-fixtures.js +++ b/client/src/data/fixtures/user-fixtures.js @@ -165,7 +165,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -176,7 +176,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -186,7 +186,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -197,7 +197,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -218,7 +218,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -238,7 +238,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -281,7 +281,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -292,7 +292,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -302,7 +302,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -313,7 +313,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -334,7 +334,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -354,7 +354,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -397,7 +397,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -408,7 +408,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -418,7 +418,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -429,7 +429,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -450,7 +450,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, @@ -470,7 +470,7 @@ module.exports = [ author: { name: 'Emilia Clarke', email: 'jobs@steve.com', - profilePic: 'http://i65.tinypic.com/9bep95.jpg', + profilePic: 'http://www.opensupports.com/profilepic.jpg', staff: true } }, From 89837b0726f6bef4cf8bb379445f27998c109ca5 Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 18 Nov 2016 01:40:43 -0300 Subject: [PATCH 23/23] Ivan - Add all ticket search and server pagination [skip ci] --- client/src/actions/admin-data-actions.js | 14 +- client/src/app-components/ticket-list.js | 19 ++- .../panel/tickets/admin-panel-all-tickets.js | 37 ++++- .../tickets/admin-panel-all-tickets.scss | 6 + client/src/core-components/search-box.js | 41 +++++ client/src/core-components/search-box.scss | 21 +++ client/src/core-components/table.js | 38 +++-- client/src/core-components/table.scss | 2 +- client/src/data/fixtures/staff-fixtures.js | 153 +++++++++--------- client/src/reducers/admin-data-reducer.js | 3 +- 10 files changed, 235 insertions(+), 99 deletions(-) create mode 100644 client/src/app/admin/panel/tickets/admin-panel-all-tickets.scss create mode 100644 client/src/core-components/search-box.js create mode 100644 client/src/core-components/search-box.scss diff --git a/client/src/actions/admin-data-actions.js b/client/src/actions/admin-data-actions.js index f9ac73f7..aea9550e 100644 --- a/client/src/actions/admin-data-actions.js +++ b/client/src/actions/admin-data-actions.js @@ -32,12 +32,22 @@ export default { }; }, - retrieveAllTickets() { + retrieveAllTickets(page) { return { type: 'ALL_TICKETS', payload: API.call({ path: '/staff/get-all-tickets', - data: {} + data: {page} + }) + }; + }, + + searchTickets(query, page) { + return { + type: 'ALL_TICKETS', + payload: API.call({ + path: '/staff/search-tickets', + data: {query, page} }) }; } diff --git a/client/src/app-components/ticket-list.js b/client/src/app-components/ticket-list.js index 3f9b2e61..fa6f8aac 100644 --- a/client/src/app-components/ticket-list.js +++ b/client/src/app-components/ticket-list.js @@ -15,6 +15,7 @@ class TicketList extends React.Component { departments: React.PropTypes.array, loading: React.PropTypes.bool, ticketPath: React.PropTypes.string, + showDepartmentDropdown: React.PropTypes.bool, tickets: React.PropTypes.arrayOf(React.PropTypes.object), type: React.PropTypes.oneOf([ 'primary', @@ -23,6 +24,7 @@ class TicketList extends React.Component { }; static defaultProps = { + showDepartmentDropdown: true, loading: false, tickets: [], departments: [], @@ -37,8 +39,8 @@ class TicketList extends React.Component { render() { return (
- {(this.props.type === 'secondary') ? this.renderDepartmentsDropDown() : null} -
+ {(this.props.type === 'secondary' && this.props.showDepartmentDropdown) ? this.renderDepartmentsDropDown() : null} +
); } @@ -62,6 +64,19 @@ class TicketList extends React.Component { size: 'medium' }; } + + getTableProps() { + return { + loading: this.props.loading, + headers: this.getTableHeaders(), + rows: this.getTableRows(), + pageSize: 10, + comp: this.compareFunction, + page: this.props.page, + pages: this.props.pages, + onPageChange: this.props.onPageChange + }; + } getDepartments() { let departments = this.props.departments.map((department) => { diff --git a/client/src/app/admin/panel/tickets/admin-panel-all-tickets.js b/client/src/app/admin/panel/tickets/admin-panel-all-tickets.js index 490a15cf..00dbc3a4 100644 --- a/client/src/app/admin/panel/tickets/admin-panel-all-tickets.js +++ b/client/src/app/admin/panel/tickets/admin-panel-all-tickets.js @@ -6,6 +6,7 @@ import i18n from 'lib-app/i18n'; import AdminDataAction from 'actions/admin-data-actions'; import Header from 'core-components/header'; import TicketList from 'app-components/ticket-list'; +import SearchBox from 'core-components/search-box'; class AdminPanelAllTickets extends React.Component { @@ -14,6 +15,11 @@ class AdminPanelAllTickets extends React.Component { tickets: [] }; + state = { + page: 1, + query: '' + }; + componentDidMount() { this.props.dispatch(AdminDataAction.retrieveAllTickets()); } @@ -22,26 +28,51 @@ class AdminPanelAllTickets extends React.Component { return (
- +
+ +
+
); } - getProps() { + getTicketListProps() { return { + showDepartmentDropdown: false, departments: this.props.departments, tickets: this.props.tickets, type: 'secondary', loading: this.props.loading, - ticketPath: '/admin/panel/tickets/view-ticket/' + ticketPath: '/admin/panel/tickets/view-ticket/', + onPageChange: this.onPageChange.bind(this), + page: this.state.page, + pages: this.props.pages }; } + + onSearch(query) { + this.setState({query, page: 1}); + this.props.dispatch(AdminDataAction.searchTickets(query)); + } + + onPageChange(event) { + this.setState({ + page: event.target.value + }); + + if(this.state.query) { + this.props.dispatch(AdminDataAction.searchTickets(this.state.query, event.target.value)); + } else { + this.props.dispatch(AdminDataAction.retrieveAllTickets(event.target.value)); + } + } } export default connect((store) => { return { departments: store.session.userDepartments, tickets: store.adminData.allTickets, + pages: store.adminData.allTicketsPages, loading: !store.adminData.allTicketsLoaded }; })(AdminPanelAllTickets); diff --git a/client/src/app/admin/panel/tickets/admin-panel-all-tickets.scss b/client/src/app/admin/panel/tickets/admin-panel-all-tickets.scss new file mode 100644 index 00000000..d09f84bc --- /dev/null +++ b/client/src/app/admin/panel/tickets/admin-panel-all-tickets.scss @@ -0,0 +1,6 @@ +.admin-panel-my-tickets { + &__search-box { + padding: 0 50px; + margin-bottom: 30px; + } +} \ No newline at end of file diff --git a/client/src/core-components/search-box.js b/client/src/core-components/search-box.js new file mode 100644 index 00000000..13489a75 --- /dev/null +++ b/client/src/core-components/search-box.js @@ -0,0 +1,41 @@ +import React from 'react'; + +import Input from 'core-components/input'; +import Icon from 'core-components/icon'; +import keyCode from 'keycode'; + +class SearchBox extends React.Component { + + static propTypes = { + onSearch: React.PropTypes.func + }; + + state = { + value: '' + }; + + render() { + return ( +
+ + + + +
+ ); + } + + onChange(event) { + this.setState({ + value: event.target.value + }); + } + + onKeyDown(event) { + if(keyCode(event) === 'enter' && this.props.onSearch) { + this.props.onSearch(this.state.value); + } + } +} + +export default SearchBox; \ No newline at end of file diff --git a/client/src/core-components/search-box.scss b/client/src/core-components/search-box.scss new file mode 100644 index 00000000..3a09ac49 --- /dev/null +++ b/client/src/core-components/search-box.scss @@ -0,0 +1,21 @@ +@import "../scss/vars"; + +.search-box { + position: relative; + color: $dark-grey; + + &__text { + width: 100%; + font-size: $font-size--lg; + + .input__text { + padding-left: 50px; + } + } + + &__icon { + position: absolute; + top: 15px; + left: 20px; + } +} \ No newline at end of file diff --git a/client/src/core-components/table.js b/client/src/core-components/table.js index b145e1c1..58494e05 100644 --- a/client/src/core-components/table.js +++ b/client/src/core-components/table.js @@ -13,9 +13,12 @@ class Table extends React.Component { className: React.PropTypes.string })), rows: React.PropTypes.arrayOf(React.PropTypes.object), - pageSize: React.PropTypes.number, loading: React.PropTypes.bool, type: React.PropTypes.oneOf(['default']), + page: React.PropTypes.number, + pages: React.PropTypes.number, + pageSize: React.PropTypes.number, + onPageChange: React.PropTypes.func, comp: React.PropTypes.func }; @@ -41,7 +44,7 @@ class Table extends React.Component {
{(this.props.loading) ? this.renderLoading() : null} - {(this.props.pageSize && this.props.rows.length > this.props.pageSize) ? this.renderNavigation() : null} + {this.renderPagination()}
); } @@ -59,8 +62,8 @@ class Table extends React.Component { renderRow(row, index) { const headersKeys = this.props.headers.map(header => header.key); - const minIndex = this.props.pageSize * (this.state.page - 1); - const maxIndex = this.props.pageSize * this.state.page; + const minIndex = this.props.pageSize * ((this.props.page) ? 0 : this.state.page - 1); + const maxIndex = this.props.pageSize * ((this.props.page) ? 1 : this.state.page); const shouldRenderRow = !this.props.pageSize || (index >= minIndex && index < maxIndex); return (shouldRenderRow) ? ( @@ -81,12 +84,15 @@ class Table extends React.Component { ); } + renderPagination() { + return (this.props.pages || (this.props.pageSize && this.props.rows.length > this.props.pageSize)) ? this.renderNavigation() : null + } + renderNavigation() { - const pages = Math.ceil(this.props.rows.length / this.props.pageSize) + 1; - const items = _.range(1, pages).map((index) => {return {content: index};}); + const items = _.range(1, this.getPages()).map((index) => {return {content: index};}); return ( - + ); } @@ -102,6 +108,10 @@ class Table extends React.Component { this.setState({ page: index + 1 }); + + if(this.props.onPageChange) { + this.props.onPageChange({target: {value: index + 1}}); + } } getRowClass(row) { @@ -114,11 +124,19 @@ class Table extends React.Component { } getRows() { - let v = _.clone(this.props.rows); - v.sort(this.props.comp); - return v; + let sortedRows = _.clone(this.props.rows); + sortedRows.sort(this.props.comp); + + return sortedRows; } + getPages() { + return (this.props.pages !== undefined) ? this.props.pages + 1 : Math.ceil(this.props.rows.length / this.props.pageSize) + 1; + } + + getPageNumber() { + return (this.props.page !== undefined) ? this.props.page: this.state.page; + } } export default Table; \ No newline at end of file diff --git a/client/src/core-components/table.scss b/client/src/core-components/table.scss index 54a73615..fe29d346 100644 --- a/client/src/core-components/table.scss +++ b/client/src/core-components/table.scss @@ -50,7 +50,7 @@ } &__loading-wrapper { - min-height: 200px; + min-height: 380px; position: relative; background-color: $grey; } diff --git a/client/src/data/fixtures/staff-fixtures.js b/client/src/data/fixtures/staff-fixtures.js index 4d1686cd..0f0536b8 100644 --- a/client/src/data/fixtures/staff-fixtures.js +++ b/client/src/data/fixtures/staff-fixtures.js @@ -1,3 +1,5 @@ +import _ from 'lodash'; + module.exports = [ { path: '/staff/get', @@ -498,90 +500,81 @@ module.exports = [ }, { path: '/staff/get-all-tickets', + time: 1000, + response: function () { + return { + status: 'success', + data: { + tickets: _.range(0, 10).map(() => { + return { + ticketNumber: '445441', + title: 'Inscription ACM ICPC', + content: 'I had a problem with the installation of the php server', + department: { + id: 1, + name: 'Sales Support' + }, + 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: [] + }; + }), + pages: 4 + } + } + } + }, + { + path: '/staff/search-tickets', time: 300, response: function () { return { status: 'success', - data: [ - { - ticketNumber: '445441', - title: 'Inscription ACM ICPC', - content: 'I had a problem with the installation of the php server', - department: { - id: 1, - name: 'Sales Support' - }, - 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: [] - }, - { - ticketNumber: '445441', - title: 'Inscription ACM ICPC', - content: 'I had a problem with the installation of the php server', - department: { - id: 1, - name: 'Sales Support' - }, - 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: [] - }, - { - ticketNumber: '445441', - title: 'Code jam is awesome', - content: 'I had a problem with the installation of the php server', - department: { - id: 2, - name: 'Technical Issues' - }, - 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: [] - } - ] + data: { + tickets: _.range(0, 10).map(() => { + return { + ticketNumber: '445441', + title: 'Inscription ACM ICPC', + content: 'I had a problem with the installation of the php server', + department: { + id: 1, + name: 'Sales Support' + }, + 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: [] + }; + }), + pages: 2 + } } } } diff --git a/client/src/reducers/admin-data-reducer.js b/client/src/reducers/admin-data-reducer.js index 6ed135ee..d3d753dc 100644 --- a/client/src/reducers/admin-data-reducer.js +++ b/client/src/reducers/admin-data-reducer.js @@ -77,7 +77,8 @@ class AdminDataReducer extends Reducer { onAllTicketsRetrieved(state, payload) { return _.extend({}, state, { - allTickets: payload.data, + allTickets: payload.data.tickets, + allTicketsPages: payload.data.pages, allTicketsLoaded: true }) }