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 b2997af2..98fbc06f 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
@@ -13,6 +13,7 @@ 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';
+import InviteUserWidget from 'app/admin/panel/users/invite-user-widget';
class AdminPanelListUsers extends React.Component {
@@ -45,6 +46,9 @@ class AdminPanelListUsers extends React.Component {
+
);
@@ -181,6 +185,20 @@ class AdminPanelListUsers extends React.Component {
ModalContainer.closeModal();
}
+ onInviteUser(user) {
+ ModalContainer.openModal(
+
+
+
+
+
+
+ );
+ }
+ onInviteUserSuccess() {
+ ModalContainer.closeModal();
+ }
+
onUsersRetrieved(result) {
this.setState({
page: result.data.page * 1,
diff --git a/client/src/app/admin/panel/users/invite-user-widget.js b/client/src/app/admin/panel/users/invite-user-widget.js
new file mode 100644
index 00000000..8336724d
--- /dev/null
+++ b/client/src/app/admin/panel/users/invite-user-widget.js
@@ -0,0 +1,165 @@
+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 InviteUserWidget extends React.Component {
+
+ static propTypes = {
+ onSuccess: React.PropTypes.func,
+ className: React.PropTypes.string
+ };
+
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ loading: false,
+ email: null,
+ customFields: []
+ };
+ }
+
+ componentDidMount() {
+ API.call({
+ path: '/system/get-custom-fields',
+ data: {}
+ })
+ .then(result => this.setState({customFields: result.data}));
+ }
+
+ render() {
+ return (
+
+
+
+
+ {this.renderMessage()}
+
+ );
+ }
+
+ renderCustomField(customField, key) {
+ if(customField.type === 'text') {
+ return (
+
+ );
+ } else {
+ const items = customField.options.map(option => ({content: option.name, value: option.name}));
+
+ return (
+
+ );
+ }
+ }
+
+ renderMessage() {
+ switch (this.state.message) {
+ case 'success':
+ return {i18n('INVITE_USER_SUCCESS')};
+ case 'fail':
+ return {i18n('EMAIL_EXISTS')};
+ default:
+ return null;
+ }
+ }
+
+ getClass() {
+ let classes = {
+ 'invite-user-widget': true,
+ [this.props.className]: this.props.className
+ };
+ return classNames(classes);
+ }
+
+ getFormProps() {
+ return {
+ loading: this.state.loading,
+ className: 'invite-user-widget__form',
+ onSubmit: this.onInviteUserFormSubmit.bind(this)
+ };
+ }
+
+ getInputProps(password) {
+ return {
+ className: 'invite-user-widget__input',
+ fieldProps: {
+ size: 'medium',
+ password: password
+ }
+ };
+ }
+
+ onInviteUserFormSubmit(formState) {
+ const captcha = this.refs.captcha.getWrappedInstance();
+
+ if (!captcha.getValue()) {
+ captcha.focus();
+ } else {
+ this.setState({
+ loading: true
+ });
+
+ const form = _.clone(formState);
+
+ this.state.customFields.forEach(customField => {
+ if(customField.type === 'select') {
+ form[`customfield_${customField.name}`] = customField.options[form[`customfield_${customField.name}`]].name;
+ }
+ })
+
+ API.call({
+ path: '/user/invite',
+ data: _.extend({captcha: captcha.getValue()}, form)
+ }).then(this.onInviteUserSuccess.bind(this)).catch(this.onInviteUserFail.bind(this));
+ }
+ }
+
+ onInviteUserSuccess() {
+ this.setState({
+ loading: false,
+ message: 'success'
+ });
+ }
+
+ onInviteUserFail() {
+ this.setState({
+ loading: false,
+ message: 'fail'
+ });
+ }
+}
+
+export default InviteUserWidget;
diff --git a/client/src/app/admin/panel/users/invite-user-widget.scss b/client/src/app/admin/panel/users/invite-user-widget.scss
new file mode 100644
index 00000000..9ecbf748
--- /dev/null
+++ b/client/src/app/admin/panel/users/invite-user-widget.scss
@@ -0,0 +1,19 @@
+.invite-user-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/data/languages/en.js b/client/src/data/languages/en.js
index 6373f738..984d76d8 100644
--- a/client/src/data/languages/en.js
+++ b/client/src/data/languages/en.js
@@ -193,6 +193,7 @@ export default {
'NEVER': 'Never',
'HIMSELF': 'himself',
'ADD_USER': 'Add user',
+ 'INVITE_USER': 'Invite user',
'UPLOAD_FILE': 'Upload file',
'PRIVATE': 'Private',
'ENABLE_USER': 'Enable User',
@@ -336,6 +337,7 @@ export default {
'IMAP_POLLING_DESCRIPTION': 'Inbox checking will not be done automatically by OpenSupports. You have to make POST requests periodically to this url to process the emails: {url}',
'NEW_CUSTOM_FIELD_DESCRIPTION': 'Here you can create a custom field for an user, it can be a blank text box or a fixed set of options.',
'CUSTOM_FIELDS_DESCRIPTION': 'Custom fields are defined additional fields the users are able to fill to provide more information about them.',
+ 'INVITE_USER_VIEW_DESCRIPTION': 'Here you can invite an user to join our support system, he will just need to provide his password to create a new user.',
//ERRORS
'EMAIL_OR_PASSWORD': 'Email or password invalid',
@@ -372,6 +374,7 @@ export default {
//MESSAGES
'SIGNUP_SUCCESS': 'You have registered successfully in our support system.',
+ 'INVITE_USER_SUCCESS': 'You have invited a new user successfully in our support system',
'TICKET_SENT': 'Ticket has been created successfully.',
'VALID_RECOVER': 'Password recovered successfully',
'EMAIL_EXISTS': 'Email already exists',