diff --git a/client/src/app/admin/panel/staff/staff-editor.js b/client/src/app/admin/panel/staff/staff-editor.js
index 65b65d01..8f2466bb 100644
--- a/client/src/app/admin/panel/staff/staff-editor.js
+++ b/client/src/app/admin/panel/staff/staff-editor.js
@@ -290,7 +290,7 @@ class StaffEditor extends React.Component {
API.call({
path: '/staff/edit',
data: {
- staffId: this.props.staffId,
+ staffId: (!this.props.myAccount) ? this.props.staffId : null,
sendEmailOnNewTicket: (eventType === 'SEND_EMAIL_ON_NEW_TICKET') ? form.sendEmailOnNewTicket * 1 : null,
email: (eventType === 'EMAIL') ? form.email : null,
password: (eventType === 'PASSWORD') ? form.password : null,
@@ -331,7 +331,7 @@ class StaffEditor extends React.Component {
path: '/staff/edit',
dataAsForm: true,
data: {
- staffId: this.props.staffId,
+ staffId: (!this.props.myAcount) ? this.props.staffId : null,
file: event.target.files[0]
}
}).then(() => {
diff --git a/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js b/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js
index caed8aaf..2b85418b 100644
--- a/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js
+++ b/client/src/app/admin/panel/tickets/admin-panel-my-tickets.js
@@ -32,7 +32,7 @@ class AdminPanelMyTickets extends React.Component {
{(this.props.error) ? {i18n('ERROR_RETRIEVING_TICKETS')} : }
@@ -55,7 +55,7 @@ class AdminPanelMyTickets extends React.Component {
-
+
);
diff --git a/client/src/app/admin/panel/users/admin-panel-list-users.js b/client/src/app/admin/panel/users/admin-panel-list-users.js
index 25607145..04380bf6 100644
--- a/client/src/app/admin/panel/users/admin-panel-list-users.js
+++ b/client/src/app/admin/panel/users/admin-panel-list-users.js
@@ -9,6 +9,9 @@ import Table from 'core-components/table';
import SearchBox from 'core-components/search-box';
import Button from 'core-components/button';
import Message from 'core-components/message';
+import Icon from 'core-components/icon';
+import ModalContainer from 'app-components/modal-container';
+import MainSignUpWidget from 'app/main/main-signup/main-signup-widget';
class AdminPanelListUsers extends React.Component {
@@ -37,6 +40,11 @@ class AdminPanelListUsers extends React.Component {
{(this.state.error) ? {i18n('ERROR_RETRIEVING_USERS')} : }
+
+
+
);
}
@@ -149,6 +157,20 @@ class AdminPanelListUsers extends React.Component {
}).then(this.onUsersRetrieved.bind(this)).catch(this.onUsersRejected.bind(this));
}
+ onCreateUser(user) {
+ ModalContainer.openModal(
+
+
+
+
+
+
+ );
+ }
+ onCreateUserSuccess() {
+ ModalContainer.closeModal();
+ }
+
onUsersRetrieved(result) {
this.setState({
page: result.data.page * 1,
diff --git a/client/src/app/admin/panel/users/admin-panel-list-users.scss b/client/src/app/admin/panel/users/admin-panel-list-users.scss
index 7b76f23c..0276301d 100644
--- a/client/src/app/admin/panel/users/admin-panel-list-users.scss
+++ b/client/src/app/admin/panel/users/admin-panel-list-users.scss
@@ -21,4 +21,8 @@
display: inline-block;
text-align: center;
}
-}
\ No newline at end of file
+
+ &__add-user-form {
+ max-width: 500px;
+ }
+}
diff --git a/client/src/app/main/main-signup/main-signup-page.js b/client/src/app/main/main-signup/main-signup-page.js
index deeb4d89..f52d4586 100644
--- a/client/src/app/main/main-signup/main-signup-page.js
+++ b/client/src/app/main/main-signup/main-signup-page.js
@@ -1,49 +1,15 @@
import React from 'react';
import ReactDOM from 'react-dom';
-import _ from 'lodash';
-import i18n from 'lib-app/i18n';
-import API from 'lib-app/api-call';
-
-import Captcha from 'app/main/captcha';
-import SubmitButton from 'core-components/submit-button';
-import Message from 'core-components/message';
-import Form from 'core-components/form';
-import FormField from 'core-components/form-field';
import Widget from 'core-components/widget';
-import Header from 'core-components/header';
+import MainSignUpWidget from 'app/main/main-signup/main-signup-widget';
-class MainSignUpPageWidget extends React.Component {
-
- constructor(props) {
- super(props);
-
- this.state = {
- loading: false,
- email: null
- };
- }
+class MainSignUpPage extends React.Component {
render() {
return (
-
-
-
-
- {this.renderMessage()}
-
+
);
}
diff --git a/client/src/app/main/main-signup/main-signup-page.scss b/client/src/app/main/main-signup/main-signup-page.scss
index f3110435..15a08918 100644
--- a/client/src/app/main/main-signup/main-signup-page.scss
+++ b/client/src/app/main/main-signup/main-signup-page.scss
@@ -1,23 +1,3 @@
.main-signup-page {
min-height: 669px;
-
- .signup-widget {
- padding: 30px;
- text-align: center;
-
- &__form {
- margin-bottom: 20px;
- }
-
- &__inputs {
- display: inline-block;
- margin: 0 auto;
- }
-
- &__captcha {
- margin: 10px auto 20px;
- height: 78px;
- width: 304px;
- }
- }
-}
\ No newline at end of file
+}
diff --git a/client/src/app/main/main-signup/main-signup-widget.js b/client/src/app/main/main-signup/main-signup-widget.js
new file mode 100644
index 00000000..0b0ab98f
--- /dev/null
+++ b/client/src/app/main/main-signup/main-signup-widget.js
@@ -0,0 +1,123 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import _ from 'lodash';
+import classNames from 'classnames';
+
+import i18n from 'lib-app/i18n';
+import API from 'lib-app/api-call';
+
+import Captcha from 'app/main/captcha';
+import SubmitButton from 'core-components/submit-button';
+import Message from 'core-components/message';
+import Form from 'core-components/form';
+import FormField from 'core-components/form-field';
+import Widget from 'core-components/widget';
+import Header from 'core-components/header';
+
+class MainSignUpWidget extends React.Component {
+
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ loading: false,
+ email: null
+ };
+ }
+ static propTypes = {
+ onSuccess: React.PropTypes.func,
+ className: React.PropTypes.string
+ };
+
+ render() {
+ return (
+
+
+
+
+ {this.renderMessage()}
+
+ );
+ }
+
+ renderMessage() {
+ switch (this.state.message) {
+ case 'success':
+ return {i18n('SIGNUP_SUCCESS')};
+ case 'fail':
+ return {i18n('EMAIL_EXISTS')};
+ default:
+ return null;
+ }
+ }
+
+ getClass() {
+ let classes = {
+ 'signup-widget': true,
+ [this.props.className]: this.props.className
+ };
+ return classNames(classes);
+ }
+
+ getFormProps() {
+ return {
+ loading: this.state.loading,
+ className: 'signup-widget__form',
+ onSubmit: this.onSignupFormSubmit.bind(this)
+ };
+ }
+
+ getInputProps(password) {
+ return {
+ className: 'signup-widget__input',
+ fieldProps: {
+ size: 'medium',
+ password: password
+ }
+ };
+ }
+
+ onSignupFormSubmit(formState) {
+ const captcha = this.refs.captcha.getWrappedInstance();
+
+ if (!captcha.getValue()) {
+ captcha.focus();
+ } else {
+ this.setState({
+ loading: true
+ });
+
+ API.call({
+ path: '/user/signup',
+ data: _.extend({captcha: captcha.getValue()}, formState)
+ }).then(this.onSignupSuccess.bind(this)).catch(this.onSignupFail.bind(this));
+ }
+ }
+
+ onSignupSuccess() {
+ this.setState({
+ loading: false,
+ message: 'success'
+ });
+ }
+
+ onSignupFail() {
+ this.setState({
+ loading: false,
+ message: 'fail'
+ });
+ }
+}
+
+export default MainSignUpWidget;
diff --git a/client/src/app/main/main-signup/main-signup-widget.scss b/client/src/app/main/main-signup/main-signup-widget.scss
new file mode 100644
index 00000000..388bf1e5
--- /dev/null
+++ b/client/src/app/main/main-signup/main-signup-widget.scss
@@ -0,0 +1,19 @@
+ .signup-widget {
+ padding: 30px;
+ text-align: center;
+
+ &__form {
+ margin-bottom: 20px;
+ }
+
+ &__inputs {
+ display: inline-block;
+ margin: 0 auto;
+ }
+
+ &__captcha {
+ margin: 10px auto 20px;
+ height: 78px;
+ width: 304px;
+ }
+ }
diff --git a/client/src/core-components/file-uploader.js b/client/src/core-components/file-uploader.js
index c18771ad..7cb78508 100644
--- a/client/src/core-components/file-uploader.js
+++ b/client/src/core-components/file-uploader.js
@@ -3,6 +3,8 @@ import React from 'react';
import Button from 'core-components/button';
import Icon from 'core-components/icon';
+import i18n from 'lib-app/i18n';
+
class FileUploader extends React.Component {
static propTypes = {
text: React.PropTypes.string,
@@ -11,7 +13,7 @@ class FileUploader extends React.Component {
};
static defaultProps = {
- text: 'Upload file'
+ text: i18n('UPLOAD_FILE')
};
render() {
@@ -37,4 +39,4 @@ class FileUploader extends React.Component {
}
}
-export default FileUploader;
\ No newline at end of file
+export default FileUploader;
diff --git a/client/src/data/languages/br.js b/client/src/data/languages/br.js
index 58c86ae1..909bee45 100644
--- a/client/src/data/languages/br.js
+++ b/client/src/data/languages/br.js
@@ -181,6 +181,8 @@ export default {
'UPDATE': 'Atualizar',
'NEVER': 'Nunca',
'HIMSELF': 'ele mesmo',
+ 'ADD_USER': 'Adicionar usuário',
+ 'UPLOAD_FILE': 'Subir arquivo',
'CHART_CREATE_TICKET': 'Chamados criados',
'CHART_CLOSE': 'Chamados fechados',
diff --git a/client/src/data/languages/cn.js b/client/src/data/languages/cn.js
index be3fc691..029f61d0 100644
--- a/client/src/data/languages/cn.js
+++ b/client/src/data/languages/cn.js
@@ -182,6 +182,8 @@ export default {
'UPDATE': '更新',
'NEVER': '从来没有',
'HIMSELF': '他自己',
+ 'ADD_USER': '添加用户',
+ 'UPLOAD_FILE': '上传文件',
'CHART_CREATE_TICKET': '已創建門票',
'CHART_CLOSE': '門票已關閉',
diff --git a/client/src/data/languages/de.js b/client/src/data/languages/de.js
index b43b0bad..9c78e024 100644
--- a/client/src/data/languages/de.js
+++ b/client/src/data/languages/de.js
@@ -182,6 +182,8 @@ export default {
'UPDATE': 'Aktualisierung',
'NEVER': 'Niemals',
'HIMSELF': 'selbst',
+ 'ADD_USER': 'Benutzer hinzufügen',
+ 'UPLOAD_FILE': 'Datei hochladen',
'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 4b95f899..d1fdf420 100644
--- a/client/src/data/languages/en.js
+++ b/client/src/data/languages/en.js
@@ -182,6 +182,8 @@ export default {
'UPDATE': 'Update',
'NEVER': 'Never',
'HIMSELF': 'himself',
+ 'ADD_USER': 'Add user',
+ 'UPLOAD_FILE': 'Upload file',
'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 8f604cc3..e3669960 100644
--- a/client/src/data/languages/es.js
+++ b/client/src/data/languages/es.js
@@ -182,6 +182,8 @@ export default {
'UPDATE': 'Actualizar',
'NEVER': 'Nunca',
'HIMSELF': 'si mismo',
+ 'ADD_USER': 'Añadir un usuario',
+ 'UPLOAD_FILE': 'Subir archivo',
'CHART_CREATE_TICKET': 'Tickets creados',
'CHART_CLOSE': 'Tickets cerrados',
diff --git a/client/src/data/languages/fr.js b/client/src/data/languages/fr.js
index 65152a60..a0e45764 100644
--- a/client/src/data/languages/fr.js
+++ b/client/src/data/languages/fr.js
@@ -182,6 +182,8 @@ export default {
'UPDATE': 'Mettre à jour',
'NEVER': 'Jamais',
'HIMSELF': 'lui-même',
+ 'ADD_USER': 'Ajouter un utilisateur',
+ 'UPLOAD_FILE': 'Téléverser un fichier',
'CHART_CREATE_TICKET': 'Tickets créés',
'CHART_CLOSE': 'Tickets fermés',
diff --git a/client/src/data/languages/gr.js b/client/src/data/languages/gr.js
index b961a00a..07f90209 100644
--- a/client/src/data/languages/gr.js
+++ b/client/src/data/languages/gr.js
@@ -182,6 +182,8 @@
'UPDATE': 'Ενημέρωση',
'NEVER': 'Ποτέ',
'HIMSELF': 'ο ίδιος',
+ 'ADD_USER': 'Πρόσθεσε χρήστη',
+ 'UPLOAD_FILE': 'Ανέβασμα αρχείου',
'CHART_CREATE_TICKET': 'Τα εισιτήρια δημιουργήθηκαν',
'CHART_CLOSE': 'Τα εισιτήρια κλείσανε',
diff --git a/client/src/data/languages/in.js b/client/src/data/languages/in.js
index 569bfe85..0b520551 100644
--- a/client/src/data/languages/in.js
+++ b/client/src/data/languages/in.js
@@ -182,6 +182,8 @@ export default {
'UPDATE': 'अद्यतन',
'NEVER': 'कभी नहीँ',
'HIMSELF': 'स्वयं',
+ 'ADD_USER': 'उपयोगकर्ता जोड़ें',
+ 'UPLOAD_FILE': 'दस्तावेज अपलोड करें',
'CHART_CREATE_TICKET': 'टिकट बनाया',
'CHART_CLOSE': 'टिकट बंद कर दिया',
diff --git a/client/src/data/languages/it.js b/client/src/data/languages/it.js
index 92aa5904..29bc65ce 100644
--- a/client/src/data/languages/it.js
+++ b/client/src/data/languages/it.js
@@ -182,6 +182,8 @@ export default {
'UPDATE': 'Aggiornare',
'NEVER': 'Mai',
'HIMSELF': 'lui stesso',
+ 'ADD_USER': 'Aggiungi utente',
+ 'UPLOAD_FILE': 'Caricare un file',
'CHART_CREATE_TICKET': 'Tickets creato',
'CHART_CLOSE': 'Tickets chiuso',
diff --git a/client/src/data/languages/jp.js b/client/src/data/languages/jp.js
index 27d5fe7c..3656c356 100644
--- a/client/src/data/languages/jp.js
+++ b/client/src/data/languages/jp.js
@@ -182,6 +182,8 @@ export default {
'UPDATE': '更新',
'NEVER': '決して',
'HIMSELF': '彼自身',
+ 'ADD_USER': 'ユーザーを追加する',
+ 'UPLOAD_FILE': 'ファイルをアップロードする',
'CHART_CREATE_TICKET': '作成されたチケット',
'CHART_CLOSE': 'チケットが閉じられました',
diff --git a/client/src/data/languages/nl.js b/client/src/data/languages/nl.js
index 1355f2d0..256ed4c6 100644
--- a/client/src/data/languages/nl.js
+++ b/client/src/data/languages/nl.js
@@ -182,6 +182,8 @@ export default {
'UPDATE': 'Update',
'NEVER': 'Nooit',
'HIMSELF': 'zichzelf',
+ 'ADD_USER': 'Voeg gebruiker toe',
+ 'UPLOAD_FILE': 'Upload bestand',
'CHART_CREATE_TICKET': 'Aangemaakte incidenten',
'CHART_CLOSE': 'Gesloten incidenten',
diff --git a/client/src/data/languages/pt.js b/client/src/data/languages/pt.js
index 67eecace..3b6e6a3d 100644
--- a/client/src/data/languages/pt.js
+++ b/client/src/data/languages/pt.js
@@ -182,6 +182,8 @@ export default {
'UPDATE': 'Actualizar',
'NEVER': 'Nunca',
'HIMSELF': 'ele mesmo',
+ 'ADD_USER': 'Adicionar usuário',
+ 'UPLOAD_FILE': 'Subir arquivo',
'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 834a3293..0858806f 100644
--- a/client/src/data/languages/ru.js
+++ b/client/src/data/languages/ru.js
@@ -182,6 +182,8 @@ export default {
'UPDATE': 'Обновить',
'NEVER': 'Никогда',
'HIMSELF': 'сам',
+ 'ADD_USER': 'Добавить пользователя',
+ 'UPLOAD_FILE': 'Загрузить файл',
'CHART_CREATE_TICKET': 'Билеты создано',
'CHART_CLOSE': ' Билеты закрыты',
diff --git a/client/src/data/languages/tr.js b/client/src/data/languages/tr.js
index 4858f522..0e78aba9 100644
--- a/client/src/data/languages/tr.js
+++ b/client/src/data/languages/tr.js
@@ -182,6 +182,8 @@ export default {
'UPDATE': 'Güncelleştirme',
'NEVER': 'Asla',
'HIMSELF': 'kendisi',
+ 'ADD_USER': 'Kullanıcı Ekle',
+ 'UPLOAD_FILE': 'Dosya yükleme',
'CHART_CREATE_TICKET': 'Biletler oluşturuldu',
'CHART_CLOSE': 'Biletler kapandı',
diff --git a/server/controllers/staff/edit.php b/server/controllers/staff/edit.php
index cf8e41d0..77ae9b48 100755
--- a/server/controllers/staff/edit.php
+++ b/server/controllers/staff/edit.php
@@ -36,7 +36,21 @@ class EditStaffController extends Controller {
public function validations() {
return [
'permission' => 'staff_1',
- 'requestData' => []
+ 'requestData' => [
+ 'email' => [
+ 'validation' => DataValidator::oneOf(DataValidator::email(), DataValidator::falseVal()),
+ 'error' => ERRORS::INVALID_EMAIL
+ ],
+ 'password' => [
+ 'validation' => DataValidator::oneOf(DataValidator::length(5, 200), DataValidator::falseVal()),
+ 'error' => ERRORS::INVALID_PASSWORD
+ ],
+ 'level' => [
+ 'validation' => DataValidator::oneOf(DataValidator::between(1, 3, true), DataValidator::falseVal()),
+ 'error' => ERRORS::INVALID_LEVEL
+ ]
+
+ ]
];
}
diff --git a/server/controllers/user/signup.php b/server/controllers/user/signup.php
index 8f48a234..b9815888 100755
--- a/server/controllers/user/signup.php
+++ b/server/controllers/user/signup.php
@@ -97,7 +97,7 @@ class SignUpController extends Controller {
throw new Exception(ERRORS::ALREADY_BANNED);
}
- if (!Setting::getSetting('registration')->value && $apiKey->isNull() && !$this->csvImported) {
+ if (!Setting::getSetting('registration')->value && $apiKey->isNull() && !Controller::isStaffLogged(2) && !$this->csvImported) {
throw new Exception(ERRORS::NO_PERMISSION);
}