diff --git a/client/src/app/admin/panel/settings/admin-panel-email-templates.js b/client/src/app/admin/panel/settings/admin-panel-email-templates.js index d111b0f6..99bdee30 100644 --- a/client/src/app/admin/panel/settings/admin-panel-email-templates.js +++ b/client/src/app/admin/panel/settings/admin-panel-email-templates.js @@ -1,14 +1,237 @@ import React from 'react'; +import _ from 'lodash'; +import RichTextEditor from 'react-rte-browserify'; + +import i18n from 'lib-app/i18n'; +import API from 'lib-app/api-call'; + +import AreYouSure from 'app-components/are-you-sure'; +import LanguageSelector from 'app-components/language-selector'; + +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'; class AdminPanelEmailTemplates extends React.Component { + state = { + loaded: false, + items: [], + formLoading: false, + selectedIndex: 0, + edited: false, + errors: {}, + language: 'en', + form: { + title: '', + content: RichTextEditor.createEmptyValue() + } + }; + + componentDidMount() { + this.retrieveEmailTemplates(); + } + render() { return ( -
- /admin/panel/settings/email-templates +
+
+ {(this.state.loaded) ? this.renderContent() : this.renderLoading()}
); } + + renderContent() { + return ( +
+
+ +
+
+ this.onItemChange(this.state.selectedIndex, event.target.value)} fieldProps={{ + type: 'allowed', + size: 'medium' + }}/> +
+
+
+ +
+
+ +
+
+ {i18n('SAVE')} +
+
+ {(this.state.edited) ? this.renderDiscardButton() : null} +
+ +
+
+
+ +
+
+ ); + } + + renderLoading() { + return ( +
+ +
+ ); + } + + renderDiscardButton() { + return ( +
+ +
+ ); + } + + getListingProps() { + return { + title: i18n('EMAIL_TEMPLATES'), + items: this.getItems(), + selectedIndex: this.state.selectedIndex, + onChange: this.onItemChange.bind(this) + }; + } + + getFormProps() { + 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})}, + onSubmit: this.onFormSubmit.bind(this) + } + } + + getItems() { + return this.state.items.map((item) => { + return { + content: i18n(item.type) + }; + }); + } + + onItemChange(index, language) { + if(this.state.edited) { + AreYouSure.openModal(i18n('WILL_LOSE_CHANGES'), this.updateForm.bind(this, index, language)); + } else { + this.updateForm(index, language); + } + } + + onFormSubmit(form) { + this.setState({formLoading: true}); + + API.call({ + path: '/system/edit-mail-template', + data: { + templateType: this.state.items[this.state.selectedIndex].type, + subject: form.title, + body: form.content, + language: this.state.language + } + }).then(() => { + this.setState({formLoading: false}); + this.retrieveEmailTemplates(); + }); + } + + onDiscardChangesClick(event) { + event.preventDefault(); + this.onItemChange(this.state.selectedIndex); + } + + onRecoverClick(event) { + event.preventDefault(); + AreYouSure.openModal(i18n('WILL_RECOVER_EMAIL_TEMPLATE'), this.recoverEmailTemplate.bind(this)); + } + + recoverEmailTemplate() { + API.call({ + path: '/system/recover-mail-template', + data: { + templateType: this.state.items[this.state.selectedIndex].type, + language: this.state.language + } + }).then(() => { + this.retrieveEmailTemplates(); + }); + } + + updateForm(index, language) { + let form = _.clone(this.state.form); + let items = this.state.items; + + language = language || this.state.language; + + form.title = (items[index] && items[index][language].subject) || ''; + form.content = RichTextEditor.createValueFromString((items[index] && items[index][language].body) || '', 'html'); + + this.setState({ + selectedIndex: index, + language: language, + edited: false, + formLoading: false, + form: form, + errors: {} + }); + } + + retrieveEmailTemplates() { + return API.call({ + path: '/system/get-mail-templates', + data: {} + }).then((result) => this.setState({ + edited: false, + loaded: true, + items: this.getParsedItems(result.data) + }, this.updateForm.bind(this, this.state.selectedIndex))); + } + + getParsedItems(items) { + let parsedItems = {}; + + _.forEach(items, (item) => { + if(parsedItems[item.type]) { + parsedItems[item.type][item.language] = { + subject: item.subject, + body: item.body + }; + } else { + parsedItems[item.type] = { + [item.language]: { + subject: item.subject, + body: item.body + } + }; + } + }); + + parsedItems = Object.keys(parsedItems).map((type) => { + return _.extend({ + type: type + }, parsedItems[type]); + }); + + return parsedItems; + } } -export default AdminPanelEmailTemplates; \ No newline at end of file +export default AdminPanelEmailTemplates; diff --git a/client/src/app/admin/panel/settings/admin-panel-email-templates.scss b/client/src/app/admin/panel/settings/admin-panel-email-templates.scss new file mode 100644 index 00000000..340c7059 --- /dev/null +++ b/client/src/app/admin/panel/settings/admin-panel-email-templates.scss @@ -0,0 +1,21 @@ +.admin-panel-email-templates { + + &__save-button { + display: inline-block; + float: left; + } + + &__optional-buttons { + display: inline-block; + float: right; + } + + &__discard-button { + display: inline-block; + } + + &__recover-button { + display: inline-block; + margin-left: 10px; + } +} \ No newline at end of file diff --git a/client/src/data/fixtures/system-fixtures.js b/client/src/data/fixtures/system-fixtures.js index a699df1c..e4657991 100644 --- a/client/src/data/fixtures/system-fixtures.js +++ b/client/src/data/fixtures/system-fixtures.js @@ -21,7 +21,7 @@ module.exports = [ } }, { - path: '/staff/add-department', + path: '/system/add-department', time: 100, response: function () { return { @@ -31,7 +31,7 @@ module.exports = [ } }, { - path: '/staff/edit-department', + path: '/system/edit-department', time: 100, response: function () { return { @@ -41,7 +41,7 @@ module.exports = [ } }, { - path: '/staff/delete-department', + path: '/system/delete-department', time: 100, response: function () { return { @@ -49,5 +49,72 @@ module.exports = [ data: {} }; } + }, + { + path: '/system/edit-mail-template', + time: 100, + response: function () { + return { + status: 'success', + data: {} + }; + } + }, + { + path: '/system/recover-mail-template', + time: 100, + response: function () { + return { + status: 'success', + data: {} + }; + } + }, + { + path: '/system/get-mail-templates', + time: 100, + response: function () { + return { + status: 'success', + data: [ + { + type: 'USER_SINGUP', + language: 'en', + subject: 'Signup {{to}} - OpenSupports', + body : 'This is the user signup content {{name}}' + }, + { + type: 'USER_SINGUP', + language: 'es', + subject: 'Registrado {{to}} - OpenSupports', + body : 'Este es el contenido de signup {{name}}' + }, + { + type: 'USER_SINGUP', + language: 'de', + subject: 'Anmelden {{to}} - OpenSupports', + body : 'Dies ist der User Signup Content {{name}}' + }, + { + type: 'USER_EDIT_PASSWORD', + language: 'en', + subject: 'Password changed {{to}} - OpenSupports', + body : 'Password has been edited {{name}}' + }, + { + type: 'USER_EDIT_PASSWORD', + language: 'es', + subject: 'Password cambiado {{to}} - OpenSupports', + body : 'El password ha sido editado {{name}}' + }, + { + type: 'USER_EDIT_PASSWORD', + language: 'de', + subject: 'Passwort geƤndert {{to}} - OpenSupports', + body : 'Passwort wurde bearbeitet {{name}}' + } + ] + }; + } } ]; diff --git a/client/src/data/languages/en.js b/client/src/data/languages/en.js index b1472eee..2fb72996 100644 --- a/client/src/data/languages/en.js +++ b/client/src/data/languages/en.js @@ -118,6 +118,7 @@ export default { 'COMMENTS': 'Comments', 'DELETE_STAFF_MEMBER': 'Delete staff member', 'MAINTENANCE_MODE': 'Maintenance mode', + 'RECOVER_DEFAULT': 'Recover default', //VIEW DESCRIPTIONS 'CREATE_TICKET_DESCRIPTION': 'This is a form for creating tickets. Fill the form and send us your issues/doubts/suggestions. Our support system will answer it as soon as possible.', @@ -147,6 +148,7 @@ export default { 'MY_ACCOUNT_DESCRIPTION': 'Here you can edit information about you.', 'DEPARTMENTS_DESCRIPTION': 'A department is a group where the tickets can go. They are used to categorize the tickets. You can assign them to other staff members.', 'MAINTENANCE_MODE_DESCRIPTION': 'The support system is in maintenance mode, thus unavailable at the moment. We will come back as soon as possible.', + 'EMAIL_TEMPLATES_DESCRIPTION': 'Here you can edit the templates of the emails that will be sent to users. Remember that the double brackets curly braces indicate a variable value. For example, \'name\' represents the user\'s name.', //ERRORS 'EMAIL_OR_PASSWORD': 'Email or password invalid', @@ -186,5 +188,6 @@ export default { 'DEPARTMENTS_UPDATED': 'Departments have been updated successfully.', 'FAILED_EDIT_STAFF': 'An error occurred while trying to edit staff member.', 'EMAIL_BANNED_SUCCESSFULLY': 'Email has been banned successfully', - 'WILL_DELETE_STAFF': 'This staff member will be deleted and all its tickets will be unassigned.' + 'WILL_DELETE_STAFF': 'This staff member will be deleted and all its tickets will be unassigned.', + 'WILL_RECOVER_EMAIL_TEMPLATE': 'This email template will be recover to it\'s default value on this language.' };