feat(instructeurs/dossiers): add summary to dossier.champs and dossier.champ_private views, also extract summary in

two component. one of type de champ editor. one for viewable champs
This commit is contained in:
mfo 2024-06-21 05:49:42 +02:00
parent 5a5ebfb235
commit d46dc7055d
No known key found for this signature in database
GPG key ID: 7CE3E1F5B794A8EC
14 changed files with 146 additions and 61 deletions

View file

@ -0,0 +1,16 @@
class TypesDeChampEditor::HeaderSectionsSummaryComponent < ApplicationComponent
def initialize(procedure:, is_private:)
@procedure = procedure
@is_private = is_private
end
def header_sections
@procedure.draft_revision
.send(@is_private ? :revision_types_de_champ_private : :revision_types_de_champ_public)
.filter { _1.type_de_champ.header_section? }
end
def href(header_section) # used by type de champ editor to anchor elements
"##{dom_id(header_section, :type_de_champ_editor)}"
end
end

View file

@ -6,6 +6,6 @@
%li.fr-sidemenu__item
- level = header.type_de_champ.header_section_level_value.to_i
- if level == 1
%a.fr-sidemenu__link{ href: "##{dom_id(header, :type_de_champ_editor)}" }= header.libelle
%a.fr-sidemenu__link{ href: href(header) }= header.libelle
- else
%a.fr-sidemenu__link{ class: level >= 3 ? 'custom-link-grey': '', href: "##{dom_id(header, :type_de_champ_editor)}" }= "-- #{header.libelle}"
%a.fr-sidemenu__link{ class: level >= 3 ? 'custom-link-grey': '', href: href(header) }= "-- #{header.libelle}"

View file

@ -0,0 +1,17 @@
class ViewableChamp::HeaderSectionsSummaryComponent < ApplicationComponent
def initialize(dossier:, is_private:)
@dossier = dossier
@is_private = is_private
end
def header_sections
@dossier.revision
.types_de_champ_for(scope: @is_private ? :private : :public)
.filter(&:header_section?)
.map { @dossier.project_champ(_1, nil) } # row_id not needed, do not link to repetiion header_sections
end
def href(header_section) # used by viewable champs to anchor elements
"##{header_section.input_group_id}"
end
end

View file

@ -0,0 +1,11 @@
#summary
- if header_sections.present?
%nav.fr-sidemenu.sticky.fr-hidden.fr-unhidden-md{ "aria-labelledby" => "fr-summary-title", role: "navigation" }
%ul.fr-sidemenu__list
- header_sections.each do |header_section|
%li.fr-sidemenu__item
- level = header_section.header_section_level_value.to_i
- if level == 1
%a.fr-sidemenu__link{ href: href(header_section) }= header_section.libelle
- else
%a.fr-sidemenu__link{ class: level >= 3 ? 'custom-link-grey': '', href: href(header_section) }= "-- #{header_section.libelle}"

View file

@ -1002,14 +1002,6 @@ class Procedure < ApplicationRecord
lien_dpo.present? && lien_dpo.match?(/@/)
end
def draft_revision_header_sections_public
draft_revision.revision_types_de_champ_public.filter { _1.type_de_champ.header_section? }
end
def draft_revision_header_sections_private
draft_revision.revision_types_de_champ_private.filter { _1.type_de_champ.header_section? }
end
def dossier_for_preview(user)
# Try to use a preview or a dossier filled by current user
dossiers.where(for_procedure_preview: true).or(dossiers.not_brouillon)

View file

@ -11,7 +11,7 @@
= render NestedForms::FormOwnerComponent.new
.fr-grid-row
= render partial: 'champs_summary', locals: { header_sections: @procedure.draft_revision_header_sections_private }
= render TypesDeChampEditor::HeaderSectionsSummaryComponent.new(procedure: @procedure, is_private: true)
.fr-col
= render TypesDeChampEditor::EditorComponent.new(revision: @procedure.draft_revision, is_annotation: true)

View file

@ -11,7 +11,7 @@
= render NestedForms::FormOwnerComponent.new
.fr-grid-row
= render partial: 'champs_summary', locals: { header_sections: @procedure.draft_revision_header_sections_public }
= render TypesDeChampEditor::HeaderSectionsSummaryComponent.new(procedure: @procedure, is_private: false)
.fr-col
= render TypesDeChampEditor::EditorComponent.new(revision: @procedure.draft_revision, is_annotation: false)

View file

@ -14,7 +14,7 @@
= turbo_stream.replace 'errors-summary', render(Procedure::ErrorsSummary.new(procedure: @procedure, validation_context: @coordinate&.private? ? :types_de_champ_private_editor : :types_de_champ_public_editor))
= turbo_stream.replace 'summary', render(partial: 'administrateurs/procedures/champs_summary', locals: { header_sections: @coordinate&.private? ? @procedure.draft_revision_header_sections_private : @procedure.draft_revision_header_sections_public})
= turbo_stream.replace 'summary', render(TypesDeChampEditor::HeaderSectionsSummaryComponent.new(procedure: @procedure, is_private: @coordinate&.private?))
- unless flash.alert
= turbo_stream.show 'autosave-notice'

View file

@ -3,4 +3,8 @@
= render partial: "header", locals: { dossier: @dossier }
#dossier-annotations-privees
= render partial: "shared/dossiers/edit_annotations", locals: { dossier: @dossier, seen_at: @annotations_privees_seen_at }
.fr-container
.fr-grid-row.fr-grid-row--center
.fr-col-md-3= render ViewableChamp::HeaderSectionsSummaryComponent.new(dossier: @dossier, is_private: true)
.fr-col-md-9
= render partial: "shared/dossiers/edit_annotations", locals: { dossier: @dossier, seen_at: @annotations_privees_seen_at }

View file

@ -14,4 +14,8 @@
%p
Les informations sur l'entreprise arriveront dici quelques heures.
= render partial: "shared/dossiers/demande", locals: { dossier: @dossier, demande_seen_at: @demande_seen_at, profile: 'instructeur' }
.fr-container
.fr-grid-row.fr-grid-row--center
.fr-col-md-3= render ViewableChamp::HeaderSectionsSummaryComponent.new(dossier: @dossier, is_private: false)
.fr-col-md-9
= render partial: "shared/dossiers/demande", locals: { dossier: @dossier, demande_seen_at: @demande_seen_at, profile: 'instructeur' }

View file

@ -2,64 +2,63 @@
- content_for(:notice_info) do
= render partial: "shared/dossiers/france_connect_informations_notice", locals: { user_information: dossier.user.france_connect_informations.first }
.fr-container.counter-start-header-section.dossier-show{ class: class_names('gallery': feature_enabled?(:gallery_demande), 'gallery-demande': feature_enabled?(:gallery_demande), "dossier-show-instructeur" => profile =="instructeur"), "data-controller": "lightbox" }
.fr-grid-row.fr-grid-row--center
.fr-col-12.fr-col-xl-8
- if profile == 'instructeur' && dossier.termine_and_accuse_lecture?
= render Dsfr::CalloutComponent.new(title: nil) do |c|
- c.with_html_body do
= t('views.shared.dossiers.demande.accuse_lecture')
- if dossier.accuse_lecture_agreement_at.present?
= t('views.shared.dossiers.demande.accuse_lecture_with_agreement', agreement: l(dossier.accuse_lecture_agreement_at, format: :long))
- else
= t('views.shared.dossiers.demande.accuse_lecture_without_agreement')
.counter-start-header-section.dossier-show{ class: class_names('gallery': feature_enabled?(:gallery_demande), 'gallery-demande': feature_enabled?(:gallery_demande), "dossier-show-instructeur" => profile =="instructeur"), "data-controller": "lightbox" }
%h2.fr-h6.fr-background-alt--grey.fr-mb-0
.flex-grow.fr-py-3v.fr-px-2w= t('views.shared.dossiers.demande.en_construction')
- if profile == 'instructeur' && dossier.termine_and_accuse_lecture?
= render Dsfr::CalloutComponent.new(title: nil) do |c|
- c.with_html_body do
= t('views.shared.dossiers.demande.accuse_lecture')
- if dossier.accuse_lecture_agreement_at.present?
= t('views.shared.dossiers.demande.accuse_lecture_with_agreement', agreement: l(dossier.accuse_lecture_agreement_at, format: :long))
- else
= t('views.shared.dossiers.demande.accuse_lecture_without_agreement')
- if dossier.depose_at.present?
= render partial: "shared/dossiers/infos_generales", locals: { dossier: dossier, profile: profile }
%h2.fr-h6.fr-background-alt--grey.fr-mb-0
.flex-grow.fr-py-3v.fr-px-2w= t('views.shared.dossiers.demande.en_construction')
- if dossier.depose_at.present?
= render partial: "shared/dossiers/infos_generales", locals: { dossier: dossier, profile: profile }
- if dossier.for_tiers?
%h2.fr-h6.fr-background-alt--grey.fr-mb-0.flex
.flex-grow.fr-py-3v.fr-px-2w= t('views.shared.dossiers.demande.mandataire_identity')
- if dossier.for_tiers?
%h2.fr-h6.fr-background-alt--grey.fr-mb-0.flex
.flex-grow.fr-py-3v.fr-px-2w= t('views.shared.dossiers.demande.mandataire_identity')
- if dossier.individual.present? && profile == 'usager' && !dossier.read_only?
= link_to t('views.shared.dossiers.demande.edit_identity'), identite_dossier_path(dossier), class: 'fr-py-3v fr-btn fr-btn--tertiary-no-outline'
- if dossier.individual.present? && profile == 'usager' && !dossier.read_only?
= link_to t('views.shared.dossiers.demande.edit_identity'), identite_dossier_path(dossier), class: 'fr-py-3v fr-btn fr-btn--tertiary-no-outline'
= render partial: "shared/dossiers/mandataire_infos", locals: { user_deleted: dossier.user_deleted?, email: dossier.user_email_for(:display), dossier: dossier }
= render partial: "shared/dossiers/mandataire_infos", locals: { user_deleted: dossier.user_deleted?, email: dossier.user_email_for(:display), dossier: dossier }
.tab-title
%h2.fr-h6.fr-background-alt--grey.fr-mb-0.flex
.flex-grow.fr-py-3v.fr-px-2w
= t('views.shared.dossiers.demande.requester_identity')
.tab-title
%h2.fr-h6.fr-background-alt--grey.fr-mb-0.flex
.flex-grow.fr-py-3v.fr-px-2w
= t('views.shared.dossiers.demande.requester_identity')
- if dossier.identity_updated_at.present? && demande_seen_at&.<(dossier.identity_updated_at)
%span.fr-badge.fr-badge--new.fr-badge--sm
= t('views.shared.dossiers.demande.requester_identity_updated_at', date: try_format_datetime(dossier.identity_updated_at))
- if dossier.identity_updated_at.present? && demande_seen_at&.<(dossier.identity_updated_at)
%span.fr-badge.fr-badge--new.fr-badge--sm
= t('views.shared.dossiers.demande.requester_identity_updated_at', date: try_format_datetime(dossier.identity_updated_at))
- if dossier.etablissement.present? && profile == 'usager' && !dossier.read_only?
= link_to t('views.shared.dossiers.demande.edit_siret'), siret_dossier_path(dossier), class: 'fr-py-3v fr-btn fr-btn--tertiary-no-outline'
- if dossier.etablissement.present? && profile == 'usager' && !dossier.read_only?
= link_to t('views.shared.dossiers.demande.edit_siret'), siret_dossier_path(dossier), class: 'fr-py-3v fr-btn fr-btn--tertiary-no-outline'
- if dossier.individual.present? && profile == 'usager' && !dossier.read_only?
= link_to t('views.shared.dossiers.demande.edit_identity'), identite_dossier_path(dossier), class: 'fr-py-3v fr-btn fr-btn--tertiary-no-outline'
- if dossier.individual.present? && profile == 'usager' && !dossier.read_only?
= link_to t('views.shared.dossiers.demande.edit_identity'), identite_dossier_path(dossier), class: 'fr-py-3v fr-btn fr-btn--tertiary-no-outline'
= render partial: "shared/dossiers/user_infos", locals: { user_deleted: dossier.user_deleted?, email: dossier.user_email_for(:display), for_tiers: dossier.for_tiers?, beneficiaire_mail: dossier.for_tiers? ? dossier.individual.email : ""}
= render partial: "shared/dossiers/user_infos", locals: { user_deleted: dossier.user_deleted?, email: dossier.user_email_for(:display), for_tiers: dossier.for_tiers?, beneficiaire_mail: dossier.for_tiers? ? dossier.individual.email : ""}
- if dossier.individual.present?
= render partial: "shared/dossiers/identite_individual", locals: { dossier: dossier }
- if dossier.individual.present?
= render partial: "shared/dossiers/identite_individual", locals: { dossier: dossier }
- if dossier.etablissement.present?
.fr-mt-1w.fr-mb-4w.fr-px-2w
= render partial: "shared/dossiers/identite_entreprise", locals: { etablissement: dossier.etablissement, profile: profile }
- if dossier.etablissement.present?
.fr-mt-1w.fr-mb-4w.fr-px-2w
= render partial: "shared/dossiers/identite_entreprise", locals: { etablissement: dossier.etablissement, profile: profile }
%h2.fr-h6.fr-background-alt--grey.fr-mb-0.flex
.flex-grow.fr-py-3v.fr-px-2w= t('views.shared.dossiers.demande.form')
%h2.fr-h6.fr-background-alt--grey.fr-mb-0.flex
.flex-grow.fr-py-3v.fr-px-2w= t('views.shared.dossiers.demande.form')
- types_de_champ = dossier.revision.types_de_champ_public
- if types_de_champ.any? || dossier.procedure.routing_enabled?
= render ViewableChamp::SectionComponent.new(dossier:, types_de_champ:, demande_seen_at:, profile:)
- types_de_champ = dossier.revision.types_de_champ_public
- if types_de_champ.any? || dossier.procedure.routing_enabled?
= render ViewableChamp::SectionComponent.new(dossier:, types_de_champ:, demande_seen_at:, profile:)

View file

@ -11,13 +11,15 @@
.fr-grid-row.fr-grid-row--center
.fr-col-xl-10
= render Dossiers::EnConstructionNotSubmittedComponent.new(dossier: @dossier, user: current_user)
= render partial: 'shared/dossiers/demande', locals: { dossier: @dossier, demande_seen_at: nil, profile: 'usager' }
.fr-container
.fr-grid-row.fr-grid-row--center
.fr-col-md-9
= render partial: 'shared/dossiers/demande', locals: { dossier: @dossier, demande_seen_at: nil, profile: 'usager' }
- if !@dossier.read_only?
.fr-container.fr-mt-2w
.fr-grid-row
.fr-grid-row.fr-grid-row--center
.fr-col-xl-8.fr-col-offset-xl-2
%p= link_to t('views.users.dossiers.demande.edit_dossier'), modifier_dossier_path(@dossier), class: 'fr-btn fr-btn-sm',
title: t('views.users.dossiers.demande.edit_dossier_title')

View file

@ -0,0 +1,26 @@
describe 'instructeurs/dossiers/annotations_privees', type: :view do
let(:current_instructeur) { create(:instructeur) }
let(:dossier) { create(:dossier, :en_construction) }
before do
sign_in(current_instructeur.user)
allow(view).to receive(:current_instructeur).and_return(current_instructeur)
assign(:dossier, dossier)
end
subject { render }
describe 'when header_sections are present' do
let(:procedure) { create(:procedure, types_de_champ_private:) }
let(:types_de_champ_private) do
[
{ type: :header_section, level: 1, libelle: 'l1' }
]
end
let(:dossier) { create(:dossier, :en_construction, procedure:) }
it 'displays a link to header_section' do
expect(subject).to have_selector('a.fr-sidemenu__link', text: 'l1')
end
end
end

View file

@ -201,4 +201,18 @@ describe 'instructeurs/dossiers/show', type: :view do
end
end
end
describe 'when header_sections are present' do
let(:procedure) { create(:procedure, types_de_champ_public:) }
let(:types_de_champ_public) do
[
{ type: :header_section, level: 1, libelle: 'l1' }
]
end
let(:dossier) { create(:dossier, :en_construction, procedure:) }
it 'displays a link to header_section' do
expect(subject).to have_selector('a.fr-sidemenu__link', text: 'l1')
end
end
end