mirror of
https://github.com/opensupports/opensupports.git
synced 2025-07-28 08:14:25 +02:00
Merge branch 'master' into 184-add-info-tooltip-form-fields
This commit is contained in:
commit
35efa73fdb
32
client/src/app-components/toggle-button.js
Normal file
32
client/src/app-components/toggle-button.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import i18n from 'lib-app/i18n';
|
||||||
|
|
||||||
|
class ToggleButton extends React.Component {
|
||||||
|
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
value: React.PropTypes.bool,
|
||||||
|
onChange: React.PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className="toggle-button" onClick={this.onClick.bind(this)}>
|
||||||
|
{this.props.value ? i18n('ON') : i18n('OFF')}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
onClick() {
|
||||||
|
if (this.props.onChange) {
|
||||||
|
this.props.onChange({
|
||||||
|
target: {
|
||||||
|
value: !this.props.value
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ToggleButton;
|
9
client/src/app-components/toggle-button.scss
Normal file
9
client/src/app-components/toggle-button.scss
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
@import "../scss/vars";
|
||||||
|
|
||||||
|
.toggle-button {
|
||||||
|
background-color: $light-grey;
|
||||||
|
width: 80px;
|
||||||
|
padding: 2px;
|
||||||
|
border-radius: 4px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
@ -1,14 +1,237 @@
|
|||||||
import React from 'react';
|
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 {
|
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() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="admin-panel-email-templates">
|
||||||
/admin/panel/settings/email-templates
|
<Header title={i18n('EMAIL_TEMPLATES')} description={i18n('EMAIL_TEMPLATES_DESCRIPTION')} />
|
||||||
|
{(this.state.loaded) ? this.renderContent() : this.renderLoading()}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderContent() {
|
||||||
|
return (
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-3">
|
||||||
|
<Listing {...this.getListingProps()}/>
|
||||||
|
</div>
|
||||||
|
<div className="col-md-9">
|
||||||
|
<FormField label={i18n('LANGUAGE')} decorator={LanguageSelector} value={this.state.language} onChange={event => this.onItemChange(this.state.selectedIndex, event.target.value)} fieldProps={{
|
||||||
|
type: 'allowed',
|
||||||
|
size: 'medium'
|
||||||
|
}}/>
|
||||||
|
<Form {...this.getFormProps()}>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-7">
|
||||||
|
<FormField label={i18n('TITLE')} name="title" validation="TITLE" required fieldProps={{size: 'large'}}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<FormField label={i18n('CONTENT')} name="content" validation="TEXT_AREA" required field="textarea" />
|
||||||
|
<div className="admin-panel-email-templates__actions">
|
||||||
|
<div className="admin-panel-email-templates__save-button">
|
||||||
|
<SubmitButton type="secondary" size="small">{i18n('SAVE')}</SubmitButton>
|
||||||
|
</div>
|
||||||
|
<div className="admin-panel-email-templates__optional-buttons">
|
||||||
|
{(this.state.edited) ? this.renderDiscardButton() : null}
|
||||||
|
<div className="admin-panel-email-templates__recover-button">
|
||||||
|
<Button onClick={this.onRecoverClick.bind(this)} size="medium">
|
||||||
|
{i18n('RECOVER_DEFAULT')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderLoading() {
|
||||||
|
return (
|
||||||
|
<div className="admin-panel-email-templates__loading">
|
||||||
|
<Loading backgrounded size="large"/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderDiscardButton() {
|
||||||
|
return (
|
||||||
|
<div className="admin-panel-email-templates__discard-button">
|
||||||
|
<Button onClick={this.onDiscardChangesClick.bind(this)} size="medium">
|
||||||
|
{i18n('DISCARD_CHANGES')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
export default AdminPanelEmailTemplates;
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -1,14 +1,230 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import _ from 'lodash';
|
||||||
|
import languageList from 'data/language-list';
|
||||||
|
|
||||||
|
import Form from 'core-components/form';
|
||||||
|
import FormField from 'core-components/form-field';
|
||||||
|
import Header from 'core-components/header';
|
||||||
|
import SubmitButton from 'core-components/submit-button';
|
||||||
|
import Button from 'core-components/button';
|
||||||
|
import Message from 'core-components/message';
|
||||||
|
|
||||||
|
import API from 'lib-app/api-call';
|
||||||
|
import i18n from 'lib-app/i18n';
|
||||||
|
import LanguageSelector from 'app-components/language-selector';
|
||||||
|
import ToggleButton from 'app-components/toggle-button';
|
||||||
|
|
||||||
class AdminPanelSystemPreferences extends React.Component {
|
class AdminPanelSystemPreferences extends React.Component {
|
||||||
|
|
||||||
|
state = {
|
||||||
|
loading: true,
|
||||||
|
message: null,
|
||||||
|
values: {
|
||||||
|
'maintenance': false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.recoverSettings();
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="admin-panel-system-preferences">
|
||||||
/admin/panel/settings/system-preferences
|
<Header title={i18n('SYSTEM_PREFERENCES')} description="Here you can adjust your system preferences :)"/>
|
||||||
|
<Form values={this.state.values} onChange={values => this.setState({values, message: null})} onSubmit={this.onSubmit.bind(this)} loading={this.state.loading}>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-12">
|
||||||
|
<div className="admin-panel-system-preferences__maintenance">
|
||||||
|
<span>Maintenance Mode</span>
|
||||||
|
<FormField className="admin-panel-system-preferences__maintenance-field" name="maintenance-mode" decorator={ToggleButton}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-12">
|
||||||
|
<span className="separator" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-6">
|
||||||
|
<FormField label={i18n('SUPPORT_CENTER_URL')} fieldProps={{size: 'large'}} name="url"/>
|
||||||
|
<FormField label={i18n('SUPPORT_CENTER_LAYOUT')} fieldProps={{size: 'large', items: [{content: i18n('BOXED')}, {content: i18n('FULL_WIDTH')}]}} field="select" name="layout"/>
|
||||||
|
</div>
|
||||||
|
<div className="col-md-6">
|
||||||
|
<FormField label={i18n('SUPPORT_CENTER_TITLE')} fieldProps={{size: 'large'}} name="title"/>
|
||||||
|
<FormField label={i18n('DEFAULT_TIMEZONE')} fieldProps={{size: 'large'}} name="time-zone"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-12">
|
||||||
|
<span className="separator" />
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-6">
|
||||||
|
<FormField label={i18n('NOREPLY_EMAIL')} fieldProps={{size: 'large'}} name="no-reply-email"/>
|
||||||
|
<FormField label={i18n('SMTP_USER')} fieldProps={{size: 'large'}} name="smtp-user"/>
|
||||||
|
</div>
|
||||||
|
<div className="col-md-6">
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-9">
|
||||||
|
<FormField label={i18n('SMTP_SERVER')} fieldProps={{size: 'large'}} name="smtp-host"/>
|
||||||
|
<FormField label={i18n('SMTP_PASSWORD')} fieldProps={{size: 'large', password: true}} name="smtp-pass"/>
|
||||||
|
</div>
|
||||||
|
<div className="col-md-3">
|
||||||
|
<FormField label={i18n('PORT')} fieldProps={{size: 'auto'}} name="smtp-port"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-12">
|
||||||
|
<span className="separator" />
|
||||||
|
</div>
|
||||||
|
<div className="col-md-6">
|
||||||
|
<div className="row admin-panel-system-preferences__languages">
|
||||||
|
<div className="col-md-6 admin-panel-system-preferences__languages-allowed">
|
||||||
|
<div>{i18n('ALLOWED_LANGUAGES')}</div>
|
||||||
|
<FormField name="allowedLanguages" field="checkbox-group" fieldProps={{items: this.getLanguageList()}} />
|
||||||
|
</div>
|
||||||
|
<div className="col-md-6 admin-panel-system-preferences__languages-supported">
|
||||||
|
<div>{i18n('SUPPORTED_LANGUAGES')}</div>
|
||||||
|
<FormField name="supportedLanguages" field="checkbox-group" fieldProps={{items: this.getLanguageList()}} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-md-6">
|
||||||
|
<FormField label={i18n('RECAPTCHA_PUBLIC_KEY')} fieldProps={{size: 'large'}} name="reCaptchaKey"/>
|
||||||
|
<FormField label={i18n('RECAPTCHA_PRIVATE_KEY')} fieldProps={{size: 'large'}} name="reCaptchaPrivate"/>
|
||||||
|
<div className="admin-panel-system-preferences__file-attachments">
|
||||||
|
<span>{i18n('ALLOW_FILE_ATTACHMENTS')}</span>
|
||||||
|
<FormField className="admin-panel-system-preferences__file-attachments-field" name="allow-attachments" decorator={ToggleButton}/>
|
||||||
|
</div>
|
||||||
|
<div className="admin-panel-system-preferences__max-size">
|
||||||
|
<span>{i18n('MAX_SIZE_KB')}</span>
|
||||||
|
<FormField className="admin-panel-system-preferences__max-size-field" fieldProps={{size: 'small'}} name="max-size"/>
|
||||||
|
</div>
|
||||||
|
<FormField className="admin-panel-system-preferences__default-language-field" name="language" label={i18n('DEFAULT_LANGUAGE')} decorator={LanguageSelector} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-12">
|
||||||
|
<span className="separator" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-4 col-md-offset-2">
|
||||||
|
<SubmitButton type="secondary">{i18n('UPDATE_SETTINGS')}</SubmitButton>
|
||||||
|
</div>
|
||||||
|
<div className="col-md-4">
|
||||||
|
<Button onClick={this.onDiscardChangesSubmit.bind(this)}>{i18n('DISCARD_CHANGES')}</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
{this.renderMessage()}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderMessage() {
|
||||||
|
switch (this.state.message) {
|
||||||
|
case 'success':
|
||||||
|
return <Message className="admin-panel-system-preferences__message" type="success">{i18n('SETTINGS_UPDATED')}</Message>;
|
||||||
|
case 'fail':
|
||||||
|
return <Message className="admin-panel-system-preferences__message" type="error">{i18n('ERROR_UPDATING_SETTINGS')}</Message>;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit(form) {
|
||||||
|
let fullList = Object.keys(languageList);
|
||||||
|
this.setState({loading: true});
|
||||||
|
|
||||||
|
API.call({
|
||||||
|
path: '/system/edit-settings',
|
||||||
|
data: {
|
||||||
|
'language': form.language,
|
||||||
|
'recaptcha-public': form.reCaptchaKey,
|
||||||
|
'recaptcha-private': form.reCaptchaPrivate,
|
||||||
|
'url': form['url'],
|
||||||
|
'title': form['title'],
|
||||||
|
'layout': form['layout'] == 1 ? 'Full width' : 'Boxed',
|
||||||
|
'time-zone': form['time-zone'],
|
||||||
|
'no-reply-email': form['no-reply-email'],
|
||||||
|
'smtp-host': form['smtp-host'],
|
||||||
|
'smtp-port': form['smtp-port'],
|
||||||
|
'smtp-user': form['smtp-user'],
|
||||||
|
'smtp-pass': form['smtp-password'],
|
||||||
|
'maintenance-mode': form['maintenance-mode'],
|
||||||
|
'allow-attachments': form['allow-attachments'],
|
||||||
|
'max-size': form['max-size'],
|
||||||
|
'allowedLanguages': JSON.stringify(form.allowedLanguages.map(index => fullList[index])),
|
||||||
|
'supportedLanguages': JSON.stringify(form.supportedLanguages.map(index => fullList[index]))
|
||||||
|
}
|
||||||
|
}).then(this.onSubmitSuccess.bind(this)).catch(() => this.setState({loading: false, message: 'fail'}));
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmitSuccess() {
|
||||||
|
this.recoverSettings();
|
||||||
|
this.setState({
|
||||||
|
message: 'success',
|
||||||
|
loading: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getLanguageList() {
|
||||||
|
return Object.keys(languageList).map(key => languageList[key].name);
|
||||||
|
}
|
||||||
|
|
||||||
|
recoverSettings() {
|
||||||
|
API.call({
|
||||||
|
path: '/system/get-settings',
|
||||||
|
data: {
|
||||||
|
allSettings: true
|
||||||
|
}
|
||||||
|
}).then(this.onRecoverSettingsSuccess.bind(this)).catch(this.onRecoverSettingsFail.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
onRecoverSettingsSuccess(result) {
|
||||||
|
let fullList = Object.keys(languageList);
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
values: {
|
||||||
|
'language': result.data.language,
|
||||||
|
'reCaptchaKey': result.data.reCaptchaKey,
|
||||||
|
'reCaptchaPrivate': result.data.reCaptchaPrivate,
|
||||||
|
'url': result.data['url'],
|
||||||
|
'title': result.data['title'],
|
||||||
|
'layout': result.data['layout'] == 'Full width' ? 1 : 0,
|
||||||
|
'time-zone': result.data['time-zone'],
|
||||||
|
'no-reply-email': result.data['no-reply-email'],
|
||||||
|
'smtp-host': result.data['smtp-host'],
|
||||||
|
'smtp-port': result.data['smtp-port'],
|
||||||
|
'smtp-user': result.data['smtp-user'],
|
||||||
|
'smtp-pass': '',
|
||||||
|
'maintenance-mode': result.data['maintenance-mode'],
|
||||||
|
'allow-attachments': result.data['allow-attachments'],
|
||||||
|
'max-size': result.data['max-size'],
|
||||||
|
'allowedLanguages': result.data.allowedLanguages.map(lang => (_.indexOf(fullList, lang))),
|
||||||
|
'supportedLanguages': result.data.supportedLanguages.map(lang => (_.indexOf(fullList, lang)))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onRecoverSettingsFail(result) {
|
||||||
|
this.setState({
|
||||||
|
message: 'error'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onDiscardChangesSubmit(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.setState({loading: true});
|
||||||
|
this.recoverSettings();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AdminPanelSystemPreferences;
|
export default AdminPanelSystemPreferences;
|
@ -0,0 +1,54 @@
|
|||||||
|
@import "../../../../scss/vars";
|
||||||
|
|
||||||
|
.admin-panel-system-preferences {
|
||||||
|
|
||||||
|
&__maintenance {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__maintenance-field {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__file-attachments {
|
||||||
|
margin-top: 8px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__file-attachments-field {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__max-size {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__max-size-field {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__languages {
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
&-allowed {
|
||||||
|
text-align: left;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-supported {
|
||||||
|
text-align: left;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__default-language-field {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__message {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
}
|
@ -16,6 +16,7 @@ const Menu = require('core-components/menu');
|
|||||||
const Tooltip = require('core-components/tooltip');
|
const Tooltip = require('core-components/tooltip');
|
||||||
const Table = require('core-components/table');
|
const Table = require('core-components/table');
|
||||||
const InfoTooltip = require('core-components/info-tooltip');
|
const InfoTooltip = require('core-components/info-tooltip');
|
||||||
|
const ToggleButton = require('app-components/toggle-button');
|
||||||
|
|
||||||
let dropDownItems = [{content: 'English'}, {content: 'Spanish'}, {content: 'German'}, {content: 'Portuguese'}, {content: 'Japanese'}];
|
let dropDownItems = [{content: 'English'}, {content: 'Spanish'}, {content: 'German'}, {content: 'Portuguese'}, {content: 'Japanese'}];
|
||||||
let secondaryMenuItems = [
|
let secondaryMenuItems = [
|
||||||
|
@ -14,7 +14,7 @@ class Input extends React.Component {
|
|||||||
value: React.PropTypes.string,
|
value: React.PropTypes.string,
|
||||||
validation: React.PropTypes.string,
|
validation: React.PropTypes.string,
|
||||||
onChange: React.PropTypes.func,
|
onChange: React.PropTypes.func,
|
||||||
size: React.PropTypes.oneOf(['small', 'medium', 'large']),
|
size: React.PropTypes.oneOf(['small', 'medium', 'large', 'auto']),
|
||||||
password: React.PropTypes.bool,
|
password: React.PropTypes.bool,
|
||||||
required: React.PropTypes.bool,
|
required: React.PropTypes.bool,
|
||||||
icon: React.PropTypes.string,
|
icon: React.PropTypes.string,
|
||||||
|
@ -19,6 +19,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&_auto {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
&_small {
|
&_small {
|
||||||
width: 200px;
|
width: 200px;
|
||||||
}
|
}
|
||||||
|
@ -2,26 +2,66 @@ module.exports = [
|
|||||||
{
|
{
|
||||||
path: '/system/get-settings',
|
path: '/system/get-settings',
|
||||||
time: 1000,
|
time: 1000,
|
||||||
response: function () {
|
response: function (params) {
|
||||||
return {
|
if(params && params.allSettings) {
|
||||||
status: 'success',
|
return {
|
||||||
data: {
|
status: 'success',
|
||||||
'language': 'en',
|
data: {
|
||||||
'reCaptchaKey': '6LfM5CYTAAAAAGLz6ctpf-hchX2_l0Ge-Bn-n8wS',
|
'language': 'en',
|
||||||
'maintenance-mode': false,
|
'reCaptchaKey': '6LfM5CYTAAAAAGLz6ctpf-hchX2_l0Ge-Bn-n8wS',
|
||||||
'departments': [
|
'reCaptchaPrivate': 'LALA',
|
||||||
{id: 1, name: 'Sales Support', owners: 2},
|
'url': 'hola@lala.com',
|
||||||
{id: 2, name: 'Technical Issues', owners: 5},
|
'title': 'Very Cool',
|
||||||
{id: 3, name: 'System and Administration', owners: 0}
|
'layout': 'Boxed',
|
||||||
],
|
'time-zone': 3,
|
||||||
'allowedLanguages': ['en', 'es', 'de', 'fr', 'pt', 'jp', 'ru', 'cn', 'in', 'tr'],
|
'no-reply-email': 'shitr@post.com',
|
||||||
'supportedLanguages': ['en', 'es', 'de']
|
'smtp-host': 'localhost',
|
||||||
}
|
'smtp-port': '7070',
|
||||||
};
|
'smtp-user': 'Wesa',
|
||||||
|
'maintenance-mode': false,
|
||||||
|
'allow-attachments': true,
|
||||||
|
'max-size': 500,
|
||||||
|
'departments': [
|
||||||
|
{id: 1, name: 'Sales Support', owners: 2},
|
||||||
|
{id: 2, name: 'Technical Issues', owners: 5},
|
||||||
|
{id: 3, name: 'System and Administration', owners: 0}
|
||||||
|
],
|
||||||
|
'allowedLanguages': ['en', 'es', 'de', 'fr', 'pt', 'jp', 'ru', 'cn', 'in', 'tr'],
|
||||||
|
'supportedLanguages': ['en', 'es', 'de']
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
status: 'success',
|
||||||
|
data: {
|
||||||
|
'language': 'en',
|
||||||
|
'reCaptchaKey': '6LfM5CYTAAAAAGLz6ctpf-hchX2_l0Ge-Bn-n8wS',
|
||||||
|
'maintenance-mode': false,
|
||||||
|
'departments': [
|
||||||
|
{id: 1, name: 'Sales Support', owners: 2},
|
||||||
|
{id: 2, name: 'Technical Issues', owners: 5},
|
||||||
|
{id: 3, name: 'System and Administration', owners: 0}
|
||||||
|
],
|
||||||
|
'allowedLanguages': ['en', 'es', 'de', 'fr', 'pt', 'jp', 'ru', 'cn', 'in', 'tr'],
|
||||||
|
'supportedLanguages': ['en', 'es', 'de']
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/staff/add-department',
|
path: '/system/edit-settings',
|
||||||
|
time: 50,
|
||||||
|
response: function() {
|
||||||
|
return {
|
||||||
|
status: 'success',
|
||||||
|
data: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/system/add-department',
|
||||||
time: 100,
|
time: 100,
|
||||||
response: function () {
|
response: function () {
|
||||||
return {
|
return {
|
||||||
@ -31,7 +71,7 @@ module.exports = [
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/staff/edit-department',
|
path: '/system/edit-department',
|
||||||
time: 100,
|
time: 100,
|
||||||
response: function () {
|
response: function () {
|
||||||
return {
|
return {
|
||||||
@ -41,7 +81,7 @@ module.exports = [
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/staff/delete-department',
|
path: '/system/delete-department',
|
||||||
time: 100,
|
time: 100,
|
||||||
response: function () {
|
response: function () {
|
||||||
return {
|
return {
|
||||||
@ -49,5 +89,72 @@ module.exports = [
|
|||||||
data: {}
|
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}}'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
@ -121,6 +121,29 @@ export default {
|
|||||||
'COMMENTS': 'Comments',
|
'COMMENTS': 'Comments',
|
||||||
'DELETE_STAFF_MEMBER': 'Delete staff member',
|
'DELETE_STAFF_MEMBER': 'Delete staff member',
|
||||||
'MAINTENANCE_MODE': 'Maintenance mode',
|
'MAINTENANCE_MODE': 'Maintenance mode',
|
||||||
|
'RECOVER_DEFAULT': 'Recover default',
|
||||||
|
'SUPPORT_CENTER_URL': 'Support Center URL',
|
||||||
|
'SUPPORT_CENTER_TITLE': 'Support Center Title',
|
||||||
|
'SUPPORT_CENTER_LAYOUT': 'Support Center Layout',
|
||||||
|
'DEFAULT_TIMEZONE': 'Default Timezone',
|
||||||
|
'NOREPLY_EMAIL': 'Noreply Email',
|
||||||
|
'SMTP_USER': 'SMTP User',
|
||||||
|
'SMTP_SERVER': 'SMTP Server',
|
||||||
|
'SMTP_PASSWORD': 'SMTP Password',
|
||||||
|
'PORT': 'Port',
|
||||||
|
'RECAPTCHA_PUBLIC_KEY': 'Recaptcha Public Key',
|
||||||
|
'RECAPTCHA_PRIVATE_KEY': 'Recaptcha Private Key',
|
||||||
|
'ALLOW_FILE_ATTACHMENTS': 'Allow file attachments',
|
||||||
|
'MAX_SIZE_KB': 'Max Size (KB)',
|
||||||
|
'UPDATE_SETTINGS': 'Update settings',
|
||||||
|
'DEFAULT_LANGUAGE': 'Default Language',
|
||||||
|
'SUPPORTED_LANGUAGES': 'Supported Languages',
|
||||||
|
'ALLOWED_LANGUAGES': 'Allowed Languages',
|
||||||
|
'SETTINGS_UPDATED': 'Settings have been updated',
|
||||||
|
'ON': 'On',
|
||||||
|
'OFF': 'Off',
|
||||||
|
'BOXED': 'Boxed',
|
||||||
|
'FULL_WIDTH': 'Full width',
|
||||||
|
|
||||||
//VIEW DESCRIPTIONS
|
//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.',
|
'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.',
|
||||||
@ -150,6 +173,7 @@ export default {
|
|||||||
'MY_ACCOUNT_DESCRIPTION': 'Here you can edit information about you.',
|
'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.',
|
'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.',
|
'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
|
//ERRORS
|
||||||
'EMAIL_OR_PASSWORD': 'Email or password invalid',
|
'EMAIL_OR_PASSWORD': 'Email or password invalid',
|
||||||
@ -189,5 +213,6 @@ export default {
|
|||||||
'DEPARTMENTS_UPDATED': 'Departments have been updated successfully.',
|
'DEPARTMENTS_UPDATED': 'Departments have been updated successfully.',
|
||||||
'FAILED_EDIT_STAFF': 'An error occurred while trying to edit staff member.',
|
'FAILED_EDIT_STAFF': 'An error occurred while trying to edit staff member.',
|
||||||
'EMAIL_BANNED_SUCCESSFULLY': 'Email has been banned successfully',
|
'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.'
|
||||||
};
|
};
|
||||||
|
@ -26,7 +26,8 @@ class EditSettingsController extends Controller {
|
|||||||
'layout',
|
'layout',
|
||||||
'allow-attachments',
|
'allow-attachments',
|
||||||
'max-size',
|
'max-size',
|
||||||
'system-title'
|
'title',
|
||||||
|
'url'
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach($settings as $setting) {
|
foreach($settings as $setting) {
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
<?php
|
|
||||||
use Respect\Validation\Validator as DataValidator;
|
|
||||||
|
|
||||||
class GetSettingController extends Controller {
|
|
||||||
const PATH = '/get-setting';
|
|
||||||
|
|
||||||
public function validations() {
|
|
||||||
return [
|
|
||||||
'permission' => 'any',
|
|
||||||
'requestData' => [
|
|
||||||
'name' => [
|
|
||||||
'validation' => DataValidator::length(4),
|
|
||||||
'error' => ERRORS::INVALID_SETTING
|
|
||||||
]
|
|
||||||
]
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function handler() {
|
|
||||||
$setting = Setting::getSetting(Controller::request('name'));
|
|
||||||
|
|
||||||
if (!$setting->isNull()) {
|
|
||||||
Response::respondSuccess([
|
|
||||||
'setting' => $setting->value
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
Response::respondError(ERRORS::INVALID_SETTING);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -11,17 +11,43 @@ class GetSettingsController extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function handler() {
|
public function handler() {
|
||||||
Response::respondSuccess([
|
|
||||||
'language' => Setting::getSetting('language')->getValue(),
|
if(Controller::request('allSettings') && Controller::isStaffLogged(3)) {
|
||||||
'reCaptchaKey' => Setting::getSetting('recaptcha-public')->getValue(),
|
$settingsList = [
|
||||||
'time-zone' => Setting::getSetting('time-zone')->getValue(),
|
'language' => Setting::getSetting('language')->getValue(),
|
||||||
'maintenance-mode' => Setting::getSetting('maintenance-mode')->getValue(),
|
'reCaptchaKey' => Setting::getSetting('recaptcha-public')->getValue(),
|
||||||
'layout' => Setting::getSetting('layout')->getValue(),
|
'reCaptchaPrivate' => Setting::getSetting('recaptcha-private')->getValue(),
|
||||||
'allow-attachments' => Setting::getSetting('allow-attachments')->getValue(),
|
'time-zone' => Setting::getSetting('time-zone')->getValue(),
|
||||||
'max-size' => Setting::getSetting('max-size')->getValue(),
|
'maintenance-mode' => Setting::getSetting('maintenance-mode')->getValue(),
|
||||||
'departments' => Department::getDepartmentNames(),
|
'layout' => Setting::getSetting('layout')->getValue(),
|
||||||
'supportedLanguages' => Language::getSupportedLanguages(),
|
'allow-attachments' => Setting::getSetting('allow-attachments')->getValue(),
|
||||||
'allowedLanguages' => Language::getAllowedLanguages()
|
'max-size' => Setting::getSetting('max-size')->getValue(),
|
||||||
]);
|
'url' => Setting::getSetting('url')->getValue(),
|
||||||
|
'title' => Setting::getSetting('title')->getValue(),
|
||||||
|
'no-reply-email' => Setting::getSetting('no-reply-email')->getValue(),
|
||||||
|
'smtp-port' => Setting::getSetting('smtp-port')->getValue(),
|
||||||
|
'smtp-host' => Setting::getSetting('smtp-port')->getValue(),
|
||||||
|
'smtp-user' => Setting::getSetting('smtp-port')->getValue(),
|
||||||
|
'departments' => Department::getDepartmentNames(),
|
||||||
|
'supportedLanguages' => Language::getSupportedLanguages(),
|
||||||
|
'allowedLanguages' => Language::getAllowedLanguages()
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$settingsList = [
|
||||||
|
'language' => Setting::getSetting('language')->getValue(),
|
||||||
|
'reCaptchaKey' => Setting::getSetting('recaptcha-public')->getValue(),
|
||||||
|
'time-zone' => Setting::getSetting('time-zone')->getValue(),
|
||||||
|
'maintenance-mode' => Setting::getSetting('maintenance-mode')->getValue(),
|
||||||
|
'layout' => Setting::getSetting('layout')->getValue(),
|
||||||
|
'allow-attachments' => Setting::getSetting('allow-attachments')->getValue(),
|
||||||
|
'max-size' => Setting::getSetting('max-size')->getValue(),
|
||||||
|
'title' => Setting::getSetting('title')->getValue(),
|
||||||
|
'departments' => Department::getDepartmentNames(),
|
||||||
|
'supportedLanguages' => Language::getSupportedLanguages(),
|
||||||
|
'allowedLanguages' => Language::getAllowedLanguages()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
Response::respondSuccess($settingsList);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -39,7 +39,8 @@ class InitSettingsController extends Controller {
|
|||||||
'layout' => 'boxed',
|
'layout' => 'boxed',
|
||||||
'allow-attachments' => 0,
|
'allow-attachments' => 0,
|
||||||
'max-size' => 0,
|
'max-size' => 0,
|
||||||
'system-title' => 'Support Center'
|
'title' => 'Support Center',
|
||||||
|
'url' => 'http://www.opensupports.com/support'
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
<?php
|
|
||||||
use Respect\Validation\Validator as DataValidator;
|
|
||||||
|
|
||||||
class GetSettingController extends Controller {
|
|
||||||
const PATH = '/get-setting';
|
|
||||||
|
|
||||||
public function validations() {
|
|
||||||
return [
|
|
||||||
'permission' => 'any',
|
|
||||||
'requestData' => [
|
|
||||||
'name' => [
|
|
||||||
'validation' => DataValidator::length(4),
|
|
||||||
'error' => ERRORS::INVALID_SETTING
|
|
||||||
],
|
|
||||||
'value' => [
|
|
||||||
'validation' => DataValidator::length(4),
|
|
||||||
'error' => ERRORS::INVALID_SETTING
|
|
||||||
]
|
|
||||||
]
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function handler() {
|
|
||||||
$setting = Setting::getSetting(Controller::request('name'));
|
|
||||||
|
|
||||||
if (!$setting->isNull()) {
|
|
||||||
$setting->value = Controller::request('value');
|
|
||||||
$setting->store();
|
|
||||||
|
|
||||||
Response::respondSuccess();
|
|
||||||
} else {
|
|
||||||
Response::respondError(ERRORS::INVALID_SETTING);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user