diff --git a/client/src/app-components/are-you-sure.js b/client/src/app-components/are-you-sure.js
index a1502c09..13c86819 100644
--- a/client/src/app-components/are-you-sure.js
+++ b/client/src/app-components/are-you-sure.js
@@ -2,6 +2,7 @@ import React from 'react';
import i18n from 'lib-app/i18n';
import Button from 'core-components/button';
+import ModalContainer from 'app-components/modal-container';
class AreYouSure extends React.Component {
static propTypes = {
@@ -12,6 +13,12 @@ class AreYouSure extends React.Component {
static contextTypes = {
closeModal: React.PropTypes.func
};
+
+ static openModal(description, onYes) {
+ ModalContainer.openModal(
+
+ );
+ }
componentDidMount() {
this.refs.yesButton && this.refs.yesButton.focus();
diff --git a/client/src/app-components/language-selector.js b/client/src/app-components/language-selector.js
index 127ed793..5ee64a17 100644
--- a/client/src/app-components/language-selector.js
+++ b/client/src/app-components/language-selector.js
@@ -12,10 +12,11 @@ const codeLanguages = {
'Indian': 'in'
};
const languages = Object.keys(codeLanguages);
+const languageCodes = Object.values(codeLanguages).concat(['en']);
class LanguageSelector extends React.Component {
static propTypes = {
- language: React.PropTypes.oneOf(languages)
+ language: React.PropTypes.oneOf(languageCodes)
};
render() {
diff --git a/client/src/app/admin/panel/tickets/admin-panel-custom-responses.js b/client/src/app/admin/panel/tickets/admin-panel-custom-responses.js
index ea619f6f..3a400595 100644
--- a/client/src/app/admin/panel/tickets/admin-panel-custom-responses.js
+++ b/client/src/app/admin/panel/tickets/admin-panel-custom-responses.js
@@ -4,9 +4,9 @@ import {connect} from 'react-redux';
import RichTextEditor from 'react-rte-browserify';
import i18n from 'lib-app/i18n';
+import API from 'lib-app/api-call';
import AdminDataActions from 'actions/admin-data-actions';
-import ModalContainer from 'app-components/modal-container';
import AreYouSure from 'app-components/are-you-sure';
import Icon from 'core-components/icon';
@@ -24,6 +24,7 @@ class AdminPanelCustomResponses extends React.Component {
};
state = {
+ formLoading: false,
selectedIndex: -1,
edited: false,
errors: {},
@@ -32,7 +33,7 @@ class AdminPanelCustomResponses extends React.Component {
componentDidMount() {
if (!this.props.loaded) {
- this.props.dispatch(AdminDataActions.retrieveCustomResponses());
+ this.retrieveCustomResponses();
}
}
@@ -59,12 +60,7 @@ class AdminPanelCustomResponses extends React.Component {
{i18n('SAVE')}
-
-
-
-
-
-
+ {(this.state.selectedIndex !== -1) ? this.renderOptionalButtons() : null}
@@ -80,6 +76,19 @@ class AdminPanelCustomResponses extends React.Component {
);
}
+ renderOptionalButtons() {
+ return (
+
+
+
+
+
+
+
+
+ );
+ }
+
getListingProps() {
return {
title: i18n('CUSTOM_RESPONSES'),
@@ -95,8 +104,10 @@ class AdminPanelCustomResponses extends React.Component {
return {
values: this.state.form,
errors: this.state.errors,
+ loading: this.state.formLoading,
onChange: (form) => {this.setState({form, edited: true})},
- onValidateErrors: (errors) => {this.setState({errors})}
+ onValidateErrors: (errors) => {this.setState({errors})},
+ onSubmit: this.onFormSubmit.bind(this)
}
}
@@ -117,14 +128,61 @@ class AdminPanelCustomResponses extends React.Component {
onItemChange(index) {
if(this.state.edited) {
- ModalContainer.openModal(
-
- );
+ AreYouSure.openModal(i18n('WILL_LOSE_CHANGES'), this.updateForm.bind(this, index));
} else {
this.updateForm(index);
}
}
+ onFormSubmit(form) {
+ this.setState({formLoading: true});
+
+ if(this.state.selectedIndex !== -1) {
+ API.call({
+ path: '/ticket/edit-custom-response',
+ data: {
+ id: this.state.selectedIndex,
+ name: form.name,
+ content: form.content,
+ language: form.language
+ }
+ }).then(() => {
+ this.setState({formLoading: false});
+ this.retrieveCustomResponses();
+ });
+ } else {
+ API.call({
+ path: '/ticket/add-custom-response',
+ data: {
+ id: this.state.selectedIndex,
+ name: form.title,
+ content: form.content,
+ language: form.language
+ }
+ }).then(() => {
+ this.setState({formLoading: false});
+ this.retrieveCustomResponses();
+ });
+ }
+ }
+
+ onDiscardChangesClick() {
+ this.onItemChange(this.state.selectedIndex);
+ }
+
+ onDeleteClick() {
+ AreYouSure.openModal(i18n('WILL_DELETE_CUSTOM_RESPONSE'), this.deleteCustomResponse.bind(this));
+ }
+
+ deleteCustomResponse() {
+ API.call({
+ path: '/ticket/delete-custom-response',
+ data: {
+ id: this.state.selectedIndex
+ }
+ }).then(this.retrieveCustomResponses.bind(this));
+ }
+
updateForm(index) {
let form = _.clone(this.state.form);
@@ -138,6 +196,10 @@ class AdminPanelCustomResponses extends React.Component {
errors: {}
});
}
+
+ retrieveCustomResponses() {
+ this.props.dispatch(AdminDataActions.retrieveCustomResponses());
+ }
}
export default connect((store) => {
diff --git a/client/src/app/admin/panel/tickets/admin-panel-custom-responses.scss b/client/src/app/admin/panel/tickets/admin-panel-custom-responses.scss
index b92025bb..33f00b58 100644
--- a/client/src/app/admin/panel/tickets/admin-panel-custom-responses.scss
+++ b/client/src/app/admin/panel/tickets/admin-panel-custom-responses.scss
@@ -16,6 +16,10 @@
margin-right: 30px;
}
+ &__optional-buttons {
+ display: inline;
+ }
+
&__discard-button {
display: inline-block;
}
diff --git a/client/src/core-components/menu.js b/client/src/core-components/menu.js
index b0b98eb2..de7cd63e 100644
--- a/client/src/core-components/menu.js
+++ b/client/src/core-components/menu.js
@@ -13,7 +13,7 @@ class Menu extends React.Component {
header: React.PropTypes.string,
type: React.PropTypes.oneOf(['primary', 'secondary', 'navigation', 'horizontal', 'horizontal-list']),
items: React.PropTypes.arrayOf(React.PropTypes.shape({
- content: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.number]),
+ content: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.number, React.PropTypes.node]),
icon: React.PropTypes.string
})).isRequired,
selectedIndex: React.PropTypes.number,
diff --git a/client/src/data/fixtures/ticket-fixtures.js b/client/src/data/fixtures/ticket-fixtures.js
index d7a178d5..f589dd78 100644
--- a/client/src/data/fixtures/ticket-fixtures.js
+++ b/client/src/data/fixtures/ticket-fixtures.js
@@ -47,5 +47,35 @@ module.exports = [
]
};
}
+ },
+ {
+ path: '/ticket/add-custom-response',
+ time: 1000,
+ response: function () {
+ return {
+ status: 'success',
+ data: {}
+ };
+ }
+ },
+ {
+ path: '/ticket/edit-custom-response',
+ time: 1000,
+ response: function () {
+ return {
+ status: 'success',
+ data: {}
+ };
+ }
+ },
+ {
+ path: '/ticket/delete-custom-response',
+ time: 1000,
+ response: function () {
+ return {
+ status: 'success',
+ data: {}
+ };
+ }
}
];
\ No newline at end of file
diff --git a/client/src/data/languages/en.js b/client/src/data/languages/en.js
index ee46f1c5..8517c52d 100644
--- a/client/src/data/languages/en.js
+++ b/client/src/data/languages/en.js
@@ -91,5 +91,6 @@ export default {
'EMAIL_CHANGED': 'Email has been changed successfully',
'PASSWORD_CHANGED': 'Password has been changed successfully',
'OLD_PASSWORD_INCORRECT': 'Old password is incorrect',
- 'WILL_LOSE_CHANGES': 'You haven\'t save. Your changes will be lost.'
+ 'WILL_LOSE_CHANGES': 'You haven\'t save. Your changes will be lost.',
+ 'WILL_DELETE_CUSTOM_RESPONSE': 'The custom response will be deleted.'
};
\ No newline at end of file
diff --git a/client/src/lib-app/validations/length-validator.js b/client/src/lib-app/validations/length-validator.js
index 82c277b9..9aa33f7d 100644
--- a/client/src/lib-app/validations/length-validator.js
+++ b/client/src/lib-app/validations/length-validator.js
@@ -10,7 +10,7 @@ class LengthValidator extends Validator {
this.errorKey = errorKey;
}
- validate(value, form) {
+ validate(value = '', form = {}) {
if (value instanceof RichTextEditor.EditorValue) {
value = value.getEditorState().getCurrentContent().getPlainText();
}
diff --git a/client/src/reducers/admin-data-reducer.js b/client/src/reducers/admin-data-reducer.js
index 82717d97..60c59d20 100644
--- a/client/src/reducers/admin-data-reducer.js
+++ b/client/src/reducers/admin-data-reducer.js
@@ -1,7 +1,6 @@
import _ from 'lodash';
import Reducer from 'reducers/reducer';
-//import sessionStore from 'lib-app/session-store';
class AdminDataReducer extends Reducer {
@@ -19,8 +18,6 @@ class AdminDataReducer extends Reducer {
}
onCustomResponses(state, payload) {
- //sessionStore.setItem('language', payload);
-
return _.extend({}, state, {
customResponses: payload.data,
customResponsesLoaded: true