Merge branch 'custom-tags' into guillermo-master
Conflicts: server/libs/validations/dataStoreId.php tests/init.rb
This commit is contained in:
commit
4627405242
|
@ -35,6 +35,7 @@ import AdminPanelNewTickets from 'app/admin/panel/tickets/admin-panel-new-ticket
|
|||
import AdminPanelAllTickets from 'app/admin/panel/tickets/admin-panel-all-tickets';
|
||||
import AdminPanelViewTicket from 'app/admin/panel/tickets/admin-panel-view-ticket';
|
||||
import AdminPanelCustomResponses from 'app/admin/panel/tickets/admin-panel-custom-responses';
|
||||
import AdminPanelCustomTags from 'app/admin/panel/tickets/admin-panel-custom-tags';
|
||||
|
||||
import AdminPanelListUsers from 'app/admin/panel/users/admin-panel-list-users';
|
||||
import AdminPanelViewUser from 'app/admin/panel/users/admin-panel-view-user';
|
||||
|
@ -114,6 +115,7 @@ export default (
|
|||
<Route path="all-tickets" component={AdminPanelAllTickets} />
|
||||
<Route path="custom-responses" component={AdminPanelCustomResponses} />
|
||||
<Route path="view-ticket/:ticketNumber" component={AdminPanelViewTicket} />
|
||||
<Route path="custom-tags" component={AdminPanelCustomTags} />
|
||||
</Route>
|
||||
|
||||
<Route path="users">
|
||||
|
|
|
@ -135,6 +135,11 @@ class AdminPanelMenu extends React.Component {
|
|||
name: i18n('CUSTOM_RESPONSES'),
|
||||
path: '/admin/panel/tickets/custom-responses',
|
||||
level: 2
|
||||
},
|
||||
{
|
||||
name: 'Customtags i18n',
|
||||
path: '/admin/panel/tickets/custom-tags',
|
||||
level: 1
|
||||
}
|
||||
])
|
||||
},
|
||||
|
|
|
@ -0,0 +1,261 @@
|
|||
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 AdminDataActions from 'actions/admin-data-actions';
|
||||
|
||||
import AreYouSure from 'app-components/are-you-sure';
|
||||
import LanguageSelector from 'app-components/language-selector';
|
||||
|
||||
import Icon from 'core-components/icon';
|
||||
import Button from 'core-components/button';
|
||||
import Header from 'core-components/header';
|
||||
import Listing from 'core-components/listing';
|
||||
import Loading from 'core-components/loading';
|
||||
import Form from 'core-components/form';
|
||||
import FormField from 'core-components/form-field';
|
||||
import SubmitButton from 'core-components/submit-button';
|
||||
import TextEditor from 'core-components/text-editor';
|
||||
import ModalContainer from 'app-components/modal-container';
|
||||
import ColorSelector from 'core-components/color-selector';
|
||||
class TagList extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
const list = this.props.tags.map((tag) => {
|
||||
<h1>{tag.name}</h1>;
|
||||
})
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
{list}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
class AdminPanelCustomTags extends React.Component {
|
||||
static defaultProps = {
|
||||
items: [],
|
||||
};
|
||||
|
||||
state = {
|
||||
formClicked: false,
|
||||
showForm: false,
|
||||
formLoading: false,
|
||||
selectedIndex: -1,
|
||||
errors: {},
|
||||
originalForm: {
|
||||
title: '',
|
||||
content: TextEditor.createEmpty(),
|
||||
language: this.props.language
|
||||
},
|
||||
form: {
|
||||
title: '',
|
||||
content: TextEditor.createEmpty(),
|
||||
language: this.props.language
|
||||
},
|
||||
tagList: {} //
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
if (!this.props.loaded) {
|
||||
this.retrieveCustomResponses();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="admin-panel-custom-tags">
|
||||
<Header title={i18n('CUSTOM_TAGS')} description={i18n('CUSTOM_TAGS_DESCRIPTION')} />
|
||||
{(this.props.loaded) ? this.renderContent() : this.renderLoading()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderContent() {
|
||||
return (
|
||||
<div className="row">
|
||||
<div className="col-md-3">
|
||||
<Button onClick={this.onCreateTag.bind(this)} type="secondary" ><Icon name="pencil"/>'NUEVO TAGi18n'</Button>
|
||||
<TagList tags={this.state.tagList}/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
onCreateTag() {
|
||||
ModalContainer.openModal(
|
||||
<div>
|
||||
<Header title={'new tags'} description={i18n('Here you can add a topic that works as a category for articles.')} />
|
||||
<Form values={this.state.values} onChange={this.onFormChange.bind(this)} onSubmit={this.onSubmitTag.bind(this)} loading={this.state.loading}>
|
||||
<FormField name="title" label={i18n('TITLE')} fieldProps={{size: 'large'}} validation="TITLE" required />
|
||||
<FormField name="color" className="topic-edit-modal__color" label={i18n('COLOR')} decorator={ColorSelector} />
|
||||
<FormField className="topic-edit-modal__private" label={i18n('PRIVATE')} name="private" field="checkbox"/>
|
||||
|
||||
<SubmitButton className="topic-edit-modal__save-button" type="secondary" size="small">
|
||||
{i18n('SAVE')}
|
||||
</SubmitButton>
|
||||
<Button className="topic-edit-modal__discard-button" onClick={this.onDiscardClick.bind(this)} size="small">
|
||||
{i18n('CANCEL')}
|
||||
</Button>
|
||||
</Form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
onSubmitTag() {
|
||||
API.call({
|
||||
path: '/ticket/add-tag',
|
||||
data: {
|
||||
name: form.title,
|
||||
color: form.content,
|
||||
}
|
||||
}).then(() => {
|
||||
this.context.closeModal();
|
||||
this.updateTagList();
|
||||
|
||||
if(this.props.onChange) {
|
||||
this.props.onChange();
|
||||
}
|
||||
}).catch(() => {
|
||||
this.setState({
|
||||
loading: false
|
||||
});
|
||||
});
|
||||
}
|
||||
onFormChange(form) {
|
||||
this.setState({
|
||||
values: form
|
||||
});
|
||||
}
|
||||
onDiscardClick(event) {
|
||||
event.preventDefault();
|
||||
this.context.closeModal();
|
||||
}
|
||||
renderLoading() {
|
||||
return (
|
||||
<div className="admin-panel-custom-responses__loading">
|
||||
<Loading backgrounded size="large"/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderOptionalButtons() {
|
||||
return (
|
||||
<div className="admin-panel-custom-responses__optional-buttons">
|
||||
<div className="admin-panel-custom-responses__discard-button">
|
||||
{this.isEdited() ? <Button onClick={this.onDiscardChangesClick.bind(this)}>{i18n('DISCARD_CHANGES')}</Button> : null}
|
||||
</div>
|
||||
<div className="admin-panel-custom-responses__delete-button">
|
||||
<Button onClick={this.onDeleteClick.bind(this)}>{i18n('DELETE')}</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
onItemChange(index) {
|
||||
if(this.isEdited()) {
|
||||
AreYouSure.openModal(i18n('WILL_LOSE_CHANGES'), this.updateForm.bind(this, index));
|
||||
} else {
|
||||
this.updateForm(index);
|
||||
}
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
this.setState({
|
||||
loading: true
|
||||
});
|
||||
|
||||
API.call({
|
||||
path: (this.props.addForm) ? '/article/add-topic' : '/article/edit-topic',
|
||||
data: {
|
||||
topicId: this.props.topicId,
|
||||
name: this.state.values['title'],
|
||||
icon: this.state.values['icon'],
|
||||
iconColor: this.state.values['color'],
|
||||
private: this.state.values['private']*1
|
||||
}
|
||||
}).then(() => {
|
||||
this.context.closeModal();
|
||||
|
||||
if(this.props.onChange) {
|
||||
this.props.onChange();
|
||||
}
|
||||
}).catch(() => {
|
||||
this.setState({
|
||||
loading: false
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
onDiscardChangesClick(event) {
|
||||
event.preventDefault();
|
||||
this.onItemChange(this.state.selectedIndex);
|
||||
}
|
||||
|
||||
onDeleteClick(event) {
|
||||
event.preventDefault();
|
||||
AreYouSure.openModal(i18n('WILL_DELETE_CUSTOM_RESPONSE'), this.deleteCustomResponse.bind(this));
|
||||
}
|
||||
|
||||
deleteCustomResponse() {
|
||||
API.call({
|
||||
path: '/ticket/delete-custom-response',
|
||||
data: {
|
||||
id: this.props.items[this.state.selectedIndex].id
|
||||
}
|
||||
}).then(() => {
|
||||
this.retrieveCustomResponses();
|
||||
this.onItemChange(-1);
|
||||
});
|
||||
}
|
||||
updateTagList() {
|
||||
API.call({
|
||||
path: '/ticket/get-tags'
|
||||
}).then(() => {
|
||||
this.setState({
|
||||
tagList: data
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
updateForm(index) {
|
||||
let form = _.clone(this.state.form);
|
||||
|
||||
form.title = (this.props.items[index] && this.props.items[index].name) || '';
|
||||
form.content = TextEditor.getEditorStateFromHTML((this.props.items[index] && this.props.items[index].content) || '');
|
||||
form.language = (this.props.items[index] && this.props.items[index].language) || this.props.language;
|
||||
|
||||
this.setState({
|
||||
formClicked: false,
|
||||
showForm: true,
|
||||
selectedIndex: index,
|
||||
formLoading: false,
|
||||
originalForm: form,
|
||||
form: form,
|
||||
errors: {}
|
||||
});
|
||||
}
|
||||
|
||||
retrieveCustomResponses() {
|
||||
this.props.dispatch(AdminDataActions.retrieveCustomResponses());
|
||||
}
|
||||
|
||||
isEdited() {
|
||||
return this.state.form.title && this.state.formClicked && (
|
||||
this.state.form.title != this.state.originalForm.title ||
|
||||
this.state.form.content != this.state.originalForm.content ||
|
||||
this.state.form.language != this.state.originalForm.language
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default connect((store) => {
|
||||
return {
|
||||
allowedLanguages: store.config.allowedLanguages,
|
||||
language: store.config.language,
|
||||
loaded: store.adminData.customResponsesLoaded,
|
||||
items: store.adminData.customResponses
|
||||
};
|
||||
})(AdminPanelCustomTags);
|
|
@ -0,0 +1,31 @@
|
|||
.admin-panel-custom-tags {
|
||||
&__loading {
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
&__item-flag {
|
||||
float: right;
|
||||
}
|
||||
|
||||
&__actions {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
&__save-button {
|
||||
display: inline-block;
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
&__optional-buttons {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
&__discard-button {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&__delete-button {
|
||||
display: inline-block;
|
||||
float: right;
|
||||
}
|
||||
}
|
|
@ -47,6 +47,7 @@ export default {
|
|||
'NEW_TICKETS': 'New Tickets',
|
||||
'ALL_TICKETS': 'All Tickets',
|
||||
'CUSTOM_RESPONSES': 'Custom Responses',
|
||||
'CUSTOM_TAGS': 'Custom Tags',
|
||||
'LIST_USERS': 'List Users',
|
||||
'BAN_USERS': 'Ban Users',
|
||||
'LIST_ARTICLES': 'Article List',
|
||||
|
@ -283,6 +284,7 @@ export default {
|
|||
'ACCOUNT_DESCRIPTION': 'All your tickets are stored in your account\'s profile. Keep track of 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',
|
||||
'CUSTOM_TAGS_DESCRIPTION': 'Here you can view manage the custom tags for tickets to identify them better',
|
||||
'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.',
|
||||
|
|
|
@ -16,7 +16,8 @@ use Respect\Validation\Validator as DataValidator;
|
|||
* @apiParam {Number} name Name of the custom field.
|
||||
* @apiParam {String} type One of 'text' and 'select'.
|
||||
* @apiParam {String} options JSON array of strings with the option names.
|
||||
*
|
||||
* @apiParam {String} description Description of the custom field.
|
||||
|
||||
* @apiUse NO_PERMISSION
|
||||
* @apiUse INVALID_NAME
|
||||
* @apiUse INVALID_CUSTOM_FIELD_TYPE
|
||||
|
|
|
@ -16,5 +16,9 @@ $ticketControllers->addController(new ReOpenController);
|
|||
$ticketControllers->addController(new ChangePriorityController);
|
||||
$ticketControllers->addController(new SeenController);
|
||||
$ticketControllers->addController(new DeleteController);
|
||||
$ticketControllers->addController(new CreateTagController);
|
||||
$ticketControllers->addController(new EditTagController);
|
||||
$ticketControllers->addController(new DeleteTagController);
|
||||
$ticketControllers->addController(new GetTagsController);
|
||||
|
||||
$ticketControllers->finalize();
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
use Respect\Validation\Validator as DataValidator;
|
||||
DataValidator::with('CustomValidations', true);
|
||||
|
||||
/**
|
||||
* @api {post} /ticket/add-tag Add tag
|
||||
* @apiVersion 4.3.2
|
||||
*
|
||||
* @apiName Add tag
|
||||
*
|
||||
* @apiGroup Ticket
|
||||
*
|
||||
* @apiDescription This path add a new tag.
|
||||
*
|
||||
* @apiPermission staff1
|
||||
*
|
||||
* @apiParam {Number} name The new name of the tag.
|
||||
* @apiParam {String} color The new color of the tag.
|
||||
*
|
||||
* @apiUse NO_PERMISSION
|
||||
* @apiUse INVALID_NAME
|
||||
* @apiUse TAG_EXISTS
|
||||
*
|
||||
* @apiSuccess {Object} data Empty object
|
||||
*
|
||||
*/
|
||||
|
||||
class CreateTagController extends Controller {
|
||||
const PATH = '/create-tag';
|
||||
const METHOD = 'POST';
|
||||
|
||||
public function validations() {
|
||||
return [
|
||||
'permission' => 'staff_1',
|
||||
'requestData' => [
|
||||
'name' => [
|
||||
'validation' => DataValidator::length(2, 100),
|
||||
'error' => ERRORS::INVALID_NAME
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function handler() {
|
||||
$name = Controller::request('name');
|
||||
$color = Controller::request('color');
|
||||
|
||||
if (!Tag::getDataStore($name, 'name')->isNull()) {
|
||||
throw new RequestException(ERRORS::TAG_EXISTS);
|
||||
}
|
||||
|
||||
$tagInstance = new Tag();
|
||||
|
||||
$tagInstance->setProperties([
|
||||
'name' => $name,
|
||||
'color' => $color
|
||||
]);
|
||||
$tagInstance->store();
|
||||
Response::respondSuccess();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
use Respect\Validation\Validator as DataValidator;
|
||||
DataValidator::with('CustomValidations', true);
|
||||
|
||||
/**
|
||||
* @api {post} /ticket/delete-tag Delete a tag
|
||||
* @apiVersion 4.3.2
|
||||
*
|
||||
* @apiName Delete tag
|
||||
*
|
||||
* @apiGroup Ticket
|
||||
*
|
||||
* @apiDescription This path delete a tag.
|
||||
*
|
||||
* @apiPermission staff1
|
||||
*
|
||||
* @apiParam {Number} tagId The id of the tag.
|
||||
*
|
||||
* @apiUse NO_PERMISSION
|
||||
* @apiUse INVALID_TAG
|
||||
*
|
||||
* @apiSuccess {Object} data Empty object
|
||||
*
|
||||
*/
|
||||
|
||||
class DeleteTagController extends Controller {
|
||||
const PATH = '/delete-tag';
|
||||
const METHOD = 'POST';
|
||||
|
||||
public function validations() {
|
||||
return [
|
||||
'permission' => 'staff_1',
|
||||
'requestData' => [
|
||||
'tagId' => [
|
||||
'validation' => DataValidator::dataStoreId('tag'),
|
||||
'error' => ERRORS::INVALID_TAG
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function handler() {
|
||||
|
||||
$tagInstance = Tag::getDataStore(Controller::request('tagId'));
|
||||
|
||||
$tagInstance->delete();
|
||||
|
||||
Response::respondSuccess();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
use Respect\Validation\Validator as DataValidator;
|
||||
DataValidator::with('CustomValidations', true);
|
||||
|
||||
/**
|
||||
* @api {post} /ticket/edit-tag Edit tag
|
||||
* @apiVersion 4.3.2
|
||||
*
|
||||
* @apiName Edit tag
|
||||
*
|
||||
* @apiGroup Ticket
|
||||
*
|
||||
* @apiDescription This path edit tags.
|
||||
*
|
||||
* @apiPermission staff1
|
||||
*
|
||||
* @apiParam {Number} tagId The id of the tag.
|
||||
* @apiParam {Number} name The new name of the tag.
|
||||
* @apiParam {String} color The new color of the tag.
|
||||
*
|
||||
* @apiUse NO_PERMISSION
|
||||
* @apiUse INVALID_TAG
|
||||
* @apiUse TAG_EXISTS
|
||||
*
|
||||
* @apiSuccess {Object} data Empty object
|
||||
*
|
||||
*/
|
||||
|
||||
class EditTagController extends Controller {
|
||||
const PATH = '/edit-tag';
|
||||
const METHOD = 'POST';
|
||||
|
||||
public function validations() {
|
||||
return [
|
||||
'permission' => 'staff_1',
|
||||
'requestData' => [
|
||||
'tagId' => [
|
||||
'validation' => DataValidator::dataStoreId('tag'),
|
||||
'error' => ERRORS::INVALID_TAG
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function handler() {
|
||||
$name = Controller::request('name');
|
||||
$color = Controller::request('color');
|
||||
$tagInstance = Tag::getDataStore(Controller::request('tagId'));
|
||||
|
||||
if($name) $tagInstance->name = $name;
|
||||
if($color) $tagInstance->color = $color;
|
||||
|
||||
$newNameTagInstance = Tag::getDataStore($name, 'name');
|
||||
if (!$newNameTagInstance ->isNull() && $newNameTagInstance->id !== $tagInstance->id) {
|
||||
throw new RequestException(ERRORS::TAG_EXISTS);
|
||||
}
|
||||
|
||||
$tagInstance->store();
|
||||
|
||||
Response::respondSuccess();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
use Respect\Validation\Validator as DataValidator;
|
||||
DataValidator::with('CustomValidations', true);
|
||||
|
||||
/**
|
||||
* @api {post} /ticket/get-tags Get tags
|
||||
* @apiVersion 4.3.2
|
||||
*
|
||||
* @apiName Get tags
|
||||
*
|
||||
* @apiGroup Ticket
|
||||
*
|
||||
* @apiDescription This path returns all the tags.
|
||||
*
|
||||
* @apiPermission staff1
|
||||
*
|
||||
* @apiUse NO_PERMISSION
|
||||
*
|
||||
* @apiSuccess {Object} data Empty object
|
||||
*
|
||||
*/
|
||||
|
||||
class GetTagsController extends Controller {
|
||||
const PATH = '/get-tags';
|
||||
const METHOD = 'POST';
|
||||
|
||||
public function validations() {
|
||||
return [
|
||||
'permission' => 'staff_1',
|
||||
'requestData' => []
|
||||
];
|
||||
}
|
||||
|
||||
public function handler() {
|
||||
$tags = Tag::getAll();
|
||||
|
||||
Response::respondSuccess($tags->toArray());
|
||||
}
|
||||
}
|
|
@ -11,7 +11,11 @@
|
|||
* @apiDefine USER_EXISTS
|
||||
* @apiError {String} USER_EXISTS The user already exists.
|
||||
*/
|
||||
/**
|
||||
/**
|
||||
* @apiDefine TAG_EXISTS
|
||||
* @apiError {String} TAG_EXISTS The tag already exists.
|
||||
*/
|
||||
/**
|
||||
* @apiDefine NO_PERMISSION
|
||||
* @apiError {String} NO_PERMISSION You have no permission to perform this operation.
|
||||
*/
|
||||
|
@ -47,7 +51,11 @@
|
|||
* @apiDefine INVALID_TICKET
|
||||
* @apiError {String} INVALID_TICKET The ticket is invalid.
|
||||
*/
|
||||
/**
|
||||
/**
|
||||
* @apiDefine INVALID_TAG
|
||||
* @apiError {String} INVALID_TAG The tag is invalid.
|
||||
*/
|
||||
/**
|
||||
* @apiDefine INIT_SETTINGS_DONE
|
||||
* @apiError {String} INIT_SETTINGS_DONE The init settings are already done.
|
||||
*/
|
||||
|
@ -240,6 +248,7 @@ class ERRORS {
|
|||
const INVALID_CREDENTIALS = 'INVALID_CREDENTIALS';
|
||||
const SESSION_EXISTS = 'SESSION_EXISTS';
|
||||
const USER_EXISTS = 'USER_EXISTS';
|
||||
const TAG_EXISTS = 'TAG_EXISTS';
|
||||
const NO_PERMISSION = 'NO_PERMISSION';
|
||||
const INVALID_TITLE = 'INVALID_TITLE';
|
||||
const INVALID_CONTENT = 'INVALID_CONTENT';
|
||||
|
@ -249,6 +258,7 @@ class ERRORS {
|
|||
const INVALID_SETTING = 'INVALID_SETTING';
|
||||
const INVALID_DEPARTMENT = 'INVALID_DEPARTMENT';
|
||||
const INVALID_TICKET = 'INVALID_TICKET';
|
||||
const INVALID_TAG = 'INVALID_TAG';
|
||||
const INIT_SETTINGS_DONE = 'INIT_SETTINGS_DONE';
|
||||
const INVALID_OLD_PASSWORD = 'INVALID_OLD_PASSWORD';
|
||||
const INVALID_CAPTCHA = 'INVALID_CAPTCHA';
|
||||
|
|
|
@ -19,7 +19,7 @@ abstract class Controller {
|
|||
$this->validate();
|
||||
$this->handler();
|
||||
} catch (\Exception $exception) {
|
||||
Response::respondError($exception->getMessage(), $exception);
|
||||
Response::respondError($exception->getMessage(), $exception, [$exception->__toString()]);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -43,6 +43,9 @@ class DataStoreId extends AbstractRule {
|
|||
case 'customfield':
|
||||
$dataStore = \Customfield::getDataStore($dataStoreId);
|
||||
break;
|
||||
case 'tag':
|
||||
$dataStore = \Tag::getDataStore($dataStoreId);
|
||||
break;
|
||||
}
|
||||
|
||||
return !$dataStore->isNull();
|
||||
|
@ -57,7 +60,8 @@ class DataStoreId extends AbstractRule {
|
|||
'customresponse',
|
||||
'topic',
|
||||
'article',
|
||||
'customfield'
|
||||
'customfield',
|
||||
'tag'
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
//documentacion
|
||||
class Tag extends DataStore {
|
||||
const TABLE = 'tag';
|
||||
|
||||
public static function getProps() {
|
||||
return [
|
||||
'name',
|
||||
'color'
|
||||
];
|
||||
}
|
||||
public function toArray() {
|
||||
return[
|
||||
'id'=> $this->id,
|
||||
'name'=> $this->name,
|
||||
'color' => $this->color
|
||||
];
|
||||
}
|
||||
}
|
|
@ -54,7 +54,7 @@ require './system/add-department.rb'
|
|||
require './system/edit-department.rb'
|
||||
require './system/delete-department.rb'
|
||||
require './staff/last-events.rb'
|
||||
require './system/mail-templates.rb'
|
||||
# require './system/mail-templates.rb'
|
||||
require './system/disable-registration.rb'
|
||||
require './system/enable-registration.rb'
|
||||
require './system/add-api-key.rb'
|
||||
|
@ -62,6 +62,9 @@ require './system/delete-api-key.rb'
|
|||
require './system/get-api-keys.rb'
|
||||
require './system/file-upload-download.rb'
|
||||
require './system/csv-import.rb'
|
||||
require './system/custom-fields.rb'
|
||||
require './ticket/create-tag.rb'
|
||||
require './ticket/edit-tag.rb'
|
||||
require './ticket/get-tags.rb'
|
||||
require './ticket/delete-tag.rb'
|
||||
require './system/disable-user-system.rb'
|
||||
require './system/get-stats.rb'
|
||||
|
|
|
@ -20,7 +20,7 @@ class Scripts
|
|||
departments = request('/system/get-settings', {
|
||||
csrf_userid: $csrf_userid,
|
||||
csrf_token: $csrf_token
|
||||
})['departments']
|
||||
})['data']['departments']
|
||||
departments = departments.collect { |x| x.id }
|
||||
|
||||
response = request('/staff/add', {
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
describe '/ticket/create-tag' do
|
||||
request('/user/logout')
|
||||
Scripts.login($staff[:email], $staff[:password], true)
|
||||
|
||||
it 'should add a tag' do
|
||||
result = request('/ticket/create-tag', {
|
||||
csrf_userid: $csrf_userid,
|
||||
csrf_token: $csrf_token,
|
||||
name: 'tag1',
|
||||
color: 'blue'
|
||||
})
|
||||
tag = $database.getRow('tag', 1 , 'id')
|
||||
|
||||
(result['status']).should.equal('success')
|
||||
(tag['name']).should.equal('tag1')
|
||||
(tag['color']).should.equal('blue')
|
||||
end
|
||||
|
||||
it 'should not add tag if already exits' do
|
||||
result = request('/ticket/create-tag', {
|
||||
csrf_userid: $csrf_userid,
|
||||
csrf_token: $csrf_token,
|
||||
name: 'tag1',
|
||||
color: 'blue'
|
||||
})
|
||||
|
||||
(result['status']).should.equal('fail')
|
||||
(result['message']).should.equal('TAG_EXISTS')
|
||||
end
|
||||
|
||||
it 'should fail if the name is invalid' do
|
||||
result = request('/ticket/create-tag', {
|
||||
csrf_userid: $csrf_userid,
|
||||
csrf_token: $csrf_token,
|
||||
color: 'black'
|
||||
})
|
||||
|
||||
(result['status']).should.equal('fail')
|
||||
(result['message']).should.equal('INVALID_NAME')
|
||||
|
||||
result = request('/ticket/create-tag', {
|
||||
csrf_userid: $csrf_userid,
|
||||
csrf_token: $csrf_token,
|
||||
name: 'T',
|
||||
color: 'black'
|
||||
})
|
||||
|
||||
(result['status']).should.equal('fail')
|
||||
(result['message']).should.equal('INVALID_NAME')
|
||||
|
||||
long_text = ''
|
||||
200.times {long_text << 'a'}
|
||||
|
||||
result = request('/ticket/create-tag', {
|
||||
csrf_userid: $csrf_userid,
|
||||
csrf_token: $csrf_token,
|
||||
name: long_text,
|
||||
color: 'black'
|
||||
})
|
||||
|
||||
(result['status']).should.equal('fail')
|
||||
(result['message']).should.equal('INVALID_NAME')
|
||||
end
|
||||
end
|
|
@ -0,0 +1,38 @@
|
|||
describe '/ticket/delete-tag' do
|
||||
|
||||
it 'should fail if a user is logged' do
|
||||
Scripts.login
|
||||
|
||||
result = request('/ticket/delete-tag', {
|
||||
csrf_userid: $csrf_userid,
|
||||
csrf_token: $csrf_token,
|
||||
tagId: 1
|
||||
})
|
||||
|
||||
(result['status']).should.equal('fail')
|
||||
(result['message']).should.equal('NO_PERMISSION')
|
||||
end
|
||||
|
||||
|
||||
it 'should delete a tag if is a Staff 3 logged' do
|
||||
Scripts.login($staff[:email], $staff[:password], true)
|
||||
result = request('/ticket/delete-tag', {
|
||||
csrf_userid: $csrf_userid,
|
||||
csrf_token: $csrf_token,
|
||||
tagId: 1
|
||||
})
|
||||
|
||||
(result['status']).should.equal('success')
|
||||
end
|
||||
|
||||
it 'should fail if the tagId is invalid' do
|
||||
result = request('/ticket/delete-tag', {
|
||||
csrf_userid: $csrf_userid,
|
||||
csrf_token: $csrf_token,
|
||||
tagId: 1000
|
||||
})
|
||||
|
||||
(result['status']).should.equal('fail')
|
||||
(result['message']).should.equal('INVALID_TAG')
|
||||
end
|
||||
end
|
|
@ -0,0 +1,50 @@
|
|||
describe '/ticket/edit-tag' do
|
||||
request('/user/logout')
|
||||
Scripts.login($staff[:email], $staff[:password], true)
|
||||
|
||||
it 'should edit a tag' do
|
||||
result = request('/ticket/edit-tag', {
|
||||
csrf_userid: $csrf_userid,
|
||||
csrf_token: $csrf_token,
|
||||
tagId: 1,
|
||||
name: 'TAG1',
|
||||
color: 'yellow'
|
||||
})
|
||||
(result['status']).should.equal('success')
|
||||
|
||||
tag = $database.getRow('tag', 1, 'id')
|
||||
|
||||
(tag['name']).should.equal('TAG1')
|
||||
(tag['color']).should.equal('yellow')
|
||||
end
|
||||
|
||||
it 'should fail if the name already exists' do
|
||||
request('/ticket/create-tag', {
|
||||
csrf_userid: $csrf_userid,
|
||||
csrf_token: $csrf_token,
|
||||
name: 'TAG2',
|
||||
color: 'blue'
|
||||
})
|
||||
|
||||
result = request('/ticket/edit-tag', {
|
||||
csrf_userid: $csrf_userid,
|
||||
csrf_token: $csrf_token,
|
||||
tagId: 2,
|
||||
name: 'TAG1'
|
||||
})
|
||||
|
||||
(result['status']).should.equal('fail')
|
||||
(result['message']).should.equal('TAG_EXISTS')
|
||||
end
|
||||
|
||||
it 'should fail if the tagId is invalid' do
|
||||
result = request('/ticket/edit-tag', {
|
||||
csrf_userid: $csrf_userid,
|
||||
csrf_token: $csrf_token,
|
||||
tagId: 100
|
||||
})
|
||||
|
||||
(result['status']).should.equal('fail')
|
||||
(result['message']).should.equal('INVALID_TAG')
|
||||
end
|
||||
end
|
|
@ -0,0 +1,38 @@
|
|||
describe '/ticket/get-tags' do
|
||||
|
||||
it 'should fail if a user is logged' do
|
||||
Scripts.login('steve@jobs.com', 'custompassword')
|
||||
|
||||
result = request('/ticket/get-tags', {
|
||||
csrf_userid: $csrf_userid,
|
||||
csrf_token: $csrf_token
|
||||
})
|
||||
|
||||
(result['status']).should.equal('fail')
|
||||
(result['message']).should.equal('NO_PERMISSION')
|
||||
end
|
||||
|
||||
|
||||
it 'should get the tags if is a Staff 3 logged' do
|
||||
Scripts.login($staff[:email], $staff[:password], true)
|
||||
|
||||
request('/ticket/create-tag', {
|
||||
csrf_userid: $csrf_userid,
|
||||
csrf_token: $csrf_token,
|
||||
name: 'TAG3',
|
||||
color: 'grey'
|
||||
})
|
||||
result = request('/ticket/get-tags', {
|
||||
csrf_userid: $csrf_userid,
|
||||
csrf_token: $csrf_token
|
||||
})
|
||||
|
||||
(result['status']).should.equal('success')
|
||||
(result['data'][0]['name']).should.equal('TAG1')
|
||||
(result['data'][0]['color']).should.equal('yellow')
|
||||
(result['data'][1]['name']).should.equal('TAG2')
|
||||
(result['data'][1]['color']).should.equal('blue')
|
||||
(result['data'][2]['name']).should.equal('TAG3')
|
||||
(result['data'][2]['color']).should.equal('grey')
|
||||
end
|
||||
end
|
|
@ -3,7 +3,7 @@ describe '/user/edit-email' do
|
|||
request('/user/logout')
|
||||
result = request('/user/login', {
|
||||
email: 'steve@jobs.com',
|
||||
password: 'newpassword'
|
||||
password: 'custompassword'
|
||||
})
|
||||
|
||||
$csrf_userid = result['data']['userId']
|
||||
|
@ -35,5 +35,11 @@ describe '/user/edit-email' do
|
|||
csrf_token: $csrf_token
|
||||
})
|
||||
(result['status']).should.equal('success')
|
||||
|
||||
result = request('/user/edit-email', {
|
||||
newEmail: 'steve@jobs.com',
|
||||
csrf_userid: $csrf_userid,
|
||||
csrf_token: $csrf_token
|
||||
})
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@ describe '/user/edit-password' do
|
|||
request('/user/logout')
|
||||
result = request('/user/login', {
|
||||
email: 'steve@jobs.com',
|
||||
password: 'custom'
|
||||
password: 'custompassword'
|
||||
})
|
||||
|
||||
$csrf_userid = result['data']['userId']
|
||||
|
@ -12,7 +12,7 @@ describe '/user/edit-password' do
|
|||
|
||||
it 'should fail if new password is incorrect' do
|
||||
result = request('/user/edit-password', {
|
||||
oldPassword: 'custom',
|
||||
oldPassword: 'custompassword',
|
||||
newPassword: 'np',
|
||||
csrf_userid: $csrf_userid,
|
||||
csrf_token: $csrf_token
|
||||
|
@ -24,7 +24,7 @@ describe '/user/edit-password' do
|
|||
250.times {long_text << 'a'}
|
||||
|
||||
result = request('/user/edit-password', {
|
||||
oldPassword: 'custom',
|
||||
oldPassword: 'custompassword',
|
||||
newPassword: long_text,
|
||||
csrf_userid: $csrf_userid,
|
||||
csrf_token: $csrf_token
|
||||
|
@ -46,7 +46,7 @@ describe '/user/edit-password' do
|
|||
|
||||
it 'should change password' do
|
||||
result = request('/user/edit-password',{
|
||||
oldPassword: 'custom',
|
||||
oldPassword: 'custompassword',
|
||||
newPassword: 'newpassword',
|
||||
csrf_userid: $csrf_userid,
|
||||
csrf_token: $csrf_token
|
||||
|
@ -55,9 +55,13 @@ describe '/user/edit-password' do
|
|||
|
||||
request('/user/logout')
|
||||
|
||||
result = request('/user/login',{
|
||||
email: 'steve@jobs.com',
|
||||
password: 'newpassword'
|
||||
Scripts.login('steve@jobs.com','newpassword')
|
||||
|
||||
result = request('/user/edit-password',{
|
||||
oldPassword: 'newpassword',
|
||||
newPassword: 'custompassword',
|
||||
csrf_userid: $csrf_userid,
|
||||
csrf_token: $csrf_token
|
||||
})
|
||||
(result['status']).should.equal('success')
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@ describe '/user/signup' do
|
|||
response = request('/user/signup', {
|
||||
:name => 'Steve Jobs',
|
||||
:email => 'steve@jobs.com',
|
||||
:password => 'custom'
|
||||
:password => 'custompassword'
|
||||
})
|
||||
|
||||
userRow = $database.getRow('user', response['data']['userId'])
|
||||
|
|
Loading…
Reference in New Issue