Skip to content

Commit 4f86d9e

Browse files
committed
ETQ admin et instructeur, le sommaire inclut les répétitions et leurs sections
1 parent 81b0114 commit 4f86d9e

8 files changed

Lines changed: 73 additions & 35 deletions

File tree

app/components/dossiers/champs_rows_show_component/champs_rows_show_component.html.erb

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
<% each_champ do |champ| %>
22
<% if champ.repetition? %>
3-
<% champ.rows.each do |row| %>
4-
<div class="fr-background-alt--grey fr-p-2w fr-my-3w fr-ml-2w champ-repetition">
5-
<%= tag.send(repetition_heading_tag, t(".repetition_heading", libelle: champ.libelle, row_number: row.index), class: "fr-h6 fr-text--bold") %>
6-
<%= render ViewableChamp::SectionComponent.new(dossier: champ.dossier, champs: row.champs_tree, demande_seen_at: seen_at, profile:) %>
7-
</div>
8-
<% end %>
3+
<div id="<%= champ.html_id %>">
4+
<% champ.rows.each do |row| %>
5+
<div class="fr-background-alt--grey fr-p-2w fr-my-3w fr-ml-2w champ-repetition">
6+
<%= tag.send(repetition_heading_tag, t(".repetition_heading", libelle: champ.libelle, row_number: row.index), class: "fr-h6 fr-text--bold") %>
7+
<%= render ViewableChamp::SectionComponent.new(dossier: champ.dossier, champs: row.champs_tree, demande_seen_at: seen_at, profile:) %>
8+
</div>
9+
<% end %>
10+
</div>
911
<% else %>
1012
<%= render row_show_component(champ) do |c| %>
1113
<% if champ.blank? %>

app/components/types_de_champ_editor/header_sections_summary_component.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ def initialize(procedure:, is_private:)
66
@is_private = is_private
77
end
88

9-
# Header sections in document order, as [type_de_champ, level] pairs.
10-
def header_sections
11-
@header_sections ||= revision.header_sections_with_depth(is_private: @is_private)
9+
# Header sections and repetitions in document order, as [type_de_champ, level] pairs.
10+
def sections
11+
@sections ||= revision.sections_with_depth(is_private: @is_private)
1212
end
1313

1414
def href(type_de_champ) # used by type de champ editor to anchor elements
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
#summary{ class: header_sections.present? ? 'fr-col-12 fr-col-md-3' : '' }
2-
- if header_sections.present?
1+
#summary{ class: sections.present? ? 'fr-col-12 fr-col-md-3' : '' }
2+
- if sections.present?
33
%nav.fr-sidemenu.sticky.fr-hidden.fr-unhidden-md{ "aria-labelledby" => "fr-summary-title", role: "navigation" }
44
%ul.fr-sidemenu__list
5-
- header_sections.each do |header, level|
5+
- sections.each do |type_de_champ, level|
66
%li.fr-sidemenu__item
77
- if level == 1
8-
%a.fr-sidemenu__link{ href: href(header) }= header.libelle
8+
%a.fr-sidemenu__link{ href: href(type_de_champ) }= type_de_champ.libelle
99
- else
10-
%a.fr-sidemenu__link{ class: level >= 3 ? 'custom-link-grey': '', href: href(header) }= "-- #{header.libelle}"
10+
%a.fr-sidemenu__link{ class: level >= 3 ? 'custom-link-grey': '', href: href(type_de_champ) }= "-- #{type_de_champ.libelle}"

app/components/viewable_champ/header_sections_summary_component.rb

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,28 @@ def initialize(dossier:, is_private:)
66
@is_private = is_private
77
end
88

9-
# Header sections in document order, as [type_de_champ, level] pairs.
10-
def header_sections
11-
@header_sections ||= @dossier.revision.header_sections_with_depth(is_private: @is_private)
9+
# Header sections and repetitions in document order, as [type_de_champ, level] pairs.
10+
def sections
11+
@sections ||= @dossier.revision.sections_with_depth(is_private: @is_private)
1212
end
1313

14-
def render? = header_sections.any?
14+
def render? = sections.any?
1515

16-
def href(header_section) # used by viewable champs to anchor elements
17-
"##{header_section.html_id}"
16+
def href(type_de_champ) # used by viewable champs to anchor elements
17+
"##{anchor_id(type_de_champ)}"
18+
end
19+
20+
private
21+
22+
def revision = @dossier.revision
23+
24+
# Sections inside a repetition are rendered once per row: anchor to the first
25+
# row's occurrence, or to the repetition itself when there are no rows yet.
26+
def anchor_id(type_de_champ)
27+
repetition = type_de_champ.repetition(revision)
28+
return type_de_champ.html_id if repetition.nil?
29+
30+
row_id = @dossier.repetition_row_ids(repetition).first
31+
row_id.present? ? type_de_champ.html_id(row_id) : repetition.html_id
1832
end
1933
end
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#summary.fr-col-12.fr-col-xl-3
22
%nav.fr-sidemenu.sticky.fr-hidden.fr-unhidden-xl{ "aria-labelledby" => "fr-summary-title", role: "navigation" }
33
%ul.fr-sidemenu__list
4-
- header_sections.each do |header_section, level|
4+
- sections.each do |type_de_champ, level|
55
%li.fr-sidemenu__item
66
- if level == 1
7-
%a.fr-sidemenu__link{ href: href(header_section) }= header_section.libelle
7+
%a.fr-sidemenu__link{ href: href(type_de_champ) }= type_de_champ.libelle
88
- else
9-
%a.fr-sidemenu__link{ class: level >= 3 ? 'custom-link-grey': '', href: href(header_section) }= "-- #{header_section.libelle}"
9+
%a.fr-sidemenu__link{ class: level >= 3 ? 'custom-link-grey': '', href: href(type_de_champ) }= "-- #{type_de_champ.libelle}"

app/models/procedure_revision.rb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ def types_de_champ_private = revision_types_de_champ_private.map(&:type_de_champ
2424
def types_de_champ_public_tree = to_tree_roots(types_de_champ: types_de_champ_public)
2525
def types_de_champ_private_tree = to_tree_roots(types_de_champ: types_de_champ_private)
2626

27-
# Header sections in document order, as [type_de_champ, depth] pairs. Depth
28-
# is the position in the tree; it can differ from the stored
27+
# Header sections and repetitions in document order, as [type_de_champ, depth]
28+
# pairs. Depth is the position in the tree; it can differ from the stored
2929
# header_section_level (used by heading tags via level_for_revision) when
3030
# levels are skipped.
31-
def header_sections_with_depth(is_private: false)
31+
def sections_with_depth(is_private: false)
3232
tree = is_private ? types_de_champ_private_tree : types_de_champ_public_tree
33-
flatten_header_sections(tree, 1)
33+
flatten_sections(tree, 1)
3434
end
3535

3636
has_one :draft_procedure, -> { with_discarded }, class_name: 'Procedure', foreign_key: :draft_revision_id, dependent: :nullify, inverse_of: :draft_revision
@@ -349,9 +349,9 @@ def apply_llm_rule_suggestion_items(changes)
349349

350350
private
351351

352-
def flatten_header_sections(types_de_champ, depth)
353-
types_de_champ.filter(&:header_section?).flat_map do |tdc|
354-
[[tdc, depth], *flatten_header_sections(tdc.children(self), depth + 1)]
352+
def flatten_sections(types_de_champ, depth)
353+
types_de_champ.filter { it.header_section? || it.repetition? }.flat_map do |tdc|
354+
[[tdc, depth], *flatten_sections(tdc.children(self), depth + 1)]
355355
end
356356
end
357357

spec/components/champ_header_sections_summary_component_spec.rb

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,34 @@
1515
]
1616
end
1717
let(:procedure) { create(:procedure, types_de_champ_public: types_de_champ, types_de_champ_private: types_de_champ) }
18-
let(:dossier) { create(:dossier, procedure:) }
18+
let(:dossier) { create(:dossier, :with_populated_champs, procedure:) }
1919
let(:component) { described_class.new(dossier:, is_private:) }
2020
let(:types_de_champ_public) { dossier.revision.types_de_champ_public.filter(&:header_section?) }
2121
let(:types_de_champ_private) { dossier.revision.types_de_champ_private.filter(&:header_section?) }
22+
let(:repetition_tdc) { dossier.revision.types_de_champ_public.find(&:repetition?) }
23+
let(:section_in_repetition) { dossier.revision.children_of(repetition_tdc).find(&:header_section?) }
2224

2325
context 'public' do
2426
it do
2527
types_de_champ_public.each { expect(subject).to have_selector("a[href='##{_1.html_id}']") }
2628
end
29+
30+
it 'anchors the repetition and its sections (on the first row)' do
31+
first_row_id = dossier.repetition_row_ids(repetition_tdc).first
32+
expect(subject).to have_selector("a[href='##{repetition_tdc.html_id}']")
33+
expect(subject).to have_selector("a[href='##{section_in_repetition.html_id(first_row_id)}']")
34+
end
35+
36+
context 'when the repetition has no rows' do
37+
let(:types_de_champ) do
38+
[{ type: :repetition, mandatory: false, children: [{ type: :text }, { type: :header_section, level: 1 }] }]
39+
end
40+
let(:dossier) { create(:dossier, procedure:) }
41+
42+
it 'anchors the section to the repetition itself' do
43+
expect(subject).to have_selector("a[href='##{repetition_tdc.html_id}']", count: 2)
44+
end
45+
end
2746
end
2847

2948
context 'private' do

spec/components/types_de_champ_editor/header_sections_summary_component_spec.rb

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,21 @@
1919
]
2020
end
2121

22-
it 'renders header sections with their depth, ignoring sections inside repetitions' do
22+
it 'renders header sections and repetitions with their depth' do
2323
expect(subject).to have_selector("a", text: /\As1\z/)
2424
expect(subject).to have_selector("a", text: '-- s1.1')
2525
expect(subject).to have_selector("a.custom-link-grey", text: '-- s1.1.1')
26+
expect(subject).to have_selector("a.custom-link-grey", text: '-- rep')
27+
expect(subject).to have_selector("a.custom-link-grey", text: '-- rs1')
2628
expect(subject).to have_selector("a", text: /\As2\z/)
27-
expect(subject).not_to have_text('rs1')
2829
expect(subject).not_to have_text('t1')
2930
end
3031

3132
it 'anchors links to the editor coordinates' do
32-
coordinate = procedure.draft_revision.revision_types_de_champ.find { _1.libelle == 's1' }
33-
expect(subject).to have_selector("a[href='##{ActionView::RecordIdentifier.dom_id(coordinate, :type_de_champ_editor)}']")
33+
['s1', 'rep', 'rs1'].each do |libelle|
34+
coordinate = procedure.draft_revision.revision_types_de_champ.find { _1.libelle == libelle }
35+
expect(subject).to have_selector("a[href='##{ActionView::RecordIdentifier.dom_id(coordinate, :type_de_champ_editor)}']")
36+
end
3437
end
3538
end
3639

0 commit comments

Comments
 (0)