Initial commit
This commit is contained in:
+103
@@ -0,0 +1,103 @@
|
||||
const CoreView = require('backbone/core-view');
|
||||
const checkAndBuildOpts = require('builder/helpers/required-opts');
|
||||
const loadingView = require('builder/components/loading/render-loading');
|
||||
const OrganizationInviteModel = require('dashboard/data/organization-invite-model');
|
||||
const TabPane = require('dashboard/components/tabpane/tabpane');
|
||||
const errorTemplate = require('dashboard/views/data-library/content/error-template.tpl');
|
||||
const InviteUsersFormView = require('./invite-users-form-view');
|
||||
const ViewFactory = require('builder/components/view-factory');
|
||||
const template = require('./invite-users-dialog.tpl');
|
||||
|
||||
require('jquery-ui');
|
||||
require('tagit');
|
||||
|
||||
const REQUIRED_OPTS = [
|
||||
'modalModel',
|
||||
'organization',
|
||||
'organizationUsers',
|
||||
'configModel'
|
||||
];
|
||||
|
||||
/**
|
||||
* Invite users dialog
|
||||
*
|
||||
* - Send invites via email.
|
||||
* - Shouldn't send emails to already enabled users.
|
||||
*
|
||||
*/
|
||||
|
||||
module.exports = CoreView.extend({
|
||||
|
||||
className: 'InviteUsers',
|
||||
|
||||
initialize: function (options) {
|
||||
checkAndBuildOpts(options, REQUIRED_OPTS, this);
|
||||
|
||||
this.model = new OrganizationInviteModel({}, {
|
||||
configModel: options.configModel,
|
||||
organizationId: this._organization.id,
|
||||
enable_organization_signup: false
|
||||
});
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.clearSubViews();
|
||||
|
||||
this.$el.html(template());
|
||||
|
||||
this.$('.content').addClass('Dialog-content--expanded');
|
||||
|
||||
this._initViews();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_initViews: function () {
|
||||
// Panes
|
||||
this._panes = new TabPane({
|
||||
el: this.$('.js-content')
|
||||
});
|
||||
|
||||
// Create form
|
||||
this._form = new InviteUsersFormView({
|
||||
model: this.model,
|
||||
organization: this._organization,
|
||||
organizationUsers: this._organizationUsers,
|
||||
el: this.$('.js-form')
|
||||
});
|
||||
|
||||
this._form.bind('onSubmit', this._sendInvites, this);
|
||||
|
||||
this._panes.addTab('form', this._form.render());
|
||||
|
||||
// Create loading
|
||||
this._panes.addTab('loading', ViewFactory.createByHTML(loadingView({
|
||||
title: 'Sending invites...'
|
||||
})).render());
|
||||
|
||||
// Create error
|
||||
this._panes.addTab('error', ViewFactory.createByHTML(errorTemplate({
|
||||
msg: 'Sorry, something went wrong.'
|
||||
})).render());
|
||||
|
||||
this._panes.active('form');
|
||||
},
|
||||
|
||||
_sendInvites: function () {
|
||||
this._panes.active('loading');
|
||||
|
||||
this.model.save(null, {
|
||||
success: () => this._modalModel.destroy(),
|
||||
error: (model, error) => {
|
||||
try {
|
||||
const message = JSON.parse(error.responseText).errors.users_emails[0];
|
||||
|
||||
this._form.showSubmitError(message);
|
||||
this._panes.active('form');
|
||||
} catch (e) {
|
||||
this._panes.active('error');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
<div class="CDB-Text Dialog-header Dialog-header--expanded">
|
||||
<div class="Dialog-headerIcon Dialog-headerIcon--neutral">
|
||||
<i class="CDB-IconFont CDB-IconFont-boss"></i>
|
||||
</div>
|
||||
<h3 class="Dialog-headerTitle">Invite users to your Organization</h3>
|
||||
<p class="Dialog-headerText">New user will become part of your CARTO organization account.</p>
|
||||
</div>
|
||||
<div class="CDB-Text Dialog-expandedSubContent js-content">
|
||||
<div class="InviteUsers-form">
|
||||
<div class="js-form"></div>
|
||||
</div>
|
||||
</div>
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
<div class="FlashMessage js-signInMessage">
|
||||
<div class='u-inner'>
|
||||
<div class="FlashMessage-content js-flashNotice">
|
||||
<p class='FlashMessage-info FlashMessage-info--larger'>If you want to invite users you need to enable the sign in page for your organization.</p>
|
||||
<button class='FlashMessage--button js-enableSignInButton'><span>Enable sign in</span></button>
|
||||
</div>
|
||||
|
||||
<div class="FlashMessage-content js-flashSuccess">
|
||||
<p class='FlashMessage-info FlashMessage-info--larger'>You have enabled the sign in page successfully!</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
const _ = require('underscore');
|
||||
const CoreView = require('backbone/core-view');
|
||||
const Utils = require('builder/helpers/utils');
|
||||
const template = require('./invite-users-form.tpl');
|
||||
const flashTemplate = require('./invite-users-flash-message.tpl');
|
||||
const checkAndBuildOpts = require('builder/helpers/required-opts');
|
||||
|
||||
const REQUIRED_OPTS = [
|
||||
'organization',
|
||||
'organizationUsers'
|
||||
];
|
||||
|
||||
/**
|
||||
* Form view for invite users dialog
|
||||
*
|
||||
*/
|
||||
|
||||
module.exports = CoreView.extend({
|
||||
|
||||
events: {
|
||||
'submit .js-invitesForm': '_onSubmit',
|
||||
'keyup .js-welcomeText': '_onTextareaChange',
|
||||
'click .js-enableSignInButton': '_signInEnabledMessage'
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
checkAndBuildOpts(options, REQUIRED_OPTS, this);
|
||||
|
||||
this._initBinds();
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.$el.html(
|
||||
template({
|
||||
welcomeText: this.model.get('welcome_text'),
|
||||
signupEnabled: this._organization.get('signup_enabled'),
|
||||
viewerEnabled: this._organization.get('viewer_seats') > 0
|
||||
})
|
||||
);
|
||||
|
||||
this._toggleEmailError(false);
|
||||
this._initViews();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_renderFlashMessage: function () {
|
||||
this.$('.js-signInMessageContainer').html(flashTemplate());
|
||||
this.$('.js-flashSuccess').hide();
|
||||
},
|
||||
|
||||
_initBinds: function () {
|
||||
this.listenTo(this.model, 'change', this._onChange);
|
||||
},
|
||||
|
||||
_initViews: function () {
|
||||
const organizationUsersEmail = this._organizationUsers.pluck('email');
|
||||
|
||||
this.$('.js-tagsList').tagit({
|
||||
allowSpaces: true,
|
||||
placeholderText: this.$('.js-tags').data('title'),
|
||||
onBlur: () => this.$('.js-tags').removeClass('is-focus'),
|
||||
onFocus: () => this.$('.js-tags').addClass('is-focus'),
|
||||
beforeTagAdded: (event, ui) => {
|
||||
var value = ui.tagLabel;
|
||||
this._removeSubmitError();
|
||||
|
||||
// It is an email
|
||||
if (!Utils.isValidEmail(value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// It is already in the organization
|
||||
if (_.contains(organizationUsersEmail, value)) {
|
||||
this._toggleEmailError(true);
|
||||
return false;
|
||||
} else {
|
||||
this._toggleEmailError(false);
|
||||
}
|
||||
},
|
||||
beforeTagRemoved: () => this._removeSubmitError(),
|
||||
afterTagRemoved: () => this._updateUsers(),
|
||||
afterTagAdded: () => this._updateUsers(),
|
||||
onSubmitTags: (event) => {
|
||||
event.preventDefault();
|
||||
this._onSubmit();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if (!this._organization.get('signup_enabled')) {
|
||||
this._renderFlashMessage();
|
||||
}
|
||||
},
|
||||
|
||||
_onTextareaChange: function () {
|
||||
this.model.set('welcome_text', this.$('.js-welcomeText').val());
|
||||
},
|
||||
|
||||
_updateUsers: function () {
|
||||
this.model.set('users_emails', this.$('.js-tagsList').tagit('assignedTags'));
|
||||
},
|
||||
|
||||
_onSubmit: function (event) {
|
||||
event && this.killEvent(event);
|
||||
|
||||
const emails = this.model.get('users_emails');
|
||||
|
||||
if (emails.length > 0) {
|
||||
this.model.set('welcome_text', this.$('.js-welcomeText').val());
|
||||
this.model.set('viewer', this.$('[name=viewer]').get(0).checked);
|
||||
this.trigger('onSubmit', this);
|
||||
}
|
||||
},
|
||||
|
||||
_signInEnabledMessage: function () {
|
||||
this.$('.js-signInMessage').addClass('FlashMessage--success');
|
||||
this.$('.js-flashNotice').hide();
|
||||
this.$('.js-flashSuccess').show();
|
||||
|
||||
this.model.set('enable_organization_signup', true);
|
||||
},
|
||||
|
||||
_toggleEmailError: function (visible) {
|
||||
this.$('.js-emailError')[ visible ? 'show' : 'hide' ]();
|
||||
},
|
||||
|
||||
showSubmitError: function (msg) {
|
||||
const $serverError = this.$('.js-serverError');
|
||||
|
||||
if ($serverError.length === 0) {
|
||||
this.$('.js-emailError').after('<p class="Form-rowInfoText Form-rowInfoText--error Form-rowInfoText--multipleLines js-serverError">' + msg + '</p>');
|
||||
}
|
||||
},
|
||||
|
||||
_removeSubmitError: function () {
|
||||
this.$('.js-serverError').remove();
|
||||
},
|
||||
|
||||
_onChange: function () {
|
||||
const users = this.model.get('users_emails');
|
||||
const welcomeText = this.model.get('welcome_text');
|
||||
|
||||
this.$('.js-submit').toggleClass('is-disabled', users.length === 0 || !welcomeText);
|
||||
}
|
||||
});
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
<div class="js-signInMessageContainer"></div>
|
||||
|
||||
<form class="Form InviteUsers-formContent js-invitesForm">
|
||||
<div class="Form-row Form-row--centered has-label">
|
||||
<div class="Form-rowLabel">
|
||||
<label class="Form-label">Users email</label>
|
||||
</div>
|
||||
<div class="Form-rowData Form-rowData--longer">
|
||||
<div class="Form-tags js-tags" data-title="Separate emails by commas">
|
||||
<ul class="Form-tagsList js-tagsList"></ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="Form-rowInfo">
|
||||
<p class="Form-rowInfoText Form-rowInfoText--error Form-rowInfoText--multipleLines js-emailError">That email is already used in this organization</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="Form-row Form-row--centered has-label">
|
||||
<div class="Form-rowLabel">
|
||||
<label class="Form-label">Welcome text</label>
|
||||
</div>
|
||||
<div class="Form-rowData Form-rowData--longer">
|
||||
<textarea class="CDB-Textarea Form-input Form-input--longer Form-textarea js-welcomeText" placeholder="Send them a welcome text"><%- welcomeText %></textarea>
|
||||
</div>
|
||||
<div class="Form-rowInfo"></div>
|
||||
</div>
|
||||
|
||||
<div class="Form-row Form-row--centered has-label">
|
||||
<div class="Form-rowLabel">
|
||||
<label class="Form-label">Viewer user</label>
|
||||
</div>
|
||||
<div class="Form-rowData Form-rowData--longer InviteUsers-userType">
|
||||
<div class="Toggler js-toggler InviteUsers-userTypeToggler <% if (!viewerEnabled) { %>is-disabled<% } %>"
|
||||
<% if (!viewerEnabled) { %>title="You can't send viewer invitations because you don't have viewer seats"<% } %>>
|
||||
<input type="checkbox" id="InviteUsers-userType" name="viewer" class="js-input" <% if (!viewerEnabled) { %>disabled="disabled"<% } %>/>
|
||||
<label for="InviteUsers-userType"></label>
|
||||
</div>
|
||||
<div class="Form-label">Viewer users can only read, not write, data and maps</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="InviteUsers-formFooterSticky">
|
||||
<div class="Dialog-footer InviteUsers-formFooter">
|
||||
<div><%/* placeholder for flex layout */%></div>
|
||||
<button type="submit" class="CDB-Button CDB-Button--primary is-disabled js-submit">
|
||||
<span class="CDB-Button-Text CDB-Text is-semibold CDB-Size-small u-upperCase">Invite users</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
Reference in New Issue
Block a user