From 4d2fe22dafa9eebe6be76b50b0c2ff319884448f Mon Sep 17 00:00:00 2001 From: Sebastian Serth Date: Tue, 20 Sep 2022 15:52:55 +0200 Subject: [PATCH] Allow assignment of study groups for internal users --- app/controllers/internal_users_controller.rb | 29 +++++++++++++++++++- app/models/internal_user.rb | 2 ++ app/models/study_group_membership.rb | 8 ++++++ app/views/internal_users/_form.html.slim | 24 +++++++++++++++- config/locales/de.yml | 9 ++++++ config/locales/en.yml | 9 ++++++ 6 files changed, 79 insertions(+), 2 deletions(-) diff --git a/app/controllers/internal_users_controller.rb b/app/controllers/internal_users_controller.rb index 3b5c568f..64e80e30 100644 --- a/app/controllers/internal_users_controller.rb +++ b/app/controllers/internal_users_controller.rb @@ -6,6 +6,7 @@ class InternalUsersController < ApplicationController before_action :require_activation_token, only: :activate before_action :require_reset_password_token, only: :reset_password before_action :set_user, only: MEMBER_ACTIONS + before_action :collect_set_and_unset_study_group_memberships, only: MEMBER_ACTIONS + %i[create] after_action :verify_authorized, except: %i[activate forgot_password reset_password] def activate @@ -73,7 +74,19 @@ class InternalUsersController < ApplicationController end def internal_user_params - params.require(:internal_user).permit(:consumer_id, :email, :name) + permitted_params = params.require(:internal_user).permit(:consumer_id, :email, :name, study_group_ids: []).presence || {} + checked_study_group_memberships = @study_group_memberships.select {|sgm| permitted_params[:study_group_ids]&.include? sgm.study_group.id.to_s } + removed_study_group_memberships = @study_group_memberships.reject {|sgm| permitted_params[:study_group_ids]&.include? sgm.study_group.id.to_s } + + checked_study_group_memberships.each do |sgm| + sgm.role = params[:study_group_membership_roles][sgm.study_group.id.to_s][:role] + sgm.user = @user + end + + permitted_params[:study_group_memberships] = checked_study_group_memberships + permitted_params.delete :study_group_ids + removed_study_group_memberships.map(&:destroy) + permitted_params end private :internal_user_params @@ -85,6 +98,7 @@ class InternalUsersController < ApplicationController def new @user = InternalUser.new authorize! + collect_set_and_unset_study_group_memberships end def render_forgot_password_form @@ -132,6 +146,19 @@ class InternalUsersController < ApplicationController end private :set_user + def collect_set_and_unset_study_group_memberships + @study_groups = policy_scope(StudyGroup) + @user ||= InternalUser.new # Only needed for the `create` action + checked_study_group_memberships = @user.study_group_memberships + checked_study_groups = checked_study_group_memberships.collect(&:study_group).sort.to_set + unchecked_study_groups = StudyGroup.all.order(name: :asc).to_set.subtract checked_study_groups + @study_group_memberships = checked_study_group_memberships + unchecked_study_groups.collect do |study_group| + StudyGroupMembership.new(user: @user, study_group: study_group) + end + end + + private :collect_set_and_unset_study_group_memberships + def show; end def update diff --git a/app/models/internal_user.rb b/app/models/internal_user.rb index 9bf8d148..5d831967 100644 --- a/app/models/internal_user.rb +++ b/app/models/internal_user.rb @@ -11,6 +11,8 @@ class InternalUser < User validates :password, confirmation: true, if: -> { password_void? && validate_password? }, on: :update, presence: true validate :password_strength, if: -> { password_void? && validate_password? }, on: :update + accepts_nested_attributes_for :study_group_memberships + def activated? activation_state == 'active' end diff --git a/app/models/study_group_membership.rb b/app/models/study_group_membership.rb index 5ff0e96e..e732e4ed 100644 --- a/app/models/study_group_membership.rb +++ b/app/models/study_group_membership.rb @@ -1,9 +1,17 @@ # frozen_string_literal: true class StudyGroupMembership < ApplicationRecord + ROLES = %w[learner teacher].freeze + belongs_to :user, polymorphic: true belongs_to :study_group + before_save :destroy_if_empty_study_group_or_user + + def destroy_if_empty_study_group_or_user + destroy if study_group.blank? || user.blank? + end + enum role: { learner: 0, teacher: 1, diff --git a/app/views/internal_users/_form.html.slim b/app/views/internal_users/_form.html.slim index a2f99f10..049671cf 100644 --- a/app/views/internal_users/_form.html.slim +++ b/app/views/internal_users/_form.html.slim @@ -12,5 +12,27 @@ .form-check label.form-check-label = f.check_box(:platform_admin, class: 'form-check-input') - = f.label(:platform_admin, t('activerecord.attributes.external_user.platform_admin'), class: 'form-label') + = f.label(:platform_admin, t('activerecord.attributes.internal_user.platform_admin'), class: 'form-label') + + h2.mt-4 = t('internal_users.form.study_groups') + ul.list-unstyled.card-group + li.card + .card-header role="tab" id="heading" + a.file-heading data-bs-toggle="collapse" href="#study-group-collapse" + div.clearfix role="button" + span = t('internal_users.form.click_to_collapse') + .card-collapse.collapse id="study-group-collapse" role="tabpanel" + .table-responsive + table.table.overflow-hidden#study-groups-table + thead + tr + th = t('activerecord.attributes.study_group.selection') + th = t('activerecord.attributes.study_group.name') + th = t('activerecord.attributes.study_group_membership.role') + = collection_check_boxes :user, :study_group_ids, @study_group_memberships, :study_group_id, :id, {namespace: :internal_user} do |b| + tr + td = b.check_box class: 'form-check-input', name: "internal_user[study_group_ids][]" + td = b.object.study_group.name + td = select "study_group_membership_roles[#{b.object.study_group.id}]", :role, StudyGroupMembership::ROLES.map { |role| [t("activerecord.attributes.study_group_membership.role_type.#{role}"), role] }, {selected: b.object.persisted? ? b.object.role : nil, include_blank: true}, class: 'form-control form-control-sm' + .actions = render('shared/submit_button', f: f, object: @user) diff --git a/config/locales/de.yml b/config/locales/de.yml index a20665d0..63b54648 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -119,6 +119,12 @@ de: consumer: Konsument members: Mitglieder member_count: Anzahl der Mitglieder + selection: Ausgewählt + study_group_membership: + role: Rolle + role_type: + learner: Lernender + teacher: Lehrender tag: name: Name usage: Verwendet @@ -583,6 +589,9 @@ de: success: Sie haben Ihr Passwort erfolgreich geändert. show: link: Profil + form: + study_groups: Lerngruppen + click_to_collapse: Zum Aus-/Einklappen hier klicken... search: search_in_forum: "Probleme? Suche hier im Forum" locales: diff --git a/config/locales/en.yml b/config/locales/en.yml index 23847f9c..aa0d8f51 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -119,6 +119,12 @@ en: consumer: Consumer members: Members member_count: Member Count + selection: Selected + study_group_membership: + role: Role + role_type: + learner: Learner + teacher: Teacher tag: name: Name usage: Used @@ -573,6 +579,9 @@ en: headline: Complete Registration submit: Set Password success: You successfully completed your registration. + form: + study_groups: Study Groups + click_to_collapse: Click to expand/collapse... forgot_password: headline: Reset Password submit: Send Password Reset Instructions