From 009e426c31354b3f097754dfa7060e6c0384831a Mon Sep 17 00:00:00 2001 From: Colin Darie Date: Tue, 10 Dec 2024 19:13:01 +0100 Subject: [PATCH] fix(dossier): show ineligibilite message on update --- .../invalid_ineligibilite_rules_component.rb | 18 ++++++++++--- ...id_ineligibilite_rules_component.html.haml | 12 ++++++--- app/controllers/users/dossiers_controller.rb | 4 +-- .../ineligibilite_rules_match_controller.ts | 19 -------------- app/models/dossier.rb | 12 --------- .../users/dossiers/update.turbo_stream.haml | 7 ++--- .../users/dossiers_controller_spec.rb | 26 +++++++++++++------ .../users/dossier_ineligibilite_spec.rb | 19 +++++++------- .../shared/dossiers/_edit.html.haml_spec.rb | 1 + 9 files changed, 55 insertions(+), 63 deletions(-) delete mode 100644 app/javascript/controllers/ineligibilite_rules_match_controller.ts diff --git a/app/components/dossiers/invalid_ineligibilite_rules_component.rb b/app/components/dossiers/invalid_ineligibilite_rules_component.rb index 78047042fd6..3de971b68ef 100644 --- a/app/components/dossiers/invalid_ineligibilite_rules_component.rb +++ b/app/components/dossiers/invalid_ineligibilite_rules_component.rb @@ -1,18 +1,28 @@ # frozen_string_literal: true class Dossiers::InvalidIneligibiliteRulesComponent < ApplicationComponent - delegate :can_passer_en_construction?, to: :@dossier + delegate :can_passer_en_construction?, to: :dossier - def initialize(dossier:) + def initialize(dossier:, wrapped: true) @dossier = dossier @revision = dossier.revision + + @opened = !dossier.can_passer_en_construction? + @wrapped = wrapped end + private + + attr_reader :dossier + def render? - !can_passer_en_construction? + dossier.revision.ineligibilite_enabled? end def error_message - @dossier.revision.ineligibilite_message + dossier.revision.ineligibilite_message end + + def opened? = @opened + def wrapped? = @wrapped end diff --git a/app/components/dossiers/invalid_ineligibilite_rules_component/invalid_ineligibilite_rules_component.html.haml b/app/components/dossiers/invalid_ineligibilite_rules_component/invalid_ineligibilite_rules_component.html.haml index dd39925cd6d..061b44c06b6 100644 --- a/app/components/dossiers/invalid_ineligibilite_rules_component/invalid_ineligibilite_rules_component.html.haml +++ b/app/components/dossiers/invalid_ineligibilite_rules_component/invalid_ineligibilite_rules_component.html.haml @@ -1,8 +1,8 @@ -%div{ id: dom_id(@dossier, :ineligibilite_rules_broken), data: { controller: 'ineligibilite-rules-match', turbo_force: :server } } - %button.fr-sr-only{ aria: {controls: 'modal-eligibilite-rules-dialog' }, data: {'fr-opened': "false" } } +- modal_content = capture do + %button.fr-sr-only{ aria: { controls: 'modal-eligibilite-rules-dialog' }, data: { 'fr-opened': opened?.to_s } } show modal - %dialog.fr-modal{ "aria-labelledby" => "fr-modal-title-modal-1", role: "dialog", id: 'modal-eligibilite-rules-dialog', data: { 'ineligibilite-rules-match-target' => 'dialog' } } + %dialog.fr-modal{ "aria-labelledby" => "fr-modal-title-modal-1", role: "dialog", id: 'modal-eligibilite-rules-dialog', data: { 'turbo-permanent' => true } } .fr-container.fr-container--fluid.fr-container-md .fr-grid-row.fr-grid-row--center .fr-col-12.fr-col-md-8.fr-col-lg-6 @@ -14,3 +14,9 @@ %span.fr-icon-arrow-right-line.fr-icon--lg> = t('.modal.title') %p= error_message + +- if wrapped? + %div{ id: dom_id(@dossier, :ineligibilite_rules_broken) } + = modal_content +- else + = modal_content diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index 626cb0692cd..00160b98458 100644 --- a/app/controllers/users/dossiers_controller.rb +++ b/app/controllers/users/dossiers_controller.rb @@ -280,9 +280,7 @@ def submit_en_construction def update @dossier = dossier.en_construction? ? dossier.find_editing_fork(dossier.user) : dossier @dossier = dossier_with_champs(pj_template: false) - @can_passer_en_construction_was, @can_passer_en_construction_is = dossier.track_can_passer_en_construction do - update_dossier_and_compute_errors - end + update_dossier_and_compute_errors respond_to do |format| format.turbo_stream do diff --git a/app/javascript/controllers/ineligibilite_rules_match_controller.ts b/app/javascript/controllers/ineligibilite_rules_match_controller.ts deleted file mode 100644 index 5b47d79b505..00000000000 --- a/app/javascript/controllers/ineligibilite_rules_match_controller.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { ApplicationController } from './application_controller'; -declare interface modal { - disclose: () => void; -} -declare interface dsfr { - modal: modal; -} -declare const window: Window & - typeof globalThis & { dsfr: (elem: HTMLElement) => dsfr }; - -export class InvalidIneligibiliteRulesController extends ApplicationController { - static targets = ['dialog']; - - declare dialogTarget: HTMLElement; - - connect() { - setTimeout(() => window.dsfr(this.dialogTarget).modal.disclose(), 100); - } -} diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 19770296337..cad644dfdc7 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -1025,18 +1025,6 @@ def termine_and_accuse_lecture? procedure.accuse_lecture? && termine? end - def track_can_passer_en_construction - if !revision.ineligibilite_enabled - yield - [true, true] # without eligibilite rules, we never reach dossier.champs.visible?, don't cache anything - else - from = can_passer_en_construction? # with eligibilite rules, self.champ[x].visible is cached by passing thru conditions checks - yield - champs.map(&:reset_visible) # we must reset self.champs[x].visible?, because an update occurred and we should re-evaluate champs[x] visibility - [from, can_passer_en_construction?] - end - end - private def build_default_champs diff --git a/app/views/users/dossiers/update.turbo_stream.haml b/app/views/users/dossiers/update.turbo_stream.haml index 2cd14be476c..0b7c1347412 100644 --- a/app/views/users/dossiers/update.turbo_stream.haml +++ b/app/views/users/dossiers/update.turbo_stream.haml @@ -1,10 +1,7 @@ = render partial: 'shared/dossiers/update_champs', locals: { to_show: @to_show, to_hide: @to_hide, to_update: @to_update, dossier: @dossier } -- if !params.key?(:validate) - - if @can_passer_en_construction_was && !@can_passer_en_construction_is - = turbo_stream.append('contenu', render(Dossiers::InvalidIneligibiliteRulesComponent.new(dossier: @dossier))) - - else @ineligibilite_rules_is_computable - = turbo_stream.remove(dom_id(@dossier, :ineligibilite_rules_broken)) +- if params[:validate].present? && @dossier.revision.ineligibilite_enabled? + = turbo_stream.update dom_id(@dossier, :ineligibilite_rules_broken), render(Dossiers::InvalidIneligibiliteRulesComponent.new(dossier: @dossier, wrapped: false)) - if @update_contact_information = turbo_stream.update "contact_information", partial: 'shared/dossiers/update_contact_information', locals: { dossier: @dossier, procedure: @dossier.procedure } diff --git a/spec/controllers/users/dossiers_controller_spec.rb b/spec/controllers/users/dossiers_controller_spec.rb index 11ce0e20fe5..62970f9f55f 100644 --- a/spec/controllers/users/dossiers_controller_spec.rb +++ b/spec/controllers/users/dossiers_controller_spec.rb @@ -775,9 +775,11 @@ let(:types_de_champ_public) { [{ type: :text }, { type: :integer_number }] } let(:text_champ) { dossier.project_champs_public.first } let(:number_champ) { dossier.project_champs_public.last } + let(:validate) { "true" } let(:submit_payload) do { id: dossier.id, + validate:, dossier: { groupe_instructeur_id: dossier.groupe_instructeur_id, champs_public_attributes: { @@ -805,28 +807,36 @@ end render_views - context 'when it switches from true to false' do + context 'when it becomes invalid' do let(:value) { must_be_greater_than + 1 } it 'raises popup' do subject dossier.reload expect(dossier.can_passer_en_construction?).to be_falsey - expect(assigns(:can_passer_en_construction_was)).to eq(true) - expect(assigns(:can_passer_en_construction_is)).to eq(false) - expect(response.body).to match(ActionView::RecordIdentifier.dom_id(dossier, :ineligibilite_rules_broken)) + expect(response.body).to match(/aria-controls='modal-eligibilite-rules-dialog'[^>]*data-fr-opened='true'/) end end - context 'when it stays true' do + context 'when it says valid' do let(:value) { must_be_greater_than - 1 } it 'does nothing' do subject dossier.reload expect(dossier.can_passer_en_construction?).to be_truthy - expect(assigns(:can_passer_en_construction_was)).to eq(true) - expect(assigns(:can_passer_en_construction_is)).to eq(true) - expect(response.body).not_to have_selector("##{ActionView::RecordIdentifier.dom_id(dossier, :ineligibilite_rules_broken)}") + expect(response.body).to match(/aria-controls='modal-eligibilite-rules-dialog'[^>]*data-fr-opened='false'/) + end + end + + context 'when not validating' do + let(:validate) { nil } + let(:value) { must_be_greater_than + 1 } + + it 'does not render invalid ineligible modal' do + subject + dossier.reload + expect(dossier.can_passer_en_construction?).to be_falsey + expect(response.body).not_to include("aria-controls='modal-eligibilite-rules-dialog'") end end end diff --git a/spec/system/users/dossier_ineligibilite_spec.rb b/spec/system/users/dossier_ineligibilite_spec.rb index ef52ae42c4c..fd7a32c1b34 100644 --- a/spec/system/users/dossier_ineligibilite_spec.rb +++ b/spec/system/users/dossier_ineligibilite_spec.rb @@ -28,21 +28,21 @@ visit brouillon_dossier_path(dossier) # no error while dossier is empty expect(page).to have_selector(:button, text: "Déposer le dossier", disabled: false) - expect(page).not_to have_content("Vous ne pouvez pas déposer votre dossier") + expect(page).to have_selector("#modal-eligibilite-rules-dialog", visible: false) - # does raise error when dossier is filled with condition that does not match + # does nothing when dossier is filled with condition that does not match within "#champ-1" do find("label", text: "Non").click end expect(page).to have_selector(:button, text: "Déposer le dossier", disabled: false) - expect(page).not_to have_content("Vous ne pouvez pas déposer votre dossier") + expect(page).to have_selector("#modal-eligibilite-rules-dialog", visible: false) - # raise error when dossier is filled with condition that matches + # open modal when dossier is filled with condition that matches within "#champ-1" do find("label", text: "Oui").click end expect(page).to have_selector(:button, text: "Déposer le dossier", disabled: true) - expect(page).to have_content("Vous ne pouvez pas déposer votre dossier") + expect(page).to have_selector("#modal-eligibilite-rules-dialog", visible: true) # reload page and see error visit brouillon_dossier_path(dossier) @@ -51,6 +51,7 @@ # modal is closable, and we can change our dossier response to be eligible expect(page).to have_selector("#modal-eligibilite-rules-dialog", visible: true) + expect(page).to have_text("Vous ne pouvez pas déposer votre dossier") within("#modal-eligibilite-rules-dialog") { click_on "Fermer" } expect(page).to have_selector("#modal-eligibilite-rules-dialog", visible: false) @@ -78,7 +79,7 @@ visit brouillon_dossier_path(dossier) # no error while dossier is empty expect(page).to have_selector(:button, text: "Déposer le dossier", disabled: false) - expect(page).not_to have_content("Vous ne pouvez pas déposer votre dossier") + expect(page).to have_selector("#modal-eligibilite-rules-dialog", visible: false) # first condition matches (so ineligible), cannot submit dossier and error message is clear within "#champ-#{first_tdc.stable_id}" do @@ -148,14 +149,14 @@ visit brouillon_dossier_path(dossier) # no error while dossier is empty expect(page).to have_selector(:button, text: "Déposer le dossier", disabled: false) - expect(page).not_to have_content("Vous ne pouvez pas déposer votre dossier") + expect(page).to have_selector("#modal-eligibilite-rules-dialog", visible: false) # only one condition is matches, can submit dossier within "#champ-#{first_tdc.stable_id}" do find("label", text: "Oui").click end expect(page).to have_selector(:button, text: "Déposer le dossier", disabled: false) - expect(page).not_to have_content("Vous ne pouvez pas déposer votre dossier") + expect(page).to have_selector("#modal-eligibilite-rules-dialog", visible: false) # Now test dossier modification click_on "Déposer le dossier" @@ -196,7 +197,7 @@ scenario 'ineligibilite rules without validation on champ ensure to re-process cached champs.visible' do visit brouillon_dossier_path(dossier) expect(page).to have_selector(:button, text: "Déposer le dossier", disabled: false) - expect(page).not_to have_content("Vous ne pouvez pas déposer votre dossier") + expect(page).to have_selector("#modal-eligibilite-rules-dialog", visible: false) within "#champ-1" do find("label", text: "Non").click diff --git a/spec/views/shared/dossiers/_edit.html.haml_spec.rb b/spec/views/shared/dossiers/_edit.html.haml_spec.rb index 4271d129b28..787e9cf0734 100644 --- a/spec/views/shared/dossiers/_edit.html.haml_spec.rb +++ b/spec/views/shared/dossiers/_edit.html.haml_spec.rb @@ -160,6 +160,7 @@ before do allow(dossier).to receive(:can_passer_en_construction?).and_return(false) + allow(dossier.revision).to receive(:ineligibilite_enabled?).and_return(true) end it 'renders broken transitions rules dialog' do