mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-09-19 19:44:40 +08:00
Merge branch 'features/protocol_versioning' into sb_SCI-8007
This commit is contained in:
commit
c4bdbdec9a
33 changed files with 322 additions and 164 deletions
|
@ -38,19 +38,19 @@ function initEditProtocolDescription() {
|
||||||
function initLinkUpdate() {
|
function initLinkUpdate() {
|
||||||
var modal = $('#confirm-link-update-modal');
|
var modal = $('#confirm-link-update-modal');
|
||||||
var modalTitle = modal.find('.modal-title');
|
var modalTitle = modal.find('.modal-title');
|
||||||
var modalBody = modal.find('.modal-body');
|
var modalMessage = modal.find('.modal-body .message');
|
||||||
var updateBtn = modal.find(".modal-footer [data-action='submit']");
|
var updateBtn = modal.find(".modal-footer [data-action='submit']");
|
||||||
$("[data-action='unlink'], [data-action='revert'], [data-action='update-parent'], [data-action='update-self']")
|
$("[data-action='unlink'], [data-action='revert'], [data-action='update-parent'], [data-action='update-self']")
|
||||||
.on('ajax:success', function(e, data) {
|
.on('ajax:success', function(e, data) {
|
||||||
modalTitle.html(data.title);
|
modalTitle.html(data.title);
|
||||||
modalBody.html(data.message);
|
modalMessage.html(data.message);
|
||||||
updateBtn.text(data.btn_text);
|
updateBtn.text(data.btn_text);
|
||||||
modal.attr('data-url', data.url);
|
modal.attr('data-url', data.url);
|
||||||
modal.modal('show');
|
modal.modal('show');
|
||||||
});
|
});
|
||||||
|
|
||||||
modal.on('hidden.bs.modal', function() {
|
modal.on('hidden.bs.modal', function() {
|
||||||
modalBody.html('');
|
modalMessage.html('');
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!$._data(updateBtn[0], 'events')) {
|
if (!$._data(updateBtn[0], 'events')) {
|
||||||
|
|
|
@ -135,9 +135,30 @@ var ProtocolsIndex = (function() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function initManageAccessButton() {
|
function initManageAccess() {
|
||||||
$('.protocols-index').on('click', '#manageProtocolAccess', function() {
|
let protocolsContainer = '.protocols-container';
|
||||||
$(`tr[data-row-id=${rowsSelected[0]}] .protocol-users-link`).click();
|
let manageAccessModal = '.protocol-assignments-modal';
|
||||||
|
|
||||||
|
function loadManageAccessModal(href) {
|
||||||
|
$.get(href, function(data) {
|
||||||
|
$(protocolsContainer).append($.parseHTML(data.html));
|
||||||
|
$(manageAccessModal).modal('show');
|
||||||
|
|
||||||
|
// Remove modal when it gets closed
|
||||||
|
$(manageAccessModal).on('hidden.bs.modal', function() {
|
||||||
|
$(manageAccessModal).remove();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protocolsTableEl.on('click', '.protocol-users-link', function(e) {
|
||||||
|
loadManageAccessModal(this.href);
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
$(protocolsContainer).on('click', '#manageProtocolAccess', function() {
|
||||||
|
loadManageAccessModal($(`tr[data-row-id=${rowsSelected[0]}] .protocol-users-link`).attr('href'));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,8 +201,8 @@ var ProtocolsIndex = (function() {
|
||||||
targets: 0,
|
targets: 0,
|
||||||
searchable: false,
|
searchable: false,
|
||||||
orderable: false,
|
orderable: false,
|
||||||
sWidth: "1%",
|
sWidth: '1%',
|
||||||
render: function (data, type, full, meta) {
|
render: function() {
|
||||||
return `<div class="sci-checkbox-container">
|
return `<div class="sci-checkbox-container">
|
||||||
<input type="checkbox" class="sci-checkbox">
|
<input type="checkbox" class="sci-checkbox">
|
||||||
<span class="sci-checkbox-label"></span>
|
<span class="sci-checkbox-label"></span>
|
||||||
|
@ -244,7 +265,7 @@ var ProtocolsIndex = (function() {
|
||||||
fnInitComplete: function(e) {
|
fnInitComplete: function(e) {
|
||||||
var dataTableWrapper = $(e.nTableWrapper);
|
var dataTableWrapper = $(e.nTableWrapper);
|
||||||
DataTableHelpers.initLengthAppearance(dataTableWrapper);
|
DataTableHelpers.initLengthAppearance(dataTableWrapper);
|
||||||
DataTableHelpers.initSearchField(dataTableWrapper, 'Enter...');
|
DataTableHelpers.initSearchField(dataTableWrapper, I18n.t('protocols.index.search_bar_placeholder'));
|
||||||
dataTableWrapper.find('.main-actions, .pagination-row').removeClass('hidden');
|
dataTableWrapper.find('.main-actions, .pagination-row').removeClass('hidden');
|
||||||
|
|
||||||
let actionToolBar = $($('#protocolActionToolbar').html());
|
let actionToolBar = $($('#protocolActionToolbar').html());
|
||||||
|
@ -675,29 +696,18 @@ var ProtocolsIndex = (function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateDataTableSelectAllCheckbox() {
|
function updateDataTableSelectAllCheckbox() {
|
||||||
var table = protocolsDatatable.table().node();
|
var table = $('.protocols-datatable');
|
||||||
var checkboxesAll = $("tbody input[type='checkbox']", protocolsTableEl);
|
var checkboxes = table.find("tbody input[type='checkbox']");
|
||||||
var checkboxesChecked = $("tbody input[type='checkbox']:checked", protocolsTableEl);
|
var selectedCheckboxes = table.find("tbody input[type='checkbox']:checked");
|
||||||
var checkboxSelectAll = $("thead input[name='select_all']", table).get(0);
|
var selectAllCheckbox = table.find("thead input[name='select_all']");
|
||||||
|
|
||||||
if (checkboxesChecked.length === 0) {
|
selectAllCheckbox.prop('indeterminate', false);
|
||||||
// If none of the checkboxes are checked
|
if (selectedCheckboxes.length === 0) {
|
||||||
checkboxSelectAll.checked = false;
|
selectAllCheckbox.prop('checked', false);
|
||||||
if ('indeterminate' in checkboxSelectAll) {
|
} else if (selectedCheckboxes.length === checkboxes.length) {
|
||||||
checkboxSelectAll.indeterminate = false;
|
selectAllCheckbox.prop('checked', true);
|
||||||
}
|
|
||||||
} else if (checkboxesChecked.length === checkboxesAll.length) {
|
|
||||||
// If all of the checkboxes are checked
|
|
||||||
checkboxSelectAll.checked = true;
|
|
||||||
if ('indeterminate' in checkboxSelectAll) {
|
|
||||||
checkboxSelectAll.indeterminate = false;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// If some of the checkboxes are checked
|
selectAllCheckbox.prop('indeterminate', true);
|
||||||
checkboxSelectAll.checked = true;
|
|
||||||
if ('indeterminate' in checkboxSelectAll) {
|
|
||||||
checkboxSelectAll.indeterminate = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1002,7 +1012,7 @@ var ProtocolsIndex = (function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
init();
|
init();
|
||||||
initManageAccessButton();
|
initManageAccess();
|
||||||
initArchiveProtocols();
|
initArchiveProtocols();
|
||||||
initRestoreProtocols();
|
initRestoreProtocols();
|
||||||
initExportProtocols();
|
initExportProtocols();
|
||||||
|
|
|
@ -1,10 +1,16 @@
|
||||||
/* global dropdownSelector HelperModule */
|
/* global dropdownSelector HelperModule */
|
||||||
(function() {
|
(function() {
|
||||||
$('#newProtocolModal').on('change', '#protocol_visibility', function() {
|
const protocolModal = '#newProtocolModal';
|
||||||
$('#roleSelectWrapper').toggleClass('hidden', !$(this)[0].checked);
|
$(protocolModal)
|
||||||
});
|
.on('change', '#protocol_visibility', function() {
|
||||||
|
$('#roleSelectWrapper').toggleClass('hidden', !$(this)[0].checked);
|
||||||
|
})
|
||||||
|
.on('show.bs.modal', function() {
|
||||||
|
$(`${protocolModal} #protocol_name`).parent().removeClass('error');
|
||||||
|
$(`${protocolModal} form[data-action="new"] #protocol_name`).val('');
|
||||||
|
});
|
||||||
|
|
||||||
let roleSelector = '#newProtocolModal #protocol_role_selector';
|
let roleSelector = `${protocolModal} #protocol_role_selector`;
|
||||||
dropdownSelector.init(roleSelector, {
|
dropdownSelector.init(roleSelector, {
|
||||||
noEmptyOption: true,
|
noEmptyOption: true,
|
||||||
singleSelect: true,
|
singleSelect: true,
|
||||||
|
@ -15,16 +21,16 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#newProtocolModal')
|
$(protocolModal)
|
||||||
.on('ajax:error', 'form', function(e, error) {
|
.on('ajax:error', 'form', function(e, error) {
|
||||||
let msg = error.responseJSON.error;
|
let msg = error.responseJSON.error;
|
||||||
$('#newProtocolModal #protocol_name').parent().addClass('error').attr('data-error-text', msg);
|
$(`${protocolModal} #protocol_name`).parent().addClass('error').attr('data-error-text', msg);
|
||||||
})
|
})
|
||||||
.on('ajax:success', 'form', function(e, data) {
|
.on('ajax:success', 'form', function(e, data) {
|
||||||
if (data.message) {
|
if (data.message) {
|
||||||
HelperModule.flashAlertMsg(data.message, 'success');
|
HelperModule.flashAlertMsg(data.message, 'success');
|
||||||
}
|
}
|
||||||
$('#newProtocolModal #protocol_name').parent().removeClass('error');
|
$(`${protocolModal} #protocol_name`).parent().removeClass('error');
|
||||||
$('#newProtocolModal').modal('hide');
|
$(protocolModal).modal('hide');
|
||||||
});
|
});
|
||||||
}());
|
}());
|
||||||
|
|
|
@ -22,7 +22,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-body {
|
.modal-body {
|
||||||
min-height: calc(100vh - 200px);
|
max-height: calc(100vh - 190px);
|
||||||
|
min-height: 370px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,10 @@
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
|
a:first-of-type:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
.task-section-caret {
|
.task-section-caret {
|
||||||
padding-right: .25em;
|
padding-right: .25em;
|
||||||
}
|
}
|
||||||
|
|
|
@ -428,9 +428,14 @@
|
||||||
width: 506px;
|
width: 506px;
|
||||||
padding: 15px 0;
|
padding: 15px 0;
|
||||||
|
|
||||||
|
.dropdown-content {
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
.dropdown-header,
|
.dropdown-header,
|
||||||
.dropdown-body {
|
.dropdown-body,
|
||||||
padding: 10px 24px;
|
.dropdown-footer {
|
||||||
|
padding: 12px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-header {
|
.dropdown-header {
|
||||||
|
@ -508,7 +513,6 @@
|
||||||
|
|
||||||
.dropdown-footer {
|
.dropdown-footer {
|
||||||
border-top: $border-tertiary;
|
border-top: $border-tertiary;
|
||||||
padding: 12px 0 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -670,8 +674,14 @@
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#confirm-link-update-modal {
|
#confirm-link-update-modal,
|
||||||
|
.delete-steps-modal {
|
||||||
|
.modal-body p {
|
||||||
|
margin: 1.2em 0;
|
||||||
|
}
|
||||||
|
|
||||||
.warning {
|
.warning {
|
||||||
margin: 0 15px 15px;
|
font-weight: bold;
|
||||||
|
margin-bottom: 1.2em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,18 @@
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.table.dataTable .sorting {
|
||||||
|
&::after {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
&::after {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar {
|
.toolbar {
|
||||||
|
@ -61,6 +73,10 @@
|
||||||
.dataTables_scrollBody {
|
.dataTables_scrollBody {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
|
td:first-child {
|
||||||
|
padding-top: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
td:not(:first-child) {
|
td:not(:first-child) {
|
||||||
padding: 14px 8px;
|
padding: 14px 8px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.details-container {
|
.protocol-details {
|
||||||
.protocol-metadata {
|
.protocol-metadata {
|
||||||
margin-bottom: 2em;
|
margin-bottom: 2em;
|
||||||
|
|
||||||
|
|
|
@ -53,21 +53,36 @@ module AccessPermissions
|
||||||
permitted_create_params[:resource_members].each do |_k, user_assignment_params|
|
permitted_create_params[:resource_members].each do |_k, user_assignment_params|
|
||||||
next unless user_assignment_params[:assign] == '1'
|
next unless user_assignment_params[:assign] == '1'
|
||||||
|
|
||||||
user_assignment = UserAssignment.find_or_initialize_by(
|
if user_assignment_params[:user_id] == 'all'
|
||||||
assignable: @project,
|
@project.update!(visibility: :visible, default_public_user_role_id: user_assignment_params[:user_role_id])
|
||||||
user_id: user_assignment_params[:user_id],
|
Activities::CreateActivityService
|
||||||
team: current_team
|
.call(activity_type: :change_project_visibility,
|
||||||
)
|
owner: current_user,
|
||||||
|
subject: @project,
|
||||||
|
team: @project.team,
|
||||||
|
project: @project,
|
||||||
|
message_items: {
|
||||||
|
project: @project.id,
|
||||||
|
visibility: t('projects.activity.visibility_visible')
|
||||||
|
})
|
||||||
|
else
|
||||||
|
|
||||||
user_assignment.update!(
|
user_assignment = UserAssignment.find_or_initialize_by(
|
||||||
user_role_id: user_assignment_params[:user_role_id],
|
assignable: @project,
|
||||||
assigned_by: current_user,
|
user_id: user_assignment_params[:user_id],
|
||||||
assigned: :manually
|
team: current_team
|
||||||
)
|
)
|
||||||
|
|
||||||
log_activity(:assign_user_to_project, user_assignment)
|
user_assignment.update!(
|
||||||
created_count += 1
|
user_role_id: user_assignment_params[:user_role_id],
|
||||||
propagate_job(user_assignment)
|
assigned_by: current_user,
|
||||||
|
assigned: :manually
|
||||||
|
)
|
||||||
|
|
||||||
|
log_activity(:assign_user_to_project, user_assignment)
|
||||||
|
created_count += 1
|
||||||
|
propagate_job(user_assignment)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
|
|
|
@ -51,25 +51,31 @@ module AccessPermissions
|
||||||
permitted_create_params[:resource_members].each do |_k, user_assignment_params|
|
permitted_create_params[:resource_members].each do |_k, user_assignment_params|
|
||||||
next unless user_assignment_params[:assign] == '1'
|
next unless user_assignment_params[:assign] == '1'
|
||||||
|
|
||||||
user_assignment = UserAssignment.find_or_initialize_by(
|
if user_assignment_params[:user_id] == 'all'
|
||||||
assignable: @protocol,
|
@protocol.update!(visibility: :visible, default_public_user_role_id: user_assignment_params[:user_role_id])
|
||||||
user_id: user_assignment_params[:user_id],
|
else
|
||||||
team: current_team
|
user_assignment = UserAssignment.find_or_initialize_by(
|
||||||
)
|
assignable: @protocol,
|
||||||
|
user_id: user_assignment_params[:user_id],
|
||||||
|
team: current_team
|
||||||
|
)
|
||||||
|
|
||||||
user_assignment.update!(
|
user_assignment.update!(
|
||||||
user_role_id: user_assignment_params[:user_role_id],
|
user_role_id: user_assignment_params[:user_role_id],
|
||||||
assigned_by: current_user,
|
assigned_by: current_user,
|
||||||
assigned: :manually
|
assigned: :manually
|
||||||
)
|
)
|
||||||
|
|
||||||
created_count += 1
|
created_count += 1
|
||||||
log_activity(:protocol_template_access_granted, user_assignment)
|
log_activity(:protocol_template_access_granted, user_assignment)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
@message = t('access_permissions.create.success', count: created_count)
|
@message = t('access_permissions.create.success', count: created_count)
|
||||||
format.json { render :edit }
|
format.json { render :edit }
|
||||||
end
|
end
|
||||||
|
|
||||||
rescue ActiveRecord::RecordInvalid
|
rescue ActiveRecord::RecordInvalid
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
@message = t('access_permissions.create.failure')
|
@message = t('access_permissions.create.failure')
|
||||||
|
|
|
@ -127,10 +127,7 @@ class ProtocolsDatatable < CustomDatatable
|
||||||
records = records.where(protocols: { published_by_id: params[:published_by] }) if params[:published_by].present?
|
records = records.where(protocols: { published_by_id: params[:published_by] }) if params[:published_by].present?
|
||||||
|
|
||||||
if params[:members].present?
|
if params[:members].present?
|
||||||
records = records.joins('LEFT OUTER JOIN "user_assignments" "all_user_assignments" '\
|
records = records.where(all_user_assignments: { user_id: params[:members] })
|
||||||
'ON "all_user_assignments"."assignable_type" = \'Protocol\' '\
|
|
||||||
'AND "all_user_assignments"."assignable_id" = "protocols"."id"')
|
|
||||||
.where(all_user_assignments: { user_id: params[:members] })
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if params[:archived_on_from].present?
|
if params[:archived_on_from].present?
|
||||||
|
@ -141,7 +138,13 @@ class ProtocolsDatatable < CustomDatatable
|
||||||
records = records.where(protocols: { archived_by_id: params[:archived_by] }) if params[:archived_by].present?
|
records = records.where(protocols: { archived_by_id: params[:archived_by] }) if params[:archived_by].present?
|
||||||
|
|
||||||
if params[:has_draft].present?
|
if params[:has_draft].present?
|
||||||
records = records.where(protocols: { protocol_type: Protocol.protocol_types[:in_repository_draft] })
|
records =
|
||||||
|
records
|
||||||
|
.joins("LEFT OUTER JOIN protocols protocol_drafts " \
|
||||||
|
"ON protocol_drafts.protocol_type = #{Protocol.protocol_types[:in_repository_draft]} " \
|
||||||
|
"AND (protocol_drafts.parent_id = protocols.id OR protocol_drafts.parent_id = protocols.parent_id)")
|
||||||
|
.where('protocols.protocol_type = ? OR protocol_drafts.id IS NOT NULL',
|
||||||
|
Protocol.protocol_types[:in_repository_draft])
|
||||||
end
|
end
|
||||||
|
|
||||||
records
|
records
|
||||||
|
@ -199,6 +202,9 @@ class ProtocolsDatatable < CustomDatatable
|
||||||
'ON "protocol_protocol_keywords"."protocol_keyword_id" = "protocol_keywords"."id"')
|
'ON "protocol_protocol_keywords"."protocol_keyword_id" = "protocol_keywords"."id"')
|
||||||
.joins('LEFT OUTER JOIN "users" "archived_users" ON "archived_users"."id" = "protocols"."archived_by_id"')
|
.joins('LEFT OUTER JOIN "users" "archived_users" ON "archived_users"."id" = "protocols"."archived_by_id"')
|
||||||
.joins('LEFT OUTER JOIN "users" ON "users"."id" = "protocols"."published_by_id"')
|
.joins('LEFT OUTER JOIN "users" ON "users"."id" = "protocols"."published_by_id"')
|
||||||
|
.joins('LEFT OUTER JOIN "user_assignments" "all_user_assignments" '\
|
||||||
|
'ON "all_user_assignments"."assignable_type" = \'Protocol\' '\
|
||||||
|
'AND "all_user_assignments"."assignable_id" = "protocols"."id"')
|
||||||
.group('"protocols"."id"')
|
.group('"protocols"."id"')
|
||||||
|
|
||||||
records = filter_protocols_records(records)
|
records = filter_protocols_records(records)
|
||||||
|
@ -212,7 +218,7 @@ class ProtocolsDatatable < CustomDatatable
|
||||||
'(COUNT(DISTINCT("self_linked_task_protocols"."id")) + ' \
|
'(COUNT(DISTINCT("self_linked_task_protocols"."id")) + ' \
|
||||||
'COUNT(DISTINCT("parent_linked_task_protocols"."id")) + ' \
|
'COUNT(DISTINCT("parent_linked_task_protocols"."id")) + ' \
|
||||||
'COUNT(DISTINCT("version_linked_task_protocols"."id"))) AS nr_of_linked_tasks',
|
'COUNT(DISTINCT("version_linked_task_protocols"."id"))) AS nr_of_linked_tasks',
|
||||||
'COUNT("user_assignments"."id") AS "nr_of_assigned_users"',
|
'COUNT(DISTINCT("all_user_assignments"."id")) AS "nr_of_assigned_users"',
|
||||||
'MAX("users"."full_name") AS "full_username_str"', # "Hack" to get single username
|
'MAX("users"."full_name") AS "full_username_str"', # "Hack" to get single username
|
||||||
'MAX("archived_users"."full_name") AS "archived_full_username_str"'
|
'MAX("archived_users"."full_name") AS "archived_full_username_str"'
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module UserRolesHelper
|
module UserRolesHelper
|
||||||
def user_roles_collection(with_inherit: false)
|
def user_roles_collection(object, with_inherit: false)
|
||||||
roles = UserRole.order(id: :asc).pluck(:name, :id)
|
permission_group = "#{object.class.name}Permissions".constantize
|
||||||
|
permissions = permission_group.constants.map { |const| permission_group.const_get(const) }
|
||||||
|
|
||||||
|
roles = user_roles_subset_by_permissions(permissions).order(id: :asc).pluck(:name, :id)
|
||||||
roles = [[t('access_permissions.reset'), 'reset']] + roles if with_inherit
|
roles = [[t('access_permissions.reset'), 'reset']] + roles if with_inherit
|
||||||
roles
|
roles
|
||||||
end
|
end
|
||||||
|
@ -12,9 +15,10 @@ module UserRolesHelper
|
||||||
PermissionExtends::TeamPermissions.constants.map { |const| TeamPermissions.const_get(const) } +
|
PermissionExtends::TeamPermissions.constants.map { |const| TeamPermissions.const_get(const) } +
|
||||||
ProtocolPermissions.constants.map { |const| ProtocolPermissions.const_get(const) } +
|
ProtocolPermissions.constants.map { |const| ProtocolPermissions.const_get(const) } +
|
||||||
RepositoryPermissions.constants.map { |const| RepositoryPermissions.const_get(const) }
|
RepositoryPermissions.constants.map { |const| RepositoryPermissions.const_get(const) }
|
||||||
UserRole.where('permissions && ARRAY[?]::varchar[]', team_permissions)
|
|
||||||
.sort_by { |user_role| (user_role.permissions & team_permissions).length }
|
user_roles_subset_by_permissions(team_permissions)
|
||||||
.reverse!
|
.sort_by { |user_role| (user_role.permissions & team_permissions).length }
|
||||||
|
.reverse!
|
||||||
end
|
end
|
||||||
|
|
||||||
def team_user_roles_for_select
|
def team_user_roles_for_select
|
||||||
|
@ -22,6 +26,12 @@ module UserRolesHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def managing_team_user_roles_collection
|
def managing_team_user_roles_collection
|
||||||
UserRole.where('permissions && ARRAY[?]::varchar[]', [TeamPermissions::USERS_MANAGE])
|
user_roles_subset_by_permissions([TeamPermissions::USERS_MANAGE])
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def user_roles_subset_by_permissions(permissions)
|
||||||
|
UserRole.where('permissions && ARRAY[?]::varchar[]', permissions)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,8 +10,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<p>{{ i18n.t('protocols.steps.modals.delete_steps.description_1')}}</p>
|
<p>{{ i18n.t('protocols.steps.modals.delete_steps.description_1')}}</p>
|
||||||
<p><b>{{ i18n.t('protocols.steps.modals.delete_steps.description_2')}}</b></p>
|
<p class="warning">{{ i18n.t('protocols.steps.modals.delete_steps.description_2')}}</p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button class="btn btn-secondary" @click="cancel">{{ i18n.t('general.cancel') }}</button>
|
<button class="btn btn-secondary" @click="cancel">{{ i18n.t('general.cancel') }}</button>
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
<button class="btn btn-light" @click="openVersionsModal">{{ i18n.t("protocols.header.versions") }}</button>
|
<button class="btn btn-light" @click="openVersionsModal">{{ i18n.t("protocols.header.versions") }}</button>
|
||||||
<button v-if="protocol.attributes.urls.publish_url" @click="$emit('publish')" class="btn btn-primary">{{ i18n.t("protocols.header.publish") }}</button>
|
<button v-if="protocol.attributes.urls.publish_url" @click="$emit('publish')" class="btn btn-primary">{{ i18n.t("protocols.header.publish") }}</button>
|
||||||
<button v-if="protocol.attributes.urls.save_as_draft_url" @click="saveAsdraft" class="btn btn-secondary">{{ i18n.t("protocols.header.save_as_draft") }}</button>
|
<button v-if="protocol.attributes.urls.save_as_draft_url" @click="saveAsdraft" class="btn btn-secondary">{{ i18n.t("protocols.header.save_as_draft") }}</button>
|
||||||
|
<button v-bind:disabled="protocol.attributes.disabled_drafting" v-if="protocol.attributes.disabled_drafting" @click="saveAsdraft" class="btn btn-secondary">{{ i18n.t("protocols.header.save_as_draft") }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="details-container" class="protocol-details collapse in">
|
<div id="details-container" class="protocol-details collapse in">
|
||||||
|
|
|
@ -21,6 +21,7 @@ class Protocol < ApplicationRecord
|
||||||
after_save :update_user_assignments, if: -> { saved_change_to_visibility? && in_repository? }
|
after_save :update_user_assignments, if: -> { saved_change_to_visibility? && in_repository? }
|
||||||
after_save :update_linked_children
|
after_save :update_linked_children
|
||||||
skip_callback :create, :after, :create_users_assignments, if: -> { in_module? }
|
skip_callback :create, :after, :create_users_assignments, if: -> { in_module? }
|
||||||
|
before_update :sync_protocol_assignments, if: :visibility_changed?
|
||||||
|
|
||||||
enum visibility: { hidden: 0, visible: 1 }
|
enum visibility: { hidden: 0, visible: 1 }
|
||||||
enum protocol_type: {
|
enum protocol_type: {
|
||||||
|
@ -230,6 +231,11 @@ class Protocol < ApplicationRecord
|
||||||
teams.blank? ? self : where(team: teams)
|
teams.blank? ? self : where(team: teams)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def original_code
|
||||||
|
# returns linked protocol code, or code of the original version of the linked protocol
|
||||||
|
parent&.parent&.code || parent&.code || code
|
||||||
|
end
|
||||||
|
|
||||||
def insert_step(step, position)
|
def insert_step(step, position)
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
steps.where('position >= ?', position).desc_order.each do |s|
|
steps.where('position >= ?', position).desc_order.each do |s|
|
||||||
|
@ -793,4 +799,12 @@ class Protocol < ApplicationRecord
|
||||||
errors.add(:base, I18n.t('activerecord.errors.models.protocol.wrong_parent_draft_number'))
|
errors.add(:base, I18n.t('activerecord.errors.models.protocol.wrong_parent_draft_number'))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def sync_protocol_assignments
|
||||||
|
if visible?
|
||||||
|
auto_assign_protocol_members
|
||||||
|
else
|
||||||
|
user_assignments.where(assigned: :automatically).destroy_all
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -105,11 +105,11 @@ Canaid::Permissions.register_for(Protocol) do
|
||||||
|
|
||||||
# protocol in repository: restore
|
# protocol in repository: restore
|
||||||
can :restore_protocol_in_repository do |user, protocol|
|
can :restore_protocol_in_repository do |user, protocol|
|
||||||
protocol.archived? && protocol.permission_granted?(user, ProtocolPermissions::MANAGE)
|
protocol.archived? && protocol.permission_granted?(user, ProtocolPermissions::RESTORE)
|
||||||
end
|
end
|
||||||
|
|
||||||
can :archive_protocol_in_repository do |user, protocol|
|
can :archive_protocol_in_repository do |user, protocol|
|
||||||
protocol.active? && protocol.permission_granted?(user, ProtocolPermissions::MANAGE)
|
protocol.active? && protocol.permission_granted?(user, ProtocolPermissions::ARCHIVE)
|
||||||
end
|
end
|
||||||
|
|
||||||
# protocol in repository: copy
|
# protocol in repository: copy
|
||||||
|
@ -119,7 +119,7 @@ Canaid::Permissions.register_for(Protocol) do
|
||||||
|
|
||||||
can :publish_protocol_in_repository do |user, protocol|
|
can :publish_protocol_in_repository do |user, protocol|
|
||||||
protocol.in_repository_draft? &&
|
protocol.in_repository_draft? &&
|
||||||
protocol.permission_granted?(user, ProtocolPermissions::MANAGE)
|
protocol.permission_granted?(user, ProtocolPermissions::PUBLISH)
|
||||||
end
|
end
|
||||||
|
|
||||||
can :delete_protocol_draft_in_repository do |user, protocol|
|
can :delete_protocol_draft_in_repository do |user, protocol|
|
||||||
|
|
|
@ -8,7 +8,7 @@ class ProtocolSerializer < ActiveModel::Serializer
|
||||||
|
|
||||||
attributes :name, :id, :urls, :description, :description_view, :updated_at, :in_repository,
|
attributes :name, :id, :urls, :description, :description_view, :updated_at, :in_repository,
|
||||||
:created_at_formatted, :updated_at_formatted, :added_by, :authors, :keywords, :version, :code,
|
:created_at_formatted, :updated_at_formatted, :added_by, :authors, :keywords, :version, :code,
|
||||||
:published, :version_comment, :archived
|
:published, :version_comment, :archived, :disabled_drafting
|
||||||
|
|
||||||
def updated_at
|
def updated_at
|
||||||
object.updated_at.to_i
|
object.updated_at.to_i
|
||||||
|
@ -84,6 +84,14 @@ class ProtocolSerializer < ActiveModel::Serializer
|
||||||
!object.in_module?
|
!object.in_module?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def disabled_drafting
|
||||||
|
protocol_types = Protocol.where(name: object.name).pluck(:protocol_type)
|
||||||
|
object.protocol_type != 'in_repository_draft' &&
|
||||||
|
!object.archived &&
|
||||||
|
protocol_types.length > 1 &&
|
||||||
|
protocol_types.include?('in_repository_draft')
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def load_from_repo_url
|
def load_from_repo_url
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
</button>
|
</button>
|
||||||
<%= f.hidden_field :default_public_user_role_id, value: f.object.default_public_user_role.id, class: "default-public-user-role-id" %>
|
<%= f.hidden_field :default_public_user_role_id, value: f.object.default_public_user_role.id, class: "default-public-user-role-id" %>
|
||||||
<ul class="dropdown-menu dropdown-menu-right user-assignment-dropdown" aria-labelledby="defaultPublicUserRole">
|
<ul class="dropdown-menu dropdown-menu-right user-assignment-dropdown" aria-labelledby="defaultPublicUserRole">
|
||||||
<% user_roles_collection.each do |role| %>
|
<% user_roles_collection(assignable).each do |role| %>
|
||||||
<li>
|
<li>
|
||||||
<a href="#" data-turbolinks="false" class="user-role-selector" data-role-id="<%= role[1] %>">
|
<a href="#" data-turbolinks="false" class="user-role-selector" data-role-id="<%= role[1] %>">
|
||||||
<%= role[0] %>
|
<%= role[0] %>
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
</button>
|
</button>
|
||||||
<%= f.hidden_field :user_role_id, value: f.object.user_role.id %>
|
<%= f.hidden_field :user_role_id, value: f.object.user_role.id %>
|
||||||
<ul class="dropdown-menu dropdown-menu-right user-assignment-dropdown" aria-labelledby="userAccess_<%= user.id %>">
|
<ul class="dropdown-menu dropdown-menu-right user-assignment-dropdown" aria-labelledby="userAccess_<%= user.id %>">
|
||||||
<% user_roles_collection(with_inherit: with_inherit).each do |role| %>
|
<% user_roles_collection(assignable, with_inherit: with_inherit).each do |role| %>
|
||||||
<li>
|
<li>
|
||||||
<a href="#" data-turbolinks="false" class="user-role-selector" data-role-id="<%= role[1] %>">
|
<a href="#" data-turbolinks="false" class="user-role-selector" data-role-id="<%= role[1] %>">
|
||||||
<%= role[0] %>
|
<%= role[0] %>
|
||||||
|
|
|
@ -16,9 +16,14 @@
|
||||||
<%= text_field_tag :search_users, '', placeholder: t('.find_people_html'), class: 'sci-input-field', data: { action: 'filter-list', target: 'new-user-assignment-to-project-form' } %>
|
<%= text_field_tag :search_users, '', placeholder: t('.find_people_html'), class: 'sci-input-field', data: { action: 'filter-list', target: 'new-user-assignment-to-project-form' } %>
|
||||||
<i class="fas fa-search"></i>
|
<i class="fas fa-search"></i>
|
||||||
</div>
|
</div>
|
||||||
|
<% if assignable.visibility && assignable.visibility == 'hidden' %>
|
||||||
|
<%= f.fields_for :users, UserAssignment.new do |user_form| %>
|
||||||
|
<%= render 'access_permissions/partials/public_assignment_field.html.erb', user_form: user_form, assignable: assignable %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
<% users.each do |user| %>
|
<% users.each do |user| %>
|
||||||
<%= f.fields_for :users, UserAssignment.new(user: user) do |user_form| %>
|
<%= f.fields_for :users, UserAssignment.new(user: user) do |user_form| %>
|
||||||
<%= render 'access_permissions/partials/user_assignment_field.html.erb', user_form: user_form %>
|
<%= render 'access_permissions/partials/user_assignment_field.html.erb', user_form: user_form, assignable: assignable %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
<% # frozen_string_literal: true %>
|
||||||
|
|
||||||
|
<div class="member-item new-member-item">
|
||||||
|
<%= user_form.hidden_field :user_id, value: :all, name:"access_permissions_new_user_form[resource_members][0][user_id]" %>
|
||||||
|
<div class="user-assignment-info">
|
||||||
|
<div class="sci-checkbox-container">
|
||||||
|
<%= user_form.check_box :assign,
|
||||||
|
name: "access_permissions_new_user_form[resource_members][0][assign]",
|
||||||
|
data: { action: 'toggle-visibility', target: 'usersAll' },
|
||||||
|
class: "sci-checkbox"
|
||||||
|
%>
|
||||||
|
<span class="sci-checkbox-label"></span>
|
||||||
|
</div>
|
||||||
|
<div class="global-avatar-container">
|
||||||
|
<%= image_tag "icon/team.png", class: 'img-circle pull-left' %>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<%= t('user_assignment.assign_all_team_members') %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="user-assignment-controls">
|
||||||
|
<div class="user-assignment-role hidden" id="usersAll">
|
||||||
|
<%= user_form.select :user_role_id,
|
||||||
|
options_for_select(user_roles_collection(assignable)),
|
||||||
|
{},
|
||||||
|
name: "access_permissions_new_user_form[resource_members][0][user_role_id]",
|
||||||
|
class: 'form-control selectpicker pull-right',
|
||||||
|
title: t('user_assignment.select_role') %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -26,7 +26,7 @@
|
||||||
<div class="user-assignment-controls">
|
<div class="user-assignment-controls">
|
||||||
<div class="user-assignment-role hidden" id="<%= id %>">
|
<div class="user-assignment-role hidden" id="<%= id %>">
|
||||||
<%= user_form.select :user_role_id,
|
<%= user_form.select :user_role_id,
|
||||||
options_for_select(user_roles_collection),
|
options_for_select(user_roles_collection(assignable)),
|
||||||
{},
|
{},
|
||||||
name: "access_permissions_new_user_form[resource_members][#{user.id}][user_role_id]",
|
name: "access_permissions_new_user_form[resource_members][#{user.id}][user_role_id]",
|
||||||
class: 'form-control selectpicker pull-right',
|
class: 'form-control selectpicker pull-right',
|
||||||
|
|
|
@ -5,8 +5,10 @@
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||||
<h4 class="modal-title" id="confirm-link-update-modal-label"></h4>
|
<h4 class="modal-title" id="confirm-link-update-modal-label"></h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body"></div>
|
<div class="modal-body">
|
||||||
<h3 class="warning"><%= t('my_modules.protocols.confirm_link_update_modal.warning') %></h3>
|
<p class="message"></p>
|
||||||
|
<p class="warning"><%= t('my_modules.protocols.confirm_link_update_modal.warning') %></p>
|
||||||
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal"><%= t("general.cancel") %></button>
|
<button type="button" class="btn btn-default" data-dismiss="modal"><%= t("general.cancel") %></button>
|
||||||
<button type="button" class="btn btn-success" data-action="submit"></button>
|
<button type="button" class="btn btn-success" data-action="submit"></button>
|
||||||
|
|
|
@ -15,53 +15,57 @@
|
||||||
<i class="fas fa-info-circle"></i>
|
<i class="fas fa-info-circle"></i>
|
||||||
</a>
|
</a>
|
||||||
<div class="dropdown-menu status-info-dropdown" aria-labelledby="my-module-protocol-info-button">
|
<div class="dropdown-menu status-info-dropdown" aria-labelledby="my-module-protocol-info-button">
|
||||||
<div class="dropdown-header">
|
<div class="dropdown-content">
|
||||||
<h2 class="protocol-name">
|
<div class="dropdown-header">
|
||||||
<%= @protocol.parent&.name || @protocol.name %>
|
<h2 class="protocol-name">
|
||||||
</h2>
|
<%= @protocol.parent&.name || @protocol.name %>
|
||||||
<% if @protocol.linked? %>
|
</h2>
|
||||||
<div class="protocol-header-info">
|
<% if @protocol.linked? %>
|
||||||
<span><%= t('my_modules.protocols.protocol_status_bar.protocol_id_label') %> <%= @protocol.parent&.code %></span>
|
<div class="protocol-header-info">
|
||||||
<span><%= t('my_modules.protocols.protocol_status_bar.protocol_version_label') %> <%= @protocol.parent&.version_number %></span>
|
<span><%= t('my_modules.protocols.protocol_status_bar.protocol_id_label') %> <%= @protocol.original_code %></span>
|
||||||
|
<span><%= t('my_modules.protocols.protocol_status_bar.protocol_version_label') %> <%= @protocol.parent&.version_number %></span>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<div class="dropdown-body">
|
||||||
</div>
|
<% if @protocol.unlinked? %>
|
||||||
<div class="dropdown-body">
|
<div class="info-line">
|
||||||
<% if @protocol.unlinked? %>
|
<div class="description"><%= t("my_modules.protocols.protocol_status_bar.protocol_created") %></div>
|
||||||
<div class="info-line">
|
<div class="value"><%= I18n.l(@protocol.created_at, format: :full) %></div>
|
||||||
<div class="description"><%= t("my_modules.protocols.protocol_status_bar.protocol_created") %></div>
|
</div>
|
||||||
<div class="value"><%= I18n.l(@protocol.created_at, format: :full) %></div>
|
<% end %>
|
||||||
</div>
|
<div class="info-line">
|
||||||
<% end %>
|
<div class="description"><%= t("my_modules.protocols.protocol_status_bar.protocol_updated") %></div>
|
||||||
<div class="info-line">
|
<div class="value"><%= I18n.l(@protocol.updated_at, format: :full) %></div>
|
||||||
<div class="description"><%= t("my_modules.protocols.protocol_status_bar.protocol_updated") %></div>
|
</div>
|
||||||
<div class="value"><%= I18n.l(@protocol.updated_at, format: :full) %></div>
|
<% if @protocol.linked?%>
|
||||||
</div>
|
<div class="info-line">
|
||||||
<% if @protocol.linked?%>
|
<div class="description"><%= t("my_modules.protocols.protocol_status_bar.protocol_loaded") %></div>
|
||||||
<div class="info-line">
|
<div class="value"><%= @protocol.linked_at ? I18n.l(@protocol.linked_at, format: :full) : '' %></div>
|
||||||
<div class="description"><%= t("my_modules.protocols.protocol_status_bar.protocol_loaded") %></div>
|
</div>
|
||||||
<div class="value"><%= @protocol.linked_at ? I18n.l(@protocol.linked_at, format: :full) : '' %></div>
|
<div class="info-line">
|
||||||
</div>
|
<div class="description"><%= t("my_modules.protocols.protocol_status_bar.protocol_published") %></div>
|
||||||
<div class="info-line">
|
<div class="value"><%= I18n.l(@protocol&.parent&.published_on, format: :full) %></div>
|
||||||
<div class="description"><%= t("my_modules.protocols.protocol_status_bar.protocol_published") %></div>
|
</div>
|
||||||
<div class="value"><%= I18n.l(@protocol&.parent&.published_on, format: :full) %></div>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<div class="dropdown-footer">
|
<div class="dropdown-footer">
|
||||||
<% if @protocol.parent_newer? %>
|
<% if @protocol.linked? %>
|
||||||
<div class="notification-line new-parent-version">
|
<% if @protocol.parent_newer? %>
|
||||||
<i class="fas fa-info-circle"></i>
|
<div class="notification-line new-parent-version">
|
||||||
<div class="description"><%= t("my_modules.protocols.protocol_status_bar.messages.template_updated_html") %></div>
|
<i class="fas fa-info-circle"></i>
|
||||||
</div>
|
<div class="description"><%= t("my_modules.protocols.protocol_status_bar.messages.template_updated_html") %></div>
|
||||||
<% end %>
|
</div>
|
||||||
<% if @protocol.newer_than_parent? %>
|
<% end %>
|
||||||
<div class="notification-line new-protocol-version">
|
<% if @protocol.newer_than_parent? %>
|
||||||
<i class="fas fa-info-circle"></i>
|
<div class="notification-line new-protocol-version">
|
||||||
<div class="description"><%= t("my_modules.protocols.protocol_status_bar.messages.protocol_updated") %></div>
|
<i class="fas fa-info-circle"></i>
|
||||||
</div>
|
<div class="description"><%= t("my_modules.protocols.protocol_status_bar.messages.protocol_updated") %></div>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<%= javascript_include_tag("my_modules/protocols/protocol_status_bar") %>
|
<%= javascript_include_tag("my_modules/protocols/protocol_status_bar") %>
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
<div class="row <%= f.object.hidden? ? 'hidden' : '' %>" id="role_select_wrapper">
|
<div class="row <%= f.object.hidden? ? 'hidden' : '' %>" id="role_select_wrapper">
|
||||||
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
|
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
|
||||||
<%= f.select :default_public_user_role_id,
|
<%= f.select :default_public_user_role_id,
|
||||||
options_for_select(user_roles_collection, selected: f.object.default_public_user_role_id),
|
options_for_select(user_roles_collection(@project), selected: f.object.default_public_user_role_id),
|
||||||
{ label: t('user_assignment.select_default_user_role') },
|
{ label: t('user_assignment.select_default_user_role') },
|
||||||
class: 'form-control selectpicker'%>
|
class: 'form-control selectpicker'%>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
<div class="row hidden" id="role_select_wrapper">
|
<div class="row hidden" id="role_select_wrapper">
|
||||||
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
|
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
|
||||||
<%= f.select :default_public_user_role_id,
|
<%= f.select :default_public_user_role_id,
|
||||||
options_for_select(user_roles_collection, UserRole.find_by(name: I18n.t('user_roles.predefined.viewer')).id),
|
options_for_select(user_roles_collection(@project), UserRole.find_by(name: I18n.t('user_roles.predefined.viewer')).id),
|
||||||
class: 'form-control selectpicker'%>
|
class: 'form-control selectpicker'%>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<%= label_tag :default_public_user_role_id, t("protocols.new_protocol_modal.role_label") %>
|
<%= label_tag :default_public_user_role_id, t("protocols.new_protocol_modal.role_label") %>
|
||||||
<% default_role = UserRole.find_by(name: I18n.t('user_roles.predefined.viewer')).id %>
|
<% default_role = UserRole.find_by(name: I18n.t('user_roles.predefined.viewer')).id %>
|
||||||
<%= hidden_field_tag :default_public_user_role_id, value: default_role %>
|
<%= hidden_field_tag :default_public_user_role_id, value: default_role %>
|
||||||
<%= select_tag :role_selector, options_for_select(user_roles_collection, default_role) %>
|
<%= select_tag :role_selector, options_for_select(user_roles_collection(@protocol), default_role) %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
<template id="protocolGeneralToolbar">
|
<template id="protocolGeneralToolbar">
|
||||||
<div class="left-general-toolbar">
|
<div class="left-general-toolbar">
|
||||||
<button data-toggle="modal"
|
<% if can_create_protocols_in_repository?(@current_team) %>
|
||||||
data-target="#newProtocolModal"
|
|
||||||
<%= 'disabled' if !can_create_protocols_in_repository?(@current_team) %>
|
|
||||||
class="btn btn-primary only-active"
|
|
||||||
>
|
|
||||||
<span class="fas fa-plus"></span>
|
|
||||||
<span class="hidden-xs"><%= t("protocols.index.create_new") %></span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<div id="protocol-import-group" class="sci-btn-group only-active" role="group">
|
<button data-toggle="modal"
|
||||||
<button class="btn btn-light btn-open-file <%= 'disabled' unless can_create_protocols_in_repository?(@current_team) %>"
|
data-target="#newProtocolModal"
|
||||||
data-toggle="dropdown"
|
class="btn btn-primary only-active"
|
||||||
aria-haspopup="true"
|
>
|
||||||
aria-expanded="false">
|
<span class="fas fa-plus"></span>
|
||||||
<span class="fas fa-upload"></span><span class="hidden-xs"><%= t("protocols.index.import") %></span>
|
<span class="hidden-xs"><%= t("protocols.index.create_new") %></span>
|
||||||
</button>
|
</button>
|
||||||
<% if can_create_protocols_in_repository?(@current_team) %>
|
|
||||||
|
<div id="protocol-import-group" class="sci-btn-group only-active" role="group">
|
||||||
|
<button class="btn btn-light btn-open-file"
|
||||||
|
data-toggle="dropdown"
|
||||||
|
aria-haspopup="true"
|
||||||
|
aria-expanded="false">
|
||||||
|
<span class="fas fa-upload"></span><span class="hidden-xs"><%= t("protocols.index.import") %></span>
|
||||||
|
</button>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li>
|
<li>
|
||||||
<a class="btn-link-alt btn-default-link btn-open-file" <%= can_create_protocols_in_repository?(@current_team) ? 'data-action="import"' : 'disabled="disabled"' %>>
|
<a class="btn-link-alt btn-default-link btn-open-file" data-action="import">
|
||||||
<span><%= t("protocols.index.import_alt") %></span>
|
<span><%= t("protocols.index.import_alt") %></span>
|
||||||
<input type="file" value="" accept=".eln" data-role="import-file-input"
|
<input type="file" value="" accept=".eln" data-role="import-file-input"
|
||||||
data-team-id="<%= @current_team.id %>" data-import-url="<%= import_protocols_path %>"
|
data-team-id="<%= @current_team.id %>" data-import-url="<%= import_protocols_path %>"
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
<%= link_to t("protocols.index.import_protocols_io"), '', data: { target: '#protocolsioModal', toggle: 'modal' } %>
|
<%= link_to t("protocols.index.import_protocols_io"), '', data: { target: '#protocolsioModal', toggle: 'modal' } %>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<% end %>
|
</div>
|
||||||
</div>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="modal" id="newProtocolModal" tabindex="-1" role="dialog">
|
<div class="modal" id="newProtocolModal" tabindex="-1" role="dialog">
|
||||||
<%= form_with model: @protocol || Protocol.new, url: type == 'new' ? protocols_path : copy_to_repository_protocol_path(@protocol), method: :post do |f| %>
|
<%= form_with model: @protocol || Protocol.new, url: type == 'new' ? protocols_path : copy_to_repository_protocol_path(@protocol), method: :post, data: { action: type } do |f| %>
|
||||||
<div class="modal-dialog" role="document">
|
<div class="modal-dialog" role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
<%= f.label :default_public_user_role_id, t("protocols.new_protocol_modal.role_label") %>
|
<%= f.label :default_public_user_role_id, t("protocols.new_protocol_modal.role_label") %>
|
||||||
<% default_role = UserRole.find_by(name: I18n.t('user_roles.predefined.viewer')).id %>
|
<% default_role = UserRole.find_by(name: I18n.t('user_roles.predefined.viewer')).id %>
|
||||||
<%= f.hidden_field :default_public_user_role_id, value: default_role %>
|
<%= f.hidden_field :default_public_user_role_id, value: default_role %>
|
||||||
<%= f.select :role_selector, options_for_select(user_roles_collection, default_role) %>
|
<%= f.select :role_selector, options_for_select(team_user_roles_for_select, default_role) %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
>
|
>
|
||||||
<div class="protocol-comment-message">
|
<div class="protocol-comment-message">
|
||||||
<div class="view-mode" data-placeholder="<%= t('protocols.index.versions.comment_placeholder') %>"><%= draft.version_comment %></div>
|
<div class="view-mode" data-placeholder="<%= t('protocols.index.versions.comment_placeholder') %>"><%= draft.version_comment %></div>
|
||||||
<%= text_area_tag 'version_comment', draft.version_comment, disabled: true, class: 'smart-text-area hidden' %>
|
<%= text_area_tag 'version_comment', draft.version_comment, disabled: can_publish_protocol_in_repository?(@protocol), class: 'smart-text-area hidden' %>
|
||||||
</div>
|
</div>
|
||||||
<div class="edit-buttons">
|
<div class="edit-buttons">
|
||||||
<span class="cancel-button btn btn-secondary"><%= t('general.cancel') %></span>
|
<span class="cancel-button btn btn-secondary"><%= t('general.cancel') %></span>
|
||||||
|
|
|
@ -31,10 +31,10 @@
|
||||||
<span><i class="fas fa-sort-amount-down"></i></span>
|
<span><i class="fas fa-sort-amount-down"></i></span>
|
||||||
</button>
|
</button>
|
||||||
<ul id="sortMenuDropdown" class="dropdown-menu sort-projects-menu dropdown-menu-right" aria-labelledby="sortMenu">
|
<ul id="sortMenuDropdown" class="dropdown-menu sort-projects-menu dropdown-menu-right" aria-labelledby="sortMenu">
|
||||||
<% {new: :newest, old: :oldest, atoz: :alpha_asc, ztoa: :alpha_desc}.each do |name, value| %>
|
<% {atoz: :alpha_asc, ztoa: :alpha_desc, new: :newest, old: :oldest}.each do |name, value| %>
|
||||||
<li>
|
<li>
|
||||||
<input type='radio' name='sort_by' value='<%= value %>' <%= name == :new ? 'checked' : '' %> />
|
<input type='radio' name='sort_by' value='<%= value %>' <%= name == :new ? 'checked' : '' %> />
|
||||||
<label for="<%= value %>"><%= t("general.sort.#{name.to_s}_html") %></label>
|
<label for="<%= value %>"><%= t("protocols.index.protocolsio.sort.#{name.to_s}_html") %></label>
|
||||||
</li>
|
</li>
|
||||||
<% end %>
|
<% end %>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -19,6 +19,9 @@ module PermissionExtends
|
||||||
%w(
|
%w(
|
||||||
READ
|
READ
|
||||||
READ_ARCHIVED
|
READ_ARCHIVED
|
||||||
|
ARCHIVE
|
||||||
|
RESTORE
|
||||||
|
PUBLISH
|
||||||
MANAGE
|
MANAGE
|
||||||
USERS_MANAGE
|
USERS_MANAGE
|
||||||
MANAGE_DRAFT
|
MANAGE_DRAFT
|
||||||
|
|
|
@ -2707,6 +2707,7 @@ en:
|
||||||
head_title_archived: "Archived protocol templates"
|
head_title_archived: "Archived protocol templates"
|
||||||
default_name: 'New protocol'
|
default_name: 'New protocol'
|
||||||
back_to_active_protocols: 'Back to active protocols'
|
back_to_active_protocols: 'Back to active protocols'
|
||||||
|
search_bar_placeholder: 'Filter protocols'
|
||||||
navigation:
|
navigation:
|
||||||
public: "Team protocols"
|
public: "Team protocols"
|
||||||
private: "My protocols"
|
private: "My protocols"
|
||||||
|
@ -2740,7 +2741,7 @@ en:
|
||||||
name: "Name"
|
name: "Name"
|
||||||
id: "ID"
|
id: "ID"
|
||||||
keywords: "Keywords"
|
keywords: "Keywords"
|
||||||
nr_of_linked_children: "No. of linked tasks"
|
nr_of_linked_children: "Linked tasks"
|
||||||
versions: "Versions"
|
versions: "Versions"
|
||||||
access: "Access"
|
access: "Access"
|
||||||
published_by: "Published by"
|
published_by: "Published by"
|
||||||
|
@ -2853,6 +2854,11 @@ en:
|
||||||
public: "Team protocols"
|
public: "Team protocols"
|
||||||
private: "My protocols"
|
private: "My protocols"
|
||||||
success_flash: 'Protocol <strong>%{name}</strong> successfully imported.'
|
success_flash: 'Protocol <strong>%{name}</strong> successfully imported.'
|
||||||
|
sort:
|
||||||
|
new_html: "<i class=\"fas fa-sort-numeric-up\"></i> Newest first"
|
||||||
|
old_html: "<i class=\"fas fa-sort-numeric-down\"></i> Oldest first"
|
||||||
|
atoz_html: "<i class=\"fas fa-sort-alpha-down\"></i> Name A to Z"
|
||||||
|
ztoa_html: "<i class=\"fas fa-sort-alpha-up\"></i> Name Z to A"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
placeholder: 'Enter step name'
|
placeholder: 'Enter step name'
|
||||||
|
@ -3207,6 +3213,7 @@ en:
|
||||||
change_experiment_role: "Change experiment role"
|
change_experiment_role: "Change experiment role"
|
||||||
change_my_module_role: "Change task role"
|
change_my_module_role: "Change task role"
|
||||||
select_role: "Select role"
|
select_role: "Select role"
|
||||||
|
assign_all_team_members: "Grant access to all team members"
|
||||||
from_project: "%{user_role} [from project]"
|
from_project: "%{user_role} [from project]"
|
||||||
from_experiment: "%{user_role} [from experiment]"
|
from_experiment: "%{user_role} [from experiment]"
|
||||||
experiment_select_role: "Change experiment role"
|
experiment_select_role: "Change experiment role"
|
||||||
|
|
Loading…
Add table
Reference in a new issue