Initial commit

This commit is contained in:
zhongjin
2020-06-15 10:58:47 +08:00
commit 4f1dfe7564
8590 changed files with 1516878 additions and 0 deletions
@@ -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');
}
}
});
}
});
@@ -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>
@@ -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>
@@ -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);
}
});
@@ -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>