From 62662c99c0965c44fde58b9522b59ac25bb429bb Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Mon, 24 Apr 2023 15:13:21 +0200 Subject: [PATCH 01/28] style: add flex auto --- app/assets/stylesheets/flex.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/stylesheets/flex.scss b/app/assets/stylesheets/flex.scss index 4b222c6fa..e8c78a5a9 100644 --- a/app/assets/stylesheets/flex.scss +++ b/app/assets/stylesheets/flex.scss @@ -42,6 +42,10 @@ &.row-reverse { flex-direction: row-reverse; } + + &.auto { + flex: auto; + } } .flex-grow { From 2fb33336d1e2cb2fb0c71c1838e05fba96734b00 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Mon, 24 Apr 2023 15:13:51 +0200 Subject: [PATCH 02/28] side_menu_component: add icon --- app/components/dsfr/sidemenu_component.rb | 5 +++-- .../dsfr/sidemenu_component/sidemenu_component.html.haml | 6 +++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/components/dsfr/sidemenu_component.rb b/app/components/dsfr/sidemenu_component.rb index d448f7852..31c2730e4 100644 --- a/app/components/dsfr/sidemenu_component.rb +++ b/app/components/dsfr/sidemenu_component.rb @@ -2,10 +2,11 @@ class Dsfr::SidemenuComponent < ApplicationComponent renders_many :links, "LinkComponent" class LinkComponent < ApplicationComponent - attr_reader :name, :url - def initialize(name:, url:) + attr_reader :name, :url, :icon + def initialize(name:, url:, icon: nil) @name = name @url = url + @icon = icon end end diff --git a/app/components/dsfr/sidemenu_component/sidemenu_component.html.haml b/app/components/dsfr/sidemenu_component/sidemenu_component.html.haml index 2e2a70014..2c6c96e26 100644 --- a/app/components/dsfr/sidemenu_component/sidemenu_component.html.haml +++ b/app/components/dsfr/sidemenu_component/sidemenu_component.html.haml @@ -6,4 +6,8 @@ %ul.fr-sidemenu__list - links.each do |link| %li{ class: "fr-sidemenu__item fr-sidemenu__item#{active?(link.url) ? '--active' : ''}" } - = link_to link.name, link.url, class: 'fr-sidemenu__link', 'aria-current': active?(link.url) ? 'page' : nil, target: "_self" + = link_to link.url, class: 'fr-sidemenu__link ', 'aria-current': active?(link.url) ? 'page' : nil, target: "_self" do + - capture do + - if link.icon.present? + %span{ class: link.icon }  + = link.name From f3c9fc014bce7f6ac0af7fde5fbf39ca5ab50587 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Mon, 24 Apr 2023 15:18:39 +0200 Subject: [PATCH 03/28] add instructeur_menu component --- .../procedure/instructeurs_menu_component.rb | 22 +++++++++++++++++++ .../instructeurs_menu_component.fr.yml | 5 +++++ .../instructeurs_menu_component.html.haml | 7 ++++++ 3 files changed, 34 insertions(+) create mode 100644 app/components/procedure/instructeurs_menu_component.rb create mode 100644 app/components/procedure/instructeurs_menu_component/instructeurs_menu_component.fr.yml create mode 100644 app/components/procedure/instructeurs_menu_component/instructeurs_menu_component.html.haml diff --git a/app/components/procedure/instructeurs_menu_component.rb b/app/components/procedure/instructeurs_menu_component.rb new file mode 100644 index 000000000..391978453 --- /dev/null +++ b/app/components/procedure/instructeurs_menu_component.rb @@ -0,0 +1,22 @@ +class Procedure::InstructeursMenuComponent < ApplicationComponent + def initialize(procedure:) + @procedure = procedure + end + + private + + def links + first_option, first_icon = if @procedure.groupe_instructeurs.one? + instructeurs_count = @procedure.groupe_instructeurs.first.instructeurs.count + [t('.instructeurs', count: instructeurs_count), 'fr-icon-user-line'] + else + ["#{@procedure.groupe_instructeurs.count} groupes", 'fr-icon-group-line'] + end + + [ + { name: first_option, url: admin_procedure_groupe_instructeurs_path(@procedure), icon: "#{first_icon} fr-icon--sm" }, + ({ name: 'Ajout de groupes', url: ajout_admin_procedure_groupe_instructeurs_path(@procedure), icon: 'fr-icon-add-circle-line fr-icon--sm' } if @procedure.routing_enabled?), + { name: 'Options', url: options_admin_procedure_groupe_instructeurs_path(@procedure), icon: 'fr-icon-settings-5-line fr-icon--sm' } + ].compact + end +end diff --git a/app/components/procedure/instructeurs_menu_component/instructeurs_menu_component.fr.yml b/app/components/procedure/instructeurs_menu_component/instructeurs_menu_component.fr.yml new file mode 100644 index 000000000..13eb65fda --- /dev/null +++ b/app/components/procedure/instructeurs_menu_component/instructeurs_menu_component.fr.yml @@ -0,0 +1,5 @@ +--- +fr: + instructeurs: + one: "%{count} instructeur" + other: "%{count} instructeurs" diff --git a/app/components/procedure/instructeurs_menu_component/instructeurs_menu_component.html.haml b/app/components/procedure/instructeurs_menu_component/instructeurs_menu_component.html.haml new file mode 100644 index 000000000..f351776b1 --- /dev/null +++ b/app/components/procedure/instructeurs_menu_component/instructeurs_menu_component.html.haml @@ -0,0 +1,7 @@ +.container + .fr-grid-row + .fr-col.fr-col-12.fr-col-md-3 + = render(Dsfr::SidemenuComponent.new) do |component| + - component.with_links(links) + .fr-col= content + From 6bfbf8ca0efefc3c25a6047952db560e1fbf531c Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Mon, 24 Apr 2023 15:24:55 +0200 Subject: [PATCH 04/28] reset admin groupe instructeur index --- .../groupe_instructeurs/index.html.haml | 35 +++---------------- 1 file changed, 4 insertions(+), 31 deletions(-) diff --git a/app/views/administrateurs/groupe_instructeurs/index.html.haml b/app/views/administrateurs/groupe_instructeurs/index.html.haml index a876b4886..0f057465c 100644 --- a/app/views/administrateurs/groupe_instructeurs/index.html.haml +++ b/app/views/administrateurs/groupe_instructeurs/index.html.haml @@ -1,31 +1,4 @@ -- if @procedure.routing_enabled? - = render partial: 'administrateurs/breadcrumbs', - locals: { steps: [[t('.procedures'), admin_procedures_path], - [@procedure.libelle.truncate_words(10), admin_procedure_path(@procedure)], - [t('.instructors_group')]] } -- else - = render partial: 'administrateurs/breadcrumbs', - locals: { steps: [[t('.procedures'), admin_procedures_path], - [@procedure.libelle.truncate_words(10), admin_procedure_path(@procedure)], - ['Instructeurs']] } - -.container.groupe-instructeur - %h1 Gérer les instructeurs et les options d'instruction de « #{@procedure.libelle} » - - - if @procedure.groupe_instructeurs.one? - = render partial: 'administrateurs/groupe_instructeurs/instructeurs', - locals: { procedure: @procedure, - groupe_instructeur: @procedure.defaut_groupe_instructeur, - instructeurs: @instructeurs, - available_instructeur_emails: @available_instructeur_emails, - disabled_as_super_admin: administrateur_as_manager? } - - if !@procedure.routing_enabled? - = render partial: 'administrateurs/groupe_instructeurs/instructeurs_self_management', locals: { procedure: @procedure } - - = render partial: 'administrateurs/groupe_instructeurs/routing', locals: { procedure: @procedure } - - = render partial: 'administrateurs/groupe_instructeurs/edit', locals: { procedure: @procedure, groupes_instructeurs: @groupes_instructeurs } - - - if @procedure.routing_enabled? && @procedure.feature_enabled?(:routing_rules) - = render(Procedure::RoutingRulesComponent.new(revision: @procedure.active_revision, - groupe_instructeurs: @procedure.groupe_instructeurs)) += render partial: 'administrateurs/breadcrumbs', + locals: { steps: [[t('.procedures'), admin_procedures_path], + [@procedure.libelle.truncate_words(10), admin_procedure_path(@procedure)], + [t('.instructors_group')]] } From 588efc8b34e6d81e3f996bf2fbfa67fb9a377214 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Mon, 24 Apr 2023 15:26:09 +0200 Subject: [PATCH 05/28] admin instructeur index: fix breadcrumb --- app/views/administrateurs/groupe_instructeurs/index.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/administrateurs/groupe_instructeurs/index.html.haml b/app/views/administrateurs/groupe_instructeurs/index.html.haml index 0f057465c..bf5d085c3 100644 --- a/app/views/administrateurs/groupe_instructeurs/index.html.haml +++ b/app/views/administrateurs/groupe_instructeurs/index.html.haml @@ -1,4 +1,4 @@ = render partial: 'administrateurs/breadcrumbs', locals: { steps: [[t('.procedures'), admin_procedures_path], [@procedure.libelle.truncate_words(10), admin_procedure_path(@procedure)], - [t('.instructors_group')]] } + [@procedure.groupe_instructeurs.many? ? 'Groupes' : 'Instructeurs']] } From 171a6b35fbf47fbc4d9fb34b66e7142e1acf57cf Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Mon, 24 Apr 2023 15:27:44 +0200 Subject: [PATCH 06/28] use instructeur_menu --- .../administrateurs/groupe_instructeurs/index.html.haml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/views/administrateurs/groupe_instructeurs/index.html.haml b/app/views/administrateurs/groupe_instructeurs/index.html.haml index bf5d085c3..edf0cd685 100644 --- a/app/views/administrateurs/groupe_instructeurs/index.html.haml +++ b/app/views/administrateurs/groupe_instructeurs/index.html.haml @@ -2,3 +2,11 @@ locals: { steps: [[t('.procedures'), admin_procedures_path], [@procedure.libelle.truncate_words(10), admin_procedure_path(@procedure)], [@procedure.groupe_instructeurs.many? ? 'Groupes' : 'Instructeurs']] } + += render Procedure::InstructeursMenuComponent.new(procedure: @procedure) do + - if @procedure.groupe_instructeurs.one? + = render Procedure::InstructeursManagementComponent.new(procedure: @procedure, + groupe_instructeur: @procedure.groupe_instructeurs.first, + instructeurs: @instructeurs, + available_instructeur_emails: @available_instructeur_emails, + disabled_as_super_admin: administrateur_as_manager?) From 142ac9173d569a2f3fb39445ef0bf6437caa3988 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Tue, 9 May 2023 11:15:02 +0200 Subject: [PATCH 07/28] add groupes_search_component --- .../procedure/groupes_search_component.rb | 5 +++++ .../groupes_search_component.html.haml | 9 ++++++++ .../groupe_instructeurs_controller.rb | 13 +++++++++-- .../groupe_instructeurs_controller_spec.rb | 22 ++++++++++++++----- 4 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 app/components/procedure/groupes_search_component.rb create mode 100644 app/components/procedure/groupes_search_component/groupes_search_component.html.haml diff --git a/app/components/procedure/groupes_search_component.rb b/app/components/procedure/groupes_search_component.rb new file mode 100644 index 000000000..e1e12d7b0 --- /dev/null +++ b/app/components/procedure/groupes_search_component.rb @@ -0,0 +1,5 @@ +class Procedure::GroupesSearchComponent < ApplicationComponent + def initialize(procedure:, query:, to_configure_count:) + @procedure, @query, @to_configure_count = procedure, query, to_configure_count + end +end diff --git a/app/components/procedure/groupes_search_component/groupes_search_component.html.haml b/app/components/procedure/groupes_search_component/groupes_search_component.html.haml new file mode 100644 index 000000000..26bcd5f34 --- /dev/null +++ b/app/components/procedure/groupes_search_component/groupes_search_component.html.haml @@ -0,0 +1,9 @@ += form_for admin_procedure_groupe_instructeurs_path(@procedure), + method: :get do + #header-search.fr-search-bar.fr-mb-2w{ role: "search" } + = label_tag :q, 'Rechercher par nom', class: 'fr-label' + = text_field_tag :q, @query, class: 'fr-input', type: 'search', autocomplete: 'off', placeholder: 'Rechercher par nom' + %button.fr-btn{ title: "Rechercher" } Rechercher + +- if @to_configure_count > 0 + %span #{ @to_configure_count } à configurer diff --git a/app/controllers/administrateurs/groupe_instructeurs_controller.rb b/app/controllers/administrateurs/groupe_instructeurs_controller.rb index 036a3d105..af3196a7a 100644 --- a/app/controllers/administrateurs/groupe_instructeurs_controller.rb +++ b/app/controllers/administrateurs/groupe_instructeurs_controller.rb @@ -291,8 +291,17 @@ module Administrateurs end def paginated_groupe_instructeurs - procedure - .groupe_instructeurs + groupes = if params[:q].present? + query = ActiveRecord::Base.sanitize_sql_like(params[:q]) + + procedure + .groupe_instructeurs + .where('unaccent(label) ILIKE unaccent(?)', "%#{query}%") + else + procedure.groupe_instructeurs + end + + groupes .page(params[:page]) .per(ITEMS_PER_PAGE) end diff --git a/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb b/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb index 35760e5b3..eda4df189 100644 --- a/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb +++ b/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb @@ -13,13 +13,25 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do describe '#index' do context 'of a procedure I own' do - before { get :index, params: { procedure_id: procedure.id } } + before { get :index, params: } context 'when a procedure has multiple groups' do - it { expect(response).to have_http_status(:ok) } - it { expect(response.body).to include(gi_1_1.label) } - it { expect(response.body).to include(gi_1_2.label) } - it { expect(response.body).not_to include(gi_2_2.label) } + let(:params) { { procedure_id: procedure.id } } + + it do + expect(response).to have_http_status(:ok) + expect(response.body).to include(gi_1_1.label) + expect(response.body).to include(gi_1_2.label) + expect(response.body).not_to include(gi_2_2.label) + end + + context 'when there is a search' do + let(:params) { { procedure_id: procedure.id, q: '2' } } + + it do + expect(assigns(:groupes_instructeurs)).to match_array([gi_1_2]) + end + end end end end From 5b0e0ced3c4f5ba21c0ff0cb39d0cd0c1ca5ec24 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Mon, 24 Apr 2023 15:32:58 +0200 Subject: [PATCH 08/28] add groupes_management_component --- .../procedure/groupes_management_component.rb | 26 ++++++++++++ .../groupes_management_component.fr.yml | 8 ++++ .../groupes_management_component.html.haml | 40 +++++++++++++++++++ app/models/groupe_instructeur.rb | 5 +++ .../groupe_instructeurs/index.html.haml | 2 + 5 files changed, 81 insertions(+) create mode 100644 app/components/procedure/groupes_management_component.rb create mode 100644 app/components/procedure/groupes_management_component/groupes_management_component.fr.yml create mode 100644 app/components/procedure/groupes_management_component/groupes_management_component.html.haml diff --git a/app/components/procedure/groupes_management_component.rb b/app/components/procedure/groupes_management_component.rb new file mode 100644 index 000000000..48f051f20 --- /dev/null +++ b/app/components/procedure/groupes_management_component.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +class Procedure::GroupesManagementComponent < ApplicationComponent + def initialize(procedure:, groupe_instructeurs:, query:) + @procedure = procedure + @groupe_instructeurs = groupe_instructeurs + @query = query + @total = groupe_instructeurs.total_count + end + + def table_header + if @query.present? + if @groupe_instructeurs.length != @total + "#{t('.groupe', count: @groupe_instructeurs.length)} sur #{@total} #{t('.found', count: @total)}" + else + "#{t('.groupe', count: @groupe_instructeurs.length)} #{t('.found', count: @groupe_instructeurs.length)}" + end + else + if @groupe_instructeurs.length != @total + "#{t('.groupe', count: @groupe_instructeurs.length)} sur #{@total}" + else + t('.groupe', count: @groupe_instructeurs.length) + end + end + end +end diff --git a/app/components/procedure/groupes_management_component/groupes_management_component.fr.yml b/app/components/procedure/groupes_management_component/groupes_management_component.fr.yml new file mode 100644 index 000000000..3230cd0a9 --- /dev/null +++ b/app/components/procedure/groupes_management_component/groupes_management_component.fr.yml @@ -0,0 +1,8 @@ +--- +fr: + groupe: + one: "%{count} groupe" + other: "%{count} groupes" + found: + one: "trouvé" + other: "trouvés" 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 new file mode 100644 index 000000000..d98152d1d --- /dev/null +++ b/app/components/procedure/groupes_management_component/groupes_management_component.html.haml @@ -0,0 +1,40 @@ +- content_for(:title, 'Groupes') +%h1 Gestion des groupes + += render Procedure::GroupesSearchComponent.new(procedure: @procedure, query: @query, to_configure_count: @procedure.groupe_instructeurs.filter(&:routing_to_configure?).count) + +.fr-table.fr-table--no-caption.fr-table--layout-fixed.fr-mt-2w + %table + %caption= table_header + %thead + %tr + %th{ scope: "col" } + .flex + .flex.auto= table_header + %span.fr-icon.fr-icon-user-line + %tbody + - @groupe_instructeurs.each do |gi| + %tr + %td + .flex + .flex.auto + = link_to admin_procedure_groupe_instructeur_path(@procedure, gi), class: 'fr-link' do + %span= gi.label + - if gi.closed + %p.fr-badge.fr-badge--info.fr-badge--sm.fr-ml-1w inactif + - elsif gi.routing_to_configure? + %p.fr-badge.fr-badge--warning.fr-badge--sm.fr-ml-1w à configurer + + %div{ style: 'width: 25px; text-align: center;' } + #{gi.instructeurs.count} + %p= gi.routing_rule&.to_s(@procedure.active_revision.types_de_champ) + .fr-mt-1w + = paginate @groupe_instructeurs + += form_tag admin_procedure_update_defaut_groupe_instructeur_path, + class: 'fr-my-3w', + data: { controller: 'autosave' } do + = label_tag :defaut_groupe_instructeur_id, 'Et si aucune règle ne correspond, router vers :', class: 'fr-label' + = select_tag :defaut_groupe_instructeur_id, + options_for_select(@procedure.groupe_instructeurs.pluck(:label, :id), selected: @procedure.defaut_groupe_instructeur.id), + class: 'fr-select' diff --git a/app/models/groupe_instructeur.rb b/app/models/groupe_instructeur.rb index 95d06694f..472935dbf 100644 --- a/app/models/groupe_instructeur.rb +++ b/app/models/groupe_instructeur.rb @@ -86,6 +86,11 @@ class GroupeInstructeur < ApplicationRecord dossiers.empty? && (procedure.groupe_instructeurs.active.many? || (procedure.groupe_instructeurs.active.one? && closed)) end + def routing_to_configure? + rule = routing_rule + !(rule.is_a?(Logic::Eq) && rule.left.is_a?(Logic::ChampValue) && rule.right.is_a?(Logic::Constant)) + end + private def toggle_routing diff --git a/app/views/administrateurs/groupe_instructeurs/index.html.haml b/app/views/administrateurs/groupe_instructeurs/index.html.haml index edf0cd685..584bf15a2 100644 --- a/app/views/administrateurs/groupe_instructeurs/index.html.haml +++ b/app/views/administrateurs/groupe_instructeurs/index.html.haml @@ -10,3 +10,5 @@ instructeurs: @instructeurs, available_instructeur_emails: @available_instructeur_emails, disabled_as_super_admin: administrateur_as_manager?) + - else + = render Procedure::GroupesManagementComponent.new(procedure: @procedure, groupe_instructeurs: @groupes_instructeurs, query: params[:q]) From 1754086c946d3f81b6d8cebe0518421191f0d997 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Mon, 24 Apr 2023 15:45:40 +0200 Subject: [PATCH 09/28] add options component --- .../instructeurs_options_component.rb | 6 +++ .../instructeurs_options_component.fr.yml | 11 +++++ .../instructeurs_options_component.html.haml | 49 +++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 app/components/procedure/instructeurs_options_component.rb create mode 100644 app/components/procedure/instructeurs_options_component/instructeurs_options_component.fr.yml create mode 100644 app/components/procedure/instructeurs_options_component/instructeurs_options_component.html.haml diff --git a/app/components/procedure/instructeurs_options_component.rb b/app/components/procedure/instructeurs_options_component.rb new file mode 100644 index 000000000..5bcf8ed0f --- /dev/null +++ b/app/components/procedure/instructeurs_options_component.rb @@ -0,0 +1,6 @@ +class Procedure::InstructeursOptionsComponent < ApplicationComponent + def initialize(procedure:, state:) + @procedure = procedure + @state = state + end +end diff --git a/app/components/procedure/instructeurs_options_component/instructeurs_options_component.fr.yml b/app/components/procedure/instructeurs_options_component/instructeurs_options_component.fr.yml new file mode 100644 index 000000000..5758e8df2 --- /dev/null +++ b/app/components/procedure/instructeurs_options_component/instructeurs_options_component.fr.yml @@ -0,0 +1,11 @@ +--- +fr: + routing_configuration_notice_1: + Le routage permet d’acheminer les dossiers vers différents groupes d’instructeurs. + routing_configuration_notice_2_html: | +

Pour le configurer, votre formulaire doit comporter + au moins un champ « choix simple ».

+

Ajoutez ce champ dans la page « Configuration des champs ».

+ delete_title: Aucun dossier ne sera supprimé. Les groupes d'instructeurs vont être supprimés. Seuls les instructeurs du groupe « %{defaut_label} » resteront affectés à la procédure. + delete_confirmation: | + Attention : tous les dossiers vont être déplacés dans le groupe « %{defaut_label} » et seuls les instructeurs présent dans ce groupe resteront affectés à la procédure. Souhaitez-vous continuer ? 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 new file mode 100644 index 000000000..0835f6a1e --- /dev/null +++ b/app/components/procedure/instructeurs_options_component/instructeurs_options_component.html.haml @@ -0,0 +1,49 @@ +- content_for(:title, 'Options') +- if @state.nil? + %h1 Options concernant l’instruction + + %ul.fr-toggle__list + %li + = form_for @procedure, + method: :patch, + url: update_instructeurs_self_management_enabled_admin_procedure_groupe_instructeurs_path(@procedure), + data: { controller: 'autosubmit', turbo: 'true' } do |f| + + = render Dsfr::ToggleComponent.new(form: f, + target: :instructeurs_self_management_enabled, + title: 'Autogestion des instructeurs', + hint: "L’autogestion des instructeurs permet aux instructeurs de gérer eux-mêmes la liste des instructeurs de la démarche.#{ ' Lorsque la démarche est routée, l’autogestion est activée d’office et n’est pas désactivable.' if @procedure.routing_enabled? }", + disabled: @procedure.routing_enabled?) + %p.fr-mt-2w Routage + %p.fr-mt-2w= t('.routing_configuration_notice_1') + - if @procedure.active_revision.routable_types_de_champ.none? + %p.fr-mt-2w= t('.routing_configuration_notice_2_html', path: champs_admin_procedure_path(@procedure)) + - elsif @procedure.groupe_instructeurs.active.one? + = link_to 'Configurer le routage', options_admin_procedure_groupe_instructeurs_path(@procedure, state: :choix), class: 'fr-btn' + + - else + = button_to 'Supprimer le routage', + destroy_all_groups_but_defaut_admin_procedure_groupe_instructeurs_path, + class: 'fr-btn', + method: :delete, + title: t('.delete_title', defaut_label: @procedure.defaut_groupe_instructeur.label), + data: ( @procedure.publiee? ? { disable_with: "Suppression...", confirm: t('.delete_confirmation', defaut_label: @procedure.defaut_groupe_instructeur.label) } : nil) + +- elsif @state == 'choix' + = form_for :choice, + method: :patch, + data: { controller: 'radio-enabled-submit' }, + url: wizard_admin_procedure_groupe_instructeurs_path(@procedure) do |f| + + %div{ data: { 'action': "click->radio-enabled-submit#click" } } + = 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: 'routage_custom', hint: 'libre à vous de créer et de configurer les groupes' }]) do + %h1 Choix du type de routage + + %ul.fr-btns-group.fr-btns-group--inline-sm + %li + = link_to 'Retour', options_admin_procedure_groupe_instructeurs_path(@procedure), class: 'fr-btn fr-btn--secondary' + %li + %button.fr-btn{ disabled: true, data: { 'radio-enabled-submit-target': 'submit' } } Continuer From 174f7a7c53d3f2dd390419b80fec8a09ec9d760a Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Mon, 24 Apr 2023 15:47:46 +0200 Subject: [PATCH 10/28] add one_groupe_management_component --- .../one_groupe_management_component.rb | 65 +++++++++++++++++++ .../one_groupe_management_component.fr.yml | 8 +++ .../one_groupe_management_component.html.haml | 54 +++++++++++++++ .../groupe_instructeurs_controller.rb | 29 +++++++-- .../routing/update.turbo_stream.haml | 5 +- config/routes.rb | 2 + ...=> one_group_management_component_spec.rb} | 15 +---- 7 files changed, 158 insertions(+), 20 deletions(-) create mode 100644 app/components/procedure/one_groupe_management_component.rb create mode 100644 app/components/procedure/one_groupe_management_component/one_groupe_management_component.fr.yml create mode 100644 app/components/procedure/one_groupe_management_component/one_groupe_management_component.html.haml rename spec/components/procedures/{routing_rules_component_spec.rb => one_group_management_component_spec.rb} (62%) diff --git a/app/components/procedure/one_groupe_management_component.rb b/app/components/procedure/one_groupe_management_component.rb new file mode 100644 index 000000000..26110487d --- /dev/null +++ b/app/components/procedure/one_groupe_management_component.rb @@ -0,0 +1,65 @@ +class Procedure::OneGroupeManagementComponent < ApplicationComponent + include Logic + + def initialize(revision:, groupe_instructeur:) + @revision = revision + @groupe_instructeur = groupe_instructeur + @procedure_id = revision.procedure_id + end + + private + + def targeted_champ + @groupe_instructeur.routing_rule&.left || empty + end + + def value + @groupe_instructeur.routing_rule&.right || empty + end + + def targeted_champ_tag + select_tag( + 'targeted_champ', + options_for_select(targeted_champs_for_select, selected: targeted_champ.to_json), + class: 'fr-select' + ) + end + + def targeted_champs_for_select + empty_target_for_select + available_targets_for_select + end + + def empty_target_for_select + [[t('.select'), empty.to_json]] + end + + def available_targets_for_select + @revision.types_de_champ_public + .filter { |tdc| [:drop_down_list].include?(tdc.type_champ.to_sym) } + .map { |tdc| [tdc.libelle, champ_value(tdc.stable_id).to_json] } + end + + def value_tag + select_tag( + 'value', + options_for_select( + values_for_select(targeted_champ), + selected: value.to_json + ), + class: 'fr-select' + ) + end + + def values_for_select(targeted_champ) + (empty_target_for_select + available_values_for_select(targeted_champ)) + # add id to help morph render selected option + .map { |(libelle, json)| [libelle, json, { id: "option-#{libelle}" }] } + end + + def available_values_for_select(targeted_champ) + return [] if targeted_champ.is_a?(Logic::Empty) + targeted_champ + .options(@revision.types_de_champ_public) + .map { |tdc| [tdc.first, constant(tdc.first).to_json] } + end +end diff --git a/app/components/procedure/one_groupe_management_component/one_groupe_management_component.fr.yml b/app/components/procedure/one_groupe_management_component/one_groupe_management_component.fr.yml new file mode 100644 index 000000000..cf63e7e03 --- /dev/null +++ b/app/components/procedure/one_groupe_management_component/one_groupe_management_component.fr.yml @@ -0,0 +1,8 @@ +--- +fr: + select: Sélectionner + move_files_confirmation: Réaffecter les dossiers à un autre groupe afin de pouvoir le supprimer + move_files: + zero: Déplacer les dossiers en brouillon + one: Déplacer un dossier + other: Déplacer les %{count} dossiers diff --git a/app/components/procedure/one_groupe_management_component/one_groupe_management_component.html.haml b/app/components/procedure/one_groupe_management_component/one_groupe_management_component.html.haml new file mode 100644 index 000000000..4c8b9ce98 --- /dev/null +++ b/app/components/procedure/one_groupe_management_component/one_groupe_management_component.html.haml @@ -0,0 +1,54 @@ +%div{ id: dom_id(@groupe_instructeur, :routing) } + %h2 Paramètres principaux + + = form_for @groupe_instructeur, + url: { controller: 'administrateurs/groupe_instructeurs', action: :update } do |f| + = f.label :label, 'Nom du groupe', class: 'fr-label fr-mb-1w' + .flex + = f.text_field :label, required: true, class: 'fr-input flex auto fr-mr-2w' + = f.button 'Renommer', class: 'fr-btn fr-btn--secondary' + + = form_for @groupe_instructeur, + url: admin_procedure_groupe_instructeur_update_state_path(@procedure_id, @groupe_instructeur), + method: :patch, + data: { turbo: true, controller: 'autosubmit' } do |f| + .fr-checkbox-group.fr-my-3w + = f.check_box :closed, { id: 'closed', "aria-describedby" => "closed-messages", :name => "closed" } + %label.fr-label{ :for => "closed" } + Groupe inactif + %span.fr-hint-text Si cette option est activée, les usagers ne pourront plus sélectionner ce groupe d'instructeurs + + = form_tag admin_procedure_routing_rules_path(@procedure_id), + method: :post, + data: { controller: 'autosave' }, + class: 'fr-mb-3w' do + + = hidden_field_tag('groupe_instructeur_id', @groupe_instructeur.id) + + .flex + %p.fr-mb-1w.fr-mr-2w Routage + - if @groupe_instructeur.routing_to_configure? + %p.fr-mb-1w.fr-badge.fr-badge--warning.fr-badge--sm à configurer + + .flex.align-baseline + .fr-mr-2w si le champ + .target.fr-mr-2w + = targeted_champ_tag + .operator.fr-mr-2w est égal à + .value + = value_tag + + %ul.fr-btns-group.fr-btns-group--sm.fr-btns-group--inline.fr-btns-group--icon-right + %li + - if @groupe_instructeur.can_delete? + %p Supprimer le groupe + = button_to admin_procedure_groupe_instructeur_path(@procedure_id, @groupe_instructeur), + class: 'fr-btn fr-btn--tertiary fr-btn--icon-left fr-icon-delete-line', + method: :delete do + Supprimer + - else + = button_to reaffecter_dossiers_admin_procedure_groupe_instructeur_path(@procedure_id, @groupe_instructeur), + class: 'fr-btn fr-btn--tertiary fr-icon-folder-2-line', + title: t('.move_files_confirmation'), + method: :get do + = t('.move_files', count: @groupe_instructeur.dossiers.visible_by_administration.size) diff --git a/app/controllers/administrateurs/groupe_instructeurs_controller.rb b/app/controllers/administrateurs/groupe_instructeurs_controller.rb index af3196a7a..024668ea0 100644 --- a/app/controllers/administrateurs/groupe_instructeurs_controller.rb +++ b/app/controllers/administrateurs/groupe_instructeurs_controller.rb @@ -48,10 +48,7 @@ module Administrateurs def update @groupe_instructeur = groupe_instructeur - if closed_params? && @groupe_instructeur.id == procedure.defaut_groupe_instructeur.id - redirect_to admin_procedure_groupe_instructeur_path(procedure, groupe_instructeur), - alert: "Il est impossible de désactiver le groupe d’instructeurs par défaut." - elsif @groupe_instructeur.update(groupe_instructeur_params) + if @groupe_instructeur.update(groupe_instructeur_params) redirect_to admin_procedure_groupe_instructeur_path(procedure, groupe_instructeur), notice: "Le nom est à présent « #{@groupe_instructeur.label} »." else @@ -64,6 +61,26 @@ module Administrateurs end end + def update_state + @groupe_instructeur = procedure.groupe_instructeurs.find(params[:groupe_instructeur_id]) + + if closed_params? && @groupe_instructeur.id == procedure.defaut_groupe_instructeur.id + redirect_to admin_procedure_groupe_instructeur_path(procedure, @groupe_instructeur), + alert: "Il est impossible de désactiver le groupe d’instructeurs par défaut." + elsif @groupe_instructeur.update(closed: params[:closed]) + state_for_notice = @groupe_instructeur.closed ? 'désactivé' : 'activé' + redirect_to admin_procedure_groupe_instructeur_path(procedure, @groupe_instructeur), + notice: "Le groupe #{@groupe_instructeur.label} est #{state_for_notice}." + else + @procedure = procedure + @instructeurs = paginated_instructeurs + @available_instructeur_emails = available_instructeur_emails + + flash.now[:alert] = @groupe_instructeur.errors.full_messages + render :show + end + end + def destroy @groupe_instructeur = groupe_instructeur @@ -264,7 +281,7 @@ module Administrateurs private def closed_params? - groupe_instructeur_params[:closed] == "1" + params[:closed] == "1" end def procedure @@ -287,7 +304,7 @@ module Administrateurs end def groupe_instructeur_params - params.require(:groupe_instructeur).permit(:label, :closed) + params.require(:groupe_instructeur).permit(:label) end def paginated_groupe_instructeurs diff --git a/app/views/administrateurs/routing/update.turbo_stream.haml b/app/views/administrateurs/routing/update.turbo_stream.haml index 3f00cde9f..d477ee9cf 100644 --- a/app/views/administrateurs/routing/update.turbo_stream.haml +++ b/app/views/administrateurs/routing/update.turbo_stream.haml @@ -1,2 +1,3 @@ -= turbo_stream.replace 'routing-rules', render(Procedure::RoutingRulesComponent.new(revision: @procedure.active_revision, - groupe_instructeurs: @procedure.groupe_instructeurs)) += turbo_stream.replace dom_id(@groupe_instructeur, :routing), + render(Procedure::OneGroupeManagementComponent.new(revision: @procedure.active_revision, + groupe_instructeur: @groupe_instructeur)) diff --git a/config/routes.rb b/config/routes.rb index 802268590..3791adbd2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -522,6 +522,8 @@ Rails.application.routes.draw do resources :mail_templates, only: [:edit, :update, :show] resources :groupe_instructeurs, only: [:index, :show, :create, :update, :destroy] do + patch 'update_state' => 'groupe_instructeurs#update_state' + member do post 'add_instructeur' delete 'remove_instructeur' diff --git a/spec/components/procedures/routing_rules_component_spec.rb b/spec/components/procedures/one_group_management_component_spec.rb similarity index 62% rename from spec/components/procedures/routing_rules_component_spec.rb rename to spec/components/procedures/one_group_management_component_spec.rb index 76478fbf2..d412e637a 100644 --- a/spec/components/procedures/routing_rules_component_spec.rb +++ b/spec/components/procedures/one_group_management_component_spec.rb @@ -1,4 +1,4 @@ -describe Procedure::RoutingRulesComponent, type: :component do +describe Procedure::OneGroupeManagementComponent, type: :component do include Logic describe 'render' do @@ -9,16 +9,7 @@ describe Procedure::RoutingRulesComponent, type: :component do subject do render_inline(described_class.new(revision: procedure.active_revision, - groupe_instructeurs: procedure.groupe_instructeurs)) - end - - context 'when there are no types de champ that can be routed' do - before do - procedure.publish_revision! - procedure.reload - subject - end - it { expect(page).to have_text('Ajoutez ce champ dans la page') } + groupe_instructeur: procedure.defaut_groupe_instructeur)) end context 'when there are types de champ that can be routed' do @@ -32,7 +23,7 @@ describe Procedure::RoutingRulesComponent, type: :component do procedure.reload subject end - it { expect(page).to have_text('Router vers') } + it { expect(page).to have_text('à configurer') } end end end From f61498693ad4295cae7c16e721bb2adf239e4c55 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Tue, 9 May 2023 14:36:20 +0200 Subject: [PATCH 11/28] use routable_type_de_champ --- app/components/procedure/one_groupe_management_component.rb | 4 ++-- app/models/procedure_revision.rb | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/components/procedure/one_groupe_management_component.rb b/app/components/procedure/one_groupe_management_component.rb index 26110487d..a5fe5ef20 100644 --- a/app/components/procedure/one_groupe_management_component.rb +++ b/app/components/procedure/one_groupe_management_component.rb @@ -34,8 +34,8 @@ class Procedure::OneGroupeManagementComponent < ApplicationComponent end def available_targets_for_select - @revision.types_de_champ_public - .filter { |tdc| [:drop_down_list].include?(tdc.type_champ.to_sym) } + @revision + .routable_types_de_champ .map { |tdc| [tdc.libelle, champ_value(tdc.stable_id).to_json] } end diff --git a/app/models/procedure_revision.rb b/app/models/procedure_revision.rb index 02ef041fe..0de68a045 100644 --- a/app/models/procedure_revision.rb +++ b/app/models/procedure_revision.rb @@ -236,6 +236,10 @@ class ProcedureRevision < ApplicationRecord [coordinate, coordinate&.type_de_champ] end + def routable_types_de_champ + types_de_champ_public.filter { |tdc| [:drop_down_list].include?(tdc.type_champ.to_sym) } + end + private def compute_estimated_fill_duration From 11a166aa51f38daf1470762eb813be59d67b9a83 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Mon, 24 Apr 2023 15:48:52 +0200 Subject: [PATCH 12/28] add group_ajout_component --- .../procedure/groupes_ajout_component.rb | 6 ++++++ .../groupes_ajout_component.fr.yml | 6 ++++++ .../groupes_ajout_component.html.haml | 15 +++++++++++++++ .../instructeurs_management_component.rb | 9 +++++++++ .../instructeurs_management_component.html.haml | 13 +++++++++++++ .../one_groupe_management_component.html.haml | 3 ++- 6 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 app/components/procedure/groupes_ajout_component.rb create mode 100644 app/components/procedure/groupes_ajout_component/groupes_ajout_component.fr.yml create mode 100644 app/components/procedure/groupes_ajout_component/groupes_ajout_component.html.haml create mode 100644 app/components/procedure/instructeurs_management_component.rb create mode 100644 app/components/procedure/instructeurs_management_component/instructeurs_management_component.html.haml diff --git a/app/components/procedure/groupes_ajout_component.rb b/app/components/procedure/groupes_ajout_component.rb new file mode 100644 index 000000000..8e82afb6c --- /dev/null +++ b/app/components/procedure/groupes_ajout_component.rb @@ -0,0 +1,6 @@ +class Procedure::GroupesAjoutComponent < ApplicationComponent + def initialize(procedure:, groupe_instructeurs:) + @procedure = procedure + @groupe_instructeurs = groupe_instructeurs + end +end diff --git a/app/components/procedure/groupes_ajout_component/groupes_ajout_component.fr.yml b/app/components/procedure/groupes_ajout_component/groupes_ajout_component.fr.yml new file mode 100644 index 000000000..9b4e48456 --- /dev/null +++ b/app/components/procedure/groupes_ajout_component/groupes_ajout_component.fr.yml @@ -0,0 +1,6 @@ +--- +fr: + add_a_group: + title: Nouveau groupe + button: + add_group: Ajouter diff --git a/app/components/procedure/groupes_ajout_component/groupes_ajout_component.html.haml b/app/components/procedure/groupes_ajout_component/groupes_ajout_component.html.haml new file mode 100644 index 000000000..77d97761f --- /dev/null +++ b/app/components/procedure/groupes_ajout_component/groupes_ajout_component.html.haml @@ -0,0 +1,15 @@ +- content_for(:title, 'Ajout de groupes') +%h1 Ajout de groupes d'instructeurs + += render partial: 'administrateurs/groupe_instructeurs/import_export', + locals: { procedure: @procedure, + groupe_instructeurs: @groupe_instructeurs } + +%section + = form_for :groupe_instructeur, + method: :post do |f| + = f.label :label, class: 'fr-label fr-mb-1w' do + = t('.add_a_group.title') + .flex.justify-between.align-baseline.fr-mb-1w + = f.text_field :label, required: true, class: 'fr-input', placeholder: 'Entrer un nom de groupe' + = f.button t('.button.add_group'), class: "fr-btn fr-btn fr-btn--secondary fr-btn--icon-right fr-icon-add-line ml-2" diff --git a/app/components/procedure/instructeurs_management_component.rb b/app/components/procedure/instructeurs_management_component.rb new file mode 100644 index 000000000..fc8c76156 --- /dev/null +++ b/app/components/procedure/instructeurs_management_component.rb @@ -0,0 +1,9 @@ +class Procedure::InstructeursManagementComponent < ApplicationComponent + def initialize(procedure:, groupe_instructeur:, instructeurs:, available_instructeur_emails:, disabled_as_super_admin:) + @procedure = procedure + @groupe_instructeur = groupe_instructeur + @instructeurs = instructeurs + @available_instructeur_emails = available_instructeur_emails + @disabled_as_super_admin = disabled_as_super_admin + end +end diff --git a/app/components/procedure/instructeurs_management_component/instructeurs_management_component.html.haml b/app/components/procedure/instructeurs_management_component/instructeurs_management_component.html.haml new file mode 100644 index 000000000..97b8dd077 --- /dev/null +++ b/app/components/procedure/instructeurs_management_component/instructeurs_management_component.html.haml @@ -0,0 +1,13 @@ +- content_for(:title, 'Instructeurs') +%h1 Gestion des instructeurs + += render partial: 'administrateurs/groupe_instructeurs/import_export', + locals: { procedure: @procedure, + groupe_instructeurs: @procedure.groupe_instructeurs } + += render partial: 'administrateurs/groupe_instructeurs/instructeurs', + locals: { procedure: @procedure, + groupe_instructeur: @groupe_instructeur, + instructeurs: @instructeurs, + available_instructeur_emails: @available_instructeur_emails, + disabled_as_super_admin: @disabled_as_super_admin } diff --git a/app/components/procedure/one_groupe_management_component/one_groupe_management_component.html.haml b/app/components/procedure/one_groupe_management_component/one_groupe_management_component.html.haml index 4c8b9ce98..1cbbd231a 100644 --- a/app/components/procedure/one_groupe_management_component/one_groupe_management_component.html.haml +++ b/app/components/procedure/one_groupe_management_component/one_groupe_management_component.html.haml @@ -2,7 +2,8 @@ %h2 Paramètres principaux = form_for @groupe_instructeur, - url: { controller: 'administrateurs/groupe_instructeurs', action: :update } do |f| + url: admin_procedure_groupe_instructeur_path(@procedure_id, @groupe_instructeur), + method: :patch do |f| = f.label :label, 'Nom du groupe', class: 'fr-label fr-mb-1w' .flex = f.text_field :label, required: true, class: 'fr-input flex auto fr-mr-2w' From c77450382c06243c2efdd27ff1bb1077ed5cee25 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Mon, 24 Apr 2023 17:15:35 +0200 Subject: [PATCH 13/28] admin groupe instructeur show : use menu and one groupe management --- app/views/administrateurs/groupe_instructeurs/show.html.haml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/views/administrateurs/groupe_instructeurs/show.html.haml b/app/views/administrateurs/groupe_instructeurs/show.html.haml index e62afa1fd..13f5d1581 100644 --- a/app/views/administrateurs/groupe_instructeurs/show.html.haml +++ b/app/views/administrateurs/groupe_instructeurs/show.html.haml @@ -4,8 +4,9 @@ ['Groupes d’instructeurs', admin_procedure_groupe_instructeurs_path(@procedure)], [@groupe_instructeur.label]] } -.container.groupe-instructeur - = render partial: 'administrateurs/groups_header' += render Procedure::InstructeursMenuComponent.new(procedure: @procedure) do + = render Procedure::OneGroupeManagementComponent.new(revision: @procedure.active_revision, groupe_instructeur: @groupe_instructeur) + = render partial: 'administrateurs/groupe_instructeurs/instructeurs', locals: { procedure: @procedure, groupe_instructeur: @groupe_instructeur, From 6b3447d71ba3cfe76ac45246b846cd1d86427b09 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Wed, 26 Apr 2023 17:31:05 +0200 Subject: [PATCH 14/28] add options --- .../administrateurs/groupe_instructeurs_controller.rb | 6 +++++- .../administrateurs/groupe_instructeurs/options.html.haml | 8 ++++++++ config/routes.rb | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 app/views/administrateurs/groupe_instructeurs/options.html.haml diff --git a/app/controllers/administrateurs/groupe_instructeurs_controller.rb b/app/controllers/administrateurs/groupe_instructeurs_controller.rb index 024668ea0..1ee31a9f2 100644 --- a/app/controllers/administrateurs/groupe_instructeurs_controller.rb +++ b/app/controllers/administrateurs/groupe_instructeurs_controller.rb @@ -19,6 +19,10 @@ module Administrateurs @available_instructeur_emails = available_instructeur_emails end + def options + @procedure = procedure + end + def show @procedure = procedure @groupe_instructeur = groupe_instructeur @@ -210,7 +214,7 @@ module Administrateurs def update_instructeurs_self_management_enabled procedure.update!(instructeurs_self_management_enabled_params) - redirect_to admin_procedure_groupe_instructeurs_path(procedure), + redirect_to options_admin_procedure_groupe_instructeurs_path(procedure), notice: "L’autogestion des instructeurs est #{procedure.instructeurs_self_management_enabled? ? "activée" : "désactivée"}." end diff --git a/app/views/administrateurs/groupe_instructeurs/options.html.haml b/app/views/administrateurs/groupe_instructeurs/options.html.haml new file mode 100644 index 000000000..93945c9e5 --- /dev/null +++ b/app/views/administrateurs/groupe_instructeurs/options.html.haml @@ -0,0 +1,8 @@ += render partial: 'administrateurs/breadcrumbs', + locals: { steps: [[t('.procedures'), admin_procedures_path], + [@procedure.libelle.truncate_words(10), admin_procedure_path(@procedure)], + [(@procedure.groupe_instructeurs.many? ? 'Groupes' : 'Instructeurs'), admin_procedure_groupe_instructeurs_path(@procedure)], + ['Options']] } + += render Procedure::InstructeursMenuComponent.new(procedure: @procedure) do + = render Procedure::InstructeursOptionsComponent.new(procedure: @procedure, state: params[:state]) diff --git a/config/routes.rb b/config/routes.rb index 3791adbd2..dece427fe 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -532,6 +532,7 @@ Rails.application.routes.draw do end collection do + get 'options' patch 'update_routing_criteria_name' patch 'update_instructeurs_self_management_enabled' post 'import' From 8b568c2035b7c1cbecfd5a63258086fddd98e382 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Wed, 26 Apr 2023 17:31:49 +0200 Subject: [PATCH 15/28] add ajout --- .../administrateurs/groupe_instructeurs_controller.rb | 6 ++++++ .../administrateurs/groupe_instructeurs/ajout.html.haml | 8 ++++++++ config/routes.rb | 2 ++ 3 files changed, 16 insertions(+) create mode 100644 app/views/administrateurs/groupe_instructeurs/ajout.html.haml diff --git a/app/controllers/administrateurs/groupe_instructeurs_controller.rb b/app/controllers/administrateurs/groupe_instructeurs_controller.rb index 1ee31a9f2..17d4eb185 100644 --- a/app/controllers/administrateurs/groupe_instructeurs_controller.rb +++ b/app/controllers/administrateurs/groupe_instructeurs_controller.rb @@ -23,6 +23,12 @@ module Administrateurs @procedure = procedure end + def ajout + redirect_to admin_procedure_groupe_instructeurs_path(procedure) if procedure.groupe_instructeurs.one? + @procedure = procedure + @groupes_instructeurs = paginated_groupe_instructeurs + end + def show @procedure = procedure @groupe_instructeur = groupe_instructeur diff --git a/app/views/administrateurs/groupe_instructeurs/ajout.html.haml b/app/views/administrateurs/groupe_instructeurs/ajout.html.haml new file mode 100644 index 000000000..cb089ac1f --- /dev/null +++ b/app/views/administrateurs/groupe_instructeurs/ajout.html.haml @@ -0,0 +1,8 @@ += render partial: 'administrateurs/breadcrumbs', + locals: { steps: [[t('.procedures'), admin_procedures_path], + [@procedure.libelle.truncate_words(10), admin_procedure_path(@procedure)], + [(@procedure.groupe_instructeurs.many? ? 'Groupes' : 'Instructeurs'), admin_procedure_groupe_instructeurs_path(@procedure)], + ['Ajout']] } + += render Procedure::InstructeursMenuComponent.new(procedure: @procedure) do + = render Procedure::GroupesAjoutComponent.new(procedure: @procedure, groupe_instructeurs: @groupes_instructeurs) diff --git a/config/routes.rb b/config/routes.rb index dece427fe..3295661ee 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -533,6 +533,8 @@ Rails.application.routes.draw do collection do get 'options' + get 'ajout' + post 'ajout' => 'groupe_instructeurs#create' patch 'update_routing_criteria_name' patch 'update_instructeurs_self_management_enabled' post 'import' From 01caa498d3d6cfa341bff2c0640f2e87a37fa4b7 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Wed, 26 Apr 2023 17:33:14 +0200 Subject: [PATCH 16/28] add simple_routing --- .../groupe_instructeurs_controller.rb | 33 +++++++++++++++++++ .../simple_routing.html.haml | 27 +++++++++++++++ config/routes.rb | 3 ++ 3 files changed, 63 insertions(+) create mode 100644 app/views/administrateurs/groupe_instructeurs/simple_routing.html.haml diff --git a/app/controllers/administrateurs/groupe_instructeurs_controller.rb b/app/controllers/administrateurs/groupe_instructeurs_controller.rb index 17d4eb185..4c5bbadd5 100644 --- a/app/controllers/administrateurs/groupe_instructeurs_controller.rb +++ b/app/controllers/administrateurs/groupe_instructeurs_controller.rb @@ -1,6 +1,7 @@ module Administrateurs class GroupeInstructeursController < AdministrateurController include ActiveSupport::NumberHelper + include Logic before_action :ensure_not_super_admin!, only: [:add_instructeur] @@ -29,6 +30,38 @@ module Administrateurs @groupes_instructeurs = paginated_groupe_instructeurs end + def simple_routing + @procedure = procedure + end + + def create_simple_routing + @procedure = procedure + stable_id = params[:create_simple_routing][:stable_id].to_i + + tdc = @procedure.active_revision.routable_types_de_champ.find { |tdc| tdc.stable_id == stable_id } + + tdc_options = tdc.options["drop_down_options"].reject(&:empty?) + + tdc_options.each do |option_label| + gi = procedure.groupe_instructeurs.find_by({ label: option_label }) || procedure.groupe_instructeurs + .create({ label: option_label, instructeurs: [current_administrateur.instructeur] }) + gi.update(routing_rule: ds_eq(champ_value(stable_id), constant(gi.label))) + end + + defaut = @procedure.defaut_groupe_instructeur + + if !tdc_options.include?(defaut.label) + new_defaut = @procedure.reload.groupe_instructeurs_but_defaut.first + @procedure.update!(defaut_groupe_instructeur: new_defaut) + reaffecter_all_dossiers_to_defaut_groupe + defaut.instructeurs.each { new_defaut.add(_1) } + defaut.destroy! + end + + flash.notice = 'Les groupes instructeurs ont été ajoutés' + redirect_to admin_procedure_groupe_instructeurs_path(procedure) + end + def show @procedure = procedure @groupe_instructeur = groupe_instructeur diff --git a/app/views/administrateurs/groupe_instructeurs/simple_routing.html.haml b/app/views/administrateurs/groupe_instructeurs/simple_routing.html.haml new file mode 100644 index 000000000..0882440ba --- /dev/null +++ b/app/views/administrateurs/groupe_instructeurs/simple_routing.html.haml @@ -0,0 +1,27 @@ += render partial: 'administrateurs/breadcrumbs', + 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']] } + += 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: 'radio-enabled-submit' }, + url: create_simple_routing_admin_procedure_groupe_instructeurs_path(@procedure) do |f| + + %div{ data: { 'action': "click->radio-enabled-submit#click" } } + .notice + Sélectionner le champ à partir duquel créer des groupes d'instructeurs + - buttons_content = @procedure.active_revision.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) + + %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: { 'radio-enabled-submit-target': 'submit' } } Créer les groupes diff --git a/config/routes.rb b/config/routes.rb index 3295661ee..28feaa1ab 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -535,6 +535,9 @@ Rails.application.routes.draw do get 'options' get 'ajout' post 'ajout' => 'groupe_instructeurs#create' + get 'simple_routing' + post 'create_simple_routing' + delete 'destroy_all_groups_but_defaut' patch 'update_routing_criteria_name' patch 'update_instructeurs_self_management_enabled' post 'import' From 2e1b8b9ef227832f09867ed4980b12b8e0cdb8f3 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Wed, 26 Apr 2023 17:33:49 +0200 Subject: [PATCH 17/28] add import export view --- .../_import_export.html.haml | 28 ++++++++++++++++ .../groupe_instructeurs/en.yml | 33 +++++++++++++------ .../groupe_instructeurs/fr.yml | 30 ++++++++++++----- 3 files changed, 73 insertions(+), 18 deletions(-) create mode 100644 app/views/administrateurs/groupe_instructeurs/_import_export.html.haml diff --git a/app/views/administrateurs/groupe_instructeurs/_import_export.html.haml b/app/views/administrateurs/groupe_instructeurs/_import_export.html.haml new file mode 100644 index 000000000..67ac977e2 --- /dev/null +++ b/app/views/administrateurs/groupe_instructeurs/_import_export.html.haml @@ -0,0 +1,28 @@ +- key = @procedure.groupe_instructeurs.one? ? 'instructeurs' : 'groupes' +%section.fr-accordion.fr-mb-3w + %h3.fr-accordion__title + %button.fr-accordion__btn{ "aria-controls" => "accordion-106", "aria-expanded" => "false" } + = t(".csv_import.#{key}.title") + .fr-collapse#accordion-106 + - csv_max_size = Administrateurs::GroupeInstructeursController::CSV_MAX_SIZE + - if procedure.publiee_or_close? + %p.notice + = t(".csv_import.#{key}.notice_1_html", csv_max_size: number_to_human_size(csv_max_size)) + %p.notice + = t(".csv_import.#{key}.notice_2") + = form_tag import_admin_procedure_groupe_instructeurs_path(@procedure), method: :post, multipart: true, class: "mt-4 form flex justify-between align-center" do + = file_field_tag :csv_file, required: true, accept: 'text/csv', size: "1" + = submit_tag t('.csv_import.import_file'), class: 'fr-btn fr-btn--secondary', data: { disable_with: "Envoi...", confirm: t('.csv_import.import_file_alert') } + - else + %p.mt-4.form.font-weight-bold.mb-2.text-lg + = t(".csv_import.#{key}.title") + %p.notice + = t('.csv_import.import_file_procedure_not_published') + - if groupe_instructeurs.many? + .flex.justify-between.align-center.mt-4 + %div + = t(".existing_groupe", count: groupe_instructeurs.total_count) + = button_to "Exporter au format CSV", + export_groupe_instructeurs_admin_procedure_groupe_instructeurs_path(@procedure, format: :csv), + method: :get, + class: 'fr-btn fr-btn--secondary' diff --git a/config/locales/views/administrateurs/groupe_instructeurs/en.yml b/config/locales/views/administrateurs/groupe_instructeurs/en.yml index 31f04dee5..60f5a0492 100644 --- a/config/locales/views/administrateurs/groupe_instructeurs/en.yml +++ b/config/locales/views/administrateurs/groupe_instructeurs/en.yml @@ -24,6 +24,29 @@ en: assigned_instructeur: one: "%{count} instructor is assigned" other: "%{count} instructors are assigned" + import_export: + csv_import: + import_file: Importer le fichier + import_file_alert: Tous les instructeurs ajoutés à la procédure vont être notifiés par email. Voulez-vous continuer ? + import_file_procedure_not_published: L’import par fichier CSV est disponible une fois la démarche publiée + groupes: + title: Import / Export en masse + notice_1_html: Pour l'import, votre fichier csv doit comporter 2 colonnes (Groupe, Email) et être séparé par des virgules (exemple de fichier). Le poids du fichier doit être inférieur %{csv_max_size}. + notice_2: L’import n’écrase pas les groupes existants. Il permet uniquement d'en ajouter. Pour supprimer un groupe, allez dans la page dédiée et cliquez sur le bouton « Supprimer ». + instructeurs: + title: Import en masse + notice_1_html: Pour l'import, le fichier csv doit comporter 1 seule colonne (Email) avec une adresse email d'instructeur par ligne (exemple de fichier). Le poids du fichier doit être inférieur %{csv_max_size}. + notice_2: L’import n’écrase pas les instructeurs existants. Il permet uniquement d'en ajouter. Pour supprimer un instructeur, cliquez sur le bouton « Retirer ». + existing_groupe: + one: "%{count} groupe existe" + other: "%{count} groupes existent" + groupe: + one: "%{count} groupe" + other: "%{count} groupes" + found: + one: "trouvé" + other: "trouvés" + edit: routing: title: Label of the groups list @@ -39,16 +62,6 @@ en: add_a_group: title: Add a group notice: This group will be a choice from the list "%{routing_criteria_name}" - csv_import: - title: CSV Import - notice_1_html: The csv file must have 1 column with instructors emails(%{instructeurs_link}). For routed procedures, the csv file must have 2 columns (Group, Email) and be separated by commas (%{groupes_link}). The import does not overwrite existing groups and instructors. - notice_2: The size of the file must be less than %{csv_max_size}. - import_file: Import file - import_file_procedure_not_published: The import of instructors by CSV file is available once the process has been published - import_file_alert: Instructors added to the procedure will receive an email. Are you sure you want to continue ?" - link_text: file example - instructeurs_file_path: /csv/import-instructeurs-test.csv - groupes_file_path: /csv/en/import-groupe-test.csv set_up: set up button: add_group: Add group diff --git a/config/locales/views/administrateurs/groupe_instructeurs/fr.yml b/config/locales/views/administrateurs/groupe_instructeurs/fr.yml index dc49c86b6..542597b08 100644 --- a/config/locales/views/administrateurs/groupe_instructeurs/fr.yml +++ b/config/locales/views/administrateurs/groupe_instructeurs/fr.yml @@ -30,6 +30,28 @@ fr: assigned_instructeur: one: "%{count} instructeur est affecté" other: "%{count} instructeurs sont affectés" + import_export: + csv_import: + import_file: Importer le fichier + import_file_alert: Tous les instructeurs ajoutés à la procédure vont être notifiés par email. Voulez-vous continuer ? + import_file_procedure_not_published: L’import par fichier CSV est disponible une fois la démarche publiée + groupes: + title: Import / Export en masse + notice_1_html: Pour l'import, votre fichier csv doit comporter 2 colonnes (Groupe, Email) et être séparé par des virgules (exemple de fichier). Le poids du fichier doit être inférieur %{csv_max_size}. + notice_2: L’import n’écrase pas les groupes existants. Il permet uniquement d'en ajouter. Pour supprimer un groupe, allez dans la page dédiée et cliquez sur le bouton « Supprimer ». + instructeurs: + title: Import en masse + notice_1_html: Pour l'import, le fichier csv doit comporter 1 seule colonne (Email) avec une adresse email d'instructeur par ligne (exemple de fichier). Le poids du fichier doit être inférieur %{csv_max_size}. + notice_2: L’import n’écrase pas les instructeurs existants. Il permet uniquement d'en ajouter. Pour supprimer un instructeur, cliquez sur le bouton « Retirer ». + existing_groupe: + one: "%{count} groupe existe" + other: "%{count} groupes existent" + groupe: + one: "%{count} groupe" + other: "%{count} groupes" + found: + one: "trouvé" + other: "trouvés" edit: routing: title: Libellé de la liste de groupes @@ -46,14 +68,6 @@ fr: title: Ajouter un nom de groupe notice: Ce groupe sera un choix de la liste "%{routing_criteria_name}" csv_import: - title: Importer par CSV - notice_1_html: | - Pour une procédure standard, le fichier csv doit comporter 1 seule colonne (Email) avec une adresse email d'instructeur par ligne (%{instructeurs_link}). - Pour une procédure routée, le fichier doit comporter 2 colonnes (Groupe, Email) et être séparé par des virgules (%{groupes_link}). - notice_2: L’import n’écrase pas les instructeurs existants. Il permet uniquement d'en ajouter. Pour supprimer un instructeur, cliquez sur le bouton « retirer ». Le poids du fichier doit être inférieur %{csv_max_size}. - import_file: Importer le fichier - import_file_procedure_not_published: L’import d’instructeurs par fichier CSV est disponible une fois la démarche publiée - import_file_alert: Tous les instructeurs ajoutés à la procédure vont être informés par email. Voulez-vous continuer ? link_text: exemple de fichier instructeurs_file_path: /csv/import-instructeurs-test.csv groupes_file_path: /csv/fr/import-groupe-test.csv From 526f70f9c0eb54e327961fc911676c2826143e67 Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Thu, 27 Apr 2023 10:10:57 +0200 Subject: [PATCH 18/28] add wizard --- .../groupe_instructeurs_controller.rb | 12 ++++++++++++ .../radio_enabled_submit_controller.tsx | 14 ++++++++++++++ config/routes.rb | 1 + 3 files changed, 27 insertions(+) create mode 100644 app/javascript/controllers/radio_enabled_submit_controller.tsx diff --git a/app/controllers/administrateurs/groupe_instructeurs_controller.rb b/app/controllers/administrateurs/groupe_instructeurs_controller.rb index 4c5bbadd5..2b201e7aa 100644 --- a/app/controllers/administrateurs/groupe_instructeurs_controller.rb +++ b/app/controllers/administrateurs/groupe_instructeurs_controller.rb @@ -62,6 +62,18 @@ module Administrateurs redirect_to admin_procedure_groupe_instructeurs_path(procedure) end + def wizard + if params[:choice][:state] == 'routage_custom' + new_label = procedure.defaut_groupe_instructeur.label + ' bis' + procedure.groupe_instructeurs + .create({ label: new_label, instructeurs: [current_administrateur.instructeur] }) + + redirect_to admin_procedure_groupe_instructeurs_path(procedure) + elsif params[:choice][:state] == 'routage_simple' + redirect_to simple_routing_admin_procedure_groupe_instructeurs_path + end + end + def show @procedure = procedure @groupe_instructeur = groupe_instructeur diff --git a/app/javascript/controllers/radio_enabled_submit_controller.tsx b/app/javascript/controllers/radio_enabled_submit_controller.tsx new file mode 100644 index 000000000..10fe8faf0 --- /dev/null +++ b/app/javascript/controllers/radio_enabled_submit_controller.tsx @@ -0,0 +1,14 @@ +import { Controller } from '@hotwired/stimulus'; + +export class RadioEnabledSubmitController extends Controller { + static targets = ['submit']; + declare readonly submitTarget: HTMLButtonElement; + + click() { + if ( + this.element.querySelectorAll('input[type="radio"]:checked').length > 0 + ) { + this.submitTarget.disabled = false; + } + } +} diff --git a/config/routes.rb b/config/routes.rb index 28feaa1ab..5c15cebf5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -535,6 +535,7 @@ Rails.application.routes.draw do get 'options' get 'ajout' post 'ajout' => 'groupe_instructeurs#create' + patch 'wizard' get 'simple_routing' post 'create_simple_routing' delete 'destroy_all_groups_but_defaut' From 692010fa32b71d77bbf8bd603117eb2b3d5e7a59 Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Thu, 27 Apr 2023 10:11:27 +0200 Subject: [PATCH 19/28] destroy all groups but defaut --- .../groupe_instructeurs_controller.rb | 27 +++++++++++++++++++ app/models/procedure.rb | 4 +++ 2 files changed, 31 insertions(+) diff --git a/app/controllers/administrateurs/groupe_instructeurs_controller.rb b/app/controllers/administrateurs/groupe_instructeurs_controller.rb index 2b201e7aa..2275a3edc 100644 --- a/app/controllers/administrateurs/groupe_instructeurs_controller.rb +++ b/app/controllers/administrateurs/groupe_instructeurs_controller.rb @@ -74,6 +74,19 @@ module Administrateurs end end + def destroy_all_groups_but_defaut + reaffecter_all_dossiers_to_defaut_groupe + procedure.groupe_instructeurs_but_defaut.each(&:destroy!) + procedure.update!(routing_enabled: false, instructeurs_self_management_enabled: false) + procedure.defaut_groupe_instructeur.update!( + routing_rule: nil, + label: GroupeInstructeur::DEFAUT_LABEL, + closed: false + ) + flash.notice = 'Tous les groupes instructeurs ont été supprimés' + redirect_to admin_procedure_groupe_instructeurs_path(procedure) + end + def show @procedure = procedure @groupe_instructeur = groupe_instructeur @@ -149,6 +162,12 @@ module Administrateurs @groupe_instructeur.destroy! if procedure.groupe_instructeurs.active.one? procedure.update!(routing_enabled: false) + procedure.update!(instructeurs_self_management_enabled: false) + procedure.defaut_groupe_instructeur.update!( + routing_rule: nil, + label: GroupeInstructeur::DEFAUT_LABEL, + closed: false + ) routing_notice = " et le routage a été désactivé" end flash[:notice] = "le groupe « #{@groupe_instructeur.label} » a été supprimé#{routing_notice}." @@ -184,6 +203,14 @@ module Administrateurs redirect_to admin_procedure_groupe_instructeurs_path(procedure) end + def reaffecter_all_dossiers_to_defaut_groupe + procedure.groupe_instructeurs_but_defaut.each do |gi| + gi.dossiers.find_each do |dossier| + dossier.assign_to_groupe_instructeur(procedure.defaut_groupe_instructeur, current_administrateur) + end + end + end + def add_instructeur emails = params['emails'].presence || [].to_json emails = JSON.parse(emails).map { EmailSanitizableConcern::EmailSanitizer.sanitize(_1) } diff --git a/app/models/procedure.rb b/app/models/procedure.rb index da8a08558..c80535628 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -738,6 +738,10 @@ class Procedure < ApplicationRecord end end + def groupe_instructeurs_but_defaut + groupe_instructeurs - [defaut_groupe_instructeur] + end + def can_be_deleted_by_administrateur? brouillon? || dossiers.state_en_instruction.empty? end From 25ebfc49281be0890dc837fc154d813d8e14eae3 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Wed, 26 Apr 2023 17:45:11 +0200 Subject: [PATCH 20/28] always set procedure.instructeurs_self_management_enabled to true when routing_enabled? --- .../administrateurs/groupe_instructeurs_controller.rb | 6 ++++-- app/models/groupe_instructeur.rb | 1 + app/models/procedure.rb | 4 ---- app/views/instructeurs/procedures/_header.html.haml | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/app/controllers/administrateurs/groupe_instructeurs_controller.rb b/app/controllers/administrateurs/groupe_instructeurs_controller.rb index 2275a3edc..bc7f1c977 100644 --- a/app/controllers/administrateurs/groupe_instructeurs_controller.rb +++ b/app/controllers/administrateurs/groupe_instructeurs_controller.rb @@ -161,8 +161,10 @@ module Administrateurs else @groupe_instructeur.destroy! if procedure.groupe_instructeurs.active.one? - procedure.update!(routing_enabled: false) - procedure.update!(instructeurs_self_management_enabled: false) + procedure.update!( + routing_enabled: false, + instructeurs_self_management_enabled: false + ) procedure.defaut_groupe_instructeur.update!( routing_rule: nil, label: GroupeInstructeur::DEFAUT_LABEL, diff --git a/app/models/groupe_instructeur.rb b/app/models/groupe_instructeur.rb index 472935dbf..d7771e950 100644 --- a/app/models/groupe_instructeur.rb +++ b/app/models/groupe_instructeur.rb @@ -95,6 +95,7 @@ class GroupeInstructeur < ApplicationRecord def toggle_routing procedure.update!(routing_enabled: procedure.groupe_instructeurs.active.many?) + procedure.update!(instructeurs_self_management_enabled: true) if procedure.routing_enabled? end serialize :routing_rule, LogicSerializer diff --git a/app/models/procedure.rb b/app/models/procedure.rb index c80535628..2e6be92f6 100644 --- a/app/models/procedure.rb +++ b/app/models/procedure.rb @@ -728,10 +728,6 @@ class Procedure < ApplicationRecord revisions.size - 2 end - def instructeurs_self_management? - routing_enabled? || instructeurs_self_management_enabled? - end - def defaut_groupe_instructeur_for_new_dossier if !routing_enabled? || feature_enabled?(:procedure_routage_api) defaut_groupe_instructeur diff --git a/app/views/instructeurs/procedures/_header.html.haml b/app/views/instructeurs/procedures/_header.html.haml index 873864dbf..1a13237bb 100644 --- a/app/views/instructeurs/procedures/_header.html.haml +++ b/app/views/instructeurs/procedures/_header.html.haml @@ -7,7 +7,7 @@ | = link_to t('instructeurs.dossiers.header.banner.statistics'), stats_instructeur_procedure_path(procedure), class: 'header-link' - - if procedure.instructeurs_self_management? + - if procedure.instructeurs_self_management_enabled? | - if can_manage_groupe_instructeurs?(procedure) = link_to t('instructeurs.dossiers.header.banner.instructeurs'), admin_procedure_groupe_instructeurs_path(procedure), class: 'header-link' From 97aac5d5886f7b458f3e31b867d77f2662121182 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Wed, 26 Apr 2023 17:29:47 +0200 Subject: [PATCH 21/28] update tests for rules based routing --- .../groupe_instructeurs_controller_spec.rb | 78 ++++-- .../procedure_groupe_instructeur_spec.rb | 19 +- .../administrateurs/procedure_routing_spec.rb | 48 ---- spec/system/routing/full_scenario_spec.rb | 238 ------------------ .../routing/rules_full_scenario_spec.rb | 104 +++++--- 5 files changed, 136 insertions(+), 351 deletions(-) delete mode 100644 spec/system/administrateurs/procedure_routing_spec.rb delete mode 100644 spec/system/routing/full_scenario_spec.rb diff --git a/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb b/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb index eda4df189..83393eb5b 100644 --- a/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb +++ b/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb @@ -1,8 +1,10 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do render_views + include Logic let(:admin) { create(:administrateur) } let(:procedure) { create(:procedure, :published, :for_individual, administrateurs: [admin]) } + let!(:gi_1_1) { procedure.defaut_groupe_instructeur } let!(:gi_1_2) { procedure.groupe_instructeurs.create(label: 'groupe instructeur 2') } @@ -193,7 +195,6 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do describe '#update' do let(:new_name) { 'nouveau nom du groupe' } - let(:closed_value) { '0' } let!(:procedure_non_routee) { create(:procedure, :published, :for_individual, administrateurs: [admin]) } let!(:gi_1_1) { procedure_non_routee.defaut_groupe_instructeur } @@ -202,7 +203,7 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do params: { procedure_id: procedure_non_routee.id, id: gi_1_1.id, - groupe_instructeur: { label: new_name, closed: closed_value } + groupe_instructeur: { label: new_name } } gi_1_1.reload end @@ -214,18 +215,6 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do expect(flash.notice).to be_present end - context 'when we try do disable the default groupe instructeur' do - let(:closed_value) { '1' } - let!(:gi_1_2) { procedure.groupe_instructeurs.create(label: 'groupe instructeur 2') } - - it do - expect(subject).to redirect_to admin_procedure_groupe_instructeur_path(procedure_non_routee, gi_1_1) - expect(gi_1_1.label).not_to eq(new_name) - expect(gi_1_1.closed).to eq(false) - expect(flash.alert).to eq('Il est impossible de désactiver le groupe d’instructeurs par défaut.') - end - end - context 'when the name is already taken' do let!(:gi_1_2) { procedure_non_routee.groupe_instructeurs.create(label: 'groupe instructeur 2') } let(:new_name) { gi_1_2.label } @@ -237,6 +226,45 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do end end + describe '#update_state' do + let(:closed_value) { '0' } + let!(:procedure_non_routee) { create(:procedure, :published, :for_individual, administrateurs: [admin]) } + let!(:gi_1_1) { procedure_non_routee.defaut_groupe_instructeur } + let!(:gi_1_2) { procedure_non_routee.groupe_instructeurs.create(label: 'groupe instructeur 2') } + + before do + patch :update_state, + params: { + procedure_id: procedure_non_routee.id, + groupe_instructeur_id: group.id, + closed: closed_value + } + group.reload + end + + context 'when we try do disable the default groupe instructeur' do + let(:closed_value) { '1' } + let(:group) { gi_1_1 } + + it do + expect(subject).to redirect_to admin_procedure_groupe_instructeur_path(procedure_non_routee, gi_1_1) + expect(gi_1_1.closed).to eq(false) + expect(flash.alert).to eq('Il est impossible de désactiver le groupe d’instructeurs par défaut.') + end + end + + context 'when we try do disable the second groupe instructeur' do + let(:closed_value) { '1' } + let(:group) { gi_1_2 } + + it do + expect(subject).to redirect_to admin_procedure_groupe_instructeur_path(procedure_non_routee, gi_1_2) + expect(gi_1_2.closed).to eq(true) + expect(flash.notice).to eq('Le groupe groupe instructeur 2 est désactivé.') + end + end + end + describe '#add_instructeur_procedure_non_routee' do # faire la meme chose sur une procedure non routee let(:procedure_non_routee) { create :procedure } @@ -636,4 +664,26 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do it { expect(procedure.reload.routing_criteria_name).to eq('new name !') } end + + describe '#create_simple_routing' do + let!(:procedure3) do + create(:procedure, + types_de_champ_public: [ + { type: :drop_down_list, libelle: 'Votre ville', options: ['Paris', 'Lyon', 'Marseille'] }, + { type: :text, libelle: 'Un champ texte' } + ], + administrateurs: [admin]) + end + + let!(:drop_down_tdc) { procedure3.draft_revision.types_de_champ.first } + + before { post :create_simple_routing, params: { procedure_id: procedure3.id, create_simple_routing: { stable_id: drop_down_tdc.stable_id } } } + + 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(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'))) + end + end end diff --git a/spec/system/administrateurs/procedure_groupe_instructeur_spec.rb b/spec/system/administrateurs/procedure_groupe_instructeur_spec.rb index 3f0716693..c5ac2c33a 100644 --- a/spec/system/administrateurs/procedure_groupe_instructeur_spec.rb +++ b/spec/system/administrateurs/procedure_groupe_instructeur_spec.rb @@ -17,24 +17,7 @@ describe 'Manage procedure instructeurs', js: true do scenario 'it works' do visit admin_procedure_path(procedure) find('#groupe-instructeurs').click - expect(page).to have_css("h1", text: "Gérer les instructeurs et les options d'instruction de « #{procedure.libelle} »") - end - end - - context 'as admin not from manager' do - let(:manager) { false } - - scenario 'can add instructeur' do - visit admin_procedure_groupe_instructeurs_path(procedure) - expect { - fill_in "instructeur_emails", with: create(:instructeur).email - click_on "Affecter" - }.to change { procedure.instructeurs.count }.by(1) - expect { - fill_in "groupe_instructeur_label", with: "Bordeaux" - click_on "Ajouter le groupe" - }.to change { procedure.groupe_instructeurs.count }.by(1) - expect(procedure.reload.routing_enabled).to eq true + expect(page).to have_css("h1", text: "Gestion des instructeurs") end end diff --git a/spec/system/administrateurs/procedure_routing_spec.rb b/spec/system/administrateurs/procedure_routing_spec.rb deleted file mode 100644 index 747de8756..000000000 --- a/spec/system/administrateurs/procedure_routing_spec.rb +++ /dev/null @@ -1,48 +0,0 @@ -describe 'As an administrateur I can manage procedure routing', js: true do - include Logic - - let(:administrateur) { procedure.administrateurs.first } - let!(:gi_1) { procedure.defaut_groupe_instructeur } - let!(:gi_2) { procedure.groupe_instructeurs.create(label: 'a second group') } - let!(:gi_3) { procedure.groupe_instructeurs.create(label: 'a third group') } - - let(:procedure) do - create(:procedure).tap do |p| - p.draft_revision.add_type_de_champ( - type_champ: :drop_down_list, - libelle: 'Un champ choix simple', - options: { "drop_down_other" => "0", "drop_down_options" => ["", "Premier choix", "Deuxième choix", "Troisième choix"] } - ) - end - end - - let(:drop_down_tdc) { procedure.draft_revision.types_de_champ.first } - - before do - Flipper.enable(:routing_rules, procedure) - procedure.publish_revision! - login_as administrateur.user, scope: :user - end - - it 'routes from a drop_down_list' do - visit admin_procedure_groupe_instructeurs_path(procedure) - - within('.condition-table tbody tr:nth-child(1)', match: :first) do - expect(page).to have_select('targeted_champ', options: ['Sélectionner', 'Un champ choix simple']) - within('.target') { select('Un champ choix simple') } - within('.value') { select('Premier choix') } - end - - expected_routing_rule = ds_eq(champ_value(drop_down_tdc.stable_id), constant('Premier choix')) - wait_until { gi_2.reload.routing_rule == expected_routing_rule } - end - - it 'displays groupes instructeurs by alphabetic order' do - visit admin_procedure_groupe_instructeurs_path(procedure) - - within('.condition-table tbody tr:nth-child(1)', match: :first) do - expect(page).to have_content 'second group' - expect(page).not_to have_content 'défaut' - end - end -end diff --git a/spec/system/routing/full_scenario_spec.rb b/spec/system/routing/full_scenario_spec.rb deleted file mode 100644 index a6f27891f..000000000 --- a/spec/system/routing/full_scenario_spec.rb +++ /dev/null @@ -1,238 +0,0 @@ -describe 'The routing', js: true do - let(:password) { 'a very complicated password' } - let(:procedure) { create(:procedure, :with_type_de_champ, :with_service, :for_individual, :with_zone) } - let(:administrateur) { create(:administrateur, procedures: [procedure]) } - let(:scientifique_user) { create(:user, password: password) } - let(:litteraire_user) { create(:user, password: password) } - - before do - procedure.update(routing_enabled: true) - procedure.defaut_groupe_instructeur.instructeurs << administrateur.instructeur - end - - scenario 'works' do - login_as administrateur.user, scope: :user - visit admin_procedure_path(procedure.id) - find('#groupe-instructeurs').click - - # add littéraire groupe - fill_in 'Ajouter un nom de groupe', with: 'littéraire' - click_on 'Ajouter le groupe' - expect(page).to have_text('Le groupe d’instructeurs « littéraire » a été créé et le routage a été activé.') - - # add victor to littéraire groupe - fill_in 'Emails', with: 'victor@inst.com' - perform_enqueued_jobs { click_on 'Affecter' } - expect(page).to have_text("L’instructeur victor@inst.com a été affecté") - - victor = User.find_by(email: 'victor@inst.com').instructeur - - # add superwoman to littéraire groupe - fill_in 'Emails', with: 'superwoman@inst.com' - perform_enqueued_jobs { click_on 'Affecter' } - expect(page).to have_text("L’instructeur superwoman@inst.com a été affecté") - - superwoman = User.find_by(email: 'superwoman@inst.com').instructeur - - # rename routing criteria to spécialité - click_on 'Groupes d’instructeurs' - fill_in 'Libellé de la liste de groupes', with: 'spécialité' - click_on 'Renommer' - expect(page).to have_text('Le libellé est maintenant « spécialité ».') - expect(page).to have_field('Libellé de la liste de groupes', with: 'spécialité') - - # add inactive groupe - fill_in 'Ajouter un nom de groupe', with: 'non visible car inactif' - click_on 'Ajouter le groupe' - check "Groupe inactif" - click_on 'Modifier' - - # add scientifique groupe - click_on 'Groupes d’instructeurs' - fill_in 'Ajouter un nom de groupe', with: 'scientifique' - click_on 'Ajouter le groupe' - expect(page).to have_text('Le groupe d’instructeurs « scientifique » a été créé.') - - # add marie to scientifique groupe - fill_in 'Emails', with: 'marie@inst.com' - perform_enqueued_jobs { click_on 'Affecter' } - expect(page).to have_text("L’instructeur marie@inst.com a été affecté") - - marie = User.find_by(email: 'marie@inst.com').instructeur - - # add superwoman to scientifique groupe - fill_in 'Emails', with: 'superwoman@inst.com' - perform_enqueued_jobs { click_on 'Affecter' } - expect(page).to have_text("L’instructeur superwoman@inst.com a été affecté") - - # publish - publish_procedure(procedure) - log_out - - # 2 users fill a dossier in each group - user_send_dossier(scientifique_user, 'scientifique') - user_send_dossier(litteraire_user, 'littéraire') - - # the litteraires instructeurs only manage the litteraires dossiers - register_instructeur_and_log_in(victor.email) - click_on procedure.libelle - expect(page).to have_text(litteraire_user.email) - expect(page).not_to have_text(scientifique_user.email) - - # the search only show litteraires dossiers - fill_in 'q', with: scientifique_user.email - find('.fr-search-bar .fr-btn').click - expect(page).to have_text('0 dossier trouvé') - - fill_in 'q', with: litteraire_user.email - find('.fr-search-bar .fr-btn').click - expect(page).to have_text('1 dossier trouvé') - - ## and the result is clickable - click_on litteraire_user.email - expect(page).to have_current_path(instructeur_dossier_path(procedure, litteraire_user.dossiers.first)) - - # follow the dossier - click_on 'Suivre le dossier' - - log_out - - # the scientifiques instructeurs only manage the scientifiques dossiers - register_instructeur_and_log_in(marie.email) - click_on procedure.libelle - expect(page).not_to have_text(litteraire_user.email) - expect(page).to have_text(scientifique_user.email) - - # follow the dossier - click_on scientifique_user.email - click_on 'Suivre le dossier' - - log_out - - # litteraire_user change its dossier - visit new_user_session_path - sign_in_with litteraire_user.email, password - - click_on litteraire_user.dossiers.first.id.to_s - click_on 'Modifier mon dossier' - - fill_in litteraire_user.dossiers.first.champs_public.first.libelle, with: 'some value' - wait_for_autosave(false) - - click_on 'Déposer les modifications' - - log_out - - # the litteraires instructeurs should have a notification - visit new_user_session_path - sign_in_with victor.user.email, password - - ## on the procedures list - expect(page).to have_current_path(instructeur_procedures_path) - expect(find('.procedure-stats')).to have_css('span.notifications') - - ## on the dossiers list - click_on procedure.libelle - expect(page).to have_current_path(instructeur_procedure_path(procedure)) - expect(find('.tabs')).to have_css('span.notifications') - - ## on the dossier itself - click_on 'suivi' - click_on litteraire_user.email - expect(page).to have_current_path(instructeur_dossier_path(procedure, litteraire_user.dossiers.first)) - expect(page).to have_text('Annotations privées') - expect(find('.tabs')).to have_css('span.notifications') - log_out - - # the scientifiques instructeurs should not have a notification - visit new_user_session_path - sign_in_with marie.user.email, password - - expect(page).to have_current_path(instructeur_procedures_path) - expect(find('.procedure-stats')).not_to have_css('span.notifications') - log_out - - # the instructeurs who belong to scientifique AND litteraire groups manage scientifique and litterraire dossiers - register_instructeur_and_log_in(superwoman.email) - visit instructeur_procedure_path(procedure, params: { statut: 'tous' }) - expect(page).to have_text(litteraire_user.email) - expect(page).to have_text(scientifique_user.email) - - # follow the dossier - click_on scientifique_user.email - click_on 'Suivre le dossier' - - visit instructeur_procedure_path(procedure, params: { statut: 'tous' }) - click_on litteraire_user.email - click_on 'Suivre le dossier' - log_out - - # scientifique_user updates its group - user_update_group(scientifique_user, 'littéraire') - - # the instructeurs who belong to scientifique AND litteraire groups should have a notification - visit new_user_session_path - sign_in_with superwoman.user.email, password - - expect(page).to have_current_path(instructeur_procedures_path) - expect(find('.procedure-stats')).to have_css('span.notifications') - end - - def publish_procedure(procedure) - click_on procedure.libelle - find('#publish-procedure-link').click - fill_in 'lien_site_web', with: 'http://some.website' - click_on 'Publier' - - expect(page).to have_text('Démarche publiée') - end - - def user_send_dossier(user, groupe) - login_as user, scope: :user - visit commencer_path(path: procedure.reload.path) - click_on 'Commencer la démarche' - - choose 'Monsieur' - fill_in 'individual_nom', with: 'Nom' - fill_in 'individual_prenom', with: 'Prenom' - click_button('Continuer') - - select(groupe, from: 'dossier_groupe_instructeur_id') - wait_for_autosave - - click_on 'Déposer le dossier' - expect(page).to have_text('Merci') - - log_out - end - - def user_update_group(user, new_group) - login_as user, scope: :user - visit dossiers_path - click_on user.dossiers.first.id.to_s - click_on "Modifier mon dossier" - expect(page).to have_selector("option", text: "scientifique") - expect(page).not_to have_selector("option", text: "Groupe inactif") - - select(new_group, from: 'dossier_groupe_instructeur_id') - wait_for_autosave(false) - - expect(page).to have_text(new_group) - - click_on 'Déposer les modifications' - - log_out - end - - def register_instructeur_and_log_in(email) - confirmation_email = emails_sent_to(email) - .find { |m| m.subject == 'Activez votre compte instructeur' } - token_params = confirmation_email.body.match(/token=[^"]+/) - - visit "users/activate?#{token_params}" - fill_in :user_password, with: password - click_button 'Définir le mot de passe' - - expect(page).to have_text('Mot de passe enregistré') - end -end diff --git a/spec/system/routing/rules_full_scenario_spec.rb b/spec/system/routing/rules_full_scenario_spec.rb index b643ba225..9abd380d3 100644 --- a/spec/system/routing/rules_full_scenario_spec.rb +++ b/spec/system/routing/rules_full_scenario_spec.rb @@ -23,15 +23,46 @@ describe 'The routing with rules', js: true do procedure.defaut_groupe_instructeur.instructeurs << administrateur.instructeur end - scenario 'works' do - login_as administrateur.user, scope: :user - visit admin_procedure_path(procedure.id) - find('#groupe-instructeurs').click + scenario 'Routage à partir d’un champ' do + steps_to_routing_configuration - # add littéraire groupe - fill_in 'Ajouter un nom de groupe', with: 'littéraire' - click_on 'Ajouter le groupe' - expect(page).to have_text('Le groupe d’instructeurs « littéraire » a été créé et le routage a été activé.') + choose('À partir d’un champ', allow_label_click: true) + click_on 'Continuer' + + expect(page).to have_text('Routage à partir d’un champ') + + choose('Spécialité', allow_label_click: true) + click_on 'Créer les groupes' + + expect(page).to have_text('Gestion des groupes') + expect(page).to have_text('2 groupes') + expect(page).not_to have_text('À configurer') + + click_on 'littéraire' + expect(page).to have_select("targeted_champ", selected: "Spécialité") + expect(page).to have_select("value", selected: "littéraire") + + click_on '2 groupes' + click_on 'scientifique' + + expect(page).to have_select("targeted_champ", selected: "Spécialité") + expect(page).to have_select("value", selected: "scientifique") + end + + scenario 'Routage personnalisé' do + steps_to_routing_configuration + + choose('Avancé', allow_label_click: true) + click_on 'Continuer' + + expect(page).to have_text('Gestion des groupes') + + # update defaut groupe + click_on 'défaut' + expect(page).to have_text('Paramètres principaux') + fill_in 'Nom du groupe', with: 'littéraire' + click_on 'Renommer' + expect(page).to have_text('Le nom est à présent « littéraire ». ') # add victor to littéraire groupe fill_in 'Emails', with: 'victor@inst.com' @@ -48,18 +79,19 @@ describe 'The routing with rules', js: true do superwoman = User.find_by(email: 'superwoman@inst.com').instructeur # add inactive groupe - click_on 'Groupes d’instructeurs' - fill_in 'Ajouter un nom de groupe', with: 'non visible car inactif' - click_on 'Ajouter le groupe' - check "Groupe inactif" - click_on 'Modifier' - - # add scientifique groupe - click_on 'Groupes d’instructeurs' - fill_in 'Ajouter un nom de groupe', with: 'scientifique' - click_on 'Ajouter le groupe' - expect(page).to have_text('Le groupe d’instructeurs « scientifique » a été créé.') + click_on 'Ajout de groupes' + fill_in 'Nouveau groupe', with: 'non visible car inactif' + click_on 'Ajouter' + expect(page).to have_text('Le groupe d’instructeurs « non visible car inactif » a été créé. ') + check("Groupe inactif", allow_label_click: true) + # # add scientifique groupe + click_on '3 groupes' + click_on 'défaut bis' + fill_in 'Nom du groupe', with: 'scientifique' + click_on 'Renommer' + expect(page).to have_text('Le nom est à présent « scientifique ». ') + # # add marie to scientifique groupe fill_in 'Emails', with: 'marie@inst.com' perform_enqueued_jobs { click_on 'Affecter' } @@ -71,24 +103,19 @@ describe 'The routing with rules', js: true do fill_in 'Emails', with: 'superwoman@inst.com' perform_enqueued_jobs { click_on 'Affecter' } expect(page).to have_text("L’instructeur superwoman@inst.com a été affecté") - + # # add routing rules - click_on 'Groupes d’instructeurs' + within('.target') { select('Spécialité') } + within('.value') { select('scientifique') } - h = procedure.groupe_instructeurs.index_by(&:label).transform_values(&:id) + click_on '3 groupes' - within(".gi-#{h['scientifique']}") do - within('.target') { select('Spécialité') } - within('.value') { select('scientifique') } - end + click_on 'littéraire' - within(".gi-#{h['littéraire']}") do - within('.target') { select('Spécialité') } - within('.value') { select('littéraire') } - end + within('.target') { select('Spécialité') } + within('.value') { select('littéraire') } - not_defauts = procedure.groupe_instructeurs.filter { |gi| ['littéraire', 'scientifique'].include?(gi.label) } - not_defauts.each { |gi| wait_until { gi.reload.routing_rule.present? } } + procedure.groupe_instructeurs.where(closed: false).each { |gi| wait_until { gi.reload.routing_rule.present? } } # publish publish_procedure(procedure) @@ -179,7 +206,7 @@ describe 'The routing with rules', js: true do expect(find('.procedure-stats')).not_to have_css('span.notifications') log_out - # the instructeurs who belong to scientifique AND litteraire groups manage scientifique and litterraire dossiers + # the instructeurs who belong to scientifique AND litteraire groups manage scientifique and litteraire dossiers register_instructeur_and_log_in(superwoman.email) visit instructeur_procedure_path(procedure, params: { statut: 'tous' }) expect(page).to have_text(litteraire_user.email) @@ -263,4 +290,15 @@ describe 'The routing with rules', js: true do expect(page).to have_text('Mot de passe enregistré') end + + def steps_to_routing_configuration + login_as administrateur.user, scope: :user + visit admin_procedure_path(procedure.id) + find('#groupe-instructeurs').click + + 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') + end end From 6c188a867d01db1f62acf35eb4ac734588d3f7c8 Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Thu, 27 Apr 2023 09:24:06 +0200 Subject: [PATCH 22/28] run routing engine only at submit --- app/controllers/users/dossiers_controller.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index c8c2b1ff6..36bb97fc1 100644 --- a/app/controllers/users/dossiers_controller.rb +++ b/app/controllers/users/dossiers_controller.rb @@ -179,7 +179,6 @@ module Users errors = submit_dossier_and_compute_errors if errors.blank? - RoutingEngine.compute(@dossier) @dossier.passer_en_construction! @dossier.process_declarative! NotificationMailer.send_en_construction_notification(@dossier).deliver_later @@ -538,9 +537,7 @@ module Users @dossier.assign_to_groupe_instructeur(defaut_groupe_instructeur) end - if !@dossier.procedure.feature_enabled?(:routing_rules) && @dossier.groupe_instructeur.nil? - errors += format_errors(errors: ["Le champ « #{@dossier.procedure.routing_criteria_name} » doit être rempli"]) - end + RoutingEngine.compute(@dossier) errors end From 9004dd9758740258e12d325431eec4e8d78d9312 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Tue, 9 May 2023 14:36:26 +0200 Subject: [PATCH 23/28] remove old logic --- .../procedure/routing_rules_component.rb | 82 ------------------- .../routing_rules_component.fr.yml | 11 --- .../routing_rules_component.html.haml | 40 --------- .../groupe_instructeurs/_edit.html.haml | 67 --------------- .../_instructeurs_self_management.html.haml | 14 ---- .../groupe_instructeurs/_routing.html.haml | 4 - .../groupe_instructeurs/en.yml | 43 ---------- .../groupe_instructeurs/fr.yml | 9 +- 8 files changed, 6 insertions(+), 264 deletions(-) delete mode 100644 app/components/procedure/routing_rules_component.rb delete mode 100644 app/components/procedure/routing_rules_component/routing_rules_component.fr.yml delete mode 100644 app/components/procedure/routing_rules_component/routing_rules_component.html.haml delete mode 100644 app/views/administrateurs/groupe_instructeurs/_edit.html.haml delete mode 100644 app/views/administrateurs/groupe_instructeurs/_instructeurs_self_management.html.haml delete mode 100644 app/views/administrateurs/groupe_instructeurs/_routing.html.haml diff --git a/app/components/procedure/routing_rules_component.rb b/app/components/procedure/routing_rules_component.rb deleted file mode 100644 index bfce00008..000000000 --- a/app/components/procedure/routing_rules_component.rb +++ /dev/null @@ -1,82 +0,0 @@ -class Procedure::RoutingRulesComponent < ApplicationComponent - include Logic - - def initialize(revision:, groupe_instructeurs:) - @revision = revision - @groupe_instructeurs = groupe_instructeurs - @procedure_id = revision.procedure_id - end - - def rows - @groupe_instructeurs.active.map do |gi| - if gi.routing_rule.present? - [gi.routing_rule.left, gi.routing_rule.right, gi] - else - [empty, empty, gi] - end - end - end - - def can_route? - available_targets_for_select.present? - end - - def targeted_champ_tag(targeted_champ, row_index) - select_tag( - 'targeted_champ', - options_for_select(targeted_champs_for_select, selected: targeted_champ.to_json), - id: input_id_for('targeted_champ', row_index) - ) - end - - def value_tag(targeted_champ, value, row_index) - select_tag( - 'value', - options_for_select( - values_for_select(targeted_champ, row_index), - selected: value.to_json - ), - id: input_id_for('value', row_index) - ) - end - - def hidden_groupe_instructeur_tag(groupe_instructeur_id) - hidden_field_tag( - 'groupe_instructeur_id', - groupe_instructeur_id - ) - end - - private - - def targeted_champs_for_select - empty_target_for_select + available_targets_for_select - end - - def empty_target_for_select - [[t('.select'), empty.to_json]] - end - - def available_targets_for_select - @revision.types_de_champ_public - .filter { |tdc| [:drop_down_list].include?(tdc.type_champ.to_sym) } - .map { |tdc| [tdc.libelle, champ_value(tdc.stable_id).to_json] } - end - - def available_values_for_select(targeted_champ) - return [] if targeted_champ.is_a?(Logic::Empty) - targeted_champ - .options(@revision.types_de_champ_public) - .map { |tdc| [tdc.first, constant(tdc.first).to_json] } - end - - def values_for_select(targeted_champ, row_index) - (empty_target_for_select + available_values_for_select(targeted_champ)) - # add id to help morph render selected option - .map { |(libelle, json)| [libelle, json, { id: "#{row_index}-option-#{libelle}" }] } - end - - def input_id_for(name, row_index) - "#{name}-#{row_index}" - end -end diff --git a/app/components/procedure/routing_rules_component/routing_rules_component.fr.yml b/app/components/procedure/routing_rules_component/routing_rules_component.fr.yml deleted file mode 100644 index a7c9426d9..000000000 --- a/app/components/procedure/routing_rules_component/routing_rules_component.fr.yml +++ /dev/null @@ -1,11 +0,0 @@ ---- -fr: - select: Sélectionner - apply_routing_rules: Règles de routage - routing_rules_notice_html: | -

Ajoutez des règles de routage à partir de champs « choix simple » créés dans le formulaire.

-

Les dossiers seront routées vers le premier groupe affiché dont la règle correspond.

- routing_rules_warning_html: | -

Pour appliquer des règles de routage, votre formulaire doit comporter - au moins un champ « choix simple ».

-

Ajoutez ce champ dans la page « Configuration des champs ».

diff --git a/app/components/procedure/routing_rules_component/routing_rules_component.html.haml b/app/components/procedure/routing_rules_component/routing_rules_component.html.haml deleted file mode 100644 index 9d0768031..000000000 --- a/app/components/procedure/routing_rules_component/routing_rules_component.html.haml +++ /dev/null @@ -1,40 +0,0 @@ -.card#routing-rules - %h2.card-title= t('.apply_routing_rules') - - if can_route? - .notice - = t('.routing_rules_notice_html', path: champs_admin_procedure_path(@procedure_id)) - .mt-2.width-100 - %table.routing-rules-table.mt-2.width-100 - %thead - %tr - %th.far-left Router vers - %th.if - %th.target Champ cible du routage - %th.operator - %th.value Valeur - .mt-2.width-100 - - rows.each.with_index do |(targeted_champ, value, groupe_instructeur), row_index| - = form_tag admin_procedure_routing_rules_path(@procedure_id), - method: :post, - class: "form width-100 gi-#{groupe_instructeur.id}", - data: { controller: 'autosave' } do - = hidden_groupe_instructeur_tag(groupe_instructeur.id) - %table.routing-rules-table.condition-table.mt-2.width-100 - %tbody - %tr - %td.far-left= groupe_instructeur.label - %td.if si - %td.target= targeted_champ_tag(targeted_champ, row_index) - %td.operator est égal à - %td.value= value_tag(targeted_champ, value, row_index) - - = form_tag admin_procedure_update_defaut_groupe_instructeur_path(@procedure_id), - class: 'form flex align-baseline defaut-groupe', - data: { controller: 'autosave' } do - = label_tag :defaut_groupe_instructeur_id, 'Et si aucune règle ne correspond, router vers :' - = select_tag :defaut_groupe_instructeur_id, - options_for_select(@groupe_instructeurs.pluck(:label, :id), selected: @revision.procedure.defaut_groupe_instructeur.id), - class: 'width-100' - - - else - .notice= t('.routing_rules_warning_html', path: champs_admin_procedure_path(@procedure_id)) diff --git a/app/views/administrateurs/groupe_instructeurs/_edit.html.haml b/app/views/administrateurs/groupe_instructeurs/_edit.html.haml deleted file mode 100644 index fdf5e95f5..000000000 --- a/app/views/administrateurs/groupe_instructeurs/_edit.html.haml +++ /dev/null @@ -1,67 +0,0 @@ -- if groupes_instructeurs.many? && !procedure.feature_enabled?(:routing_rules) - .card - = form_for procedure, - url: { action: :update_routing_criteria_name }, - html: { class: 'form' } do |f| - - = f.label :routing_criteria_name do - = t('.routing.title') - %p.notice - = f.text_field :routing_criteria_name, required: true - = f.submit t('.button.rename'), class: 'button primary send' - -.card - %h2.card-title= t('.group_management.title') - - = form_for :groupe_instructeur, html: { class: 'form' } do |f| - = f.label :label do - = t('.add_a_group.title') - - if groupes_instructeurs.many? - %p.notice - = t('.add_a_group.notice', routing_criteria_name: procedure.routing_criteria_name) - = f.text_field :label, required: true - = f.submit t('.button.add_group'), class: "button primary send" - - - csv_max_size = Administrateurs::GroupeInstructeursController::CSV_MAX_SIZE - - if procedure.publiee_or_close? - = form_tag import_admin_procedure_groupe_instructeurs_path(procedure), method: :post, multipart: true, class: "mt-4 form" do - = label_tag t('.csv_import.title') - %p.notice - = t('.csv_import.notice_1_html', - instructeurs_link: link_to(t('.csv_import.link_text'), t('.csv_import.instructeurs_file_path')), - groupes_link: link_to(t('.csv_import.link_text'), t('.csv_import.groupes_file_path'))) - %p.notice - = t('.csv_import.notice_2', csv_max_size: number_to_human_size(csv_max_size)) - = file_field_tag :csv_file, required: true, accept: 'text/csv', size: "1" - = submit_tag t('.csv_import.import_file'), class: 'button primary send', data: { disable_with: "Envoi...", confirm: t('.csv_import.import_file_alert') } - - else - %p.mt-4.form.font-weight-bold.mb-2.text-lg - = t('.csv_import.title') - %p.notice - = t('.csv_import.import_file_procedure_not_published') - - if procedure.groupe_instructeurs.many? - %table.table.mt-2 - %thead - %tr - // i18n-tasks-use t('.existing_groupe') - %th{ colspan: 2 }= t(".existing_groupe", count: groupes_instructeurs.total_count) - %th.actions - = link_to "Exporter au format CSV", export_groupe_instructeurs_admin_procedure_groupe_instructeurs_path(procedure, format: :csv) - %tbody - - groupes_instructeurs.each do |group| - %tr - %td= group.label - %td.setup= link_to t('.set_up'), admin_procedure_groupe_instructeur_path(procedure, group) - - if group.can_delete? - %td.actions - = link_to admin_procedure_groupe_instructeur_path(procedure, group), { method: :delete, class: 'button', data: { confirm: t('.group_management.delete_confirmation', group_name: group.label) }} do - %span.icon.delete - = t('.group_management.delete') - - else - %td.actions - = link_to reaffecter_dossiers_admin_procedure_groupe_instructeur_path(procedure, group), class: 'button', title: t('.group_management.move_files_confirmation') do - %span.icon.follow - = t('.group_management.move_files', count: group.dossiers.visible_by_administration.size) - - - = paginate groupes_instructeurs, views_prefix: 'shared' diff --git a/app/views/administrateurs/groupe_instructeurs/_instructeurs_self_management.html.haml b/app/views/administrateurs/groupe_instructeurs/_instructeurs_self_management.html.haml deleted file mode 100644 index 5b85b3504..000000000 --- a/app/views/administrateurs/groupe_instructeurs/_instructeurs_self_management.html.haml +++ /dev/null @@ -1,14 +0,0 @@ -.card - %h2.card-title L’autogestion des instructeurs - %p.notice= t('.self_managment_notice_html') - - = form_for procedure, - method: :patch, - url: update_instructeurs_self_management_enabled_admin_procedure_groupe_instructeurs_path(procedure), - data: { controller: 'autosubmit', turbo: 'true' }, - html: { class: 'form procedure-form__column--form no-background' } do |f| - %label.toggle-switch - = f.check_box :instructeurs_self_management_enabled, class: 'toggle-switch-checkbox' - %span.toggle-switch-control.round - %span.toggle-switch-label.on - %span.toggle-switch-label.off diff --git a/app/views/administrateurs/groupe_instructeurs/_routing.html.haml b/app/views/administrateurs/groupe_instructeurs/_routing.html.haml deleted file mode 100644 index 1530dab59..000000000 --- a/app/views/administrateurs/groupe_instructeurs/_routing.html.haml +++ /dev/null @@ -1,4 +0,0 @@ -.card - %h2.card-title= t('.title') - - %p.notice= t('.notice_html') diff --git a/config/locales/views/administrateurs/groupe_instructeurs/en.yml b/config/locales/views/administrateurs/groupe_instructeurs/en.yml index 60f5a0492..f4690053a 100644 --- a/config/locales/views/administrateurs/groupe_instructeurs/en.yml +++ b/config/locales/views/administrateurs/groupe_instructeurs/en.yml @@ -8,7 +8,6 @@ en: groupe_instructeurs: index: procedures: Procedures - instructors_group: Group of instructors add_instructeur: wrong_address: one: "%{emails} is not a valid email address" @@ -40,45 +39,3 @@ en: existing_groupe: one: "%{count} groupe existe" other: "%{count} groupes existent" - groupe: - one: "%{count} groupe" - other: "%{count} groupes" - found: - one: "trouvé" - other: "trouvés" - - edit: - routing: - title: Label of the groups list - group_management: - title: Group management - delete: delete the group - delete_confirmation: Are you sure you want to delete the group "%{group_name}" - move_files: - zero: move draft files - one: move one file - other: move the %{count} files - move_files_confirmation: Reassign folders to another group so you can delete it - add_a_group: - title: Add a group - notice: This group will be a choice from the list "%{routing_criteria_name}" - set_up: set up - button: - add_group: Add group - rename: Rename - existing_groupe: - one: "%{count} group exist" - other: "%{count} groups exist" - routing: - title: Routing - notice_html: | - Routing is a feature for procedures requiring the sharing of instructions between different groups according to a specific criterion (territory, theme or other). -

- This feature makes it possible to route the files to each group, and to no longer need to filter its files among a large quantity of requests. It is therefore particularly suitable for national approaches instructed locally. -

- Instructors only see the files that concern them, and therefore do not have access to data outside their scope. -

- Routing is activated once there are at least two active instructors groups - instructeurs_self_management: - self_managment_notice_html: | - Instructor Self-Management allows instructors to self-manage the list of Gait Instructors. diff --git a/config/locales/views/administrateurs/groupe_instructeurs/fr.yml b/config/locales/views/administrateurs/groupe_instructeurs/fr.yml index 542597b08..d9ed95496 100644 --- a/config/locales/views/administrateurs/groupe_instructeurs/fr.yml +++ b/config/locales/views/administrateurs/groupe_instructeurs/fr.yml @@ -52,6 +52,12 @@ fr: found: one: "trouvé" other: "trouvés" + ajout: + procedures: Démarches + options: + procedures: Démarches + simple_routing: + procedures: Démarches edit: routing: title: Libellé de la liste de groupes @@ -86,6 +92,3 @@ fr: button: self_managment_toggle: Activer l’autogestion des instructeurs add_group: Ajouter le groupe - instructeurs_self_management: - self_managment_notice_html: | - L’autogestion des instructeurs permet aux instructeurs de gérer eux-mêmes la liste des instructeurs de la démarche. From ba5c64ea843f6cc015e6811cb1860ec628d6b2f1 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Thu, 11 May 2023 15:15:25 +0200 Subject: [PATCH 24/28] a cheap solution ? --- app/graphql/mutations/groupe_instructeur_creer.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/graphql/mutations/groupe_instructeur_creer.rb b/app/graphql/mutations/groupe_instructeur_creer.rb index 465606fe1..4b664572f 100644 --- a/app/graphql/mutations/groupe_instructeur_creer.rb +++ b/app/graphql/mutations/groupe_instructeur_creer.rb @@ -26,6 +26,16 @@ module Mutations .build(label: groupe_instructeur.label, closed: groupe_instructeur.closed, instructeurs: [current_administrateur.instructeur].compact) if groupe_instructeur.save + + # ugly hack to keep retro compatibility + # do not judge + if !ENV['OLD_GROUPE_INSTRUCTEURS_CREATE_API_PROCEDURE_ID'].nil? && demarche_number.in?(ENV['OLD_GROUPE_INSTRUCTEURS_CREATE_API_PROCEDURE_ID']&.split(',')&.map(&:to_i)) + stable_id = procedure.groupe_instructeurs.first.routing_rule.left.stable_id + tdc = procedure.published_revision.types_de_champ.find_by(stable_id: stable_ids) + tdc.update(options: tdc.options['drop_down_options'].push(groupe_instructeur.label)) + groupe_instructeur.update(routing_rule: ds_eq(champ_value(stable_id), constant(groupe_instruteur.label))) + end + result = { groupe_instructeur: } if emails.present? || ids.present? From 6e88c49470853070883dfb99dc9b91f168185bb7 Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Fri, 12 May 2023 10:24:17 +0200 Subject: [PATCH 25/28] remove old logic test --- spec/controllers/users/dossiers_controller_spec.rb | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/spec/controllers/users/dossiers_controller_spec.rb b/spec/controllers/users/dossiers_controller_spec.rb index 27d1ab7a1..2b758ae56 100644 --- a/spec/controllers/users/dossiers_controller_spec.rb +++ b/spec/controllers/users/dossiers_controller_spec.rb @@ -412,16 +412,6 @@ describe Users::DossiersController, type: :controller do it { expect(flash.alert).to eq(["Le champ « l » doit être rempli, #{anchor_to_first_champ}"]) } end - context 'when a dossier is invalid' do - before do - allow_any_instance_of(Dossier).to receive(:groupe_instructeur).and_return(double(nil?: true)) - subject - end - - it { expect(response).to render_template(:brouillon) } - it { expect(flash.alert).to eq(["Le champ « Votre ville » doit être rempli"]) } - end - context 'when dossier has no champ' do let(:submit_payload) { { id: dossier.id } } From 50abf496fd356ba811331b33498fb45d35746fdc Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Mon, 15 May 2023 11:40:03 +0200 Subject: [PATCH 26/28] add warning in gi pages in rule does not match tdc --- app/models/groupe_instructeur.rb | 8 +++- .../groupe_instructeurs_controller_spec.rb | 39 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/app/models/groupe_instructeur.rb b/app/models/groupe_instructeur.rb index d7771e950..a05a85c7c 100644 --- a/app/models/groupe_instructeur.rb +++ b/app/models/groupe_instructeur.rb @@ -88,11 +88,17 @@ class GroupeInstructeur < ApplicationRecord def routing_to_configure? rule = routing_rule - !(rule.is_a?(Logic::Eq) && rule.left.is_a?(Logic::ChampValue) && rule.right.is_a?(Logic::Constant)) + return true if !(rule.is_a?(Logic::Eq) && rule.left.is_a?(Logic::ChampValue) && rule.right.is_a?(Logic::Constant)) + !routing_rule_matches_tdc? end private + def routing_rule_matches_tdc? + routing_tdc = procedure.active_revision.types_de_champ.find_by(stable_id: routing_rule.left.stable_id) + routing_rule.right.value.in?(routing_tdc.options['drop_down_options']) + end + def toggle_routing procedure.update!(routing_enabled: procedure.groupe_instructeurs.active.many?) procedure.update!(instructeurs_self_management_enabled: true) if procedure.routing_enabled? diff --git a/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb b/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb index 83393eb5b..a2318f14e 100644 --- a/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb +++ b/spec/controllers/administrateurs/groupe_instructeurs_controller_spec.rb @@ -60,6 +60,45 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do expect(assigns(:available_instructeur_emails)).to match_array(['instructeur_3@ministere-a.gouv.fr', 'instructeur_4@ministere-b.gouv.fr']) end end + + context 'group without routing rule' do + before { get :show, params: { procedure_id: procedure.id, id: gi_1_1.id } } + + it do + expect(response).to have_http_status(:ok) + expect(response.body).to include('à configurer') + end + end + + context 'group with routing rule matching tdc' do + let!(:drop_down_tdc) { create(:type_de_champ_drop_down_list, procedure: procedure, drop_down_options: options) } + let(:options) { procedure.groupe_instructeurs.pluck(:label) } + + before do + gi_1_1.update(routing_rule: ds_eq(champ_value(drop_down_tdc.stable_id), constant(gi_1_1.label))) + get :show, params: { procedure_id: procedure.id, id: gi_1_1.id } + end + + it do + expect(response).to have_http_status(:ok) + expect(response.body).not_to include('à configurer') + end + end + + context 'group with routing rule not matching tdc' do + let!(:drop_down_tdc) { create(:type_de_champ_drop_down_list, procedure: procedure, drop_down_options: options) } + let(:options) { ['parmesan', 'brie', 'morbier'] } + + before do + gi_1_1.update(routing_rule: ds_eq(champ_value(drop_down_tdc.stable_id), constant(gi_1_1.label))) + get :show, params: { procedure_id: procedure.id, id: gi_1_1.id } + end + + it do + expect(response).to have_http_status(:ok) + expect(response.body).to include('à configurer') + end + end end describe '#create' do From 54fe10ff7654586f6668a7d063ec7c3237762d23 Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Mon, 15 May 2023 15:03:35 +0200 Subject: [PATCH 27/28] add warning in revision change component if tdc options used for routing has been changed --- .../revision_changes_component.fr.yml | 1 + .../revision_changes_component.html.haml | 3 +++ app/models/procedure_revision_change.rb | 1 + app/models/type_de_champ.rb | 1 + 4 files changed, 6 insertions(+) diff --git a/app/components/procedure/revision_changes_component/revision_changes_component.fr.yml b/app/components/procedure/revision_changes_component/revision_changes_component.fr.yml index 9412c067e..6fb5a8df5 100644 --- a/app/components/procedure/revision_changes_component/revision_changes_component.fr.yml +++ b/app/components/procedure/revision_changes_component/revision_changes_component.fr.yml @@ -24,6 +24,7 @@ fr: update_type_champ: Le type du champ « %{label} » a été modifié. Il est maintenant de type « %{to} ». update_piece_justificative_template: Le modèle de pièce justificative du champ « %{label} » a été modifié. update_drop_down_options: "Les options de sélection du champ « %{label} » ont été modifiées :" + update_drop_down_options_alert: "Le champ « %{label} » est utilisé pour le routage des dossiers. Veuillez mettre à jour la configuration des groupes d'instructeurs après avoir publié les modifications." enable_mandatory: Le champ « %{label} » est maintenant obligatoire. disable_mandatory: Le champ « %{label} » n’est plus obligatoire. enable_drop_down_other: Le champ « %{label} » comporte maintenant un choix « Autre ». diff --git a/app/components/procedure/revision_changes_component/revision_changes_component.html.haml b/app/components/procedure/revision_changes_component/revision_changes_component.html.haml index 285dc66e2..8325a5c41 100644 --- a/app/components/procedure/revision_changes_component/revision_changes_component.html.haml +++ b/app/components/procedure/revision_changes_component/revision_changes_component.html.haml @@ -74,6 +74,9 @@ - if !total_dossiers.zero? && !change.can_rebase? .fr-alert.fr-alert--warning.fr-mt-1v %p= t('.breaking_change', count: total_dossiers) + - if removed.present? && change.type_de_champ.used_by_routing_rules? + .fr-alert.fr-alert--warning.fr-mt-1v + = t(".#{prefix}.update_drop_down_options_alert", label: change.label) - when :drop_down_other - if change.from == false - list.with_item do diff --git a/app/models/procedure_revision_change.rb b/app/models/procedure_revision_change.rb index 46f762f32..8079c8cdb 100644 --- a/app/models/procedure_revision_change.rb +++ b/app/models/procedure_revision_change.rb @@ -1,4 +1,5 @@ class ProcedureRevisionChange + attr_reader :type_de_champ def initialize(type_de_champ) @type_de_champ = type_de_champ end diff --git a/app/models/type_de_champ.rb b/app/models/type_de_champ.rb index 324b9f0a3..06acc7907 100644 --- a/app/models/type_de_champ.rb +++ b/app/models/type_de_champ.rb @@ -131,6 +131,7 @@ class TypeDeChamp < ApplicationRecord has_one :procedure, through: :revision delegate :estimated_fill_duration, :estimated_read_duration, :tags_for_template, :libelle_for_export, to: :dynamic_type + delegate :used_by_routing_rules?, to: :revision_type_de_champ class WithIndifferentAccess def self.load(options) From e8d687f5e7542b6185b64c4c3bd1f39344e4b555 Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Thu, 25 May 2023 14:53:51 +0200 Subject: [PATCH 28/28] fix(routing): routing engine works even with unconfigured groups --- app/models/routing_engine.rb | 2 +- spec/models/routing_engine_spec.rb | 30 ++++++++++++++----- .../routing/rules_full_scenario_spec.rb | 21 +++++++++---- 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/app/models/routing_engine.rb b/app/models/routing_engine.rb index ca3e9e5ff..b08cc4bf8 100644 --- a/app/models/routing_engine.rb +++ b/app/models/routing_engine.rb @@ -2,7 +2,7 @@ module RoutingEngine def self.compute(dossier) return if !dossier.procedure.feature_enabled?(:routing_rules) - matching_groupe = dossier.procedure.groupe_instructeurs.active.find do |gi| + matching_groupe = dossier.procedure.groupe_instructeurs.active.reject(&:routing_to_configure?).find do |gi| gi.routing_rule&.compute(dossier.champs) end matching_groupe ||= dossier.procedure.defaut_groupe_instructeur diff --git a/spec/models/routing_engine_spec.rb b/spec/models/routing_engine_spec.rb index 36a072720..cf90dddc8 100644 --- a/spec/models/routing_engine_spec.rb +++ b/spec/models/routing_engine_spec.rb @@ -5,12 +5,15 @@ describe RoutingEngine, type: :model do describe '.compute' do let(:procedure) do - create(:procedure).tap do |p| - p.groupe_instructeurs.create(label: 'a second group') - p.groupe_instructeurs.create(label: 'a third group') - end + create(:procedure, + types_de_champ_public: [{ type: :drop_down_list, libelle: 'Votre ville', options: ['Paris', 'Lyon', 'Marseille'] }]).tap do |p| + p.groupe_instructeurs.create(label: 'a second group') + p.groupe_instructeurs.create(label: 'a third group') + end end + let(:drop_down_tdc) { procedure.draft_revision.types_de_champ.first } + let(:dossier) { create(:dossier, procedure:) } let(:defaut_groupe) { procedure.defaut_groupe_instructeur } let(:gi_2) { procedure.groupe_instructeurs.find_by(label: 'a second group') } @@ -34,13 +37,26 @@ describe RoutingEngine, type: :model do it { is_expected.to eq(defaut_groupe) } end - context 'with a matching rules' do - before { gi_2.update(routing_rule: constant(true)) } + context 'with rules not configured yet' do + before do + procedure.groupe_instructeurs.each do |gi| + gi.update(routing_rule: ds_eq(empty, empty)) + end + end + + it { is_expected.to eq(defaut_groupe) } + end + + context 'with a matching rule' do + before do + gi_2.update(routing_rule: ds_eq(champ_value(drop_down_tdc.stable_id), constant('Lyon'))) + dossier.champs.first.update(value: 'Lyon') + end it { is_expected.to eq(gi_2) } end - context 'with a closed gi with a matching rules' do + context 'with a closed gi with a matching rule' do before { gi_2.update(routing_rule: constant(true), closed: true) } it { is_expected.to eq(defaut_groupe) } diff --git a/spec/system/routing/rules_full_scenario_spec.rb b/spec/system/routing/rules_full_scenario_spec.rb index 9abd380d3..93b487e10 100644 --- a/spec/system/routing/rules_full_scenario_spec.rb +++ b/spec/system/routing/rules_full_scenario_spec.rb @@ -10,13 +10,14 @@ describe 'The routing with rules', js: true do p.draft_revision.add_type_de_champ( type_champ: :drop_down_list, libelle: 'Spécialité', - options: { "drop_down_other" => "0", "drop_down_options" => ["", "littéraire", "scientifique"] } + options: { "drop_down_other" => "0", "drop_down_options" => ["", "littéraire", "scientifique", "artistique"] } ) end end let(:administrateur) { create(:administrateur, procedures: [procedure]) } let(:scientifique_user) { create(:user, password: password) } let(:litteraire_user) { create(:user, password: password) } + let(:artistique_user) { create(:user, password: password) } before do Flipper.enable(:routing_rules, procedure) @@ -35,14 +36,14 @@ describe 'The routing with rules', js: true do click_on 'Créer les groupes' expect(page).to have_text('Gestion des groupes') - expect(page).to have_text('2 groupes') + expect(page).to have_text('3 groupes') expect(page).not_to have_text('À configurer') click_on 'littéraire' expect(page).to have_select("targeted_champ", selected: "Spécialité") expect(page).to have_select("value", selected: "littéraire") - click_on '2 groupes' + click_on '3 groupes' click_on 'scientifique' expect(page).to have_select("targeted_champ", selected: "Spécialité") @@ -91,7 +92,7 @@ describe 'The routing with rules', js: true do fill_in 'Nom du groupe', with: 'scientifique' click_on 'Renommer' expect(page).to have_text('Le nom est à présent « scientifique ». ') - # + # add marie to scientifique groupe fill_in 'Emails', with: 'marie@inst.com' perform_enqueued_jobs { click_on 'Affecter' } @@ -103,7 +104,7 @@ describe 'The routing with rules', js: true do fill_in 'Emails', with: 'superwoman@inst.com' perform_enqueued_jobs { click_on 'Affecter' } expect(page).to have_text("L’instructeur superwoman@inst.com a été affecté") - # + # add routing rules within('.target') { select('Spécialité') } within('.value') { select('scientifique') } @@ -117,13 +118,21 @@ describe 'The routing with rules', js: true do procedure.groupe_instructeurs.where(closed: false).each { |gi| wait_until { gi.reload.routing_rule.present? } } + # add a group without routing rules + click_on 'Ajout de groupes' + fill_in 'Nouveau groupe', with: 'artistique' + click_on 'Ajouter' + expect(page).to have_text('Le groupe d’instructeurs « artistique » a été créé. ') + expect(procedure.groupe_instructeurs.count).to eq(4) + # publish publish_procedure(procedure) log_out - # 2 users fill a dossier in each group + # 3 users fill a dossier in each group user_send_dossier(scientifique_user, 'scientifique') user_send_dossier(litteraire_user, 'littéraire') + user_send_dossier(artistique_user, 'artistique') # the litteraires instructeurs only manage the litteraires dossiers register_instructeur_and_log_in(victor.email)