From fd2e253ebc3f051efb7bfb44c93d357d075c65c6 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Tue, 12 Mar 2024 14:28:19 +0100 Subject: [PATCH 1/2] refactor(champs): use ViewableChamp::SectionComponent --- app/views/instructeurs/dossiers/print.html.haml | 4 ++-- app/views/shared/dossiers/_champs.html.haml | 1 - app/views/shared/dossiers/_demande.html.haml | 2 +- spec/views/shared/dossiers/_champs.html.haml_spec.rb | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) delete mode 100644 app/views/shared/dossiers/_champs.html.haml diff --git a/app/views/instructeurs/dossiers/print.html.haml b/app/views/instructeurs/dossiers/print.html.haml index 57815b73f..e10243699 100644 --- a/app/views/instructeurs/dossiers/print.html.haml +++ b/app/views/instructeurs/dossiers/print.html.haml @@ -15,13 +15,13 @@ - types_de_champ_public = @dossier.revision.types_de_champ_public - if types_de_champ_public.any? || @dossier.procedure.routing_enabled? - = render partial: "shared/dossiers/champs", locals: { types_de_champ: types_de_champ_public, dossier: @dossier, demande_seen_at: nil, profile: 'instructeur' } + = render ViewableChamp::SectionComponent.new(types_de_champ: types_de_champ_public, champs_by_stable_id_with_row: @dossier.champs_by_stable_id_with_row, demande_seen_at: nil, profile: 'instructeur') %h2 Annotations privées - types_de_champ_private = @dossier.revision.types_de_champ_private - if types_de_champ_private.any? - = render partial: "shared/dossiers/champs", locals: { types_de_champ: types_de_champ_private, dossier: @dossier, demande_seen_at: nil, profile: 'instructeur' } + = render ViewableChamp::SectionComponent.new(types_de_champ: types_de_champ_private, champs_by_stable_id_with_row: @dossier.champs_by_stable_id_with_row, demande_seen_at: nil, profile: 'instructeur') - else Aucune annotation privée diff --git a/app/views/shared/dossiers/_champs.html.haml b/app/views/shared/dossiers/_champs.html.haml deleted file mode 100644 index 3320f7ca8..000000000 --- a/app/views/shared/dossiers/_champs.html.haml +++ /dev/null @@ -1 +0,0 @@ -= render ViewableChamp::SectionComponent.new(types_de_champ:, champs_by_stable_id_with_row: dossier.champs_by_stable_id_with_row, demande_seen_at:, profile:) diff --git a/app/views/shared/dossiers/_demande.html.haml b/app/views/shared/dossiers/_demande.html.haml index 57b4bf49b..0ce0616ab 100644 --- a/app/views/shared/dossiers/_demande.html.haml +++ b/app/views/shared/dossiers/_demande.html.haml @@ -53,4 +53,4 @@ - types_de_champ = dossier.revision.types_de_champ_public - if types_de_champ.any? || dossier.procedure.routing_enabled? - = render partial: "shared/dossiers/champs", locals: { types_de_champ:, dossier:, demande_seen_at:, profile: } + = render ViewableChamp::SectionComponent.new(types_de_champ:, champs_by_stable_id_with_row: dossier.champs_by_stable_id_with_row, demande_seen_at:, profile:) diff --git a/spec/views/shared/dossiers/_champs.html.haml_spec.rb b/spec/views/shared/dossiers/_champs.html.haml_spec.rb index 322c80db0..aab93a4ef 100644 --- a/spec/views/shared/dossiers/_champs.html.haml_spec.rb +++ b/spec/views/shared/dossiers/_champs.html.haml_spec.rb @@ -15,7 +15,7 @@ describe 'shared/dossiers/champs', type: :view do end end - subject { render 'shared/dossiers/champs', types_de_champ:, dossier:, demande_seen_at:, profile: } + subject { render ViewableChamp::SectionComponent.new(types_de_champ:, dossier:, demande_seen_at:, profile:) } context "there are some champs" do let(:types_de_champ_public) { [{ type: :checkbox }, { type: :header_section }, { type: :explication }, { type: :dossier_link }, { type: :textarea }, { type: :rna }] } From 900db5624feeb5ac8e3c6595e38e41bb0ab9c094 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Thu, 14 Mar 2024 15:13:13 +0100 Subject: [PATCH 2/2] refactor(champs): if champ not found - build it --- .../dossiers/champs_rows_show_component.rb | 14 +++-- .../champs_rows_show_component.html.haml | 9 ++- .../repetition_component.html.haml | 6 +- .../repetition_row_component.rb | 11 ++-- .../repetition_row_component.html.haml | 4 +- .../editable_champ/section_component.rb | 14 ++--- .../viewable_champ/section_component.rb | 24 +++----- .../section_component.html.haml | 4 +- .../champs/repetition_controller.rb | 17 +++++- app/models/champ.rb | 4 +- app/models/champs/header_section_champ.rb | 14 ++--- app/models/champs/repetition_champ.rb | 2 +- app/models/dossier.rb | 10 +++ app/models/type_de_champ.rb | 15 ++++- .../champs/repetition/add.turbo_stream.haml | 2 +- .../instructeurs/dossiers/print.html.haml | 4 +- app/views/root/patron.html.haml | 2 +- app/views/shared/dossiers/_demande.html.haml | 2 +- app/views/shared/dossiers/_edit.html.haml | 2 +- .../dossiers/_edit_annotations.html.haml | 2 +- config/routes.rb | 7 ++- .../editable_champ/section_component_spec.rb | 61 +++++++++---------- spec/factories/procedure.rb | 4 ++ spec/models/dossier_spec.rb | 12 ---- 24 files changed, 128 insertions(+), 118 deletions(-) diff --git a/app/components/dossiers/champs_rows_show_component.rb b/app/components/dossiers/champs_rows_show_component.rb index 45517bc78..d352e9a9b 100644 --- a/app/components/dossiers/champs_rows_show_component.rb +++ b/app/components/dossiers/champs_rows_show_component.rb @@ -3,15 +3,17 @@ class Dossiers::ChampsRowsShowComponent < ApplicationComponent attr_reader :seen_at def initialize(champs:, profile:, seen_at:) - @champs = champs - @seen_at = seen_at - @profile = profile + @champs, @profile, @seen_at = champs, profile, seen_at end - def updated_after_deposer?(champ) - return false if champ.dossier.depose_at.blank? + private - champ.updated_at > champ.dossier.depose_at + def updated_at_after_deposer(champ) + return if champ.dossier.depose_at.blank? + + if champ.updated_at > champ.dossier.depose_at + champ.updated_at + end end def number_with_html_delimiter(num) diff --git a/app/components/dossiers/champs_rows_show_component/champs_rows_show_component.html.haml b/app/components/dossiers/champs_rows_show_component/champs_rows_show_component.html.haml index 83c462630..2ff8db51a 100644 --- a/app/components/dossiers/champs_rows_show_component/champs_rows_show_component.html.haml +++ b/app/components/dossiers/champs_rows_show_component/champs_rows_show_component.html.haml @@ -1,14 +1,13 @@ - each_champ do |champ| - if champ.repetition? - types_de_champ = champ.dossier.revision.children_of(champ.type_de_champ) - - champs_by_stable_id_with_row = champ.dossier.champs_by_stable_id_with_row - - champ.row_ids.each.with_index do |row_id, i| + - champ.row_ids.each.with_index(1) do |row_id, row_number| .fr-background-alt--grey.fr-p-2w.fr-my-3w.fr-ml-2w.champ-repetition - %p.font-weight-bold= "#{champ.libelle} #{i + 1} :" - = render ViewableChamp::SectionComponent.new(types_de_champ:, champs_by_stable_id_with_row:, row_id:, demande_seen_at: seen_at, profile:) + %p.font-weight-bold= "#{champ.libelle} #{row_number} :" + = render ViewableChamp::SectionComponent.new(dossier: champ.dossier, types_de_champ:, row_id:, demande_seen_at: seen_at, profile:) - else - = render Dossiers::RowShowComponent.new(label: champ.libelle, seen_at:, profile:, content_class: champ.type_champ, updated_at: updated_after_deposer?(champ) ? champ.updated_at : nil) do |c| + = render Dossiers::RowShowComponent.new(label: champ.libelle, seen_at:, profile:, content_class: champ.type_champ, updated_at: updated_at_after_deposer(champ)) do |c| - if champ.blank? - c.with_blank do = t(blank_key(champ)) diff --git a/app/components/editable_champ/repetition_component/repetition_component.html.haml b/app/components/editable_champ/repetition_component/repetition_component.html.haml index e2b565d89..4372dfc7b 100644 --- a/app/components/editable_champ/repetition_component/repetition_component.html.haml +++ b/app/components/editable_champ/repetition_component/repetition_component.html.haml @@ -5,9 +5,9 @@ .repetition{ id: dom_id(@champ, :rows) } - - @champ.row_ids.each do |row_id| - = render EditableChamp::RepetitionRowComponent.new(form: @form, champ: @champ, row_id:, seen_at: @seen_at) + - @champ.row_ids.each.with_index(1) do |row_id, row_number| + = render EditableChamp::RepetitionRowComponent.new(form: @form, dossier: @champ.dossier, type_de_champ: @champ.type_de_champ, row_id:, row_number:, seen_at: @seen_at) .actions - = render NestedForms::OwnedButtonComponent.new(formaction: champs_repetition_path(@champ.id), http_method: :create, opt: { class: "fr-btn fr-btn--secondary fr-btn--icon-left fr-icon-add-circle-line fr-mb-3w", title: t(".add_title", libelle: @champ.libelle), id: dom_id(@champ, :create_repetition)}) do + = render NestedForms::OwnedButtonComponent.new(formaction: champs_repetition_path(@champ.dossier, @champ.stable_id), http_method: :create, opt: { class: "fr-btn fr-btn--secondary fr-btn--icon-left fr-icon-add-circle-line fr-mb-3w", title: t(".add_title", libelle: @champ.libelle), id: dom_id(@champ, :create_repetition)}) do = t(".add", libelle: @champ.libelle) diff --git a/app/components/editable_champ/repetition_row_component.rb b/app/components/editable_champ/repetition_row_component.rb index 207d1a241..cb9925286 100644 --- a/app/components/editable_champ/repetition_row_component.rb +++ b/app/components/editable_champ/repetition_row_component.rb @@ -1,10 +1,7 @@ class EditableChamp::RepetitionRowComponent < ApplicationComponent - def initialize(form:, champ:, row_id:, seen_at: nil) - @form, @champ, @row_id, @seen_at = form, champ, row_id, seen_at - - @types_de_champ = champ.dossier.revision.children_of(champ.type_de_champ) - @champs_by_stable_id_with_row = champ.dossier.champs_by_stable_id_with_row - @row_number = champ.row_ids.find_index(row_id) + def initialize(form:, dossier:, type_de_champ:, row_id:, row_number:, seen_at: nil) + @form, @dossier, @type_de_champ, @row_id, @row_number, @seen_at = form, dossier, type_de_champ, row_id, row_number, seen_at + @types_de_champ = dossier.revision.children_of(type_de_champ) end attr_reader :row_id, :row_number @@ -12,6 +9,6 @@ class EditableChamp::RepetitionRowComponent < ApplicationComponent private def section_component - EditableChamp::SectionComponent.new(types_de_champ: @types_de_champ, champs_by_stable_id_with_row: @champs_by_stable_id_with_row, row_id:) + EditableChamp::SectionComponent.new(dossier: @dossier, types_de_champ: @types_de_champ, row_id:) end end diff --git a/app/components/editable_champ/repetition_row_component/repetition_row_component.html.haml b/app/components/editable_champ/repetition_row_component/repetition_row_component.html.haml index df3dc005b..a0498505e 100644 --- a/app/components/editable_champ/repetition_row_component/repetition_row_component.html.haml +++ b/app/components/editable_champ/repetition_row_component/repetition_row_component.html.haml @@ -1,11 +1,11 @@ .row{ id: "safe-row-selector-#{row_id}" } - if @types_de_champ.size > 1 %fieldset - %legend.block-id= "#{@champ.libelle} " + %legend.block-id= "#{@type_de_champ.libelle} " = render section_component - else = render section_component .flex.row-reverse - = render NestedForms::OwnedButtonComponent.new(formaction: champs_repetition_path(@champ.id, row_id:), http_method: :delete, opt: { class: "fr-btn fr-btn--sm fr-btn--tertiary fr-text-action-high--red-marianne", title: t(".delete_title", row_number:)}) do + = render NestedForms::OwnedButtonComponent.new(formaction: champs_repetition_path(@dossier, @type_de_champ.stable_id, row_id:), http_method: :delete, opt: { class: "fr-btn fr-btn--sm fr-btn--tertiary fr-text-action-high--red-marianne", title: t(".delete_title", row_number:)}) do = t(".delete") diff --git a/app/components/editable_champ/section_component.rb b/app/components/editable_champ/section_component.rb index 6a00123cd..69b3c9dcc 100644 --- a/app/components/editable_champ/section_component.rb +++ b/app/components/editable_champ/section_component.rb @@ -2,9 +2,9 @@ class EditableChamp::SectionComponent < ApplicationComponent include ApplicationHelper include TreeableConcern - def initialize(nodes: nil, types_de_champ: nil, row_id: nil, champs_by_stable_id_with_row:) + def initialize(dossier:, nodes: nil, types_de_champ: nil, row_id: nil) nodes ||= to_tree(types_de_champ:) - @champs_by_stable_id_with_row = champs_by_stable_id_with_row + @dossier = dossier @row_id = row_id @nodes = to_fieldset(nodes:) end @@ -15,7 +15,7 @@ class EditableChamp::SectionComponent < ApplicationComponent def header_section node = @nodes.first - champ_for_type_de_champ(node) if node.is_a?(TypeDeChamp) && node.header_section? + @dossier.project_champ(node, @row_id) if node.is_a?(TypeDeChamp) && node.header_section? end def splitted_tail @@ -38,21 +38,17 @@ class EditableChamp::SectionComponent < ApplicationComponent when EditableChamp::SectionComponent [node, nil] else - [nil, champ_for_type_de_champ(node)] + [nil, @dossier.project_champ(node, @row_id)] end end private def to_fieldset(nodes:) - nodes.map { _1.is_a?(Array) ? EditableChamp::SectionComponent.new(nodes: _1, row_id: @row_id, champs_by_stable_id_with_row: @champs_by_stable_id_with_row) : _1 } + nodes.map { _1.is_a?(Array) ? EditableChamp::SectionComponent.new(dossier: @dossier, nodes: _1, row_id: @row_id) : _1 } end def first_champ_is_an_header_section? header_section.present? end - - def champ_for_type_de_champ(type_de_champ) - @champs_by_stable_id_with_row[[@row_id, type_de_champ.stable_id].compact] - end end diff --git a/app/components/viewable_champ/section_component.rb b/app/components/viewable_champ/section_component.rb index c52725c48..24b3c5e47 100644 --- a/app/components/viewable_champ/section_component.rb +++ b/app/components/viewable_champ/section_component.rb @@ -2,25 +2,25 @@ class ViewableChamp::SectionComponent < ApplicationComponent include ApplicationHelper include TreeableConcern - def initialize(nodes: nil, types_de_champ: nil, row_id: nil, demande_seen_at:, profile:, champs_by_stable_id_with_row:) - @demande_seen_at, @profile, @row_id, @champs_by_stable_id_with_row = demande_seen_at, profile, row_id, champs_by_stable_id_with_row + def initialize(dossier:, nodes: nil, types_de_champ: nil, row_id: nil, demande_seen_at:, profile:) + @dossier, @demande_seen_at, @profile, @row_id = dossier, demande_seen_at, profile, row_id nodes ||= to_tree(types_de_champ:) @nodes = to_sections(nodes:) end + private + def section_id @section_id ||= header_section ? dom_id(header_section, :content) : SecureRandom.uuid end def header_section - maybe_header_section = @nodes.first - if maybe_header_section.is_a?(TypeDeChamp) && maybe_header_section.header_section? - champ_for_type_de_champ(maybe_header_section) - end + node = @nodes.first + @dossier.project_champ(node, @row_id) if node.is_a?(TypeDeChamp) && node.header_section? end def champs - tail.filter_map { _1.is_a?(TypeDeChamp) ? champ_for_type_de_champ(_1) : nil } + tail.filter_map { _1.is_a?(TypeDeChamp) ? @dossier.project_champ(_1, @row_id) : nil } end def sections @@ -28,14 +28,14 @@ class ViewableChamp::SectionComponent < ApplicationComponent end def tail - return @nodes if header_section.blank? + return @nodes if header_section.nil? _, *rest_of_champ = @nodes rest_of_champ end def reset_tag_for_depth - return if !header_section + return if header_section.nil? "reset-h#{header_section.level + 1}" end @@ -49,10 +49,6 @@ class ViewableChamp::SectionComponent < ApplicationComponent private def to_sections(nodes:) - nodes.map { _1.is_a?(Array) ? ViewableChamp::SectionComponent.new(nodes: _1, demande_seen_at: @demande_seen_at, profile: @profile, champs_by_stable_id_with_row: @champs_by_stable_id_with_row, row_id: @row_id) : _1 } - end - - def champ_for_type_de_champ(type_de_champ) - @champs_by_stable_id_with_row[[@row_id, type_de_champ.stable_id].compact] + nodes.map { _1.is_a?(Array) ? ViewableChamp::SectionComponent.new(dossier: @dossier, nodes: _1, demande_seen_at: @demande_seen_at, profile: @profile, row_id: @row_id) : _1 } end end diff --git a/app/components/viewable_champ/section_component/section_component.html.haml b/app/components/viewable_champ/section_component/section_component.html.haml index e5453c8a1..86e87b38b 100644 --- a/app/components/viewable_champ/section_component/section_component.html.haml +++ b/app/components/viewable_champ/section_component/section_component.html.haml @@ -1,14 +1,14 @@ = tag.div(class: class_names(reset_tag_for_depth => true, "fr-my-2w" => !first_level?), 'data-controller': 'expand') do - if header_section %div{ class: class_names(flex: true, "top-bordered" => first_level?) } - = render EditableChamp::HeaderSectionComponent.new(champ: header_section, html_class: {' fr-m-0 fr-text--md fr-px-4v flex-grow' => true, "fr-text-action-high--blue-france" => header_section.level == 1, 'fr-py-2w' => first_level?, 'fr-py-1v' => !first_level?}) + = render EditableChamp::HeaderSectionComponent.new(champ: header_section, html_class: { 'fr-m-0 fr-text--md fr-px-4v flex-grow': true, "fr-text-action-high--blue-france fr-py-2w": first_level?, 'fr-py-1v': !first_level? }) - if ![champs, sections].map(&:empty?).all? && first_level? %button{ type: "button", aria: { controls: section_id, "expanded": "true", label: t('.toggle_section', section: header_section.libelle) }, href: section_id, 'data-action': 'click->expand#toggle', class: "fr-btn fr-btn--tertiary-no-outline" } %i.fr-icon-arrow-up-s-line{ 'aria-hidden': 'true', 'data-expand-target': 'icon' } %div{ id: section_id, 'data-expand-target': 'content' } - if !champs.empty? - = render Dossiers::ChampsRowsShowComponent.new(champs: champs, seen_at: @demande_seen_at, profile: @profile) + = render Dossiers::ChampsRowsShowComponent.new(champs:, seen_at: @demande_seen_at, profile: @profile) - sections.each do |section| = render section diff --git a/app/controllers/champs/repetition_controller.rb b/app/controllers/champs/repetition_controller.rb index aabfa3601..27e65b117 100644 --- a/app/controllers/champs/repetition_controller.rb +++ b/app/controllers/champs/repetition_controller.rb @@ -2,16 +2,29 @@ class Champs::RepetitionController < ApplicationController before_action :authenticate_logged_user! def add - @champ = policy_scope(Champ).includes(:champs).find(params[:champ_id]) + @champ = find_champ row = @champ.add_row(@champ.dossier.revision) @first_champ_id = row.map(&:focusable_input_id).compact.first @row_id = row.first&.row_id + @row_number = @champ.row_ids.find_index(@row_id) + 1 end def remove - @champ = policy_scope(Champ).includes(:champs).find(params[:champ_id]) + @champ = find_champ @champ.champs.where(row_id: params[:row_id]).destroy_all @champ.reload @row_id = params[:row_id] end + + private + + def find_champ + if params[:champ_id].present? + policy_scope(Champ).includes(:champs).find(params[:champ_id]) + else + policy_scope(Champ) + .includes(:champs, :type_de_champ) + .find_by!(dossier_id: params[:dossier_id], type_de_champ: { stable_id: params[:stable_id] }) + end + end end diff --git a/app/models/champ.rb b/app/models/champ.rb index 3fcd43563..ebf3fec90 100644 --- a/app/models/champ.rb +++ b/app/models/champ.rb @@ -160,7 +160,7 @@ class Champ < ApplicationRecord end def input_group_id - "champ-#{html_id}" + html_id end def input_id @@ -258,7 +258,7 @@ class Champ < ApplicationRecord end def html_id - "champ-#{stable_id}-#{id}" + row_id.present? ? "champ-#{stable_id}-#{row_id}" : "champ-#{stable_id}" end def needs_dossier_id? diff --git a/app/models/champs/header_section_champ.rb b/app/models/champs/header_section_champ.rb index 27e0c128b..88b232d53 100644 --- a/app/models/champs/header_section_champ.rb +++ b/app/models/champs/header_section_champ.rb @@ -1,14 +1,4 @@ class Champs::HeaderSectionChamp < Champ - def level - if parent.present? - header_section_level_value.to_i + parent.current_section_level(dossier.revision) - elsif header_section_level_value - header_section_level_value.to_i - else - 0 - end - end - def search_terms # The user cannot enter any information here so it doesn’t make much sense to search end @@ -16,4 +6,8 @@ class Champs::HeaderSectionChamp < Champ def libelle_with_section_index? libelle =~ /^\d/ end + + def level + type_de_champ.level_for_revision(dossier.revision) + end end diff --git a/app/models/champs/repetition_champ.rb b/app/models/champs/repetition_champ.rb index ad6a58159..9f424699f 100644 --- a/app/models/champs/repetition_champ.rb +++ b/app/models/champs/repetition_champ.rb @@ -42,7 +42,7 @@ class Champs::RepetitionChamp < Champ def rows_for_export champs = dossier.champs_by_stable_id_with_row - row_ids.each.with_index(1).map do |row_id, index| + row_ids.map.with_index(1) do |row_id, index| Champs::RepetitionChamp::Row.new(index: index, row_id:, dossier_id: dossier_id.to_s, champs:) end end diff --git a/app/models/dossier.rb b/app/models/dossier.rb index ab0dabc22..5d612e4c7 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -1410,6 +1410,16 @@ class Dossier < ApplicationRecord revision.revision_types_de_champ_private.present? end + def project_champ(type_de_champ, row_id) + stable_id_with_row = [row_id, type_de_champ.stable_id].compact + champ = champs.find { _1.stable_id_with_row == stable_id_with_row } + if champ.nil? + type_de_champ.build_champ(dossier: self, row_id:) + else + champ + end + end + private def create_missing_traitemets diff --git a/app/models/type_de_champ.rb b/app/models/type_de_champ.rb index 4dd5b8c4a..fd5bb3db6 100644 --- a/app/models/type_de_champ.rb +++ b/app/models/type_de_champ.rb @@ -145,7 +145,7 @@ class TypeDeChamp < ApplicationRecord has_one :revision, through: :revision_type_de_champ has_one :procedure, through: :revision - delegate :estimated_fill_duration, :estimated_read_duration, :tags_for_template, :libelle_for_export, to: :dynamic_type + delegate :estimated_fill_duration, :estimated_read_duration, :tags_for_template, :libelle_for_export, :primary_options, :secondary_options, to: :dynamic_type delegate :used_by_routing_rules?, to: :revision_type_de_champ class WithIndifferentAccess @@ -167,8 +167,6 @@ class TypeDeChamp < ApplicationRecord attr_reader :dynamic_type - delegate :primary_options, :secondary_options, to: :dynamic_type - scope :public_only, -> { where(private: false) } scope :private_only, -> { where(private: true) } scope :repetition, -> { where(type_champ: type_champs.fetch(:repetition)) } @@ -526,6 +524,17 @@ class TypeDeChamp < ApplicationRecord previous_section_level(tdcs.take(tdcs.find_index(self))) end + def level_for_revision(revision) + rtdc = revision.revision_types_de_champ.find { |rtdc| rtdc.stable_id == stable_id } + if rtdc.child? + header_section_level_value.to_i + rtdc.parent.type_de_champ.current_section_level(revision) + elsif header_section_level_value + header_section_level_value.to_i + else + 0 + end + end + def self.filter_hash_type(type_champ) if is_choice_type_from(type_champ) :enum diff --git a/app/views/champs/repetition/add.turbo_stream.haml b/app/views/champs/repetition/add.turbo_stream.haml index c2c01cabc..94e426678 100644 --- a/app/views/champs/repetition/add.turbo_stream.haml +++ b/app/views/champs/repetition/add.turbo_stream.haml @@ -1,5 +1,5 @@ - if @row_id.present? = fields_for @champ.input_name, @champ do |form| - = turbo_stream.append dom_id(@champ, :rows), render(EditableChamp::RepetitionRowComponent.new(form: form, champ: @champ, row_id: @row_id)) + = turbo_stream.append dom_id(@champ, :rows), render(EditableChamp::RepetitionRowComponent.new(form: form, dossier: @champ.dossier, type_de_champ: @champ.type_de_champ, row_id: @row_id, row_number: @row_number)) - if @first_champ_id = turbo_stream.focus(@first_champ_id) diff --git a/app/views/instructeurs/dossiers/print.html.haml b/app/views/instructeurs/dossiers/print.html.haml index e10243699..11d5bb3b7 100644 --- a/app/views/instructeurs/dossiers/print.html.haml +++ b/app/views/instructeurs/dossiers/print.html.haml @@ -15,13 +15,13 @@ - types_de_champ_public = @dossier.revision.types_de_champ_public - if types_de_champ_public.any? || @dossier.procedure.routing_enabled? - = render ViewableChamp::SectionComponent.new(types_de_champ: types_de_champ_public, champs_by_stable_id_with_row: @dossier.champs_by_stable_id_with_row, demande_seen_at: nil, profile: 'instructeur') + = render ViewableChamp::SectionComponent.new(dossier: @dossier, types_de_champ: types_de_champ_public, demande_seen_at: nil, profile: 'instructeur') %h2 Annotations privées - types_de_champ_private = @dossier.revision.types_de_champ_private - if types_de_champ_private.any? - = render ViewableChamp::SectionComponent.new(types_de_champ: types_de_champ_private, champs_by_stable_id_with_row: @dossier.champs_by_stable_id_with_row, demande_seen_at: nil, profile: 'instructeur') + = render ViewableChamp::SectionComponent.new(dossier: @dossier, types_de_champ: types_de_champ_private, demande_seen_at: nil, profile: 'instructeur') - else Aucune annotation privée diff --git a/app/views/root/patron.html.haml b/app/views/root/patron.html.haml index 4316dfcef..9c51ba6c9 100644 --- a/app/views/root/patron.html.haml +++ b/app/views/root/patron.html.haml @@ -33,7 +33,7 @@ %form.form = form_for @dossier, url: '', html: { class: 'form' } do |f| - = render EditableChamp::SectionComponent.new(types_de_champ: @dossier.revision.types_de_champ_public, champs_by_stable_id_with_row: @dossier.champs_by_stable_id_with_row) + = render EditableChamp::SectionComponent.new(dossier: @dossier, types_de_champ: @dossier.revision.types_de_champ_public) .editable-champ.editable-champ-text %label Mot de passe diff --git a/app/views/shared/dossiers/_demande.html.haml b/app/views/shared/dossiers/_demande.html.haml index 0ce0616ab..fa784d760 100644 --- a/app/views/shared/dossiers/_demande.html.haml +++ b/app/views/shared/dossiers/_demande.html.haml @@ -53,4 +53,4 @@ - types_de_champ = dossier.revision.types_de_champ_public - if types_de_champ.any? || dossier.procedure.routing_enabled? - = render ViewableChamp::SectionComponent.new(types_de_champ:, champs_by_stable_id_with_row: dossier.champs_by_stable_id_with_row, demande_seen_at:, profile:) + = render ViewableChamp::SectionComponent.new(dossier:, types_de_champ:, demande_seen_at:, profile:) diff --git a/app/views/shared/dossiers/_edit.html.haml b/app/views/shared/dossiers/_edit.html.haml index 90379bb1d..1a67c85d8 100644 --- a/app/views/shared/dossiers/_edit.html.haml +++ b/app/views/shared/dossiers/_edit.html.haml @@ -21,7 +21,7 @@ = render Procedure::NoticeComponent.new(procedure: dossier.procedure) - = render EditableChamp::SectionComponent.new(types_de_champ: dossier_for_editing.revision.types_de_champ_public, champs_by_stable_id_with_row: dossier_for_editing.champs_by_stable_id_with_row) + = render EditableChamp::SectionComponent.new(dossier: dossier_for_editing, types_de_champ: dossier_for_editing.revision.types_de_champ_public) = render Dossiers::PendingCorrectionCheckboxComponent.new(dossier: dossier) diff --git a/app/views/shared/dossiers/_edit_annotations.html.haml b/app/views/shared/dossiers/_edit_annotations.html.haml index 7cef69996..5457cd0c7 100644 --- a/app/views/shared/dossiers/_edit_annotations.html.haml +++ b/app/views/shared/dossiers/_edit_annotations.html.haml @@ -3,7 +3,7 @@ %section.counter-start-header-section = render NestedForms::FormOwnerComponent.new = form_for dossier, url: annotations_instructeur_dossier_path(dossier.procedure, dossier), html: { class: 'form', multipart: true } do |f| - = render EditableChamp::SectionComponent.new(types_de_champ: dossier.revision.types_de_champ_private, champs_by_stable_id_with_row: dossier.champs_by_stable_id_with_row) + = render EditableChamp::SectionComponent.new(dossier:, types_de_champ: dossier.revision.types_de_champ_private) = render Dossiers::EditFooterComponent.new(dossier: dossier, annotation: true) - else diff --git a/config/routes.rb b/config/routes.rb index 66957ff5f..1e7d4421b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -191,10 +191,13 @@ Rails.application.routes.draw do end namespace :champs do + post ':dossier_id/:stable_id/repetition', to: 'repetition#add', as: :repetition + delete ':dossier_id/:stable_id/repetition', to: 'repetition#remove' + post ':champ_id/repetition', to: 'repetition#add' + delete ':champ_id/repetition', to: 'repetition#remove' + get ':champ_id/siret', to: 'siret#show', as: :siret get ':champ_id/rna', to: 'rna#show', as: :rna - post ':champ_id/repetition', to: 'repetition#add', as: :repetition - delete ':champ_id/repetition', to: 'repetition#remove' delete ':champ_id/options', to: 'options#remove', as: :options get ':champ_id/carte/features', to: 'carte#index', as: :carte_features diff --git a/spec/components/editable_champ/section_component_spec.rb b/spec/components/editable_champ/section_component_spec.rb index f3f474297..df65f5d45 100644 --- a/spec/components/editable_champ/section_component_spec.rb +++ b/spec/components/editable_champ/section_component_spec.rb @@ -1,12 +1,14 @@ describe EditableChamp::SectionComponent, type: :component do include TreeableConcern - let(:types_de_champ) { champs.map(&:type_de_champ) } - let(:champs_by_stable_id_with_row) { champs.index_by(&:stable_id_with_row) } - let(:component) { described_class.new(types_de_champ:, champs_by_stable_id_with_row:) } + let(:procedure) { create(:procedure, types_de_champ_public:) } + let(:types_de_champ_public) { [] } + let(:dossier) { create(:dossier, :with_populated_champs, procedure:) } + let(:types_de_champ) { dossier.revision.types_de_champ_public } + let(:component) { described_class.new(types_de_champ:, dossier:) } before { render_inline(component).to_html } context 'list of champs without an header_section' do - let(:champs) { [build(:champ_text), build(:champ_textarea)] } + let(:types_de_champ_public) { [{ type: :text }, { type: :textarea }] } it 'render in a fieldset' do expect(page).to have_selector("fieldset", count: 1) @@ -19,7 +21,7 @@ describe EditableChamp::SectionComponent, type: :component do end context 'list of champs with an header_section' do - let(:champs) { [build(:champ_header_section_level_1), build(:champ_text), build(:champ_textarea)] } + let(:types_de_champ_public) { [{ type: :header_section, level: 1 }, { type: :text }, { type: :textarea }] } it 'renders fieldset' do expect(page).to have_selector("fieldset") @@ -33,7 +35,7 @@ describe EditableChamp::SectionComponent, type: :component do end context 'list of champs without section and an header_section having champs' do - let(:champs) { [build(:champ_text), build(:champ_header_section_level_1), build(:champ_text)] } + let(:types_de_champ_public) { [{ type: :text }, { type: :header_section, level: 1 }, { type: :text }] } it 'renders fieldset' do expect(page).to have_selector("fieldset", count: 2) @@ -47,7 +49,7 @@ describe EditableChamp::SectionComponent, type: :component do end context 'list of header_section without champs' do - let(:champs) { [build(:champ_header_section_level_1), build(:champ_header_section_level_2), build(:champ_header_section_level_3)] } + let(:types_de_champ_public) { [{ type: :header_section, level: 1 }, { type: :header_section, level: 2 }, { type: :header_section, level: 3 }] } it 'render header within fieldset' do expect(page).to have_selector("fieldset > legend", count: 3) @@ -58,7 +60,7 @@ describe EditableChamp::SectionComponent, type: :component do end context 'header_section followed by explication and another fieldset' do - let(:champs) { [build(:champ_header_section_level_1), build(:champ_explication), build(:champ_header_section_level_1), build(:champ_text)] } + let(:types_de_champ_public) { [{ type: :header_section, level: 1 }, { type: :explication }, { type: :header_section, level: 1 }, { type: :text }] } it 'render fieldset, header_section, also render explication' do expect(page).to have_selector("h2", count: 2) @@ -69,7 +71,7 @@ describe EditableChamp::SectionComponent, type: :component do end context 'nested fieldsset' do - let(:champs) { [build(:champ_header_section_level_1), build(:champ_text), build(:champ_header_section_level_2), build(:champ_textarea)] } + let(:types_de_champ_public) { [{ type: :header_section, level: 1 }, { type: :text }, { type: :header_section, level: 2 }, { type: :textarea }] } it 'render nested fieldsets' do expect(page).to have_selector("fieldset") @@ -85,22 +87,19 @@ describe EditableChamp::SectionComponent, type: :component do end context 'with repetition' do - let(:procedure) do - create(:procedure, types_de_champ_public: [ - { type: :header_section, header_section_level: 1 }, + let(:types_de_champ_public) do + [ + { type: :header_section, level: 1 }, { type: :repetition, libelle: 'repetition', children: [ - { type: :header_section, header_section_level: 1, libelle: 'child_1' }, + { type: :header_section, level: 1, libelle: 'child_1' }, { type: :text, libelle: 'child_2' } ] } - ]) + ] end - let(:dossier) { create(:dossier, :with_populated_champs, procedure: procedure) } - let(:champs) { dossier.champs_public } - let(:champs_by_stable_id_with_row) { dossier.champs_by_stable_id_with_row } it 'render nested fieldsets, increase heading level for repetition header_section' do expect(page).to have_selector("fieldset") @@ -137,24 +136,24 @@ describe EditableChamp::SectionComponent, type: :component do end end - let(:champs) { + let(:types_de_champ_public) { [ - build(:champ_header_section_level_1), - build(:champ_header_section_level_2), - build(:champ_header_section_level_3), - build(:champ_integer_number), + { type: :header_section, level: 1 }, + { type: :header_section, level: 2 }, + { type: :header_section, level: 3 }, + { type: :integer_number }, - build(:champ_header_section_level_3), - build(:champ_yes_no), + { type: :header_section, level: 3 }, + { type: :yes_no }, - build(:champ_header_section_level_2), - build(:champ_header_section_level_3), - build(:champ_integer_number), + { type: :header_section, level: 2 }, + { type: :header_section, level: 3 }, + { type: :integer_number }, - build(:champ_header_section_level_1), - build(:champ_text), - build(:champ_header_section_level_2), - build(:champ_text) + { type: :header_section, level: 1 }, + { type: :text }, + { type: :header_section, level: 2 }, + { type: :text } ] } diff --git a/spec/factories/procedure.rb b/spec/factories/procedure.rb index 10dbffecf..e2c96c34a 100644 --- a/spec/factories/procedure.rb +++ b/spec/factories/procedure.rb @@ -319,6 +319,10 @@ def build_types_de_champ(types_de_champ, revision:, scope: :public, parent: nil) type_de_champ_attributes[:editable_options] = layers.index_with { '1' } end + if type == :header_section + type_de_champ_attributes[:header_section_level] = type_de_champ_attributes.delete(:level) + end + type_de_champ = if scope == :private build(:"type_de_champ_#{type}", :private, no_coordinate: true, **type_de_champ_attributes) else diff --git a/spec/models/dossier_spec.rb b/spec/models/dossier_spec.rb index 94d205a90..161447a79 100644 --- a/spec/models/dossier_spec.rb +++ b/spec/models/dossier_spec.rb @@ -46,18 +46,6 @@ describe Dossier, type: :model do end end - describe 'with_champs' do - let(:procedure) { create(:procedure) } - let!(:tdc_1) { create(:type_de_champ, libelle: 'l1', position: 1, procedure: procedure) } - let!(:tdc_3) { create(:type_de_champ, libelle: 'l3', position: 3, procedure: procedure) } - let!(:tdc_2) { create(:type_de_champ, libelle: 'l2', position: 2, procedure: procedure) } - let(:dossier) { create(:dossier, procedure: procedure) } - - it do - expect(Dossier.with_champs.find(dossier.id).champs_public.map(&:libelle)).to match(['l1', 'l2', 'l3']) - end - end - describe 'brouillon_close_to_expiration' do let(:procedure) { create(:procedure, :published, duree_conservation_dossiers_dans_ds: 6) } let!(:young_dossier) { create(:dossier, :en_construction, procedure: procedure) }