From f3795ebc9817903597836df6dc0bf99164611f75 Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Fri, 24 May 2024 09:46:45 +0200 Subject: [PATCH 1/6] feat(gallery): add pdf previews --- app/views/instructeurs/dossiers/pieces_jointes.html.haml | 6 +++--- app/views/shared/champs/piece_justificative/_show.html.haml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/views/instructeurs/dossiers/pieces_jointes.html.haml b/app/views/instructeurs/dossiers/pieces_jointes.html.haml index 58a867ccd..e3480d617 100644 --- a/app/views/instructeurs/dossiers/pieces_jointes.html.haml +++ b/app/views/instructeurs/dossiers/pieces_jointes.html.haml @@ -8,17 +8,17 @@ - champ.piece_justificative_file.with_all_variant_records.each do |attachment| .gallery-item - blob = attachment.blob - - if blob.content_type.in?(AUTHORIZED_PDF_TYPES) + - if blob.previewable? && blob.content_type.in?(AUTHORIZED_PDF_TYPES) = 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("pdf-placeholder.png") + = image_tag(attachment.preview(resize_to_limit: [400, 400]).processed.url, 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 blob.content_type.in?(AUTHORIZED_IMAGE_TYPES) + - elsif blob.variable? && blob.content_type.in?(AUTHORIZED_IMAGE_TYPES) = link_to image_url(blob.url), title: "#{champ.libelle} -- #{blob.filename}", data: { src: blob.url }, class: 'gallery-link' do .thumbnail = image_tag(attachment.variant(resize_to_limit: [400, 400]).processed.url, loading: :lazy) diff --git a/app/views/shared/champs/piece_justificative/_show.html.haml b/app/views/shared/champs/piece_justificative/_show.html.haml index 734aeadd8..b32f05595 100644 --- a/app/views/shared/champs/piece_justificative/_show.html.haml +++ b/app/views/shared/champs/piece_justificative/_show.html.haml @@ -8,14 +8,14 @@ - champ.piece_justificative_file.attachments.with_all_variant_records.each do |attachment| .gallery-item - blob = attachment.blob - - if blob.content_type.in?(AUTHORIZED_PDF_TYPES) + - if blob.previewable? && blob.content_type.in?(AUTHORIZED_PDF_TYPES) = 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("pdf-placeholder.png") + = image_tag(attachment.preview(resize_to_limit: [400, 400]).processed.url, loading: :lazy) .fr-btn.fr-btn--tertiary.fr-btn--icon-left.fr-icon-eye{ role: :button } = 'Visualiser' - - elsif blob.content_type.in?(AUTHORIZED_IMAGE_TYPES) + - elsif blob.variable? && blob.content_type.in?(AUTHORIZED_IMAGE_TYPES) = link_to image_url(blob.url), title: "#{champ.libelle} -- #{blob.filename}", data: { src: blob.url }, class: 'gallery-link' do .thumbnail = image_tag(attachment.variant(resize_to_limit: [400, 400]).processed.url, loading: :lazy) From 05ad5dcbd67c44ae2663b37d2bc8bf6217b1501b Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Fri, 24 May 2024 09:58:19 +0200 Subject: [PATCH 2/6] feat(gallery): display large variant for rare image types --- app/jobs/image_processor_job.rb | 3 ++ .../dossiers/pieces_jointes.html.haml | 3 +- .../piece_justificative/_show.html.haml | 3 +- .../initializers/authorized_content_types.rb | 4 +++ spec/fixtures/files/pencil.tiff | Bin 0 -> 15224 bytes spec/jobs/image_processor_job_spec.rb | 29 +++++++++++++----- 6 files changed, 33 insertions(+), 9 deletions(-) create mode 100644 spec/fixtures/files/pencil.tiff diff --git a/app/jobs/image_processor_job.rb b/app/jobs/image_processor_job.rb index 8017d2b35..798ba86a1 100644 --- a/app/jobs/image_processor_job.rb +++ b/app/jobs/image_processor_job.rb @@ -38,6 +38,9 @@ class ImageProcessorJob < ApplicationJob blob.attachments.each do |attachment| next unless attachment&.representable? attachment.representation(resize_to_limit: [400, 400]).processed + if attachment.blob.content_type.in?(RARE_IMAGE_TYPES) + attachment.variant(resize_to_limit: [2000, 2000]).processed + end end end diff --git a/app/views/instructeurs/dossiers/pieces_jointes.html.haml b/app/views/instructeurs/dossiers/pieces_jointes.html.haml index e3480d617..eb67f850c 100644 --- a/app/views/instructeurs/dossiers/pieces_jointes.html.haml +++ b/app/views/instructeurs/dossiers/pieces_jointes.html.haml @@ -19,7 +19,8 @@ = render Attachment::ShowComponent.new(attachment: attachment, truncate: true) - elsif blob.variable? && blob.content_type.in?(AUTHORIZED_IMAGE_TYPES) - = link_to image_url(blob.url), title: "#{champ.libelle} -- #{blob.filename}", data: { src: blob.url }, class: 'gallery-link' do + - blob_url = blob.content_type.in?(RARE_IMAGE_TYPES) ? attachment.variant(resize_to_limit: [2000, 2000]).processed.url : blob.url + = link_to image_url(blob_url), title: "#{champ.libelle} -- #{blob.filename}", data: { src: blob.url }, class: 'gallery-link' do .thumbnail = image_tag(attachment.variant(resize_to_limit: [400, 400]).processed.url, loading: :lazy) .fr-btn.fr-btn--tertiary.fr-btn--icon-left.fr-icon-eye{ role: :button } diff --git a/app/views/shared/champs/piece_justificative/_show.html.haml b/app/views/shared/champs/piece_justificative/_show.html.haml index b32f05595..1624f86e1 100644 --- a/app/views/shared/champs/piece_justificative/_show.html.haml +++ b/app/views/shared/champs/piece_justificative/_show.html.haml @@ -16,7 +16,8 @@ = 'Visualiser' - elsif blob.variable? && blob.content_type.in?(AUTHORIZED_IMAGE_TYPES) - = link_to image_url(blob.url), title: "#{champ.libelle} -- #{blob.filename}", data: { src: blob.url }, class: 'gallery-link' do + - blob_url = blob.content_type.in?(RARE_IMAGE_TYPES) ? attachment.variant(resize_to_limit: [2000, 2000]).processed.url : blob.url + = link_to image_url(blob_url), title: "#{champ.libelle} -- #{blob.filename}", data: { src: blob.url }, class: 'gallery-link' do .thumbnail = image_tag(attachment.variant(resize_to_limit: [400, 400]).processed.url, loading: :lazy) .fr-btn.fr-btn--tertiary.fr-btn--icon-left.fr-icon-eye{ role: :button } diff --git a/config/initializers/authorized_content_types.rb b/config/initializers/authorized_content_types.rb index e5af1c74f..eaa16fbd9 100644 --- a/config/initializers/authorized_content_types.rb +++ b/config/initializers/authorized_content_types.rb @@ -15,6 +15,10 @@ AUTHORIZED_IMAGE_TYPES = [ 'image/vnd.dwg' # multimedia x 137 auto desk ] +RARE_IMAGE_TYPES = [ + 'image/tiff' # multimedia x 3985 +] + AUTHORIZED_CONTENT_TYPES = AUTHORIZED_IMAGE_TYPES + AUTHORIZED_PDF_TYPES + [ # multimedia 'video/mp4', # multimedia x 2075 diff --git a/spec/fixtures/files/pencil.tiff b/spec/fixtures/files/pencil.tiff new file mode 100644 index 0000000000000000000000000000000000000000..67af5a81aa3db48f070524d1b52c588491b74861 GIT binary patch literal 15224 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 bn3?@sFux%Kd*|f9^ Date: Wed, 29 May 2024 10:54:38 +0200 Subject: [PATCH 3/6] refactor(gallery): add helper methods --- app/helpers/gallery_helper.rb | 21 +++++++++++++++++++ .../dossiers/pieces_jointes.html.haml | 11 +++++----- .../piece_justificative/_show.html.haml | 11 +++++----- 3 files changed, 31 insertions(+), 12 deletions(-) create mode 100644 app/helpers/gallery_helper.rb diff --git a/app/helpers/gallery_helper.rb b/app/helpers/gallery_helper.rb new file mode 100644 index 000000000..67068d480 --- /dev/null +++ b/app/helpers/gallery_helper.rb @@ -0,0 +1,21 @@ +module GalleryHelper + def displayable_pdf?(blob) + blob.previewable? && blob.content_type.in?(AUTHORIZED_PDF_TYPES) + end + + def displayable_image?(blob) + blob.variable? && blob.content_type.in?(AUTHORIZED_IMAGE_TYPES) + end + + def preview_url_for(attachment) + attachment.preview(resize_to_limit: [400, 400]).processed.url + end + + def variant_url_for(attachment) + attachment.variant(resize_to_limit: [400, 400]).processed.url + end + + def blob_url(attachment) + attachment.blob.content_type.in?(RARE_IMAGE_TYPES) ? attachment.variant(resize_to_limit: [2000, 2000]).processed.url : attachment.blob.url + end +end diff --git a/app/views/instructeurs/dossiers/pieces_jointes.html.haml b/app/views/instructeurs/dossiers/pieces_jointes.html.haml index eb67f850c..d770433d4 100644 --- a/app/views/instructeurs/dossiers/pieces_jointes.html.haml +++ b/app/views/instructeurs/dossiers/pieces_jointes.html.haml @@ -8,21 +8,20 @@ - champ.piece_justificative_file.with_all_variant_records.each do |attachment| .gallery-item - blob = attachment.blob - - if blob.previewable? && blob.content_type.in?(AUTHORIZED_PDF_TYPES) + - 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(attachment.preview(resize_to_limit: [400, 400]).processed.url, loading: :lazy) + = 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 blob.variable? && blob.content_type.in?(AUTHORIZED_IMAGE_TYPES) - - blob_url = blob.content_type.in?(RARE_IMAGE_TYPES) ? attachment.variant(resize_to_limit: [2000, 2000]).processed.url : blob.url - = link_to image_url(blob_url), title: "#{champ.libelle} -- #{blob.filename}", data: { src: blob.url }, class: 'gallery-link' do + - 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(attachment.variant(resize_to_limit: [400, 400]).processed.url, loading: :lazy) + = 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 diff --git a/app/views/shared/champs/piece_justificative/_show.html.haml b/app/views/shared/champs/piece_justificative/_show.html.haml index 1624f86e1..abb301872 100644 --- a/app/views/shared/champs/piece_justificative/_show.html.haml +++ b/app/views/shared/champs/piece_justificative/_show.html.haml @@ -8,18 +8,17 @@ - champ.piece_justificative_file.attachments.with_all_variant_records.each do |attachment| .gallery-item - blob = attachment.blob - - if blob.previewable? && blob.content_type.in?(AUTHORIZED_PDF_TYPES) + - 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(attachment.preview(resize_to_limit: [400, 400]).processed.url, loading: :lazy) + = image_tag(preview_url_for(attachment), loading: :lazy) .fr-btn.fr-btn--tertiary.fr-btn--icon-left.fr-icon-eye{ role: :button } = 'Visualiser' - - elsif blob.variable? && blob.content_type.in?(AUTHORIZED_IMAGE_TYPES) - - blob_url = blob.content_type.in?(RARE_IMAGE_TYPES) ? attachment.variant(resize_to_limit: [2000, 2000]).processed.url : blob.url - = link_to image_url(blob_url), title: "#{champ.libelle} -- #{blob.filename}", data: { src: blob.url }, class: 'gallery-link' do + - 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(attachment.variant(resize_to_limit: [400, 400]).processed.url, loading: :lazy) + = image_tag(variant_url_for(attachment), loading: :lazy) .fr-btn.fr-btn--tertiary.fr-btn--icon-left.fr-icon-eye{ role: :button } = 'Visualiser' - else From ffc0ddc446775bde5702a5932fa500dd75941340 Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Wed, 29 May 2024 11:15:40 +0200 Subject: [PATCH 4/6] chore(gallery): add activestorage error catching in front --- app/helpers/gallery_helper.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/helpers/gallery_helper.rb b/app/helpers/gallery_helper.rb index 67068d480..98f7ffc1e 100644 --- a/app/helpers/gallery_helper.rb +++ b/app/helpers/gallery_helper.rb @@ -9,13 +9,19 @@ module GalleryHelper def preview_url_for(attachment) attachment.preview(resize_to_limit: [400, 400]).processed.url + rescue ActiveStorage::Error + 'pdf-placeholder.png' end def variant_url_for(attachment) attachment.variant(resize_to_limit: [400, 400]).processed.url + rescue ActiveStorage::Error + 'apercu-indisponible.png' end def blob_url(attachment) attachment.blob.content_type.in?(RARE_IMAGE_TYPES) ? attachment.variant(resize_to_limit: [2000, 2000]).processed.url : attachment.blob.url + rescue ActiveStorage::Error + attachment.blob.url end end From f6e54a540bcaef229cb28c5bbfeb1236dbc6a1f4 Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Wed, 29 May 2024 16:08:23 +0200 Subject: [PATCH 5/6] chore(gallery): add activestorage error catching in job --- app/jobs/image_processor_job.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/app/jobs/image_processor_job.rb b/app/jobs/image_processor_job.rb index 798ba86a1..ee914a925 100644 --- a/app/jobs/image_processor_job.rb +++ b/app/jobs/image_processor_job.rb @@ -10,6 +10,10 @@ class ImageProcessorJob < ApplicationJob # (to avoid modifying the file while it is being scanned). retry_on FileNotScannedYetError, wait: :exponentially_longer, attempts: 10 + rescue_from ActiveStorage::PreviewError do + retry_or_discard + end + def perform(blob) return if blob.nil? raise FileNotScannedYetError if blob.virus_scanner.pending? @@ -58,4 +62,14 @@ class ImageProcessorJob < ApplicationJob end end end + + def retry_or_discard + if executions < max_attempts + retry_job wait: 5.minutes + end + end + + def max_attempts + 3 + end end From 48c092a74a3c339c307cf846690541de1a91d937 Mon Sep 17 00:00:00 2001 From: Eric Leroy-Terquem Date: Wed, 5 Jun 2024 11:56:29 +0200 Subject: [PATCH 6/6] test(gallery): test gallery helper --- .github/workflows/ci.yml | 3 +- spec/helpers/gallery_helper_spec.rb | 57 +++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 spec/helpers/gallery_helper_spec.rb diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 11e97ca81..89d52a61d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -81,7 +81,8 @@ jobs: - name: Install build dependancies # - fonts pickable by ImageMagick # - rust for YJIT support - run: sudo apt-get update && sudo apt-get install -y gsfonts rustc redis-server + # - poppler-utils for pdf previews + run: sudo apt-get update && sudo apt-get install -y gsfonts rustc redis-server poppler-utils - name: Setup the app runtime and dependencies uses: ./.github/actions/ci-setup-rails diff --git a/spec/helpers/gallery_helper_spec.rb b/spec/helpers/gallery_helper_spec.rb new file mode 100644 index 000000000..41469798c --- /dev/null +++ b/spec/helpers/gallery_helper_spec.rb @@ -0,0 +1,57 @@ +RSpec.describe GalleryHelper, type: :helper do + let(:procedure) { create(:procedure_with_dossiers) } + let(:type_de_champ_pj) { create(:type_de_champ_piece_justificative, stable_id: 3, libelle: 'Justificatif de domicile', procedure:) } + let(:champ_pj) { create(:champ_piece_justificative, type_de_champ: type_de_champ_pj) } + let(:blob_info) do + { + filename: file.original_filename, + byte_size: file.size, + checksum: Digest::SHA256.file(file.path), + content_type: file.content_type, + # we don't want to run virus scanner on this file + metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE } + } + end + let(:blob) do + blob = ActiveStorage::Blob.create_before_direct_upload!(**blob_info) + blob.upload(file) + blob + end + let(:attachment) { ActiveStorage::Attachment.create(name: "test", blob: blob, record: champ_pj) } + + describe ".variant_url_for" do + subject { variant_url_for(attachment) } + + context "when attachment can be represented with a variant" do + let(:file) { fixture_file_upload('spec/fixtures/files/logo_test_procedure.png', 'image/png') } + + it { expect { subject }.to change { ActiveStorage::VariantRecord.count }.by(1) } + it { is_expected.not_to eq("apercu-indisponible.png") } + end + + context "when attachment cannot be represented with a variant" do + let(:file) { fixture_file_upload('spec/fixtures/files/instructeurs-file.csv', 'text/csv') } + + it { expect { subject }.not_to change { ActiveStorage::VariantRecord.count } } + it { is_expected.to eq("apercu-indisponible.png") } + end + end + + describe ".preview_url_for" do + subject { preview_url_for(attachment) } + + context "when attachment can be represented with a preview" do + let(:file) { fixture_file_upload('spec/fixtures/files/RIB.pdf', 'application/pdf') } + + it { expect { subject }.to change { ActiveStorage::VariantRecord.count }.by(1) } + it { is_expected.not_to eq("pdf-placeholder.png") } + end + + context "when attachment cannot be represented with a preview" do + let(:file) { fixture_file_upload('spec/fixtures/files/instructeurs-file.csv', 'text/csv') } + + it { expect { subject }.not_to change { ActiveStorage::VariantRecord.count } } + it { is_expected.to eq("pdf-placeholder.png") } + end + end +end