frontend 1part

This commit is contained in:
Guillermo 2019-01-15 20:44:21 -03:00
parent a85386a162
commit 57feafd453
7 changed files with 304 additions and 3 deletions

View File

@ -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';
@ -113,6 +114,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">

View File

@ -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
}
])
},

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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',
@ -267,6 +268,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.',

View File

@ -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;
}
};

View File

@ -3,11 +3,11 @@ class Response {
private static $response;
private static $responseException;
public static function respondError($errorMsg, $exception = null) {
public static function respondError($errorMsg, $exception = null, $data = null) {
self::$response = array(
'status' => 'fail',
'message' => $errorMsg,
'data' => null
'data' => $data
);
self::$responseException = $exception;