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 (
- -
-
-
- - - - -
-
- -
- {i18n('SIGN_UP')} - - - {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 ( + +
+
+
+ + + + +
+
+ +
+ {i18n('SIGN_UP')} + + + {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); }