428 lines
12 KiB
Plaintext
428 lines
12 KiB
Plaintext
.organization
|
|
form#item_form(onsubmit="return editOrganization()")
|
|
| {% if can_edit %}
|
|
.input-group
|
|
label(for='org-name-field') Name
|
|
input.item-name.input-transparent#org-name-field(
|
|
name="name",
|
|
type="text",
|
|
placeholder="Organization's name",
|
|
value="{{ organization.name | hide_none }}")
|
|
.input-group
|
|
label(for='org-description-field') Description
|
|
textarea.item-description.input-transparent#org-description-field(
|
|
name="description",
|
|
type="text",
|
|
rows=1,
|
|
placeholder="Organization's description") {{ organization.description | hide_none }}
|
|
.input-group
|
|
label(for='org-website-field') Website
|
|
input.item-website.input-transparent#org-website-field(
|
|
name="website",
|
|
type="text",
|
|
placeholder="Organization's website",
|
|
value="{{ organization.website | hide_none }}")
|
|
.input-group
|
|
label(for='org-location-field') Location
|
|
input.item-location.input-transparent#org-location-field(
|
|
name="location",
|
|
type="text",
|
|
placeholder="Organization's location",
|
|
value="{{ organization.location | hide_none }}")
|
|
.input-group
|
|
label(for='org-ip-ranges-field') IP Ranges
|
|
textarea.item-ip-ranges#org-ip-ranges-field(
|
|
name="ip_ranges",
|
|
type="text",
|
|
rows="{{ organization.human_ip_ranges|length|default(1, true) }}",
|
|
placeholder="IP ranges in CIDR notation, one on each line",
|
|
title="IPv6 like 2a01:1234:abcd:3b::0/64\nIPv4 like 172.16.0.0/16")
|
|
| {{ organization.human_ip_ranges | join('\n') }}
|
|
p.help-block.
|
|
Clients with a matching IP address will be considered part of the organization. IPv4
|
|
ranges are always normalized to IPv6 prior to saving. Changes to IP Ranges take up
|
|
to an hour to affect already logged-in users.
|
|
|
|
| {% if can_super_edit %}
|
|
.input-group
|
|
label(for='org-seat-count-field') Seat count
|
|
input.item-location.input-transparent#org-seat-count-field(
|
|
name="seat_count",
|
|
type="text",
|
|
placeholder="Seat count",
|
|
value="{{ organization.seat_count | hide_none }}")
|
|
p.help-block Users covered by the IP Ranges do not count towards the seat count.
|
|
.input-group
|
|
label(for='org-roles-field') Roles
|
|
input.item-location.input-transparent#org-roles-field(
|
|
name="org_roles",
|
|
type="text",
|
|
placeholder="Organization roles",
|
|
value="{{ organization.org_roles | hide_none | sort | join(' ') }}")
|
|
| {% endif %}
|
|
|
|
.input-group.org-admin
|
|
label.item-admin-user Organization Administrator
|
|
p#admin-name
|
|
a(href='javascript:showAdminPicker()', title='Click to choose another administrator') {{ admin_user.full_name }}
|
|
p#admin-picker
|
|
input#admin-select.form-control(
|
|
name='admin_user',
|
|
type='text',
|
|
placeholder='Search for a new administrator')
|
|
a(href='javascript:hideAdminPicker()')
|
|
span.text-danger Cancel
|
|
script $('#admin-picker').hide();
|
|
|
|
.input-group
|
|
button#item-save.btn.btn-outline-success.btn-block(type='submit')
|
|
i.pi-check
|
|
| Save Changes
|
|
| {% else %}
|
|
p.item-name {{ organization.name | hide_none }}
|
|
| {% if organization.description %}
|
|
p.item-description {{ organization.description | hide_none }}
|
|
| {% endif %}
|
|
| {% if organization.website %}
|
|
p.item-website
|
|
a(href='{{ organization.website }}', target='_blank') {{ organization.website }}
|
|
| {% endif %}
|
|
| {% if organization.location %}
|
|
p.item-location {{ organization.location | hide_none }}
|
|
| {% endif %}
|
|
p.item-admin-user Organization administrator: {{ admin_user.full_name }}
|
|
| {% endif %}
|
|
|
|
hr
|
|
|
|
h4 Properties
|
|
.table.item-properties
|
|
.table-body
|
|
.table-row.properties-last-updated
|
|
.table-cell Last Updated
|
|
.table-cell(title='Unable to edit, set by Organization')
|
|
| {{ organization._updated | hide_none | pretty_date_time }}
|
|
.table-row.properties-seat-count
|
|
.table-cell Seat Count
|
|
.table-cell(title='Unable to edit, determined by subscription')
|
|
| {{ organization.seat_count }} ({{ seats_used }} used)
|
|
.table-row.properties-org-roles
|
|
.table-cell User roles
|
|
.table-cell(title='Unable to edit, determined by subscription')
|
|
| {{ organization.org_roles | hide_none | sort | join(', ') }}
|
|
|
|
hr
|
|
|
|
h4 Organization members
|
|
.members
|
|
|
|
| {% if can_edit %}
|
|
.sharing-users-search
|
|
.form-group
|
|
input#user-select.form-control(
|
|
name='contacts',
|
|
type='text',
|
|
placeholder='Add member by name')
|
|
| {% endif %}
|
|
|
|
ul.sharing-users-list
|
|
| {% for member in members %}
|
|
li.sharing-users-item(
|
|
data-user-id="{{ member['_id'] }}",
|
|
class="{% if current_user.objectid == member['_id'] %}self{% endif %}")
|
|
.sharing-users-avatar
|
|
img(src="{{ member['avatar'] }}")
|
|
.sharing-users-details
|
|
span.sharing-users-name
|
|
| {{ member['full_name'] }}
|
|
| {% if current_user.objectid == member['_id'] %}
|
|
small (You)
|
|
| {% endif %}
|
|
| {% if organization['admin_uid'] == member['_id'] %}
|
|
small (admin)
|
|
| {% endif %}
|
|
span.sharing-users-extra {{ member['username'] }}
|
|
.sharing-users-action
|
|
| {% if can_edit or current_user.objectid == member['_id'] %}
|
|
| {% if current_user.objectid == member['_id'] %}
|
|
button.user-remove(title="Leave as member of this organization")
|
|
i.pi-trash
|
|
| {% else %}
|
|
button.user-remove(title="Remove this user from this organization")
|
|
i.pi-trash
|
|
| {% endif %}
|
|
| {% endif %}
|
|
| {% else %}
|
|
li
|
|
p.text-warning No members yet
|
|
| {% endfor %}
|
|
|
|
| {% if organization.unknown_members %}
|
|
hr
|
|
|
|
p Pending Members (i.e. without Blender Cloud account)
|
|
ul.sharing-users-list.unknown-members
|
|
| {% for email in organization.unknown_members %}
|
|
li.sharing-users-item.unknown-member(data-user-email='{{ email }}')
|
|
.sharing-users-avatar
|
|
img(src="{{ email | gravatar }}")
|
|
.sharing-users-details
|
|
span.sharing-users-email {{ email }}
|
|
.sharing-users-action
|
|
| {% if can_edit %}
|
|
button.user-remove(title="Remove this user from this organization")
|
|
i.pi-trash
|
|
| {% endif %}
|
|
| {% endfor %}
|
|
| {% endif %}
|
|
|
|
| {% if can_edit %}
|
|
br
|
|
|
|
p Batch-add members by email address:
|
|
form#batch_add_form(onsubmit="return batchAddUsers()")
|
|
.input-group
|
|
textarea.item-description(
|
|
name="emails",
|
|
type="text",
|
|
rows=1,
|
|
placeholder="Enter the email addresses separated by space or a new line")
|
|
|
|
.input-group
|
|
button.btn.btn-info.btn-block(type='submit')
|
|
i.pi-plus
|
|
| Add Members
|
|
| {% endif %}
|
|
|
|
.action-result-panel
|
|
|
|
| {% if config.DEBUG %}
|
|
#item-view-feed
|
|
.debug-info
|
|
a.debug-info-toggle(role='button',
|
|
data-toggle='collapse',
|
|
href='#debug-content-organization',
|
|
aria-expanded='false',
|
|
aria-controls='debug-content-organization')
|
|
i.pi-info
|
|
| Debug Info
|
|
#debug-content-organization.collapse
|
|
pre.
|
|
{{ organization.to_dict() | pprint }}
|
|
| {% endif %}
|
|
|
|
| {% block footer_scripts %}
|
|
|
|
| {% if can_edit %}
|
|
script.
|
|
$(document).ready(function() {
|
|
$('#user-select').userSearch(
|
|
function (event, hit, dataset) {
|
|
var $existing = $('li.sharing-users-item[data-user-id="' + hit.objectID + '"]');
|
|
if ($existing.length) {
|
|
$existing
|
|
.addClass('active')
|
|
.delay(1000)
|
|
.queue(function() {
|
|
$existing.removeClass('active');
|
|
$existing.dequeue();
|
|
});
|
|
toastr.info('User is already member of this organization');
|
|
}
|
|
else {
|
|
addUser(hit.objectID);
|
|
}
|
|
}
|
|
);
|
|
$('#admin-select').userSearch(
|
|
function (event, hit, dataset) {
|
|
setAdmin(hit.objectID, hit.full_name);
|
|
}
|
|
);
|
|
});
|
|
|
|
function addUser(userId) {
|
|
if (!userId || userId.length == 0) {
|
|
toastr.error('Please select a user from the list');
|
|
return;
|
|
}
|
|
|
|
patchOrganization({
|
|
op: 'assign-user',
|
|
user_id: userId
|
|
})
|
|
.done(function (data) {
|
|
setTimeout(function(){ $('.sharing-users-item').removeClass('added');}, 350);
|
|
toastr.success('Member added to this organization!');
|
|
|
|
// TODO fsiddi: avoid the reloading of the entire page?
|
|
window.location.reload();
|
|
})
|
|
.fail(function (err) {
|
|
var msg = xhrErrorResponseMessage(err);
|
|
toastr.error('Could not add member: ' + msg);
|
|
});
|
|
};
|
|
|
|
function setAdmin(user_id, full_name) {
|
|
if (!user_id || user_id.length == 0) {
|
|
toastr.error('Please select a user from the list');
|
|
return;
|
|
}
|
|
|
|
if (!confirm("Are you sure you want to transfer administrator privileges to " + full_name + "?")) {
|
|
hideAdminPicker();
|
|
toastr.warning('Cancelled administrative transfer.');
|
|
return;
|
|
}
|
|
|
|
patchOrganization({
|
|
op: 'assign-admin',
|
|
user_id: user_id
|
|
})
|
|
.done(function (data) {
|
|
window.location.reload();
|
|
toastr.info('Updated admin user');
|
|
})
|
|
.fail(function (err) {
|
|
var msg = xhrErrorResponseMessage(err);
|
|
toastr.error('Could not add member: ' + msg);
|
|
});
|
|
};
|
|
|
|
function editOrganization() {
|
|
var $form = $('#item_form');
|
|
var new_name = $form.find('*[name="name"]').val();
|
|
|
|
{% if can_super_edit %}
|
|
var org_roles_str = $form.find('*[name="org_roles"]').val().trim();
|
|
var org_roles = Array();
|
|
if (org_roles_str.length) org_roles = org_roles_str.split(/\s/);
|
|
{% endif %}
|
|
|
|
var ipr = $form.find('*[name="ip_ranges"]').val().trim();
|
|
if (ipr == '') ip_ranges = Array();
|
|
else ip_ranges = ipr.split(/\s/);
|
|
|
|
patchOrganization({
|
|
op: 'edit-from-web',
|
|
name: new_name,
|
|
description: $form.find('*[name="description"]').val(),
|
|
website: $form.find('*[name="website"]').val(),
|
|
location: $form.find('*[name="location"]').val(),
|
|
ip_ranges: ip_ranges,
|
|
{% if can_super_edit %}
|
|
seat_count: parseInt($form.find('*[name="seat_count"]').val()),
|
|
org_roles: org_roles,
|
|
{% endif %}
|
|
})
|
|
.done(function() {
|
|
$('span.organization-name-{{ organization._id }}').text(new_name);
|
|
item_open('{{ organization._id }}', false);
|
|
})
|
|
.fail(function(err) {
|
|
var msg = xhrErrorResponseMessage(err);
|
|
toastr.error('Error editing organization: ' + msg);
|
|
})
|
|
;
|
|
|
|
return false;
|
|
}
|
|
|
|
function batchAddUsers() {
|
|
var $form = $('#batch_add_form');
|
|
var emails = $form.find('*[name="emails"]').val().split(/\s/);
|
|
console.log(emails);
|
|
|
|
patchOrganization({
|
|
op: 'assign-users',
|
|
emails: emails,
|
|
})
|
|
.done(function() {
|
|
item_open('{{ organization._id }}', false);
|
|
})
|
|
.fail(function(err) {
|
|
var msg = xhrErrorResponseMessage(err);
|
|
toastr.error('Error adding members: ' + msg);
|
|
})
|
|
;
|
|
|
|
return false;
|
|
}
|
|
|
|
function showAdminPicker() {
|
|
$('#admin-name').hide();
|
|
$('#admin-picker').show(function() {
|
|
$(this).find('input').focus();
|
|
});
|
|
}
|
|
function hideAdminPicker() {
|
|
$('#admin-picker').hide();
|
|
$('#admin-name').show();
|
|
}
|
|
|
|
| {% endif %}
|
|
script.
|
|
$(document).ready(function() {
|
|
$('body').off('click', '.user-remove'); // remove previous handlers.
|
|
$('body').on('click', '.user-remove', function(e) {
|
|
var user_id = $(this).closest('*[data-user-id]').data('user-id');
|
|
var user_email = $(this).closest('*[data-user-email]').data('user-email');
|
|
removeUser(user_id, user_email);
|
|
});
|
|
});
|
|
|
|
function patchOrganization(patch) {
|
|
if (typeof patch == 'undefined') {
|
|
throw 'patchOrganization(undefined) called';
|
|
}
|
|
|
|
if (console) console.log('patchOrganization', patch);
|
|
|
|
var promise = $.ajax({
|
|
url: '/api/organizations/{{ organization._id }}',
|
|
method: 'PATCH',
|
|
contentType: 'application/json',
|
|
data: JSON.stringify(patch),
|
|
})
|
|
.fail(function(err) {
|
|
if (console) console.log('Error patching: ', err);
|
|
})
|
|
;
|
|
|
|
return promise;
|
|
}
|
|
|
|
function removeUser(user_id, email) {
|
|
if (typeof user_id == 'undefined' && typeof email == 'undefined') {
|
|
throw "removeUser(undefined, undefined) called";
|
|
}
|
|
var organization_id = '{{ organization._id }}';
|
|
var patch = {op: 'remove-user'};
|
|
|
|
if (typeof user_id !== 'undefined') {
|
|
patch.user_id = user_id;
|
|
}
|
|
if (typeof email !== 'undefined') {
|
|
patch.email = String(email);
|
|
}
|
|
|
|
patchOrganization(patch)
|
|
.done(function() {
|
|
$("ul.sharing-users-list").find("[data-user-id='" + user_id + "']").remove();
|
|
if ('{{ current_user.user_id }}' == user_id) {
|
|
// User removed self, so we cannot open this organization again.
|
|
$('#organization-{{ organization._id}}').remove();
|
|
toastr.success('You left the organization.')
|
|
} else {
|
|
item_open('{{ organization._id }}', false);
|
|
toastr.success('User removed from this organization');
|
|
}
|
|
}).fail(function (data) {
|
|
var msg = xhrErrorResponseMessage(data);
|
|
toastr.error('Error removing user: ' + msg);
|
|
});
|
|
}
|
|
|
|
| {% endblock %}
|