mirror of
https://github.com/opensupports/opensupports.git
synced 2025-07-28 16:24:42 +02:00
edit stags feature
This commit is contained in:
parent
6e0b7b7c80
commit
37ab1c5817
@ -35,7 +35,6 @@ import AdminPanelNewTickets from 'app/admin/panel/tickets/admin-panel-new-ticket
|
|||||||
import AdminPanelAllTickets from 'app/admin/panel/tickets/admin-panel-all-tickets';
|
import AdminPanelAllTickets from 'app/admin/panel/tickets/admin-panel-all-tickets';
|
||||||
import AdminPanelViewTicket from 'app/admin/panel/tickets/admin-panel-view-ticket';
|
import AdminPanelViewTicket from 'app/admin/panel/tickets/admin-panel-view-ticket';
|
||||||
import AdminPanelCustomResponses from 'app/admin/panel/tickets/admin-panel-custom-responses';
|
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 AdminPanelListUsers from 'app/admin/panel/users/admin-panel-list-users';
|
||||||
import AdminPanelViewUser from 'app/admin/panel/users/admin-panel-view-user';
|
import AdminPanelViewUser from 'app/admin/panel/users/admin-panel-view-user';
|
||||||
@ -52,6 +51,7 @@ import AdminPanelViewStaff from 'app/admin/panel/staff/admin-panel-view-staff';
|
|||||||
import AdminPanelSystemPreferences from 'app/admin/panel/settings/admin-panel-system-preferences';
|
import AdminPanelSystemPreferences from 'app/admin/panel/settings/admin-panel-system-preferences';
|
||||||
import AdminPanelAdvancedSettings from 'app/admin/panel/settings/admin-panel-advanced-settings';
|
import AdminPanelAdvancedSettings from 'app/admin/panel/settings/admin-panel-advanced-settings';
|
||||||
import AdminPanelEmailSettings from 'app/admin/panel/settings/admin-panel-email-settings';
|
import AdminPanelEmailSettings from 'app/admin/panel/settings/admin-panel-email-settings';
|
||||||
|
import AdminPanelCustomTags from 'app/admin/panel/settings/admin-panel-custom-tags';
|
||||||
|
|
||||||
// INSTALLATION
|
// INSTALLATION
|
||||||
import InstallLayout from 'app/install/install-layout';
|
import InstallLayout from 'app/install/install-layout';
|
||||||
@ -115,7 +115,6 @@ export default (
|
|||||||
<Route path="all-tickets" component={AdminPanelAllTickets} />
|
<Route path="all-tickets" component={AdminPanelAllTickets} />
|
||||||
<Route path="custom-responses" component={AdminPanelCustomResponses} />
|
<Route path="custom-responses" component={AdminPanelCustomResponses} />
|
||||||
<Route path="view-ticket/:ticketNumber" component={AdminPanelViewTicket} />
|
<Route path="view-ticket/:ticketNumber" component={AdminPanelViewTicket} />
|
||||||
<Route path="custom-tags" component={AdminPanelCustomTags} />
|
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
<Route path="users">
|
<Route path="users">
|
||||||
@ -144,6 +143,7 @@ export default (
|
|||||||
<Route path="system-preferences" component={AdminPanelSystemPreferences} />
|
<Route path="system-preferences" component={AdminPanelSystemPreferences} />
|
||||||
<Route path="advanced-settings" component={AdminPanelAdvancedSettings} />
|
<Route path="advanced-settings" component={AdminPanelAdvancedSettings} />
|
||||||
<Route path="email-settings" component={AdminPanelEmailSettings} />
|
<Route path="email-settings" component={AdminPanelEmailSettings} />
|
||||||
|
<Route path="custom-tags" component={AdminPanelCustomTags} />
|
||||||
</Route>
|
</Route>
|
||||||
</Route>
|
</Route>
|
||||||
</Route>
|
</Route>
|
||||||
|
@ -135,11 +135,6 @@ class AdminPanelMenu extends React.Component {
|
|||||||
name: i18n('CUSTOM_RESPONSES'),
|
name: i18n('CUSTOM_RESPONSES'),
|
||||||
path: '/admin/panel/tickets/custom-responses',
|
path: '/admin/panel/tickets/custom-responses',
|
||||||
level: 2
|
level: 2
|
||||||
},
|
|
||||||
{
|
|
||||||
name: i18n('CUSTOM_TAGS'),
|
|
||||||
path: '/admin/panel/tickets/custom-tags',
|
|
||||||
level: 1
|
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
@ -219,6 +214,11 @@ class AdminPanelMenu extends React.Component {
|
|||||||
name: i18n('EMAIL_SETTINGS'),
|
name: i18n('EMAIL_SETTINGS'),
|
||||||
path: '/admin/panel/settings/email-settings',
|
path: '/admin/panel/settings/email-settings',
|
||||||
level: 3
|
level: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: i18n('CUSTOM_TAGS'),
|
||||||
|
path: '/admin/panel/settings/custom-tags',
|
||||||
|
level: 3
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
101
client/src/app/admin/panel/settings/admin-panel-custom-tags.js
Normal file
101
client/src/app/admin/panel/settings/admin-panel-custom-tags.js
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {connect} from 'react-redux';
|
||||||
|
|
||||||
|
import AdminPanelCustomTagsModal from 'app/admin/panel/tickets/admin-panel-custom-tags-modal';
|
||||||
|
|
||||||
|
import i18n from 'lib-app/i18n';
|
||||||
|
import API from 'lib-app/api-call';
|
||||||
|
import ConfigActions from 'actions/config-actions';
|
||||||
|
|
||||||
|
import AreYouSure from 'app-components/are-you-sure';
|
||||||
|
import ModalContainer from 'app-components/modal-container';
|
||||||
|
|
||||||
|
import Icon from 'core-components/icon';
|
||||||
|
import Button from 'core-components/button';
|
||||||
|
import Header from 'core-components/header';
|
||||||
|
import Tag from 'core-components/tag';
|
||||||
|
|
||||||
|
class AdminPanelCustomTags extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
tags: React.PropTypes.arrayOf(
|
||||||
|
React.PropTypes.shape({
|
||||||
|
name: React.PropTypes.string,
|
||||||
|
color: React.PropTypes.string,
|
||||||
|
id: React.PropTypes.number
|
||||||
|
})
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.retrieveCustomTags();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className="admin-panel-custom-tags">
|
||||||
|
<Header title={i18n('CUSTOM_TAGS')} description={i18n('CUSTOM_TAGS_DESCRIPTION')} />
|
||||||
|
{this.renderContent()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderContent() {
|
||||||
|
return (
|
||||||
|
<div className="admin-panel-custom-tags__content">
|
||||||
|
<div>
|
||||||
|
<Button onClick={this.openTagModal.bind(this)} type="secondary">
|
||||||
|
{i18n('ADD_CUSTOM_TAG')}<Icon className="admin-panel-custom-tags__add-button-icon" name="plus"/>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div className="admin-panel-custom-tags__tag-list">
|
||||||
|
{this.props.tags.map(this.renderTag.bind(this))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderTag(tag, index) {
|
||||||
|
return(
|
||||||
|
<div key={index} className="admin-panel-custom-tags__tag-container" >
|
||||||
|
<Tag color={tag.color} name={tag.name} onEditClick={this.openEditTagModal.bind(this, tag.id, tag.name, tag.color)} onRemoveClick={this.onDeleteClick.bind(this, tag.id)} size='large' showEditButton showDeleteButton />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
openTagModal() {
|
||||||
|
ModalContainer.openModal(
|
||||||
|
<AdminPanelCustomTagsModal onTagCreated={this.retrieveCustomTags.bind(this)} createTag />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
openEditTagModal(tagId,tagName,tagColor, event) {
|
||||||
|
ModalContainer.openModal(
|
||||||
|
<AdminPanelCustomTagsModal defaultValues={{name: tagName , color: tagColor}} id={tagId} onTagChange={this.retrieveCustomTags.bind(this)}/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
onDeleteClick(tagId, event) {
|
||||||
|
event.preventDefault();
|
||||||
|
AreYouSure.openModal(i18n('WILL_DELETE_CUSTOM_RESPONSE'), this.deleteCustomTag.bind(this, tagId));
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteCustomTag(tagId) {
|
||||||
|
API.call({
|
||||||
|
path: '/ticket/delete-tag',
|
||||||
|
data: {
|
||||||
|
tagId,
|
||||||
|
}
|
||||||
|
}).then(() => {
|
||||||
|
this.retrieveCustomTags()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
retrieveCustomTags() {
|
||||||
|
this.props.dispatch(ConfigActions.updateData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect((store) => {
|
||||||
|
return {
|
||||||
|
tags: store.config['tags']
|
||||||
|
};
|
||||||
|
})(AdminPanelCustomTags);
|
@ -0,0 +1,18 @@
|
|||||||
|
.admin-panel-custom-tags {
|
||||||
|
|
||||||
|
&__content {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__add-button-icon{
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__tag-list{
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__tag-container{
|
||||||
|
margin-top:5px ;
|
||||||
|
}
|
||||||
|
}
|
@ -26,13 +26,45 @@ class AdminPanelCustomTagsModal extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
return(
|
||||||
|
this.props.createTag ? this.renderCreateTagContent() : this.renderEditTagContent()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderEditTagContent() {
|
||||||
|
return (
|
||||||
|
<div className='admin-panel-custom-tags-modal'>
|
||||||
|
<Header title={i18n('EDIT_CUSTOM_TAG')} description={i18n('DESCRIPTION_EDIT_CUSTOM_TAG')} />
|
||||||
|
<Form
|
||||||
|
values={this.state.form}
|
||||||
|
onChange={this.onFormChange.bind(this)}
|
||||||
|
onSubmit={this.onSubmitEditTag.bind(this)}
|
||||||
|
errors={this.state.errors}
|
||||||
|
onValidateErrors={errors => this.setState({errors})}
|
||||||
|
loading={this.state.loading}>
|
||||||
|
<FormField name="name" label={i18n('NAME')} fieldProps={{size: 'large'}}/>
|
||||||
|
<FormField name="color" label={i18n('COLOR')} decorator={ColorSelector} />
|
||||||
|
<div className='admin-panel-custom-tags-modal__actions'>
|
||||||
|
<SubmitButton type="secondary" size="small">
|
||||||
|
{i18n('SAVE')}
|
||||||
|
</SubmitButton>
|
||||||
|
<Button onClick={this.onDiscardClick.bind(this)} size="small">
|
||||||
|
{i18n('CANCEL')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderCreateTagContent() {
|
||||||
return (
|
return (
|
||||||
<div className='admin-panel-custom-tags-modal'>
|
<div className='admin-panel-custom-tags-modal'>
|
||||||
<Header title={i18n('ADD_CUSTOM_TAG')} description={i18n('DESCRIPTION_ADD_CUSTOM_TAG')} />
|
<Header title={i18n('ADD_CUSTOM_TAG')} description={i18n('DESCRIPTION_ADD_CUSTOM_TAG')} />
|
||||||
<Form
|
<Form
|
||||||
values={this.state.form}
|
values={this.state.form}
|
||||||
onChange={this.onFormChange.bind(this)}
|
onChange={this.onFormChange.bind(this)}
|
||||||
onSubmit={this.onSubmitTag.bind(this)}
|
onSubmit={this.onSubmitNewTag.bind(this)}
|
||||||
errors={this.state.errors}
|
errors={this.state.errors}
|
||||||
onValidateErrors={errors => this.setState({errors})}
|
onValidateErrors={errors => this.setState({errors})}
|
||||||
loading={this.state.loading}>
|
loading={this.state.loading}>
|
||||||
@ -56,8 +88,39 @@ class AdminPanelCustomTagsModal extends React.Component {
|
|||||||
form
|
form
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
onSubmitEditTag(form) {
|
||||||
|
this.setState({
|
||||||
|
loading: true
|
||||||
|
});
|
||||||
|
|
||||||
onSubmitTag(form) {
|
API.call({
|
||||||
|
path: '/ticket/edit-tag',
|
||||||
|
data: {
|
||||||
|
tagId: this.props.id,
|
||||||
|
name: form.name,
|
||||||
|
color: form.color,
|
||||||
|
}
|
||||||
|
}).then(() => {
|
||||||
|
this.context.closeModal();
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
errors: {}
|
||||||
|
});
|
||||||
|
if(this.props.onTagChange) {
|
||||||
|
this.props.onTagChange();
|
||||||
|
}
|
||||||
|
}).catch((result) => {
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
errors: {
|
||||||
|
'name': result.message
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
onSubmitNewTag(form) {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: true
|
loading: true
|
||||||
});
|
});
|
||||||
|
@ -16,11 +16,21 @@ class Tag extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div className={this.getClass()} style={{backgroundColor:this.props.color}} onClick={event => event.stopPropagation()} >
|
<div className={this.getClass()} style={{backgroundColor:this.props.color}} onClick={event => event.stopPropagation()} >
|
||||||
<span className="tag__name">{this.props.name}</span>
|
<span className="tag__name">{this.props.name}</span>
|
||||||
{this.props.showDeleteButton ? this.renderRemoveButton() : null}
|
<span>
|
||||||
|
{this.props.showEditButton ? this.renderEditButton() : null}
|
||||||
|
{this.props.showDeleteButton ? this.renderRemoveButton() : null}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderEditButton() {
|
||||||
|
return (
|
||||||
|
<span onClick={this.props.onEditClick} className="tag__edit" >
|
||||||
|
<Icon name="pencil" size="small"/>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
renderRemoveButton() {
|
renderRemoveButton() {
|
||||||
return (
|
return (
|
||||||
<span onClick={this.props.onRemoveClick} className="tag__remove" >
|
<span onClick={this.props.onRemoveClick} className="tag__remove" >
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
|
margin-top: 3px;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
@ -17,6 +18,12 @@
|
|||||||
color: $light-grey;
|
color: $light-grey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&__edit {
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
color: $light-grey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&_small {
|
&_small {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
|
@ -106,6 +106,7 @@ export default {
|
|||||||
'LAST_EDITED_IN': 'Last edited in {date}',
|
'LAST_EDITED_IN': 'Last edited in {date}',
|
||||||
'EDIT': 'Edit',
|
'EDIT': 'Edit',
|
||||||
'ADD_CUSTOM_TAG': 'Add custom tag',
|
'ADD_CUSTOM_TAG': 'Add custom tag',
|
||||||
|
'EDIT_CUSTOM_TAG': 'Edit custom tag',
|
||||||
'NO_RESULTS': 'No results',
|
'NO_RESULTS': 'No results',
|
||||||
'DELETE_AND_BAN': 'Delete and ban',
|
'DELETE_AND_BAN': 'Delete and ban',
|
||||||
'STAFF_LEVEL': 'Staff Level',
|
'STAFF_LEVEL': 'Staff Level',
|
||||||
@ -209,6 +210,7 @@ export default {
|
|||||||
'OPTIONS': 'Options',
|
'OPTIONS': 'Options',
|
||||||
'FIELD_DESCRIPTION': 'Field description (Optional)',
|
'FIELD_DESCRIPTION': 'Field description (Optional)',
|
||||||
'DESCRIPTION_ADD_CUSTOM_TAG': 'here you can add a new custom tag',
|
'DESCRIPTION_ADD_CUSTOM_TAG': 'here you can add a new custom tag',
|
||||||
|
'DESCRIPTION_EDIT_CUSTOM_TAG': 'here you can edit a custom tag',
|
||||||
'CUSTOM_FIELDS': 'Custom fields',
|
'CUSTOM_FIELDS': 'Custom fields',
|
||||||
|
|
||||||
'CHART_CREATE_TICKET': 'Tickets created',
|
'CHART_CREATE_TICKET': 'Tickets created',
|
||||||
|
@ -12,7 +12,7 @@ DataValidator::with('CustomValidations', true);
|
|||||||
*
|
*
|
||||||
* @apiDescription This path creates a new tag.
|
* @apiDescription This path creates a new tag.
|
||||||
*
|
*
|
||||||
* @apiPermission staff1
|
* @apiPermission staff3
|
||||||
*
|
*
|
||||||
* @apiParam {Number} name The new name of the tag.
|
* @apiParam {Number} name The new name of the tag.
|
||||||
* @apiParam {String} color The new color of the tag.
|
* @apiParam {String} color The new color of the tag.
|
||||||
@ -31,7 +31,7 @@ class CreateTagController extends Controller {
|
|||||||
|
|
||||||
public function validations() {
|
public function validations() {
|
||||||
return [
|
return [
|
||||||
'permission' => 'staff_1',
|
'permission' => 'staff_3',
|
||||||
'requestData' => [
|
'requestData' => [
|
||||||
'name' => [
|
'name' => [
|
||||||
'validation' => DataValidator::length(2, 100),
|
'validation' => DataValidator::length(2, 100),
|
||||||
|
@ -12,7 +12,7 @@ DataValidator::with('CustomValidations', true);
|
|||||||
*
|
*
|
||||||
* @apiDescription This path delete a tag.
|
* @apiDescription This path delete a tag.
|
||||||
*
|
*
|
||||||
* @apiPermission staff1
|
* @apiPermission staff3
|
||||||
*
|
*
|
||||||
* @apiParam {Number} tagId The id of the tag.
|
* @apiParam {Number} tagId The id of the tag.
|
||||||
*
|
*
|
||||||
@ -29,7 +29,7 @@ class DeleteTagController extends Controller {
|
|||||||
|
|
||||||
public function validations() {
|
public function validations() {
|
||||||
return [
|
return [
|
||||||
'permission' => 'staff_1',
|
'permission' => 'staff_3',
|
||||||
'requestData' => [
|
'requestData' => [
|
||||||
'tagId' => [
|
'tagId' => [
|
||||||
'validation' => DataValidator::dataStoreId('tag'),
|
'validation' => DataValidator::dataStoreId('tag'),
|
||||||
|
@ -12,7 +12,7 @@ DataValidator::with('CustomValidations', true);
|
|||||||
*
|
*
|
||||||
* @apiDescription This path edit tags.
|
* @apiDescription This path edit tags.
|
||||||
*
|
*
|
||||||
* @apiPermission staff1
|
* @apiPermission staff3
|
||||||
*
|
*
|
||||||
* @apiParam {Number} tagId The id of the tag.
|
* @apiParam {Number} tagId The id of the tag.
|
||||||
* @apiParam {Number} name The new name of the tag.
|
* @apiParam {Number} name The new name of the tag.
|
||||||
@ -32,7 +32,7 @@ class EditTagController extends Controller {
|
|||||||
|
|
||||||
public function validations() {
|
public function validations() {
|
||||||
return [
|
return [
|
||||||
'permission' => 'staff_1',
|
'permission' => 'staff_3',
|
||||||
'requestData' => [
|
'requestData' => [
|
||||||
'tagId' => [
|
'tagId' => [
|
||||||
'validation' => DataValidator::dataStoreId('tag'),
|
'validation' => DataValidator::dataStoreId('tag'),
|
||||||
|
@ -12,7 +12,7 @@ DataValidator::with('CustomValidations', true);
|
|||||||
*
|
*
|
||||||
* @apiDescription This path returns all the tags.
|
* @apiDescription This path returns all the tags.
|
||||||
*
|
*
|
||||||
* @apiPermission staff1
|
* @apiPermission staff3
|
||||||
*
|
*
|
||||||
* @apiUse NO_PERMISSION
|
* @apiUse NO_PERMISSION
|
||||||
*
|
*
|
||||||
@ -26,14 +26,14 @@ class GetTagsController extends Controller {
|
|||||||
|
|
||||||
public function validations() {
|
public function validations() {
|
||||||
return [
|
return [
|
||||||
'permission' => 'staff_1',
|
'permission' => 'staff_3',
|
||||||
'requestData' => []
|
'requestData' => []
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handler() {
|
public function handler() {
|
||||||
$tags = Tag::getAll();
|
$tags = Tag::getAll();
|
||||||
|
|
||||||
Response::respondSuccess($tags->toArray());
|
Response::respondSuccess($tags->toArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user