From fd4a9a6a2f06ccf9abd414d44a99ef392bf9240a Mon Sep 17 00:00:00 2001 From: Colin Darie Date: Tue, 18 Apr 2023 18:06:24 +0200 Subject: [PATCH] refactor(instruction): menu repasser en construction + demander une correction --- app/assets/stylesheets/motivation.scss | 1 - .../en_construction_menu_component.rb | 24 +++++++ .../en_construction_menu_component.en.yml | 4 ++ .../en_construction_menu_component.fr.yml | 4 ++ .../en_construction_menu_component.html.haml | 31 +++++++++ .../instruction_menu_component.rb | 11 +-- .../instruction_menu_component.html.haml | 68 +++++++------------ .../dossiers/_header_actions.html.haml | 4 +- .../_instruction_button_motivation.html.haml | 2 +- .../procedures/_dossier_actions.html.haml | 6 +- .../instructeurs/procedures/show.html.haml | 3 +- app/views/recherche/index.html.haml | 3 +- .../en_contruction_menu_component_spec.rb | 53 +++++++++++++++ .../instruction_menu_component_spec.rb | 8 +-- .../dossiers/show.html.haml_spec.rb | 12 ++-- 15 files changed, 164 insertions(+), 70 deletions(-) create mode 100644 app/components/instructeurs/en_construction_menu_component.rb create mode 100644 app/components/instructeurs/en_construction_menu_component/en_construction_menu_component.en.yml create mode 100644 app/components/instructeurs/en_construction_menu_component/en_construction_menu_component.fr.yml create mode 100644 app/components/instructeurs/en_construction_menu_component/en_construction_menu_component.html.haml create mode 100644 spec/components/instructeurs/en_contruction_menu_component_spec.rb diff --git a/app/assets/stylesheets/motivation.scss b/app/assets/stylesheets/motivation.scss index 32e076dff..fff6c80f0 100644 --- a/app/assets/stylesheets/motivation.scss +++ b/app/assets/stylesheets/motivation.scss @@ -2,7 +2,6 @@ @import "constants"; .motivation { - padding: $default-padding; color: $black; width: 450px; diff --git a/app/components/instructeurs/en_construction_menu_component.rb b/app/components/instructeurs/en_construction_menu_component.rb new file mode 100644 index 000000000..a2c930f80 --- /dev/null +++ b/app/components/instructeurs/en_construction_menu_component.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +class Instructeurs::EnConstructionMenuComponent < ApplicationComponent + attr_reader :dossier + + def initialize(dossier:) + @dossier = dossier + end + + def render? + return true if dossier.may_repasser_en_construction? + return true if dossier.may_flag_as_pending_correction? + + false + end + + def menu_label + if dossier.en_construction? + t('.request_correction') + else + t(".revert_en_construction") + end + end +end diff --git a/app/components/instructeurs/en_construction_menu_component/en_construction_menu_component.en.yml b/app/components/instructeurs/en_construction_menu_component/en_construction_menu_component.en.yml new file mode 100644 index 000000000..d9d6426bb --- /dev/null +++ b/app/components/instructeurs/en_construction_menu_component/en_construction_menu_component.en.yml @@ -0,0 +1,4 @@ +--- +en: + revert_en_construction: Revert to in progress + request_correction: Request a correction diff --git a/app/components/instructeurs/en_construction_menu_component/en_construction_menu_component.fr.yml b/app/components/instructeurs/en_construction_menu_component/en_construction_menu_component.fr.yml new file mode 100644 index 000000000..4430f7654 --- /dev/null +++ b/app/components/instructeurs/en_construction_menu_component/en_construction_menu_component.fr.yml @@ -0,0 +1,4 @@ +--- +fr: + revert_en_construction: Repasser en construction + request_correction: Demander une correction diff --git a/app/components/instructeurs/en_construction_menu_component/en_construction_menu_component.html.haml b/app/components/instructeurs/en_construction_menu_component/en_construction_menu_component.html.haml new file mode 100644 index 000000000..67c90adcb --- /dev/null +++ b/app/components/instructeurs/en_construction_menu_component/en_construction_menu_component.html.haml @@ -0,0 +1,31 @@ += render Dropdown::MenuComponent.new(wrapper: :div, button_options: { class: "fr-btn--secondary" }, wrapper_options: { data: {'turbo-force': true} }, role: :region) do |menu| + - menu.with_button_inner_html do + = menu_label + + - if dossier.may_repasser_en_construction? + = menu.with_item do + = link_to(repasser_en_construction_instructeur_dossier_path(dossier.procedure.id, dossier.id), method: :post, role: 'menuitem') do + %span.fr-icon.fr-icon-draft-line.fr-text-default--info.fr-mt-1v{ "aria-hidden": "true" } + .dropdown-description + %h4= t('.revert_en_construction') + L’usager sera notifié qu’il peut modifier son dossier + + - menu.with_item do + = link_to('#', onclick: "DS.showMotivation(event, 'pending_correction');", role: 'menuitem') do + %span.fr-icon.fr-icon-error-warning-line.fr-text-default--info.fr-mt-1v{ "aria-hidden": "true" } + + .dropdown-description + %h4= t('.request_correction') + L’usager sera notifié que des modifications sont attendues + + - menu.with_item(class: "inactive form-inside fr-pt-1v") do + = render partial: 'instructeurs/dossiers/instruction_button_motivation', locals: { dossier:, + visible: true, + form_path: pending_correction_instructeur_dossier_path(dossier.procedure, dossier), + placeholder: 'Expliquez au demandeur quelle(s) correction(s) sont attendues', + popup_class: 'pending_correction', + button_justificatif_label: "Ajouter une pièce jointe (facultatif)", + process_button: dossier.en_construction? ? 'Valider' : 'Valider et repasser en construction', + process_action: nil, + title: 'Marquer en attente de corrections', + confirm: 'Envoyer la demande de corrections ?'} diff --git a/app/components/instructeurs/instruction_menu_component.rb b/app/components/instructeurs/instruction_menu_component.rb index e704fd7fc..01dc27f85 100644 --- a/app/components/instructeurs/instruction_menu_component.rb +++ b/app/components/instructeurs/instruction_menu_component.rb @@ -8,17 +8,10 @@ class Instructeurs::InstructionMenuComponent < ApplicationComponent end def render? - return true if dossier.en_instruction? - return true if dossier.en_construction? && dossier.may_flag_as_pending_correction? - - false + dossier.en_instruction? end def menu_label - if dossier.en_instruction? - t(".instruct") - else - "Demander une correction" - end + t(".instruct") end end diff --git a/app/components/instructeurs/instruction_menu_component/instruction_menu_component.html.haml b/app/components/instructeurs/instruction_menu_component/instruction_menu_component.html.haml index 7f0bb8b9d..51a08855a 100644 --- a/app/components/instructeurs/instruction_menu_component/instruction_menu_component.html.haml +++ b/app/components/instructeurs/instruction_menu_component/instruction_menu_component.html.haml @@ -2,53 +2,33 @@ - menu.with_button_inner_html do = menu_label - - if dossier.en_instruction? - - menu.with_item do - = link_to('#', onclick: "DS.showMotivation(event, 'accept');", role: 'menuitem') do - %span.icon.accept - .dropdown-description - %h4 Accepter - L’usager sera informé que son dossier a été accepté + - menu.with_item do + = link_to('#', onclick: "DS.showMotivation(event, 'accept');", role: 'menuitem') do + %span.icon.accept + .dropdown-description + %h4 Accepter + L’usager sera informé que son dossier a été accepté - - menu.with_item(class: "hidden inactive form-inside") do - = render partial: 'instructeurs/dossiers/instruction_button_motivation', locals: { dossier: dossier, placeholder: 'Expliquez au demandeur pourquoi ce dossier est accepté (facultatif)', popup_class: 'accept', process_action: 'accepter', title: 'Accepter', confirm: "Confirmez-vous l'acceptation ce dossier ?" } + - menu.with_item(class: "hidden inactive form-inside fr-pt-1v") do + = render partial: 'instructeurs/dossiers/instruction_button_motivation', locals: { dossier: dossier, placeholder: 'Expliquez au demandeur pourquoi ce dossier est accepté (facultatif)', popup_class: 'accept', process_action: 'accepter', title: 'Accepter', confirm: "Confirmez-vous l'acceptation ce dossier ?" } - - menu.with_item do - = link_to('#', onclick: "DS.showMotivation(event, 'without-continuation');", role: 'menuitem') do - %span.icon.without-continuation - .dropdown-description - %h4 Classer sans suite - L’usager sera informé que son dossier a été classé sans suite + - menu.with_item do + = link_to('#', onclick: "DS.showMotivation(event, 'without-continuation');", role: 'menuitem') do + %span.icon.without-continuation + .dropdown-description + %h4 Classer sans suite + L’usager sera informé que son dossier a été classé sans suite - - menu.with_item(class: "hidden inactive form-inside") do - = render partial: 'instructeurs/dossiers/instruction_button_motivation', locals: { dossier: dossier, placeholder: 'Expliquez au demandeur pourquoi ce dossier est classé sans suite (obligatoire)', popup_class: 'without-continuation', process_action: 'classer_sans_suite', title: 'Classer sans suite', confirm: 'Confirmez-vous le classement sans suite de ce dossier ?' } + - menu.with_item(class: "hidden inactive form-inside fr-pt-1v") do + = render partial: 'instructeurs/dossiers/instruction_button_motivation', locals: { dossier: dossier, placeholder: 'Expliquez au demandeur pourquoi ce dossier est classé sans suite (obligatoire)', popup_class: 'without-continuation', process_action: 'classer_sans_suite', title: 'Classer sans suite', confirm: 'Confirmez-vous le classement sans suite de ce dossier ?' } - - menu.with_item do - = link_to('#', onclick: "DS.showMotivation(event, 'refuse');", role: 'menuitem') do - %span.icon.refuse - .dropdown-description - %h4 Refuser - L’usager sera informé que son dossier a été refusé + - menu.with_item do + = link_to('#', onclick: "DS.showMotivation(event, 'refuse');", role: 'menuitem') do + %span.icon.refuse + .dropdown-description + %h4 Refuser + L’usager sera informé que son dossier a été refusé - - menu.with_item(class: "hidden inactive form-inside") do - = render partial: 'instructeurs/dossiers/instruction_button_motivation', locals: { dossier: dossier, placeholder: 'Expliquez au demandeur pourquoi ce dossier est refusé (obligatoire)', popup_class: 'refuse', process_action: 'refuser', title: 'Refuser', confirm: 'Confirmez-vous le refus de ce dossier ?' } + - menu.with_item(class: "hidden inactive form-inside fr-pt-1v") do + = render partial: 'instructeurs/dossiers/instruction_button_motivation', locals: { dossier: dossier, placeholder: 'Expliquez au demandeur pourquoi ce dossier est refusé (obligatoire)', popup_class: 'refuse', process_action: 'refuser', title: 'Refuser', confirm: 'Confirmez-vous le refus de ce dossier ?' } - - if dossier.may_flag_as_pending_correction? - - menu.with_item do - = link_to('#', onclick: "DS.showMotivation(event, 'pending_correction');", role: 'menuitem') do - %span.fr-icon.fr-icon-error-warning-line.fr-text-default--info{ "aria-hidden": "true" } - .dropdown-description - %h4 Demander une correction - L’usager sera informé que des modifications sont attendues - - - menu.with_item(class: class_names("inactive form-inside": true, hidden: dossier.en_instruction?)) do - = render partial: 'instructeurs/dossiers/instruction_button_motivation', locals: { dossier: dossier, - visible: !dossier.en_instruction?, - form_path: pending_correction_instructeur_dossier_path(dossier.procedure, dossier), - placeholder: 'Expliquez au demandeur quelle(s) correction(s) sont attendues', - popup_class: 'pending_correction', - button_justificatif_label: "Ajouter une pièce jointe (facultatif)", - process_button: dossier.en_construction? ? 'Valider' : 'Valider et repasser en construction', - process_action: nil, - title: 'Marquer en attente de corrections', - confirm: 'Envoyer la demande de corrections ?'} diff --git a/app/views/instructeurs/dossiers/_header_actions.html.haml b/app/views/instructeurs/dossiers/_header_actions.html.haml index af4275504..d5d28a0b1 100644 --- a/app/views/instructeurs/dossiers/_header_actions.html.haml +++ b/app/views/instructeurs/dossiers/_header_actions.html.haml @@ -2,12 +2,14 @@ = render partial: "instructeurs/procedures/dossier_actions", locals: { procedure_id: dossier.procedure.id, dossier_id: dossier.id, + dossier: dossier, state: dossier.state, archived: dossier.archived, dossier_is_followed: current_instructeur&.follow?(dossier), close_to_expiration: dossier.close_to_expiration?, hidden_by_administration: dossier.hidden_by_administration?, - turbo: true } + turbo: true, + with_menu: true } %li.instruction-button = render Instructeurs::InstructionMenuComponent.new(dossier:) diff --git a/app/views/instructeurs/dossiers/_instruction_button_motivation.html.haml b/app/views/instructeurs/dossiers/_instruction_button_motivation.html.haml index 31bc2c56f..76b4d576e 100644 --- a/app/views/instructeurs/dossiers/_instruction_button_motivation.html.haml +++ b/app/views/instructeurs/dossiers/_instruction_button_motivation.html.haml @@ -1,4 +1,4 @@ -.motivation{ class: class_names(popup_class => true, hidden: !defined?(visible) || !visible) } +.motivation{ class: class_names(popup_class => true, hidden: !defined?(visible) || !visible, "fr-pb-2w fr-px-2w": true) } = form_tag(defined?(form_path) ? form_path : terminer_instructeur_dossier_path(dossier.procedure, dossier), data: { turbo: true, turbo_confirm: confirm }, method: :post, multipart: true) do - if title == 'Accepter' = text_area :dossier, :motivation, class: 'fr-input', placeholder: placeholder, required: false diff --git a/app/views/instructeurs/procedures/_dossier_actions.html.haml b/app/views/instructeurs/procedures/_dossier_actions.html.haml index 91de51c96..d6e65f175 100644 --- a/app/views/instructeurs/procedures/_dossier_actions.html.haml +++ b/app/views/instructeurs/procedures/_dossier_actions.html.haml @@ -29,11 +29,15 @@ = "" - elsif Dossier::EN_CONSTRUCTION_OU_INSTRUCTION.include?(state) + - if with_menu + %li.en-construction-menu{ 'data-turbo': turbo ? 'true' : 'false' } + = render Instructeurs::EnConstructionMenuComponent.new(dossier:) + - if Dossier.states[:en_construction] == state %li{ 'data-turbo': turbo ? 'true' : 'false' } = button_to passer_en_instruction_instructeur_dossier_path(procedure_id, dossier_id), method: :post, class: 'fr-btn fr-btn--secondary fr-icon-edit-line' do Passer en instruction - - elsif Dossier.states[:en_instruction] == state + - elsif Dossier.states[:en_instruction] == state && !with_menu %li{ 'data-turbo': turbo ? 'true' : 'false' } = button_to repasser_en_construction_instructeur_dossier_path(procedure_id, dossier_id), method: :post, class: 'fr-btn fr-btn--secondary fr-icon-draft-line' do Repasser en construction diff --git a/app/views/instructeurs/procedures/show.html.haml b/app/views/instructeurs/procedures/show.html.haml index d5c62c75f..a9b7fc008 100644 --- a/app/views/instructeurs/procedures/show.html.haml +++ b/app/views/instructeurs/procedures/show.html.haml @@ -183,7 +183,8 @@ dossier_is_followed: @followed_dossiers_id.include?(p.dossier_id), close_to_expiration: @statut == 'expirant', hidden_by_administration: @statut == 'supprimes_recemment', - turbo: false } + turbo: false, + with_menu: false } %tfoot %tr %td.force-table-100{ colspan: @procedure_presentation.displayed_fields_for_headers.size + 2 } diff --git a/app/views/recherche/index.html.haml b/app/views/recherche/index.html.haml index d98aeef72..71814bd8c 100644 --- a/app/views/recherche/index.html.haml +++ b/app/views/recherche/index.html.haml @@ -101,7 +101,8 @@ dossier_is_followed: @followed_dossiers_id.include?(p.dossier_id), close_to_expiration: nil, hidden_by_administration: nil, - turbo: false } + turbo: false, + with_menu: false } - else %td diff --git a/spec/components/instructeurs/en_contruction_menu_component_spec.rb b/spec/components/instructeurs/en_contruction_menu_component_spec.rb new file mode 100644 index 000000000..491d722f5 --- /dev/null +++ b/spec/components/instructeurs/en_contruction_menu_component_spec.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +RSpec.describe Instructeurs::EnConstructionMenuComponent, type: :component do + include DossierHelper + + subject do + render_inline(described_class.new(dossier:)) + end + + matcher :have_dropdown_title do |expected_title| + match do |subject| + expect(subject).to have_selector('.dropdown .dropdown-button', text: expected_title) + end + end + + matcher :have_dropdown_items do |options| + match do |subject| + expected_count = options[:count] || 1 + expect(subject).to have_selector('ul.dropdown-items li:not(.hidden)', count: expected_count) + end + end + + matcher :have_dropdown_item do |expected_title, options = {}| + match do |subject| + expected_href = options[:href] + if (expected_href.present?) + expect(subject).to have_selector("ul.dropdown-items li a[href='#{expected_href}']", text: expected_title) + else + expect(subject).to have_selector('ul.dropdown-items li', text: expected_title) + end + end + end + + context 'en_construction' do + let(:dossier) { create(:dossier, :en_construction) } + + it 'renders a dropdown' do + expect(subject).to have_dropdown_title('Demander une correction') + expect(subject).to have_dropdown_items(count: 2) # form is already expanded so we have 2 visible items + end + end + + context 'en_instruction' do + let(:dossier) { create(:dossier, :en_instruction) } + + it 'renders a dropdown' do + expect(subject).to have_dropdown_title('Repasser en construction') + expect(subject).to have_dropdown_item('Demander une correction') + expect(subject).to have_dropdown_item('Repasser en construction') + expect(subject).to have_dropdown_items(count: 3) + end + end +end diff --git a/spec/components/instructeurs/instruction_menu_component_spec.rb b/spec/components/instructeurs/instruction_menu_component_spec.rb index 96c6a64a2..f655c371d 100644 --- a/spec/components/instructeurs/instruction_menu_component_spec.rb +++ b/spec/components/instructeurs/instruction_menu_component_spec.rb @@ -34,9 +34,8 @@ RSpec.describe Instructeurs::InstructionMenuComponent, type: :component do context 'en_construction' do let(:dossier) { create(:dossier, :en_construction) } - it 'renders a dropdown' do - expect(subject).to have_dropdown_title('Demander une correction') - expect(subject).to have_dropdown_items(count: 2) # form is already expanded so we have 2 visible items + it 'does not render' do + expect(subject.to_s).to be_empty end end @@ -45,11 +44,10 @@ RSpec.describe Instructeurs::InstructionMenuComponent, type: :component do it 'renders a dropdown' do expect(subject).to have_dropdown_title('Instruire le dossier') - expect(subject).to have_dropdown_items(count: 4) + expect(subject).to have_dropdown_items(count: 3) expect(subject).to have_dropdown_item('Accepter') expect(subject).to have_dropdown_item('Classer sans suite') expect(subject).to have_dropdown_item('Refuser') - expect(subject).to have_dropdown_item('Demander une correction') end end end diff --git a/spec/views/instructeur/dossiers/show.html.haml_spec.rb b/spec/views/instructeur/dossiers/show.html.haml_spec.rb index 8b38e703b..8745a8b2e 100644 --- a/spec/views/instructeur/dossiers/show.html.haml_spec.rb +++ b/spec/views/instructeur/dossiers/show.html.haml_spec.rb @@ -52,7 +52,7 @@ describe 'instructeurs/dossiers/show', type: :view do end end - context 'en_contruction' do + context 'en_construction' do let(:dossier) { create(:dossier, :en_construction) } it 'displays the correct actions' do within("form[action=\"#{passer_en_instruction_instructeur_dossier_path(dossier.procedure, dossier)}\"]") do @@ -75,15 +75,15 @@ describe 'instructeurs/dossiers/show', type: :view do end it 'displays the correct actions' do - within("form[action=\"#{repasser_en_construction_instructeur_dossier_path(dossier.procedure, dossier)}\"]") do - expect(subject).to have_button('Repasser en construction') - end within("form[action=\"#{unfollow_instructeur_dossier_path(dossier.procedure, dossier)}\"]") do expect(subject).to have_button('Ne plus suivre') end + + expect(subject).to have_button('Repasser en construction') + expect(subject).to have_selector('.en-construction-menu .fr-btn', count: 5) + expect(subject).to have_button('Instruire le dossier') - expect(subject).to have_selector('.header-actions ul:first-child > li .fr-btn', count: 15) - expect(subject).to have_selector('.header-actions ul:first-child > li.instruction-button', count: 1) + expect(subject).to have_selector('.instruction-button .fr-btn', count: 13) end end