diff --git a/app/controllers/access_permissions/projects_controller.rb b/app/controllers/access_permissions/projects_controller.rb index 5948429ef..5e7a9bc51 100644 --- a/app/controllers/access_permissions/projects_controller.rb +++ b/app/controllers/access_permissions/projects_controller.rb @@ -9,17 +9,59 @@ module AccessPermissions before_action :check_manage_permissions, except: %i(show) before_action :available_users, only: %i(new create) - def new - @user_assignment = @project.user_assignments.new( - assigned_by: current_user, - team: current_team - ) + def show + render json: @project.user_assignments.includes(:user_role, :user).order('users.full_name ASC'), + each_serializer: UserAssignmentSerializer end - def show; end + def new + render json: @available_users, each_serializer: UserSerializer + end def edit; end + def create + ActiveRecord::Base.transaction do + created_count = 0 + if permitted_create_params[:user_id] == 'all' + @project.update!(visibility: :visible, default_public_user_role_id: permitted_create_params[:user_role_id]) + log_activity(:project_grant_access_to_all_team_members, + { visibility: t('projects.activity.visibility_visible'), + role: @project.default_public_user_role.name, + team: @project.team.id }) + else + user_assignment = UserAssignment.find_or_initialize_by( + assignable: @project, + user_id: permitted_create_params[:user_id], + team: current_team + ) + + user_assignment.update!( + user_role_id: permitted_create_params[:user_role_id], + assigned_by: current_user, + assigned: :manually + ) + + log_activity(:assign_user_to_project, { user_target: user_assignment.user.id, + role: user_assignment.user_role.name }) + created_count += 1 + propagate_job(user_assignment) + end + + @message = if created_count.zero? + t('access_permissions.create.success', member_name: t('access_permissions.all_team')) + else + t('access_permissions.create.success', member_name: escape_input(user_assignment.user.name)) + end + render json: { message: @message } + rescue ActiveRecord::RecordInvalid => e + Rails.logger.error e.message + errors = @project.errors.present? ? @project.errors&.map(&:message)&.join(',') : e.message + render json: { flash: errors }, status: :unprocessable_entity + raise ActiveRecord::Rollback + end + end + def update @user_assignment = @project.user_assignments.find_by( user_id: permitted_update_params[:user_id], @@ -44,52 +86,6 @@ module AccessPermissions render json: { flash: t('access_permissions.update.failure') }, status: :unprocessable_entity end - def create - ActiveRecord::Base.transaction do - created_count = 0 - permitted_create_params[:resource_members].each do |_k, user_assignment_params| - next unless user_assignment_params[:assign] == '1' - - if user_assignment_params[:user_id] == 'all' - @project.update!(visibility: :visible, default_public_user_role_id: user_assignment_params[:user_role_id]) - log_activity(:project_grant_access_to_all_team_members, - { visibility: t('projects.activity.visibility_visible'), - role: @project.default_public_user_role.name, - team: @project.team.id }) - else - user_assignment = UserAssignment.find_or_initialize_by( - assignable: @project, - user_id: user_assignment_params[:user_id], - team: current_team - ) - - user_assignment.update!( - user_role_id: user_assignment_params[:user_role_id], - assigned_by: current_user, - assigned: :manually - ) - - log_activity(:assign_user_to_project, { user_target: user_assignment.user.id, - role: user_assignment.user_role.name }) - created_count += 1 - propagate_job(user_assignment) - end - end - - @message = if created_count.zero? - t('access_permissions.create.success', count: t('access_permissions.all_team')) - else - t('access_permissions.create.success', count: created_count) - end - render :edit - rescue ActiveRecord::RecordInvalid => e - Rails.logger.error e.message - errors = @project.errors.present? ? @project.errors&.map(&:message)&.join(',') : e.message - render json: { flash: errors }, status: :unprocessable_entity - raise ActiveRecord::Rollback - end - end - def destroy user = @project.assigned_users.find(params[:user_id]) user_assignment = @project.user_assignments.find_by(user: user, team: current_team) @@ -100,12 +96,15 @@ module AccessPermissions end propagate_job(user_assignment, destroy: true) + + user_assignment.destroy! + log_activity(:unassign_user_from_project, { user_target: user_assignment.user.id, role: user_assignment.user_role.name }) - render json: { flash: t('access_permissions.destroy.success', member_name: escape_input(user.full_name)) } + render json: { message: t('access_permissions.destroy.success', member_name: escape_input(user.full_name)) } rescue ActiveRecord::RecordInvalid - render json: { flash: t('access_permissions.destroy.failure') }, + render json: { message: t('access_permissions.destroy.failure') }, status: :unprocessable_entity end @@ -123,7 +122,7 @@ module AccessPermissions { visibility: t('projects.activity.visibility_hidden'), role: previous_user_role_name, team: @project.team.id }) - render json: { flash: t('access_permissions.update.revoke_all_team_members') } + render json: { message: t('access_permissions.update.revoke_all_team_members') } else # update all team members access @project.visibility = :visible @@ -151,8 +150,8 @@ module AccessPermissions end def permitted_create_params - params.require(:access_permissions_new_user_form) - .permit(resource_members: %i(assign user_id user_role_id)) + params.require(:user_assignment) + .permit(%i(user_id user_role_id)) end def set_project @@ -185,7 +184,7 @@ module AccessPermissions id: @project.user_assignments.automatically_assigned.select(:user_id) ).or( current_team.users.where.not(id: @project.users.select(:id)) - ) + ).order('users.full_name ASC') end def log_activity(type_of, message_items = {}) diff --git a/app/controllers/access_permissions/protocols_controller.rb b/app/controllers/access_permissions/protocols_controller.rb index 30b4dad64..9510fdbc7 100644 --- a/app/controllers/access_permissions/protocols_controller.rb +++ b/app/controllers/access_permissions/protocols_controller.rb @@ -6,6 +6,8 @@ module AccessPermissions before_action :check_read_permissions, only: %i(show) before_action :check_manage_permissions, except: %i(show) + def show; end + def new @user_assignment = UserAssignment.new( assignable: @protocol, @@ -14,32 +16,8 @@ module AccessPermissions ) end - def show; end - def edit; end - def update - @user_assignment = @protocol.user_assignments.find_by( - user_id: permitted_update_params[:user_id], - team: current_team - ) - - # prevent role change if it would result in no manually assigned users having the user management permission - new_user_role = UserRole.find(permitted_update_params[:user_role_id]) - if !new_user_role.has_permission?(ProtocolPermissions::USERS_MANAGE) && - @user_assignment.last_with_permission?(ProtocolPermissions::USERS_MANAGE, assigned: :manually) - raise ActiveRecord::RecordInvalid - end - - @user_assignment.update!(permitted_update_params) - log_activity(:protocol_template_access_changed, { user_target: @user_assignment.user.id, - role: @user_assignment.user_role.name }) - - render :protocol_member - rescue ActiveRecord::RecordInvalid - render json: { flash: t('access_permissions.update.failure') }, status: :unprocessable_entity - end - def create ActiveRecord::Base.transaction do created_count = 0 @@ -83,6 +61,28 @@ module AccessPermissions end end + def update + @user_assignment = @protocol.user_assignments.find_by( + user_id: permitted_update_params[:user_id], + team: current_team + ) + + # prevent role change if it would result in no manually assigned users having the user management permission + new_user_role = UserRole.find(permitted_update_params[:user_role_id]) + if !new_user_role.has_permission?(ProtocolPermissions::USERS_MANAGE) && + @user_assignment.last_with_permission?(ProtocolPermissions::USERS_MANAGE, assigned: :manually) + raise ActiveRecord::RecordInvalid + end + + @user_assignment.update!(permitted_update_params) + log_activity(:protocol_template_access_changed, { user_target: @user_assignment.user.id, + role: @user_assignment.user_role.name }) + + render :protocol_member + rescue ActiveRecord::RecordInvalid + render json: { flash: t('access_permissions.update.failure') }, status: :unprocessable_entity + end + def destroy user = @protocol.assigned_users.find(params[:user_id]) user_assignment = @protocol.user_assignments.find_by(user: user, team: current_team) diff --git a/app/javascript/vue/projects/card.vue b/app/javascript/vue/projects/card.vue index d68f61296..dc3b5b23c 100644 --- a/app/javascript/vue/projects/card.vue +++ b/app/javascript/vue/projects/card.vue @@ -12,7 +12,7 @@
{{ params.code }}
- + {{ params.name }}
@@ -27,7 +27,7 @@ {{ params.hidden ? i18n.t('projects.index.hidden') : i18n.t('projects.index.visible') }} {{ i18n.t('projects.index.card.users') }} - +
diff --git a/app/javascript/vue/projects/list.vue b/app/javascript/vue/projects/list.vue index 68a6fccd3..d72cdd253 100644 --- a/app/javascript/vue/projects/list.vue +++ b/app/javascript/vue/projects/list.vue @@ -21,6 +21,7 @@ @delete_folders="deleteFolder" @export="exportProjects" @move="move" + @access="access" > diff --git a/app/javascript/vue/shared/access_modal/modal.vue b/app/javascript/vue/shared/access_modal/modal.vue new file mode 100644 index 000000000..480a18746 --- /dev/null +++ b/app/javascript/vue/shared/access_modal/modal.vue @@ -0,0 +1,68 @@ + + + diff --git a/app/javascript/vue/shared/access_modal/new.vue b/app/javascript/vue/shared/access_modal/new.vue new file mode 100644 index 000000000..c3d7696ce --- /dev/null +++ b/app/javascript/vue/shared/access_modal/new.vue @@ -0,0 +1,136 @@ + + + \ No newline at end of file diff --git a/app/javascript/vue/shared/datatable/table.vue b/app/javascript/vue/shared/datatable/table.vue index 70db2ac26..776271ba3 100644 --- a/app/javascript/vue/shared/datatable/table.vue +++ b/app/javascript/vue/shared/datatable/table.vue @@ -25,7 +25,7 @@ v-if="currentViewRender === 'table'" class="ag-theme-alpine w-full flex-grow h-full z-10" :class="{'opacity-0': initializing}" - :columnDefs="columnDefs" + :columnDefs="extendedColumnDefs" :rowData="rowData" :defaultColDef="defaultColDef" :rowSelection="'multiple'" @@ -177,38 +177,48 @@ export default { return { suppressCellFocus: true } - } - }, - beforeMount() { - if (this.withCheckboxes) { - this.columnDefs.unshift({ - field: "checkbox", - headerCheckboxSelection: true, - headerCheckboxSelectionFilteredOnly: true, - checkboxSelection: true, - width: 48, - minWidth: 48, - resizable: false, - pinned: 'left' + }, + extendedColumnDefs() { + let columns = this.columnDefs.map(column => { + return { + ...column, + cellRendererParams: { + dtComponent: this + } + } }); - } - if (this.withRowMenu) { - this.columnDefs.push({ - field: "rowMenu", - headerName: '', - width: 42, - minWidth: 42, - resizable: false, - sortable: false, - cellRenderer: 'RowMenuRenderer', - cellRendererParams: { - dtComponent: this - }, - pinned: 'right', - cellStyle: {padding: 0, display: 'flex', justifyContent: 'center', alignItems: 'center', overflow: 'visible'} + if (this.withCheckboxes) { + columns.unshift({ + field: "checkbox", + headerCheckboxSelection: true, + headerCheckboxSelectionFilteredOnly: true, + checkboxSelection: true, + width: 48, + minWidth: 48, + resizable: false, + pinned: 'left' + }); + } - }); + if (this.withRowMenu) { + columns.push({ + field: "rowMenu", + headerName: '', + width: 42, + minWidth: 42, + resizable: false, + sortable: false, + cellRenderer: 'RowMenuRenderer', + cellRendererParams: { + dtComponent: this + }, + pinned: 'right', + cellStyle: {padding: 0, display: 'flex', justifyContent: 'center', alignItems: 'center', overflow: 'visible'} + }); + } + + return columns; } }, watch: { @@ -308,7 +318,7 @@ export default { this.loadData(); }, clickCell(e) { - if (e.column.colId !== 'rowMenu') { + if (e.column.colId !== 'rowMenu' && e.column.userProvidedColDef.notSelectable !== true) { e.node.setSelected(true); } }, diff --git a/app/javascript/vue/shared/menu_dropdown.vue b/app/javascript/vue/shared/menu_dropdown.vue index 1d3e3f2b8..a30e221af 100644 --- a/app/javascript/vue/shared/menu_dropdown.vue +++ b/app/javascript/vue/shared/menu_dropdown.vue @@ -1,69 +1,69 @@