diff --git a/app/components/dsfr/radio_button_list_component.rb b/app/components/dsfr/radio_button_list_component.rb index 566d36653..df84138a3 100644 --- a/app/components/dsfr/radio_button_list_component.rb +++ b/app/components/dsfr/radio_button_list_component.rb @@ -17,8 +17,8 @@ class Dsfr::RadioButtonListComponent < ApplicationComponent end def each_button - @buttons.each do |button| - yield(*button.values_at(:label, :value, :hint), **button.except(:label, :value, :hint)) + @buttons.each.with_index do |button, index| + yield(*button.values_at(:label, :value, :hint, :tooltip), **button.merge!(index:).except(:label, :value, :hint, :tooltip)) end end end diff --git a/app/components/dsfr/radio_button_list_component/radio_button_list_component.html.haml b/app/components/dsfr/radio_button_list_component/radio_button_list_component.html.haml index 8776b11af..8c58448ad 100644 --- a/app/components/dsfr/radio_button_list_component/radio_button_list_component.html.haml +++ b/app/components/dsfr/radio_button_list_component/radio_button_list_component.html.haml @@ -1,18 +1,22 @@ %fieldset{ class: class_names("fr-fieldset": true, "fr-fieldset--error": error?), 'aria-labelledby': 'radio-hint-element-legend radio-hint-element-messages', role: error? ? :group : nil } %legend.fr-fieldset__legend--regular.fr-fieldset__legend = content - - - each_button do |label, value, hint, **button_options| + - each_button do |label, value, hint, tooltip, **button_options| .fr-fieldset__element .fr-radio-group - = @form.radio_button @target, value, **button_options + = @form.radio_button @target, value, **button_options.except(:index) = @form.label @target, value: value, class: 'fr-label' do - capture do = label = button_options[:after_label] if button_options[:after_label] - %span.fr-hint-text= hint if hint + - if hint.present? + .flex + .fr-hint-text= hint + - if tooltip.present? && button_options[:index] + .fr-icon-information-line.fr-icon--sm.ml-1{ 'aria-describedby': "tooltip-#{button_options[:index]}" } + %span.fr-tooltip.fr-placement{ id: "tooltip-#{button_options[:index]}", role: 'tooltip', 'aria-hidden': 'true' }= tooltip .fr-messages-group{ 'aria-live': 'assertive' } - if error? diff --git a/app/components/procedure/groupes_management_component/groupes_management_component.html.haml b/app/components/procedure/groupes_management_component/groupes_management_component.html.haml index 7548d6da0..2e6bc12fe 100644 --- a/app/components/procedure/groupes_management_component/groupes_management_component.html.haml +++ b/app/components/procedure/groupes_management_component/groupes_management_component.html.haml @@ -53,3 +53,5 @@ - if flash[:routing_mode] == 'custom' = render partial: 'custom_routing_modal' +- elsif flash[:routing_mode] == 'simple' + = render partial: 'simple_routing_modal', locals: { procedure: @procedure } diff --git a/app/components/procedure/instructeurs_options_component/instructeurs_options_component.html.haml b/app/components/procedure/instructeurs_options_component/instructeurs_options_component.html.haml index e4084a801..36f8d1665 100644 --- a/app/components/procedure/instructeurs_options_component/instructeurs_options_component.html.haml +++ b/app/components/procedure/instructeurs_options_component/instructeurs_options_component.html.haml @@ -55,14 +55,14 @@ url: wizard_admin_procedure_groupe_instructeurs_path(@procedure) do |f| %h1 Configuration du routage - %h2 Choix du type de routage + %h2 Choix du type de configuration .card.fr-pb-0{ data: { 'action': "click->enable-submit-if-checked#click" } } - %p.fr-mb-0 Routage + %p.fr-mb-0 Configuration = render Dsfr::RadioButtonListComponent.new(form: f, target: :state, - buttons: [ { label: 'À partir d’un champ', value: 'routage_simple', hint: 'crée les groupes en fonction d’un champ du formulaire' } , - { label: 'Avancé', value: 'custom_routing', hint: 'libre à vous de créer et de configurer les groupes' }]) + buttons: [ { label: 'Automatique', value: 'routage_simple', hint: 'crée les groupes automatiquement à partir des valeurs possibles d’un champ du formulaire usager' } , + { label: 'Manuelle', value: 'custom_routing', hint: 'libre à vous de créer et de configurer les groupes en utilisant les champs « routables » du formulaire usager' }]) %ul.fr-btns-group.fr-btns-group--inline-sm diff --git a/app/controllers/administrateurs/groupe_instructeurs_controller.rb b/app/controllers/administrateurs/groupe_instructeurs_controller.rb index fa76101ed..43ab472fe 100644 --- a/app/controllers/administrateurs/groupe_instructeurs_controller.rb +++ b/app/controllers/administrateurs/groupe_instructeurs_controller.rb @@ -88,7 +88,8 @@ module Administrateurs defaut.destroy! end - flash.notice = 'Les groupes instructeurs ont été ajoutés' + flash[:routing_mode] = 'simple' + redirect_to admin_procedure_groupe_instructeurs_path(@procedure) end diff --git a/app/models/logic/champ_value.rb b/app/models/logic/champ_value.rb index b63972089..1d9c9858e 100644 --- a/app/models/logic/champ_value.rb +++ b/app/models/logic/champ_value.rb @@ -8,11 +8,11 @@ class Logic::ChampValue < Logic::Term :decimal_number, :drop_down_list, :multiple_drop_down_list, + :address, :communes, :epci, :departements, :regions, - :address, :pays ) diff --git a/app/models/type_de_champ.rb b/app/models/type_de_champ.rb index 0403ac864..b380dc9fe 100644 --- a/app/models/type_de_champ.rb +++ b/app/models/type_de_champ.rb @@ -529,6 +529,18 @@ class TypeDeChamp < ApplicationRecord .map { |_, v| v.map { "« #{I18n.t(_1, scope: [:activerecord, :attributes, :type_de_champ, :type_champs])} »" } } end + def self.humanized_simple_routable_types_by_category + Logic::ChampValue::MANAGED_TYPE_DE_CHAMP_BY_CATEGORY + .map { |_, v| v.filter_map { "« #{I18n.t(_1, scope: [:activerecord, :attributes, :type_de_champ, :type_champs])} »" if _1.to_s.in?(SIMPLE_ROUTABLE_TYPES) } } + .reject(&:empty?) + end + + def self.humanized_custom_routable_types_by_category + Logic::ChampValue::MANAGED_TYPE_DE_CHAMP_BY_CATEGORY + .map { |_, v| v.filter_map { "« #{I18n.t(_1, scope: [:activerecord, :attributes, :type_de_champ, :type_champs])} »" if !_1.to_s.in?(SIMPLE_ROUTABLE_TYPES) } } + .reject(&:empty?) + end + def invalid_regexp? self.errors.delete(:expression_reguliere) self.errors.delete(:expression_reguliere_exemple_text) diff --git a/app/views/administrateurs/groupe_instructeurs/_custom_routing_modal.html.haml b/app/views/administrateurs/groupe_instructeurs/_custom_routing_modal.html.haml index cc503f514..4f14875e0 100644 --- a/app/views/administrateurs/groupe_instructeurs/_custom_routing_modal.html.haml +++ b/app/views/administrateurs/groupe_instructeurs/_custom_routing_modal.html.haml @@ -8,7 +8,7 @@ .fr-modal__content %h1#fr-modal-title-modal-1.fr-modal__title %span.fr-icon-arrow-right-line.fr-icon--lg - Routage avancé + Configuration manuelle du routage .fr-alert.fr-alert--success %h2.fr-alert__title Deux groupes par défaut ont été créés diff --git a/app/views/administrateurs/groupe_instructeurs/_simple_routing_modal.html.haml b/app/views/administrateurs/groupe_instructeurs/_simple_routing_modal.html.haml new file mode 100644 index 000000000..ff817b750 --- /dev/null +++ b/app/views/administrateurs/groupe_instructeurs/_simple_routing_modal.html.haml @@ -0,0 +1,14 @@ +%dialog{ aria: { labelledby: "fr-modal-title-modal-1" }, role: "dialog", id: "routing-mode-modal", class: "fr-modal fr-modal--opened" } + .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 + .fr-modal__body + .fr-modal__header + %button.fr-btn.fr-btn--close{ title: "Fermer la fenêtre modale", aria: { controls: "routing-mode-modal" } } Fermer + .fr-modal__content + %h1#fr-modal-title-modal-1.fr-modal__title + %span.fr-icon-arrow-right-line.fr-icon--lg + Configuration automatique du routage + .fr-alert.fr-alert--success + %h2.fr-alert__title + Les groupes instructeurs ont été créés à partir du champ « #{procedure.routing_champs.first} » diff --git a/app/views/administrateurs/groupe_instructeurs/simple_routing.html.haml b/app/views/administrateurs/groupe_instructeurs/simple_routing.html.haml index c1a97daa0..de4deae6a 100644 --- a/app/views/administrateurs/groupe_instructeurs/simple_routing.html.haml +++ b/app/views/administrateurs/groupe_instructeurs/simple_routing.html.haml @@ -2,26 +2,53 @@ locals: { steps: [[t('.procedures'), admin_procedures_path], [@procedure.libelle.truncate_words(10), admin_procedure_path(@procedure)], ['Groupes', admin_procedure_groupe_instructeurs_path(@procedure)], - ['Routage à partir d’un champ']] } + ['Configuration automatique du routage']] } -= render Procedure::InstructeursMenuComponent.new(procedure: @procedure) do - - content_for(:title, 'Routage') - %h1 Routage à partir d’un champ - = form_for :create_simple_routing, - method: :post, - data: { controller: 'enable-submit-if-checked' }, - url: create_simple_routing_admin_procedure_groupe_instructeurs_path(@procedure) do |f| +.container + .fr-grid-row + .fr-col.fr-col-12.fr-col-md-3 + .fr-container + %ul.fr-btns-group.fr-btns-group--inline-md.fr-ml-0 + %li + = link_to options_admin_procedure_groupe_instructeurs_path, class: 'fr-link fr-icon-arrow-left-line fr-link--icon-left fr-mb-2w fr-mr-2w' do + Revenir aux options - %div{ data: { 'action': "click->enable-submit-if-checked#click" } } - .notice - Sélectionner le champ à partir duquel créer des groupes d’instructeurs - - buttons_content = @procedure.active_revision.simple_routable_types_de_champ.map { |tdc| { label: tdc.libelle, value: tdc.stable_id } } - = render Dsfr::RadioButtonListComponent.new(form: f, - target: :stable_id, - buttons: buttons_content) + .fr-col + - content_for(:title, 'Routage') + %h1 Configuration du routage + %h2 Configuration automatique + .fr-alert.fr-alert--info.fr-mb-3w{ aria: { hidden: true } } + %p + Vous trouverez ci-dessous une liste de champs de votre formulaire à partir desquels configurer le routage de façon automatique. Les groupes d’instructeurs seront créés à partir des valeurs possibles du champ. + Seuls les champs suivants sont ouverts à ce mode de configuration : + %ul + - TypeDeChamp.humanized_simple_routable_types_by_category.each do |category| + %li + = category.join(', ') - %ul.fr-btns-group.fr-btns-group--inline-sm - %li - = link_to 'Retour', options_admin_procedure_groupe_instructeurs_path(@procedure, state: :choix), class: 'fr-btn fr-btn--secondary' - %li - %button.fr-btn{ disabled: true, data: { disable_with: 'Création des groupes…', 'enable-submit-if-checked-target': 'submit' } } Créer les groupes + %p + Si besoin, vous pourrez ensuite affiner votre configuration de façon manuelle, également à partir des champs suivants : + + %ul + - TypeDeChamp.humanized_custom_routable_types_by_category.each do |category| + %li + = category.join(', ') + + = form_for :create_simple_routing, + method: :post, + data: { controller: 'enable-submit-if-checked' }, + url: create_simple_routing_admin_procedure_groupe_instructeurs_path(@procedure) do |f| + + .card.fr-pb-0{ data: { 'action': "click->enable-submit-if-checked#click" } } + .notice + Sélectionner le champ à partir duquel créer des groupes d’instructeurs + - buttons_content = @procedure.active_revision.simple_routable_types_de_champ.map { |tdc| { label: tdc.libelle, value: tdc.stable_id, hint: "[#{I18n.t(tdc.type_champ, scope: 'activerecord.attributes.type_de_champ.type_champs')}]", tooltip: tdc.drop_down_options.join(", ")} } + = render Dsfr::RadioButtonListComponent.new(form: f, + target: :stable_id, + buttons: buttons_content) + + %ul.fr-btns-group.fr-btns-group--inline-sm + %li + = link_to 'Annuler', options_admin_procedure_groupe_instructeurs_path(@procedure, state: :choix), class: 'fr-btn fr-btn--secondary' + %li + %button.fr-btn{ disabled: true, data: { disable_with: 'Création des groupes…', 'enable-submit-if-checked-target': 'submit' } } Créer les groupes diff --git a/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb b/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb index 7b4e54ba1..84db0d18f 100644 --- a/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb +++ b/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb @@ -879,7 +879,7 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do it do expect(response).to have_http_status(:ok) - expect(response.body).to include('Choix du type de routage') + expect(response.body).to include('Choix du type de configuration') expect(procedure.reload.routing_enabled).to be_falsey end end @@ -918,7 +918,7 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do it do expect(response).to redirect_to(admin_procedure_groupe_instructeurs_path(procedure3)) - expect(flash.notice).to eq 'Les groupes instructeurs ont été ajoutés' + expect(flash[:routing_mode]).to eq 'simple' expect(procedure3.groupe_instructeurs.pluck(:label)).to match_array(['Paris', 'Lyon', 'Marseille']) expect(procedure3.reload.defaut_groupe_instructeur.routing_rule).to eq(ds_eq(champ_value(drop_down_tdc.stable_id), constant('Lyon'))) expect(procedure3.routing_enabled).to be_truthy @@ -938,7 +938,7 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do it do expect(response).to redirect_to(admin_procedure_groupe_instructeurs_path(procedure3)) - expect(flash.notice).to eq 'Les groupes instructeurs ont été ajoutés' + expect(flash[:routing_mode]).to eq 'simple' expect(procedure3.groupe_instructeurs.pluck(:label)).to include("01 – Ain") expect(procedure3.reload.defaut_groupe_instructeur.routing_rule).to eq(ds_eq(champ_value(departements_tdc.stable_id), constant('01'))) expect(procedure3.routing_enabled).to be_truthy @@ -958,7 +958,7 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do it do expect(response).to redirect_to(admin_procedure_groupe_instructeurs_path(procedure3)) - expect(flash.notice).to eq 'Les groupes instructeurs ont été ajoutés' + expect(flash[:routing_mode]).to eq 'simple' expect(procedure3.groupe_instructeurs.pluck(:label)).to include("Guadeloupe") expect(procedure3.reload.defaut_groupe_instructeur.routing_rule).to eq(ds_eq(champ_value(regions_tdc.stable_id), constant('84'))) expect(procedure3.routing_enabled).to be_truthy @@ -978,7 +978,7 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do it do expect(response).to redirect_to(admin_procedure_groupe_instructeurs_path(procedure3)) - expect(flash.notice).to eq 'Les groupes instructeurs ont été ajoutés' + expect(flash[:routing_mode]).to eq 'simple' expect(procedure3.groupe_instructeurs.pluck(:label)).to include("AD – Andorre") expect(procedure3.reload.defaut_groupe_instructeur.routing_rule).to eq(ds_eq(champ_value(pays_tdc.stable_id), constant('AD'))) expect(procedure3.routing_enabled).to be_truthy @@ -998,7 +998,7 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do it do expect(response).to redirect_to(admin_procedure_groupe_instructeurs_path(procedure3)) - expect(flash.notice).to eq 'Les groupes instructeurs ont été ajoutés' + expect(flash[:routing_mode]).to eq 'simple' expect(procedure3.groupe_instructeurs.pluck(:label)).to include("01 – Ain") expect(procedure3.reload.defaut_groupe_instructeur.routing_rule).to eq(ds_in_departement(champ_value(communes_tdc.stable_id), constant('01'))) expect(procedure3.routing_enabled).to be_truthy @@ -1018,7 +1018,7 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do it do expect(response).to redirect_to(admin_procedure_groupe_instructeurs_path(procedure3)) - expect(flash.notice).to eq 'Les groupes instructeurs ont été ajoutés' + expect(flash[:routing_mode]).to eq 'simple' expect(procedure3.groupe_instructeurs.pluck(:label)).to include("01 – Ain") expect(procedure3.reload.defaut_groupe_instructeur.routing_rule).to eq(ds_in_departement(champ_value(epci_tdc.stable_id), constant('01'))) expect(procedure3.routing_enabled).to be_truthy @@ -1038,7 +1038,7 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do it do expect(response).to redirect_to(admin_procedure_groupe_instructeurs_path(procedure3)) - expect(flash.notice).to eq 'Les groupes instructeurs ont été ajoutés' + expect(flash[:routing_mode]).to eq 'simple' expect(procedure3.groupe_instructeurs.pluck(:label)).to include("01 – Ain") expect(procedure3.reload.defaut_groupe_instructeur.routing_rule).to eq(ds_in_departement(champ_value(address_tdc.stable_id), constant('01'))) expect(procedure3.routing_enabled).to be_truthy diff --git a/spec/models/type_de_champ_spec.rb b/spec/models/type_de_champ_spec.rb index 3210d5465..b8d4e44f3 100644 --- a/spec/models/type_de_champ_spec.rb +++ b/spec/models/type_de_champ_spec.rb @@ -462,6 +462,6 @@ describe TypeDeChamp do describe '#humanized_conditionable_types_by_category' do subject { TypeDeChamp.humanized_conditionable_types_by_category } - it { is_expected.to eq([["« Oui/Non »", "« Case à cocher seule »", "« Choix simple »", "« Choix multiple »"], ["« Nombre entier »", "« Nombre décimal »"], ["« Communes »", "« EPCI »", "« Départements »", "« Régions »", "« Adresse »", "« Pays »"]]) } + it { is_expected.to eq([["« Oui/Non »", "« Case à cocher seule »", "« Choix simple »", "« Choix multiple »"], ["« Nombre entier »", "« Nombre décimal »"], ["« Adresse »", "« Communes »", "« EPCI »", "« Départements »", "« Régions »", "« Pays »"]]) } end end diff --git a/spec/system/routing/rules_full_scenario_spec.rb b/spec/system/routing/rules_full_scenario_spec.rb index 56e1c7942..682f7ed10 100644 --- a/spec/system/routing/rules_full_scenario_spec.rb +++ b/spec/system/routing/rules_full_scenario_spec.rb @@ -18,13 +18,13 @@ describe 'The routing with rules', js: true do procedure.defaut_groupe_instructeur.instructeurs << administrateur.instructeur end - scenario 'Routage à partir d’un champ' do + scenario 'Configuration automatique du routage' do steps_to_routing_configuration - choose('À partir d’un champ', allow_label_click: true) + choose('Automatique', allow_label_click: true) click_on 'Continuer' - expect(page).to have_text('Routage à partir d’un champ') + expect(page).to have_text('Configuration automatique') choose('Spécialité', allow_label_click: true) click_on 'Créer les groupes' @@ -33,6 +33,8 @@ describe 'The routing with rules', js: true do expect(page).to have_text('3 groupes') expect(page).not_to have_text('à configurer') + within("#routing-mode-modal") { click_on "Fermer" } + click_on 'littéraire' expect(page).to have_select("groupe_instructeur[condition_form][rows][][targeted_champ]", selected: "Spécialité") expect(page).to have_select("groupe_instructeur[condition_form][rows][][value]", selected: "littéraire") @@ -44,10 +46,10 @@ describe 'The routing with rules', js: true do expect(page).to have_select("groupe_instructeur[condition_form][rows][][value]", selected: "scientifique") end - scenario 'Routage avancé' do + scenario 'Configuration manuelle du routage' do steps_to_routing_configuration - choose('Avancé', allow_label_click: true) + choose('Manuelle', allow_label_click: true) click_on 'Continuer' expect(page).to have_text('Gestion des groupes') @@ -331,6 +333,6 @@ describe 'The routing with rules', js: true do click_on 'Options' expect(page).to have_text('Options concernant l’instruction') click_on 'Configurer le routage' - expect(page).to have_text('Choix du type de routage') + expect(page).to have_text('Choix du type de configuration') end end