Implemented functionality to allow staff members invite other staffs.
This commit is contained in:
parent
18be18ebf8
commit
93ade9cf0f
|
@ -11,7 +11,7 @@ import SessionStore from 'lib-app/session-store';
|
|||
import PeopleList from 'app-components/people-list';
|
||||
import ModalContainer from 'app-components/modal-container';
|
||||
|
||||
import AddStaffModal from 'app/admin/panel/staff/add-staff-modal';
|
||||
import InviteStaffModal from 'app/admin/panel/staff/invite-staff-modal';
|
||||
|
||||
import Header from 'core-components/header';
|
||||
import DropDown from 'core-components/drop-down';
|
||||
|
@ -47,8 +47,8 @@ class AdminPanelStaffMembers extends React.Component {
|
|||
<Header title={i18n('STAFF_MEMBERS')} description={i18n('STAFF_MEMBERS_DESCRIPTION')} />
|
||||
<div className="admin-panel-staff-members__wrapper">
|
||||
<DepartmentDropdown {...this.getDepartmentDropdownProps()} className="admin-panel-staff-members__dropdown" />
|
||||
<Button onClick={this.onAddNewStaff.bind(this)} size="medium" type="secondary" className="admin-panel-staff-members__button">
|
||||
<Icon name="user-plus" className=""/> {i18n('ADD_NEW_STAFF')}
|
||||
<Button onClick={this.onInviteStaff.bind(this)} size="medium" type="secondary" className="admin-panel-staff-members__button">
|
||||
<Icon name="user-plus" className=""/> {i18n('INVITE_STAFF')}
|
||||
</Button>
|
||||
</div>
|
||||
{(this.props.loading) ? <Loading backgrounded /> : <PeopleList list={this.getStaffList()} page={this.state.page} onPageSelect={(index) => this.setState({page: index+1})} />}
|
||||
|
@ -56,8 +56,8 @@ class AdminPanelStaffMembers extends React.Component {
|
|||
);
|
||||
}
|
||||
|
||||
onAddNewStaff() {
|
||||
ModalContainer.openModal(<AddStaffModal onSuccess={this.retrieveStaffMembers.bind(this)} />);
|
||||
onInviteStaff() {
|
||||
ModalContainer.openModal(<InviteStaffModal onSuccess={this.retrieveStaffMembers.bind(this)} />);
|
||||
}
|
||||
|
||||
getDepartmentDropdownProps() {
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
|
||||
import i18n from 'lib-app/i18n';
|
||||
import API from 'lib-app/api-call';
|
||||
import SessionStore from 'lib-app/session-store';
|
||||
|
||||
import Header from 'core-components/header'
|
||||
import Form from 'core-components/form';
|
||||
import FormField from 'core-components/form-field';
|
||||
import SubmitButton from 'core-components/submit-button';
|
||||
import Button from 'core-components/button';
|
||||
import Icon from 'core-components/icon';
|
||||
|
||||
class InviteStaffModal extends React.Component {
|
||||
|
||||
static contextTypes = {
|
||||
closeModal: React.PropTypes.func
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
onSuccess: React.PropTypes.func
|
||||
};
|
||||
|
||||
state = {
|
||||
loading: false,
|
||||
errors: {},
|
||||
error: null
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="invite-staff-modal">
|
||||
<Header title={i18n('INVITE_STAFF')} description={i18n('INVITE_STAFF_DESCRIPTION')} />
|
||||
<Form onSubmit={this.onSubmit.bind(this)} errors={this.getErrors()} onValidateErrors={errors => this.setState({errors})} loading={this.state.loading}>
|
||||
<div className="row">
|
||||
<div className="col-md-7">
|
||||
<FormField name="name" label={i18n('NAME')} fieldProps={{size: 'large'}} validation="NAME" required />
|
||||
<FormField name="email" label={i18n('EMAIL')} fieldProps={{size: 'large'}} validation="EMAIL" required />
|
||||
<div className="invite-staff-modal__level-selector">
|
||||
<FormField name="level" label={i18n('LEVEL')} field="select" fieldProps={{
|
||||
items: [{content: i18n('LEVEL_1')}, {content: i18n('LEVEL_2')}, {content: i18n('LEVEL_3')}],
|
||||
size: 'large'
|
||||
}} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-5">
|
||||
<div className="invite-staff-modal__departments">
|
||||
<div className="invite-staff-modal__departments-title">{i18n('Departments')}</div>
|
||||
<FormField name="departments" field="checkbox-group" fieldProps={{items: this.getDepartments()}} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<SubmitButton type="secondary" size="small">
|
||||
{i18n('SAVE')}
|
||||
</SubmitButton>
|
||||
<Button type="clean" onClick={this.onCancelClick.bind(this)}>
|
||||
{i18n('CANCEL')}
|
||||
</Button>
|
||||
</Form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
getDepartments() {
|
||||
return SessionStore.getDepartments().map(department => {
|
||||
if(department.private*1){
|
||||
return <span>{department.name} <Icon name='user-secret'/> </span>
|
||||
} else {
|
||||
return department.name;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onSubmit(form) {
|
||||
let departments = _.filter(SessionStore.getDepartments(), (department, index) => {
|
||||
return _.includes(form.departments, index);
|
||||
}).map(department => department.id);
|
||||
|
||||
this.setState({loading: true});
|
||||
|
||||
API.call({
|
||||
path: '/staff/invite',
|
||||
data: {
|
||||
name: form.name,
|
||||
email: form.email,
|
||||
level: form.level + 1,
|
||||
departments: JSON.stringify(departments)
|
||||
}
|
||||
}).then(() => {
|
||||
this.context.closeModal();
|
||||
|
||||
if(this.props.onSuccess) {
|
||||
this.props.onSuccess();
|
||||
}
|
||||
}).catch((result) => {
|
||||
this.setState({
|
||||
loading: false,
|
||||
error: result.message
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
onCancelClick(event) {
|
||||
event.preventDefault();
|
||||
this.context.closeModal();
|
||||
}
|
||||
|
||||
getErrors() {
|
||||
let errors = _.extend({}, this.state.errors);
|
||||
|
||||
if (this.state.error === 'ALREADY_A_STAFF') {
|
||||
errors.email = i18n('EMAIL_EXISTS');
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
}
|
||||
|
||||
export default InviteStaffModal;
|
|
@ -0,0 +1,23 @@
|
|||
@import "../../../../scss/vars";
|
||||
|
||||
.invite-staff-modal {
|
||||
width: 700px;
|
||||
|
||||
&__level-selector {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&__departments {
|
||||
@include scrollbars();
|
||||
|
||||
border: 1px solid $grey;
|
||||
padding: 20px;
|
||||
height: 320px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
&__departments-title {
|
||||
font-size: $font-size--md;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
|
@ -195,6 +195,7 @@ export default {
|
|||
'HIMSELF': 'himself',
|
||||
'ADD_USER': 'Add user',
|
||||
'INVITE_USER': 'Invite user',
|
||||
'INVITE_STAFF': 'Invite staff',
|
||||
'UPLOAD_FILE': 'Upload file',
|
||||
'PRIVATE': 'Private',
|
||||
'ENABLE_USER': 'Enable User',
|
||||
|
@ -340,6 +341,7 @@ export default {
|
|||
'NEW_CUSTOM_FIELD_DESCRIPTION': 'Here you can create a custom field for an user, it can be a blank text box or a fixed set of options.',
|
||||
'CUSTOM_FIELDS_DESCRIPTION': 'Custom fields are defined additional fields the users are able to fill to provide more information about them.',
|
||||
'INVITE_USER_VIEW_DESCRIPTION': 'Here you can invite an user to join our support system, he will just need to provide his password to create a new user.',
|
||||
'INVITE_STAFF_DESCRIPTION': 'Here you can invite staff members to your teams.',
|
||||
|
||||
//ERRORS
|
||||
'EMAIL_OR_PASSWORD': 'Email or password invalid',
|
||||
|
|
|
@ -9,7 +9,8 @@ $systemControllerGroup->addController(new GetTicketStaffController);
|
|||
$systemControllerGroup->addController(new GetNewTicketsStaffController);
|
||||
$systemControllerGroup->addController(new GetAllTicketsStaffController);
|
||||
$systemControllerGroup->addController(new SearchTicketStaffController);
|
||||
$systemControllerGroup->addController(new AddStaffController);
|
||||
// $systemControllerGroup->addController(new AddStaffController);
|
||||
$systemControllerGroup->addController(new InviteStaffController);
|
||||
$systemControllerGroup->addController(new GetAllStaffController);
|
||||
$systemControllerGroup->addController(new DeleteStaffController);
|
||||
$systemControllerGroup->addController(new EditStaffController);
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
<?php
|
||||
use Respect\Validation\Validator as DataValidator;
|
||||
DataValidator::with('CustomValidations', true);
|
||||
|
||||
/**
|
||||
* @api {post} /staff/invite Invite staff
|
||||
* @apiVersion 4.5.0
|
||||
*
|
||||
* @apiName Invite staff
|
||||
*
|
||||
* @apiGroup Staff
|
||||
*
|
||||
* @apiDescription This path invites a new staff member.
|
||||
*
|
||||
* @apiPermission staff3
|
||||
*
|
||||
* @apiParam {String} name The name of the new staff member.
|
||||
* @apiParam {String} email The email of the new staff member.
|
||||
* @apiParam {Number} level The level of the new staff member.
|
||||
* @apiParam {String} profilePic The profile pic of the new staff member.
|
||||
* @apiParam {Number[]} departments The departments that will have assigned the new staff member.
|
||||
*
|
||||
* @apiUse NO_PERMISSION
|
||||
* @apiUse INVALID_NAME
|
||||
* @apiUse INVALID_EMAIL
|
||||
* @apiUse INVALID_PASSWORD
|
||||
* @apiUse INVALID_LEVEL
|
||||
* @apiUse ALREADY_A_STAFF
|
||||
*
|
||||
* @apiSuccess {Object} data Staff info object
|
||||
* @apiSuccess {Number} data.id Staff id
|
||||
*
|
||||
*/
|
||||
|
||||
class InviteStaffController extends Controller {
|
||||
const PATH = '/invite';
|
||||
const METHOD = 'POST';
|
||||
|
||||
private $name;
|
||||
private $email;
|
||||
private $profilePic;
|
||||
private $level;
|
||||
private $departments;
|
||||
|
||||
public function validations() {
|
||||
return [
|
||||
'permission' => 'staff_3',
|
||||
'requestData' => [
|
||||
'name' => [
|
||||
'validation' => DataValidator::length(2, 55),
|
||||
'error' => ERRORS::INVALID_NAME
|
||||
],
|
||||
'email' => [
|
||||
'validation' => DataValidator::email(),
|
||||
'error' => ERRORS::INVALID_EMAIL
|
||||
],
|
||||
'level' => [
|
||||
'validation' => DataValidator::between(1, 3, true),
|
||||
'error' => ERRORS::INVALID_LEVEL
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function handler() {
|
||||
$this->storeRequestData();
|
||||
|
||||
$staffRow = Staff::getDataStore($this->email, 'email');
|
||||
|
||||
if(!$staffRow->isNull()) throw new RequestException(ERRORS::ALREADY_A_STAFF);
|
||||
|
||||
if(!MailSender::getInstance()->isConnected()) throw new RequestException(ERRORS::MAIL_SENDER_NOT_CONNECTED);
|
||||
|
||||
$staff = new Staff();
|
||||
$staff->setProperties([
|
||||
'name'=> $this->name,
|
||||
'email' => $this->email,
|
||||
'password'=> Hashing::hashPassword(Hashing::generateRandomToken()),
|
||||
'profilePic' => $this->profilePic,
|
||||
'level' => $this->level,
|
||||
'sharedDepartmentList' => $this->getDepartmentList()
|
||||
]);
|
||||
|
||||
$this->addOwner();
|
||||
|
||||
$this->token = Hashing::generateRandomToken();
|
||||
|
||||
$recoverPassword = new RecoverPassword();
|
||||
$recoverPassword->setProperties(array(
|
||||
'email' => $this->email,
|
||||
'token' => $this->token,
|
||||
'staff' => true
|
||||
));
|
||||
$recoverPassword->store();
|
||||
|
||||
$this->sendInvitationMail();
|
||||
|
||||
Response::respondSuccess([
|
||||
'id' => $staff->store()
|
||||
]);
|
||||
|
||||
// TODO: Log::createLog('ADD_STAFF', $this->name);
|
||||
}
|
||||
|
||||
public function storeRequestData() {
|
||||
$this->name = Controller::request('name');
|
||||
$this->email = Controller::request('email');
|
||||
$this->profilePic = Controller::request('profilePic');
|
||||
$this->level = Controller::request('level');
|
||||
$this->departments = Controller::request('departments');
|
||||
}
|
||||
|
||||
public function getDepartmentList() {
|
||||
$listDepartments = new DataStoreList();
|
||||
$departmentIds = json_decode($this->departments);
|
||||
|
||||
foreach($departmentIds as $id) {
|
||||
$department = Department::getDataStore($id);
|
||||
$listDepartments->add($department);
|
||||
}
|
||||
|
||||
return $listDepartments;
|
||||
}
|
||||
|
||||
public function addOwner() {
|
||||
$departmentIds = json_decode($this->departments);
|
||||
|
||||
foreach($departmentIds as $id) {
|
||||
$departmentRow = Department::getDataStore($id);
|
||||
$departmentRow->owners++;
|
||||
$departmentRow->store();
|
||||
}
|
||||
}
|
||||
|
||||
public function sendInvitationMail() {
|
||||
$mailSender = MailSender::getInstance();
|
||||
|
||||
$mailSender->setTemplate(MailTemplate::USER_INVITE, [
|
||||
'to' => $this->email,
|
||||
'name' => $this->name,
|
||||
'url' => Setting::getSetting('url')->getValue(),
|
||||
'token' => $this->token
|
||||
]);
|
||||
|
||||
$mailSender->send();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue