Merge pull request #10579 from demarches-simplifiees/instructeur-invitation-include-typo-suggestion-ldu
ETQ admin et instructeur, lorsque je gère ma liste d'instructeurs sur une démarche, je suis guidé pour eviter les typos
This commit is contained in:
commit
72f840e393
8 changed files with 76 additions and 43 deletions
|
@ -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
|
||||
|
|
|
@ -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',
|
||||
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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,7 +425,7 @@ 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
|
||||
|
@ -433,14 +433,14 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do
|
|||
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))
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue