Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ETQ administrateur, je peux ajouter des conditions d'eligibilité auxquelles les dossiers doivent correspondre sans quoi l'usager ne peut déposer son dossier #10292

Merged
merged 12 commits into from
Jun 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions app/assets/stylesheets/conditions_component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,14 @@ form.form > .conditionnel {
select.alert {
border-color: $dark-red;
}

&:first-child {
padding-left: 0;
}

&:last-child {
text-align: right;
padding-right: 0;
}
}
}
2 changes: 1 addition & 1 deletion app/components/conditions/conditions_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def empty_target_for_select

def available_targets_for_select
@source_tdcs
.filter { |tdc| ChampValue::MANAGED_TYPE_DE_CHAMP.values.include?(tdc.type_champ) }
.filter(&:conditionable?)
.map { |tdc| [tdc.libelle, champ_value(tdc.stable_id).to_json] }
end

Expand Down
34 changes: 34 additions & 0 deletions app/components/conditions/ineligibilite_rules_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
class Conditions::IneligibiliteRulesComponent < Conditions::ConditionsComponent
include Logic

def initialize(draft_revision:)
@draft_revision = draft_revision
@published_revision = draft_revision.procedure.published_revision
@condition = draft_revision.ineligibilite_rules
@source_tdcs = draft_revision.types_de_champ_for(scope: :public)
end

def pending_changes?
return false if !@published_revision

!@published_revision.compare_ineligibilite_rules(@draft_revision).empty?
end

private

def input_prefix
'procedure_revision[condition_form]'
end

def input_id_for(name, row_index)
"#{@draft_revision.id}-#{name}-#{row_index}"
end

def delete_condition_path(row_index)
delete_row_admin_procedure_ineligibilite_rules_path(@draft_revision.procedure_id, revision_id: @draft_revision.id, row_index:)
end

def add_condition_path
add_row_admin_procedure_ineligibilite_rules_path(@draft_revision.procedure_id, revision_id: @draft_revision.id)
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
fr:
display_if: Bloquer si
select: Sélectionner
add_condition: Ajouter une règle d’inéligibilité
remove_a_row: Supprimer une règle
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
%div{ id: dom_id(@draft_revision, :ineligibilite_rules) }
= render Procedure::PendingRepublishComponent.new(procedure: @draft_revision.procedure, render_if: pending_changes?)
= render Conditions::ConditionsErrorsComponent.new(conditions: condition_per_row, source_tdcs: @source_tdcs)
.fr-fieldset
= form_for(@draft_revision, url: change_admin_procedure_ineligibilite_rules_path(@draft_revision.procedure_id), html: { id: 'ineligibilite_form', class: 'width-100' }) do |f|
.fr-fieldset__element
.fr-toggle.fr-toggle--label-left
= f.check_box :ineligibilite_enabled, class: 'fr-toggle__input', data: @opt
= f.label :ineligibilite_enabled, "Bloquer le dépôt des dossiers répondant à des conditions d’inéligibilité", data: { 'fr-checked-label': "Activé", 'fr-unchecked-label': "Désactivé" }, class: 'fr-toggle__label'

.fr-fieldset__element= render Dsfr::InputComponent.new(form: f, attribute: :ineligibilite_message, input_type: :text_area, opts: {rows: 5})

.fr-mx-1w.fr-label.fr-py-0.fr-mb-1w.fr-mt-2w
Conditions d’inéligibilité
%span.fr-hint-text Vous pouvez utiliser une ou plusieurs condtions pour bloquer le dépot.
.fr-fieldset__element
= form_tag admin_procedure_ineligibilite_rules_path(@draft_revision.procedure_id), method: :patch, data: { turbo: true, controller: 'autosave' }, class: 'form width-100' do
.conditionnel.width-100
%table.condition-table
- if rows.size > 0
%thead
%tr
%th.fr-pt-0.far-left
%th.fr-pt-0.target Champ Cible
%th.fr-pt-0.operator Opérateur
%th.fr-pt-0.value Valeur
%th.fr-pt-0.delete-column
%tbody
- rows.each.with_index do |(targeted_champ, operator_name, value), row_index|
%tr
%td.far-left= far_left_tag(row_index)
%td.target= left_operand_tag(targeted_champ, row_index)
%td.operator= operator_tag(operator_name, targeted_champ, row_index)
%td.value= right_operand_tag(targeted_champ, value, row_index, operator_name)
%td.delete-column= delete_condition_tag(row_index)
%tfoot
%tr
%td.text-right{ colspan: 5 }= add_condition_tag

.padded-fixed-footer
.fixed-footer
.fr-container
.fr-grid-row.fr-col-offset-md-2.fr-col-md-8
.fr-col-12
%ul.fr-btns-group.fr-btns-group--inline-md
%li
= link_to "Annuler et revenir à l'écran de gestion", admin_procedure_path(id: @draft_revision.procedure), class: 'fr-btn fr-btn--secondary', data: { confirm: 'Si vous avez fait des modifications elles ne seront pas sauvegardées.'}
%li
= button_tag "Enregistrer", class: "fr-btn", form: 'ineligibilite_form'
17 changes: 14 additions & 3 deletions app/components/dossiers/edit_footer_component.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
class Dossiers::EditFooterComponent < ApplicationComponent
delegate :can_passer_en_construction?, to: :@dossier

def initialize(dossier:, annotation:)
@dossier = dossier
@annotation = annotation
Expand All @@ -14,20 +16,29 @@ def annotation?
@annotation.present?
end

def disabled_submit_buttons_options
{
class: 'fr-text--sm fr-mb-0 fr-mr-2w',
data: { 'fr-opened': "true" },
aria: { controls: 'modal-eligibilite-rules-dialog' }
}
end

def submit_draft_button_options
{
class: 'fr-btn fr-btn--sm',
disabled: !owner?,
disabled: !owner? || !can_passer_en_construction?,
method: :post,
data: { 'disable-with': t('.submitting'), controller: 'autosave-submit' }
data: { 'disable-with': t('.submitting'), controller: 'autosave-submit', turbo_force: :server }
}
end

def submit_en_construction_button_options
{
class: 'fr-btn fr-btn--sm',
disabled: !can_passer_en_construction?,
method: :post,
data: { 'disable-with': t('.submitting'), controller: 'autosave-submit' },
data: { 'disable-with': t('.submitting'), controller: 'autosave-submit', turbo_force: :server },
form: { id: "form-submit-en-construction" }
}
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
en:
submit: Submit the file
submit_changes: Submit file changes
submit_disabled: File submission disabled
submitting: Submitting…
invite_notice: You are invited to make amendments to this file but <strong>only the owner themselves can submit it</strong>.
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
fr:
submit: Déposer le dossier
submit_changes: Déposer les modifications
submit_disabled: Pourquoi je ne peux pas déposer mon dossier ?
submitting: Envoi en cours…
invite_notice: En tant qu’invité, vous pouvez remplir ce formulaire – mais <strong>le titulaire du dossier doit le déposer lui-même</strong>.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@
= render Dossiers::AutosaveFooterComponent.new(dossier: @dossier, annotation: annotation?)

- if !annotation? && @dossier.can_transition_to_en_construction?
- if !can_passer_en_construction?
= link_to t('.submit_disabled'), "#", disabled_submit_buttons_options
= button_to t('.submit'), brouillon_dossier_url(@dossier), submit_draft_button_options
- elsif @dossier.forked_with_changes?

- if @dossier.forked_with_changes?
- if !can_passer_en_construction?
= link_to t('.submit_disabled'), "#", disabled_submit_buttons_options
= button_to t('.submit_changes'), modifier_dossier_url(@dossier.editing_fork_origin), submit_en_construction_button_options


Expand Down
8 changes: 3 additions & 5 deletions app/components/dossiers/errors_full_messages_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,15 @@
class Dossiers::ErrorsFullMessagesComponent < ApplicationComponent
ErrorDescriptor = Data.define(:anchor, :label, :error_message)

def initialize(dossier:, errors:)
def initialize(dossier:)
@dossier = dossier
@errors = errors
end

def dedup_and_partitioned_errors
formated_errors = @errors.to_enum # ActiveModel::Errors.to_a is an alias to full_messages, we don't want that
@dossier.errors.to_enum # ActiveModel::Errors.to_a is an alias to full_messages, we don't want that
.to_a # but enum.to_a gives back an array
.uniq { |error| [error.inner_error.base] } # dedup cumulated errors from dossier.champs, dossier.champs_public, dossier.champs_private which run the validator one time per association
.map { |error| to_error_descriptor(error) }
yield(Array(formated_errors[0..2]), Array(formated_errors[3..]))
end

def to_error_descriptor(error)
Expand All @@ -27,6 +25,6 @@ def to_error_descriptor(error)
end

def render?
[email protected]?
!@dossier.errors.empty?
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@ en:
Your file has 1 error. <a href="%{url}">Fix-it</a> to continue :
other: |
Your file has %{count} errors. <a href="%{url}">Fix-them</a> to continue :
see_more: Show all errors
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@ fr:
Votre dossier contient 1 champ en erreur. <a href="%{url}">Corrigez-la</a> pour poursuivre :
other: |
Votre dossier contient %{count} champs en erreurs. <a href="%{url}">Corrigez-les</a> pour poursuivre :
see_more: Afficher toutes les erreurs
Original file line number Diff line number Diff line change
@@ -1,15 +1,4 @@
.fr-alert.fr-alert--error.fr-mb-3w{ role: "alertdialog" }
- dedup_and_partitioned_errors do |head, tail|
%p#sumup-errors= t('.sumup_html', count: head.size + tail.size, url: head.first.anchor)
%ul.fr-mb-0#head-errors
- head.each do |error_descriptor|
%li
= link_to error_descriptor.label, error_descriptor.anchor, class: 'error-anchor'
= error_descriptor.error_message
- if tail.size > 0
%button{ type: "button", "aria-controls": 'tail-errors', "aria-expanded": "false", class: "fr-btn fr-btn--sm fr-btn--tertiary-no-outline" }= t('.see_more')
%ul#tail-errors.fr-collapse.fr-mt-0
- tail.each do |error_descriptor|
%li
= link_to error_descriptor.label, error_descriptor.anchor, class: 'error-anchor'
= "(#{error_descriptor.error_message})"
- if dedup_and_partitioned_errors.size > 0
%p#sumup-errors= t('.sumup_html', count: dedup_and_partitioned_errors.size, url: dedup_and_partitioned_errors.first.anchor)
= render ExpandableErrorList.new(errors: dedup_and_partitioned_errors)
16 changes: 16 additions & 0 deletions app/components/dossiers/invalid_ineligibilite_rules_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
class Dossiers::InvalidIneligibiliteRulesComponent < ApplicationComponent
delegate :can_passer_en_construction?, to: :@dossier

def initialize(dossier:)
@dossier = dossier
@revision = dossier.revision
end

def render?
!can_passer_en_construction?
end

def error_message
@dossier.revision.ineligibilite_message
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
fr:
modal:
title: "Your file does not match submission criteria"
close: "Close"
close_alt: "Close this modal"
body: "The procedure « %{procedure_libelle} » have submission criteria, unfortunately your file does not match them. You can not submit your file"
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fr:
modal:
title: "Vous ne pouvez pas déposer votre dossier"
close: "Fermer"
close_alt: "Fermer la fenêtre modale"
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
%div{ id: dom_id(@dossier, :ineligibilite_rules_broken), data: { controller: 'ineligibilite-rules-match', turbo_force: :server } }
%button.fr-sr-only{ aria: {controls: 'modal-eligibilite-rules-dialog' }, data: {'fr-opened': "false" } }
show modal

%dialog.fr-modal{ "aria-labelledby" => "fr-modal-title-modal-1", role: "dialog", id: 'modal-eligibilite-rules-dialog', data: { 'ineligibilite-rules-match-target' => 'dialog' } }
.fr-container.fr-container--fluid.fr-container-md
.fr-grid-row.fr-grid-row--center
.fr-col-12.fr-col-md-8.fr-col-lg-6
.fr-modal__body
.fr-modal__header
%button.fr-btn--close.fr-btn{ aria: { controls: 'modal-eligibilite-rules-dialog' }, title: t('.modal.close_alt') }= t('.modal.close')
.fr-modal__content
%h1#fr-modal-title-modal-1.fr-modal__title
%span.fr-icon-arrow-right-line.fr-icon--lg>
= t('.modal.title')
%p= error_message
9 changes: 9 additions & 0 deletions app/components/expandable_error_list.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class ExpandableErrorList < ApplicationComponent
def initialize(errors:)
@errors = errors
end

def splitted_errors
yield(Array(@errors[0..2]), Array(@errors[3..]))
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
en:
see_more: Show all errors
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
fr:
see_more: Afficher toutes les erreurs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
- splitted_errors do |head, tail|
%ul#head-errors.fr-mb-0
- head.each do |error_descriptor|
%li
= link_to error_descriptor.label, error_descriptor.anchor, class: 'error-anchor'
= error_descriptor.error_message

- if tail.size > 0
%button.fr-mt-0.fr-btn.fr-btn--sm.fr-btn--tertiary-no-outline{ type: "button", "aria-controls": 'tail-errors', "aria-expanded": "false", class: "" }= t('see_more')
%ul#tail-errors.fr-collapse.fr-mt-0
- tail.each do |error_descriptor|
%li
= link_to error_descriptor.label, error_descriptor.anchor, class: 'error-anchor'
= error_descriptor.error_message
19 changes: 19 additions & 0 deletions app/components/procedure/card/ineligibilite_dossier_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class Procedure::Card::IneligibiliteDossierComponent < ApplicationComponent
def initialize(procedure:)
@procedure = procedure
end

def ready?
@procedure.draft_revision
.conditionable_types_de_champ
.present? && @procedure.draft_revision.ineligibilite_enabled
end

def error?
[email protected]_revision.validate(:ineligibilite_rules_editor)

Check warning on line 13 in app/components/procedure/card/ineligibilite_dossier_component.rb

View check run for this annotation

Codecov / codecov/patch

app/components/procedure/card/ineligibilite_dossier_component.rb#L13

Added line #L13 was not covered by tests
end

def completed?
@procedure.draft_revision.ineligibilite_enabled

Check warning on line 17 in app/components/procedure/card/ineligibilite_dossier_component.rb

View check run for this annotation

Codecov / codecov/patch

app/components/procedure/card/ineligibilite_dossier_component.rb#L17

Added line #L17 was not covered by tests
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
fr:
title: Inéligibilité des dossiers
state:
pending: Désactivé
ready: À configurer
completed: Activé
subtitle: Gérez vos conditions d’inéligibilité en fonction des champs du formulaire
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.fr-col-6.fr-col-md-4.fr-col-lg-3
= link_to edit_admin_procedure_ineligibilite_rules_path(@procedure), class: 'fr-tile fr-enlarge-link' do
.fr-tile__body.flex.column.align-center.justify-between
- if !ready?
%p.fr-badge.fr-badge= t('.state.pending')
- elsif error?
%p.fr-badge.fr-badge--error À modifier
- else
%p.fr-badge.fr-badge--success= t('.state.completed')
%div
%h3.fr-h6.fr-mt-10v= t('.title')
%p.fr-tile-subtitle= t('.subtitle')
%p.fr-btn.fr-btn--tertiary= t('views.shared.actions.edit')
Loading
Loading