feat(piece_justificative): supports multiple files

Closes #7924
This commit is contained in:
Colin Darie 2022-10-25 14:14:24 +02:00
parent ab1928dc33
commit b8296c6d4d
17 changed files with 242 additions and 78 deletions

View file

@ -1,16 +1,27 @@
# Display a widget for uploading, editing and deleting a file attachment
class Attachment::EditComponent < ApplicationComponent
def initialize(form:, attached_file:, template: nil, user_can_destroy: false, direct_upload: true, id: nil)
attr_reader :template, :form, :attachment
delegate :persisted?, to: :attachment, allow_nil: true
def initialize(form:, attached_file:, attachment: nil, user_can_destroy: false, direct_upload: true, id: nil, index: 0)
@form = form
@attached_file = attached_file
@template = template
@attachment = if attachment
attachment
elsif attached_file.respond_to?(:attachment)
attached_file.attachment
else
# multiple attachments: attachment kwarg is expected, unless adding a new attachment
end
@user_can_destroy = user_can_destroy
@direct_upload = direct_upload
@id = id
@index = index
end
attr_reader :template, :form
def max_file_size
file_size_validator.options[:less_than]
end
@ -19,26 +30,18 @@ class Attachment::EditComponent < ApplicationComponent
@user_can_destroy
end
def attachment
@attached_file.attachment
end
def attachment_path
helpers.attachment_path attachment.id, { signed_id: attachment.blob.signed_id }
end
def attachment_id
@attachment_id ||= attachment ? attachment.id : SecureRandom.uuid
@attachment_id ||= (attachment&.id || SecureRandom.uuid)
end
def attachment_input_class
"attachment-input-#{attachment_id}"
end
def persisted?
attachment&.persisted?
end
def champ
@form.object.is_a?(Champ) ? @form.object : nil
end
@ -51,13 +54,25 @@ class Attachment::EditComponent < ApplicationComponent
id: input_id(@id),
aria: { describedby: champ&.describedby_id },
data: {
auto_attach_url: helpers.auto_attach_url(form.object)
}.merge(has_file_size_validator? ? { max_file_size: max_file_size } : {})
auto_attach_url:
}.merge(has_file_size_validator? ? { max_file_size: } : {})
}.merge(has_content_type_validator? ? { accept: accept_content_type } : {})
end
def auto_attach_url
helpers.auto_attach_url(form.object, replace_attachment_id: persisted? ? attachment_id : nil)
end
def input_id(given_id)
[given_id, champ&.input_id, file_field_name].reject(&:blank?).compact.first
return given_id if given_id.present?
if champ.present?
# Single or first attachment input must match label "for" attribute. Others must remain unique.
return champ.input_id if @index.zero?
return "#{champ.input_id}_#{attachment_id}"
end
file_field_name
end
def file_field_name

View file

@ -1,15 +1,4 @@
.attachment
- if template&.attached?
%p.mb-1
Veuillez télécharger, remplir et joindre
= link_to(url_for(template), download: "", class: "fr-link fr-link--icon-right fr-icon-download-line") do
le modèle suivant
- if helpers.administrateur_signed_in?
%span.ml-2.fr-text--xs.fr-text-mention--grey.visible-on-previous-hover
%span.fr-text-action-high--blue-france.fr-icon-questionnaire-line{ "aria-hidden": "true" }
= t('shared.ephemeral_link')
.fr-mb-2w
- if persisted?
.attachment-actions{ id: dom_id(attachment, :actions) }
.attachment-action
@ -30,8 +19,9 @@
%span.icon.retry
Ré-essayer
- if !persisted?
%label.text-sm.font-weight-normal{ for: file_field_options[:id] }
= t('.max_file_size', max_file_size: number_to_human_size(max_file_size))
%label.text-sm.font-weight-normal{ for: file_field_options[:id] }
= t('.max_file_size', max_file_size: number_to_human_size(max_file_size))
%p= form.file_field(file_field_name, **file_field_options)
= form.file_field(file_field_name, **file_field_options)

View file

@ -0,0 +1,43 @@
# Display a widget for uploading, editing and deleting a file attachment
class Attachment::MultipleComponent < ApplicationComponent
renders_one :template
attr_reader :form
attr_reader :attached_file
attr_reader :direct_upload
attr_reader :id
attr_reader :user_can_destroy
delegate :count, :empty?, to: :attachments, prefix: true
def initialize(form:, attached_file:, user_can_destroy: false, direct_upload: true, id: nil)
@form = form
@attached_file = attached_file
@user_can_destroy = user_can_destroy
@direct_upload = direct_upload
@id = id
@attachments = attached_file.attachments || []
end
def each_attachment(&block)
@attachments.each_with_index(&block)
end
def can_attach_next?
return false if @attachments.empty?
return false if !@attachments.last.persisted?
true
end
def stimulus_controller_name
"attachment-multiple"
end
private
def attachments
@attachments
end
end

View file

@ -0,0 +1,13 @@
.fr-mb-4w{ data: { controller: stimulus_controller_name }}
= template
- each_attachment do |attachment, index|
%div{id: dom_id(attachment)}
= render Attachment::EditComponent.new(form:, attached_file:, attachment:, user_can_destroy:, direct_upload:, id:, index:)
%div{class: [attachments_empty? ? nil : "hidden"], data: { "#{stimulus_controller_name}-target": "empty" }}
= render Attachment::EditComponent.new(form:, attached_file:, user_can_destroy:, direct_upload:, id:, index: attachments_count)
- if can_attach_next?
%button.fr-btn.fr-btn--tertiary.fr-btn--sm{ data: { "#{stimulus_controller_name}-target": "buttonAdd", action: "click->attachment-multiple#add" }} Ajouter un fichier