From 1268f323cb080cedfed61fcac4b1d698910352f6 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Sat, 26 Oct 2024 21:14:05 +0200 Subject: [PATCH] move filter button to component and use plug it to new route --- .../instructeurs/filter_buttons_component.rb | 47 ++++++++++ .../_dossiers_filter_tags.html.haml | 17 ---- .../instructeurs/procedures/show.html.haml | 2 +- .../filter_buttons_component_spec.rb | 88 +++++++++++++++++++ spec/models/procedure_presentation_spec.rb | 38 -------- 5 files changed, 136 insertions(+), 56 deletions(-) create mode 100644 app/components/instructeurs/filter_buttons_component.rb delete mode 100644 app/views/instructeurs/procedures/_dossiers_filter_tags.html.haml create mode 100644 spec/components/instructeurs/filter_buttons_component_spec.rb diff --git a/app/components/instructeurs/filter_buttons_component.rb b/app/components/instructeurs/filter_buttons_component.rb new file mode 100644 index 000000000..960b67b4e --- /dev/null +++ b/app/components/instructeurs/filter_buttons_component.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +class Instructeurs::FilterButtonsComponent < ApplicationComponent + def initialize(filters:, procedure_presentation:, statut:) + @filters = filters + @procedure_presentation = procedure_presentation + @statut = statut + end + + def call + safe_join(filters_by_family, ' et ') + end + + private + + def filters_by_family + @filters + .group_by { _1.column.id } + .values + .map { |group| group.map { |f| filter_form(f) } } + .map { |group| safe_join(group, ' ou ') } + end + + def filter_form(filter) + form_with(model: [:instructeur, @procedure_presentation], class: 'inline') do + safe_join([ + hidden_field_tag('filters[]', ''), # to ensure the filters is not empty + *other_hidden_fields(filter), # other filters to keep + hidden_field_tag('statut', @statut), # collection to set + button_tag(button_content(filter), class: 'fr-tag fr-tag--dismiss fr-my-1w') + ]) + end + end + + def other_hidden_fields(filter) + @filters.reject { _1 == filter }.flat_map do |f| + [ + hidden_field_tag("filters[][id]", f.column.id), + hidden_field_tag("filters[][filter]", f.filter) + ] + end + end + + def button_content(filter) + "#{filter.column.label.truncate(50)} : #{@procedure_presentation.human_value_for_filter(filter)}" + end +end diff --git a/app/views/instructeurs/procedures/_dossiers_filter_tags.html.haml b/app/views/instructeurs/procedures/_dossiers_filter_tags.html.haml deleted file mode 100644 index b8673ed2f..000000000 --- a/app/views/instructeurs/procedures/_dossiers_filter_tags.html.haml +++ /dev/null @@ -1,17 +0,0 @@ -- if current_filters.count > 0 - .fr-mb-2w - - current_filters.group_by { |filter| filter.column.table }.each_with_index do |(table, filters), i| - - if i > 0 - = " et " - - filters.each_with_index do |filter, i| - - if i > 0 - = " ou " - = form_tag(add_filter_instructeur_procedure_path(procedure), class: 'inline') do - - prefix = procedure_presentation.filters_name_for(statut) - = hidden_field_tag "#{prefix}[]", '' - - (current_filters - [filter]).each do |f| - = hidden_field_tag "#{prefix}[][id]", f.column.id - = hidden_field_tag "#{prefix}[][filter]", f.filter - - = button_tag "#{filter.column.label.truncate(50)} : #{procedure_presentation.human_value_for_filter(filter)}", - class: 'fr-tag fr-tag--dismiss fr-my-1w' diff --git a/app/views/instructeurs/procedures/show.html.haml b/app/views/instructeurs/procedures/show.html.haml index a7dd1e0a3..e36560e88 100644 --- a/app/views/instructeurs/procedures/show.html.haml +++ b/app/views/instructeurs/procedures/show.html.haml @@ -70,7 +70,7 @@ = render Dossiers::ExportDropdownComponent.new(procedure: @procedure, export_templates: current_instructeur.export_templates_for(@procedure), statut: @statut, count: @dossiers_count, class_btn: 'fr-btn--tertiary', export_url: method(:download_export_instructeur_procedure_path)) - if @filtered_sorted_paginated_ids.present? || @current_filters.count > 0 - = render partial: "dossiers_filter_tags", locals: { procedure: @procedure, procedure_presentation: @procedure_presentation, current_filters: @current_filters, statut: @statut } + = render Instructeurs::FilterButtonsComponent.new(filters: @current_filters, procedure_presentation: @procedure_presentation, statut: @statut) - batch_operation_component = Dossiers::BatchOperationComponent.new(statut: @statut, procedure: @procedure) diff --git a/spec/components/instructeurs/filter_buttons_component_spec.rb b/spec/components/instructeurs/filter_buttons_component_spec.rb new file mode 100644 index 000000000..e022bc150 --- /dev/null +++ b/spec/components/instructeurs/filter_buttons_component_spec.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true + +describe Instructeurs::FilterButtonsComponent, type: :component do + let(:component) { described_class.new(filters:, procedure_presentation:, statut:) } + let(:instructeur) { create(:instructeur) } + let(:assign_to) { create(:assign_to, procedure:, instructeur:) } + let(:procedure_presentation) { create(:procedure_presentation, assign_to: assign_to) } + let(:statut) { 'tous' } + let(:filters) { [filter] } + + def to_filter((label, filter)) = FilteredColumn.new(column: procedure.find_column(label: label), filter: filter) + + before { render_inline(component) } + + describe "visible text" do + let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :text }]) } + let(:first_type_de_champ) { procedure.active_revision.types_de_champ_public.first } + let(:filter) { to_filter([first_type_de_champ.libelle, "true"]) } + + context 'when type_de_champ text' do + it 'should passthrough value' do + expect(page).to have_text("true") + end + end + + context 'when type_de_champ yes_no' do + let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :yes_no }]) } + + it 'should transform value' do + expect(page).to have_text("oui") + end + end + + context 'when filter is state' do + let(:filter) { to_filter(['État du dossier', "en_construction"]) } + + it 'should get i18n value' do + expect(page).to have_text("En construction") + end + end + + context 'when filter is a date' do + let(:filter) { to_filter(['Date de création', "15/06/2023"]) } + + it 'should get formatted value' do + expect(page).to have_text("15/06/2023") + end + end + + context 'when there are multiple filters' do + let(:filters) do + [ + to_filter(['État du dossier', "en_construction"]), + to_filter(['État du dossier', "en_instruction"]), + to_filter(['Date de création', "15/06/2023"]) + ] + end + + it 'should display all filters' do + text = "État du dossier : En construction ou État du dossier : En instruction et Date de création : 15/06/2023" + expect(page).to have_text(text) + end + end + end + + describe "hidden inputs" do + let(:procedure) { create(:procedure) } + + context 'with 2 filters' do + let(:en_construction_filter) { to_filter(['État du dossier', "en_construction"]) } + let(:en_instruction_filter) { to_filter(['État du dossier', "en_instruction"]) } + let(:column_id) { procedure.find_column(label: 'État du dossier').id } + let(:filters) { [en_construction_filter, en_instruction_filter] } + + it 'should have the necessary inputs' do + expect(page).to have_field('statut', with: 'tous', type: 'hidden') + + expect(page.all('form').count).to eq(2) + + del_en_construction = page.all('form').first + expect(del_en_construction).to have_text('En construction') + expect(del_en_construction).to have_field('filters[]', with: '', type: 'hidden') + expect(del_en_construction).to have_field('filters[][id]', with: column_id, type: 'hidden') + expect(del_en_construction).to have_field('filters[][filter]', with: 'en_instruction', type: 'hidden') + end + end + end +end diff --git a/spec/models/procedure_presentation_spec.rb b/spec/models/procedure_presentation_spec.rb index 821204a3c..36c4197d3 100644 --- a/spec/models/procedure_presentation_spec.rb +++ b/spec/models/procedure_presentation_spec.rb @@ -55,44 +55,6 @@ describe ProcedurePresentation do end end - describe "#human_value_for_filter" do - let(:filtered_column) { to_filter([first_type_de_champ.libelle, "true"]) } - - subject do - procedure_presentation.human_value_for_filter(filtered_column) - end - - context 'when type_de_champ text' do - it 'should passthrough value' do - expect(subject).to eq("true") - end - end - - context 'when type_de_champ yes_no' do - let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :yes_no }]) } - - it 'should transform value' do - expect(subject).to eq("oui") - end - end - - context 'when filter is state' do - let(:filtered_column) { to_filter(['État du dossier', "en_construction"]) } - - it 'should get i18n value' do - expect(subject).to eq("En construction") - end - end - - context 'when filter is a date' do - let(:filtered_column) { to_filter(['Date de création', "15/06/2023"]) } - - it 'should get formatted value' do - expect(subject).to eq("15/06/2023") - end - end - end - describe '#update_displayed_fields' do let(:en_construction_column) { procedure.find_column(label: 'Date de passage en construction') } let(:mise_a_jour_column) { procedure.find_column(label: 'Date du dernier évènement') }