diff --git a/app/controllers/instructeurs/dossiers_controller.rb b/app/controllers/instructeurs/dossiers_controller.rb index ae148d258..c95fb1ee5 100644 --- a/app/controllers/instructeurs/dossiers_controller.rb +++ b/app/controllers/instructeurs/dossiers_controller.rb @@ -370,9 +370,24 @@ module Instructeurs def pieces_jointes @dossier = current_instructeur.dossiers.find(params[:dossier_id]) - @champs_with_pieces_jointes = @dossier + + champs_attachments_and_libelles = @dossier .champs .filter { _1.class.in?([Champs::PieceJustificativeChamp, Champs::TitreIdentiteChamp]) } + .flat_map do |c| + c.piece_justificative_file.map do |attachment| + [attachment, c.libelle] + end + end + + commentaires_attachments_and_libelles = @dossier + .commentaires + .map(&:piece_jointe) + .map(&:attachments) + .flatten + .map { [_1, 'Messagerie'] } + + @attachments_and_libelles = champs_attachments_and_libelles + commentaires_attachments_and_libelles end private diff --git a/app/models/concerns/blob_image_processor_concern.rb b/app/models/concerns/blob_image_processor_concern.rb index 3b92ad4e4..d69e380f5 100644 --- a/app/models/concerns/blob_image_processor_concern.rb +++ b/app/models/concerns/blob_image_processor_concern.rb @@ -8,11 +8,19 @@ module BlobImageProcessorConcern end def representation_required? - attachments.any? { _1.record.class == Champs::TitreIdentiteChamp || _1.record.class == Champs::PieceJustificativeChamp } + from_champ? || from_messagerie? end private + def from_champ? + attachments.any? { _1.record.class == Champs::TitreIdentiteChamp || _1.record.class == Champs::PieceJustificativeChamp } + end + + def from_messagerie? + attachments.any? { _1.record.class == Commentaire } + end + def watermark_required? attachments.any? { _1.record.class == Champs::TitreIdentiteChamp } end diff --git a/app/tasks/maintenance/create_previews_for_pjs_from_messagerie_task.rb b/app/tasks/maintenance/create_previews_for_pjs_from_messagerie_task.rb new file mode 100644 index 000000000..b75c530b9 --- /dev/null +++ b/app/tasks/maintenance/create_previews_for_pjs_from_messagerie_task.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module Maintenance + class CreatePreviewsForPjsFromMessagerieTask < MaintenanceTasks::Task + attribute :start_text, :string + validates :start_text, presence: true + + attribute :end_text, :string + validates :end_text, presence: true + + def collection + start_date = DateTime.parse(start_text) + end_date = DateTime.parse(end_text) + + Dossier + .state_en_construction_ou_instruction + .where(depose_at: start_date..end_date) + end + + def process(dossier) + commentaire_ids = Commentaire + .where(dossier_id: dossier) + .pluck(:id) + + attachments = ActiveStorage::Attachment + .where(record_id: commentaire_ids) + + attachments.each do |attachment| + next if !(attachment.previewable? && attachment.representation_required?) + attachment.preview(resize_to_limit: [400, 400]).processed unless attachment.preview(resize_to_limit: [400, 400]).image.attached? + rescue MiniMagick::Error, ActiveStorage::Error + end + end + end +end diff --git a/app/tasks/maintenance/create_variants_for_pjs_from_messagerie__task.rb b/app/tasks/maintenance/create_variants_for_pjs_from_messagerie__task.rb new file mode 100644 index 000000000..fa1eb30d2 --- /dev/null +++ b/app/tasks/maintenance/create_variants_for_pjs_from_messagerie__task.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +module Maintenance + class CreateVariantsForPjsFromMessagerieTask < MaintenanceTasks::Task + attribute :start_text, :string + validates :start_text, presence: true + + attribute :end_text, :string + validates :end_text, presence: true + + def collection + start_date = DateTime.parse(start_text) + end_date = DateTime.parse(end_text) + + Dossier + .state_en_construction_ou_instruction + .where(depose_at: start_date..end_date) + end + + def process(dossier) + commentaire_ids = Commentaire + .where(dossier_id: dossier) + .pluck(:id) + + attachments = ActiveStorage::Attachment + .where(record_id: commentaire_ids) + + attachments.each do |attachment| + next if !(attachment.variable? && attachment.representation_required?) + attachment.variant(resize_to_limit: [400, 400]).processed if attachment.variant(resize_to_limit: [400, 400]).key.nil? + if attachment.blob.content_type.in?(RARE_IMAGE_TYPES) && attachment.variant(resize_to_limit: [2000, 2000]).key.nil? + attachment.variant(resize_to_limit: [2000, 2000]).processed + end + rescue MiniMagick::Error, ActiveStorage::Error + end + end + end +end diff --git a/app/views/instructeurs/dossiers/pieces_jointes.html.haml b/app/views/instructeurs/dossiers/pieces_jointes.html.haml index d770433d4..97ab75c55 100644 --- a/app/views/instructeurs/dossiers/pieces_jointes.html.haml +++ b/app/views/instructeurs/dossiers/pieces_jointes.html.haml @@ -4,33 +4,32 @@ .fr-container .gallery.gallery-pieces-jointes{ "data-controller": "lightbox" } - - @champs_with_pieces_jointes.each do |champ| - - champ.piece_justificative_file.with_all_variant_records.each do |attachment| - .gallery-item - - blob = attachment.blob - - if displayable_pdf?(blob) - = link_to blob.url, id: blob.id, data: { iframe: true, src: blob.url }, class: 'gallery-link', type: blob.content_type, title: "#{champ.libelle} -- #{blob.filename}" do - .thumbnail - = image_tag(preview_url_for(attachment), loading: :lazy) - .fr-btn.fr-btn--tertiary.fr-btn--icon-left.fr-icon-eye{ role: :button } - Visualiser - .champ-libelle - = champ.libelle.truncate(25) - = render Attachment::ShowComponent.new(attachment: attachment, truncate: true) - - - elsif displayable_image?(blob) - = link_to image_url(blob_url(attachment)), title: "#{champ.libelle} -- #{blob.filename}", data: { src: blob.url }, class: 'gallery-link' do - .thumbnail - = image_tag(variant_url_for(attachment), loading: :lazy) - .fr-btn.fr-btn--tertiary.fr-btn--icon-left.fr-icon-eye{ role: :button } - Visualiser - .champ-libelle - = champ.libelle.truncate(25) - = render Attachment::ShowComponent.new(attachment: attachment, truncate: true) - - - else + - @attachments_and_libelles.each do |attachment, libelle| + .gallery-item + - blob = attachment.blob + - if displayable_pdf?(blob) + = link_to blob.url, id: blob.id, data: { iframe: true, src: blob.url }, class: 'gallery-link', type: blob.content_type, title: "#{libelle} -- #{blob.filename}" do .thumbnail - = image_tag('apercu-indisponible.png') - .champ-libelle - = champ.libelle.truncate(25) - = render Attachment::ShowComponent.new(attachment: attachment, truncate: true) + = image_tag(preview_url_for(attachment), loading: :lazy) + .fr-btn.fr-btn--tertiary.fr-btn--icon-left.fr-icon-eye{ role: :button } + Visualiser + .champ-libelle + = libelle.truncate(25) + = render Attachment::ShowComponent.new(attachment: attachment, truncate: true) + + - elsif displayable_image?(blob) + = link_to image_url(blob_url(attachment)), title: "#{libelle} -- #{blob.filename}", data: { src: blob.url }, class: 'gallery-link' do + .thumbnail + = image_tag(variant_url_for(attachment), loading: :lazy) + .fr-btn.fr-btn--tertiary.fr-btn--icon-left.fr-icon-eye{ role: :button } + Visualiser + .champ-libelle + = libelle.truncate(25) + = render Attachment::ShowComponent.new(attachment: attachment, truncate: true) + + - else + .thumbnail + = image_tag('apercu-indisponible.png') + .champ-libelle + = libelle.truncate(25) + = render Attachment::ShowComponent.new(attachment: attachment, truncate: true) diff --git a/spec/controllers/instructeurs/dossiers_controller_spec.rb b/spec/controllers/instructeurs/dossiers_controller_spec.rb index 2ad0cb84d..a8ae359ab 100644 --- a/spec/controllers/instructeurs/dossiers_controller_spec.rb +++ b/spec/controllers/instructeurs/dossiers_controller_spec.rb @@ -1466,25 +1466,37 @@ describe Instructeurs::DossiersController, type: :controller do describe '#pieces_jointes' do let(:procedure) { create(:procedure, :published, types_de_champ_public: [{ type: :piece_justificative }], instructeurs:) } let(:dossier) { create(:dossier, :en_construction, :with_populated_champs, procedure: procedure) } - let(:path) { 'spec/fixtures/files/logo_test_procedure.png' } + let(:logo_path) { 'spec/fixtures/files/logo_test_procedure.png' } + let(:rib_path) { 'spec/fixtures/files/RIB.pdf' } + let(:commentaire) { create(:commentaire, dossier: dossier) } before do dossier.champs.first.piece_justificative_file.attach( - io: File.open(path), + io: File.open(logo_path), filename: "logo_test_procedure.png", content_type: "image/png", metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE } ) + + commentaire.piece_jointe.attach( + io: File.open(rib_path), + filename: "RIB.pdf", + content_type: "application/pdf", + metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE } + ) + get :pieces_jointes, params: { procedure_id: procedure.id, dossier_id: dossier.id } end - it do + it 'returns pieces jointes from champs and from messagerie' do expect(response.body).to include('Télécharger le fichier toto.txt') expect(response.body).to include('Télécharger le fichier logo_test_procedure.png') + expect(response.body).to include('Télécharger le fichier RIB.pdf') expect(response.body).to include('Visualiser') + expect(assigns(:attachments_and_libelles).count).to eq 3 end end end diff --git a/spec/tasks/maintenance/create_previews_for_pjs_from_messagerie_task_spec.rb b/spec/tasks/maintenance/create_previews_for_pjs_from_messagerie_task_spec.rb new file mode 100644 index 000000000..245c1971c --- /dev/null +++ b/spec/tasks/maintenance/create_previews_for_pjs_from_messagerie_task_spec.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +require "rails_helper" + +module Maintenance + RSpec.describe CreatePreviewsForPjsFromMessagerieTask do + describe "#process" do + let(:procedure) { create(:procedure_with_dossiers) } + let(:dossier) { procedure.dossiers.first } + let(:commentaire) { create(:commentaire, dossier: dossier) } + + before do + commentaire.piece_jointe.attach( + io: File.open(file_path), + filename: file_name, + content_type: content_type, + metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE } + ) + dossier.update( + depose_at: Date.new(2024, 05, 23), + state: "en_construction" + ) + end + + subject(:process) { described_class.process(dossier) } + + context "when pj is a pdf" do + let(:file_path) { 'spec/fixtures/files/RIB.pdf' } + let(:file_name) { 'RIB.pdf' } + let(:content_type) { 'application/pdf' } + + it "creates a preview" do + expect(commentaire.piece_jointe.first.preview(resize_to_limit: [400, 400]).image.attached?).to be false + expect { subject }.to change { commentaire.piece_jointe.first.reload.preview(resize_to_limit: [400, 400]).image.attached? } + end + end + end + end +end diff --git a/spec/tasks/maintenance/create_variants_for_pjs_from_messagerie__task_spec.rb b/spec/tasks/maintenance/create_variants_for_pjs_from_messagerie__task_spec.rb new file mode 100644 index 000000000..0428e6d0b --- /dev/null +++ b/spec/tasks/maintenance/create_variants_for_pjs_from_messagerie__task_spec.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +require "rails_helper" + +module Maintenance + RSpec.describe CreateVariantsForPjsFromMessagerieTask do + describe "#process" do + let(:procedure) { create(:procedure_with_dossiers) } + let(:dossier) { procedure.dossiers.first } + let(:commentaire) { create(:commentaire, dossier: dossier) } + + before do + commentaire.piece_jointe.attach( + io: File.open(file_path), + filename: file_name, + content_type: content_type, + metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE } + ) + dossier.update( + depose_at: Date.new(2024, 05, 23), + state: "en_construction" + ) + end + + subject(:process) { described_class.process(dossier) } + + context "when pj is a classical format image" do + let(:file_path) { 'spec/fixtures/files/logo_test_procedure.png' } + let(:file_name) { 'logo_test_procedure.png' } + let(:content_type) { 'image/png' } + + it "creates a variant" do + expect(commentaire.piece_jointe.first.variant(resize_to_limit: [400, 400]).key).to be_nil + expect { subject }.to change { ActiveStorage::VariantRecord.count }.by(1) + expect(commentaire.piece_jointe.first.variant(resize_to_limit: [400, 400]).key).not_to be_nil + expect(commentaire.piece_jointe.first.variant(resize_to_limit: [2000, 2000]).key).to be_nil + end + end + + context "when pj is a rare format image" do + let(:file_path) { 'spec/fixtures/files/pencil.tiff' } + let(:file_name) { 'pencil.tiff' } + let(:content_type) { 'image/tiff' } + + it "creates a variant" do + expect(commentaire.piece_jointe.first.variant(resize_to_limit: [400, 400]).key).to be_nil + expect { subject }.to change { ActiveStorage::VariantRecord.count }.by(2) + expect(commentaire.piece_jointe.first.variant(resize_to_limit: [400, 400]).key).not_to be_nil + expect(commentaire.piece_jointe.first.variant(resize_to_limit: [2000, 2000]).key).not_to be_nil + end + end + end + end +end