From 88029111263ff3ebfe8fa8bab8d2e0810d46d53e Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Thu, 31 Aug 2023 18:16:14 +0200 Subject: [PATCH 01/60] fix(carte): initialize map only when container is visible fix #9417 --- .../components/shared/maplibre/MapLibre.tsx | 7 ++-- .../components/shared/maplibre/hooks.ts | 35 ++++++++++++++++++- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/app/javascript/components/shared/maplibre/MapLibre.tsx b/app/javascript/components/shared/maplibre/MapLibre.tsx index a7ddf4191..a6ae5f181 100644 --- a/app/javascript/components/shared/maplibre/MapLibre.tsx +++ b/app/javascript/components/shared/maplibre/MapLibre.tsx @@ -13,7 +13,7 @@ import type { Style } from 'maplibre-gl'; import invariant from 'tiny-invariant'; -import { useStyle } from './hooks'; +import { useStyle, useElementVisible } from './hooks'; import { StyleControl } from './StyleControl'; const Context = createContext<{ map?: Map | null }>({}); @@ -35,6 +35,7 @@ export function MapLibre({ children, layers }: MapLibreProps) { [] ); const containerRef = useRef(null); + const visible = useElementVisible(containerRef); const [map, setMap] = useState(); const onStyleChange = useCallback( @@ -48,7 +49,7 @@ export function MapLibre({ children, layers }: MapLibreProps) { const { style, ...mapStyleProps } = useStyle(layers, onStyleChange); useEffect(() => { - if (isSupported && !map) { + if (isSupported && visible && !map) { invariant(containerRef.current, 'Map container not found'); const map = new Map({ container: containerRef.current, @@ -59,7 +60,7 @@ export function MapLibre({ children, layers }: MapLibreProps) { setMap(map); }); } - }, [map, style, isSupported]); + }, [map, style, visible, isSupported]); if (!isSupported) { return ( diff --git a/app/javascript/components/shared/maplibre/hooks.ts b/app/javascript/components/shared/maplibre/hooks.ts index 56a59ddf3..078e5fb15 100644 --- a/app/javascript/components/shared/maplibre/hooks.ts +++ b/app/javascript/components/shared/maplibre/hooks.ts @@ -1,4 +1,10 @@ -import { useCallback, useEffect, useState, useMemo } from 'react'; +import { + useCallback, + useEffect, + useState, + useMemo, + type RefObject +} from 'react'; import type { LngLatBoundsLike, LngLat, @@ -118,3 +124,30 @@ export function useStyle( return { style, layers, setStyle, setLayerEnabled, setLayerOpacity }; } + +function isElementVisible( + element: HTMLElement, + callback: (visible: boolean) => void +) { + if (element.offsetWidth > 0 && element.offsetHeight > 0) { + callback(true); + } else { + callback(false); + const observer = new IntersectionObserver( + (entries) => callback(entries[0].isIntersecting == true), + { threshold: [0] } + ); + observer.observe(element); + return () => observer.unobserve(element); + } +} + +export function useElementVisible(element: RefObject) { + const [visible, setVisible] = useState(false); + useEffect(() => { + if (element.current) { + return isElementVisible(element.current, setVisible); + } + }, [element]); + return visible; +} From 24b15422d909786405da56ce08e5213468a4f82f Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Fri, 1 Sep 2023 10:51:26 +0200 Subject: [PATCH 02/60] fix(coldwire): bump @coldwired/actions to fix event dispatch --- package.json | 2 +- yarn.lock | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index d2085b11f..c118473b9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "@coldwired/actions": "^0.11.1", + "@coldwired/actions": "^0.11.2", "@coldwired/turbo-stream": "^0.11.1", "@coldwired/utils": "^0.11.1", "@gouvfr/dsfr": "^1.7.2", diff --git a/yarn.lock b/yarn.lock index e7d45284c..fdf6cac76 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1164,6 +1164,15 @@ morphdom "^2.7.0" tiny-invariant "^1.3.1" +"@coldwired/actions@^0.11.2": + version "0.11.2" + resolved "https://registry.yarnpkg.com/@coldwired/actions/-/actions-0.11.2.tgz#025917b7ad18d162b3bfe752361cbeef28a21db6" + integrity sha512-Q1vC1Rcs+Vmql7npaO1dYJQPOQouotjgcrqqyXTAAlMJeHFqOWv7Qy+qeaQSIcY6qsveEkDChh6qTjpA5XdaFw== + dependencies: + "@coldwired/utils" "^0.11.1" + morphdom "^2.7.0" + tiny-invariant "^1.3.1" + "@coldwired/turbo-stream@^0.11.1": version "0.11.1" resolved "https://registry.yarnpkg.com/@coldwired/turbo-stream/-/turbo-stream-0.11.1.tgz#0f0f710422f61700cb8d8d8368799dbce64dd083" From 0ba0fd5058bc7b7a3f2f5d7fb18406d512bc6bd2 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Fri, 1 Sep 2023 10:50:17 +0200 Subject: [PATCH 03/60] feat(type_de_champ): insert an add champ button after each type de champ --- .../stylesheets/procedure_champs_editor.scss | 23 +- app/components/application_component.rb | 7 - .../add_champ_button_component.rb | 8 +- .../types_de_champ_editor/champ_component.rb | 3 +- .../champ_component/champ_component.html.haml | 219 +++++++++--------- .../type_de_champ_editor_controller.ts | 28 --- .../procedure_revision_type_de_champ.rb | 4 + .../types_de_champ/_insert.turbo_stream.haml | 5 + 8 files changed, 140 insertions(+), 157 deletions(-) diff --git a/app/assets/stylesheets/procedure_champs_editor.scss b/app/assets/stylesheets/procedure_champs_editor.scss index 72e8cf4bb..e788ec727 100644 --- a/app/assets/stylesheets/procedure_champs_editor.scss +++ b/app/assets/stylesheets/procedure_champs_editor.scss @@ -14,13 +14,18 @@ .type-de-champ { width: 100%; - background-color: #FAFDFF; - border: 1px solid $border-grey; - border-radius: 5px; - margin-bottom: $default-padding * 2; - box-shadow: 0px 2px 4px -4px; + margin-bottom: $default-padding; overflow: hidden; + .type-de-champ-container { + width: 100%; + background-color: #FAFDFF; + border: 1px solid $border-grey; + border-radius: 5px; + margin-bottom: $default-padding; + box-shadow: 0px 2px 4px -4px; + } + .handle.icon { width: 32px; height: 32px; @@ -71,6 +76,10 @@ display: none; } + &.last .type-de-champ-add-button.root { + display: none; + } + .head { background-color: #FAFDFF; @@ -91,10 +100,6 @@ &.section { padding: $default-spacer $default-spacer 0; margin-bottom: 8px; - - input { - background-color: $white; - } } &.hr { diff --git a/app/components/application_component.rb b/app/components/application_component.rb index 3f32fe9e6..2cfb80769 100644 --- a/app/components/application_component.rb +++ b/app/components/application_component.rb @@ -2,13 +2,6 @@ class ApplicationComponent < ViewComponent::Base include ViewComponent::Translatable include FlipperHelper - # Takes a Hash of { class_name: boolean }. - # Returns truthy class names in an array. Array can be passed as-it in rails helpers, - # and is still manipulable if needed. - def class_names(class_names) - class_names.filter { _2 }.keys - end - def current_user controller.current_user end diff --git a/app/components/types_de_champ_editor/add_champ_button_component.rb b/app/components/types_de_champ_editor/add_champ_button_component.rb index ad23aaf41..ac1c28af0 100644 --- a/app/components/types_de_champ_editor/add_champ_button_component.rb +++ b/app/components/types_de_champ_editor/add_champ_button_component.rb @@ -1,8 +1,9 @@ class TypesDeChampEditor::AddChampButtonComponent < ApplicationComponent - def initialize(revision:, parent: nil, is_annotation: false) + def initialize(revision:, parent: nil, is_annotation: false, after_stable_id: nil) @revision = revision @parent = parent @is_annotation = is_annotation + @after_stable_id = after_stable_id end private @@ -25,8 +26,7 @@ class TypesDeChampEditor::AddChampButtonComponent < ApplicationComponent def button_options { - class: "button", - form: { class: @parent ? "add-to-block" : "add-to-root" }, + class: "fr-btn fr-btn--secondary fr-btn--icon-left fr-icon-add-line", method: :post, params: { type_de_champ: { @@ -34,7 +34,7 @@ class TypesDeChampEditor::AddChampButtonComponent < ApplicationComponent type_champ: TypeDeChamp.type_champs.fetch(:text), private: annotations? ? true : nil, parent_stable_id: @parent&.stable_id, - after_stable_id: '' + after_stable_id: @after_stable_id }.compact } } diff --git a/app/components/types_de_champ_editor/champ_component.rb b/app/components/types_de_champ_editor/champ_component.rb index 6fe4fb9a1..d2e6e39b5 100644 --- a/app/components/types_de_champ_editor/champ_component.rb +++ b/app/components/types_de_champ_editor/champ_component.rb @@ -30,8 +30,7 @@ class TypesDeChampEditor::ChampComponent < ApplicationComponent controller: 'type-de-champ-editor', type_de_champ_editor_move_url_value: move_admin_procedure_type_de_champ_path(procedure, type_de_champ.stable_id), type_de_champ_editor_move_up_url_value: move_up_admin_procedure_type_de_champ_path(procedure, type_de_champ.stable_id), - type_de_champ_editor_move_down_url_value: move_down_admin_procedure_type_de_champ_path(procedure, type_de_champ.stable_id), - type_de_champ_editor_type_de_champ_stable_id_value: type_de_champ.stable_id + type_de_champ_editor_move_down_url_value: move_down_admin_procedure_type_de_champ_path(procedure, type_de_champ.stable_id) } } end diff --git a/app/components/types_de_champ_editor/champ_component/champ_component.html.haml b/app/components/types_de_champ_editor/champ_component/champ_component.html.haml index b2dd9f91b..56da3b30e 100644 --- a/app/components/types_de_champ_editor/champ_component/champ_component.html.haml +++ b/app/components/types_de_champ_editor/champ_component/champ_component.html.haml @@ -1,117 +1,122 @@ %li.type-de-champ.flex.column.justify-start{ html_options } - .flex.justify-between.section.head.hr - .handle.small.icon-only.icon.move-handle{ title: "Déplacer le champ vers le haut ou vers le bas" } + .type-de-champ-container + .flex.justify-between.section.head.hr + .handle.small.icon-only.icon.move-handle{ title: "Déplacer le champ vers le haut ou vers le bas" } - - if coordinate.used_by_routing_rules? - .flex.align-center - %span - utilisé pour - = link_to('le routage', admin_procedure_groupe_instructeurs_path(revision.procedure_id, anchor: 'routing-rules')) - - else - .flex.justify-start.delete - = button_to type_de_champ_path, class: 'button small icon-only danger', method: :delete, form: { data: { turbo_confirm: 'Êtes vous sûr de vouloir supprimer ce champ ?' } } do - .icon.delete - %span.sr-only Supprimer + - if coordinate.used_by_routing_rules? + .flex.align-center + %span + utilisé pour + = link_to('le routage', admin_procedure_groupe_instructeurs_path(revision.procedure_id, anchor: 'routing-rules')) + - else + .flex.justify-start.delete + = button_to type_de_champ_path, class: 'fr-btn fr-btn--sm fr-btn--secondary fr-icon-delete-line', title: "Supprimer le champ", method: :delete, form: { data: { turbo_confirm: 'Êtes vous sûr de vouloir supprimer ce champ ?' } } do + .icon.delete + %span.sr-only Supprimer - - if @errors.present? - .types-de-champ-errors - = @errors + - if @errors.present? + .types-de-champ-errors + = @errors - .flex.justify-start.section.ml-1 - = form_for(type_de_champ, form_options) do |form| - .flex.justify-start - .flex.justify-start.width-33 - .flex.justify-start.column - %button.move-up.cell.mb-1{ move_button_options(:up) } - .icon.arrow-up.small - %span.sr-only Déplacer le champ vers le haut - %button.move-down.cell{ move_button_options(:down) } - .icon.arrow-down.small - %span.sr-only Déplacer le champ vers le bas - .cell.flex.justify-start.column.flex-grow - = form.label :type_champ, "Type de champ", for: dom_id(type_de_champ, :type_champ) - = form.select :type_champ, grouped_options_for_select(types_of_type_de_champ, type_de_champ.type_champ), {}, class: 'small-margin small inline width-100', id: dom_id(type_de_champ, :type_champ), disabled: coordinate.used_by_routing_rules? - .flex.column.justify-start.flex-grow - .cell - .flex.align-center - = form.label :libelle, "Libellé du champ", class: 'flex-grow', for: dom_id(type_de_champ, :libelle) - - if can_be_mandatory? - .cell.flex.align-center - = form.check_box :mandatory, class: 'small-margin small', id: dom_id(type_de_champ, :mandatory) - = form.label :mandatory, "Champ obligatoire", for: dom_id(type_de_champ, :mandatory) - = form.text_field :libelle, class: 'small-margin small width-100', id: dom_id(type_de_champ, :libelle), data: input_autofocus - - if type_de_champ.header_section? - %p - %small Nous numérotons automatiquement les titres lorsqu’aucun de vos titres ne commence par un chiffre. - - - if !type_de_champ.header_section? && !type_de_champ.titre_identite? - .cell.mt-1 - = form.label :description, "Description du champ (optionnel)", for: dom_id(type_de_champ, :description) - = form.text_area :description, class: 'small-margin small width-100', rows: 3, id: dom_id(type_de_champ, :description) - - if type_de_champ.header_section? - .cell.mt-1 - = render TypesDeChampEditor::HeaderSectionComponent.new(form: form, tdc: type_de_champ, upper_tdcs: @upper_coordinates.map(&:type_de_champ)) - - - - .flex.justify-start.mt-1 - - if type_de_champ.drop_down_list? - .flex.column.justify-start.width-33 - .cell - = form.label :drop_down_list_value, "Options de la liste", for: dom_id(type_de_champ, :drop_down_list_value) - = form.text_area :drop_down_list_value, class: 'small-margin small width-100', rows: 7, id: dom_id(type_de_champ, :drop_down_list_value) - - if type_de_champ.simple_drop_down_list? - .cell - = form.label :drop_down_other, for: dom_id(type_de_champ, :drop_down_other) do - Proposer une option « autre » avec un texte libre - = form.check_box :drop_down_other, class: "small-margin small", id: dom_id(type_de_champ, :drop_down_other) - - - if type_de_champ.linked_drop_down_list? + .flex.justify-start.section.ml-1 + = form_for(type_de_champ, form_options) do |form| + .flex.justify-start + .flex.justify-start.width-33 + .flex.justify-start.column + %button.move-up.cell.mb-1{ move_button_options(:up) } + .icon.arrow-up.small + %span.sr-only Déplacer le champ vers le haut + %button.move-down.cell{ move_button_options(:down) } + .icon.arrow-down.small + %span.sr-only Déplacer le champ vers le bas + .cell.flex.justify-start.column.flex-grow + = form.label :type_champ, "Type de champ", for: dom_id(type_de_champ, :type_champ) + = form.select :type_champ, grouped_options_for_select(types_of_type_de_champ, type_de_champ.type_champ), {}, class: 'fr-select small-margin small inline width-100', id: dom_id(type_de_champ, :type_champ), disabled: coordinate.used_by_routing_rules? .flex.column.justify-start.flex-grow .cell - = form.label :drop_down_secondary_libelle, "Libellé du champ secondaire", class: 'flex-grow', for: dom_id(type_de_champ, :drop_down_secondary_libelle) - = form.text_field :drop_down_secondary_libelle, class: 'small-margin small width-100', id: dom_id(type_de_champ, :drop_down_secondary_libelle) - .cell.mt-1 - = form.label :drop_down_secondary_description, "Description du champ secondaire (optionnel)", for: dom_id(type_de_champ, :drop_down_secondary_description) - = form.text_area :drop_down_secondary_description, class: 'small-margin small width-100', rows: 3, id: dom_id(type_de_champ, :drop_down_secondary_description) - - if type_de_champ.piece_justificative? - .cell - = form.label :piece_justificative_template, "Modèle", for: dom_id(type_de_champ, :piece_justificative_template) - = render Attachment::EditComponent.new(**piece_justificative_template_options) + .flex.align-center + = form.label :libelle, "Libellé du champ", class: 'flex-grow', for: dom_id(type_de_champ, :libelle) + - if can_be_mandatory? + .cell.flex.align-center + = form.check_box :mandatory, class: 'small-margin small', id: dom_id(type_de_champ, :mandatory) + = form.label :mandatory, "Champ obligatoire", for: dom_id(type_de_champ, :mandatory) + = form.text_field :libelle, class: 'fr-input small-margin small width-100', id: dom_id(type_de_champ, :libelle), data: input_autofocus + - if type_de_champ.header_section? + %p + %small Nous numérotons automatiquement les titres lorsqu’aucun de vos titres ne commence par un chiffre. - - if type_de_champ.titre_identite? - %p Dans le cadre de la RGPD, le titre d’identité sera supprimé lors de l’acceptation du dossier - - elsif procedure.piece_justificative_multiple? - %p Les usagers pourront envoyer plusieurs fichiers si nécessaire. - - if type_de_champ.carte? - - type_de_champ.editable_options.each do |slice| + - if !type_de_champ.header_section? && !type_de_champ.titre_identite? + .cell.mt-1 + = form.label :description, "Description du champ (optionnel)", for: dom_id(type_de_champ, :description) + = form.text_area :description, class: 'fr-input small-margin small width-100', rows: 3, id: dom_id(type_de_champ, :description) + - if type_de_champ.header_section? + .cell.mt-1 + = render TypesDeChampEditor::HeaderSectionComponent.new(form: form, tdc: type_de_champ, upper_tdcs: @upper_coordinates.map(&:type_de_champ)) + + + + .flex.justify-start.mt-1 + - if type_de_champ.drop_down_list? + .flex.column.justify-start.width-33 + .cell + = form.label :drop_down_list_value, "Options de la liste", for: dom_id(type_de_champ, :drop_down_list_value) + = form.text_area :drop_down_list_value, class: 'fr-input small-margin small width-100', rows: 7, id: dom_id(type_de_champ, :drop_down_list_value) + - if type_de_champ.simple_drop_down_list? + .cell + = form.label :drop_down_other, for: dom_id(type_de_champ, :drop_down_other) do + Proposer une option « autre » avec un texte libre + = form.check_box :drop_down_other, class: "small-margin small", id: dom_id(type_de_champ, :drop_down_other) + + - if type_de_champ.linked_drop_down_list? + .flex.column.justify-start.flex-grow + .cell + = form.label :drop_down_secondary_libelle, "Libellé du champ secondaire", class: 'flex-grow', for: dom_id(type_de_champ, :drop_down_secondary_libelle) + = form.text_field :drop_down_secondary_libelle, class: 'fr-input small-margin small width-100', id: dom_id(type_de_champ, :drop_down_secondary_libelle) + .cell.mt-1 + = form.label :drop_down_secondary_description, "Description du champ secondaire (optionnel)", for: dom_id(type_de_champ, :drop_down_secondary_description) + = form.text_area :drop_down_secondary_description, class: 'fr-input small-margin small width-100', rows: 3, id: dom_id(type_de_champ, :drop_down_secondary_description) + - if type_de_champ.piece_justificative? .cell - .carte-options - = form.fields_for :editable_options do |form| - - slice.each do |(name, checked)| - = form.label name, for: dom_id(type_de_champ, "layer_#{name}") do - = form.check_box name, checked: checked, class: 'small-margin small', id: dom_id(type_de_champ, "layer_#{name}") - = t(".layers.#{name}") - - if type_de_champ.explication? - .cell.width-66 - = form.label :collapsible_explanation_enabled, for: dom_id(type_de_champ, :collapsible_explanation_enabled) do - Afficher un texte complementaire affichable au clic - = form.check_box :collapsible_explanation_enabled, class: "small-margin small", id: dom_id(type_de_champ, :collapsible_explanation_enabled) - - if form.object.collapsible_explanation_enabled? - = form.label :collapsible_explanation_text, for: dom_id(type_de_champ, :collapsible_explanation_text) do - = "Texte à afficher quand l'utiliser a choisi de l'afficher" - = form.text_area :collapsible_explanation_text, class: "small-margin small", id: dom_id(type_de_champ, :collapsible_explanation_text) - - if type_de_champ.textarea? - .cell - = form.label :character_limit, for: dom_id(type_de_champ, :character_limit) do - Spécifier un nombre maximal conseillé de caractères : - = form.select :character_limit, options_for_character_limit, id: dom_id(type_de_champ, :character_limit) + = form.label :piece_justificative_template, "Modèle", for: dom_id(type_de_champ, :piece_justificative_template) + = render Attachment::EditComponent.new(**piece_justificative_template_options) - - if type_de_champ.block? - .flex.justify-start.section.ml-1 - .editor-block.flex-grow.cell - = render TypesDeChampEditor::BlockComponent.new(block: coordinate, coordinates: coordinate.revision_types_de_champ, upper_coordinates: @upper_coordinates) - = render TypesDeChampEditor::AddChampButtonComponent.new(revision: coordinate.revision, parent: coordinate, is_annotation: coordinate.private?) + - if type_de_champ.titre_identite? + %p Dans le cadre de la RGPD, le titre d’identité sera supprimé lors de l’acceptation du dossier + - elsif procedure.piece_justificative_multiple? + %p Les usagers pourront envoyer plusieurs fichiers si nécessaire. + - if type_de_champ.carte? + - type_de_champ.editable_options.each do |slice| + .cell + .carte-options + = form.fields_for :editable_options do |form| + - slice.each do |(name, checked)| + = form.label name, for: dom_id(type_de_champ, "layer_#{name}") do + = form.check_box name, checked: checked, class: 'small-margin small', id: dom_id(type_de_champ, "layer_#{name}") + = t(".layers.#{name}") + - if type_de_champ.explication? + .cell.width-66 + = form.label :collapsible_explanation_enabled, for: dom_id(type_de_champ, :collapsible_explanation_enabled) do + Afficher un texte complementaire affichable au clic + = form.check_box :collapsible_explanation_enabled, class: "small-margin small", id: dom_id(type_de_champ, :collapsible_explanation_enabled) + - if form.object.collapsible_explanation_enabled? + = form.label :collapsible_explanation_text, for: dom_id(type_de_champ, :collapsible_explanation_text) do + = "Texte à afficher quand l'utiliser a choisi de l'afficher" + = form.text_area :collapsible_explanation_text, class: "fr-input small-margin small", id: dom_id(type_de_champ, :collapsible_explanation_text) + - if type_de_champ.textarea? + .cell + = form.label :character_limit, for: dom_id(type_de_champ, :character_limit) do + Spécifier un nombre maximal conseillé de caractères : + = form.select :character_limit, options_for_character_limit, id: dom_id(type_de_champ, :character_limit), class: 'fr-select' - - if conditional_enabled? - = render(TypesDeChampEditor::ConditionsComponent.new(tdc: type_de_champ, upper_tdcs: @upper_coordinates.map(&:type_de_champ), procedure_id: procedure.id)) + - if type_de_champ.block? + .flex.justify-start.section.ml-1 + .editor-block.flex-grow.cell + = render TypesDeChampEditor::BlockComponent.new(block: coordinate, coordinates: coordinate.revision_types_de_champ, upper_coordinates: @upper_coordinates) + .type-de-champ-add-button{ id: dom_id(coordinate, :type_de_champ_add_button), class: class_names(hidden: !coordinate.empty?) } + = render TypesDeChampEditor::AddChampButtonComponent.new(revision: coordinate.revision, parent: coordinate, is_annotation: coordinate.private?) + + - if conditional_enabled? + = render(TypesDeChampEditor::ConditionsComponent.new(tdc: type_de_champ, upper_tdcs: @upper_coordinates.map(&:type_de_champ), procedure_id: procedure.id)) + + .type-de-champ-add-button{ class: class_names(root: !coordinate.child?) } + = render TypesDeChampEditor::AddChampButtonComponent.new(revision: coordinate.revision, parent: coordinate&.parent, is_annotation: coordinate.private?, after_stable_id: type_de_champ.stable_id) diff --git a/app/javascript/controllers/type_de_champ_editor_controller.ts b/app/javascript/controllers/type_de_champ_editor_controller.ts index 9f9a0f01e..6f6af508d 100644 --- a/app/javascript/controllers/type_de_champ_editor_controller.ts +++ b/app/javascript/controllers/type_de_champ_editor_controller.ts @@ -7,7 +7,6 @@ import { isTextInputElement, getConfig } from '@utils'; -import { useIntersection } from 'stimulus-use'; import { AutoUpload } from '../shared/activestorage/auto-upload'; import { ApplicationController } from './application_controller'; @@ -28,7 +27,6 @@ export class TypeDeChampEditorController extends ApplicationController { declare readonly moveUrlValue: string; declare readonly moveUpUrlValue: string; declare readonly moveDownUrlValue: string; - declare readonly typeDeChampStableIdValue: string; declare readonly isVisible: boolean; #latestPromise = Promise.resolve(); @@ -36,8 +34,6 @@ export class TypeDeChampEditorController extends ApplicationController { #inFlightForms: Map = new Map(); connect() { - useIntersection(this, { threshold: 0.6 }); - this.#latestPromise = Promise.resolve(); this.on('change', (event) => this.onChange(event)); this.on('input', (event) => this.onInput(event)); @@ -62,10 +58,6 @@ export class TypeDeChampEditorController extends ApplicationController { this.requestSubmitForm(form); } - appear() { - this.updateAfterId(); - } - private onChange(event: Event) { const target = event.target as HTMLElement & { form?: HTMLFormElement }; @@ -144,28 +136,8 @@ export class TypeDeChampEditorController extends ApplicationController { this.#inFlightForms.set(form, controller); return controller; } - - private updateAfterId() { - const parent = this.element.closest( - '.editor-block, .editor-root' - ); - if (parent) { - const selector = parent.classList.contains('editor-block') - ? '.add-to-block' - : '.add-to-root'; - const input = parent.querySelector( - `${selector} ${AFTER_STABLE_ID_INPUT_SELECTOR}` - ); - if (input) { - input.value = this.typeDeChampStableIdValue; - } - } - } } -const AFTER_STABLE_ID_INPUT_SELECTOR = - 'input[name="type_de_champ[after_stable_id]"]'; - function createForm(action: string, method: string) { const form = document.createElement('form'); form.action = action; diff --git a/app/models/procedure_revision_type_de_champ.rb b/app/models/procedure_revision_type_de_champ.rb index b5396351e..9e7b8464d 100644 --- a/app/models/procedure_revision_type_de_champ.rb +++ b/app/models/procedure_revision_type_de_champ.rb @@ -25,6 +25,10 @@ class ProcedureRevisionTypeDeChamp < ApplicationRecord siblings.last == self end + def empty? + revision_types_de_champ.empty? + end + def siblings if parent_id.present? revision.revision_types_de_champ.where(parent_id: parent_id).ordered diff --git a/app/views/administrateurs/types_de_champ/_insert.turbo_stream.haml b/app/views/administrateurs/types_de_champ/_insert.turbo_stream.haml index fe1769549..fee164d69 100644 --- a/app/views/administrateurs/types_de_champ/_insert.turbo_stream.haml +++ b/app/views/administrateurs/types_de_champ/_insert.turbo_stream.haml @@ -26,3 +26,8 @@ - render TypesDeChampEditor::EstimatedFillDurationComponent.new(revision: @coordinate.revision, is_annotation: @coordinate.private?) = turbo_stream.dispatch 'sortable:sort' + +- if @created&.coordinate&.child? + = turbo_stream.hide dom_id(@created.coordinate.parent, :type_de_champ_add_button) +- elsif @destroyed&.child? && @destroyed.parent.empty? + = turbo_stream.show dom_id(@destroyed.parent, :type_de_champ_add_button) From 91d3f7885dd5a71d5e3405ddfa624310f7f569d7 Mon Sep 17 00:00:00 2001 From: seb-by-ouidou Date: Fri, 1 Sep 2023 12:33:30 +0000 Subject: [PATCH 04/60] fix: fix link confirmer_compte_chaque_connexion_url to faq --- app/views/users/sessions/link_sent.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/users/sessions/link_sent.html.haml b/app/views/users/sessions/link_sent.html.haml index 9f8fd76dc..9010d1e8c 100644 --- a/app/views/users/sessions/link_sent.html.haml +++ b/app/views/users/sessions/link_sent.html.haml @@ -24,6 +24,6 @@ %section %p.fr-mt-3w - Si vous voyez cette page trop souvent, consultez notre aide : #{link_to t("links.common.faq.confirmer_compte_chaque_connexion_url"), **external_link_attributes} + Si vous voyez cette page trop souvent, consultez notre aide : #{link_to t("links.common.faq.confirmer_compte_chaque_connexion_url"), t("links.common.faq.confirmer_compte_chaque_connexion_url"), **external_link_attributes} %p.fr-mt-3w = t('views.users.shared.contact_us_if_any_trouble_html', href: contact_admin_url) From fb8fcd00b34d2734a808c835ba5ce25368760884 Mon Sep 17 00:00:00 2001 From: Kara Diaby Date: Wed, 28 Jun 2023 12:14:04 +0200 Subject: [PATCH 05/60] Passe les champs select au DSFR --- app/assets/stylesheets/buttons.scss | 5 +-- app/assets/stylesheets/forms.scss | 3 +- .../departements_component.html.haml | 2 +- .../drop_down_list_component.rb | 2 +- .../editable_champ_component.rb | 37 ++++++++++++++++++- .../epci_component/epci_component.html.haml | 4 +- .../pays_component/pays_component.html.haml | 2 +- .../regions_component.html.haml | 2 +- .../champ_component/champ_component.html.haml | 1 + 9 files changed, 46 insertions(+), 12 deletions(-) diff --git a/app/assets/stylesheets/buttons.scss b/app/assets/stylesheets/buttons.scss index 57a09165b..98840f1d6 100644 --- a/app/assets/stylesheets/buttons.scss +++ b/app/assets/stylesheets/buttons.scss @@ -316,13 +316,12 @@ ul.dropdown-items { margin-bottom: 2 * $default-spacer; } - input:not(.fr-btn), - select { + input:not(.fr-btn) { width: 200px; display: inline-block; background-color: $light-grey; border: 1px solid $border-grey; - } + } [disabled] { display: none; diff --git a/app/assets/stylesheets/forms.scss b/app/assets/stylesheets/forms.scss index 048252a6e..448576932 100644 --- a/app/assets/stylesheets/forms.scss +++ b/app/assets/stylesheets/forms.scss @@ -246,8 +246,7 @@ } } - input[type=text]:not([data-address='true']), - select { + input[type=text]:not([data-address='true']) { border-radius: 4px; border: solid 1px $border-grey; padding: $default-padding; diff --git a/app/components/editable_champ/departements_component/departements_component.html.haml b/app/components/editable_champ/departements_component/departements_component.html.haml index 5d121dcf1..5324f7204 100644 --- a/app/components/editable_champ/departements_component/departements_component.html.haml +++ b/app/components/editable_champ/departements_component/departements_component.html.haml @@ -1 +1 @@ -= @form.select :value, options, select_options, required: @champ.required?, id: @champ.input_id, aria: { describedby: @champ.describedby_id }, class: "width-33-desktop width-100-mobile" += @form.select :value, options, select_options, required: @champ.required?, id: @champ.input_id, aria: { describedby: @champ.describedby_id }, class: "fr-select" diff --git a/app/components/editable_champ/drop_down_list_component.rb b/app/components/editable_champ/drop_down_list_component.rb index ceed34675..4295114e3 100644 --- a/app/components/editable_champ/drop_down_list_component.rb +++ b/app/components/editable_champ/drop_down_list_component.rb @@ -1,6 +1,6 @@ class EditableChamp::DropDownListComponent < EditableChamp::EditableChampBaseComponent def select_class_names - class_names('width-100': contains_long_option?) + class_names('width-100': contains_long_option?, 'fr-select': true) end def contains_long_option? diff --git a/app/components/editable_champ/editable_champ_component.rb b/app/components/editable_champ/editable_champ_component.rb index a4a553af9..2981008a9 100644 --- a/app/components/editable_champ/editable_champ_component.rb +++ b/app/components/editable_champ/editable_champ_component.rb @@ -21,6 +21,40 @@ class EditableChamp::EditableChampComponent < ApplicationComponent "EditableChamp::#{@champ.type_champ.camelcase}Component".constantize end + def select_group + [ + 'departements', + 'drop_down_list', + 'epci', + 'pays', + 'regions' + ] + end + + def input_group + [ + 'annuaire_education', + 'date', + 'datetime', + 'decimal_number', + 'dgfip', + 'dossier_link', + 'email', + 'iban', + 'integer_number', + 'mesri', + 'number', + 'phone', + 'piece_justificative', + 'pole_emploi', + 'rna', + 'siret', + 'text', + 'textarea', + 'titre_identite' + ] + end + def html_options { class: class_names( @@ -28,7 +62,8 @@ class EditableChamp::EditableChampComponent < ApplicationComponent 'editable-champ': true, "editable-champ-#{@champ.type_champ}": true, "hidden": !@champ.visible?, - "fr-input-group": true + "fr-input-group": input_group.include?(@champ.type_champ), + "fr-select-group": select_group.include?(@champ.type_champ) }.merge(input_group_error_class_names) ), id: @champ.input_group_id, diff --git a/app/components/editable_champ/epci_component/epci_component.html.haml b/app/components/editable_champ/epci_component/epci_component.html.haml index 432ff72be..9d462fc9d 100644 --- a/app/components/editable_champ/epci_component/epci_component.html.haml +++ b/app/components/editable_champ/epci_component/epci_component.html.haml @@ -1,5 +1,5 @@ %label.notice{ for: @champ.code_departement_input_id } Le département de l’EPCI -= @form.select :code_departement, departement_options, departement_select_options, required: @champ.required?, id: @champ.code_departement_input_id, class: "width-33-desktop width-100-mobile" += @form.select :code_departement, departement_options, departement_select_options, required: @champ.required?, id: @champ.code_departement_input_id, class: "width-33-desktop width-100-mobile fr-select" - if @champ.departement? = @form.label "EPCI", for: @champ.epci_input_id - = @form.select :value, epci_options, epci_select_options, required: @champ.required?, id: @champ.epci_input_id, aria: { describedby: @champ.describedby_id }, class: "width-33-desktop width-100-mobile" + = @form.select :value, epci_options, epci_select_options, required: @champ.required?, id: @champ.epci_input_id, aria: { describedby: @champ.describedby_id }, class: "width-33-desktop width-100-mobile fr-select" diff --git a/app/components/editable_champ/pays_component/pays_component.html.haml b/app/components/editable_champ/pays_component/pays_component.html.haml index 5d121dcf1..a42c7af0f 100644 --- a/app/components/editable_champ/pays_component/pays_component.html.haml +++ b/app/components/editable_champ/pays_component/pays_component.html.haml @@ -1 +1 @@ -= @form.select :value, options, select_options, required: @champ.required?, id: @champ.input_id, aria: { describedby: @champ.describedby_id }, class: "width-33-desktop width-100-mobile" += @form.select :value, options, select_options, required: @champ.required?, id: @champ.input_id, aria: { describedby: @champ.describedby_id }, class: "width-33-desktop width-100-mobile fr-select" diff --git a/app/components/editable_champ/regions_component/regions_component.html.haml b/app/components/editable_champ/regions_component/regions_component.html.haml index 5d121dcf1..a42c7af0f 100644 --- a/app/components/editable_champ/regions_component/regions_component.html.haml +++ b/app/components/editable_champ/regions_component/regions_component.html.haml @@ -1 +1 @@ -= @form.select :value, options, select_options, required: @champ.required?, id: @champ.input_id, aria: { describedby: @champ.describedby_id }, class: "width-33-desktop width-100-mobile" += @form.select :value, options, select_options, required: @champ.required?, id: @champ.input_id, aria: { describedby: @champ.describedby_id }, class: "width-33-desktop width-100-mobile fr-select" diff --git a/app/components/types_de_champ_editor/champ_component/champ_component.html.haml b/app/components/types_de_champ_editor/champ_component/champ_component.html.haml index 56da3b30e..39dc48ffe 100644 --- a/app/components/types_de_champ_editor/champ_component/champ_component.html.haml +++ b/app/components/types_de_champ_editor/champ_component/champ_component.html.haml @@ -32,6 +32,7 @@ .cell.flex.justify-start.column.flex-grow = form.label :type_champ, "Type de champ", for: dom_id(type_de_champ, :type_champ) = form.select :type_champ, grouped_options_for_select(types_of_type_de_champ, type_de_champ.type_champ), {}, class: 'fr-select small-margin small inline width-100', id: dom_id(type_de_champ, :type_champ), disabled: coordinate.used_by_routing_rules? + .flex.column.justify-start.flex-grow .cell .flex.align-center From 0ab31ba64933d65387b0d88522316fdb2d5f563c Mon Sep 17 00:00:00 2001 From: Kara Diaby Date: Mon, 3 Jul 2023 11:16:49 +0200 Subject: [PATCH 06/60] Boutons radio au DSFR --- .../champ_label_component.html.haml | 3 +++ .../drop_down_list_component.html.haml | 25 +++++++++++-------- .../drop_down_other_input_component.html.haml | 4 +-- .../editable_champ_component.rb | 11 +++++++- .../editable_champ_component.html.haml | 2 +- .../yes_no_component.html.haml | 16 ++++++------ app/models/champ.rb | 4 +++ app/models/champs/drop_down_list_champ.rb | 8 ++++++ app/models/champs/yes_no_champ.rb | 8 ++++++ spec/system/users/dropdown_spec.rb | 2 +- 10 files changed, 59 insertions(+), 24 deletions(-) diff --git a/app/components/editable_champ/champ_label_component/champ_label_component.html.haml b/app/components/editable_champ/champ_label_component/champ_label_component.html.haml index eda623420..52afe69e9 100644 --- a/app/components/editable_champ/champ_label_component/champ_label_component.html.haml +++ b/app/components/editable_champ/champ_label_component/champ_label_component.html.haml @@ -1,7 +1,10 @@ = # we do this trick because some html elements should use 'label' and some should be plain paragraphs + - if @champ.html_label? = @form.label @champ.main_value_name, id: @champ.labelledby_id, for: @champ.input_id, class: 'fr-label' do - render EditableChamp::ChampLabelContentComponent.new form: @form, champ: @champ, seen_at: @seen_at +- elsif @champ.legend_label? + %legend.fr-fieldset__legend.fr-text--regular= render EditableChamp::ChampLabelContentComponent.new form: @form, champ: @champ, seen_at: @seen_at - else .fr-label.mb-4{ id: @champ.labelledby_id } = render EditableChamp::ChampLabelContentComponent.new form: @form, champ: @champ, seen_at: @seen_at diff --git a/app/components/editable_champ/drop_down_list_component/drop_down_list_component.html.haml b/app/components/editable_champ/drop_down_list_component/drop_down_list_component.html.haml index 94f97cb65..01ada4d72 100644 --- a/app/components/editable_champ/drop_down_list_component/drop_down_list_component.html.haml +++ b/app/components/editable_champ/drop_down_list_component/drop_down_list_component.html.haml @@ -1,20 +1,23 @@ - if @champ.options? - if @champ.render_as_radios? - %fieldset.radios - - @champ.enabled_non_empty_options.each do |option| - %label - = @form.radio_button :value, option - = option + .fr-fieldset__content + - @champ.enabled_non_empty_options.each_with_index do |option, index| + .fr-radio-group + = @form.radio_button :value, option, id: "#{@champ.id}_radio_option_#{index}" + %label.fr-label{ for: "#{@champ.id}_radio_option_#{index}" } + = option - if !@champ.mandatory? - %label.blank-radio - = @form.radio_button :value, '', checked: @champ.value.blank? && !@champ.other? - Non renseigné + .fr-radio-group + = @form.radio_button :value, '', checked: @champ.value.blank? && !@champ.other?, id: "#{@champ.id}_radio_option_blank" + %label.fr-label{ for: "#{@champ.id}_radio_option_blank" } + Non renseigné - if @champ.drop_down_other? - %label - = @form.radio_button :value, Champs::DropDownListChamp::OTHER, checked: @champ.other? - Autre + .fr-radio-group + = @form.radio_button :value, Champs::DropDownListChamp::OTHER, checked: @champ.other?, id: "#{@champ.id}_radio_option_other" + %label.fr-label{ for: "#{@champ.id}_radio_option_other" } + Autre - else = @form.select :value, @champ.options_without_empty_value_when_mandatory(@champ.options), { selected: @champ.selected }, required: @champ.required?, id: @champ.input_id, class: select_class_names, aria: { describedby: @champ.describedby_id } diff --git a/app/components/editable_champ/drop_down_other_input_component/drop_down_other_input_component.html.haml b/app/components/editable_champ/drop_down_other_input_component/drop_down_other_input_component.html.haml index f0160046b..11b222ff2 100644 --- a/app/components/editable_champ/drop_down_other_input_component/drop_down_other_input_component.html.haml +++ b/app/components/editable_champ/drop_down_other_input_component/drop_down_other_input_component.html.haml @@ -1,4 +1,4 @@ .drop_down_other .notice - %label{ for: dom_id(@champ, :value_other) } Veuillez saisir votre autre choix - = @form.text_field :value_other, maxlength: 200, size: nil, id: dom_id(@champ, :value_other) + %label.fr-label{ for: dom_id(@champ, :value_other) } Veuillez saisir votre autre choix + = @form.text_field :value_other, maxlength: 200, size: nil, id: dom_id(@champ, :value_other), class: 'fr-input' diff --git a/app/components/editable_champ/editable_champ_component.rb b/app/components/editable_champ/editable_champ_component.rb index 2981008a9..c416f6643 100644 --- a/app/components/editable_champ/editable_champ_component.rb +++ b/app/components/editable_champ/editable_champ_component.rb @@ -55,6 +55,13 @@ class EditableChamp::EditableChampComponent < ApplicationComponent ] end + def radio_group + [ + 'boolean', + 'yes_no' + ] + end + def html_options { class: class_names( @@ -63,7 +70,9 @@ class EditableChamp::EditableChampComponent < ApplicationComponent "editable-champ-#{@champ.type_champ}": true, "hidden": !@champ.visible?, "fr-input-group": input_group.include?(@champ.type_champ), - "fr-select-group": select_group.include?(@champ.type_champ) + "fr-select-group": select_group.include?(@champ.type_champ), + "fr-radio-group": radio_group.include?(@champ.type_champ), + "fr-fieldset": @champ.legend_label? }.merge(input_group_error_class_names) ), id: @champ.input_group_id, diff --git a/app/components/editable_champ/editable_champ_component/editable_champ_component.html.haml b/app/components/editable_champ/editable_champ_component/editable_champ_component.html.haml index 89b4f3521..b68791fdd 100644 --- a/app/components/editable_champ/editable_champ_component/editable_champ_component.html.haml +++ b/app/components/editable_champ/editable_champ_component/editable_champ_component.html.haml @@ -1,4 +1,4 @@ -= content_tag(:div, html_options) do += content_tag((@champ.legend_label? ? :fieldset : :div), html_options) do - if has_label?(@champ) = render EditableChamp::ChampLabelComponent.new form: @form, champ: @champ, seen_at: @seen_at = render component_class.new(form: @form, champ: @champ, seen_at: @seen_at) diff --git a/app/components/editable_champ/yes_no_component/yes_no_component.html.haml b/app/components/editable_champ/yes_no_component/yes_no_component.html.haml index 7dfb2d9e3..999b0fb05 100644 --- a/app/components/editable_champ/yes_no_component/yes_no_component.html.haml +++ b/app/components/editable_champ/yes_no_component/yes_no_component.html.haml @@ -1,11 +1,11 @@ -%fieldset.fr-fieldset - %legend.fr-fieldset__legend.visually-hidden - = t(".legend") - %label{ for: @champ.yes_input_id } +.fr-fieldset__element.fr-fieldset__element--inline + .fr-radio-group = @form.radio_button :value, true, id: @champ.yes_input_id - = t(".yes") - - %label{ for: @champ.no_input_id } + %label.fr-label{ for: @champ.yes_input_id } + = t(".yes") +.fr-fieldset__element.fr-fieldset__element--inline + .fr-radio-group = @form.radio_button :value, false, id: @champ.no_input_id - = t(".no") + %label.fr-label{ for: @champ.no_input_id } + = t(".no") diff --git a/app/models/champ.rb b/app/models/champ.rb index 3b4bfb310..f8dc56ff9 100644 --- a/app/models/champ.rb +++ b/app/models/champ.rb @@ -160,6 +160,10 @@ class Champ < ApplicationRecord true end + def legend_label? + false + end + def input_group_id "champ-#{html_id}" end diff --git a/app/models/champs/drop_down_list_champ.rb b/app/models/champs/drop_down_list_champ.rb index 72bd4758a..9872957aa 100644 --- a/app/models/champs/drop_down_list_champ.rb +++ b/app/models/champs/drop_down_list_champ.rb @@ -22,6 +22,14 @@ class Champs::DropDownListChamp < Champ end end + def html_label? + !render_as_radios? + end + + def legend_label? + render_as_radios? + end + def selected other? ? OTHER : value end diff --git a/app/models/champs/yes_no_champ.rb b/app/models/champs/yes_no_champ.rb index 3b814e295..3cdf6a1b0 100644 --- a/app/models/champs/yes_no_champ.rb +++ b/app/models/champs/yes_no_champ.rb @@ -1,4 +1,12 @@ class Champs::YesNoChamp < Champs::BooleanChamp + def legend_label? + true + end + + def html_label? + false + end + def yes_input_id "#{input_id}-yes" end diff --git a/spec/system/users/dropdown_spec.rb b/spec/system/users/dropdown_spec.rb index 2d8043132..733d22e37 100644 --- a/spec/system/users/dropdown_spec.rb +++ b/spec/system/users/dropdown_spec.rb @@ -23,7 +23,7 @@ describe 'dropdown list with other option activated', js: true, retry: 3 do scenario 'Select other option and the other input hidden must appear', js: true, retry: 3 do fill_individual - find('.radios').find('label:last-child').find('input').select_option + find('.fr-fieldset__content .fr-radio-group:last-of-type input').select_option expect(page).to have_selector('.drop_down_other', visible: true) end From 37796b8843621d9030d553c1491f7a686a3413ea Mon Sep 17 00:00:00 2001 From: Kara Diaby Date: Mon, 10 Jul 2023 14:48:33 +0200 Subject: [PATCH 07/60] Checkbox au DSFR --- app/assets/stylesheets/forms.scss | 1 - .../champ_label_component.html.haml | 4 ++-- .../checkbox_component/checkbox_component.html.haml | 12 ++++++++---- app/models/champ.rb | 4 ++++ app/models/champs/checkbox_champ.rb | 8 ++++++++ 5 files changed, 22 insertions(+), 7 deletions(-) diff --git a/app/assets/stylesheets/forms.scss b/app/assets/stylesheets/forms.scss index 448576932..372d8f196 100644 --- a/app/assets/stylesheets/forms.scss +++ b/app/assets/stylesheets/forms.scss @@ -125,7 +125,6 @@ &.editable-champ-checkbox { label { - padding-left: 28px; font-weight: normal; } diff --git a/app/components/editable_champ/champ_label_component/champ_label_component.html.haml b/app/components/editable_champ/champ_label_component/champ_label_component.html.haml index 52afe69e9..daf49d3b9 100644 --- a/app/components/editable_champ/champ_label_component/champ_label_component.html.haml +++ b/app/components/editable_champ/champ_label_component/champ_label_component.html.haml @@ -5,8 +5,8 @@ - render EditableChamp::ChampLabelContentComponent.new form: @form, champ: @champ, seen_at: @seen_at - elsif @champ.legend_label? %legend.fr-fieldset__legend.fr-text--regular= render EditableChamp::ChampLabelContentComponent.new form: @form, champ: @champ, seen_at: @seen_at +- elsif @champ.single_checkbox? + -# no label to add - else .fr-label.mb-4{ id: @champ.labelledby_id } = render EditableChamp::ChampLabelContentComponent.new form: @form, champ: @champ, seen_at: @seen_at - - diff --git a/app/components/editable_champ/checkbox_component/checkbox_component.html.haml b/app/components/editable_champ/checkbox_component/checkbox_component.html.haml index 34e6a0a5a..5bc156725 100644 --- a/app/components/editable_champ/checkbox_component/checkbox_component.html.haml +++ b/app/components/editable_champ/checkbox_component/checkbox_component.html.haml @@ -1,4 +1,8 @@ -= @form.check_box :value, - { required: @champ.required?, id: @champ.input_id, checked: @champ.true?, aria: { describedby: @champ.describedby_id }, class: class_names('required' => @champ.required?)}, - 'true', - 'false' +.fr-fieldset__element + .fr-checkbox-group + = @form.check_box :value, + { required: @champ.required?, id: @champ.input_id, checked: @champ.true?, aria: { describedby: @champ.describedby_id }, class: class_names('required' => @champ.required?)}, + 'true', + 'false' + %label.fr-label{ for: @champ.input_id } + = render EditableChamp::ChampLabelContentComponent.new form: @form, champ: @champ, seen_at: @seen_at diff --git a/app/models/champ.rb b/app/models/champ.rb index f8dc56ff9..1b01faa97 100644 --- a/app/models/champ.rb +++ b/app/models/champ.rb @@ -164,6 +164,10 @@ class Champ < ApplicationRecord false end + def single_checkbox? + false + end + def input_group_id "champ-#{html_id}" end diff --git a/app/models/champs/checkbox_champ.rb b/app/models/champs/checkbox_champ.rb index dd67f7be0..671015373 100644 --- a/app/models/champs/checkbox_champ.rb +++ b/app/models/champs/checkbox_champ.rb @@ -12,6 +12,14 @@ class Champs::CheckboxChamp < Champs::BooleanChamp value_with_legacy == TRUE_VALUE end + def html_label? + false + end + + def single_checkbox? + true + end + private # TODO remove when normalize_checkbox_values is over From 58bcdb406dc4a474eadd291bbbc6914f554dfa28 Mon Sep 17 00:00:00 2001 From: Kara Diaby Date: Tue, 18 Jul 2023 17:26:07 +0200 Subject: [PATCH 08/60] Multiple drop down list au DSFR --- app/assets/stylesheets/dsfr.scss | 15 +++++++++++++++ .../multiple_drop_down_list_component.html.haml | 16 +++++++++++----- .../champs/multiple_drop_down_list_champ.rb | 8 ++++++++ 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/app/assets/stylesheets/dsfr.scss b/app/assets/stylesheets/dsfr.scss index 7eb7a5569..7ef1209bc 100644 --- a/app/assets/stylesheets/dsfr.scss +++ b/app/assets/stylesheets/dsfr.scss @@ -99,6 +99,21 @@ fieldset { width: max-content; } +button.fr-tag-bug { + background-color: $blue-france-500; + color: #FFFFFF; + + &:hover { + background-color: #1212FF; + color: #FFFFFF; + } + + .tag-dismiss { + font-size: 1rem; + margin-left: 10px; + } +} + // on veut ferrer à droite le dropdown de sélecteur de langue @media (min-width: 62em) { .fr-nav__item.custom-fr-translate-flex-end { diff --git a/app/components/editable_champ/multiple_drop_down_list_component/multiple_drop_down_list_component.html.haml b/app/components/editable_champ/multiple_drop_down_list_component/multiple_drop_down_list_component.html.haml index d667b87bc..585cbe97f 100644 --- a/app/components/editable_champ/multiple_drop_down_list_component/multiple_drop_down_list_component.html.haml +++ b/app/components/editable_champ/multiple_drop_down_list_component/multiple_drop_down_list_component.html.haml @@ -1,15 +1,21 @@ - if @champ.options? - if @champ.render_as_checkboxes? - = @form.collection_check_boxes(:value, @champ.enabled_non_empty_options, :to_s, :to_s) do |b| + %legend.fr-fieldset__legend--regular.fr-fieldset__legend= render EditableChamp::ChampLabelContentComponent.new form: @form, champ: @champ, seen_at: @seen_at + = @form.collection_check_boxes :value, @champ.enabled_non_empty_options, :to_s, :to_s do |b| - tag.div(class: 'editable-champ editable-champ-checkbox') do - - b.label(for: @champ.checkbox_id(b.value)) do - - b.check_box({ multiple: true, checked: @champ.selected_options.include?(b.value), aria: { describedby: @champ.describedby_id }, id: @champ.checkbox_id(b.value) }) + b.text + %fieldset.fr-fieldset__element + .fr-checkbox-group + = b.check_box(checked: @champ.selected_options.include?(b.value), aria: { describedby: @champ.describedby_id }, id: @champ.checkbox_id(b.value), class: 'fr-checkbox-group__checkbox') + %label.fr-label{ for: @champ.checkbox_id(b.value) } + = b.text + - else %div{ 'data-turbo-focus-group': true } - if @champ.selected_options.present? .fr-mb-2w - @champ.selected_options.each do |option| - = render NestedForms::OwnedButtonComponent.new(formaction: champs_options_path(@champ.id, option:), http_method: :delete, opt: { class: 'fr-tag fr-tag--dismiss fr-mb-1w fr-mr-1w', id: @champ.checkbox_id(option) }) do + = render NestedForms::OwnedButtonComponent.new(formaction: champs_options_path(@champ.id, option:), http_method: :delete, opt: { class: 'fr-tag fr-tag-bug fr-mb-1w fr-mr-1w', id: @champ.checkbox_id(option) }) do = option + %span.tag-dismiss x - if @champ.unselected_options.present? - = @form.select :value, @champ.unselected_options, { selected: '', include_blank: '' }, id: @champ.input_id, aria: { describedby: @champ.describedby_id } + = @form.select :value, @champ.unselected_options, { selected: '', include_blank: '' }, id: @champ.input_id, aria: { describedby: @champ.describedby_id }, class: 'fr-select' diff --git a/app/models/champs/multiple_drop_down_list_champ.rb b/app/models/champs/multiple_drop_down_list_champ.rb index 1fd8c0190..00bf4a2fb 100644 --- a/app/models/champs/multiple_drop_down_list_champ.rb +++ b/app/models/champs/multiple_drop_down_list_champ.rb @@ -43,6 +43,14 @@ class Champs::MultipleDropDownListChamp < Champ enabled_non_empty_options.size <= THRESHOLD_NB_OPTIONS_AS_CHECKBOX end + def html_label? + !render_as_checkboxes? + end + + def single_checkbox? + render_as_checkboxes? + end + def blank? selected_options.blank? end From 7bc7106a96469175aedccb6019a8fd4abf883230 Mon Sep 17 00:00:00 2001 From: Kara Diaby Date: Tue, 25 Jul 2023 08:49:58 +0200 Subject: [PATCH 09/60] Passage au DSFR 1.10.00 --- package.json | 2 +- yarn.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index c118473b9..e2dbca844 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "@coldwired/actions": "^0.11.2", "@coldwired/turbo-stream": "^0.11.1", "@coldwired/utils": "^0.11.1", - "@gouvfr/dsfr": "^1.7.2", + "@gouvfr/dsfr": "^1.10.0", "@graphiql/plugin-explorer": "^0.2.0", "@graphiql/toolkit": "^0.8.4", "@headlessui/react": "^1.6.6", diff --git a/yarn.lock b/yarn.lock index fdf6cac76..af3baf93b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1361,9 +1361,9 @@ "@floating-ui/dom" "^1.3.0" "@gouvfr/dsfr@^1.7.2": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@gouvfr/dsfr/-/dsfr-1.8.1.tgz#2484eb8ad9a73b5f01c5f41f49146d1aa8a71b7b" - integrity sha512-XpVFdvhtalA5jSAhzzNaMd+/Hvf8Ef9jCdAZhuukEEMo2/cWvCgzz9tfbE+9QTJDIVP+EwJ7aCGWcXUSWkOHJg== + version "1.10.0" + resolved "https://registry.yarnpkg.com/@gouvfr/dsfr/-/dsfr-1.10.0.tgz#a3f4939c728e35d8c9ecf06f7a62369ae46256db" + integrity sha512-fHqGCvc8jGtkX2AKRCWi9o3jf/kirP/BeeZ2FBVGwS9Oxd8KsG22xk/6Tls8nA+qPaI+2ZkZQxATBV8KlhwNhQ== "@graphiql/plugin-explorer@^0.2.0": version "0.2.0" From 74d04c84f5ef1593080e07757b2b56ef106c6c34 Mon Sep 17 00:00:00 2001 From: Kara Diaby Date: Tue, 25 Jul 2023 09:21:16 +0200 Subject: [PATCH 10/60] Multiple drop down list au DSFR --- .../multiple_drop_down_list_component.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/editable_champ/multiple_drop_down_list_component/multiple_drop_down_list_component.html.haml b/app/components/editable_champ/multiple_drop_down_list_component/multiple_drop_down_list_component.html.haml index 585cbe97f..882773bde 100644 --- a/app/components/editable_champ/multiple_drop_down_list_component/multiple_drop_down_list_component.html.haml +++ b/app/components/editable_champ/multiple_drop_down_list_component/multiple_drop_down_list_component.html.haml @@ -12,7 +12,7 @@ - else %div{ 'data-turbo-focus-group': true } - if @champ.selected_options.present? - .fr-mb-2w + .fr-mb-2w{ "data-turbo": "true" } - @champ.selected_options.each do |option| = render NestedForms::OwnedButtonComponent.new(formaction: champs_options_path(@champ.id, option:), http_method: :delete, opt: { class: 'fr-tag fr-tag-bug fr-mb-1w fr-mr-1w', id: @champ.checkbox_id(option) }) do = option From 27e7bc1dbd3efe845e7a5226bec731958c65905c Mon Sep 17 00:00:00 2001 From: Kara Diaby Date: Thu, 27 Jul 2023 11:02:00 +0200 Subject: [PATCH 11/60] =?UTF-8?q?Deux=20menus=20deroulants=20li=C3=A9s=20a?= =?UTF-8?q?u=20DSFR?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../linked_drop_down_list_component.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/components/editable_champ/linked_drop_down_list_component/linked_drop_down_list_component.html.haml b/app/components/editable_champ/linked_drop_down_list_component/linked_drop_down_list_component.html.haml index 4ed612278..bbc11174f 100644 --- a/app/components/editable_champ/linked_drop_down_list_component/linked_drop_down_list_component.html.haml +++ b/app/components/editable_champ/linked_drop_down_list_component/linked_drop_down_list_component.html.haml @@ -1,5 +1,5 @@ - if @champ.options? - = @form.select :primary_value, @champ.primary_options, {}, required: @champ.required?, id: @champ.input_id, aria: { describedby: @champ.describedby_id } + = @form.select :primary_value, @champ.primary_options, {}, required: @champ.required?, class: 'fr-select', id: @champ.input_id, aria: { describedby: @champ.describedby_id } - if @champ.has_secondary_options_for_primary? .secondary = @form.label :secondary_value, for: "#{@champ.input_id}-secondary" do @@ -7,6 +7,6 @@ - if @champ.drop_down_secondary_description.present? .notice{ id: "#{@champ.describedby_id}-secondary" } = render SimpleFormatComponent.new(@champ.drop_down_secondary_description, allow_a: true) - = @form.select :secondary_value, @champ.secondary_options[@champ.primary_value], {}, required: @champ.required?, id: "#{@champ.input_id}-secondary", aria: { describedby: "#{@champ.describedby_id}-secondary" } + = @form.select :secondary_value, @champ.secondary_options[@champ.primary_value], {}, required: @champ.required?, class: 'fr-select', id: "#{@champ.input_id}-secondary", aria: { describedby: "#{@champ.describedby_id}-secondary" } - else = @form.hidden_field :secondary_value, value: '' From b42fd4ceb6329d29e8b62aadc2c63daa69ff8ffe Mon Sep 17 00:00:00 2001 From: Kara Diaby Date: Fri, 28 Jul 2023 17:19:47 +0200 Subject: [PATCH 12/60] Fix admin/show after dsfr 1.10 --- .../administrateurs_component.html.haml | 2 +- .../card/annotations_component/annotations_component.html.haml | 2 +- .../api_entreprise_component.html.haml | 2 +- .../api_particulier_component.html.haml | 2 +- .../card/attestation_component/attestation_component.html.haml | 2 +- .../procedure/card/champs_component/champs_component.html.haml | 2 +- .../dossier_submitted_message_component.html.haml | 2 +- .../procedure/card/emails_component/emails_component.html.haml | 2 +- .../card/experts_component/experts_component.html.haml | 2 +- .../instructeurs_component/instructeurs_component.html.haml | 2 +- .../modifications_component/modifications_component.html.haml | 2 +- .../card/mon_avis_component/mon_avis_component.html.haml | 2 +- .../presentation_component/presentation_component.html.haml | 2 +- .../card/service_component/service_component.html.haml | 2 +- .../card/sva_svr_component/sva_svr_component.html.haml | 2 +- .../procedure/card/zones_component/zones_component.html.haml | 2 +- app/views/layouts/_header.haml | 3 +-- 17 files changed, 17 insertions(+), 18 deletions(-) diff --git a/app/components/procedure/card/administrateurs_component/administrateurs_component.html.haml b/app/components/procedure/card/administrateurs_component/administrateurs_component.html.haml index 5b435f55f..bf035cf3b 100644 --- a/app/components/procedure/card/administrateurs_component/administrateurs_component.html.haml +++ b/app/components/procedure/card/administrateurs_component/administrateurs_component.html.haml @@ -1,6 +1,6 @@ .fr-col-6.fr-col-md-4.fr-col-lg-3 = link_to admin_procedure_administrateurs_path(@procedure), id: 'administrateurs', class: 'fr-tile fr-enlarge-link' do - .fr-tile__body.flex.justify-between + .fr-tile__body.flex.column.align-center.justify-between %div %span.icon.accept %p.fr-tile-status-accept Validé diff --git a/app/components/procedure/card/annotations_component/annotations_component.html.haml b/app/components/procedure/card/annotations_component/annotations_component.html.haml index beb2eef3a..0eb809dd7 100644 --- a/app/components/procedure/card/annotations_component/annotations_component.html.haml +++ b/app/components/procedure/card/annotations_component/annotations_component.html.haml @@ -1,6 +1,6 @@ .fr-col-6.fr-col-md-4.fr-col-lg-3 = link_to annotations_admin_procedure_path(@procedure), class: 'fr-tile fr-enlarge-link', title: error_messages do - .fr-tile__body.flex.justify-between + .fr-tile__body.flex.column.align-center.justify-between - if error_messages.present? %div %span.icon.refuse diff --git a/app/components/procedure/card/api_entreprise_component/api_entreprise_component.html.haml b/app/components/procedure/card/api_entreprise_component/api_entreprise_component.html.haml index 929ba9f5c..8981e5b02 100644 --- a/app/components/procedure/card/api_entreprise_component/api_entreprise_component.html.haml +++ b/app/components/procedure/card/api_entreprise_component/api_entreprise_component.html.haml @@ -1,6 +1,6 @@ .fr-col-6.fr-col-md-4.fr-col-lg-3 = link_to jeton_admin_procedure_path(@procedure), class: 'fr-tile fr-enlarge-link' do - .fr-tile__body.flex.justify-between + .fr-tile__body.flex.column.align-center.justify-between - if @procedure.api_entreprise_token.present? %div %span.icon.accept diff --git a/app/components/procedure/card/api_particulier_component/api_particulier_component.html.haml b/app/components/procedure/card/api_particulier_component/api_particulier_component.html.haml index 06874d392..6eaf18232 100644 --- a/app/components/procedure/card/api_particulier_component/api_particulier_component.html.haml +++ b/app/components/procedure/card/api_particulier_component/api_particulier_component.html.haml @@ -1,6 +1,6 @@ .fr-col-6.fr-col-md-4.fr-col-lg-3 = link_to admin_procedure_api_particulier_path(@procedure), class: 'fr-tile fr-enlarge-link', id: 'api-particulier' do - .fr-tile__body.flex.justify-between + .fr-tile__body.flex.column.align-center.justify-between - if @procedure.api_particulier_token.present? %div %span.icon.accept diff --git a/app/components/procedure/card/attestation_component/attestation_component.html.haml b/app/components/procedure/card/attestation_component/attestation_component.html.haml index 62de3d440..20cd5c3d0 100644 --- a/app/components/procedure/card/attestation_component/attestation_component.html.haml +++ b/app/components/procedure/card/attestation_component/attestation_component.html.haml @@ -1,6 +1,6 @@ .fr-col-6.fr-col-md-4.fr-col-lg-3 = link_to edit_admin_procedure_attestation_template_path(@procedure), class: 'fr-tile fr-enlarge-link' do - .fr-tile__body.flex.justify-between + .fr-tile__body.flex.column.align-center.justify-between - if @procedure.attestation_template&.activated? %div - if error_messages.present? diff --git a/app/components/procedure/card/champs_component/champs_component.html.haml b/app/components/procedure/card/champs_component/champs_component.html.haml index 1ab9018dd..669497630 100644 --- a/app/components/procedure/card/champs_component/champs_component.html.haml +++ b/app/components/procedure/card/champs_component/champs_component.html.haml @@ -1,6 +1,6 @@ .fr-col-6.fr-col-md-4.fr-col-lg-3 = link_to champs_admin_procedure_path(@procedure), class: 'fr-tile fr-enlarge-link', title: error_messages do - .fr-tile__body.flex.justify-between + .fr-tile__body.flex.column.align-center.justify-between - if error_messages.present? %div %span.icon.refuse diff --git a/app/components/procedure/card/dossier_submitted_message_component/dossier_submitted_message_component.html.haml b/app/components/procedure/card/dossier_submitted_message_component/dossier_submitted_message_component.html.haml index 179759d75..69146624e 100644 --- a/app/components/procedure/card/dossier_submitted_message_component/dossier_submitted_message_component.html.haml +++ b/app/components/procedure/card/dossier_submitted_message_component/dossier_submitted_message_component.html.haml @@ -1,6 +1,6 @@ .fr-col-6.fr-col-md-4.fr-col-lg-3 = link_to edit_admin_procedure_dossier_submitted_message_path(@procedure), class: 'fr-tile fr-enlarge-link' do - .fr-tile__body.flex.justify-between + .fr-tile__body.flex.column.align-center.justify-between - if @procedure.active_dossier_submitted_message.present? %div %span.icon.accept diff --git a/app/components/procedure/card/emails_component/emails_component.html.haml b/app/components/procedure/card/emails_component/emails_component.html.haml index 5918224ba..42ee0b234 100644 --- a/app/components/procedure/card/emails_component/emails_component.html.haml +++ b/app/components/procedure/card/emails_component/emails_component.html.haml @@ -1,6 +1,6 @@ .fr-col-6.fr-col-md-4.fr-col-lg-3 = link_to admin_procedure_mail_templates_path(@procedure), class: 'fr-tile fr-enlarge-link' do - .fr-tile__body.flex.justify-between + .fr-tile__body.flex.column.align-center.justify-between %div - if error_messages.present? %span.icon.refuse diff --git a/app/components/procedure/card/experts_component/experts_component.html.haml b/app/components/procedure/card/experts_component/experts_component.html.haml index 406b0d900..1ef946814 100644 --- a/app/components/procedure/card/experts_component/experts_component.html.haml +++ b/app/components/procedure/card/experts_component/experts_component.html.haml @@ -1,6 +1,6 @@ .fr-col-6.fr-col-md-4.fr-col-lg-3 = link_to admin_procedure_experts_path(@procedure), class: 'fr-tile fr-enlarge-link' do - .fr-tile__body.flex.justify-between + .fr-tile__body.flex.column.align-center.justify-between %div %span.icon.preview %p.fr-tile-status-todo À configurer diff --git a/app/components/procedure/card/instructeurs_component/instructeurs_component.html.haml b/app/components/procedure/card/instructeurs_component/instructeurs_component.html.haml index 970c7ff43..102b5a687 100644 --- a/app/components/procedure/card/instructeurs_component/instructeurs_component.html.haml +++ b/app/components/procedure/card/instructeurs_component/instructeurs_component.html.haml @@ -1,6 +1,6 @@ .fr-col-6.fr-col-md-4.fr-col-lg-3 = link_to admin_procedure_groupe_instructeurs_path(@procedure), id: 'groupe-instructeurs', class: 'fr-tile fr-enlarge-link' do - .fr-tile__body.flex.justify-between + .fr-tile__body.flex.column.align-center.justify-between - if @procedure.routing_enabled? || @procedure.instructeurs.present? %div %span.icon.accept diff --git a/app/components/procedure/card/modifications_component/modifications_component.html.haml b/app/components/procedure/card/modifications_component/modifications_component.html.haml index 57d3cbe1d..677847f6a 100644 --- a/app/components/procedure/card/modifications_component/modifications_component.html.haml +++ b/app/components/procedure/card/modifications_component/modifications_component.html.haml @@ -1,6 +1,6 @@ .fr-col-6.fr-col-md-4.fr-col-lg-3 = link_to modifications_admin_procedure_path(@procedure), id: 'modifications', class: 'fr-tile fr-enlarge-link' do - .fr-tile__body.flex.justify-between + .fr-tile__body.flex.column.align-center.justify-between %div %span.icon.accept %p.fr-tile-status-accept Activée diff --git a/app/components/procedure/card/mon_avis_component/mon_avis_component.html.haml b/app/components/procedure/card/mon_avis_component/mon_avis_component.html.haml index d06775674..564451ead 100644 --- a/app/components/procedure/card/mon_avis_component/mon_avis_component.html.haml +++ b/app/components/procedure/card/mon_avis_component/mon_avis_component.html.haml @@ -1,6 +1,6 @@ .fr-col-6.fr-col-md-4.fr-col-lg-3 = link_to monavis_admin_procedure_path(@procedure), class: 'fr-tile fr-enlarge-link' do - .fr-tile__body.flex.justify-between + .fr-tile__body.flex.column.align-center.justify-between - if @procedure.monavis_embed.present? %div %span.icon.accept diff --git a/app/components/procedure/card/presentation_component/presentation_component.html.haml b/app/components/procedure/card/presentation_component/presentation_component.html.haml index 22e996a71..0620c11cc 100644 --- a/app/components/procedure/card/presentation_component/presentation_component.html.haml +++ b/app/components/procedure/card/presentation_component/presentation_component.html.haml @@ -1,6 +1,6 @@ .fr-col-6.fr-col-md-4.fr-col-lg-3 = link_to edit_admin_procedure_path(@procedure), id: 'presentation', class: 'fr-tile fr-enlarge-link' do - .fr-tile__body.flex.justify-between + .fr-tile__body.flex.column.align-center.justify-between %div %span.icon.accept %p.fr-tile-status-accept Validé diff --git a/app/components/procedure/card/service_component/service_component.html.haml b/app/components/procedure/card/service_component/service_component.html.haml index 9077a2206..2073b990b 100644 --- a/app/components/procedure/card/service_component/service_component.html.haml +++ b/app/components/procedure/card/service_component/service_component.html.haml @@ -1,6 +1,6 @@ .fr-col-6.fr-col-md-4.fr-col-lg-3 = link_to service_link, class: 'fr-tile fr-enlarge-link', id: 'service' do - .fr-tile__body.flex.justify-between + .fr-tile__body.flex.column.align-center.justify-between - if @procedure.service_id.present? %div %span.icon.accept diff --git a/app/components/procedure/card/sva_svr_component/sva_svr_component.html.haml b/app/components/procedure/card/sva_svr_component/sva_svr_component.html.haml index ac9dc7a1b..906e78976 100644 --- a/app/components/procedure/card/sva_svr_component/sva_svr_component.html.haml +++ b/app/components/procedure/card/sva_svr_component/sva_svr_component.html.haml @@ -1,6 +1,6 @@ .fr-col-6.fr-col-md-4.fr-col-lg-3 = link_to edit_admin_procedure_sva_svr_path(@procedure), class: 'fr-tile fr-enlarge-link', id: 'sva' do - .fr-tile__body.flex.justify-between + .fr-tile__body.flex.column.align-center.justify-between - if @procedure.sva_svr_enabled? %div %span.icon.accept diff --git a/app/components/procedure/card/zones_component/zones_component.html.haml b/app/components/procedure/card/zones_component/zones_component.html.haml index 7f0d43b8e..d2ca9bd67 100644 --- a/app/components/procedure/card/zones_component/zones_component.html.haml +++ b/app/components/procedure/card/zones_component/zones_component.html.haml @@ -1,6 +1,6 @@ .fr-col-6.fr-col-md-4.fr-col-lg-3 = link_to zones_admin_procedure_path(@procedure), id: 'zones', class: 'fr-tile fr-enlarge-link' do - .fr-tile__body.flex.justify-between + .fr-tile__body.flex.column.align-center.justify-between - if @procedure.zones.size >= 1 %div %span.icon.accept diff --git a/app/views/layouts/_header.haml b/app/views/layouts/_header.haml index f00aca282..58e290b9b 100644 --- a/app/views/layouts/_header.haml +++ b/app/views/layouts/_header.haml @@ -51,7 +51,7 @@ = render partial: 'shared/help/help_dropdown_instructeur' - else // NB: on mobile in order to have links correctly aligned, we need a left icon - = link_to t('help'), t("links.common.faq.url"), class: 'fr-btn fr-icon-questionnaire-line fr-btn--icon-left', title: new_tab_suffix(t('help')), **external_link_attributes + = link_to t('help'), t("links.common.faq.url"), class: 'fr-btn dropdown-button', title: new_tab_suffix(t('help')), **external_link_attributes @@ -100,4 +100,3 @@ = render partial: 'layouts/header/avis_tab', locals: { current_expert: current_expert } = yield(:notice_info) - From b7f3fc151511ed3c32bfcaf4b2866ae09b90ddbe Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 28 Jul 2023 17:32:41 +0200 Subject: [PATCH 13/60] fix(node): version --- .node-version | 2 +- package.json | 2 +- yarn.lock | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.node-version b/.node-version index 832d38506..603606bc9 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -16.14.0 +18.17.0 diff --git a/package.json b/package.json index e2dbca844..203a6915a 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "coverage": "vitest run --coverage" }, "engines": { - "node": ">= 16.*" + "node": ">= 18.17.0" }, "graphdoc": { "schemaFile": "./app/graphql/schema.json", diff --git a/yarn.lock b/yarn.lock index af3baf93b..9e161cc3c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1360,7 +1360,7 @@ dependencies: "@floating-ui/dom" "^1.3.0" -"@gouvfr/dsfr@^1.7.2": +"@gouvfr/dsfr@^1.10.0": version "1.10.0" resolved "https://registry.yarnpkg.com/@gouvfr/dsfr/-/dsfr-1.10.0.tgz#a3f4939c728e35d8c9ecf06f7a62369ae46256db" integrity sha512-fHqGCvc8jGtkX2AKRCWi9o3jf/kirP/BeeZ2FBVGwS9Oxd8KsG22xk/6Tls8nA+qPaI+2ZkZQxATBV8KlhwNhQ== From f40192faecc05b0e246149f5079184aa75d4fb51 Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 28 Jul 2023 17:54:38 +0200 Subject: [PATCH 14/60] amelioration(dsfr.radio/checkbox): utilise les classes de fieldset error/valid plutot que les classes pour les input-group --- app/components/dsfr/input_errorable.rb | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/app/components/dsfr/input_errorable.rb b/app/components/dsfr/input_errorable.rb index 294c2cd27..b5f1a7d94 100644 --- a/app/components/dsfr/input_errorable.rb +++ b/app/components/dsfr/input_errorable.rb @@ -22,10 +22,17 @@ module Dsfr end def input_group_error_class_names - { - "fr-input-group--error": errors_on_attribute?, - "fr-input-group--valid": !errors_on_attribute? && errors_on_another_attribute? - } + if @champ && @champ.legend_label? + { + "fr-fieldset--error": errors_on_attribute?, + "fr-fieldset--valid": !errors_on_attribute? && errors_on_another_attribute? + } + else + { + "fr-input-group--error": errors_on_attribute?, + "fr-input-group--valid": !errors_on_attribute? && errors_on_another_attribute? + } + end end def input_error_class_names From 370d8a8cf17919e1178e395b015ae32b27a3fdc5 Mon Sep 17 00:00:00 2001 From: Kara Diaby Date: Fri, 4 Aug 2023 13:41:02 +0200 Subject: [PATCH 15/60] tests --- spec/support/shared_examples_for_prefilled_dossier.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/support/shared_examples_for_prefilled_dossier.rb b/spec/support/shared_examples_for_prefilled_dossier.rb index fdfa7df7c..6a2593e2b 100644 --- a/spec/support/shared_examples_for_prefilled_dossier.rb +++ b/spec/support/shared_examples_for_prefilled_dossier.rb @@ -20,7 +20,7 @@ shared_examples "the user has got a prefilled dossier, owned by themselves" do expect(page).to have_field(text_repetition_libelle, with: text_repetition_value) expect(page).to have_field(integer_repetition_libelle, with: integer_repetition_value) expect(page).to have_field(type_de_champ_datetime.libelle, with: datetime_value) - expect(page).to have_css('label', text: type_de_champ_multiple_drop_down_list.libelle) + expect(page).to have_css('legend', text: type_de_champ_multiple_drop_down_list.libelle) expect(page).to have_content(multiple_drop_down_list_values.first) expect(page).to have_content(multiple_drop_down_list_values.last) expect(page).to have_field("Le département de l’EPCI", with: epci_value.first) From 6aec12f02f23cfea05b1d123531b3709e162cf17 Mon Sep 17 00:00:00 2001 From: Martin Date: Mon, 14 Aug 2023 15:20:27 +0200 Subject: [PATCH 16/60] correctif(spec): mise a jour des brouillons_spec.rb pour adapter l'integration des checkbox au DSFR --- spec/system/users/brouillon_spec.rb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/spec/system/users/brouillon_spec.rb b/spec/system/users/brouillon_spec.rb index d4ef793f1..0b7846fa0 100644 --- a/spec/system/users/brouillon_spec.rb +++ b/spec/system/users/brouillon_spec.rb @@ -432,17 +432,17 @@ describe 'The user' do fill_individual expect(page).to have_css('label', text: 'age du candidat', visible: true) - expect(page).to have_no_css('label', text: 'permis de conduire', visible: true) - expect(page).to have_no_css('legend h2', text: 'info voiture', visible: true) + expect(page).to have_no_css('legend', text: 'permis de conduire', visible: true) + expect(page).to have_no_css('legend', text: 'info voiture', visible: true) expect(page).to have_no_css('label', text: 'tonnage', visible: true) fill_in('age du candidat (facultatif)', with: '18') - expect(page).to have_css('label', text: 'permis de conduire', visible: true) - expect(page).to have_css('legend h2', text: 'info voiture', visible: true) + expect(page).to have_css('legend', text: 'permis de conduire', visible: true) + expect(page).to have_css('legend', text: 'info voiture', visible: true) expect(page).to have_no_css('label', text: 'tonnage', visible: true) - choose('Oui') - expect(page).to have_css('label', text: 'permis de conduire', visible: true) + page.find('label', text: 'Oui').click + expect(page).to have_css('legend', text: 'permis de conduire', visible: true) expect(page).to have_css('label', text: 'tonnage', visible: true) fill_in('tonnage', with: '1') @@ -453,7 +453,7 @@ describe 'The user' do expect(page).to have_no_css('label', text: 'parking', visible: true) fill_in('age du candidat (facultatif)', with: '2') - expect(page).to have_no_css('label', text: 'permis de conduire', visible: true) + expect(page).to have_no_css('legend', text: 'permis de conduire', visible: true) expect(page).to have_no_css('label', text: 'tonnage', visible: true) click_on 'Déposer le dossier' @@ -461,14 +461,14 @@ describe 'The user' do click_on 'Modifier mon dossier' expect(page).to have_css('label', text: 'age du candidat', visible: true) - expect(page).to have_no_css('label', text: 'permis de conduire', visible: true) + expect(page).to have_no_css('legend', text: 'permis de conduire', visible: true) expect(page).to have_no_css('label', text: 'tonnage', visible: true) fill_in('age du candidat (facultatif)', with: '18') wait_for_autosave # the champ keeps their previous value so they are all displayed - expect(page).to have_css('label', text: 'permis de conduire', visible: true) + expect(page).to have_css('legend', text: 'permis de conduire', visible: true) expect(page).to have_css('label', text: 'tonnage', visible: true) end end From a947457b5788b0d64a6e8a3d6945d945b6e89ca2 Mon Sep 17 00:00:00 2001 From: Martin Date: Thu, 17 Aug 2023 16:43:39 +0200 Subject: [PATCH 17/60] amelioration(champs.epci): passe le champs epci au DSFR et l'encapsule dans un fieldset --- .../epci_component/epci_component.html.haml | 12 ++++++++---- app/models/champs/epci_champ.rb | 12 ++++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/app/components/editable_champ/epci_component/epci_component.html.haml b/app/components/editable_champ/epci_component/epci_component.html.haml index 9d462fc9d..6a0f132f5 100644 --- a/app/components/editable_champ/epci_component/epci_component.html.haml +++ b/app/components/editable_champ/epci_component/epci_component.html.haml @@ -1,5 +1,9 @@ -%label.notice{ for: @champ.code_departement_input_id } Le département de l’EPCI -= @form.select :code_departement, departement_options, departement_select_options, required: @champ.required?, id: @champ.code_departement_input_id, class: "width-33-desktop width-100-mobile fr-select" +.fr-fieldset__element + = @form.label "Le département de l’EPCI", for: @champ.code_departement_input_id, class: 'fr-label' + = @form.select :code_departement, departement_options, departement_select_options, required: @champ.required?, id: @champ.code_departement_input_id, class: "width-33-desktop width-100-mobile fr-select" + - if @champ.departement? - = @form.label "EPCI", for: @champ.epci_input_id - = @form.select :value, epci_options, epci_select_options, required: @champ.required?, id: @champ.epci_input_id, aria: { describedby: @champ.describedby_id }, class: "width-33-desktop width-100-mobile fr-select" + .fr-fieldset__element + .fr-select-group + = @form.label "EPCI", for: @champ.epci_input_id, class: 'fr-label' + = @form.select :value, epci_options, epci_select_options, required: @champ.required?, id: @champ.epci_input_id, aria: { describedby: @champ.describedby_id }, class: "width-33-desktop width-100-mobile fr-select" diff --git a/app/models/champs/epci_champ.rb b/app/models/champs/epci_champ.rb index 3b65f864f..01fe0bf7f 100644 --- a/app/models/champs/epci_champ.rb +++ b/app/models/champs/epci_champ.rb @@ -22,6 +22,18 @@ class Champs::EpciChamp < Champs::TextChamp code_departement.present? end + def dsfr_champ_container + :fieldset + end + + def html_label? + false + end + + def legend_label? + true + end + def code? code.present? end From d164605f3295edadf9dc137032695f940988aba6 Mon Sep 17 00:00:00 2001 From: Martin Date: Thu, 17 Aug 2023 16:45:23 +0200 Subject: [PATCH 18/60] =?UTF-8?q?amelioration(champs.commune):=20passe=20l?= =?UTF-8?q?e=20champs=20commune=20au=20DSFR,=20l'encapsule=20dans=20un=20f?= =?UTF-8?q?ieldset=20et=20am=C3=A9liore=20le=20wording?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../communes_component.en.yml | 3 +- .../communes_component.fr.yml | 3 +- .../communes_component.html.haml | 31 +++++++++++++------ app/models/champs/commune_champ.rb | 12 +++++++ 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/app/components/editable_champ/communes_component/communes_component.en.yml b/app/components/editable_champ/communes_component/communes_component.en.yml index 94928ea15..7bd07cc72 100644 --- a/app/components/editable_champ/communes_component/communes_component.en.yml +++ b/app/components/editable_champ/communes_component/communes_component.en.yml @@ -1,4 +1,5 @@ --- en: - postal_code: Enter the postal code then select the municipality from the list + postal_code: "Enter the postal code" + commune: "Select the municipality from the list" not_found: No municipality found for postal code %{postal_code}. Please check that you haven't made any mistakes. diff --git a/app/components/editable_champ/communes_component/communes_component.fr.yml b/app/components/editable_champ/communes_component/communes_component.fr.yml index 77b096d10..160339a51 100644 --- a/app/components/editable_champ/communes_component/communes_component.fr.yml +++ b/app/components/editable_champ/communes_component/communes_component.fr.yml @@ -1,4 +1,5 @@ --- fr: - postal_code: Renseignez le code postal puis sélectionnez la commune dans la liste + postal_code: "Renseignez le code postal" + commune: "Sélectionnez la commune dans la liste" not_found: Aucune commune trouvée pour le code postal %{postal_code}. Verifiez que vous n'avez pas fait d’erreur. diff --git a/app/components/editable_champ/communes_component/communes_component.html.haml b/app/components/editable_champ/communes_component/communes_component.html.haml index 849a5e1c8..fa297cf12 100644 --- a/app/components/editable_champ/communes_component/communes_component.html.haml +++ b/app/components/editable_champ/communes_component/communes_component.html.haml @@ -1,13 +1,26 @@ -%label.notice{ for: code_postal_input_id }= t('.postal_code') -= @form.text_field :code_postal, required: @champ.required?, id: code_postal_input_id, class: "width-33-desktop width-100-mobile small-margin" -- if @champ.code_postal? +.fr-fieldset__element.fr-mb-0 + .fr-input-group + = @form.label :code_postal, t('.postal_code').html_safe, class: 'fr-label', for: code_postal_input_id + = @form.text_field :code_postal, required: @champ.required?, id: code_postal_input_id, class: "width-33-desktop width-100-mobile small-margin fr-input" + - if @champ.code_postal? + - if commune_options.empty? + .fr-error-text.mb-4= t('.not_found', postal_code: @champ.code_postal) + +.fr-fieldset__element.fr-mb-0 - if commune_options.empty? - .fr-error-text.mb-4= t('.not_found', postal_code: @champ.code_postal) + - #noop - elsif commune_options.size <= 3 - %fieldset.radios + %fieldset.fr-fieldset + .fr-fieldset__legend--regular.fr-fieldset__legend= t('.commune').html_safe + - commune_options.each.with_index do |(option, value), index| - %label - = @form.radio_button :value, value, checked: @champ.selected == value, id: index == 0 ? @champ.input_id : nil - = option + .fr-fieldset__element + .fr-radio-group + = @form.radio_button :value, value, checked: @champ.selected == value, id: index == 0 ? @champ.input_id : nil + = @form.label :value, option, for: option, class: 'fr-label' + / %label + / = @form.radio_button :value, value, checked: @champ.selected == value, id: index == 0 ? @champ.input_id : nil + / = option - else - = @form.select :value, commune_options, commune_select_options, required: @champ.required?, id: @champ.input_id, aria: { describedby: @champ.describedby_id }, class: "width-33-desktop width-100-mobile" + = @form.label :value, t('.commune').html_safe, for: @champ.input_id, class: 'fr-label' + = @form.select :value, commune_options, commune_select_options, required: @champ.required?, id: @champ.input_id, aria: { describedby: @champ.describedby_id }, class: "width-33-desktop width-100-mobile fr-select" diff --git a/app/models/champs/commune_champ.rb b/app/models/champs/commune_champ.rb index 9b9ca0335..6631735f0 100644 --- a/app/models/champs/commune_champ.rb +++ b/app/models/champs/commune_champ.rb @@ -88,6 +88,18 @@ class Champs::CommuneChamp < Champs::TextChamp end end + def html_label? + false + end + + def legend_label? + true + end + + def dsfr_champ_container + :fieldset + end + private def safe_to_s From b34b4fcb0c31ec9bb53fd1a6f0f0efe827789e19 Mon Sep 17 00:00:00 2001 From: Martin Date: Thu, 17 Aug 2023 17:11:58 +0200 Subject: [PATCH 19/60] tech(extraction.erreurs): isole l'affichage des erreurs d'un champs ds un composant --- .../dsfr/input_status_message_component.rb | 13 +++++++++++++ .../input_status_message_component.html.haml | 3 +++ .../editable_champ_component.html.haml | 9 +-------- 3 files changed, 17 insertions(+), 8 deletions(-) create mode 100644 app/components/dsfr/input_status_message_component.rb create mode 100644 app/components/dsfr/input_status_message_component/input_status_message_component.html.haml diff --git a/app/components/dsfr/input_status_message_component.rb b/app/components/dsfr/input_status_message_component.rb new file mode 100644 index 000000000..a2b8fa510 --- /dev/null +++ b/app/components/dsfr/input_status_message_component.rb @@ -0,0 +1,13 @@ +module Dsfr + class InputStatusMessageComponent < ApplicationComponent + def initialize(errors_on_attribute:, error_full_messages:, described_by:) + @errors_on_attribute = errors_on_attribute + @error_full_messages = error_full_messages + @described_by = described_by + end + + def render? + @errors_on_attribute + end + end +end diff --git a/app/components/dsfr/input_status_message_component/input_status_message_component.html.haml b/app/components/dsfr/input_status_message_component/input_status_message_component.html.haml new file mode 100644 index 000000000..5b745b4dc --- /dev/null +++ b/app/components/dsfr/input_status_message_component/input_status_message_component.html.haml @@ -0,0 +1,3 @@ +.fr-messages-group{ id: @describedby_id } + - @error_full_messages.each do |error_message| + %p{ class: class_names('fr-message' => true, "fr-message--#{@errors_on_attribute ? 'error' : 'valid'}" => true)}= error_message diff --git a/app/components/editable_champ/editable_champ_component/editable_champ_component.html.haml b/app/components/editable_champ/editable_champ_component/editable_champ_component.html.haml index b68791fdd..26c1178f4 100644 --- a/app/components/editable_champ/editable_champ_component/editable_champ_component.html.haml +++ b/app/components/editable_champ/editable_champ_component/editable_champ_component.html.haml @@ -3,13 +3,6 @@ = render EditableChamp::ChampLabelComponent.new form: @form, champ: @champ, seen_at: @seen_at = render component_class.new(form: @form, champ: @champ, seen_at: @seen_at) - - if errors_on_attribute? - - if error_full_messages.size == 1 - %p.fr-error-text{ id: describedby_id }= error_full_messages.first - - else - .fr-error-text{ id: describedby_id } - %ul.list-style-type-none.fr-pl-0 - - error_full_messages.each do |error_message| - %li= error_message + = render Dsfr::InputStatusMessageComponent.new(errors_on_attribute: errors_on_attribute?, error_full_messages: error_full_messages, described_by: describedby_id) = @form.hidden_field :id, value: @champ.id From 77106ee84ccddbf8a91d89f80e446bea3e2ac449 Mon Sep 17 00:00:00 2001 From: Martin Date: Thu, 17 Aug 2023 17:16:37 +0200 Subject: [PATCH 20/60] amelioration(dsfr): quelques maj de style pour des espacements --- app/assets/stylesheets/forms.scss | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/assets/stylesheets/forms.scss b/app/assets/stylesheets/forms.scss index 372d8f196..94c266825 100644 --- a/app/assets/stylesheets/forms.scss +++ b/app/assets/stylesheets/forms.scss @@ -20,7 +20,8 @@ font-style: italic; } - .fr-input-group { + .fr-input-group, + .fr-select-group { margin-bottom: 1rem; } @@ -209,18 +210,17 @@ } } - .fr-label { + .fr-label .fr-hint-text > *, + .fr-fieldset__legend .fr-hint-text > * { // la description d'un champ peut contenir du markup (markdown->html), // on herite donc la fontsize/mrgin/padding du fr-hint-text - .fr-hint-text > * { - font-size: inherit; - margin: inherit; - padding: inherit; - } + font-size: inherit; + margin: inherit; + padding: inherit; } input[type=password], - select { + select:not(.fr-select) { display: block; margin-bottom: 0; From 40d1de22eac2468d130e244ff6c26d01df8d26d1 Mon Sep 17 00:00:00 2001 From: Martin Date: Thu, 17 Aug 2023 17:17:21 +0200 Subject: [PATCH 21/60] correctif(champ_label_component): ajoute le labelledby_id aux sans quoi les ancres vers les erreurs plantent --- .../champ_label_component/champ_label_component.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/editable_champ/champ_label_component/champ_label_component.html.haml b/app/components/editable_champ/champ_label_component/champ_label_component.html.haml index daf49d3b9..f40eefc8f 100644 --- a/app/components/editable_champ/champ_label_component/champ_label_component.html.haml +++ b/app/components/editable_champ/champ_label_component/champ_label_component.html.haml @@ -4,7 +4,7 @@ = @form.label @champ.main_value_name, id: @champ.labelledby_id, for: @champ.input_id, class: 'fr-label' do - render EditableChamp::ChampLabelContentComponent.new form: @form, champ: @champ, seen_at: @seen_at - elsif @champ.legend_label? - %legend.fr-fieldset__legend.fr-text--regular= render EditableChamp::ChampLabelContentComponent.new form: @form, champ: @champ, seen_at: @seen_at + %legend.fr-fieldset__legend.fr-text--regular{ id: @champ.labelledby_id }= render EditableChamp::ChampLabelContentComponent.new form: @form, champ: @champ, seen_at: @seen_at - elsif @champ.single_checkbox? -# no label to add - else From 3697d8335de98584dd0309a5fab176ed3133bef4 Mon Sep 17 00:00:00 2001 From: Martin Date: Thu, 17 Aug 2023 17:18:32 +0200 Subject: [PATCH 22/60] =?UTF-8?q?correctif(checkbox=5Fcomponent):=20ajoute?= =?UTF-8?q?=20le=20labelledby=5Fid=20au=20