Merge pull request #9871 from mfo/US/add-pj-to-explication
ETQ administrateur, je peux ajouter une notice explicative a un champs explication
This commit is contained in:
commit
e75c4456e8
13 changed files with 112 additions and 26 deletions
|
@ -1,2 +1,4 @@
|
|||
class EditableChamp::ExplicationComponent < EditableChamp::EditableChampBaseComponent
|
||||
delegate :type_de_champ, to: :@champ
|
||||
delegate :notice_explicative, to: :type_de_champ
|
||||
end
|
||||
|
|
|
@ -8,3 +8,5 @@
|
|||
%button{ type: "button", "aria-controls": dom_id(@champ, :explanation), "aria-expanded": "false", href: dom_id(@champ, :explanation), class: "fr-btn ft-btn--sm fr-btn--secondary" } Lire plus
|
||||
.fr-collapse{ id: dom_id(@champ, :explanation) }
|
||||
= render SimpleFormatComponent.new(@champ.collapsible_explanation_text, allow_a: true)
|
||||
- if notice_explicative.attached?
|
||||
= render Dsfr::DownloadComponent.new(attachment: notice_explicative, virus_not_analyzed: !notice_explicative.virus_scanner.started?, new_tab: true)
|
||||
|
|
|
@ -24,6 +24,7 @@ fr:
|
|||
update_drop_down_secondary_description: La description secondaire du champ « %{label} » a été modifiée. La nouvelle description est « %{to} ».
|
||||
update_type_champ: Le type du champ « %{label} » a été modifié. Il est maintenant de type « %{to} ».
|
||||
update_piece_justificative_template: Le modèle de pièce justificative du champ « %{label} » a été modifié.
|
||||
update_notice_explicative: La notice explicative du champ « %{label} » a été modifiée.
|
||||
update_drop_down_options: "Les options de sélection du champ « %{label} » ont été modifiées :"
|
||||
update_drop_down_options_alert: "Le champ « %{label} » est utilisé pour le routage des dossiers. Veuillez mettre à jour la configuration des groupes d'instructeurs après avoir publié les modifications."
|
||||
enable_mandatory: Le champ « %{label} » est maintenant obligatoire.
|
||||
|
@ -59,6 +60,7 @@ fr:
|
|||
update_drop_down_secondary_description: La description secondaire de l’annotation « %{label} » a été modifiée. La nouvelle description est « %{to} ».
|
||||
update_type_champ: Le type de l’annotation privée « %{label} » a été modifié. Elle est maintenant de type « %{to} ».
|
||||
update_piece_justificative_template: Le modèle de pièce justificative de l’annotation privée « %{label} » a été modifié.
|
||||
update_notice_explicative: La notice explicative l’annotation privée « %{label} » a été modifiée.
|
||||
update_drop_down_options: "Les options de sélection de l’annotation privée « %{label} » ont été modifiées :"
|
||||
update_carte_layers: "Les référentiels cartographiques de l’annotation privée « %{label} » ont été modifiés :"
|
||||
enable_drop_down_other: L’annotation privée « %{label} » comporte maintenant un choix « Autre ».
|
||||
|
|
|
@ -59,6 +59,9 @@
|
|||
- when :piece_justificative_template
|
||||
- list.with_item do
|
||||
= t(".#{prefix}.update_piece_justificative_template", label: change.label)
|
||||
- when :notice_explicative
|
||||
- list.with_item do
|
||||
= t(".#{prefix}.update_notice_explicative", label: change.label)
|
||||
- when :drop_down_options
|
||||
- added = change.to.sort - change.from.sort
|
||||
- removed = change.from.sort - change.to.sort
|
||||
|
|
|
@ -82,6 +82,14 @@ class TypesDeChampEditor::ChampComponent < ApplicationComponent
|
|||
}
|
||||
end
|
||||
|
||||
def notice_explicative_options
|
||||
{
|
||||
attached_file: type_de_champ.notice_explicative,
|
||||
auto_attach_url: helpers.auto_attach_url(type_de_champ),
|
||||
view_as: :download
|
||||
}
|
||||
end
|
||||
|
||||
EXCLUDE_FROM_BLOCK = [
|
||||
TypeDeChamp.type_champs.fetch(:carte),
|
||||
TypeDeChamp.type_champs.fetch(:dossier_link),
|
||||
|
|
|
@ -41,34 +41,46 @@
|
|||
%small Nous numérotons automatiquement les titres lorsqu’aucun de vos titres ne commence par un chiffre.
|
||||
|
||||
- if type_de_champ.expression_reguliere?
|
||||
.cell.mt-1
|
||||
.cell.fr-mt-1w
|
||||
= form.label :expression_reguliere, for: dom_id(type_de_champ, :expression_reguliere) do
|
||||
= t('.expression_reguliere.labels.regex')
|
||||
.type-de-champ-expression-reguliere
|
||||
= form.text_field :expression_reguliere, class: "fr-input small-margin small", id: dom_id(type_de_champ, :expression_reguliere)
|
||||
|
||||
.cell.mt-1
|
||||
.cell.fr-mt-1w
|
||||
= form.label :expression_reguliere_exemple_text, for: dom_id(type_de_champ, :expression_reguliere_exemple_text) do
|
||||
= t('.expression_reguliere.labels.valid_exemple')
|
||||
= form.text_field :expression_reguliere_exemple_text, class: "fr-input small-margin small", id: dom_id(type_de_champ, :expression_reguliere_exemple_text)
|
||||
- if type_de_champ.invalid_regexp?
|
||||
%p.fr-message.fr-message--error
|
||||
= type_de_champ.errors[:expression_reguliere_exemple_text].join(", ")
|
||||
.cell.mt-1
|
||||
.cell.fr-mt-1w
|
||||
= form.label :expression_reguliere_error_message, for: dom_id(type_de_champ, :expression_reguliere_error_message) do
|
||||
= t('.expression_reguliere.labels.error_message')
|
||||
= form.text_field :expression_reguliere_error_message, class: "fr-input small-margin small", id: dom_id(type_de_champ, :expression_reguliere_error_message)
|
||||
- if !type_de_champ.header_section? && !type_de_champ.titre_identite?
|
||||
.cell.mt-1
|
||||
.cell.fr-mt-1w
|
||||
= 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
|
||||
.cell.fr-mt-1w
|
||||
= render TypesDeChampEditor::HeaderSectionComponent.new(form: form, tdc: type_de_champ, upper_tdcs: @upper_coordinates.map(&:type_de_champ))
|
||||
- if type_de_champ.explication?
|
||||
.cell.fr-mt-1w
|
||||
= 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)
|
||||
.cell.fr-mt-1w
|
||||
= form.label :notice_explicative, "Notice explicative", for: dom_id(type_de_champ, :notice_explicative)
|
||||
= render Attachment::EditComponent.new(**notice_explicative_options)
|
||||
|
||||
|
||||
|
||||
.flex.justify-start.mt-1
|
||||
.flex.justify-start.fr-mt-1w
|
||||
- if type_de_champ.drop_down_list?
|
||||
.flex.column.justify-start.width-33
|
||||
.cell
|
||||
|
@ -85,7 +97,7 @@
|
|||
.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
|
||||
.cell.fr-mt-1w
|
||||
= 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?
|
||||
|
@ -99,6 +111,7 @@
|
|||
Dans le cadre de la RGPD, le titre d’identité sera supprimé lors de l’acceptation, du refus ou du classement sans suite du dossier. Aussi, pour des raisons de sécurités, un filigrane est automatiquement ajouté aux images.
|
||||
- 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
|
||||
|
@ -108,15 +121,6 @@
|
|||
= 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
|
||||
|
|
|
@ -44,6 +44,19 @@ module Administrateurs
|
|||
end
|
||||
end
|
||||
|
||||
def notice_explicative
|
||||
type_de_champ = draft.find_and_ensure_exclusive_use(params[:stable_id])
|
||||
|
||||
if type_de_champ.notice_explicative.attach(params[:blob_signed_id])
|
||||
@coordinate = draft.coordinate_for(type_de_champ)
|
||||
@morphed = [champ_component_from(@coordinate)]
|
||||
|
||||
render :create
|
||||
else
|
||||
render json: { errors: @champ.errors.full_messages }, status: 422
|
||||
end
|
||||
end
|
||||
|
||||
def move
|
||||
draft.move_type_de_champ(params[:stable_id], params[:position].to_i)
|
||||
end
|
||||
|
|
|
@ -10,8 +10,10 @@ module ChampHelper
|
|||
def auto_attach_url(object, params = {})
|
||||
if object.is_a?(Champ)
|
||||
champs_attach_piece_justificative_url(object.id, params)
|
||||
elsif object.is_a?(TypeDeChamp)
|
||||
elsif object.is_a?(TypeDeChamp) && object.piece_justificative?
|
||||
piece_justificative_template_admin_procedure_type_de_champ_url(stable_id: object.stable_id, procedure_id: object.procedure.id, **params)
|
||||
elsif object.is_a?(TypeDeChamp) && object.explication?
|
||||
notice_explicative_admin_procedure_type_de_champ_url(stable_id: object.stable_id, procedure_id: object.procedure.id, **params)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -363,11 +363,18 @@ class ProcedureRevision < ApplicationRecord
|
|||
to_type_de_champ.carte_optional_layers)
|
||||
end
|
||||
elsif to_type_de_champ.piece_justificative?
|
||||
if from_type_de_champ.piece_justificative_template_checksum != to_type_de_champ.piece_justificative_template_checksum
|
||||
if from_type_de_champ.checksum_for_attachment(:piece_justificative_template) != to_type_de_champ.checksum_for_attachment(:piece_justificative_template)
|
||||
changes << ProcedureRevisionChange::UpdateChamp.new(from_type_de_champ,
|
||||
:piece_justificative_template,
|
||||
from_type_de_champ.piece_justificative_template_filename,
|
||||
to_type_de_champ.piece_justificative_template_filename)
|
||||
from_type_de_champ.filename_for_attachement(:piece_justificative_template),
|
||||
to_type_de_champ.filename_for_attachement(:piece_justificative_template))
|
||||
end
|
||||
elsif to_type_de_champ.explication?
|
||||
if from_type_de_champ.checksum_for_attachment(:notice_explicative) != to_type_de_champ.checksum_for_attachment(:notice_explicative)
|
||||
changes << ProcedureRevisionChange::UpdateChamp.new(from_type_de_champ,
|
||||
:notice_explicative,
|
||||
from_type_de_champ.filename_for_attachement(:notice_explicative),
|
||||
to_type_de_champ.filename_for_attachement(:notice_explicative))
|
||||
end
|
||||
elsif to_type_de_champ.textarea?
|
||||
if from_type_de_champ.character_limit != to_type_de_champ.character_limit
|
||||
|
|
|
@ -193,6 +193,21 @@ class TypeDeChamp < ApplicationRecord
|
|||
validates :piece_justificative_template, size: { less_than: FILE_MAX_SIZE }
|
||||
validates :piece_justificative_template, content_type: AUTHORIZED_CONTENT_TYPES
|
||||
|
||||
has_one_attached :notice_explicative
|
||||
validates :notice_explicative, content_type: [
|
||||
"application/msword",
|
||||
"application/pdf",
|
||||
"application/vnd.ms-powerpoint",
|
||||
"application/vnd.oasis.opendocument.presentation",
|
||||
"application/vnd.oasis.opendocument.text",
|
||||
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||
"image/jpeg",
|
||||
"image/jpg",
|
||||
"image/png",
|
||||
"text/plain"
|
||||
], size: { less_than: 20.megabytes }
|
||||
|
||||
validates :libelle, presence: true, allow_blank: false, allow_nil: false
|
||||
validates :type_champ, presence: true, allow_blank: false, allow_nil: false
|
||||
validates :character_limit, numericality: {
|
||||
|
@ -446,15 +461,17 @@ class TypeDeChamp < ApplicationRecord
|
|||
"TypesDeChamp::#{type_champ.classify}TypeDeChamp"
|
||||
end
|
||||
|
||||
def piece_justificative_template_filename
|
||||
if piece_justificative_template.attached?
|
||||
piece_justificative_template.filename
|
||||
def filename_for_attachement(attachment_sym)
|
||||
attachment = send(attachment_sym)
|
||||
if attachment.attached?
|
||||
attachment.filename
|
||||
end
|
||||
end
|
||||
|
||||
def piece_justificative_template_checksum
|
||||
if piece_justificative_template.attached?
|
||||
piece_justificative_template.checksum
|
||||
def checksum_for_attachment(attachment_sym)
|
||||
attachment = send(attachment_sym)
|
||||
if attachment.attached?
|
||||
attachment.checksum
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -625,6 +625,7 @@ Rails.application.routes.draw do
|
|||
patch :move_up
|
||||
patch :move_down
|
||||
put :piece_justificative_template
|
||||
put :notice_explicative
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -50,5 +50,14 @@ describe TypesDeChampEditor::ChampComponent, type: :component do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'tdc explication' do
|
||||
let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :explication }]) }
|
||||
let(:coordinate) { procedure.draft_revision.revision_types_de_champ_public.first }
|
||||
it 'includes an uploader for notice_explicative' do
|
||||
expect(page).to have_css('label', text: 'Notice explicative')
|
||||
expect(page).to have_css('input[type=file]')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -188,4 +188,20 @@ describe Administrateurs::TypesDeChampController, type: :controller do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#notice_explicative' do
|
||||
let(:procedure) { create(:procedure, types_de_champ_public: [{ type: :explication }]) }
|
||||
let(:coordinate) { procedure.draft_revision.types_de_champ.first }
|
||||
let(:file) { Tempfile.new }
|
||||
let(:blob) { ActiveStorage::Blob.create_before_direct_upload!(filename: File.basename(file.path), byte_size: file.size, checksum: Digest::SHA256.file(file.path), content_type: 'text/plain') }
|
||||
|
||||
context 'when sending a valid blob' do
|
||||
it 'attaches the blob and responds with 200' do
|
||||
expect { put :notice_explicative, format: :turbo_stream, params: { stable_id: coordinate.stable_id, procedure_id: procedure.id, blob_signed_id: blob.signed_id } }
|
||||
.to change { coordinate.reload.notice_explicative.attached? }
|
||||
.from(false).to(true)
|
||||
expect(response).to have_http_status(:success)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue