Ivan - Add all tickets and new tickets[skip ci]

This commit is contained in:
ivan 2016-10-28 04:01:03 -03:00
parent 343b455905
commit 1966697a21
10 changed files with 366 additions and 67 deletions

View File

@ -20,5 +20,25 @@ export default {
data: {} 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: {}
})
};
} }
}; };

View File

@ -1,16 +1,19 @@
import React from 'react'; import React from 'react';
import _ from 'lodash';
import i18n from 'lib-app/i18n'; 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 Table from 'core-components/table';
import Button from 'core-components/button'; import Button from 'core-components/button';
import Tooltip from 'core-components/tooltip'; import Tooltip from 'core-components/tooltip';
import TicketInfo from 'app-components/ticket-info'; import DropDown from 'core-components/drop-down';
import DateTransformer from 'lib-core/date-transformer';
class TicketList extends React.Component { class TicketList extends React.Component {
static propTypes = { static propTypes = {
departments: React.PropTypes.array,
loading: React.PropTypes.bool, loading: React.PropTypes.bool,
ticketPath: React.PropTypes.string, ticketPath: React.PropTypes.string,
tickets: React.PropTypes.arrayOf(React.PropTypes.object), tickets: React.PropTypes.arrayOf(React.PropTypes.object),
@ -26,14 +29,51 @@ class TicketList extends React.Component {
type: 'primary' type: 'primary'
}; };
state = {
selectedDepartment: 0
};
render() { render() {
return ( return (
<div className="ticket-list"> <div className="ticket-list">
{(this.props.type === 'secondary') ? this.renderDepartmentsDropDown() : null}
<Table loading={this.props.loading} headers={this.getTableHeaders()} rows={this.getTableRows()} pageSize={10} comp={this.compareFunction} /> <Table loading={this.props.loading} headers={this.getTableHeaders()} rows={this.getTableRows()} pageSize={10} comp={this.compareFunction} />
</div> </div>
); );
} }
renderDepartmentsDropDown() {
return (
<div className="ticket-list__department-selector">
<DropDown {...this.getDepartmentDropdownProps()} />
</div>
);
}
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() { getTableHeaders() {
if (this.props.type == 'primary' ) { if (this.props.type == 'primary' ) {
return [ return [
@ -95,7 +135,13 @@ class TicketList extends React.Component {
} }
getTableRows() { 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) { gerTicketTableObject(ticket) {

View File

@ -0,0 +1,5 @@
.ticket-list {
&__department-selector {
margin-bottom: 25px;
}
}

View File

@ -1,14 +1,47 @@
import React from 'react'; 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 { class AdminPanelAllTickets extends React.Component {
static defaultProps = {
departments: [],
tickets: []
};
componentDidMount() {
this.props.dispatch(AdminDataAction.retrieveAllTickets());
}
render() { render() {
return ( return (
<div> <div className="admin-panel-my-tickets">
/admin/panel/tickets/all-tickets <Header title={i18n('ALL_TICKETS')} description={i18n('ALL_TICKETS_DESCRIPTION')} />
<TicketList {...this.getProps()}/>
</div> </div>
); );
} }
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; export default connect((store) => {
return {
departments: store.session.userDepartments,
tickets: store.adminData.newTickets,
loading: !store.adminData.newTicketsLoaded
};
})(AdminPanelAllTickets);

View File

@ -1,12 +1,10 @@
import React from 'react'; import React from 'react';
import _ from 'lodash';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
import i18n from 'lib-app/i18n'; import i18n from 'lib-app/i18n';
import AdminDataAction from 'actions/admin-data-actions'; import AdminDataAction from 'actions/admin-data-actions';
import Header from 'core-components/header'; import Header from 'core-components/header';
import DropDown from 'core-components/drop-down';
import TicketList from 'app-components/ticket-list'; import TicketList from 'app-components/ticket-list';
class AdminPanelMyTickets extends React.Component { class AdminPanelMyTickets extends React.Component {
@ -16,10 +14,6 @@ class AdminPanelMyTickets extends React.Component {
tickets: [] tickets: []
}; };
state = {
selectedDepartment: 0
};
componentDidMount() { componentDidMount() {
this.props.dispatch(AdminDataAction.retrieveMyTickets()); this.props.dispatch(AdminDataAction.retrieveMyTickets());
} }
@ -28,9 +22,6 @@ class AdminPanelMyTickets extends React.Component {
return ( return (
<div className="admin-panel-my-tickets"> <div className="admin-panel-my-tickets">
<Header title={i18n('MY_TICKETS')} description={i18n('MY_TICKETS_DESCRIPTION')} /> <Header title={i18n('MY_TICKETS')} description={i18n('MY_TICKETS_DESCRIPTION')} />
<div className="admin-panel-my-tickets__department-select">
<DropDown {...this.getDropdownProps()} />
</div>
<TicketList {...this.getProps()}/> <TicketList {...this.getProps()}/>
</div> </div>
); );
@ -38,50 +29,13 @@ class AdminPanelMyTickets extends React.Component {
getProps() { getProps() {
return { return {
tickets: this.getTickets(), departments: this.props.departments,
tickets: this.props.tickets,
type: 'secondary', type: 'secondary',
loading: this.props.loading, loading: this.props.loading,
ticketPath: '/admin/panel/tickets/view-ticket/' 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) => { export default connect((store) => {

View File

@ -1,6 +0,0 @@
.admin-panel-my-tickets {
&__department-select {
margin-bottom: 25px;
}
}

View File

@ -1,14 +1,47 @@
import React from 'react'; 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 { class AdminPanelNewTickets extends React.Component {
static defaultProps = {
departments: [],
tickets: []
};
componentDidMount() {
this.props.dispatch(AdminDataAction.retrieveNewTickets());
}
render() { render() {
return ( return (
<div> <div className="admin-panel-my-tickets">
/admin/panel/tickets/new-tickets <Header title={i18n('NEW_TICKETS')} description={i18n('NEW_TICKETS_DESCRIPTION')} />
<TicketList {...this.getProps()}/>
</div> </div>
); );
} }
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; export default connect((store) => {
return {
departments: store.session.userDepartments,
tickets: store.adminData.newTickets,
loading: !store.adminData.newTicketsLoaded
};
})(AdminPanelNewTickets);

View File

@ -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: []
}
]
}
}
} }
]; ];

View File

@ -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.', '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', 'CUSTOM_RESPONSES_DESCRIPTION': 'Custom responses are automated responses for common problems',
'MY_TICKETS_DESCRIPTION': 'Here you can view the tickets you are responsible for.', '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', 'TICKET_VIEW_DESCRIPTION': 'This ticket has been sent by a customer. Here you can respond or assign the ticket',
//ERRORS //ERRORS

View File

@ -7,10 +7,14 @@ class AdminDataReducer extends Reducer {
getInitialState() { getInitialState() {
return { return {
customResponses: [],
customResponsesLoaded: false,
myTickets: [], myTickets: [],
myTicketsLoaded: false, myTicketsLoaded: false,
customResponses: [], newTickets: [],
customResponsesLoaded: false newTicketsLoaded: false,
allTickets: [],
allTicketsLoaded: false
}; };
} }
@ -19,7 +23,11 @@ class AdminDataReducer extends Reducer {
'CUSTOM_RESPONSES_FULFILLED': this.onCustomResponses, 'CUSTOM_RESPONSES_FULFILLED': this.onCustomResponses,
'SESSION_CHECKED': this.onSessionChecked, 'SESSION_CHECKED': this.onSessionChecked,
'MY_TICKETS_FULFILLED': this.onMyTicketsRetrieved, '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 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(); export default AdminDataReducer.getInstance();