diff --git a/client/src/actions/admin-data-actions.js b/client/src/actions/admin-data-actions.js
index f4daa5ff..94c9cde5 100644
--- a/client/src/actions/admin-data-actions.js
+++ b/client/src/actions/admin-data-actions.js
@@ -1,7 +1,7 @@
import API from 'lib-app/api-call';
export default {
-
+
retrieveCustomResponses() {
return {
type: 'CUSTOM_RESPONSES',
@@ -42,6 +42,16 @@ export default {
};
},
+ retrieveStaffMembers() {
+ return {
+ type: 'STAFF_MEMBERS',
+ payload: API.call({
+ path: '/staff/get-all',
+ data: {}
+ })
+ };
+ },
+
searchTickets(query, page = 1) {
return {
type: 'ALL_TICKETS',
@@ -51,4 +61,4 @@ export default {
})
};
}
-};
\ No newline at end of file
+};
diff --git a/client/src/app-components/ticket-viewer.js b/client/src/app-components/ticket-viewer.js
index 10d62c24..06a92c37 100644
--- a/client/src/app-components/ticket-viewer.js
+++ b/client/src/app-components/ticket-viewer.js
@@ -2,6 +2,8 @@ import React from 'react';
import _ from 'lodash';
import {connect} from 'react-redux';
+import AdminDataActions from 'actions/admin-data-actions';
+
import i18n from 'lib-app/i18n';
import API from 'lib-app/api-call';
import SessionStore from 'lib-app/session-store';
@@ -24,7 +26,9 @@ class TicketViewer extends React.Component {
onChange: React.PropTypes.func,
editable: React.PropTypes.bool,
customResponses: React.PropTypes.array,
- assignmentAllowed: React.PropTypes.bool
+ assignmentAllowed: React.PropTypes.bool,
+ staffMembers: React.PropTypes.array,
+ staffMembersLoaded: React.PropTypes.bool,
};
static defaultProps = {
@@ -42,6 +46,12 @@ class TicketViewer extends React.Component {
commentEdited: false
};
+ componentDidMount() {
+ if(!this.props.staffMembersLoaded && this.props.editable) {
+ this.props.dispatch(AdminDataActions.retrieveStaffMembers());
+ }
+ }
+
render() {
const ticket = this.props.ticket;
@@ -84,7 +94,7 @@ class TicketViewer extends React.Component {
{i18n('DEPARTMENT')}
-
{i18n('AUTHOR')}
+
{i18n('AUTHOR')}
{i18n('DATE')}
@@ -165,11 +175,7 @@ class TicketViewer extends React.Component {
let {ticket, userId} = this.props;
if (_.isEmpty(ticket.owner) || ticket.owner.id == userId) {
- ownerNode = (
-
- );
+ ownerNode = this.renderAssignStaffList();
} else {
ownerNode = (this.props.ticket.owner) ? this.props.ticket.owner.name : i18n('NONE')
}
@@ -193,6 +199,18 @@ class TicketViewer extends React.Component {
return ownerNode;
}
+ renderAssignStaffList() {
+ const items = this.getStaffAssignmentItems();
+ const ownerId = this.props.ticket.owner && this.props.ticket.owner.id;
+ return (
+
+ );
+ }
+
renderTicketEvent(options, index) {
return (
@@ -265,6 +283,23 @@ class TicketViewer extends React.Component {
};
}
+ getStaffAssignmentItems() {
+ const {staffMembers, userId} = this.props;
+ let staffAssignmentItems = [
+ {content: 'None', id: 0},
+ {content: 'Assign to me', id: userId}
+ ];
+
+ staffAssignmentItems = staffAssignmentItems.concat(
+ _.map(
+ _.filter(staffMembers, ({id}) => (id != userId)),
+ ({id, name}) => ({content: name, id})
+ )
+ );
+
+ return staffAssignmentItems;
+ }
+
onDepartmentDropdownChanged(event) {
AreYouSure.openModal(null, this.changeDepartment.bind(this, event.index));
}
@@ -273,12 +308,17 @@ class TicketViewer extends React.Component {
AreYouSure.openModal(null, this.changePriority.bind(this, event.index));
}
- onAssignClick() {
+ onAssignmentChange(event) {
+ AreYouSure.openModal(null, this.assingTo.bind(this, event.index));
+ }
+
+ assingTo(index) {
+ const id = this.getStaffAssignmentItems()[index].id;
+ const {ticketNumber} = this.props.ticket;
+
API.call({
- path: (this.props.ticket.owner) ? '/staff/un-assign-ticket' : '/staff/assign-ticket',
- data: {
- ticketNumber: this.props.ticket.ticketNumber
- }
+ path: (index == 0) ? '/staff/un-assign-ticket' : '/staff/assign-ticket',
+ data: { ticketNumber, staffId: id }
}).then(this.onTicketModification.bind(this));
}
@@ -387,6 +427,8 @@ class TicketViewer extends React.Component {
export default connect((store) => {
return {
userId: store.session.userId,
+ staffMembers: store.adminData.staffMembers,
+ staffMembersLoaded: store.adminData.staffMembersLoaded,
allowAttachments: store.config['allow-attachments'],
userSystemEnabled: store.config['user-system-enabled']
};
diff --git a/client/src/app/admin/panel/staff/admin-panel-staff-members.js b/client/src/app/admin/panel/staff/admin-panel-staff-members.js
index 4717d2eb..97d5726d 100644
--- a/client/src/app/admin/panel/staff/admin-panel-staff-members.js
+++ b/client/src/app/admin/panel/staff/admin-panel-staff-members.js
@@ -1,6 +1,9 @@
import React from 'react';
import {Link} from 'react-router';
import _ from 'lodash';
+import {connect} from 'react-redux';
+
+import AdminDataActions from 'actions/admin-data-actions';
import i18n from 'lib-app/i18n';
import API from 'lib-app/api-call';
@@ -18,15 +21,23 @@ import Loading from 'core-components/loading';
class AdminPanelStaffMembers extends React.Component {
- state = {
- selectedDepartment: 0,
+ static propTypes = {
+ staffList: React.PropTypes.array,
+ loading: React.PropTypes.boolean,
+ }
+
+ static defaultProps = {
staffList: [],
loading: true,
+ };
+
+ state = {
+ selectedDepartment: 0,
page: 1
};
componentDidMount() {
- this.retrieveStaffMembers();
+ this.props.dispatch(AdminDataActions.retrieveStaffMembers());
}
render() {
@@ -39,7 +50,7 @@ class AdminPanelStaffMembers extends React.Component {
{i18n('ADD_NEW_STAFF')}
- {(this.state.loading) ?
:
this.setState({page: index+1})} />}
+ {(this.props.loading) ? : this.setState({page: index+1})} />}
);
}
@@ -66,9 +77,9 @@ class AdminPanelStaffMembers extends React.Component {
let staffList;
if(!this.state.selectedDepartment) {
- staffList = this.state.staffList;
+ staffList = this.props.staffList;
} else {
- staffList = _.filter(this.state.staffList, (staff) => {
+ staffList = _.filter(this.props.staffList, (staff) => {
return _.findIndex(staff.departments, {id: this.state.selectedDepartment}) !== -1;
});
}
@@ -96,22 +107,12 @@ class AdminPanelStaffMembers extends React.Component {
return departments;
}
-
- retrieveStaffMembers() {
- API.call({
- path: '/staff/get-all',
- data: {}
- }).then(this.onStaffRetrieved.bind(this));
- }
-
- onStaffRetrieved(result) {
- if(result.status == 'success'){
- this.setState({
- loading: false,
- staffList: result.data
- });
- }
- }
}
-export default AdminPanelStaffMembers;
\ No newline at end of file
+export default connect((store) => {
+ return {
+ staffList: store.adminData.staffMembers,
+ loading: !store.adminData.staffMembersLoaded,
+ error: store.adminData.staffMembersError
+ };
+})(AdminPanelStaffMembers);
diff --git a/client/src/data/fixtures/ticket-fixtures.js b/client/src/data/fixtures/ticket-fixtures.js
index 75af3df7..1c456fea 100644
--- a/client/src/data/fixtures/ticket-fixtures.js
+++ b/client/src/data/fixtures/ticket-fixtures.js
@@ -99,7 +99,7 @@ module.exports = [
title: 'Lorem ipsum door',
content: 'I had a problem with the installation of the php server',
department: {
- id: 1,
+ id: '1',
name: 'Sales Support'
},
date: '201604151155',
@@ -110,12 +110,12 @@ module.exports = [
closed: false,
priority: 'medium',
author: {
- id: 3,
+ id: '3',
name: 'Haskell Curry',
email: 'haskell@lambda.com'
},
owner: {
- id: 1,
+ id: '12',
name: 'Steve Jobs'
},
events: [
diff --git a/client/src/reducers/admin-data-reducer.js b/client/src/reducers/admin-data-reducer.js
index e3de7207..5aa12b2d 100644
--- a/client/src/reducers/admin-data-reducer.js
+++ b/client/src/reducers/admin-data-reducer.js
@@ -9,6 +9,7 @@ class AdminDataReducer extends Reducer {
return {
customResponses: [],
customResponsesLoaded: false,
+
myTickets: [],
myTicketsLoaded: false,
myTicketsError: false,
@@ -19,7 +20,11 @@ class AdminDataReducer extends Reducer {
allTickets: [],
allTicketsLoaded: false,
- allTicketsError: false
+ allTicketsError: false,
+
+ staffMembers: [],
+ staffMembersLoaded: false,
+ staffMembersError: false,
};
}
@@ -37,7 +42,11 @@ class AdminDataReducer extends Reducer {
'ALL_TICKETS_FULFILLED': this.onAllTicketsRetrieved,
'ALL_TICKETS_REJECTED': this.onAllTicketsRejected,
- 'ALL_TICKETS_PENDING': this.onAllTicketsPending
+ 'ALL_TICKETS_PENDING': this.onAllTicketsPending,
+
+ 'STAFF_MEMBERS_FULFILLED': this.onStaffMembersRetrieved,
+ 'STAFF_MEMBERS_REJECTED': this.onStaffMembersRejected,
+ 'STAFF_MEMBERS_PENDING': this.onStaffMembersPending
};
}
@@ -102,7 +111,7 @@ class AdminDataReducer extends Reducer {
onAllTicketsRejected(state) {
return _.extend({}, state, {
- allTicketsError: false,
+ allTicketsError: true,
allTicketsLoaded: false
});
}
@@ -113,6 +122,27 @@ class AdminDataReducer extends Reducer {
allTicketsLoaded: false
});
}
+
+ onStaffMembersRetrieved(state, payload) {
+ return _.extend({}, state, {
+ staffMembers: payload.data,
+ staffMembersLoaded: true
+ });
+ }
+
+ onStaffMembersRejected(state) {
+ return _.extend({}, state, {
+ staffMembersError: true,
+ staffMembersLoaded: false
+ });
+ }
+
+ onStaffMembersPending(state) {
+ return _.extend({}, state, {
+ staffMembersError: false,
+ staffMembersLoaded: false
+ });
+ }
}
-export default AdminDataReducer.getInstance();
\ No newline at end of file
+export default AdminDataReducer.getInstance();
diff --git a/server/controllers/staff/get-all.php b/server/controllers/staff/get-all.php
index aadc83af..305da700 100755
--- a/server/controllers/staff/get-all.php
+++ b/server/controllers/staff/get-all.php
@@ -12,7 +12,7 @@ use Respect\Validation\Validator as DataValidator;
* @apiDescription This path retrieves information about all the staff member.
*
* @apiPermission staff3
- *
+ *
* @apiUse NO_PERMISSION
*
* @apiSuccess {[Staff](#api-Data_Structures-ObjectStaff)[]} data Array of staff members.
@@ -25,7 +25,7 @@ class GetAllStaffController extends Controller {
public function validations() {
return [
- 'permission' => 'staff_3',
+ 'permission' => 'staff_1',
'requestData' => []
];
}
@@ -58,6 +58,6 @@ class GetAllStaffController extends Controller {
}
Response::respondSuccess($staffArray);
-
+
}
-}
\ No newline at end of file
+}