Add access modal for protocols [SCI-7518]

This commit is contained in:
Anton 2022-12-22 13:27:46 +01:00
parent 7437af540b
commit d1a68adb22
14 changed files with 291 additions and 1 deletions

View file

@ -0,0 +1,99 @@
# frozen_string_literal: true
module AccessPermissions
class ProtocolsController < ApplicationController
before_action :set_protocol
before_action :check_read_permissions, only: %i(show)
before_action :check_manage_permissions, except: %i(show)
def new
respond_to do |format|
format.json
end
end
def show
respond_to do |format|
format.json
end
end
def edit
respond_to do |format|
format.json
end
end
def update
@user_assignment = UserAssignment.find_by(user_id: permitted_update_params[:user_id], assignable: @protocol)
@user_assignment.update(permitted_update_params)
respond_to do |format|
format.json do
render :protocol_member
end
end
end
def create
respond_to do |format|
if @form.save
@message = t('access_permissions.create.success', count: @form.new_members_count)
format.json { render :edit }
else
@message = t('access_permissions.create.failure')
format.json { render :new }
end
end
end
def destroy
respond_to do |format|
if project_member.destroy
format.json do
render json: { flash: t('access_permissions.destroy.success', member_name: user.full_name) },
status: :ok
end
else
format.json do
render json: { flash: t('access_permissions.destroy.failure') },
status: :unprocessable_entity
end
end
end
end
def update_default_public_user_role
@protocol.update!(permitted_default_public_user_role_params)
end
private
def permitted_default_public_user_role_params
params.require(:protocol).permit(:default_public_user_role_id)
end
def permitted_update_params
params.require(:user_assignment)
.permit(%i(user_role_id user_id))
end
def permitted_create_params
params.require(:access_permissions_new_user_protocol_form)
.permit(resource_members: %i(assign user_id user_role_id))
end
def set_protocol
@protocol = current_team.protocols.includes(user_assignments: %i(user user_role)).find_by(id: params[:id])
render_404 unless @protocol
end
def check_manage_permissions
render_403 unless can_manage_protocol_users?(@protocol)
end
def check_read_permissions
render_403 unless can_read_protocol?(@protocol)
end
end
end

View file

@ -16,6 +16,10 @@ class UserAssignment < ApplicationRecord
validates :user, uniqueness: { scope: %i(assignable team_id) }
def last_assignable_owner?
assignable_owners.count == 1 && user_role.owner?
end
private
def assign_team_child_objects
@ -29,4 +33,10 @@ class UserAssignment < ApplicationRecord
def unassign_team_child_objects
UserAssignments::RemoveTeamUserAssignmentsService.new(self).call
end
def assignable_owners
@assignable_owners ||= assignable.user_assignments
.includes(:user_role)
.where(user_roles: { name: I18n.t('user_roles.predefined.owner') })
end
end

View file

@ -0,0 +1,33 @@
<% # frozen_string_literal: true %>
<%
protocol_assignment = UserAssignment.find_by(user_id: user.id, assignable: protocol)
item_id = dom_id(user, :protocol_member)
%>
<%= form_with(model: protocol_assignment, url: update_path, method: :put, remote: true, html: { class: 'row member-item', id: item_id, data: { action: 'replace-form autosave-form', object_type: :protocol } }) do |f| %>
<%= f.hidden_field :user_id, value: f.object.user.id %>
<div class="user-assignment-info">
<div class="global-avatar-container">
<%= image_tag avatar_path(user, :icon_small), title: current_assignee_name(user), class: 'img-circle pull-left' %>
</div>
<div>
<%= current_assignee_name(user) %>
<br>
<small class="text-muted"><%= user_assignment_resource_role_name(user, protocol) %></small>
</div>
</div>
<div class="user-assignment-controls">
<div class="user-assignment-role">
<%= f.select :user_role_id, options_for_select(user_roles_collection, selected: f.object.user_role.id), {}, class: 'form-control selectpicker', title: t('user_assignment.change_protocol_role'), data: { 'selected-text-format' => 'static' } %>
</div>
<div class="user-assignment-remove">
<% unless protocol_assignment.last_assignable_owner? %>
<%= link_to access_permissions_protocol_path(protocol, user_id: user), remote: true, method: :delete, class: 'btn btn-secondary', data: { action: 'remote-destroy', target: "##{item_id}" } do %>
<span class="fas fa-times"></span>
<%= t 'general.remove' %>
<% end %>
<% end %>
</div>
</div>
<% end %>

View file

@ -0,0 +1,20 @@
<%= form_with(model: protocol, url: update_default_public_user_role_access_permissions_protocol_path(protocol), method: :put, remote: true, html: { class: 'row member-item', id: 'public_assignments', data: { action: 'replace-form autosave-form', object_type: :protocol } }) do |f| %>
<div class="user-assignment-info">
<div class="global-avatar-container">
<%= image_tag "icon/team.png", class: 'img-circle pull-left' %>
</div>
<div>
<%= t('access_permissions.everyone_else', team_name: protocol.team.name) %>
<%= render 'access_permissions/partials/public_members_dropdown', team: protocol.team, protocol: protocol %>
</div>
</div>
<div class="user-assignment-controls">
<div class="user-assignment-role">
<% if editable %>
<%= f.select :default_public_user_role_id, options_for_select(user_roles_collection) {}, class: 'form-control selectpicker', title: t('user_assignment.change_protocol_role'), data: { 'selected-text-format' => 'static' } %>
<% end %>
</div>
<div class="user-assignment-remove">
</div>
</div>
<% end %>

View file

@ -5,7 +5,14 @@
<div class="title">
<%= t('.title', team: team.name) %>
</div>
<% team.users.order(full_name: :asc).where.not(id: project.manually_assigned_users.select(:id)).each do |user| %>
<%
users_excluded = if defined? project
project.manually_assigned_users.select(:id)
elsif protocol
protocol.manually_assigned_users.select(:id)
end
%>
<% team.users.order(full_name: :asc).where.not(id: users_excluded).each do |user| %>
<div class="name">
<%= user.full_name %>
</div>

View file

@ -0,0 +1,14 @@
# frozen_string_literal: true
json.modal controller.render_to_string(
partial: 'access_permissions/protocols/modals/edit_modal',
formats: [:html],
locals: {
protocol: @protocol,
update_path: access_permissions_protocol_path(@protocol),
new_resource_path: new_access_permissions_protocol_path(id: @protocol)
},
layout: false
)
json.flash @message

View file

@ -0,0 +1,25 @@
<% # frozen_string_literal: true %>
<div class="modal fade user-assignments-modal protocol-assignments-modal" tabindex="-1" role="dialog" data-action="modal-close">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content" id="user_assignments_modal">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title"><%= t '.title', resource_name: protocol.name %></h4>
</div>
<div class="modal-body">
<% protocol.manually_assigned_users.order(full_name: :asc).each do |user| %>
<%= render('access_permissions/partials/protocol_member_field', user: user, protocol: protocol, update_path: update_path) %>
<% end %>
<%= render('access_permissions/partials/protocol_public_user_role_form', protocol: protocol, editable: true) %>
</div>
<div class="modal-footer">
<%= link_to new_resource_path, class: 'btn btn-default pull-left', data: { action: 'swap-remote-container', target: '#user_assignments_modal' } do %>
<i class="fas fa-plus"></i>
<%= t('.new_resource_assignments', resource: protocol.model_name.human.downcase) %>
<% end %>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,19 @@
<% # frozen_string_literal: true %>
<div class="modal fade protocol-assignments-modal" tabindex="-1" role="dialog" data-action="modal-close">
<div class="modal-dialog modal-md" role="document">
<div class="modal-content" id="user_assignments_modal">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title"><%= t '.title', resource_name: protocol.name %></h4>
</div>
<div class="modal-body">
<% users.order(full_name: :asc).each do |user| %>
<% user_assignment = protocol.user_assignments.find_by(user: user) %>
<%= render partial: 'access_permissions/partials/user_assignment', locals: { user_assignment: user_assignment, user: user, resource: protocol } %>
<% end %>
<%= render('access_permissions/partials/default_public_user_role_form', protocol: protocol, editable: false) if protocol.visible? %>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,13 @@
# frozen_string_literal: true
json.html controller.render_to_string(
partial: 'access_permissions/partials/new_assignments_form',
formats: [:html],
locals: {
resource: @protocol,
form_object: @form,
create_path: access_permissions_protocol_path(id: @protocol.id),
resource_path: edit_access_permissions_protocol_path(@protocol)
},
layout: false
)

View file

@ -0,0 +1,12 @@
# frozen_string_literal: true
json.form controller.render_to_string(
partial: 'access_permissions/partials/protocol_member_field',
formats: [:html],
locals: {
user: @user_assignment.user,
protocol: @protocol,
update_path: access_permissions_protocol_path(@protocol)
},
layout: false
)

View file

@ -0,0 +1,12 @@
# frozen_string_literal: true
json.modal controller.render_to_string(
partial: 'access_permissions/protocols/modals/show_modal',
formats: [:html],
locals: {
protocol: @protocol,
users: @protocol.manually_assigned_users,
can_manage_resource: can_manage_protocol_users?(@protocol)
},
layout: false
)

View file

@ -0,0 +1,11 @@
# frozen_string_literal: true
json.form controller.render_to_string(
partial: 'access_permissions/partials/default_public_user_role_form',
formats: [:html],
locals: {
protocol: @protocol,
editable: true
},
layout: false
)

View file

@ -3036,6 +3036,7 @@ en:
user_assignment:
current_assignee: "(you)"
change_project_role: "Change project role"
change_protocol_role: "Change protocol role"
select_default_user_role: "Select default user role"
change_experiment_role: "Change experiment role"
change_my_module_role: "Change task role"
@ -3078,6 +3079,9 @@ en:
project: "Project"
project_tooltip: "This role was set on this project."
project_tooltip_inherit: "This role was inherited from the project."
protocol: "Protocol"
protocol_tooltip: "This role was set on this protocol."
protocol_tooltip_inherit: "This role was inherited from the protocol."
experiment: "Experiment"
experiment_tooltip: "This role was set on this experiment."
experiment_tooltip_inherit: "This role was inherited from the experiment."
@ -3091,6 +3095,14 @@ en:
show_modal:
title: "Access to %{resource_name}"
new_resource_assignments: "Grant new access to %{resource}"
protocols:
modals:
show_modal:
title: "Access to %{resource_name}"
new_resource_assignments: "Grant new access to %{resource}"
edit_modal:
title: "Manage access for %{resource_name}"
new_resource_assignments: "Grant new access to %{resource}"
experiments:
modals:
show_modal:

View file

@ -280,6 +280,9 @@ Rails.application.routes.draw do
end
namespace :access_permissions do
resources :protocols, defaults: { format: 'json' } do
put :update_default_public_user_role, on: :member
end
resources :projects, defaults: { format: 'json' } do
put :update_default_public_user_role, on: :member
resources :experiments, only: %i(show update edit) do