Enable leave for team owners for yourself [SCI-9957]

This commit is contained in:
Andrej 2024-04-04 16:15:18 +02:00
parent 6e95ba13f9
commit 8e94cd5ce6
7 changed files with 68 additions and 131 deletions

View file

@ -110,10 +110,9 @@
function(e, data) { function(e, data) {
// Populate the modal heading & body // Populate the modal heading & body
var modal = $('#destroy-user-team-modal'); var modal = $('#destroy-user-team-modal');
var modalHeading = modal.find('.modal-header').find('.modal-title'); const modalContent = modal.find('.modal-content');
var modalBody = modal.find('.modal-body');
modalHeading.text($('<div>').html(data.heading).text()); modalContent.html(data.html);
modalBody.html(data.html);
// Show the modal // Show the modal
modal.modal('show'); modal.modal('show');
@ -122,13 +121,14 @@
'ajax:error', 'ajax:error',
"[data-action='destroy-user-team']", "[data-action='destroy-user-team']",
function() { function() {
// TODO HelperModule.flashAlertMsg(I18n.t('users.settings.user_teams.general_error'), 'danger');
} }
); );
// Also, bind the click action on the modal // Also, bind the click action on the modal
$('#destroy-user-team-modal') $('#destroy-user-team-modal')
.on('click', "[data-action='submit']", function() { .on('click', "[data-action='submit']", function() {
animateSpinner();
var btn = $(this); var btn = $(this);
var form = btn var form = btn
.closest('.modal') .closest('.modal')
@ -154,14 +154,16 @@
// Hide the modal // Hide the modal
modal.modal('hide'); modal.modal('hide');
animateSpinner(null, false);
// Reload the whole table // Reload the whole table
usersDatatable.ajax.reload(); location.reload();
} }
).on( ).on(
'ajax:error', 'ajax:error',
"[data-id='destroy-user-team-form']", "[data-id='destroy-user-team-form']",
function() { function() {
// TODO animateSpinner(null, false);
HelperModule.flashAlertMsg(I18n.t('users.settings.user_teams.general_error'), 'danger');
} }
); );
} }

View file

@ -51,11 +51,6 @@ module Users
'destroy_user_team_modal_body', 'destroy_user_team_modal_body',
locals: { user_assignment: @user_assignment }, locals: { user_assignment: @user_assignment },
formats: :html formats: :html
),
heading: I18n.t(
'users.settings.user_teams.destroy_uo_heading',
user: escape_input(@user_assignment.user.full_name),
team: escape_input(@user_assignment.assignable.name)
) )
} }
end end
@ -63,29 +58,12 @@ module Users
def destroy def destroy
# If user is last administrator of team, # If user is last administrator of team,
# he/she cannot be deleted from it. # he/she cannot be deleted from it.
invalid = invalid = @user_assignment.last_with_permission?(TeamPermissions::USERS_MANAGE)
managing_team_user_roles_collection.include?(@user_assignment.user_role) &&
@user_assignment
.assignable
.user_assignments
.where(user_role: managing_team_user_roles_collection)
.count <= 1
unless invalid unless invalid
begin begin
@user_assignment.transaction do @user_assignment.transaction do
# If user leaves on his/her own accord,
# new owner for projects is the first
# administrator of team
if params[:leave] if params[:leave]
new_owner =
@user_assignment
.assignable
.user_assignments
.where(user_role: managing_team_user_roles_collection)
.where.not(id: @user_assignment.id)
.first
.user
Activities::CreateActivityService Activities::CreateActivityService
.call(activity_type: :user_leave_team, .call(activity_type: :user_leave_team,
owner: current_user, owner: current_user,
@ -95,10 +73,6 @@ module Users
team: @user_assignment.assignable.id team: @user_assignment.assignable.id
}) })
else else
# Otherwise, the new owner for projects is
# the current user (= an administrator removing
# the user from the team)
new_owner = current_user
Activities::CreateActivityService Activities::CreateActivityService
.call(activity_type: :remove_user_from_team, .call(activity_type: :remove_user_from_team,
owner: current_user, owner: current_user,
@ -110,8 +84,7 @@ module Users
}) })
end end
reset_user_current_team(@user_assignment) reset_user_current_team(@user_assignment)
@user_assignment.destroy!
remove_user_from_team!(@user_assignment, new_owner)
end end
rescue StandardError => e rescue StandardError => e
Rails.logger.error e.message Rails.logger.error e.message
@ -119,21 +92,27 @@ module Users
end end
end end
if !invalid if invalid
if params[:leave] render json: @user_assignment.errors, status: :unprocessable_entity
flash[:notice] = I18n.t( else
flash[:success] = if params[:leave]
I18n.t(
'users.settings.user_teams.leave_flash', 'users.settings.user_teams.leave_flash',
team: @user_assignment.assignable.name team: @user_assignment.assignable.name
) )
flash.keep(:notice) else
I18n.t(
'users.settings.user_teams.remove_flash',
user: @user_assignment.user.full_name,
team: @user_assignment.assignable.name
)
end end
generate_notification(current_user, generate_notification(current_user,
@user_assignment.user, @user_assignment.user,
@user_assignment.assignable, @user_assignment.assignable,
false) false)
render json: { status: :ok } render json: { status: :ok }
else
render json: @user_assignment.errors, status: :unprocessable_entity
end end
end end
@ -165,33 +144,6 @@ module Users
user_assignment.user.current_team_id = ids.first user_assignment.user.current_team_id = ids.first
user_assignment.user.save user_assignment.user.save
end end
def remove_user_from_team!(user_assignment, new_owner)
return user_assignment.destroy! unless new_owner
# Also, make new owner author of all protocols that belong
# to the departing user and belong to this team.
p_ids = user_assignment.user.added_protocols.where(team: user_assignment.assignable).pluck(:id)
Protocol.where(id: p_ids).find_each do |protocol|
protocol.record_timestamps = false
protocol.added_by = new_owner
protocol.archived_by = new_owner if protocol.archived_by == user_assignment.user
protocol.restored_by = new_owner if protocol.restored_by == user_assignment.user
protocol.save!(validate: false)
protocol.user_assignments.find_by(user: new_owner)&.destroy!
protocol.user_assignments.create!(
user: new_owner,
user_role: UserRole.find_predefined_owner_role,
assigned: :manually
)
end
# Make new owner author of all inventory items that were added
# by departing user and belong to this team.
RepositoryRow.change_owner(user_assignment.assignable, user_assignment.user, new_owner)
user_assignment.destroy!
end
end end
end end
end end

View file

@ -1,5 +1,5 @@
<% if user_assignment.user == user %> <% if user_assignment.user == user %>
<button class="btn btn-light btn-xs icon-btn" type="button" disabled="disabled"> <button class="btn btn-light btn-xs icon-btn" id="leave-team-btn" type="button" disabled="disabled">
<span class="sn-icon sn-icon-down"></span> <span class="sn-icon sn-icon-down"></span>
</button> </button>
<% else %> <% else %>

View file

@ -5,18 +5,6 @@
aria-labelledby="destroy-user-team-modal-label"> aria-labelledby="destroy-user-team-modal-label">
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i class="sn-icon sn-icon-close"></i></button>
<h4 class="modal-title" id="destroy-user-team-modal-label">
</h4>
</div>
<div class="modal-body"></div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal"><%=t 'general.cancel' %></button>
<button type="button"
class="btn btn-danger"
data-action="submit"><%=t 'users.settings.user_teams.destroy_uo_confirm' %></button>
</div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,21 +1,28 @@
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i class="sn-icon sn-icon-close"></i></button>
<h4 class="modal-title" id="destroy-user-team-modal-label">
<%= t('users.settings.user_teams.destroy_uo_heading',
user: user_assignment.user.full_name,
team: user_assignment.assignable.name,
role: user_assignment.user_role.name.downcase) %>
</h4>
</div>
<div class="modal-body">
<%= form_with model: user_assignment, <%= form_with model: user_assignment,
url: destroy_user_team_path(user_assignment, format: :json), url: destroy_user_team_path(user_assignment, format: :json),
data: { remote: true, id: 'destroy-user-team-form' }, data: { remote: true, id: 'destroy-user-team-form' },
method: :delete do |f| %> method: :delete do |f| %>
<p><%= t("users.settings.user_teams.destroy_uo_message", <div class='flex flex-col gap-6'>
user: user_assignment.user.full_name, <div><%= t("users.settings.user_teams.destroy_message", role: user_assignment.user_role.name.downcase) %></div>
team: user_assignment.assignable.name) %></p> <div><%= t("users.settings.user_teams.message_owner") %></div>
<% if user_assignment.user.confirmed? %> <div><%= t("users.settings.user_teams.message_alert") %></div>
<div class="alert alert-danger" role="alert">
<span class="fas fa-exclamation-triangle"></span>
&nbsp;
<%= t("users.settings.user_teams.destroy_uo_alert_heading") %>
<ul>
<li><%= t("users.settings.user_teams.destroy_uo_alert_line_1") %></li>
<li><%= t("users.settings.user_teams.destroy_uo_alert_line_2").html_safe %></li>
<li><%= t("users.settings.user_teams.destroy_uo_alert_line_3") %></li>
<li><%= t("users.settings.user_teams.destroy_uo_alert_line_4") %></li>
</ul>
</div> </div>
<% end %> <% end %>
<% end %> </div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal"><%=t 'general.cancel' %></button>
<button type="button"
class="btn btn-danger"
data-action="submit"><%=t 'users.settings.user_teams.destroy_uo_confirm' %>
</button>
</div>

View file

@ -4,16 +4,9 @@
method: :delete, method: :delete,
data: { id: 'leave-user-team-form' } do |f| %> data: { id: 'leave-user-team-form' } do |f| %>
<%= hidden_field_tag :leave, true %> <%= hidden_field_tag :leave, true %>
<p><%= t("users.settings.user_teams.leave_uo_message", team: @user_assignment.team.name) %></p> <div class='flex flex-col gap-6'>
<div class="alert alert-danger" role="alert"> <div><%= t("users.settings.user_teams.leave_message") %></div>
<span class="fas fa-exclamation-triangle"></span> <div><%= t("users.settings.user_teams.message_owner") %></div>
&nbsp; <div><%= t("users.settings.user_teams.message_alert") %></div>
<%= t("users.settings.user_teams.leave_uo_alert_heading") %>
<ul>
<li><%= t("users.settings.user_teams.leave_uo_alert_line_1") %></li>
<li><%= t("users.settings.user_teams.leave_uo_alert_line_2").html_safe %></li>
<li><%= t("users.settings.user_teams.leave_uo_alert_line_3")%></li>
<li><%= t("users.settings.user_teams.leave_uo_alert_line_4")%></li>
</ul>
</div> </div>
<% end %> <% end %>

View file

@ -2988,22 +2988,17 @@ en:
flash_success: "Team %{team} was successfully deleted." flash_success: "Team %{team} was successfully deleted."
user_teams: user_teams:
leave_uo_heading: "Leave team %{team}" leave_uo_heading: "Leave team %{team}"
leave_uo_message: "Are you sure you wish to leave team %{team}? This action is irreversible." leave_message: "You will lose access to all content associated with the team, including projects, inventories, and protocol templates."
leave_uo_alert_heading: "Leaving team has following consequences:" destroy_message: 'Removing a team %{role} will revoke their access to all content associated with the team, including projects, inventories, and protocol templates.'
leave_uo_alert_line_1: "you will lose access to all content belonging to the team (including projects, tasks, protocols and activities);" leave_uo_confirm: "Leave team"
leave_uo_alert_line_2: "all projects in the team where you were the sole <b>Owner</b> will receive a new owner from the team administrators;" destroy_uo_heading: "Remove team %{role} %{user} from team %{team}"
leave_uo_alert_line_3: "all repository protocols in the team belonging to you will be reassigned onto a new owner from team administrators;" message_owner: "Other team owner(s) will be able to view and manage access to the content."
leave_uo_alert_line_4: "all inventory items in the team added by you will be reassigned onto a new owner from team administrators." message_alert: "This action cannot be undone."
leave_uo_confirm: "Leave" destroy_uo_alert_line_3: "This action cannot be undone."
destroy_uo_heading: "Remove user %{user} from team %{team}"
destroy_uo_message: "Are you sure you wish to remove user %{user} from team %{team}?"
destroy_uo_alert_heading: "Removing user from team has following consequences:"
destroy_uo_alert_line_1: "user will lose access to all content belonging to the team (including projects, tasks, protocols and activities);"
destroy_uo_alert_line_2: "all projects in the team where user was the sole <b>Owner</b> will be reassigned onto you as a new owner;"
destroy_uo_alert_line_3: "all repository protocols in the team belonging to user will be reassigned onto you;"
destroy_uo_alert_line_4: "all inventory items in the team added by user will be reassigned onto you."
destroy_uo_confirm: "Remove" destroy_uo_confirm: "Remove"
leave_flash: "Successfully left team %{team}." leave_flash: "You have left %{team}."
remove_flash: "%{user} has been successfully removed from the team %{team}"
general_error: "Something went wrong"
user_roles: user_roles:
predefined: predefined: