From d35ceb7214533228c0320885cf3979fce6faa16d Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Thu, 8 Sep 2022 11:25:39 +0200 Subject: [PATCH 1/2] fix(champs): finish EditableChampComponent refactor --- .../editable_champ/address_component.rb | 6 +-- .../annuaire_education_component.rb | 6 +-- .../editable_champ/carte_component.rb | 6 +-- .../editable_champ/champ_label_component.rb | 6 ++- .../champ_label_component.html.haml | 10 ++--- .../champ_label_content_component.rb | 4 +- .../champ_label_content_component.html.haml | 6 +-- .../editable_champ/checkbox_component.rb | 5 +-- .../editable_champ/civilite_component.rb | 5 +-- .../editable_champ/cnaf_component.rb | 5 +-- .../editable_champ/communes_component.rb | 6 +-- .../editable_champ/date_component.rb | 5 +-- .../editable_champ/datetime_component.rb | 6 +-- .../decimal_number_component.rb | 5 +-- .../editable_champ/departements_component.rb | 6 +-- .../editable_champ/dgfip_component.rb | 5 +-- .../editable_champ/dossier_link_component.rb | 5 +-- .../drop_down_list_component.rb | 5 +-- .../drop_down_other_input_component.rb | 5 +-- .../editable_champ_base_component.rb | 5 +++ .../editable_champ_component.rb | 44 +++++++++++++++++- .../editable_champ_component.html.haml | 8 ++-- .../editable_champ/email_component.rb | 5 +-- .../editable_champ/engagement_component.rb | 5 +-- .../editable_champ/explication_component.rb | 6 +-- .../header_section_component.rb | 5 +-- .../editable_champ/iban_component.rb | 5 +-- .../integer_number_component.rb | 5 +-- .../linked_drop_down_list_component.rb | 6 +-- .../linked_drop_down_list_component.html.haml | 2 +- .../editable_champ/mesri_component.rb | 5 +-- .../multiple_drop_down_list_component.rb | 6 +-- .../editable_champ/number_component.rb | 5 +-- .../editable_champ/pays_component.rb | 6 +-- .../editable_champ/phone_component.rb | 5 +-- .../piece_justificative_component.rb | 5 +-- .../editable_champ/pole_emploi_component.rb | 5 +-- .../editable_champ/regions_component.rb | 6 +-- .../editable_champ/repetition_component.rb | 5 +-- .../repetition_component.html.haml | 2 +- .../repetition_row_component.rb | 4 +- .../repetition_row_component.html.haml | 2 +- .../editable_champ/siret_component.rb | 5 +-- .../editable_champ/text_component.rb | 5 +-- .../editable_champ/textarea_component.rb | 6 +-- .../titre_identite_component.rb | 5 +-- .../editable_champ/yes_no_component.rb | 5 +-- app/helpers/champ_helper.rb | 45 ------------------- app/models/champ.rb | 1 + app/models/type_de_champ.rb | 4 ++ .../show.turbo_stream.haml | 3 +- app/views/root/patron.html.haml | 4 +- app/views/shared/dossiers/_edit.html.haml | 2 +- .../dossiers/_edit_annotations.html.haml | 11 ++--- .../editable_champs/_champ_label.html.haml | 10 ----- .../_champ_label_content.html.haml | 11 ----- .../editable_champs/_editable_champ.html.haml | 13 ------ .../editable_champ_component_spec.rb} | 28 +++++++----- 58 files changed, 135 insertions(+), 282 deletions(-) create mode 100644 app/components/editable_champ/editable_champ_base_component.rb delete mode 100644 app/views/shared/dossiers/editable_champs/_champ_label.html.haml delete mode 100644 app/views/shared/dossiers/editable_champs/_champ_label_content.html.haml delete mode 100644 app/views/shared/dossiers/editable_champs/_editable_champ.html.haml rename spec/{helpers/champ_helper_spec.rb => components/editable_champ/editable_champ_component_spec.rb} (64%) diff --git a/app/components/editable_champ/address_component.rb b/app/components/editable_champ/address_component.rb index 66526d057..0b1db8bff 100644 --- a/app/components/editable_champ/address_component.rb +++ b/app/components/editable_champ/address_component.rb @@ -1,7 +1,3 @@ -class EditableChamp::AddressComponent < ApplicationComponent +class EditableChamp::AddressComponent < EditableChamp::EditableChampBaseComponent include ApplicationHelper - - def initialize(form:, champ:) - @form, @champ = form, champ - end end diff --git a/app/components/editable_champ/annuaire_education_component.rb b/app/components/editable_champ/annuaire_education_component.rb index e5e1ff8e4..2dd780eb1 100644 --- a/app/components/editable_champ/annuaire_education_component.rb +++ b/app/components/editable_champ/annuaire_education_component.rb @@ -1,7 +1,3 @@ -class EditableChamp::AnnuaireEducationComponent < ApplicationComponent +class EditableChamp::AnnuaireEducationComponent < EditableChamp::EditableChampBaseComponent include ApplicationHelper - - def initialize(form:, champ:) - @form, @champ = form, champ - end end diff --git a/app/components/editable_champ/carte_component.rb b/app/components/editable_champ/carte_component.rb index 21aec9f77..737ffdf87 100644 --- a/app/components/editable_champ/carte_component.rb +++ b/app/components/editable_champ/carte_component.rb @@ -1,7 +1,3 @@ -class EditableChamp::CarteComponent < ApplicationComponent +class EditableChamp::CarteComponent < EditableChamp::EditableChampBaseComponent include ApplicationHelper - - def initialize(form:, champ:) - @form, @champ = form, champ - end end diff --git a/app/components/editable_champ/champ_label_component.rb b/app/components/editable_champ/champ_label_component.rb index ec1c01f8e..3f8f8abf9 100644 --- a/app/components/editable_champ/champ_label_component.rb +++ b/app/components/editable_champ/champ_label_component.rb @@ -1,5 +1,7 @@ class EditableChamp::ChampLabelComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ + include StringToHtmlHelper + + def initialize(form:, champ:, seen_at: nil) + @form, @champ, @seen_at = form, champ, seen_at end end 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 6af20926c..e8e5874ba 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,10 +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 do - = render partial: 'shared/dossiers/editable_champs/champ_label_content', locals: { champ: champ, seen_at: seen_at } + = @form.label @champ.main_value_name, id: @champ.labelledby_id, for: @champ.input_id do + = render EditableChamp::ChampLabelContentComponent.new champ: @champ, seen_at: @seen_at - else - .@form-label.mb-4 - = render partial: 'shared/dossiers/editable_champs/champ_label_content', locals: { champ: champ, seen_at: seen_at } + .form-label.mb-4 + = render EditableChamp::ChampLabelContentComponent.new champ: @champ, seen_at: @seen_at - if @champ.description.present? - .notice{ id: @champ.describedby_id }= string_to_html(champ.description) + .notice{ id: @champ.describedby_id }= string_to_html(@champ.description) diff --git a/app/components/editable_champ/champ_label_content_component.rb b/app/components/editable_champ/champ_label_content_component.rb index 08a56e9b1..44cf3ece6 100644 --- a/app/components/editable_champ/champ_label_content_component.rb +++ b/app/components/editable_champ/champ_label_content_component.rb @@ -1,5 +1,5 @@ class EditableChamp::ChampLabelContentComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ + def initialize(champ:, seen_at: nil) + @champ, @seen_at = champ, seen_at end end diff --git a/app/components/editable_champ/champ_label_content_component/champ_label_content_component.html.haml b/app/components/editable_champ/champ_label_content_component/champ_label_content_component.html.haml index 0282402f3..8d13141a6 100644 --- a/app/components/editable_champ/champ_label_content_component/champ_label_content_component.html.haml +++ b/app/components/editable_champ/champ_label_content_component/champ_label_content_component.html.haml @@ -2,10 +2,10 @@ - if @champ.type_de_champ.mandatory? %span.mandatory * -- if @champ.updated_at.present? && seen_at.present? - %span.updated-at{ class: highlight_if_unseen_class(seen_at, @champ.updated_at) } +- if @champ.updated_at.present? && @seen_at.present? + %span.updated-at{ class: highlight_if_unseen_class(@seen_at, @champ.updated_at) } = "modifié le #{try_format_datetime(@champ.updated_at)}" -- if @champ.rebased_at.present? && champ.rebased_at > (seen_at || champ.updated_at) && current_user.owns_or_invite?(champ.dossier) +- if @champ.rebased_at.present? && @champ.rebased_at > (@seen_at || @champ.updated_at) && controller.current_user.owns_or_invite?(@champ.dossier) %span.updated-at.highlighted Le type de ce @champ où sa description a été modifiée par l'administration. Vérifier son contenu. diff --git a/app/components/editable_champ/checkbox_component.rb b/app/components/editable_champ/checkbox_component.rb index a578c398d..e007157b9 100644 --- a/app/components/editable_champ/checkbox_component.rb +++ b/app/components/editable_champ/checkbox_component.rb @@ -1,5 +1,2 @@ -class EditableChamp::CheckboxComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::CheckboxComponent < EditableChamp::EditableChampBaseComponent end diff --git a/app/components/editable_champ/civilite_component.rb b/app/components/editable_champ/civilite_component.rb index 0edd4c2f7..7c2434207 100644 --- a/app/components/editable_champ/civilite_component.rb +++ b/app/components/editable_champ/civilite_component.rb @@ -1,5 +1,2 @@ -class EditableChamp::CiviliteComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::CiviliteComponent < EditableChamp::EditableChampBaseComponent end diff --git a/app/components/editable_champ/cnaf_component.rb b/app/components/editable_champ/cnaf_component.rb index 853a7eba5..4e3fc65cc 100644 --- a/app/components/editable_champ/cnaf_component.rb +++ b/app/components/editable_champ/cnaf_component.rb @@ -1,5 +1,2 @@ -class EditableChamp::CnafComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::CnafComponent < EditableChamp::EditableChampBaseComponent end diff --git a/app/components/editable_champ/communes_component.rb b/app/components/editable_champ/communes_component.rb index b9ba37fac..cc5bfee0b 100644 --- a/app/components/editable_champ/communes_component.rb +++ b/app/components/editable_champ/communes_component.rb @@ -1,7 +1,3 @@ -class EditableChamp::CommunesComponent < ApplicationComponent +class EditableChamp::CommunesComponent < EditableChamp::EditableChampBaseComponent include ApplicationHelper - - def initialize(form:, champ:) - @form, @champ = form, champ - end end diff --git a/app/components/editable_champ/date_component.rb b/app/components/editable_champ/date_component.rb index 58920f3ad..2ba79bbb6 100644 --- a/app/components/editable_champ/date_component.rb +++ b/app/components/editable_champ/date_component.rb @@ -1,5 +1,2 @@ -class EditableChamp::DateComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::DateComponent < EditableChamp::EditableChampBaseComponent end diff --git a/app/components/editable_champ/datetime_component.rb b/app/components/editable_champ/datetime_component.rb index ad19da13b..09f7337e5 100644 --- a/app/components/editable_champ/datetime_component.rb +++ b/app/components/editable_champ/datetime_component.rb @@ -1,8 +1,4 @@ -class EditableChamp::DatetimeComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end - +class EditableChamp::DatetimeComponent < EditableChamp::EditableChampBaseComponent def datetime_start_year(date) if date == nil || date.year == 0 || date.year >= Date.today.year - 1 Date.today.year - 1 diff --git a/app/components/editable_champ/decimal_number_component.rb b/app/components/editable_champ/decimal_number_component.rb index 7686e31b0..f60a85669 100644 --- a/app/components/editable_champ/decimal_number_component.rb +++ b/app/components/editable_champ/decimal_number_component.rb @@ -1,5 +1,2 @@ -class EditableChamp::DecimalNumberComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::DecimalNumberComponent < EditableChamp::EditableChampBaseComponent end diff --git a/app/components/editable_champ/departements_component.rb b/app/components/editable_champ/departements_component.rb index efa804718..79771c075 100644 --- a/app/components/editable_champ/departements_component.rb +++ b/app/components/editable_champ/departements_component.rb @@ -1,7 +1,3 @@ -class EditableChamp::DepartementsComponent < ApplicationComponent +class EditableChamp::DepartementsComponent < EditableChamp::EditableChampBaseComponent include ApplicationHelper - - def initialize(form:, champ:) - @form, @champ = form, champ - end end diff --git a/app/components/editable_champ/dgfip_component.rb b/app/components/editable_champ/dgfip_component.rb index ca3260e19..d9ecc6b8d 100644 --- a/app/components/editable_champ/dgfip_component.rb +++ b/app/components/editable_champ/dgfip_component.rb @@ -1,5 +1,2 @@ -class EditableChamp::DgfipComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::DgfipComponent < EditableChamp::EditableChampBaseComponent end diff --git a/app/components/editable_champ/dossier_link_component.rb b/app/components/editable_champ/dossier_link_component.rb index 840d83146..e26ff0ea8 100644 --- a/app/components/editable_champ/dossier_link_component.rb +++ b/app/components/editable_champ/dossier_link_component.rb @@ -1,5 +1,2 @@ -class EditableChamp::DossierLinkComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::DossierLinkComponent < EditableChamp::EditableChampBaseComponent end diff --git a/app/components/editable_champ/drop_down_list_component.rb b/app/components/editable_champ/drop_down_list_component.rb index c904bf925..def70d331 100644 --- a/app/components/editable_champ/drop_down_list_component.rb +++ b/app/components/editable_champ/drop_down_list_component.rb @@ -1,5 +1,2 @@ -class EditableChamp::DropDownListComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::DropDownListComponent < EditableChamp::EditableChampBaseComponent end diff --git a/app/components/editable_champ/drop_down_other_input_component.rb b/app/components/editable_champ/drop_down_other_input_component.rb index 35a8cfef1..94e695d4c 100644 --- a/app/components/editable_champ/drop_down_other_input_component.rb +++ b/app/components/editable_champ/drop_down_other_input_component.rb @@ -1,5 +1,2 @@ -class EditableChamp::DropDownOtherInputComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::DropDownOtherInputComponent < EditableChamp::EditableChampBaseComponent end diff --git a/app/components/editable_champ/editable_champ_base_component.rb b/app/components/editable_champ/editable_champ_base_component.rb new file mode 100644 index 000000000..08408a95c --- /dev/null +++ b/app/components/editable_champ/editable_champ_base_component.rb @@ -0,0 +1,5 @@ +class EditableChamp::EditableChampBaseComponent < ApplicationComponent + def initialize(form:, champ:, seen_at: nil) + @form, @champ, @seen_at = form, champ, seen_at + end +end diff --git a/app/components/editable_champ/editable_champ_component.rb b/app/components/editable_champ/editable_champ_component.rb index c19d07e0e..f7d96fd3c 100644 --- a/app/components/editable_champ/editable_champ_component.rb +++ b/app/components/editable_champ/editable_champ_component.rb @@ -1,5 +1,45 @@ class EditableChamp::EditableChampComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ + include StringToHtmlHelper + + def initialize(form:, champ:, seen_at: nil) + @form, @champ, @seen_at = form, champ, seen_at + end + + private + + def has_label?(champ) + types_without_label = [TypeDeChamp.type_champs.fetch(:header_section), TypeDeChamp.type_champs.fetch(:explication)] + !types_without_label.include?(@champ.type_champ) + end + + def component_class + "EditableChamp::#{@champ.type_champ.camelcase}Component".constantize + end + + def html_options + { + class: "editable-champ-#{@champ.type_champ} #{'hidden' if !@champ.visible?}", + id: @champ.input_group_id, + data: { controller: stimulus_controller } + } + end + + def stimulus_controller + if !@champ.repetition? && @champ.fillable? + # This is an editable champ. Lets find what controllers it might need. + controllers = [] + + # This is a public champ – it can have an autosave controller. + if @champ.public? + controllers << 'autosave' + end + + # This is a dropdown champ. Activate special behaviours it might have. + if @champ.simple_drop_down_list? || @champ.linked_drop_down_list? + controllers << 'champ-dropdown' + end + + controllers.join(' ') + end end end 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 5356a4c76..733b8c6d5 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,13 +1,13 @@ -.editable-@champ{ class: "editable-champ-#{champ.type_champ} #{champ.visible? ? '' : 'hidden'}", id: champ.input_group_id, data: editable_champ_controller(champ) } +.editable-champ{ html_options } - if @champ.repetition? %h3.header-subsection= @champ.libelle - if @champ.description.present? %p.notice= string_to_html(@champ.description, false) - elsif has_label?(@champ) - = render partial: 'shared/dossiers/editable_champs/champ_label', locals: { form: @form, champ: champ, seen_at: defined?(seen_at) ? seen_at : nil } + = render EditableChamp::ChampLabelComponent.new form: @form, champ: @champ, seen_at: @seen_at - if @champ.type_champ == "titre_identite" %p.notice Carte nationale d’identité (uniquement le recto), passeport, titre de séjour ou autre justificatif d’identité. Formats acceptés : jpg/png - = @form.hidden_field :id, value: @champ.id, data: champ.repetition? ? { id: true } : {} - = render partial: "shared/dossiers/editable_champs/#{champ.type_champ}", locals: { form: @form, champ: champ } + = @form.hidden_field :id, value: @champ.id, data: @champ.repetition? ? { id: true } : {} + = render component_class.new(form: @form, champ: @champ, seen_at: @seen_at) diff --git a/app/components/editable_champ/email_component.rb b/app/components/editable_champ/email_component.rb index 18d673f10..fbc0774e2 100644 --- a/app/components/editable_champ/email_component.rb +++ b/app/components/editable_champ/email_component.rb @@ -1,5 +1,2 @@ -class EditableChamp::EmailComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::EmailComponent < EditableChamp::EditableChampBaseComponent end diff --git a/app/components/editable_champ/engagement_component.rb b/app/components/editable_champ/engagement_component.rb index a768738c8..829adce26 100644 --- a/app/components/editable_champ/engagement_component.rb +++ b/app/components/editable_champ/engagement_component.rb @@ -1,5 +1,2 @@ -class EditableChamp::EngagementComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::EngagementComponent < EditableChamp::EditableChampBaseComponent end diff --git a/app/components/editable_champ/explication_component.rb b/app/components/editable_champ/explication_component.rb index 12be0cef2..f3173419d 100644 --- a/app/components/editable_champ/explication_component.rb +++ b/app/components/editable_champ/explication_component.rb @@ -1,7 +1,3 @@ -class EditableChamp::ExplicationComponent < ApplicationComponent +class EditableChamp::ExplicationComponent < EditableChamp::EditableChampBaseComponent include StringToHtmlHelper - - def initialize(form:, champ:) - @form, @champ = form, champ - end end diff --git a/app/components/editable_champ/header_section_component.rb b/app/components/editable_champ/header_section_component.rb index 03cf9a489..f5e71cfce 100644 --- a/app/components/editable_champ/header_section_component.rb +++ b/app/components/editable_champ/header_section_component.rb @@ -1,5 +1,2 @@ -class EditableChamp::HeaderSectionComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::HeaderSectionComponent < EditableChamp::EditableChampBaseComponent end diff --git a/app/components/editable_champ/iban_component.rb b/app/components/editable_champ/iban_component.rb index 4313b4471..0b89043fd 100644 --- a/app/components/editable_champ/iban_component.rb +++ b/app/components/editable_champ/iban_component.rb @@ -1,5 +1,2 @@ -class EditableChamp::IbanComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::IbanComponent < EditableChamp::EditableChampBaseComponent end diff --git a/app/components/editable_champ/integer_number_component.rb b/app/components/editable_champ/integer_number_component.rb index c9063bc04..4d3678ef9 100644 --- a/app/components/editable_champ/integer_number_component.rb +++ b/app/components/editable_champ/integer_number_component.rb @@ -1,5 +1,2 @@ -class EditableChamp::IntegerNumberComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::IntegerNumberComponent < EditableChamp::EditableChampBaseComponent end diff --git a/app/components/editable_champ/linked_drop_down_list_component.rb b/app/components/editable_champ/linked_drop_down_list_component.rb index d1b17ab15..e31d49b44 100644 --- a/app/components/editable_champ/linked_drop_down_list_component.rb +++ b/app/components/editable_champ/linked_drop_down_list_component.rb @@ -1,5 +1,3 @@ -class EditableChamp::LinkedDropDownListComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::LinkedDropDownListComponent < EditableChamp::EditableChampBaseComponent + include StringToHtmlHelper end 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 62cc369b3..317d4db6e 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 @@ -10,7 +10,7 @@ - if @champ.type_de_champ.mandatory? %span.mandatory * - if @champ.drop_down_secondary_description.present? - .notice{ id: "#{@champ.describedby_id}-secondary" }= helpers.string_to_html(@champ.drop_down_secondary_description) + .notice{ id: "#{@champ.describedby_id}-secondary" }= string_to_html(@champ.drop_down_secondary_description) = @form.select :secondary_value, @champ.secondary_options[@champ.primary_value], {}, diff --git a/app/components/editable_champ/mesri_component.rb b/app/components/editable_champ/mesri_component.rb index 4984c670a..decea7e4b 100644 --- a/app/components/editable_champ/mesri_component.rb +++ b/app/components/editable_champ/mesri_component.rb @@ -1,5 +1,2 @@ -class EditableChamp::MesriComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::MesriComponent < EditableChamp::EditableChampBaseComponent end diff --git a/app/components/editable_champ/multiple_drop_down_list_component.rb b/app/components/editable_champ/multiple_drop_down_list_component.rb index 85c1c3289..f8742dd6e 100644 --- a/app/components/editable_champ/multiple_drop_down_list_component.rb +++ b/app/components/editable_champ/multiple_drop_down_list_component.rb @@ -1,7 +1,3 @@ -class EditableChamp::MultipleDropDownListComponent < ApplicationComponent +class EditableChamp::MultipleDropDownListComponent < EditableChamp::EditableChampBaseComponent include ApplicationHelper - - def initialize(form:, champ:) - @form, @champ = form, champ - end end diff --git a/app/components/editable_champ/number_component.rb b/app/components/editable_champ/number_component.rb index 32c9676e5..474cf7498 100644 --- a/app/components/editable_champ/number_component.rb +++ b/app/components/editable_champ/number_component.rb @@ -1,5 +1,2 @@ -class EditableChamp::NumberComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::NumberComponent < EditableChamp::EditableChampBaseComponent end diff --git a/app/components/editable_champ/pays_component.rb b/app/components/editable_champ/pays_component.rb index dc6ff48a0..e6d4da952 100644 --- a/app/components/editable_champ/pays_component.rb +++ b/app/components/editable_champ/pays_component.rb @@ -1,7 +1,3 @@ -class EditableChamp::PaysComponent < ApplicationComponent +class EditableChamp::PaysComponent < EditableChamp::EditableChampBaseComponent include ApplicationHelper - - def initialize(form:, champ:) - @form, @champ = form, champ - end end diff --git a/app/components/editable_champ/phone_component.rb b/app/components/editable_champ/phone_component.rb index 425ae808e..792813f65 100644 --- a/app/components/editable_champ/phone_component.rb +++ b/app/components/editable_champ/phone_component.rb @@ -1,5 +1,2 @@ -class EditableChamp::PhoneComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::PhoneComponent < EditableChamp::EditableChampBaseComponent end diff --git a/app/components/editable_champ/piece_justificative_component.rb b/app/components/editable_champ/piece_justificative_component.rb index 466eb2a5d..fb6469fea 100644 --- a/app/components/editable_champ/piece_justificative_component.rb +++ b/app/components/editable_champ/piece_justificative_component.rb @@ -1,5 +1,2 @@ -class EditableChamp::PieceJustificativeComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::PieceJustificativeComponent < EditableChamp::EditableChampBaseComponent end diff --git a/app/components/editable_champ/pole_emploi_component.rb b/app/components/editable_champ/pole_emploi_component.rb index 3bbf839df..49479bbf9 100644 --- a/app/components/editable_champ/pole_emploi_component.rb +++ b/app/components/editable_champ/pole_emploi_component.rb @@ -1,5 +1,2 @@ -class EditableChamp::PoleEmploiComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::PoleEmploiComponent < EditableChamp::EditableChampBaseComponent end diff --git a/app/components/editable_champ/regions_component.rb b/app/components/editable_champ/regions_component.rb index 2fb023459..5aea4ff3b 100644 --- a/app/components/editable_champ/regions_component.rb +++ b/app/components/editable_champ/regions_component.rb @@ -1,7 +1,3 @@ -class EditableChamp::RegionsComponent < ApplicationComponent +class EditableChamp::RegionsComponent < EditableChamp::EditableChampBaseComponent include ApplicationHelper - - def initialize(form:, champ:) - @form, @champ = form, champ - end end diff --git a/app/components/editable_champ/repetition_component.rb b/app/components/editable_champ/repetition_component.rb index f0b52655c..03fba3de5 100644 --- a/app/components/editable_champ/repetition_component.rb +++ b/app/components/editable_champ/repetition_component.rb @@ -1,5 +1,2 @@ -class EditableChamp::RepetitionComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::RepetitionComponent < EditableChamp::EditableChampBaseComponent end diff --git a/app/components/editable_champ/repetition_component/repetition_component.html.haml b/app/components/editable_champ/repetition_component/repetition_component.html.haml index 1aef84f0d..5bc1238f2 100644 --- a/app/components/editable_champ/repetition_component/repetition_component.html.haml +++ b/app/components/editable_champ/repetition_component/repetition_component.html.haml @@ -1,6 +1,6 @@ .repetition{ id: dom_id(@champ, :rows) } - @champ.rows.each do |champs| - = render EditableChamp::RepetitionRowComponent.new(form: @form, champ: @champ, row: champs) + = render EditableChamp::RepetitionRowComponent.new(form: @form, champ: @champ, row: champs, seen_at: @seen_at) .actions{ 'data-turbo': 'true' } = link_to champs_repetition_path(@champ.id), data: { turbo_method: :post }, class: 'button add-row' do diff --git a/app/components/editable_champ/repetition_row_component.rb b/app/components/editable_champ/repetition_row_component.rb index 27f945875..e647b5640 100644 --- a/app/components/editable_champ/repetition_row_component.rb +++ b/app/components/editable_champ/repetition_row_component.rb @@ -1,5 +1,5 @@ class EditableChamp::RepetitionRowComponent < ApplicationComponent - def initialize(form:, champ:, row:) - @form, @champ, @row = form, champ, row + def initialize(form:, champ:, row:, seen_at: nil) + @form, @champ, @row, @seen_at = form, champ, row, seen_at end end diff --git a/app/components/editable_champ/repetition_row_component/repetition_row_component.html.haml b/app/components/editable_champ/repetition_row_component/repetition_row_component.html.haml index f9b0511f5..2974eed79 100644 --- a/app/components/editable_champ/repetition_row_component/repetition_row_component.html.haml +++ b/app/components/editable_champ/repetition_row_component/repetition_row_component.html.haml @@ -2,7 +2,7 @@ .row{ id: row_dom_id } - @row.each do |champ| = fields_for champ.input_name, champ do |form| - = render partial: 'shared/dossiers/editable_champs/editable_champ', locals: { form: form, champ: champ } + = render EditableChamp::EditableChampComponent.new form: form, champ: champ, seen_at: @seen_at .flex.row-reverse{ 'data-turbo': 'true' } = link_to champs_repetition_path(@champ.id, champ_ids: @row.map(&:id), row_id: row_dom_id), data: { turbo_method: :delete }, class: 'button danger remove-row' do diff --git a/app/components/editable_champ/siret_component.rb b/app/components/editable_champ/siret_component.rb index 6baf95934..a1c9717c1 100644 --- a/app/components/editable_champ/siret_component.rb +++ b/app/components/editable_champ/siret_component.rb @@ -1,5 +1,2 @@ -class EditableChamp::SiretComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::SiretComponent < EditableChamp::EditableChampBaseComponent end diff --git a/app/components/editable_champ/text_component.rb b/app/components/editable_champ/text_component.rb index 17bed9ead..da8e529ea 100644 --- a/app/components/editable_champ/text_component.rb +++ b/app/components/editable_champ/text_component.rb @@ -1,5 +1,2 @@ -class EditableChamp::TextComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::TextComponent < EditableChamp::EditableChampBaseComponent end diff --git a/app/components/editable_champ/textarea_component.rb b/app/components/editable_champ/textarea_component.rb index b8cae1798..41fa0fc9f 100644 --- a/app/components/editable_champ/textarea_component.rb +++ b/app/components/editable_champ/textarea_component.rb @@ -1,7 +1,3 @@ -class EditableChamp::TextareaComponent < ApplicationComponent +class EditableChamp::TextareaComponent < EditableChamp::EditableChampBaseComponent include HtmlToStringHelper - - def initialize(form:, champ:) - @form, @champ = form, champ - end end diff --git a/app/components/editable_champ/titre_identite_component.rb b/app/components/editable_champ/titre_identite_component.rb index 4295cbd6c..7bb8536d0 100644 --- a/app/components/editable_champ/titre_identite_component.rb +++ b/app/components/editable_champ/titre_identite_component.rb @@ -1,5 +1,2 @@ -class EditableChamp::TitreIdentiteComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::TitreIdentiteComponent < EditableChamp::EditableChampBaseComponent end diff --git a/app/components/editable_champ/yes_no_component.rb b/app/components/editable_champ/yes_no_component.rb index e67b391bb..7bb8da3c0 100644 --- a/app/components/editable_champ/yes_no_component.rb +++ b/app/components/editable_champ/yes_no_component.rb @@ -1,5 +1,2 @@ -class EditableChamp::YesNoComponent < ApplicationComponent - def initialize(form:, champ:) - @form, @champ = form, champ - end +class EditableChamp::YesNoComponent < EditableChamp::EditableChampBaseComponent end diff --git a/app/helpers/champ_helper.rb b/app/helpers/champ_helper.rb index 4e76446dd..2a66461bf 100644 --- a/app/helpers/champ_helper.rb +++ b/app/helpers/champ_helper.rb @@ -1,17 +1,4 @@ module ChampHelper - def has_label?(champ) - types_without_label = [TypeDeChamp.type_champs.fetch(:header_section), TypeDeChamp.type_champs.fetch(:explication)] - !types_without_label.include?(champ.type_champ) - end - - def champ_carte_params(champ) - if champ.persisted? - { champ_id: champ.id } - else - { type_de_champ_id: champ.type_de_champ_id } - end - end - def format_text_value(text) sanitized_text = sanitize(text) auto_linked_text = Anchored::Linker.auto_link(sanitized_text, target: '_blank', rel: 'noopener') do |link_href| @@ -27,36 +14,4 @@ module ChampHelper piece_justificative_template_admin_procedure_type_de_champ_url(stable_id: object.stable_id, procedure_id: object.procedure.id) end end - - def autosave_available?(champ) - # FIXME: enable autosave on champs private? once we figured out how to batch audit events - champ.dossier.brouillon? && !champ.repetition? - end - - def editable_champ_controller(champ) - if !champ.repetition? && !champ.non_fillable? - # This is an editable champ. Lets find what controllers it might need. - controllers = [] - - # This is a public champ – it can have an autosave controller. - if champ.public? - # This is a champ on dossier in draft state. Activate autosave. - if champ.dossier.brouillon? - controllers << 'autosave' - # This is a champ on a dossier in en_construction state. Enable conditions checker. - elsif champ.public? && champ.dossier.en_construction? - controllers << 'check-conditions' - end - end - - # This is a dropdown champ. Activate special behaviours it might have. - if champ.simple_drop_down_list? || champ.linked_drop_down_list? - controllers << 'champ-dropdown' - end - - if controllers.present? - { controller: controllers.join(' ') } - end - end - end end diff --git a/app/models/champ.rb b/app/models/champ.rb index 58b85e44d..41fd80a34 100644 --- a/app/models/champ.rb +++ b/app/models/champ.rb @@ -51,6 +51,7 @@ class Champ < ApplicationRecord :simple_drop_down_list?, :linked_drop_down_list?, :non_fillable?, + :fillable?, :cnaf?, :dgfip?, :pole_emploi?, diff --git a/app/models/type_de_champ.rb b/app/models/type_de_champ.rb index 6221e78a3..a0f0409b3 100644 --- a/app/models/type_de_champ.rb +++ b/app/models/type_de_champ.rb @@ -186,6 +186,10 @@ class TypeDeChamp < ApplicationRecord drop_down_other == "1" || drop_down_other == true end + def fillable? + !non_fillable? + end + def non_fillable? type_champ.in?([ TypeDeChamp.type_champs.fetch(:header_section), diff --git a/app/views/champs/piece_justificative/show.turbo_stream.haml b/app/views/champs/piece_justificative/show.turbo_stream.haml index 0afadc2c1..c170e5cb5 100644 --- a/app/views/champs/piece_justificative/show.turbo_stream.haml +++ b/app/views/champs/piece_justificative/show.turbo_stream.haml @@ -1,5 +1,6 @@ = fields_for @champ.input_name, @champ do |form| - = turbo_stream.morph @champ.input_group_id, partial: "shared/dossiers/editable_champs/editable_champ", locals: { champ: @champ, form: form } + = turbo_stream.morph @champ.input_group_id do + = render EditableChamp::EditableChampComponent.new champ: @champ, form: form - if @champ.piece_justificative_file.attached? - attachment = @champ.piece_justificative_file.attachment diff --git a/app/views/root/patron.html.haml b/app/views/root/patron.html.haml index 8d433ae6a..907ba3118 100644 --- a/app/views/root/patron.html.haml +++ b/app/views/root/patron.html.haml @@ -45,9 +45,7 @@ %form.form = form_for @dossier, url: '', html: { class: 'form' } do |f| = f.fields_for :champs do |champ_form| - - champ = champ_form.object - = render partial: "shared/dossiers/editable_champs/editable_champ", - locals: { champ: champ, form: champ_form, seen_at: nil } + = render EditableChamp::EditableChampComponent.new champ: champ_form.object, form: champ_form .editable-champ.editable-champ-text %label Mot de passe diff --git a/app/views/shared/dossiers/_edit.html.haml b/app/views/shared/dossiers/_edit.html.haml index c0fc915d7..9ad011611 100644 --- a/app/views/shared/dossiers/_edit.html.haml +++ b/app/views/shared/dossiers/_edit.html.haml @@ -33,7 +33,7 @@ - dossier.champs.each do |champ| = fields_for champ.input_name, champ do |form| - = render partial: "shared/dossiers/editable_champs/editable_champ", locals: { form: form, champ: champ } + = render EditableChamp::EditableChampComponent.new form: form, champ: champ - if !dossier.for_procedure_preview? .dossier-edit-sticky-footer diff --git a/app/views/shared/dossiers/_edit_annotations.html.haml b/app/views/shared/dossiers/_edit_annotations.html.haml index 163dd5862..ebf3339d3 100644 --- a/app/views/shared/dossiers/_edit_annotations.html.haml +++ b/app/views/shared/dossiers/_edit_annotations.html.haml @@ -4,16 +4,11 @@ = form_for dossier, url: annotations_instructeur_dossier_path(dossier.procedure, dossier), html: { class: 'form', multipart: true } do |f| - dossier.champs_private.each do |champ| = fields_for champ.input_name, champ do |form| - = render partial: "shared/dossiers/editable_champs/editable_champ", locals: { form: form, champ: champ, seen_at: seen_at } + = render EditableChamp::EditableChampComponent.new form: form, champ: champ, seen_at: seen_at - if !dossier.for_procedure_preview? - - if autosave_available?(dossier.champs_private.first) - .dossier-edit-sticky-footer - .send-dossier-actions-bar - = render partial: 'autosave' - - else - .send-wrapper - = f.submit 'Sauvegarder', class: 'button primary send', data: { disable: true } + .send-wrapper + = f.submit 'Sauvegarder', class: 'button primary send', data: { disable: true } - else %h2.empty-text Aucune annotation privée diff --git a/app/views/shared/dossiers/editable_champs/_champ_label.html.haml b/app/views/shared/dossiers/editable_champs/_champ_label.html.haml deleted file mode 100644 index 6258a7bcf..000000000 --- a/app/views/shared/dossiers/editable_champs/_champ_label.html.haml +++ /dev/null @@ -1,10 +0,0 @@ -= # 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 do - = render partial: 'shared/dossiers/editable_champs/champ_label_content', locals: { champ: champ, seen_at: seen_at } -- else - .form-label.mb-4 - = render partial: 'shared/dossiers/editable_champs/champ_label_content', locals: { champ: champ, seen_at: seen_at } - -- if champ.description.present? - .notice{ id: champ.describedby_id }= string_to_html(champ.description) diff --git a/app/views/shared/dossiers/editable_champs/_champ_label_content.html.haml b/app/views/shared/dossiers/editable_champs/_champ_label_content.html.haml deleted file mode 100644 index 54e056eb4..000000000 --- a/app/views/shared/dossiers/editable_champs/_champ_label_content.html.haml +++ /dev/null @@ -1,11 +0,0 @@ -#{champ.libelle} -- if champ.type_de_champ.mandatory? - %span.mandatory * - -- if champ.updated_at.present? && seen_at.present? - %span.updated-at{ class: highlight_if_unseen_class(seen_at, champ.updated_at) } - = "modifié le #{try_format_datetime(champ.updated_at)}" - -- if champ.rebased_at.present? && champ.rebased_at > (seen_at || champ.updated_at) && current_user.owns_or_invite?(champ.dossier) - %span.updated-at.highlighted - Le type de ce champ où sa description a été modifiée par l'administration. Vérifier son contenu. diff --git a/app/views/shared/dossiers/editable_champs/_editable_champ.html.haml b/app/views/shared/dossiers/editable_champs/_editable_champ.html.haml deleted file mode 100644 index bd231ea4b..000000000 --- a/app/views/shared/dossiers/editable_champs/_editable_champ.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -.editable-champ{ class: "editable-champ-#{champ.type_champ} #{champ.visible? ? '' : 'hidden'}", id: champ.input_group_id, data: editable_champ_controller(champ) } - - if champ.repetition? - %h3.header-subsection= champ.libelle - - if champ.description.present? - %p.notice= string_to_html(champ.description, false) - - - elsif has_label?(champ) - = render partial: 'shared/dossiers/editable_champs/champ_label', locals: { form: form, champ: champ, seen_at: defined?(seen_at) ? seen_at : nil } - - if champ.type_champ == "titre_identite" - %p.notice Carte nationale d’identité (uniquement le recto), passeport, titre de séjour ou autre justificatif d’identité. Formats acceptés : jpg/png - - = form.hidden_field :id, value: champ.id, data: champ.repetition? ? { id: true } : {} - = render "EditableChamp::#{champ.type_champ.camelcase}Component".constantize.new(form: form, champ: champ) diff --git a/spec/helpers/champ_helper_spec.rb b/spec/components/editable_champ/editable_champ_component_spec.rb similarity index 64% rename from spec/helpers/champ_helper_spec.rb rename to spec/components/editable_champ/editable_champ_component_spec.rb index cb7a62f8d..08025b670 100644 --- a/spec/helpers/champ_helper_spec.rb +++ b/spec/components/editable_champ/editable_champ_component_spec.rb @@ -1,46 +1,50 @@ -describe ChampHelper, type: :helper do +describe EditableChamp::EditableChampComponent, type: :component do + let(:component) { described_class.new(form: nil, champ: champ) } + describe "editable_champ_controller" do let(:dossier) { create(:dossier) } let(:champ) { create(:champ, dossier: dossier) } let(:controllers) { [] } - let(:data) { { controller: controllers.join(' ') } } + let(:data) { controllers.join(' ') } + + subject { component.send(:stimulus_controller) } context 'when an editable champ' do let(:controllers) { ['autosave'] } - it { expect(editable_champ_controller(champ)).to eq(data) } + it { expect(subject).to eq(data) } end context 'when a repetition champ' do let(:champ) { create(:champ_repetition, dossier: dossier) } - it { expect(editable_champ_controller(champ)).to eq(nil) } + it { expect(subject).to eq(nil) } end context 'when a private champ' do let(:champ) { create(:champ, dossier: dossier, private: true) } - it { expect(editable_champ_controller(champ)).to eq(nil) } + it { expect(subject).to eq('') } end context 'when a dossier is en_construction' do - let(:controllers) { ['check-conditions'] } + let(:controllers) { ['autosave'] } let(:dossier) { create(:dossier, :en_construction) } - it { expect(editable_champ_controller(champ)).to eq(data) } + it { expect(subject).to eq(data) } context 'when a public dropdown champ' do - let(:controllers) { ['check-conditions', 'champ-dropdown'] } + let(:controllers) { ['autosave', 'champ-dropdown'] } let(:champ) { create(:champ_drop_down_list, dossier: dossier) } - it { expect(editable_champ_controller(champ)).to eq(data) } + it { expect(subject).to eq(data) } end context 'when a private dropdown champ' do let(:controllers) { ['champ-dropdown'] } let(:champ) { create(:champ_drop_down_list, dossier: dossier, private: true) } - it { expect(editable_champ_controller(champ)).to eq(data) } + it { expect(subject).to eq(data) } end end @@ -48,14 +52,14 @@ describe ChampHelper, type: :helper do let(:controllers) { ['autosave', 'champ-dropdown'] } let(:champ) { create(:champ_drop_down_list, dossier: dossier) } - it { expect(editable_champ_controller(champ)).to eq(data) } + it { expect(subject).to eq(data) } end context 'when a private dropdown champ' do let(:controllers) { ['champ-dropdown'] } let(:champ) { create(:champ_drop_down_list, dossier: dossier, private: true) } - it { expect(editable_champ_controller(champ)).to eq(data) } + it { expect(subject).to eq(data) } end end end From d6f5be622c90d4b0353b1b23963f8a3c77d17e0c Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Thu, 8 Sep 2022 11:26:18 +0200 Subject: [PATCH 2/2] feat(dossier): autosave en construction --- app/controllers/users/dossiers_controller.rb | 30 +++++-------------- .../controllers/autosave_controller.ts | 12 ++++++-- .../instructeurs/dossiers/_autosave.html.haml | 17 ----------- .../dossiers/_autosave.html.haml | 12 ++++++-- app/views/shared/dossiers/_edit.html.haml | 22 +++++--------- .../users/dossiers/update.turbo_stream.haml | 5 ++++ config/locales/en.yml | 10 +++---- config/locales/fr.yml | 13 ++++---- .../users/dossiers_controller_spec.rb | 6 ++-- spec/system/routing/full_scenario_spec.rb | 5 ++-- spec/system/users/brouillon_spec.rb | 3 ++ spec/system/users/dossier_details_spec.rb | 6 ++-- spec/system/users/dossier_shared_examples.rb | 5 +++- spec/system/users/invite_spec.rb | 2 +- 14 files changed, 66 insertions(+), 82 deletions(-) delete mode 100644 app/views/instructeurs/dossiers/_autosave.html.haml rename app/views/{users => shared}/dossiers/_autosave.html.haml (61%) create mode 100644 app/views/users/dossiers/update.turbo_stream.haml diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index cbeae0320..dbc6a0611 100644 --- a/app/controllers/users/dossiers_controller.rb +++ b/app/controllers/users/dossiers_controller.rb @@ -188,19 +188,15 @@ module Users def update @dossier = dossier_with_champs + errors = update_dossier_and_compute_errors - if check_conditions? - assign_dossier_and_check_conditions - render :update_brouillon - else - errors = update_dossier_and_compute_errors + if errors.present? + flash.now.alert = errors + end - if errors.present? - flash.now.alert = errors - render :modifier - else - redirect_to demande_dossier_path(@dossier) - end + respond_to do |format| + format.html { render :modifier } + format.turbo_stream { render layout: false } end end @@ -308,18 +304,6 @@ module Users private - def check_conditions? - params[:check_conditions] && champs_params[:dossier] - end - - def assign_dossier_and_check_conditions - @dossier.assign_attributes(champs_params[:dossier]) - # We need to set dossier on champs, otherwise dossier will be reloaded - @dossier.champs.each do |champ| - champ.association(:dossier).target = @dossier - end - end - # if the status tab is filled, then this tab # else first filled tab # else en-cours diff --git a/app/javascript/controllers/autosave_controller.ts b/app/javascript/controllers/autosave_controller.ts index 99c915d86..6f786c219 100644 --- a/app/javascript/controllers/autosave_controller.ts +++ b/app/javascript/controllers/autosave_controller.ts @@ -42,7 +42,10 @@ export class AutosaveController extends ApplicationController { this.#latestPromise = Promise.resolve(); this.onGlobal('autosave:retry', () => this.didRequestRetry()); this.on('change', (event) => this.onChange(event)); - this.on('input', (event) => this.onInput(event)); + + if (this.saveOnInput) { + this.on('input', (event) => this.onInput(event)); + } } disconnect() { @@ -80,7 +83,8 @@ export class AutosaveController extends ApplicationController { this.debounce(this.enqueueAutosaveRequest, AUTOSAVE_DEBOUNCE_DELAY); } else if ( isSelectElement(target) || - isCheckboxOrRadioInputElement(target) + isCheckboxOrRadioInputElement(target) || + (!this.saveOnInput && isTextInputElement(target)) ) { this.enqueueAutosaveRequest(); } @@ -99,6 +103,10 @@ export class AutosaveController extends ApplicationController { } } + private get saveOnInput() { + return !!this.form?.dataset.saveOnInput; + } + private didRequestRetry() { if (this.#needsRetry) { this.enqueueAutosaveRequest(); diff --git a/app/views/instructeurs/dossiers/_autosave.html.haml b/app/views/instructeurs/dossiers/_autosave.html.haml deleted file mode 100644 index 73b60b790..000000000 --- a/app/views/instructeurs/dossiers/_autosave.html.haml +++ /dev/null @@ -1,17 +0,0 @@ -.autosave.autosave-state-idle{ data: { controller: 'autosave-status' } } - %p.autosave-explanation - %span.autosave-explanation-text - = t('views.instructeurs.dossiers.autosave.autosave_draft') - - %p.autosave-status.succeeded - %span.autosave-icon.icon.accept - %span.autosave-label - = t('views.instructeurs.dossiers.autosave.autosave_confirmation') - - %p.autosave-status.failed - %span.autosave-icon ⚠️ - %span.autosave-label Impossible d’enregistrer les annotations - %button.button.small.autosave-retry{ type: :button, data: { action: 'autosave-status#onClickRetryButton', autosave_status_target: 'retryButton' } } - %span.autosave-retry-label réessayer - %span.autosave-retrying-label enregistrement en cours… - diff --git a/app/views/users/dossiers/_autosave.html.haml b/app/views/shared/dossiers/_autosave.html.haml similarity index 61% rename from app/views/users/dossiers/_autosave.html.haml rename to app/views/shared/dossiers/_autosave.html.haml index 73fb580b6..583f4ee52 100644 --- a/app/views/users/dossiers/_autosave.html.haml +++ b/app/views/shared/dossiers/_autosave.html.haml @@ -1,13 +1,19 @@ .autosave.autosave-state-idle{ data: { controller: 'autosave-status' } } %p.autosave-explanation %span.autosave-explanation-text - = t('views.users.dossiers.autosave.autosave_draft') - = link_to t('views.users.dossiers.autosave.more_infos'), FAQ_AUTOSAVE_URL, target: '_blank', rel: 'noopener', class: 'autosave-more-infos' + - if dossier.brouillon? + = t('views.users.dossiers.autosave.draft_explanation') + - else + = t('views.users.dossiers.autosave.explanation') + = link_to t('views.users.dossiers.autosave.more_information'), FAQ_AUTOSAVE_URL, target: '_blank', rel: 'noopener', class: 'autosave-more-infos' %p.autosave-status.succeeded %span.autosave-icon.icon.accept %span.autosave-label - = t('views.users.dossiers.autosave.autosave_confirmation') + - if dossier.brouillon? + = t('views.users.dossiers.autosave.draft_confirmation') + - else + = t('views.users.dossiers.autosave.confirmation') = link_to t('views.users.dossiers.autosave.more_information'), FAQ_AUTOSAVE_URL, target: '_blank', rel: 'noopener', class: 'autosave-more-infos' %p.autosave-status.failed diff --git a/app/views/shared/dossiers/_edit.html.haml b/app/views/shared/dossiers/_edit.html.haml index 9ad011611..71d1ee544 100644 --- a/app/views/shared/dossiers/_edit.html.haml +++ b/app/views/shared/dossiers/_edit.html.haml @@ -2,7 +2,7 @@ = render partial: "shared/dossiers/submit_is_over", locals: { dossier: dossier } - if dossier.brouillon? - - form_options = { url: brouillon_dossier_url(dossier), method: :patch } + - form_options = { url: brouillon_dossier_url(dossier), method: :patch, data: { save_on_input: true } } - else - form_options = { url: modifier_dossier_url(dossier), method: :patch } @@ -23,7 +23,7 @@ %hr - if dossier.show_groupe_instructeur_selector? - %span{ data: { controller: dossier.brouillon? ? 'autosave' : 'check-conditions' } } + %span{ data: { controller: 'autosave' } } = f.label :groupe_instructeur_id do = dossier.procedure.routing_criteria_name %span.mandatory * @@ -38,20 +38,14 @@ - if !dossier.for_procedure_preview? .dossier-edit-sticky-footer .send-dossier-actions-bar - - if dossier.brouillon? - = render partial: 'users/dossiers/autosave' + = render partial: 'shared/dossiers/autosave', locals: { dossier: dossier } - - if dossier.can_transition_to_en_construction? - = f.button t('views.shared.dossiers.edit.submit_dossier'), - name: :submit_draft, - value: true, - class: 'button send primary', - disabled: !current_user.owns?(dossier), - data: { 'disable-with': "Envoi en cours…" } - - - else - = f.button t('views.shared.dossiers.edit.save_changes'), + - if dossier.can_transition_to_en_construction? + = f.button t('views.shared.dossiers.edit.submit_dossier'), + name: :submit_draft, + value: true, class: 'button send primary', + disabled: !current_user.owns?(dossier), data: { 'disable-with': "Envoi en cours…" } - if dossier.brouillon? && !current_user.owns?(dossier) diff --git a/app/views/users/dossiers/update.turbo_stream.haml b/app/views/users/dossiers/update.turbo_stream.haml new file mode 100644 index 000000000..59eb62452 --- /dev/null +++ b/app/views/users/dossiers/update.turbo_stream.haml @@ -0,0 +1,5 @@ +- @dossier.champs.filter(&:conditional?).each do |champ| + - if champ.visible? + = turbo_stream.show champ.input_group_id + - else + = turbo_stream.hide champ.input_group_id diff --git a/config/locales/en.yml b/config/locales/en.yml index d277e4111..11bd01d58 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -137,7 +137,6 @@ en: edit: autosave: Your file is automatically saved after each modification. You can close the window at any time and pick up where you left off later. submit_dossier: Submit the file - save_changes: Save the changes of the file messages: form: send_message: "Send message" @@ -151,9 +150,6 @@ en: edit_identity: "Edit identity data" instructeurs: dossiers: - autosave: - autosave_draft: Your annotations are automatically saved. - autosave_confirmation: Annotations saved tab_steps: to_follow: to follow total: total @@ -192,8 +188,10 @@ en: dossiers: archived_dossier: "Your file will be kept %{duree_conservation_dossiers_dans_ds} more months" autosave: - autosave_draft: Your draft is automatically saved. - autosave_confirmation: Draft saved + explanation: Your file is automatically saved. + confirmation: File saved + draft_explanation: Your draft is automatically saved. + draft_confirmation: Draft saved more_information: More informations identite: identity_data: Identity data diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 9c3ce623d..ff8847661 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -132,7 +132,6 @@ fr: edit: autosave: Votre dossier est enregistré automatiquement après chaque modification. Vous pouvez à tout moment fermer la fenêtre et reprendre plus tard là où vous en étiez. submit_dossier: Déposer le dossier - save_changes: Enregistrer les modifications du dossier messages: form: send_message: "Envoyer le message" @@ -146,9 +145,6 @@ fr: edit_identity: "Modifier l’identité" instructeurs: dossiers: - autosave: - autosave_draft: Vos annotations sont automatiquement enregistrées. - autosave_confirmation: Annotations enregistrées tab_steps: to_follow: à suivre total: au total @@ -188,10 +184,11 @@ fr: dossiers: archived_dossier: "Votre dossier sera conservé %{duree_conservation_dossiers_dans_ds} mois supplémentaire" autosave: - autosave_draft: Votre brouillon est automatiquement enregistré. - autosave_confirmation: Brouillon enregistré - more_information: More informations - more_infos: En savoir plus + explanation: Votre dossier est automatiquement enregistré. + confirmation: Dossier enregistré + draft_explanation: Votre brouillon est automatiquement enregistré. + draft_confirmation: Brouillon enregistré + more_information: En savoir plus identite: identity_data: Données d’identité civility: Civilité diff --git a/spec/controllers/users/dossiers_controller_spec.rb b/spec/controllers/users/dossiers_controller_spec.rb index 958fc04f4..33c4d699e 100644 --- a/spec/controllers/users/dossiers_controller_spec.rb +++ b/spec/controllers/users/dossiers_controller_spec.rb @@ -649,7 +649,7 @@ describe Users::DossiersController, type: :controller do expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_construction)) end - it { is_expected.to redirect_to(demande_dossier_path(dossier)) } + it { is_expected.to have_http_status(:ok) } context 'when only a single file champ are modified' do # A bug in ActiveRecord causes records changed through grand-parent <-> parent <-> child @@ -726,7 +726,7 @@ describe Users::DossiersController, type: :controller do it 'does not raise any errors' do subject - expect(response).to redirect_to(demande_dossier_path(dossier)) + expect(response).to have_http_status(:ok) end end @@ -741,7 +741,7 @@ describe Users::DossiersController, type: :controller do it { expect(first_champ.reload.value).to eq('beautiful value') } it { expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_construction)) } - it { expect(response).to redirect_to(demande_dossier_path(dossier)) } + it { expect(response).to have_http_status(:ok) } end context 'when the dossier is followed by an instructeur' do diff --git a/spec/system/routing/full_scenario_spec.rb b/spec/system/routing/full_scenario_spec.rb index 17a039035..0556a4c07 100644 --- a/spec/system/routing/full_scenario_spec.rb +++ b/spec/system/routing/full_scenario_spec.rb @@ -120,7 +120,8 @@ describe 'The routing', js: true do click_on 'Modifier mon dossier' fill_in litteraire_user.dossiers.first.champs.first.libelle, with: 'some value' - click_on 'Enregistrer les modifications du dossier' + blur + expect(page).to have_css('span', text: 'Dossier enregistré', visible: true) log_out # the litteraires instructeurs should have a notification @@ -214,7 +215,7 @@ describe 'The routing', js: true do expect(page).not_to have_selector("option", text: "Groupe inactif") select(new_group, from: 'dossier_groupe_instructeur_id') - click_on "Enregistrer les modifications du dossier" + expect(page).to have_css('span', text: 'Dossier enregistré', visible: true) expect(page).to have_text(new_group) log_out diff --git a/spec/system/users/brouillon_spec.rb b/spec/system/users/brouillon_spec.rb index 98b5e8c5f..4f4d9a90e 100644 --- a/spec/system/users/brouillon_spec.rb +++ b/spec/system/users/brouillon_spec.rb @@ -390,6 +390,9 @@ describe 'The user' do expect(page).to have_no_css('label', text: 'tonnage', visible: true) fill_in('age', with: '18') + blur + expect(page).to have_css('span', text: 'Dossier enregistré', visible: true) + # 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('label', text: 'tonnage', visible: true) diff --git a/spec/system/users/dossier_details_spec.rb b/spec/system/users/dossier_details_spec.rb index 153dfaaec..5f73359ce 100644 --- a/spec/system/users/dossier_details_spec.rb +++ b/spec/system/users/dossier_details_spec.rb @@ -48,8 +48,10 @@ describe 'Dossier details:' do expect(page).to have_current_path(dossier_path(dossier)) end - it_behaves_like 'the user can edit the submitted demande' - it_behaves_like 'the user can send messages to the instructeur' + context 'with js', js: true do + it_behaves_like 'the user can edit the submitted demande' + it_behaves_like 'the user can send messages to the instructeur' + end private diff --git a/spec/system/users/dossier_shared_examples.rb b/spec/system/users/dossier_shared_examples.rb index d9c36a73b..35e7c418c 100644 --- a/spec/system/users/dossier_shared_examples.rb +++ b/spec/system/users/dossier_shared_examples.rb @@ -10,9 +10,12 @@ RSpec.shared_examples 'the user can edit the submitted demande' do expect(page).to have_current_path(modifier_dossier_path(dossier)) fill_in('Texte obligatoire', with: 'Nouveau texte') - click_on 'Enregistrer les modifications du dossier' + blur + expect(page).to have_css('span', text: 'Dossier enregistré', visible: true) + click_on 'Demande' expect(page).to have_current_path(demande_dossier_path(dossier)) + expect(page).to have_content('Nouveau texte') end end diff --git a/spec/system/users/invite_spec.rb b/spec/system/users/invite_spec.rb index c7cfbaded..64d8f1d33 100644 --- a/spec/system/users/invite_spec.rb +++ b/spec/system/users/invite_spec.rb @@ -127,7 +127,7 @@ describe 'Invitations' do expect(page).to have_text("user_invite@exemple.fr") end - context 'as an invited user' do + context 'as an invited user', js: true do before do navigate_to_invited_dossier(invite) expect(page).to have_current_path(dossier_path(invite.dossier))