mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-09-07 05:34:55 +08:00
Add first version of invite users modal
This commit is contained in:
parent
12d1c31651
commit
ccf8932611
7 changed files with 333 additions and 0 deletions
164
app/assets/javascripts/sitewide/invite_users_modal.js
Normal file
164
app/assets/javascripts/sitewide/invite_users_modal.js
Normal file
|
@ -0,0 +1,164 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
function initializeModal(modal) {
|
||||
var modalDialog = modal.find('.modal-dialog');
|
||||
var type = modal.attr('data-type');
|
||||
var stepForm = modal.find('[data-role=step-form]');
|
||||
var stepResults = modal.find('[data-role=step-results]');
|
||||
var inviteBtn = modal.find('[data-role=invite-btn]');
|
||||
var inviteWithRoleDiv =
|
||||
modal.find('[data-role=invite-with-role-div]');
|
||||
var inviteWithRoleBtn =
|
||||
modal.find('[data-role=invite-with-role-btn]');
|
||||
var orgSelectorCheckbox =
|
||||
modal.find('[data-role=org-selector-checkbox]');
|
||||
var orgSelectorDropdown =
|
||||
modal.find('[data-role=org-selector-dropdown]');
|
||||
var orgSelectorDropdown2 = $();
|
||||
var tagsInput = modal.find('[data-role=tagsinput]');
|
||||
|
||||
modal
|
||||
.on('show.bs.modal', function() {
|
||||
// This cannot be scoped outside this function
|
||||
// because it is generated via JS
|
||||
orgSelectorDropdown2 =
|
||||
orgSelectorDropdown
|
||||
.next('.btn-group.bootstrap-select.form-control')
|
||||
.find('button.dropdown-toggle, li');
|
||||
|
||||
// Show/hide correct step
|
||||
stepForm.show();
|
||||
stepResults.hide();
|
||||
|
||||
// Show/hide buttons & other elements
|
||||
switch (type) {
|
||||
case 'invite_to_org_with_role':
|
||||
case 'invite':
|
||||
case 'invite_with_org_selector':
|
||||
case 'invite_with_org_selector_and_role':
|
||||
inviteBtn.show();
|
||||
inviteWithRoleDiv.hide();
|
||||
break;
|
||||
case 'invite_to_org':
|
||||
inviteBtn.hide();
|
||||
inviteWithRoleDiv.show();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Checkbox toggle event
|
||||
if (
|
||||
type === 'invite_with_org_selector' ||
|
||||
type === 'invite_with_org_selector_and_role'
|
||||
) {
|
||||
orgSelectorCheckbox.on('change', function() {
|
||||
if ($(this).is(':checked')) {
|
||||
orgSelectorDropdown.removeAttr('disabled');
|
||||
orgSelectorDropdown2.removeClass('disabled');
|
||||
if (type === 'invite_with_org_selector') {
|
||||
inviteBtn.hide();
|
||||
inviteWithRoleDiv.show();
|
||||
}
|
||||
} else {
|
||||
orgSelectorDropdown.attr('disabled', 'disabled');
|
||||
orgSelectorDropdown2.addClass('disabled');
|
||||
if (type === 'invite_with_org_selector') {
|
||||
inviteBtn.show();
|
||||
inviteWithRoleDiv.hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Toggle depending on input tags
|
||||
tagsInput
|
||||
.on('itemAdded', function(event) {
|
||||
inviteBtn.removeAttr('disabled');
|
||||
inviteWithRoleBtn.removeAttr('disabled');
|
||||
})
|
||||
.on('itemRemoved', function(event) {
|
||||
if ($(this).val() === null) {
|
||||
inviteBtn.attr('disabled', 'disabled');
|
||||
inviteWithRoleBtn.attr('disabled', 'disabled');
|
||||
}
|
||||
});
|
||||
|
||||
// Click action
|
||||
$('[data-action=invite]').on('click', function() {
|
||||
animateSpinner(modalDialog);
|
||||
|
||||
var data = {
|
||||
emails: tagsInput.val()
|
||||
};
|
||||
switch (type) {
|
||||
case 'invite_to_org':
|
||||
data.organizationId = modal.attr('data-organization-id');
|
||||
data.role = $(this).attr('data-organization-role');
|
||||
break;
|
||||
case 'invite_to_org_with_role':
|
||||
data.organizationId = modal.attr('data-organization-id');
|
||||
data.role = modal.attr('data-organization-role');
|
||||
break;
|
||||
case 'invite':
|
||||
break;
|
||||
case 'invite_with_org_selector':
|
||||
if (orgSelectorCheckbox.is(':checked')) {
|
||||
data.organizationId = orgSelectorDropdown.val();
|
||||
data.role = $(this).attr('data-organization-role');
|
||||
}
|
||||
break;
|
||||
case 'invite_with_org_selector_and_role':
|
||||
if (orgSelectorCheckbox.is(':checked')) {
|
||||
data.organizationId = orgSelectorDropdown.val();
|
||||
data.role = modal.attr('data-organization-role');
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
url: modal.attr('data-url'),
|
||||
dataType: 'json',
|
||||
data: data,
|
||||
success: function(data) {
|
||||
}
|
||||
});
|
||||
});
|
||||
})
|
||||
.on('shown.bs.modal', function() {
|
||||
tagsInput.tagsinput('focus');
|
||||
})
|
||||
.on('hide.bs.modal', function() {
|
||||
// 'Reset' modal state
|
||||
tagsInput.tagsinput('removeAll');
|
||||
orgSelectorCheckbox.prop('checked', false);
|
||||
inviteBtn.attr('disabled', 'disabled');
|
||||
inviteWithRoleBtn.attr('disabled', 'disabled');
|
||||
orgSelectorDropdown2.addClass('disabled');
|
||||
animateSpinner(modalDialog, false);
|
||||
|
||||
// Unbind event listeners
|
||||
orgSelectorCheckbox.off('change');
|
||||
tagsInput.off('itemAdded itemRemoved');
|
||||
});
|
||||
}
|
||||
|
||||
function initializeModalsToggle() {
|
||||
$("[data-trigger='invite-users']").on('click', function() {
|
||||
var id = $(this).attr('data-modal-id');
|
||||
$('[data-role=invite-users-modal][data-id=' + id + ']')
|
||||
.modal('show');
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$('[data-role=invite-users-modal]').each(function() {
|
||||
initializeModal($(this));
|
||||
});
|
||||
initializeModalsToggle();
|
||||
});
|
||||
})();
|
|
@ -1496,3 +1496,19 @@ html.turbolinks-progress-bar::before {
|
|||
width: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-invite-users {
|
||||
.bootstrap-tagsinput {
|
||||
min-width: 450px;
|
||||
}
|
||||
|
||||
.org-selector .heading {
|
||||
margin-top: 15px;
|
||||
margin-bottom: 5px;
|
||||
|
||||
input[type=checkbox] {
|
||||
vertical-align: middle;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,4 +27,8 @@ class Users::InvitationsController < Devise::InvitationsController
|
|||
|
||||
resource
|
||||
end
|
||||
|
||||
def invite_users
|
||||
# TODO
|
||||
end
|
||||
end
|
||||
|
|
129
app/views/shared/_invite_users_modal.html.erb
Normal file
129
app/views/shared/_invite_users_modal.html.erb
Normal file
|
@ -0,0 +1,129 @@
|
|||
<%
|
||||
# How to use this modal:
|
||||
# 1. Render it in the page (HTML) of your choice
|
||||
# 2. Add an element (e.g. <a href>) with following attributes:
|
||||
# * data-trigger="invite-users",
|
||||
# * data-modal-id="modal-id",
|
||||
#
|
||||
# Modal parameters:
|
||||
# * modal_id: unique id so the JS works if multiple modals are present
|
||||
# on the same page
|
||||
# * type:
|
||||
# * 'invite_to_org' => params: organization
|
||||
# * 'invite_to_org_with_role' => params: organization, role
|
||||
# * 'invite',
|
||||
# * 'invite_with_org_selector',
|
||||
# * 'invite_with_org_selector_and_role' => params: role
|
||||
# * organization: invite users to the specified organization
|
||||
# * role: all users are invited as the specified role
|
||||
%>
|
||||
<div
|
||||
class="modal modal-invite-users"
|
||||
tabindex="-1"
|
||||
role="dialog"
|
||||
aria-labelledby="invite-users-modal-label"
|
||||
data-id="<%= modal_id %>"
|
||||
data-role="invite-users-modal"
|
||||
data-type="<%= type %>"
|
||||
data-url="<%= invite_users_path %>"
|
||||
data-backdrop="static"
|
||||
data-keyboard="false"
|
||||
<%= "data-organization-id=#{organization.id}" if type.in?(['invite_to_org', 'invite_to_org_with_role']) %>
|
||||
<%= "data-organization-role=#{role}" if type.in?(['invite_to_org_with_role', 'invite_with_org_selector_and_role']) %>
|
||||
>
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">
|
||||
<% if type.in?(['invite_to_org', 'invite_to_org_with_role']) %>
|
||||
<%= t('invite_users.to_org.title', organization: organization.name) %>
|
||||
<% else %>
|
||||
<%= t('invite_users.no_org.title') %>
|
||||
<% end %>
|
||||
</h4>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div data-role="step-form">
|
||||
<p>
|
||||
<% if type.in?(['invite_to_org', 'invite_to_org_with_role']) %>
|
||||
<%= t('invite_users.to_org.heading', organization: organization.name) %>
|
||||
<% else %>
|
||||
<%= t('invite_users.no_org.heading') %>
|
||||
<% end %>
|
||||
</p>
|
||||
|
||||
<select class="emails-input" multiple data-role="tagsinput" name="emails[]">
|
||||
</select>
|
||||
<br />
|
||||
<em><%= t('invite_users.input_subtitle') %></em>
|
||||
|
||||
<% if type.in?(['invite_with_org_selector', 'invite_with_org_selector_and_role']) %>
|
||||
<% uos = current_user.user_organizations.where(role: UserOrganization.roles[:admin]).joins(:organization) %>
|
||||
<% if uos.count > 0 %>
|
||||
<div class="org-selector">
|
||||
<div class="heading">
|
||||
<input type="checkbox" data-role="org-selector-checkbox" />
|
||||
<span><%= t('invite_users.invite_to_org_heading') %></span>
|
||||
</div>
|
||||
<%= select_tag(
|
||||
'organization-select',
|
||||
options_for_select(
|
||||
uos.pluck('organizations.name', 'organizations.id')
|
||||
),
|
||||
{
|
||||
class: 'form-control selectpicker',
|
||||
'data-role' => 'org-selector-dropdown',
|
||||
disabled: 'disabled'
|
||||
}
|
||||
) %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div data-role="step-results" data-clear="true">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<div data-role="step-form">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">
|
||||
<%= t('general.cancel') %>
|
||||
</button>
|
||||
|
||||
<!-- Invite buttons -->
|
||||
<button type="button" data-role="invite-btn" class="btn btn-primary" disabled="disabled" data-action="invite">
|
||||
<%= t('invite_users.invite_btn') %>
|
||||
</button>
|
||||
|
||||
<div class="btn-group" data-role="invite-with-role-div">
|
||||
<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" data-id="invite-btn" aria-haspopup="true" aria-expanded="false" data-role="invite-with-role-btn" disabled="disabled">
|
||||
<%= t('invite_users.invite_btn') %>
|
||||
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#" data-action="invite" data-organization-role="guest">
|
||||
<%= t("invite_users.invite_guest") %>
|
||||
</a></li>
|
||||
<li><a href="#" data-action="invite" data-organization-role="normal_user">
|
||||
<%= t("invite_users.invite_user") %>
|
||||
</a></li>
|
||||
<li><a href="#" data-action="invite" data-organization-role="admin">
|
||||
<%= t("invite_users.invite_admin") %>
|
||||
</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div data-role="step-results">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">
|
||||
<%= t('general.close') %>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -59,6 +59,7 @@ Rails.application.config.assets.precompile += %w(assets.js)
|
|||
Rails.application.config.assets.precompile += %w(comments.js)
|
||||
Rails.application.config.assets.precompile += %w(projects/show.js)
|
||||
Rails.application.config.assets.precompile += %w(notifications.js)
|
||||
Rails.application.config.assets.precompile += %w(users/invite_users_modal.js)
|
||||
|
||||
# Libraries needed for Handsontable formulas
|
||||
Rails.application.config.assets.precompile += %w(lodash.js)
|
||||
|
|
|
@ -1449,6 +1449,20 @@ en:
|
|||
head_title: "Edit protocol"
|
||||
no_keywords: "No keywords"
|
||||
|
||||
invite_users:
|
||||
to_org:
|
||||
title: "Invite users to team %{organization}"
|
||||
heading: "Invite more people to team %{organization} and start using sciNote."
|
||||
no_org:
|
||||
title: "Invite users to sciNote"
|
||||
heading: "Invite more people to start using sciNote."
|
||||
input_subtitle: "Input one or multiple emails, confirm each email with ENTER key."
|
||||
invite_to_org_heading: "Invite users to my team:"
|
||||
invite_btn: "Invite user/s"
|
||||
invite_guest: "as Guest/s"
|
||||
invite_user: "as Normal user/s"
|
||||
invite_admin: "as Administrator/s"
|
||||
|
||||
time:
|
||||
formats:
|
||||
full: "%d.%m.%Y %H:%M"
|
||||
|
|
|
@ -39,6 +39,11 @@ Rails.application.routes.draw do
|
|||
get "users/settings/user_organizations/:user_organization_id/destroy_html", to: "users/settings#destroy_user_organization_html", as: "destroy_user_organization_html"
|
||||
delete "users/settings/user_organizations/:user_organization_id", to: "users/settings#destroy_user_organization", as: "destroy_user_organization"
|
||||
|
||||
# Invite users
|
||||
post 'users/invite',
|
||||
to: 'users/invitations#invite_users',
|
||||
as: 'invite_users'
|
||||
|
||||
# Notifications
|
||||
get 'users/:id/recent_notifications',
|
||||
to: 'user_notifications#recent_notifications',
|
||||
|
|
Loading…
Add table
Reference in a new issue