diff --git a/client/src/app/admin/panel/dashboard/admin-panel-my-account.js b/client/src/app/admin/panel/dashboard/admin-panel-my-account.js
index 2f53b03d..336bd442 100644
--- a/client/src/app/admin/panel/dashboard/admin-panel-my-account.js
+++ b/client/src/app/admin/panel/dashboard/admin-panel-my-account.js
@@ -29,6 +29,7 @@ class AdminPanelMyAccount extends React.Component {
profilePic: this.props.userProfilePic,
level: this.props.userLevel * 1,
departments: this.props.userDepartments,
+ sendEmailOnNewTicket: this.props.userSendEmailOnNewTicket,
onChange: () => this.props.dispatch(SessionActions.getUserData(null, null, true))
};
}
diff --git a/client/src/app/admin/panel/staff/staff-editor.js b/client/src/app/admin/panel/staff/staff-editor.js
index a9c0f93c..9b55cff6 100644
--- a/client/src/app/admin/panel/staff/staff-editor.js
+++ b/client/src/app/admin/panel/staff/staff-editor.js
@@ -27,6 +27,7 @@ class StaffEditor extends React.Component {
level: React.PropTypes.number.isRequired,
tickets: React.PropTypes.array.isRequired,
departments: React.PropTypes.array.isRequired,
+ sendEmailOnNewTicket: React.PropTypes.bool,
onChange: React.PropTypes.func,
onDelete: React.PropTypes.func
};
@@ -40,7 +41,8 @@ class StaffEditor extends React.Component {
level: this.props.level - 1,
message: null,
loadingPicture: false,
- departments: this.getUserDepartments()
+ departments: this.getUserDepartments(),
+ sendEmailOnNewTicket: this.props.sendEmailOnNewTicket
};
render() {
@@ -95,7 +97,7 @@ class StaffEditor extends React.Component {
{i18n('UPDATE_PASSWORD')}
- {(!this.props.myAccount) ? this.renderLevelForm() : null}
+ {(this.props.myAccount) ? this.renderSendEmailOnNewTicketForm() : this.renderLevelForm()}
@@ -137,6 +139,9 @@ class StaffEditor extends React.Component {
case 'DEPARTMENTS':
message = 'DEPARTMENTS_UPDATED';
break;
+ case 'EMAIL_SETTING':
+ message = 'EMAIL_SETTING_UPDATED';
+ break;
case 'FAIL':
message = 'FAILED_EDIT_STAFF';
break;
@@ -145,6 +150,18 @@ class StaffEditor extends React.Component {
return {i18n(message)};
}
+ renderSendEmailOnNewTicketForm() {
+ return (
+
+
+
+
+ );
+ }
+
renderLevelForm() {
return (
@@ -273,6 +290,7 @@ class StaffEditor extends React.Component {
path: '/staff/edit',
data: {
staffId: this.props.staffId,
+ sendEmailOnNewTicket: form.sendEmailOnNewTicket,
email: form.email,
password: form.password,
level: (form.level !== undefined) ? form.level + 1 : null,
diff --git a/client/src/app/admin/panel/staff/staff-editor.scss b/client/src/app/admin/panel/staff/staff-editor.scss
index f3bbd162..6ddfa0ff 100644
--- a/client/src/app/admin/panel/staff/staff-editor.scss
+++ b/client/src/app/admin/panel/staff/staff-editor.scss
@@ -141,10 +141,17 @@
&__update-email,
&__update-password,
- &__update-level {
+ &__update-level,
+ &__update-email-setting {
position: relative;
}
+ &__update-email-setting {
+ margin-top: 28px;
+ margin-bottom: 20px;
+ text-align: left;
+ }
+
&__departments {
border: 1px solid $grey;
padding: 20px 50px;
diff --git a/client/src/app/main/dashboard/dashboard-create-ticket/create-ticket-form.js b/client/src/app/main/dashboard/dashboard-create-ticket/create-ticket-form.js
index 35dc66fb..c04ae6b4 100644
--- a/client/src/app/main/dashboard/dashboard-create-ticket/create-ticket-form.js
+++ b/client/src/app/main/dashboard/dashboard-create-ticket/create-ticket-form.js
@@ -37,7 +37,7 @@ class CreateTicketForm extends React.Component {
departmentIndex: 0,
email: '',
name: '',
- language: 'en'
+ language: this.props.language
}
};
@@ -158,6 +158,7 @@ class CreateTicketForm extends React.Component {
export default connect((store) => {
return {
+ language: store.config.language,
allowAttachments: store.config['allow-attachments']
};
})(CreateTicketForm);
diff --git a/client/src/core-components/form-field.js b/client/src/core-components/form-field.js
index c6e59b14..c1e38ef3 100644
--- a/client/src/core-components/form-field.js
+++ b/client/src/core-components/form-field.js
@@ -134,10 +134,10 @@ class FormField extends React.Component {
if (this.props.field === 'select') {
props.selectedIndex = this.props.value;
- } else {
- props.value = this.props.value;
}
+ props.value = this.props.value;
+
return props;
}
diff --git a/client/src/data/fixtures/staff-fixtures.js b/client/src/data/fixtures/staff-fixtures.js
index 77e47603..f86ea68a 100644
--- a/client/src/data/fixtures/staff-fixtures.js
+++ b/client/src/data/fixtures/staff-fixtures.js
@@ -11,6 +11,7 @@ module.exports = [
name: 'Emilia Clarke',
email: 'staff@opensupports.com',
profilePic: '',
+ sendEmailOnNewTicket: true,
level: 3,
staff: true,
departments: [
diff --git a/client/src/data/fixtures/system-fixtures.js b/client/src/data/fixtures/system-fixtures.js
index 58b95da4..50e1d5d8 100644
--- a/client/src/data/fixtures/system-fixtures.js
+++ b/client/src/data/fixtures/system-fixtures.js
@@ -18,6 +18,7 @@ module.exports = [
'smtp-host': 'localhost',
'smtp-port': '7070',
'smtp-user': 'Wesa',
+ 'session-prefix': 'opensupports-z6ctpq2winvfhchX2_',
'maintenance-mode': false,
'allow-attachments': true,
'max-size': 500,
diff --git a/client/src/data/fixtures/user-fixtures.js b/client/src/data/fixtures/user-fixtures.js
index 2ff9801b..65bb8fa2 100644
--- a/client/src/data/fixtures/user-fixtures.js
+++ b/client/src/data/fixtures/user-fixtures.js
@@ -156,6 +156,7 @@ module.exports = [
name: 'Kurt Gödel',
email: 'kurt@currycurrylady.hs',
verified: false,
+ sendEmailOnNewTicket: true,
tickets: _.times(13).map(() => {
return {
ticketNumber: '118551',
@@ -375,6 +376,7 @@ module.exports = [
data: {
name: 'Haskell Curry',
email: 'haskell@lambda.com',
+ sendEmailOnNewTicket: true,
tickets: [
{
ticketNumber: '445441',
diff --git a/client/src/data/languages/cn.js b/client/src/data/languages/cn.js
index 278123ef..8ebd5be4 100644
--- a/client/src/data/languages/cn.js
+++ b/client/src/data/languages/cn.js
@@ -176,6 +176,8 @@ export default {
'HOME': '家',
'TICKET_NUMBER': '票號',
'NEXT': '下一個',
+ 'SEND_EMAIL_ON_NEW_TICKET': '电子邮件为每个新票',
+ 'UPDATE': '更新',
'CHART_CREATE_TICKET': '已創建門票',
'CHART_CLOSE': '門票已關閉',
diff --git a/client/src/data/languages/de.js b/client/src/data/languages/de.js
index 1ad60689..2586cf66 100644
--- a/client/src/data/languages/de.js
+++ b/client/src/data/languages/de.js
@@ -176,6 +176,8 @@ export default {
'HOME': 'Zuhause',
'TICKET_NUMBER': 'Ticketnummer',
'NEXT': 'Nächster',
+ 'SEND_EMAIL_ON_NEW_TICKET': 'Email für jedes neues Ticket',
+ 'UPDATE': 'Aktualisierung',
'CHART_CREATE_TICKET': 'Tickets erstellt',
'CHART_CLOSE': 'Tickets geschlossen',
diff --git a/client/src/data/languages/en.js b/client/src/data/languages/en.js
index 1fbf0306..1f373680 100644
--- a/client/src/data/languages/en.js
+++ b/client/src/data/languages/en.js
@@ -176,6 +176,8 @@ export default {
'HOME': 'Home',
'TICKET_NUMBER': 'Ticket number',
'NEXT': 'Next',
+ 'SEND_EMAIL_ON_NEW_TICKET': 'Send email on new ticket',
+ 'UPDATE': 'Update',
'CHART_CREATE_TICKET': 'Tickets created',
'CHART_CLOSE': 'Tickets closed',
diff --git a/client/src/data/languages/es.js b/client/src/data/languages/es.js
index fd7f8584..13273cbb 100644
--- a/client/src/data/languages/es.js
+++ b/client/src/data/languages/es.js
@@ -176,6 +176,8 @@ export default {
'HOME': 'Inicio',
'TICKET_NUMBER': 'Número de Ticket',
'NEXT': 'Siguiente',
+ 'SEND_EMAIL_ON_NEW_TICKET': 'Enviar email por cada nuevo ticket',
+ 'UPDATE': 'Actualizar',
'CHART_CREATE_TICKET': 'Tickets creados',
'CHART_CLOSE': 'Tickets cerrados',
@@ -248,7 +250,7 @@ export default {
'TICKETS_DESCRIPTION': 'Envíe un ticket a través de nuestro centro de soporte y obtenga respuesta de sus dudas, sugerencias y problemas.',
'ARTICLES_DESCRIPTION': 'Echa un vistazo a nuestros artículos sobre temas comunes, guías y documentación.',
'ACCOUNT_DESCRIPTION': 'Todos sus tickets están almacenados en el perfil de su cuenta. Mantenga un registro de todos los tickets envíados a nuestro equipo de soporte.',
- 'SUPPORT_CENTER_DESCRIPTION': 'Bienvenido a nuestro centro de soporte. Puede ponerse en contacto con nosotros a través de un sistema de tickets. Sus tickets serán contestadps por nuestro personal.',
+ 'SUPPORT_CENTER_DESCRIPTION': 'Bienvenido a nuestro centro de soporte. Puede ponerse en contacto con nosotros a través de un sistema de tickets. Sus tickets serán contestados por nuestro personal.',
'CUSTOM_RESPONSES_DESCRIPTION': 'Las respuestas personalizadas son respuestas automatizadas para problemas comunes.',
'MY_TICKETS_DESCRIPTION': 'Aquí puedes ver los tickets que tienes asignado.',
'NEW_TICKETS_DESCRIPTION': 'Aquí puedes ver todos los tickets nuevos que no están asignados por nadie.',
diff --git a/client/src/data/languages/fr.js b/client/src/data/languages/fr.js
index a1c633bd..4f012bbd 100644
--- a/client/src/data/languages/fr.js
+++ b/client/src/data/languages/fr.js
@@ -176,6 +176,8 @@ export default {
'HOME': 'Accueil',
'TICKET_NUMBER': 'Numéro de ticket',
'NEXT': 'Suivant',
+ 'SEND_EMAIL_ON_NEW_TICKET': 'Envoyer un e-mail pour chaque nouveau ticket',
+ 'UPDATE': 'Mettre à jour',
'CHART_CREATE_TICKET': 'Tickets créés',
'CHART_CLOSE': 'Tickets fermés',
diff --git a/client/src/data/languages/in.js b/client/src/data/languages/in.js
index 5e019e72..5f2092ef 100644
--- a/client/src/data/languages/in.js
+++ b/client/src/data/languages/in.js
@@ -176,6 +176,8 @@ export default {
'HOME': 'घर',
'TICKET_NUMBER': 'टिकट नंबर',
'NEXT': 'आगामी',
+ 'SEND_EMAIL_ON_NEW_TICKET': 'एक ईमेल भेजने के लिए प्रत्येक नए टिकट',
+ 'UPDATE': 'अद्यतन',
'CHART_CREATE_TICKET': 'टिकट बनाया',
'CHART_CLOSE': 'टिकट बंद कर दिया',
diff --git a/client/src/data/languages/jp.js b/client/src/data/languages/jp.js
index 0c4ac281..71edaf6e 100644
--- a/client/src/data/languages/jp.js
+++ b/client/src/data/languages/jp.js
@@ -176,6 +176,8 @@ export default {
'HOME': 'ホーム',
'TICKET_NUMBER': 'チケット番号',
'NEXT': '次',
+ 'SEND_EMAIL_ON_NEW_TICKET': 'メールを送信毎に新しいチケット',
+ 'UPDATE': '更新',
'CHART_CREATE_TICKET': '作成されたチケット',
'CHART_CLOSE': 'チケットが閉じられました',
diff --git a/client/src/data/languages/pt.js b/client/src/data/languages/pt.js
index 939500a1..2b642104 100644
--- a/client/src/data/languages/pt.js
+++ b/client/src/data/languages/pt.js
@@ -176,6 +176,8 @@ export default {
'HOME': 'Casa',
'TICKET_NUMBER': 'Número do bilhete',
'NEXT': 'Próximo',
+ 'SEND_EMAIL_ON_NEW_TICKET': 'Enviar email para cada novo ticket',
+ 'UPDATE': 'Actualizar',
'CHART_CREATE_TICKET': 'Ingressos criados',
'CHART_CLOSE': 'Ingressos fechados',
diff --git a/client/src/data/languages/ru.js b/client/src/data/languages/ru.js
index ff561236..563a3ff1 100644
--- a/client/src/data/languages/ru.js
+++ b/client/src/data/languages/ru.js
@@ -176,6 +176,8 @@ export default {
'HOME': 'Главная',
'TICKET_NUMBER': 'Номер билета',
'NEXT': 'следующий',
+ 'SEND_EMAIL_ON_NEW_TICKET': 'Отправить письмо на новый билет',
+ 'UPDATE': 'Обновить',
'CHART_CREATE_TICKET': 'Билеты создано',
'CHART_CLOSE': ' Билеты закрыты',
diff --git a/client/src/data/languages/tr.js b/client/src/data/languages/tr.js
index 0baf0487..f8d2e0b7 100644
--- a/client/src/data/languages/tr.js
+++ b/client/src/data/languages/tr.js
@@ -176,6 +176,8 @@ export default {
'HOME': 'Ev',
'TICKET_NUMBER': 'Bilet numarası',
'NEXT': 'Sonraki',
+ 'SEND_EMAIL_ON_NEW_TICKET': 'Yeni biletle e-posta gönder',
+ 'UPDATE': 'Güncelleştirme',
'CHART_CREATE_TICKET': 'Biletler oluşturuldu',
'CHART_CLOSE': 'Biletler kapandı',
diff --git a/client/src/lib-app/__tests__/session-store-test.js b/client/src/lib-app/__tests__/session-store-test.js
index 883d38a3..40f51a62 100644
--- a/client/src/lib-app/__tests__/session-store-test.js
+++ b/client/src/lib-app/__tests__/session-store-test.js
@@ -19,26 +19,26 @@ describe('sessionStore library', function () {
it('should get, set and remove items from LocalStorage', function () {
sessionStore.getItem('SOME_KEY');
- expect(LocalStorageMock.getItem).to.have.been.calledWith('SOME_KEY');
+ expect(LocalStorageMock.getItem).to.have.been.calledWith(root + '_SOME_KEY');
sessionStore.setItem('SOME_KEY', 'SOME_VALUE');
- expect(LocalStorageMock.setItem).to.have.been.calledWith('SOME_KEY', 'SOME_VALUE');
+ expect(LocalStorageMock.setItem).to.have.been.calledWith(root + '_SOME_KEY', 'SOME_VALUE');
sessionStore.removeItem('SOME_KEY');
- expect(LocalStorageMock.removeItem).to.have.been.calledWith('SOME_KEY');
+ expect(LocalStorageMock.removeItem).to.have.been.calledWith(root + '_SOME_KEY');
});
it('should create session correctly', function () {
sessionStore.createSession(14, 'TOKEN');
- expect(LocalStorageMock.setItem).to.have.been.calledWith('userId', 14);
- expect(LocalStorageMock.setItem).to.have.been.calledWith('token', 'TOKEN');
+ expect(LocalStorageMock.setItem).to.have.been.calledWith(root + '_userId', 14);
+ expect(LocalStorageMock.setItem).to.have.been.calledWith(root + '_token', 'TOKEN');
});
it('should return session data', function () {
LocalStorageMock.getItem = function (key) {
- if (key === 'userId') return 'USER_ID';
- if (key === 'token') return 'TOKEN';
+ if (key === root + '_userId') return 'USER_ID';
+ if (key === root + '_token') return 'TOKEN';
};
let sessionData = sessionStore.getSessionData();
@@ -59,8 +59,8 @@ describe('sessionStore library', function () {
it('should clear session data if session is closed', function () {
sessionStore.closeSession();
- expect(LocalStorageMock.removeItem).to.have.been.calledWith('userId');
- expect(LocalStorageMock.removeItem).to.have.been.calledWith('token');
+ expect(LocalStorageMock.removeItem).to.have.been.calledWith(root + '_userId');
+ expect(LocalStorageMock.removeItem).to.have.been.calledWith(root + '_token');
});
it('should store remember data', function () {
@@ -70,26 +70,26 @@ describe('sessionStore library', function () {
expiration: 20160623
});
- expect(LocalStorageMock.setItem).to.have.been.calledWith('rememberData-token', 'SOME_TOKEN');
- expect(LocalStorageMock.setItem).to.have.been.calledWith('rememberData-userId', 12);
- expect(LocalStorageMock.setItem).to.have.been.calledWith('rememberData-expiration', 20160623);
+ expect(LocalStorageMock.setItem).to.have.been.calledWith(root + '_rememberData-token', 'SOME_TOKEN');
+ expect(LocalStorageMock.setItem).to.have.been.calledWith(root + '_rememberData-userId', 12);
+ expect(LocalStorageMock.setItem).to.have.been.calledWith(root + '_rememberData-expiration', 20160623);
});
it('should inform if remember expired', function () {
- LocalStorageMock.getItem = (key) => (key === 'rememberData-expiration') ? 20160505 : null;
+ LocalStorageMock.getItem = (key) => (key === root + '_rememberData-expiration') ? 20160505 : null;
date.getCurrentDate.returns(20160506);
expect(sessionStore.isRememberDataExpired()).to.equal(true);
- LocalStorageMock.getItem = (key) => (key === 'rememberData-expiration') ? 20160505 : null;
+ LocalStorageMock.getItem = (key) => (key === root + '_rememberData-expiration') ? 20160505 : null;
date.getCurrentDate.returns(20160503);
expect(sessionStore.isRememberDataExpired()).to.equal(false);
});
it('should return all remember data', function () {
LocalStorageMock.getItem = function (key) {
- if (key === 'rememberData-userId') return 'USER_ID';
- if (key === 'rememberData-token') return 'TOKEN';
- if (key === 'rememberData-expiration') return 'EXPIRATION';
+ if (key === root + '_rememberData-userId') return 'USER_ID';
+ if (key === root + '_rememberData-token') return 'TOKEN';
+ if (key === root + '_rememberData-expiration') return 'EXPIRATION';
};
let rememberData = sessionStore.getRememberData();
@@ -103,8 +103,8 @@ describe('sessionStore library', function () {
it('should clear remember data', function () {
sessionStore.clearRememberData();
- expect(LocalStorageMock.removeItem).to.have.been.calledWith('rememberData-userId');
- expect(LocalStorageMock.removeItem).to.have.been.calledWith('rememberData-token');
- expect(LocalStorageMock.removeItem).to.have.been.calledWith('rememberData-expiration');
+ expect(LocalStorageMock.removeItem).to.have.been.calledWith(root + '_rememberData-userId');
+ expect(LocalStorageMock.removeItem).to.have.been.calledWith(root + '_rememberData-token');
+ expect(LocalStorageMock.removeItem).to.have.been.calledWith(root + '_rememberData-expiration');
});
});
\ No newline at end of file
diff --git a/client/src/lib-app/session-store.js b/client/src/lib-app/session-store.js
index d5d1086a..6164860f 100644
--- a/client/src/lib-app/session-store.js
+++ b/client/src/lib-app/session-store.js
@@ -53,6 +53,7 @@ class SessionStore {
}
storeConfigs(configs) {
+ this.setItem('session-prefix', configs['session-prefix']);
this.setItem('language', configs.language);
this.setItem('reCaptchaKey', configs.reCaptchaKey);
this.setItem('departments', JSON.stringify(configs.departments));
@@ -106,15 +107,15 @@ class SessionStore {
}
getItem(key) {
- return this.storage.getItem(key);
+ return this.storage.getItem(root + '_' + key);
}
setItem(key, value) {
- return this.storage.setItem(key, (value !== undefined) ? value : '');
+ return this.storage.setItem(root + '_' + key, (value !== undefined) ? value : '');
}
removeItem(key) {
- this.storage.removeItem(key);
+ this.storage.removeItem(root + '_' + key);
}
}
diff --git a/client/src/reducers/config-reducer.js b/client/src/reducers/config-reducer.js
index 80fafb90..d4aa5919 100644
--- a/client/src/reducers/config-reducer.js
+++ b/client/src/reducers/config-reducer.js
@@ -33,7 +33,11 @@ class ConfigReducer extends Reducer {
}
onInitConfigs(state, payload) {
- const currentLanguage = sessionStore.getItem('language');
+ let currentLanguage = sessionStore.getItem('language');
+
+ if(!_.includes(payload.data.allowedLanguages, currentLanguage)) {
+ currentLanguage = payload.data.language;
+ }
sessionStore.storeConfigs(_.extend({}, payload.data, {
language: currentLanguage || payload.data.language
diff --git a/client/src/reducers/session-reducer.js b/client/src/reducers/session-reducer.js
index a51d7e67..436516dc 100644
--- a/client/src/reducers/session-reducer.js
+++ b/client/src/reducers/session-reducer.js
@@ -113,7 +113,8 @@ class SessionReducer extends Reducer {
userProfilePic: userData.profilePic,
userLevel: userData.level,
userDepartments: userData.departments,
- userTickets: userData.tickets
+ userTickets: userData.tickets,
+ userSendEmailOnNewTicket: userData.sendEmailOnNewTicket
});
}
@@ -131,7 +132,8 @@ class SessionReducer extends Reducer {
userLevel: userData.level,
userDepartments: userData.departments,
userTickets: userData.tickets,
- userId: userId
+ userId: userId,
+ userSendEmailOnNewTicket: userData.sendEmailOnNewTicket
});
}