diff --git a/app/controllers/administrateurs/experts_procedures_controller.rb b/app/controllers/administrateurs/experts_procedures_controller.rb index c9e3c5763..54895580b 100644 --- a/app/controllers/administrateurs/experts_procedures_controller.rb +++ b/app/controllers/administrateurs/experts_procedures_controller.rb @@ -10,16 +10,10 @@ module Administrateurs def create emails = params['emails'].presence || [] - emails = emails.map { EmailSanitizer.sanitize(_1) } - @maybe_typos, no_suggestions = emails - .map { |email| [email, EmailChecker.check(email:)[:suggestions]&.first] } - .partition { _1[1].present? } + emails = check_if_typo(emails) errors = Array.wrap(generate_emails_suggestions_message(@maybe_typos)) - emails = no_suggestions.map(&:first) - emails << EmailSanitizer.sanitize(params['final_email']) if params['final_email'].present? - valid_users, invalid_users = emails .map { |email| User.create_or_promote_to_expert(email, SecureRandom.hex) } .partition(&:valid?) @@ -78,14 +72,5 @@ module Administrateurs def expert_procedure_params params.require(:experts_procedure).permit(:allow_decision_access) end - - def generate_emails_suggestions_message(suggestions) - return if suggestions.empty? - - typo_list = suggestions.map(&:first).join(', ') - verification_link = view_context.link_to("vérifier l’orthographe", "#maybe_typos_errors") - - "Attention, nous pensons avoir identifié une faute de frappe dans les invitations : #{typo_list}. Veuillez #{verification_link} des invitations." - end end end diff --git a/app/controllers/administrateurs/groupe_instructeurs_controller.rb b/app/controllers/administrateurs/groupe_instructeurs_controller.rb index 4e566982b..aa422b281 100644 --- a/app/controllers/administrateurs/groupe_instructeurs_controller.rb +++ b/app/controllers/administrateurs/groupe_instructeurs_controller.rb @@ -1,6 +1,7 @@ module Administrateurs class GroupeInstructeursController < AdministrateurController include ActiveSupport::NumberHelper + include EmailSanitizableConcern include Logic include UninterlacePngConcern include GroupeInstructeursSignatureConcern @@ -218,19 +219,22 @@ module Administrateurs end def add_instructeur - emails = params[:emails].presence || [] - emails = emails.map { EmailSanitizableConcern::EmailSanitizer.sanitize(_1) } + emails = params['emails'].presence || [] + emails = check_if_typo(emails) + errors = Array.wrap(generate_emails_suggestions_message(@maybe_typos)) instructeurs, invalid_emails = groupe_instructeur.add_instructeurs(emails:) if invalid_emails.present? - flash[:alert] = t('.wrong_address', - count: invalid_emails.size, - emails: invalid_emails.join(', ')) + errors += [ + t('.wrong_address', + count: invalid_emails.size, + emails: invalid_emails.join(', ')) + ] end if instructeurs.present? - flash[:notice] = if procedure.routing_enabled? + flash.now[:notice] = if procedure.routing_enabled? t('.assignment', count: instructeurs.size, emails: instructeurs.map(&:email).join(', '), @@ -250,10 +254,18 @@ module Administrateurs end end + flash.now[:alert] = errors.join(". ") if !errors.empty? + + @procedure = procedure + @instructeurs = paginated_instructeurs + @available_instructeur_emails = available_instructeur_emails + if procedure.routing_enabled? - redirect_to admin_procedure_groupe_instructeur_path(procedure, groupe_instructeur) + @groupe_instructeur = groupe_instructeur + render :show else - redirect_to admin_procedure_groupe_instructeurs_path(procedure) + @groupes_instructeurs = paginated_groupe_instructeurs + render :index end end diff --git a/app/controllers/instructeurs/groupe_instructeurs_controller.rb b/app/controllers/instructeurs/groupe_instructeurs_controller.rb index 3193d9455..932564f83 100644 --- a/app/controllers/instructeurs/groupe_instructeurs_controller.rb +++ b/app/controllers/instructeurs/groupe_instructeurs_controller.rb @@ -1,5 +1,6 @@ module Instructeurs class GroupeInstructeursController < InstructeurController + include EmailSanitizableConcern include UninterlacePngConcern include GroupeInstructeursSignatureConcern @@ -19,16 +20,29 @@ module Instructeurs end def add_instructeur - instructeur = Instructeur.by_email(instructeur_email) || - create_instructeur(instructeur_email) + email = instructeur_email.present? ? [instructeur_email] : [] + email = check_if_typo(email)&.first + errors = Array.wrap(generate_emails_suggestions_message(@maybe_typos)) + + if !errors.empty? + flash.now[:alert] = errors.join(". ") if !errors.empty? + + @procedure = procedure + @groupe_instructeur = groupe_instructeur + @instructeurs = paginated_instructeurs + return render :show + end + + instructeur = Instructeur.by_email(email) || + create_instructeur(email) if instructeur.blank? - flash[:alert] = "L’adresse email « #{instructeur_email} » n’est pas valide." + flash[:alert] = "L’adresse email « #{email} » n’est pas valide." elsif groupe_instructeur.instructeurs.include?(instructeur) - flash[:alert] = "L’instructeur « #{instructeur_email} » est déjà dans le groupe." + flash[:alert] = "L’instructeur « #{email} » est déjà dans le groupe." else groupe_instructeur.add(instructeur) - flash[:notice] = "L’instructeur « #{instructeur_email} » a été affecté au groupe." + flash[:notice] = "L’instructeur « #{email} » a été affecté au groupe." if instructeur.user.email_verified_at GroupeInstructeurMailer @@ -100,7 +114,7 @@ module Instructeurs end def instructeur_email - params[:instructeur][:email].strip.downcase + params.dig('instructeur', 'email')&.strip&.downcase end def instructeur_id diff --git a/app/models/concerns/email_sanitizable_concern.rb b/app/models/concerns/email_sanitizable_concern.rb index d143c7c7d..80b598eec 100644 --- a/app/models/concerns/email_sanitizable_concern.rb +++ b/app/models/concerns/email_sanitizable_concern.rb @@ -8,6 +8,26 @@ module EmailSanitizableConcern end end + def generate_emails_suggestions_message(suggestions) + return if suggestions.empty? + + typo_list = suggestions.map(&:first).join(', ') + verification_link = view_context.link_to("vérifier l’orthographe", "#maybe_typos_errors") + + "Attention, nous pensons avoir identifié une faute de frappe dans les invitations : #{typo_list}. Veuillez #{verification_link} des invitations." + end + + def check_if_typo(emails) + emails = emails.map { EmailSanitizer.sanitize(_1) } + @maybe_typos, no_suggestions = emails + .map { |email| [email, EmailChecker.check(email:)[:suggestions]&.first] } + .partition { _1[1].present? } + + emails = no_suggestions.map(&:first) + emails << EmailSanitizer.sanitize(params['final_email']) if params['final_email'].present? + emails + end + class EmailSanitizer def self.sanitize(value) value.gsub(/[[:space:]]/, ' ').strip.downcase diff --git a/app/views/administrateurs/groupe_instructeurs/_instructeurs.html.haml b/app/views/administrateurs/groupe_instructeurs/_instructeurs.html.haml index d4ff19e32..4c8c4371d 100644 --- a/app/views/administrateurs/groupe_instructeurs/_instructeurs.html.haml +++ b/app/views/administrateurs/groupe_instructeurs/_instructeurs.html.haml @@ -1,5 +1,6 @@ .card + = render Procedure::InvitationWithTypoComponent.new(maybe_typos: @maybe_typos, url: add_instructeur_admin_procedure_groupe_instructeur_path(@procedure, groupe_instructeur.id), title: "Avant d'ajouter l'email, veuillez confirmer" ) .card-title Affectation des instructeurs = form_for :instructeur, url: { action: :add_instructeur, id: groupe_instructeur.id }, html: { class: 'form' } do |f| .instructeur-wrapper diff --git a/app/views/instructeurs/groupe_instructeurs/show.html.haml b/app/views/instructeurs/groupe_instructeurs/show.html.haml index 1197d93bd..e0a42aa46 100644 --- a/app/views/instructeurs/groupe_instructeurs/show.html.haml +++ b/app/views/instructeurs/groupe_instructeurs/show.html.haml @@ -21,6 +21,7 @@ Démarche « #{@procedure.libelle} » .card.fr-mt-2w + = render Procedure::InvitationWithTypoComponent.new(maybe_typos: @maybe_typos, url: add_instructeur_instructeur_groupe_path(@procedure, @groupe_instructeur.id), title: "Avant d'ajouter l'email, veuillez confirmer" ) %h2.fr-h3 Gestion des instructeurs = form_for(Instructeur.new(user: User.new), url: { action: :add_instructeur }, html: { class: 'form' }) do |f| %h3.fr-h4 Affecter un nouvel instructeur diff --git a/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb b/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb index 4b5c3d796..e916435de 100644 --- a/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb +++ b/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb @@ -341,7 +341,7 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do context 'when all emails are valid' do let(:emails) { ['test@b.gouv.fr', 'test2@b.gouv.fr'] } it do - expect(subject).to redirect_to admin_procedure_groupe_instructeurs_path(procedure_non_routee) + expect(subject).to render_template(:index) expect(subject.request.flash[:alert]).to be_nil expect(subject.request.flash[:notice]).to be_present end @@ -350,7 +350,7 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do context 'when there is at least one bad email' do let(:emails) { ['badmail', 'instructeur2@gmail.com'] } it do - expect(subject).to redirect_to admin_procedure_groupe_instructeurs_path(procedure_non_routee) + expect(subject).to render_template(:index) expect(subject.request.flash[:alert]).to be_present expect(subject.request.flash[:notice]).to be_present end @@ -360,7 +360,7 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do let(:instructeur) { create(:instructeur) } before { procedure_non_routee.groupe_instructeurs.first.add_instructeurs(emails: [instructeur.user.email]) } let(:emails) { [instructeur.email] } - it { expect(subject).to redirect_to admin_procedure_groupe_instructeurs_path(procedure_non_routee) } + it { expect(subject).to render_template(:index) } end context 'when signed in admin comes from manager' do @@ -385,7 +385,7 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do context 'of news instructeurs' do let!(:user_email_verified) { create(:user, :with_email_verified) } let!(:instructeur_email_verified) { create(:instructeur, user: user_email_verified) } - let(:new_instructeur_emails) { ['new_i1@mail.com', 'new_i2@mail.com', instructeur_email_verified.email] } + let(:new_instructeur_emails) { ['new_i1@gmail.com', 'new_i2@gmail.com', instructeur_email_verified.email] } before do allow(GroupeInstructeurMailer).to receive(:notify_added_instructeurs) @@ -398,7 +398,7 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do it 'validates changes and responses' do expect(gi_1_2.instructeurs.pluck(:email)).to include(*new_instructeur_emails) expect(flash.notice).to be_present - expect(response).to redirect_to(admin_procedure_groupe_instructeur_path(procedure, gi_1_2)) + expect(response).to render_template(:show) expect(procedure.routing_enabled?).to be_truthy expect(GroupeInstructeurMailer).to have_received(:notify_added_instructeurs).with( gi_1_2, @@ -409,13 +409,13 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do it "calls InstructeurMailer with the right params" do expect(InstructeurMailer).to have_received(:confirm_and_notify_added_instructeur).with( - User.find_by(email: 'new_i1@mail.com').instructeur, + User.find_by(email: 'new_i1@gmail.com').instructeur, gi_1_2, admin.email ) expect(InstructeurMailer).to have_received(:confirm_and_notify_added_instructeur).with( - User.find_by(email: 'new_i2@mail.com').instructeur, + User.find_by(email: 'new_i2@gmail.com').instructeur, gi_1_2, admin.email ) @@ -425,22 +425,22 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do context 'of an instructeur already in the group' do let(:new_instructeur_emails) { [instructeur.email] } before { do_request } - it { expect(response).to redirect_to(admin_procedure_groupe_instructeur_path(procedure, gi_1_2)) } + it { expect(response).to render_template(:show) } end context 'of badly formed email' do let(:new_instructeur_emails) { ['badly_formed_email'] } before { do_request } it do - expect(flash.alert).to be_present - expect(response).to redirect_to(admin_procedure_groupe_instructeur_path(procedure, gi_1_2)) - end + expect(flash.alert).to be_present + expect(response).to render_template(:show) + end end context 'of an empty string' do let(:new_instructeur_emails) { [''] } before { do_request } - it { expect(response).to redirect_to(admin_procedure_groupe_instructeur_path(procedure, gi_1_2)) } + it { expect(response).to render_template(:show) } end context 'when connected as an administrateur from manager' do diff --git a/spec/controllers/instructeurs/groupe_instructeurs_controller_spec.rb b/spec/controllers/instructeurs/groupe_instructeurs_controller_spec.rb index bc5bf8e2b..5fa6cf44f 100644 --- a/spec/controllers/instructeurs/groupe_instructeurs_controller_spec.rb +++ b/spec/controllers/instructeurs/groupe_instructeurs_controller_spec.rb @@ -86,7 +86,7 @@ describe Instructeurs::GroupeInstructeursController, type: :controller do end context 'of a new instructeur' do - let(:new_instructeur_email) { 'new_instructeur@mail.com' } + let(:new_instructeur_email) { 'new_instructeur@gmail.com' } before { subject } it "works" do