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