From d3fb03082c84b6b68b1a7e046fdd5db5ba21db4f Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Fri, 22 Nov 2024 14:37:25 +0100 Subject: [PATCH 1/9] clean: french quote in trad file --- config/locales/fr.yml | 76 +++++++++---------- ...onnaire_administrateurs_controller_spec.rb | 10 +-- .../_procedure_description.html.haml_spec.rb | 2 +- 3 files changed, 44 insertions(+), 44 deletions(-) diff --git a/config/locales/fr.yml b/config/locales/fr.yml index dae9dba767e..3c5698260f7 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -100,7 +100,7 @@ fr: line_three: "75007 PARIS" direction: "Direction de la publication" direction_content: "Madame Stéphanie Schaer, Directrice interministérielle du numérique." - hosting: "Prestataire d'hébergement" + hosting: "Prestataire d’hébergement" hosting_content: firm: "OVH" RCS_term: "RCS" @@ -120,12 +120,12 @@ fr: content_html: "Le site Démarches simplifiées est partiellement conforme au Référentiel Général d’Amélioration de l’Accessibilité (RGAA) version 4.1.2 en raison des non-conformités listées ci-après." results: title: "Résultats des tests" - content: "L'audit réalisé en interne en juin 2023 révèle que le taux de conformité global est de 81,36% sur l'échantillon de pages analysés." + content: "L’audit réalisé en interne en juin 2023 révèle que le taux de conformité global est de 81,36% sur l’échantillon de pages analysés." programme: intro: "Les usagers peuvent suivre les mesures engagées par le service pour améliorer l’accessibilité du site grâce au " - label: "programme d'amélioration continue de DS en matière d'accessibilité" + label: "programme d’amélioration continue de DS en matière d’accessibilité" url: "https://github.com/demarches-simplifiees/demarches-simplifiees.fr/issues?q=accessibilit%C3%A9+" - title: "programme d'amélioration continue de DS en matière d'accessibilité - nouvel onglet" + title: "programme d’amélioration continue de DS en matière d’accessibilité - nouvel onglet" no_accessible: title: "Contenus non accessibles" subtitle_one: "Non-conformités" @@ -145,7 +145,7 @@ fr: " subtitle_two: "Remarques complémentaires" content_html: "

Les pages de documentation sont gérées par un outil tiers. Elles ne sont pas entièrement accessibles.

-

La gestion de la FAQ était déléguée à un outil tiers. Elle a été réintégrée à la plateforme en mai 2024 et n'a pas encore été auditée.

" +

La gestion de la FAQ était déléguée à un outil tiers. Elle a été réintégrée à la plateforme en mai 2024 et n’a pas encore été auditée.

" preparation: title: "Établissement de cette déclaration d’accessibilité" @@ -194,11 +194,11 @@ fr: adress_html: "Par voie postale : DINUM , 20 avenue de Ségur 75007 Paris" remedies: title: "Voies de recours" - line_one: "Si vous constatez un défaut d’accessibilité vous empêchant d’accéder à un contenu ou une fonctionnalité du site, que vous nous le signalez et que vous ne parvenez pas à obtenir une réponse rapide de notre part, vous êtes en droit de contacter l'Arcom ou de saisir le Défenseur des droits." - arcom_title: "Contacter l'Arcom" - arcom_content_html: "Afin de signaler un ou plusieurs manquement(s) à la réglementation relative à l’accessibilité numérique, rendez-vous sur le formulaire de contact du site web de l'Arcom." + line_one: "Si vous constatez un défaut d’accessibilité vous empêchant d’accéder à un contenu ou une fonctionnalité du site, que vous nous le signalez et que vous ne parvenez pas à obtenir une réponse rapide de notre part, vous êtes en droit de contacter l’Arcom ou de saisir le Défenseur des droits." + arcom_title: "Contacter l’Arcom" + arcom_content_html: "Afin de signaler un ou plusieurs manquement(s) à la réglementation relative à l’accessibilité numérique, rendez-vous sur le formulaire de contact du site web de l’Arcom." ddd_title: "Saisir le Défenseur des droits" - ddd_intro: "Pour faire valoir vos droits relatifs à des défauts d'accessibilité que vous avez rencontrés, plusieurs moyens sont à votre disposition :" + ddd_intro: "Pour faire valoir vos droits relatifs à des défauts d’accessibilité que vous avez rencontrés, plusieurs moyens sont à votre disposition :" remedies_one: label: "Un formulaire de contact" url: "https://www.defenseurdesdroits.fr/nous-contacter" @@ -208,14 +208,14 @@ fr: label: "Contacter le délégué du Défenseur des droits dans votre région" url: "https://www.defenseurdesdroits.fr/fr/saisir/delegues" title: "Contacter le délégué du Défenseur des droits dans votre région - nouvel onglet" - remedies_three_html: "Envoyer un courrier par la poste (gratuit, ne pas mettre de timbre) à l'adresse suivante : + remedies_three_html: "Envoyer un courrier par la poste (gratuit, ne pas mettre de timbre) à l’adresse suivante :

Défenseur des droits
Libre réponse 71120
75342 Paris CEDEX 07

" prefill_descriptions: edit: - intro_html: "Vous souhaitez permettre à vos usager·ères la création d'un dossier prérempli, à partir de données dont vous disposez déjà, pour la démarche « %{libelle} »." - info_html: Pour cela, sélectionnez ci-dessous les champs que vous souhaitez préremplir.
Vous trouverez ensuite en bas de cette page un lien de préremplissage qu'il ne vous restera plus qu'à copier, à adapter en remplaçant les valeurs par défaut et à partager.
De la même façon, vous trouverez en bas de page un exemple de requête cURL à adapter si vous souhaitez préremplir les dossiers par API. + intro_html: "Vous souhaitez permettre à vos usager·ères la création d’un dossier prérempli, à partir de données dont vous disposez déjà, pour la démarche « %{libelle} »." + info_html: Pour cela, sélectionnez ci-dessous les champs que vous souhaitez préremplir.
Vous trouverez ensuite en bas de cette page un lien de préremplissage qu’il ne vous restera plus qu’à copier, à adapter en remplaçant les valeurs par défaut et à partager.
De la même façon, vous trouverez en bas de page un exemple de requête cURL à adapter si vous souhaitez préremplir les dossiers par API. champ_id: ID champ_type: Type entity_add: Ajouter @@ -259,9 +259,9 @@ fr: rna_html: Un numéro RNA siret_html: Un numéro de SIRET repetition_html: Un tableau de dictionnaires avec les valeurs possibles pour chaque champ de la répétition. - annuaire_education_html: Un code d'établissement scolaire, tel que défini par l'Annuaire de l'Éducation Nationale + annuaire_education_html: Un code d’établissement scolaire, tel que défini par l’Annuaire de l’Éducation Nationale dossier_link_html: L’identifiant du dossier, sous forme de nombre entier - epci_html: Un tableau contenant le code de département et celui de l'EPCI + epci_html: Un tableau contenant le code de département et celui de l’EPCI examples: title: Exemple prenom: "Jean" @@ -393,15 +393,15 @@ fr: a_suivre: Aucun instructeur n’est affecté au suivi de ces dossiers. Soyez le premier ! suivis: Les dossiers qui sont dans cet onglet sont uniquement ceux que vous suivez. Vous pouvez échanger avec le demandeur jusqu’à pouvoir les accepter, les refuser ou les classer sans suite. traites_html: "Les dossiers dans cet onglet sont terminés : ils ont été acceptés, refusés ou classés sans suite. Vous pouvez télécharger les archives au format zip des dossiers terminés et leurs pièces jointes." - tous: Tous les dossiers déposés sur cette démarche, qu'ils soient à suivre, suivis par vous ou suivis par d'autres instructeurs. - tous_with_routing: Tous les dossiers déposés sur cette démarche et attribués aux groupes d'instructeurs dont vous faites partie. + tous: Tous les dossiers déposés sur cette démarche, qu’ils soient à suivre, suivis par vous ou suivis par d’autres instructeurs. + tous_with_routing: Tous les dossiers déposés sur cette démarche et attribués aux groupes d’instructeurs dont vous faites partie. supprimes: Tous les dossiers non archivés, terminés et supprimés par les instructeurs sur cette démarche archives: "Les dossiers de cet onglet sont archivés : vous ne pouvez plus y répondre, et les demandeurs ne peuvent plus les modifier." expirant: Les dossiers n’expireront pas avant la période de conservation des données. archived_dossier: "Le dossier sera conservé 1 mois supplémentaire" delete_dossier: "Supprimer le dossier" deleted_reason: - user_request: supprimé par l'usager + user_request: supprimé par l’usager expired: a expiré acts_on_behalf: "agit pour" deleted_by_administration: "Dossier supprimé par l’administration" @@ -412,7 +412,7 @@ fr: select_all: Tout selectionner batch_operation: enabled: "Ajouter le dossier %{dossier_id} à la sélection pour un traitement de masse" - disabled: "Impossible d'ajouter le dossier %{dossier_id} à la selection car il est déjà dans un traitement de masse" + disabled: "Impossible d’ajouter le dossier %{dossier_id} à la selection car il est déjà dans un traitement de masse" show_deleted_dossiers: Historique des dossiers supprimés customize: Personnaliser le tableau passer_en_instruction: Passer en instruction @@ -477,7 +477,7 @@ fr: delay_title: sva: "Votre dossier est soumis au cadre législatif « Silence Vaut Accord »" svr: "Votre dossier est soumis au cadre législatif « Silence Vaut Rejet »" - delay_text_sva_svr: "Vous aurez un retour de l'administration au plus tard le %{date}." + delay_text_sva_svr: "Vous aurez un retour de l’administration au plus tard le %{date}." status_completed: terminé use_mailbox_for_questions_html: "Vous avez une question ? Utilisez la messagerie pour contacter l’administration directement." acceptee_html: "Votre dossier a été accepté." @@ -519,12 +519,12 @@ fr: other_html: Cette démarche est close. Vous ne pouvez pas déposer ce dossier, ni en déposer un nouveau pour cette démarche. %{link} en_cours: internal_procedure_html: Cette démarche est close. Votre dossier est bien déposé et peut être instruit par l’administration. Au besoin, vous pouvez déposer un nouveau dossier sur la %{link} qui la remplace. - other_html: Cette démarche est close. Votre dossier est bien déposé et peut être instruit par l'administration. Vous ne pouvez pas déposer de nouveau dossier pour cette démarche. %{link} + other_html: Cette démarche est close. Votre dossier est bien déposé et peut être instruit par l’administration. Vous ne pouvez pas déposer de nouveau dossier pour cette démarche. %{link} termine: - internal_procedure_html: Cette démarche est close. Votre dossier a bien été traité par l'administration. Au besoin, vous pouvez déposer un nouveau dossier sur la %{link} qui la remplace. - other_html: Cette démarche est close. Votre dossier a bien été traité par l'administration. Vous ne pouvez pas déposer de nouveau dossier pour cette démarche. %{link} + internal_procedure_html: Cette démarche est close. Votre dossier a bien été traité par l’administration. Au besoin, vous pouvez déposer un nouveau dossier sur la %{link} qui la remplace. + other_html: Cette démarche est close. Votre dossier a bien été traité par l’administration. Vous ne pouvez pas déposer de nouveau dossier pour cette démarche. %{link} title_new_procedure: Nouvelle démarche disponible - title_closing_details: Plus d'informations sur la clôture de la démarche + title_closing_details: Plus d’informations sur la clôture de la démarche more_details: Plus d’informations procedure: démarche this_procedure: cette démarche @@ -533,8 +533,8 @@ fr: created_at: Créé le %{date} updated_at: modifié le %{date} shared_with: Dossier partagé par %{owner} avec - deleted_by_user: Supprimé le %{date} par l'usager - deleted_by_automatic: Supprimé le %{date} automatiquement du à la date d'expiration + deleted_by_user: Supprimé le %{date} par l’usager + deleted_by_automatic: Supprimé le %{date} automatiquement du à la date d’expiration dossier_action: edit_dossier: "Modifier le dossier" start_other_dossier: "Commencer un nouveau dossier" @@ -726,9 +726,9 @@ fr: code_departement: not_in_departement_codes: "doit être un code de département valide" external_id: - not_in_departement_epci_codes: "doit être un code d'EPCI du département correspondant" + not_in_departement_epci_codes: "doit être un code d’EPCI du département correspondant" value: - not_in_departement_epci_names: "doit être un nom d'EPCI du département correspondant" + not_in_departement_epci_names: "doit être un nom d’EPCI du département correspondant" "champs/dossier_link_champ": attributes: value: @@ -751,9 +751,9 @@ fr: france_connect: connexion: "Erreur lors de la connexion à France Connect." forbidden_html: "Seul-e-s les usagers peuvent se connecter via France Connect. En tant qu’instructeur ou administrateur, nous vous invitons à réininitialiser votre mot de passe." - evil_regexp: L'expression régulière que vous avez entrée est potentiellement dangereuse et pourrait entraîner des problèmes de performance - mismatch_regexp: L'exemple doit correspondre à l'expression régulière fournie - syntax_error_regexp: La syntaxe de l'expression régulière n'est pas valide + evil_regexp: L’expression régulière que vous avez entrée est potentiellement dangereuse et pourrait entraîner des problèmes de performance + mismatch_regexp: L’exemple doit correspondre à l’expression régulière fournie + syntax_error_regexp: La syntaxe de l’expression régulière n’est pas valide # procedure_not_draft: "Cette démarche n’est maintenant plus en brouillon." cadastres_empty: one: "Aucune parcelle cadastrale sur la zone sélectionnée" @@ -831,7 +831,7 @@ fr: users: dossiers: test_procedure: "Ce dossier est déposé sur une démarche en test. Toute modification de la démarche par l’administrateur (ajout d’un champ, publication de la démarche...) entraînera sa suppression." - no_access_html: "Vous n’avez pas accès à ce dossier.
Vérifiez que votre adresse email de connexion %{email} est bien celle utilisée pour remplir cette démarche.
Si ce n'est pas le cas, déconnectez-vous" + no_access_html: "Vous n’avez pas accès à ce dossier.
Vérifiez que votre adresse email de connexion %{email} est bien celle utilisée pour remplir cette démarche.
Si ce n’est pas le cas, déconnectez-vous" no_longer_editable: "Votre dossier ne peut plus être modifié" en_construction_submitted: "Les modifications ont déjà été déposées" fill_identity: @@ -934,7 +934,7 @@ fr: particulier: choose_email: intro_html: "Votre compte FranceConnect utilise %{email} comme email de contact." - use_email_for_notifications: Souhaitez-vous l'utiliser pour recevoir les notifications concernant l'avancement de vos dossiers ? + use_email_for_notifications: Souhaitez-vous l’utiliser pour recevoir les notifications concernant l’avancement de vos dossiers ? confirm: Confirmer choose_email_contact: Choisissez votre email de contact pour finaliser votre connexion alternative_email: Veuillez nous fournir l'email à utiliser pour vous contacter. @@ -970,16 +970,16 @@ fr: flash: alert: groupe_gestionnaire_administrateur: - cannot_be_deleted: "L'administrateur « %{email} » ne peut pas être supprimé du groupe gestionnaire." - not_in_groupe_gestionnaire: "L'administrateur « %{email} » n’est pas dans le groupe gestionnaire." + cannot_be_deleted: "L’administrateur « %{email} » ne peut pas être supprimé du groupe gestionnaire." + not_in_groupe_gestionnaire: "L’administrateur « %{email} » n’est pas dans le groupe gestionnaire." groupe_gestionnaire_gestionnaire: destroy_at_least_one: "Suppression impossible : il doit y avoir au moins un gestionnaire dans le groupe racine" not_in_groupe_gestionnaire: "Le gestionnaire « %{email} » n’est pas dans le groupe gestionnaire." notice: groupe_gestionnaire_administrateur: create: "Les administrateurs ont bien été affectés au groupe gestionnaire" - destroy: "L'administrateur « %{email} » a été supprimé." - remove: "L'administrateur « %{email} » a été retiré du groupe gestionnaire." + destroy: "L’administrateur « %{email} » a été supprimé." + remove: "L’administrateur « %{email} » a été retiré du groupe gestionnaire." groupe_gestionnaire_gestionnaire: create: "Les gestionnaires ont bien été affectés au groupe gestionnaire" destroy: "Le gestionnaire « %{email} » a été retiré du groupe gestionnaire." @@ -1011,7 +1011,7 @@ fr: estimated_fill_duration: "Temps de remplissage estimé : %{estimated_minutes} min" estimated_fill_duration_title: Quelle est la durée de remplissage de la démarche ? estimated_fill_duration_detail: "La durée de remplissage est estimée à %{estimated_minutes} min. Ce délai peut varier selon les options que vous choisirez." - usual_traitement_time_title: Quels sont les délais d'instruction pour cette démarche ? + usual_traitement_time_title: Quels sont les délais d’instruction pour cette démarche ? pieces_jointes : Quelles sont les pièces justificatives à fournir ? pieces_jointes_conditionnal_list_title : Liste des pièces en fonction de votre situation sva_svr_title: "Cette démarche applique le « %{rule} »" @@ -1019,5 +1019,5 @@ fr: svr_text_html: "Le SVR, ou « Silence Vaut Rejet », est un principe législatif qui définit le comportement d’une demande en cas d’absence de réponse de l’administration : la demande sera automatiquement refusée à l’issue d’un délai si votre dossier est complet." sva_svr_prevision_date: Ainsi, vous recevrez une réponse à votre demande dans les %{delay} après avoir déposé votre dossier complet. - Par exemple, si vous déposez votre dossier aujourd'hui, vous aurez une réponse au plus tard le %{date}. + Par exemple, si vous déposez votre dossier aujourd’hui, vous aurez une réponse au plus tard le %{date}. Si votre dossier est incomplet, cette date pourrait être repoussée jusqu’à la soumission d’un dossier complété. diff --git a/spec/controllers/gestionnaires/groupe_gestionnaire_administrateurs_controller_spec.rb b/spec/controllers/gestionnaires/groupe_gestionnaire_administrateurs_controller_spec.rb index cf8f4e80a93..b69d3d569ef 100644 --- a/spec/controllers/gestionnaires/groupe_gestionnaire_administrateurs_controller_spec.rb +++ b/spec/controllers/gestionnaires/groupe_gestionnaire_administrateurs_controller_spec.rb @@ -45,7 +45,7 @@ def destroy(administrateur) before { destroy(new_administrateur) } it { expect(groupe_gestionnaire.reload.administrateurs.count).to eq(0) } - it { expect(flash.notice).to eq("L'administrateur « #{new_administrateur.email} » a été supprimé.") } + it { expect(flash.notice).to eq("L’administrateur « #{new_administrateur.email} » a été supprimé.") } end context 'when administrateur has some procedure' do @@ -57,7 +57,7 @@ def destroy(administrateur) end it { expect(groupe_gestionnaire.reload.administrateurs.count).to eq(2) } - it { expect(flash.alert).to eq("L'administrateur « #{administrateur_with_procedure.email} » ne peut pas être supprimé du groupe gestionnaire.") } + it { expect(flash.alert).to eq("L’administrateur « #{administrateur_with_procedure.email} » ne peut pas être supprimé du groupe gestionnaire.") } end context 'when administrateur is not in the groupe_gestionnaire' do @@ -65,7 +65,7 @@ def destroy(administrateur) before { destroy(other_administrateur) } it { expect(groupe_gestionnaire.reload.administrateurs.count).to eq(1) } - it { expect(flash.alert).to eq("L'administrateur « #{other_administrateur.email} » n’est pas dans le groupe gestionnaire.") } + it { expect(flash.alert).to eq("L’administrateur « #{other_administrateur.email} » n’est pas dans le groupe gestionnaire.") } end end @@ -90,7 +90,7 @@ def remove(administrateur) before { remove(new_administrateur) } it { expect(groupe_gestionnaire.reload.administrateurs.count).to eq(0) } - it { expect(flash.notice).to eq("L'administrateur « #{new_administrateur.email} » a été retiré du groupe gestionnaire.") } + it { expect(flash.notice).to eq("L’administrateur « #{new_administrateur.email} » a été retiré du groupe gestionnaire.") } end context 'when administrateur is not in the groupe_gestionnaire' do @@ -98,7 +98,7 @@ def remove(administrateur) before { remove(other_administrateur) } it { expect(groupe_gestionnaire.reload.administrateurs.count).to eq(1) } - it { expect(flash.alert).to eq("L'administrateur « #{other_administrateur.email} » n’est pas dans le groupe gestionnaire.") } + it { expect(flash.alert).to eq("L’administrateur « #{other_administrateur.email} » n’est pas dans le groupe gestionnaire.") } end end end diff --git a/spec/views/shared/_procedure_description.html.haml_spec.rb b/spec/views/shared/_procedure_description.html.haml_spec.rb index 69b77932f47..b9db9292f6d 100644 --- a/spec/views/shared/_procedure_description.html.haml_spec.rb +++ b/spec/views/shared/_procedure_description.html.haml_spec.rb @@ -56,7 +56,7 @@ it 'shows a usual traitement text' do subject - expect(rendered).to have_text("Quels sont les délais d'instruction pour cette démarche ?") + expect(rendered).to have_text("Quels sont les délais d’instruction pour cette démarche ?") expect(rendered).to have_text("Dans le meilleur des cas, le délai d’instruction est : 1 jour.") end end From 08083f8febbf33161dad0009b4340069aab89b8d Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Fri, 22 Nov 2024 14:49:31 +0100 Subject: [PATCH 2/9] refactor: small UX improvements --- config/locales/fr.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 3c5698260f7..8ee69b8c3c8 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -935,17 +935,17 @@ fr: choose_email: intro_html: "Votre compte FranceConnect utilise %{email} comme email de contact." use_email_for_notifications: Souhaitez-vous l’utiliser pour recevoir les notifications concernant l’avancement de vos dossiers ? - confirm: Confirmer + confirm: Valider choose_email_contact: Choisissez votre email de contact pour finaliser votre connexion - alternative_email: Veuillez nous fournir l'email à utiliser pour vous contacter. - keep_fc_email_html: "Oui, utiliser %{email} comme email de contact." - use_another_email: Non, utiliser une autre adresse. + alternative_email: Veuillez nous fournir l’adresse électronique à utiliser pour vous contacter + keep_fc_email_html: "Oui, utiliser %{email} comme email de contact" + use_another_email: Non, utiliser une autre adresse email_suggest: wanna_say: 'Voulez-vous dire ?' confirmation_sent: confirmation_sent_by_email: Confirmez votre email intro_html: "Un mail de confirmation a été envoyé à votre adresse %{email}" - click_the_link_in_the_email: Vous devez impérativement cliquer sur le lien du mail pour activer votre adresse et recevoir les notifications sur l'avancement de vos dossiers. + click_the_link_in_the_email: Vous devez impérativement cliquer sur le lien du mail pour activer votre adresse et recevoir les notifications sur l’avancement de vos dossiers. continue: Continuer merge: title: "Fusion des comptes FranceConnect et %{application_name}" From 5edd54b59898168a4fe1b24305c806da3666781b Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Fri, 22 Nov 2024 15:19:47 +0100 Subject: [PATCH 3/9] fix: verified_email from FC --- .../france_connect/particulier_controller.rb | 5 ++--- .../particulier/confirmation_sent.html.haml | 12 ------------ config/locales/en.yml | 5 ----- config/locales/fr.yml | 5 ----- .../france_connect/particulier_controller_spec.rb | 5 ++--- 5 files changed, 4 insertions(+), 28 deletions(-) delete mode 100644 app/views/france_connect/particulier/confirmation_sent.html.haml diff --git a/app/controllers/france_connect/particulier_controller.rb b/app/controllers/france_connect/particulier_controller.rb index e0a7740de37..0fef3bd653d 100644 --- a/app/controllers/france_connect/particulier_controller.rb +++ b/app/controllers/france_connect/particulier_controller.rb @@ -59,12 +59,11 @@ def send_email_merge_request def merge_using_fc_email @fci.safely_associate_user!(@fci.email_france_connect) + @fci.user.update!(email_verified_at: Time.current) sign_in(@fci.user) - @fci.send_custom_confirmation_instructions - - render :confirmation_sent, locals: { email: @fci.email_france_connect, destination_path: destination_path(@fci.user) } + redirect_to destination_path(@fci.user), notice: t('france_connect.particulier.flash.connection_done', application_name: Current.application_name) end def merge_using_password diff --git a/app/views/france_connect/particulier/confirmation_sent.html.haml b/app/views/france_connect/particulier/confirmation_sent.html.haml deleted file mode 100644 index 98ca08acc3c..00000000000 --- a/app/views/france_connect/particulier/confirmation_sent.html.haml +++ /dev/null @@ -1,12 +0,0 @@ -.fr-container - .fr-col-12.fr-col-md-6.fr-col-offset-md-3 - %h1.fr-mt-6w.fr-h2.center= t('.confirmation_sent_by_email') - - %p.center= image_tag("user/confirmation-email.svg", alt: '') - - = render Dsfr::AlertComponent.new(title: '', state: :info, heading_level: 'h2', extra_class_names: 'fr-mt-6w fr-mb-3w') do |c| - - c.with_body do - %p= t('.intro_html', email: h(email)).html_safe - %p= t('.click_the_link_in_the_email') - - %p.center= link_to t('.continue'), destination_path, class: 'fr-btn' diff --git a/config/locales/en.yml b/config/locales/en.yml index 45765dfed36..80257772832 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -888,11 +888,6 @@ en: alternative_email: "Please provide the email to use for contacting you." keep_fc_email_html: Yes, use %{email} as contact email. use_another_email: No, use another address. - confirmation_sent: - confirmation_sent_by_email: "Confirm your email" - intro_html: "A confirmation email has been sent to your address %{email}" - click_the_link_in_the_email: "Please click the link in the email to confirm your account and connect with France Connect in the future." - continue: "Continue" merge: title: "Merge your account FranceConnect and %{application_name}" subtitle_html: "Hello,

Your account FranceConnect uses %{email} as contact email.
But there is an existing %{application_name} account using this email." diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 8ee69b8c3c8..40a068d4945 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -942,11 +942,6 @@ fr: use_another_email: Non, utiliser une autre adresse email_suggest: wanna_say: 'Voulez-vous dire ?' - confirmation_sent: - confirmation_sent_by_email: Confirmez votre email - intro_html: "Un mail de confirmation a été envoyé à votre adresse %{email}" - click_the_link_in_the_email: Vous devez impérativement cliquer sur le lien du mail pour activer votre adresse et recevoir les notifications sur l’avancement de vos dossiers. - continue: Continuer merge: title: "Fusion des comptes FranceConnect et %{application_name}" subtitle_html: "Bonjour,

Votre compte FranceConnect utilise %{email} comme email de contact.
Or il existe un compte sur %{application_name} avec cet email." diff --git a/spec/controllers/france_connect/particulier_controller_spec.rb b/spec/controllers/france_connect/particulier_controller_spec.rb index bdf717e27d0..8fdf24cadfa 100644 --- a/spec/controllers/france_connect/particulier_controller_spec.rb +++ b/spec/controllers/france_connect/particulier_controller_spec.rb @@ -155,10 +155,9 @@ user = User.last expect(user.email).to eq(email.downcase) - expect(UserMailer).to have_received(:custom_confirmation_instructions).with(user, user.confirmation_token) - expect(user.email_verified_at).to be_nil + expect(user.email_verified_at).not_to be_nil expect(fci.reload.merge_token).to be_nil - expect(response).to render_template(:confirmation_sent) + expect(response).to redirect_to(root_path(user)) end end From d4a69aa61863340aa7ad2eb6ff90c348b2c9c1cf Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Fri, 22 Nov 2024 15:44:28 +0100 Subject: [PATCH 4/9] refactor: no need to leak merge.token in url ... --- .../particulier/choose_email.html.haml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/app/views/france_connect/particulier/choose_email.html.haml b/app/views/france_connect/particulier/choose_email.html.haml index 018d51b399d..4a468635328 100644 --- a/app/views/france_connect/particulier/choose_email.html.haml +++ b/app/views/france_connect/particulier/choose_email.html.haml @@ -9,19 +9,31 @@ %p= t('.use_email_for_notifications') %fieldset.fr-fieldset - = form_with url: france_connect_particulier_merge_using_fc_email_path(merge_token: @fci.merge_token), method: :post, data: { controller: 'email-france-connect' } do |f| + = form_with url: france_connect_particulier_merge_using_fc_email_path, + method: :post, + data: { controller: 'email-france-connect' } do |f| + = hidden_field_tag :merge_token, @fci.merge_token %fieldset.fr-fieldset %legend.fr-fieldset__legend .fr-fieldset__element .fr-radio-group - = f.radio_button :use_france_connect_email, true, id: 'use_france_connect_email_yes', class: 'fr-radio', required: true, data: { action: "email-france-connect#triggerEmailField", email_france_connect_target: "useFranceConnectEmail" } + = f.radio_button :use_france_connect_email, true, + id: 'use_france_connect_email_yes', + class: 'fr-radio', + required: true, + data: { action: "email-france-connect#triggerEmailField", email_france_connect_target: "useFranceConnectEmail" } %label.fr-label.fr-text--wrap{ for: 'use_france_connect_email_yes' } = t('.keep_fc_email_html', email: h(@fci.email_france_connect)).html_safe + .fr-fieldset__element .fr-radio-group - = f.radio_button :use_france_connect_email, false, id: 'use_france_connect_email_no', class: 'fr-radio', required: true, data: { action: "email-france-connect#triggerEmailField", email_france_connect_target: "useFranceConnectEmail" } + = f.radio_button :use_france_connect_email, false, + id: 'use_france_connect_email_no', + class: 'fr-radio', + required: true, + data: { action: "email-france-connect#triggerEmailField", email_france_connect_target: "useFranceConnectEmail" } %label.fr-label.fr-text--wrap{ for: 'use_france_connect_email_no' } = t('.use_another_email') From 451c0165b4b2dd323a2694e02b50a5a6c9acb566 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Fri, 22 Nov 2024 16:13:50 +0100 Subject: [PATCH 5/9] refactor: remove useless connect --- app/javascript/controllers/email_france_connect_controller.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/javascript/controllers/email_france_connect_controller.ts b/app/javascript/controllers/email_france_connect_controller.ts index d9be703affc..173d1798a15 100644 --- a/app/javascript/controllers/email_france_connect_controller.ts +++ b/app/javascript/controllers/email_france_connect_controller.ts @@ -6,10 +6,6 @@ export class EmailFranceConnectController extends ApplicationController { emailFieldTarget!: HTMLElement; useFranceConnectEmailTargets!: HTMLInputElement[]; - connect() { - this.triggerEmailField(); - } - triggerEmailField() { const checkedTarget = this.useFranceConnectEmailTargets.find( (target) => target.checked From 016e9357e194ccb60ad0cd14536e74567fcc020a Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Fri, 22 Nov 2024 16:24:54 +0100 Subject: [PATCH 6/9] refactor: no need for html_safe --- app/views/france_connect/particulier/choose_email.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/france_connect/particulier/choose_email.html.haml b/app/views/france_connect/particulier/choose_email.html.haml index 4a468635328..ab7bca16fa2 100644 --- a/app/views/france_connect/particulier/choose_email.html.haml +++ b/app/views/france_connect/particulier/choose_email.html.haml @@ -25,7 +25,7 @@ required: true, data: { action: "email-france-connect#triggerEmailField", email_france_connect_target: "useFranceConnectEmail" } %label.fr-label.fr-text--wrap{ for: 'use_france_connect_email_yes' } - = t('.keep_fc_email_html', email: h(@fci.email_france_connect)).html_safe + = t('.keep_fc_email_html', email: h(@fci.email_france_connect)) .fr-fieldset__element .fr-radio-group From 4cd6e08a3d0ab5ab80fc3589873990838eb3eafa Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Fri, 22 Nov 2024 16:54:21 +0100 Subject: [PATCH 7/9] UX: change submit disabled state --- .../email_france_connect_controller.ts | 42 ++++++++++++------- .../particulier/choose_email.html.haml | 24 ++++++++--- 2 files changed, 47 insertions(+), 19 deletions(-) diff --git a/app/javascript/controllers/email_france_connect_controller.ts b/app/javascript/controllers/email_france_connect_controller.ts index 173d1798a15..7fe74cee560 100644 --- a/app/javascript/controllers/email_france_connect_controller.ts +++ b/app/javascript/controllers/email_france_connect_controller.ts @@ -1,29 +1,43 @@ import { ApplicationController } from './application_controller'; export class EmailFranceConnectController extends ApplicationController { - static targets = ['useFranceConnectEmail', 'emailField']; + static targets = ['useFranceConnectEmail', 'emailField', 'submit', 'emailInput']; emailFieldTarget!: HTMLElement; useFranceConnectEmailTargets!: HTMLInputElement[]; + submitTarget!: HTMLButtonElement; + emailInputTarget!: HTMLInputElement; triggerEmailField() { - const checkedTarget = this.useFranceConnectEmailTargets.find( - (target) => target.checked - ); - - const inputElement = this.emailFieldTarget.querySelector( - 'input[type="email"]' - ) as HTMLInputElement; + if (this.useFCEmail()) { + this.emailFieldTarget.classList.add('hidden'); + this.emailFieldTarget.setAttribute('aria-hidden', 'true'); - if (checkedTarget && checkedTarget.value === 'false') { + this.emailInputTarget.removeAttribute('required'); + this.emailInputTarget.value = ''; + } else { this.emailFieldTarget.classList.remove('hidden'); this.emailFieldTarget.setAttribute('aria-hidden', 'false'); - inputElement.setAttribute('required', ''); + + this.emailInputTarget.setAttribute('required', ''); + } + } + + triggerSubmitDisabled() { + if (this.useFCEmail() || this.isEmailInputFilled()) { + this.submitTarget.disabled = false; } else { - this.emailFieldTarget.classList.add('hidden'); - this.emailFieldTarget.setAttribute('aria-hidden', 'true'); - inputElement.removeAttribute('required'); - inputElement.value = ''; + this.submitTarget.disabled = true; } } + + useFCEmail() { + return this.useFranceConnectEmailTargets.find( + (target) => target.checked + )?.value === 'true' || false; + } + + isEmailInputFilled() { + return this.emailInputTarget.value.length > 0; + } } diff --git a/app/views/france_connect/particulier/choose_email.html.haml b/app/views/france_connect/particulier/choose_email.html.haml index ab7bca16fa2..da8ae565fa6 100644 --- a/app/views/france_connect/particulier/choose_email.html.haml +++ b/app/views/france_connect/particulier/choose_email.html.haml @@ -23,7 +23,8 @@ id: 'use_france_connect_email_yes', class: 'fr-radio', required: true, - data: { action: "email-france-connect#triggerEmailField", email_france_connect_target: "useFranceConnectEmail" } + data: { action: "email-france-connect#triggerEmailField email-france-connect#triggerSubmitDisabled", + email_france_connect_target: "useFranceConnectEmail" } %label.fr-label.fr-text--wrap{ for: 'use_france_connect_email_yes' } = t('.keep_fc_email_html', email: h(@fci.email_france_connect)) @@ -33,14 +34,24 @@ id: 'use_france_connect_email_no', class: 'fr-radio', required: true, - data: { action: "email-france-connect#triggerEmailField", email_france_connect_target: "useFranceConnectEmail" } + data: { action: "email-france-connect#triggerEmailField email-france-connect#triggerSubmitDisabled", email_france_connect_target: "useFranceConnectEmail" } %label.fr-label.fr-text--wrap{ for: 'use_france_connect_email_no' } = t('.use_another_email') - .fr-fieldset__element.fr-fieldset__element--inline.hidden{ aria: { hidden: true }, data: { email_france_connect_target: "emailField", controller: 'email-input', email_input_url_value: show_email_suggestions_path } } + .fr-fieldset__element.fr-fieldset__element--inline.hidden{ + aria: { hidden: true }, + data: { + email_france_connect_target: "emailField", + controller: 'email-input', + email_input_url_value: show_email_suggestions_path + } + } + = f.label :email, t('.alternative_email'), class: "fr-label" %span.fr-hint-text.mb-1= t('activerecord.attributes.user.hints.email') - = f.email_field :email, class: "fr-input" + = f.email_field :email, + data: { action: "email-france-connect#triggerSubmitDisabled", email_france_connect_target: "emailInput" }, + class: "fr-input" .suspect-email.hidden{ data: { "email-input-target": 'ariaRegion'}, aria: { live: 'off' } } = render Dsfr::AlertComponent.new(title: t('utils.email_suggest.wanna_say'), state: :info, heading_level: :div) do |c| @@ -52,4 +63,7 @@ = button_tag type: 'button', class: 'fr-btn fr-btn--sm', data: { action: 'click->email-input#discard'} do = t('utils.no') %div - = f.submit t('.confirm'), class: 'fr-btn' + = f.submit t('.confirm'), + class: 'fr-btn', + data: { email_france_connect_target: "submit" }, + disabled: true From 2a2517173803a48cef3a88478eadf9f1c826e10d Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Fri, 22 Nov 2024 17:17:11 +0100 Subject: [PATCH 8/9] Fix: allow custom email (!), require a mail confirmation previous code was wrong, it was impossible to choose another email than the FC one --- .../email_france_connect_controller.ts | 28 ++++++++++++++++--- .../particulier/choose_email.html.haml | 5 +++- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/app/javascript/controllers/email_france_connect_controller.ts b/app/javascript/controllers/email_france_connect_controller.ts index 7fe74cee560..a5675a56e51 100644 --- a/app/javascript/controllers/email_france_connect_controller.ts +++ b/app/javascript/controllers/email_france_connect_controller.ts @@ -1,12 +1,27 @@ import { ApplicationController } from './application_controller'; export class EmailFranceConnectController extends ApplicationController { - static targets = ['useFranceConnectEmail', 'emailField', 'submit', 'emailInput']; + static targets = [ + 'useFranceConnectEmail', + 'emailField', + 'submit', + 'emailInput', + 'form' + ]; emailFieldTarget!: HTMLElement; useFranceConnectEmailTargets!: HTMLInputElement[]; submitTarget!: HTMLButtonElement; emailInputTarget!: HTMLInputElement; + formTarget!: HTMLFormElement; + + fcEmailPathValue!: string; + customEmailPathValue!: string; + + static values = { + fcEmailPath: String, + customEmailPath: String + }; triggerEmailField() { if (this.useFCEmail()) { @@ -15,11 +30,15 @@ export class EmailFranceConnectController extends ApplicationController { this.emailInputTarget.removeAttribute('required'); this.emailInputTarget.value = ''; + + this.formTarget.action = this.fcEmailPathValue; } else { this.emailFieldTarget.classList.remove('hidden'); this.emailFieldTarget.setAttribute('aria-hidden', 'false'); this.emailInputTarget.setAttribute('required', ''); + + this.formTarget.action = this.customEmailPathValue; } } @@ -32,9 +51,10 @@ export class EmailFranceConnectController extends ApplicationController { } useFCEmail() { - return this.useFranceConnectEmailTargets.find( - (target) => target.checked - )?.value === 'true' || false; + return ( + this.useFranceConnectEmailTargets.find((target) => target.checked) + ?.value === 'true' || false + ); } isEmailInputFilled() { diff --git a/app/views/france_connect/particulier/choose_email.html.haml b/app/views/france_connect/particulier/choose_email.html.haml index da8ae565fa6..ce1118a7adc 100644 --- a/app/views/france_connect/particulier/choose_email.html.haml +++ b/app/views/france_connect/particulier/choose_email.html.haml @@ -11,7 +11,10 @@ %fieldset.fr-fieldset = form_with url: france_connect_particulier_merge_using_fc_email_path, method: :post, - data: { controller: 'email-france-connect' } do |f| + data: { controller: 'email-france-connect', + email_france_connect_fc_email_path_value: france_connect_particulier_merge_using_fc_email_path, + email_france_connect_custom_email_path_value: france_connect_particulier_send_email_merge_request_path, + email_france_connect_target: "form" } do |f| = hidden_field_tag :merge_token, @fci.merge_token From 7b02aeb02e9e3b7d7395e7cb0cc342e57840f6a7 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Tue, 26 Nov 2024 10:18:55 +0100 Subject: [PATCH 9/9] fix spec --- .../france_connect_particulier_spec.rb | 47 +++++++++++++------ spec/system/users/dossier_prefill_get_spec.rb | 10 ++-- .../system/users/dossier_prefill_post_spec.rb | 8 ++-- 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/spec/system/france_connect/france_connect_particulier_spec.rb b/spec/system/france_connect/france_connect_particulier_spec.rb index e6fdb5786cf..10ba50dcb79 100644 --- a/spec/system/france_connect/france_connect_particulier_spec.rb +++ b/spec/system/france_connect/france_connect_particulier_spec.rb @@ -7,7 +7,7 @@ let(:birthdate) { '20150821' } let(:gender) { 'M' } let(:birthplace) { '1234' } - let(:email) { 'plop@plop.com' } + let(:fc_email) { 'plop@plop.com' } let(:france_connect_particulier_id) { 'blabla' } let(:user_info) do @@ -18,7 +18,7 @@ birthdate: birthdate, birthplace: birthplace, gender: gender, - email_france_connect: email + email_france_connect: fc_email } end @@ -40,32 +40,49 @@ let(:france_connect_information) { build(:france_connect_information, user_info) } context 'and no user has the same email' do - before { page.find('.fr-connect').click } + before do + page.find('.fr-connect').click + end - scenario 'he is redirected to user dossiers page' do + scenario 'he is redirected to user dossiers page', js: true do expect(page).to have_content("Choisissez votre email de contact pour finaliser votre connexion") - find("#use_france_connect_email_no").click - fill_in("email", with: "exemple@email.com") - page.find("input[type='submit'][name='commit'][value='Confirmer']").click - expect(page).to have_content("Confirmez votre email") - click_on 'Continuer' - expect(User.find_by(email: email)).not_to be nil + + find('label', text: "Oui, utiliser #{fc_email} comme email de contact").click + + click_on 'Valider' + expect(User.find_by(email: fc_email).email_verified_at).to be_present end - scenario 'he can choose not to use FranceConnect email and input an alternative email' do + scenario 'he can choose not to use FranceConnect email and input an alternative email', js: true do + alternative_email = 'alternative@example.com' + expect(page).to have_content("Choisissez votre email de contact pour finaliser votre connexion") + find('label', text: 'utiliser une autre adresse').click expect(page).to have_selector("input[name='email']", visible: true, wait: 10) - fill_in 'email', with: 'alternative@example.com' - click_on 'Confirmer' + fill_in 'email', with: alternative_email + click_on 'Valider' + + expect(page).to have_content('Nous venons de vous envoyer le mail de confirmation') + expect(User.find_by(email: alternative_email)).to be_nil + + perform_enqueued_jobs + + confirmation_email = open_email(alternative_email) + link = confirmation_email.body.match(/href="[^"]*(\/france_connect\/particulier\/merge_using_email_link.*?)"/)[1] + + visit link + + expect(page).to have_content('Les comptes FranceConnect et demarches-simplifiees.fr sont à présent fusionnés') + expect(page).to have_content(alternative_email) - expect(page).to have_content("Confirmez votre email") + expect(User.find_by(email: alternative_email).email_verified_at).to be_present end end context 'and an user exists with the same email' do - let!(:user) { create(:user, email: email, password: SECURE_PASSWORD) } + let!(:user) { create(:user, email: fc_email, password: SECURE_PASSWORD) } before do page.find('.fr-connect').click diff --git a/spec/system/users/dossier_prefill_get_spec.rb b/spec/system/users/dossier_prefill_get_spec.rb index fe1e33e4c21..4f6ec6b102c 100644 --- a/spec/system/users/dossier_prefill_get_spec.rb +++ b/spec/system/users/dossier_prefill_get_spec.rb @@ -182,12 +182,10 @@ page.find('.fr-connect').click expect(page).to have_content("Choisissez votre email de contact pour finaliser votre connexion") - expect(page).to have_selector("#use_france_connect_email_no", visible: false, wait: 10) - page.execute_script('document.getElementById("use_france_connect_email_no").click()') - fill_in("email", with: "exemple@email.com") - page.find("input[type='submit'][name='commit'][value='Confirmer']").click - expect(page).to have_content("Confirmez votre email") - click_on 'Continuer' + + find('label', text: /Oui, utiliser .* comme email de contact/).click + + click_on 'Valider' expect(page).to have_content('Vous avez un dossier prérempli') find('.fr-btn.fr-mb-2w', text: 'Poursuivre mon dossier prérempli', wait: 10).click end diff --git a/spec/system/users/dossier_prefill_post_spec.rb b/spec/system/users/dossier_prefill_post_spec.rb index 0c8c065824e..39cfb4c7b3a 100644 --- a/spec/system/users/dossier_prefill_post_spec.rb +++ b/spec/system/users/dossier_prefill_post_spec.rb @@ -135,12 +135,10 @@ page.find('.fr-connect').click expect(page).to have_content("Choisissez votre email de contact pour finaliser votre connexion") - expect(page).to have_selector("#use_france_connect_email_yes", visible: false, wait: 10) - page.execute_script('document.getElementById("use_france_connect_email_yes").click()') - click_on 'Confirmer' - expect(page).to have_content("Confirmez votre email") - click_on 'Continuer' + find('label', text: /Oui, utiliser .* comme email de contact/).click + + click_on 'Valider' expect(page).to have_content('Vous avez un dossier prérempli') find('.fr-btn.fr-mb-2w', text: 'Poursuivre mon dossier prérempli', wait: 10).click end