Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/components/dossiers/champs_rows_show_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def blank_key(champ)
end

def visible?(champ)
return false if champ.header_section? || champ.explication?
return false if champ.explication?
return true if champ.visible?

if profile == 'instructeur' && champ.public?
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
- each_champ do |champ|
- if champ.repetition?
- types_de_champ = champ.dossier.revision.children_of(champ.type_de_champ)
- 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} #{row_number} :"
= render ViewableChamp::SectionComponent.new(dossier: champ.dossier, types_de_champ:, row_id:, demande_seen_at: seen_at, profile:)
= render ViewableChamp::RepetitionComponent.new(repetition: champ, demande_seen_at: seen_at, profile:)

- elsif champ.header_section?
= render ViewableChamp::HeaderSectionComponent.new(header_section: champ)
- else
= 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?
Expand Down
64 changes: 32 additions & 32 deletions app/components/editable_champ/editable_champ_component.rb
Original file line number Diff line number Diff line change
@@ -1,57 +1,57 @@
# frozen_string_literal: true

class EditableChamp::EditableChampComponent < ApplicationComponent
def initialize(form:, champ:, seen_at: nil)
@form, @champ, @seen_at = form, champ, seen_at
def initialize(champs:, seen_at: nil)
@champs, @seen_at = champs, seen_at
@attribute = :value
end

def champ_component
@champ_component ||= component_class.new(form: @form, champ: @champ, seen_at: @seen_at)
def champ_component(form:, champ:)
component_class(champ:).new(form:, champ:, seen_at: @seen_at)
end

private

def has_label?(champ)
def has_label?(champ:)
types_without_label = [
TypeDeChamp.type_champs.fetch(:header_section),
TypeDeChamp.type_champs.fetch(:explication),
TypeDeChamp.type_champs.fetch(:repetition),
TypeDeChamp.type_champs.fetch(:linked_drop_down_list)
]
!types_without_label.include?(@champ.type_champ)
!types_without_label.include?(champ.type_champ)
end

def component_class
"EditableChamp::#{@champ.type_champ.camelcase}Component".constantize
def component_class(champ:)
"EditableChamp::#{champ.type_champ.camelcase}Component".constantize
end

def html_options
def html_options(component:, champ:)
{
class: class_names(
{
'editable-champ': true,
"editable-champ-#{@champ.type_champ}": true,
champ_component.dsfr_group_classname => true
}.merge(champ_component.input_group_error_class_names)
"editable-champ-#{champ.type_champ}": true,
component.dsfr_group_classname => true
}.merge(component.input_group_error_class_names)
),
data: { controller: stimulus_controller, **data_dependent_conditions, **stimulus_values }
data: { controller: stimulus_controller(champ:), **data_dependent_conditions(champ:), **stimulus_values(champ:) }
}
.deep_merge(champ_component.fieldset_aria_opts)
.deep_merge(champ_component.fieldset_error_opts)
.deep_merge(component.fieldset_aria_opts)
.deep_merge(component.fieldset_error_opts)
end

def fieldset_element_attributes
def fieldset_element_attributes(champ:)
{
id: @champ.input_group_id,
"hidden": !@champ.visible?
id: champ.input_group_id,
"hidden": !champ.visible?
}
end

def stimulus_values
if @champ.waiting_for_external_data?
def stimulus_values(champ:)
if champ.waiting_for_external_data?
{
turbo_poll_url_value:,
turbo_poll_url_value: turbo_poll_url_value(champ:),
turbo_poll_interval_value: 2_000,
turbo_poll_strategy_value: 'fixed'
}
Expand All @@ -60,36 +60,36 @@ def stimulus_values
end
end

def turbo_poll_url_value
if @champ.private?
annotation_instructeur_dossier_path(@champ.dossier.procedure, @champ.dossier, @champ.stable_id, row_id: @champ.row_id)
def turbo_poll_url_value(champ:)
if champ.private?
annotation_instructeur_dossier_path(champ.dossier.procedure, champ.dossier, champ.stable_id, row_id: champ.row_id)
else
champ_dossier_path(@champ.dossier, @champ.stable_id, row_id: @champ.row_id)
champ_dossier_path(champ.dossier, champ.stable_id, row_id: champ.row_id)
end
end

def stimulus_controller
if autosave_enabled?
def stimulus_controller(champ:)
if autosave_enabled?(champ:)
# This is an editable champ. Lets find what controllers it might need.
controllers = ['autosave']

if @champ.waiting_for_external_data?
if champ.waiting_for_external_data?
controllers << 'turbo-poll'
end

controllers.join(' ')
end
end

def data_dependent_conditions
if @champ.dependent_conditions?
def data_dependent_conditions(champ:)
if champ.dependent_conditions?
{ "dependent-conditions": "true" }
else
{}
end
end

def autosave_enabled?
!@champ.carte? && !@champ.repetition? && @champ.fillable?
def autosave_enabled?(champ:)
!champ.carte? && !champ.repetition? && champ.fillable?
end
end
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
.fr-fieldset__element{ **fieldset_element_attributes }
= content_tag((champ_component.dsfr_champ_container), html_options) do
- if has_label?(@champ)
= render EditableChamp::ChampLabelComponent.new form: @form, champ: @champ, seen_at: @seen_at
- @champs.each do |champ|
- if champ.header_section?
= render EditableChamp::SectionComponent.new(header_section: champ)
- else
= fields_for champ.input_name, champ do |form|
- component = champ_component(form:, champ:)
.fr-fieldset__element{ **fieldset_element_attributes(champ:) }
= content_tag(component.dsfr_champ_container, html_options(component:, champ:)) do
- if has_label?(champ:)
= render EditableChamp::ChampLabelComponent.new(form:, champ:, seen_at: @seen_at)

= render champ_component
= render component

= render Dsfr::InputStatusMessageComponent.new(errors_on_attribute: champ_component.errors_on_attribute?, error_full_messages: champ_component.error_full_messages, champ: @champ)
= render EditableChamp::ReferentielDisplayComponent.new(champ: @champ)
= render Dsfr::InputStatusMessageComponent.new(errors_on_attribute: component.errors_on_attribute?, error_full_messages: component.error_full_messages, champ:)
= render EditableChamp::ReferentielDisplayComponent.new(champ:)
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@


.repetition{ id: dom_id(@champ, :rows), class: class_names('utils-repetition-required' => @champ.mandatory?) }
- @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)
- @champ.new_rows.each.with_index(1) do |row, row_number|
= render EditableChamp::RepetitionRowComponent.new(row:, row_number:, seen_at: @seen_at)


.actions
= 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
Expand Down
13 changes: 4 additions & 9 deletions app/components/editable_champ/repetition_row_component.rb
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
# frozen_string_literal: true

class EditableChamp::RepetitionRowComponent < ApplicationComponent
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

private

def section_component
EditableChamp::SectionComponent.new(dossier: @dossier, types_de_champ: @types_de_champ, row_id:)
def initialize(row_number:, row: nil, seen_at: nil)
@row = row
@dossier = row.dossier
@row_id = row.row_id
end
end
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
.champs-group{ id: "safe-row-selector-#{row_id}" }
- if @types_de_champ.size > 1
- if @row.children.size > 1
%fieldset.fr-mx-0.fr-px-0
%legend.block-id.fr-px-0= "#{@type_de_champ.libelle} "
= render section_component
%legend.block-id.fr-px-0= "#{@row.libelle} "
= render EditableChamp::EditableChampComponent.new(champs: @row.children, seen_at: @seen_at)
- else
= render section_component
= render EditableChamp::EditableChampComponent.new(champs: @row.children, seen_at: @seen_at)

.flex.row-reverse
= 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 utils-repetition-required-destroy-button", title: t(".delete_title", row_number:), "aria-label": t(".delete_label", row_number:)}) do
= render NestedForms::OwnedButtonComponent.new(formaction: champs_repetition_path(@dossier, @row.stable_id, row_id:), http_method: :delete, opt: { class: "fr-btn fr-btn--sm fr-btn--tertiary fr-text-action-high--red-marianne utils-repetition-required-destroy-button", title: t(".delete_title", row_number:), "aria-label": t(".delete_label", row_number:)}) do
= t(".delete")
47 changes: 3 additions & 44 deletions app/components/editable_champ/section_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,55 +2,14 @@

class EditableChamp::SectionComponent < ApplicationComponent
include ApplicationHelper
include TreeableConcern

def initialize(dossier:, nodes: nil, types_de_champ: nil, row_id: nil)
nodes ||= to_tree(types_de_champ:)
@dossier = dossier
@row_id = row_id
@nodes = to_fieldset(nodes:)
end

def render_within_fieldset?
first_champ_is_an_header_section?
end

def header_section
node = @nodes.first
@dossier.project_champ(node, row_id: @row_id) if node.is_a?(TypeDeChamp) && node.header_section?
end

def splitted_tail
tail.map { split_section_champ(_1) }
end

def tail
return @nodes if !first_champ_is_an_header_section?
_, *rest_of_champ = @nodes
attr_reader :header_section

rest_of_champ
def initialize(header_section:)
@header_section = header_section
end

def tag_for_depth
"h#{header_section.level + 1}"
end

def split_section_champ(node)
case node
when EditableChamp::SectionComponent
[node, nil]
else
[nil, @dossier.project_champ(node, row_id: @row_id)]
end
end

private

def to_fieldset(nodes:)
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
end
Original file line number Diff line number Diff line change
@@ -1,21 +1,5 @@
- if render_within_fieldset?
.fr-fieldset__element{ class: class_names("fr-my-0" => render_within_fieldset?) }
%fieldset.fr-fieldset.fr-my-0{ class: "reset-#{tag_for_depth}" }
%legend.fr-fieldset__legend
= render EditableChamp::HeaderSectionComponent.new(champ: header_section)
- splitted_tail.each do |section, champ|
- if section.present?
= render section
- else
= fields_for champ.input_name, champ do |form|
= render EditableChamp::EditableChampComponent.new form:, champ:
- else
- if header_section
.fr-fieldset__legend.fr-my-0{ class: "reset-#{tag_for_depth}" }
.fr-fieldset__element.fr-my-0
%fieldset.fr-fieldset.fr-my-0{ class: "reset-#{tag_for_depth}" }
%legend.fr-fieldset__legend
= render EditableChamp::HeaderSectionComponent.new(champ: header_section)
- splitted_tail.each do |section, champ|
- if section.present?
= render section
- else
= fields_for champ.input_name, champ do |form|
= render EditableChamp::EditableChampComponent.new form:, champ:
= render EditableChamp::EditableChampComponent.new champs: header_section.children
2 changes: 1 addition & 1 deletion app/components/types_de_champ_editor/champ_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def types_of_type_de_champ
end
end

ACCEPTED_TYPES = Columns::ChampColumn::CAST.keys.group_by { |(from)| from.to_s }.transform_values { |(_, to)| to.to_s }
ACCEPTED_TYPES = Columns::ChampColumn::CAST.keys.group_by { |(from)| from.to_s }.transform_values { |(_, to)| to.map(&:to_s) }

def accepted_type_champs
published_type_champ = procedure.published_revision&.types_de_champ&.find { _1.stable_id == type_de_champ.stable_id }&.type_champ
Expand Down
11 changes: 11 additions & 0 deletions app/components/viewable_champ/header_section_component.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
= tag.div(class: class_names(reset_tag_for_depth => true, "fr-my-2w" => !first_level?), 'data-controller': 'expand') do
%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 fr-py-2w": first_level?, 'fr-py-1v': !first_level? })
- if !header_section.children.empty? && first_level?
%button{ type: "button", aria: { controls: section_id, "expanded": "true" }, 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' }
%span.fr-sr-only= t('.toggle_section', section: header_section.libelle)

%div{ id: section_id, 'data-expand-target': 'content' }
- if !header_section.children.empty?
= render Dossiers::ChampsRowsShowComponent.new(champs: header_section.children, seen_at: @demande_seen_at, profile: @profile)
21 changes: 21 additions & 0 deletions app/components/viewable_champ/header_section_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

class ViewableChamp::HeaderSectionComponent < ApplicationComponent
attr_reader :header_section

def initialize(header_section:)
@header_section = header_section
end

def reset_tag_for_depth
"reset-h#{header_section.level + 1}"
end

def first_level?
header_section.level == 1
end

def section_id = dom_id(header_section, :content)

def render? = header_section.visible?
end
11 changes: 11 additions & 0 deletions app/components/viewable_champ/repetition_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

class ViewableChamp::RepetitionComponent < ApplicationComponent
include ApplicationHelper
attr_reader :repetition, :rows, :seen_at, :profile

def initialize(repetition:, demande_seen_at:, profile:)
@repetition, @seen_at, @profile = repetition, demande_seen_at, profile
@rows = repetition.new_rows
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- rows.each.with_index(1) do |row, row_number|
.fr-background-alt--grey.fr-p-2w.fr-my-3w.fr-ml-2w.champ-repetition
%p.font-weight-bold= "#{repetition.libelle} #{row_number} :"
= render Dossiers::ChampsRowsShowComponent.new(champs: row.children, seen_at:, profile:)
Loading
Loading