Merge pull request #10918 from demarches-simplifiees/gallery_v2_add_origins
ETQ instructeur je vois dans la galerie les pjs issues des avis, annotations privées et justificatifs de décision
This commit is contained in:
commit
3f43e3433a
11 changed files with 221 additions and 22 deletions
|
@ -17,17 +17,35 @@ class Attachment::GalleryItemComponent < ApplicationComponent
|
|||
def gallery_demande? = @gallery_demande
|
||||
|
||||
def libelle
|
||||
from_dossier? ? attachment.record.libelle : 'Pièce jointe au message'
|
||||
if from_champ?
|
||||
attachment.record.libelle
|
||||
elsif from_messagerie?
|
||||
'Pièce jointe au message'
|
||||
elsif from_avis_externe?
|
||||
'Pièce jointe à l’avis'
|
||||
elsif from_justificatif_motivation?
|
||||
'Pièce jointe à la décision'
|
||||
end
|
||||
end
|
||||
|
||||
def origin
|
||||
case
|
||||
when from_dossier?
|
||||
when from_public_champ?
|
||||
'Dossier usager'
|
||||
when from_private_champ?
|
||||
'Annotation privée'
|
||||
when from_messagerie_expert?
|
||||
'Messagerie (expert)'
|
||||
when from_messagerie_instructeur?
|
||||
'Messagerie (instructeur)'
|
||||
when from_messagerie_usager?
|
||||
'Messagerie (usager)'
|
||||
when from_avis_externe_instructeur?
|
||||
'Avis externe (instructeur)'
|
||||
when from_avis_externe_expert?
|
||||
'Avis externe (expert)'
|
||||
when from_justificatif_motivation?
|
||||
'Justificatif de décision'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -52,7 +70,7 @@ class Attachment::GalleryItemComponent < ApplicationComponent
|
|||
end
|
||||
|
||||
def updated?
|
||||
from_dossier? && updated_at > attachment.record.dossier.depose_at
|
||||
from_public_champ? && updated_at > attachment.record.dossier.depose_at
|
||||
end
|
||||
|
||||
def updated_at
|
||||
|
@ -68,10 +86,18 @@ class Attachment::GalleryItemComponent < ApplicationComponent
|
|||
|
||||
private
|
||||
|
||||
def from_dossier?
|
||||
def from_champ?
|
||||
attachment.record.class.in?([Champs::PieceJustificativeChamp, Champs::TitreIdentiteChamp])
|
||||
end
|
||||
|
||||
def from_public_champ?
|
||||
from_champ? && !attachment.record.private?
|
||||
end
|
||||
|
||||
def from_private_champ?
|
||||
from_champ? && attachment.record.private?
|
||||
end
|
||||
|
||||
def from_messagerie?
|
||||
attachment.record.is_a?(Commentaire)
|
||||
end
|
||||
|
@ -80,7 +106,27 @@ class Attachment::GalleryItemComponent < ApplicationComponent
|
|||
from_messagerie? && attachment.record.instructeur.present?
|
||||
end
|
||||
|
||||
def from_messagerie_expert?
|
||||
from_messagerie? && attachment.record.expert.present?
|
||||
end
|
||||
|
||||
def from_messagerie_usager?
|
||||
from_messagerie? && attachment.record.instructeur.nil?
|
||||
from_messagerie? && attachment.record.instructeur.nil? && attachment.record.expert.nil?
|
||||
end
|
||||
|
||||
def from_avis_externe?
|
||||
attachment.record.is_a?(Avis)
|
||||
end
|
||||
|
||||
def from_avis_externe_instructeur?
|
||||
from_avis_externe? && attachment.name == 'introduction_file'
|
||||
end
|
||||
|
||||
def from_avis_externe_expert?
|
||||
from_avis_externe? && attachment.name == 'piece_justificative_file'
|
||||
end
|
||||
|
||||
def from_justificatif_motivation?
|
||||
attachment.name == 'justificatif_motivation'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
Visualiser
|
||||
- if !gallery_demande?
|
||||
.fr-text--sm.fr-mt-2v.fr-mb-1v
|
||||
= libelle.truncate(25)
|
||||
= libelle.truncate(30)
|
||||
= render Attachment::ShowComponent.new(attachment:, truncate: true, new_tab: gallery_demande?)
|
||||
- if !gallery_demande?
|
||||
.fr-mt-2v.fr-mb-2v{ class: badge_updated_class }
|
||||
|
@ -19,7 +19,7 @@
|
|||
= image_tag('apercu-indisponible.png')
|
||||
- if !gallery_demande?
|
||||
.fr-text--sm.fr-mt-2v.fr-mb-1v
|
||||
= libelle.truncate(25)
|
||||
= libelle.truncate(30)
|
||||
= render Attachment::ShowComponent.new(attachment:, truncate: true, new_tab: gallery_demande?)
|
||||
- if !gallery_demande?
|
||||
.fr-mt-2v.fr-mb-2v{ class: badge_updated_class }
|
||||
|
|
|
@ -104,7 +104,12 @@ module Experts
|
|||
updated_recently = @avis.updated_recently?
|
||||
if @avis.update(avis_params)
|
||||
flash.notice = 'Votre réponse est enregistrée.'
|
||||
@avis.dossier.update!(last_avis_updated_at: Time.zone.now)
|
||||
|
||||
timestamps = [:last_avis_updated_at, :updated_at]
|
||||
timestamps << :last_avis_piece_jointe_updated_at if @avis.piece_justificative_file.attached?
|
||||
|
||||
@avis.dossier.touch(*timestamps)
|
||||
|
||||
if !updated_recently
|
||||
@avis.dossier.followers_instructeurs
|
||||
.with_instant_expert_avis_email_notifications_enabled
|
||||
|
@ -162,7 +167,11 @@ module Experts
|
|||
@commentaire = CommentaireService.create(current_expert, avis.dossier, commentaire_params)
|
||||
|
||||
if @commentaire.errors.empty?
|
||||
@commentaire.dossier.update!(last_commentaire_updated_at: Time.zone.now)
|
||||
timestamps = [:last_commentaire_updated_at, :updated_at]
|
||||
timestamps << :last_commentaire_piece_jointe_updated_at if @commentaire.piece_jointe.attached?
|
||||
|
||||
@commentaire.dossier.touch(*timestamps)
|
||||
|
||||
flash.notice = "Message envoyé"
|
||||
redirect_to messagerie_expert_avis_path(avis.procedure, avis)
|
||||
else
|
||||
|
|
|
@ -513,11 +513,21 @@ module Instructeurs
|
|||
.commentaires
|
||||
.includes(piece_jointe_attachments: :blob)
|
||||
.map(&:piece_jointe)
|
||||
.map(&:attachments)
|
||||
.flatten
|
||||
.flat_map(&:attachments)
|
||||
.map(&:id)
|
||||
|
||||
champs_attachments_ids + commentaires_attachments_ids
|
||||
avis_attachments_ids = dossier
|
||||
.avis.flat_map { [_1.introduction_file, _1.piece_justificative_file] }
|
||||
.flat_map(&:attachments)
|
||||
.compact
|
||||
.map(&:id)
|
||||
|
||||
justificatif_motivation_id = dossier
|
||||
.justificatif_motivation
|
||||
&.attachment
|
||||
&.id
|
||||
|
||||
champs_attachments_ids + commentaires_attachments_ids + avis_attachments_ids + [justificatif_motivation_id]
|
||||
end
|
||||
@gallery_attachments = ActiveStorage::Attachment.where(id: gallery_attachments_ids)
|
||||
end
|
||||
|
|
|
@ -10,7 +10,7 @@ module BlobImageProcessorConcern
|
|||
end
|
||||
|
||||
def representation_required?
|
||||
from_champ? || from_messagerie? || logo? || from_action_text?
|
||||
from_champ? || from_messagerie? || logo? || from_action_text? || from_avis? || from_justificatif_motivation?
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -31,7 +31,15 @@ module BlobImageProcessorConcern
|
|||
attachments.any? { _1.record.class == ActionText::RichText }
|
||||
end
|
||||
|
||||
def from_avis?
|
||||
attachments.any? { _1.record.class == Avis }
|
||||
end
|
||||
|
||||
def watermark_required?
|
||||
attachments.any? { _1.record.class == Champs::TitreIdentiteChamp }
|
||||
end
|
||||
|
||||
def from_justificatif_motivation?
|
||||
attachments.any? { _1.name == 'justificatif_motivation' }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -378,7 +378,8 @@ class Dossier < ApplicationRecord
|
|||
' OR last_avis_updated_at > follows.avis_seen_at' \
|
||||
' OR last_commentaire_updated_at > follows.messagerie_seen_at' \
|
||||
' OR last_commentaire_piece_jointe_updated_at > follows.pieces_jointes_seen_at' \
|
||||
' OR last_champ_piece_jointe_updated_at > follows.pieces_jointes_seen_at')
|
||||
' OR last_champ_piece_jointe_updated_at > follows.pieces_jointes_seen_at' \
|
||||
' OR last_avis_piece_jointe_updated_at > follows.pieces_jointes_seen_at')
|
||||
.distinct
|
||||
end
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ class Instructeur < ApplicationRecord
|
|||
annotations_privees = dossier.last_champ_private_updated_at&.>(follow.annotations_privees_seen_at) || false
|
||||
avis_notif = dossier.last_avis_updated_at&.>(follow.avis_seen_at) || false
|
||||
messagerie = dossier.last_commentaire_updated_at&.>(follow.messagerie_seen_at) || false
|
||||
pieces_jointes = dossier.last_champ_piece_jointe_updated_at&.>(follow.pieces_jointes_seen_at) || dossier.last_commentaire_piece_jointe_updated_at&.>(follow.pieces_jointes_seen_at) || false
|
||||
pieces_jointes = dossier.last_champ_piece_jointe_updated_at&.>(follow.pieces_jointes_seen_at) || dossier.last_commentaire_piece_jointe_updated_at&.>(follow.pieces_jointes_seen_at) || dossier.last_avis_piece_jointe_updated_at&.>(follow.pieces_jointes_seen_at) || false
|
||||
|
||||
annotations_hash(demande, annotations_privees, avis_notif, messagerie, pieces_jointes)
|
||||
else
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddLastAvisPieceJointeUpdatedAt < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
add_column :dossiers, :last_avis_piece_jointe_updated_at, :datetime
|
||||
end
|
||||
end
|
|
@ -495,6 +495,7 @@ ActiveRecord::Schema[7.0].define(version: 2024_10_14_084333) do
|
|||
t.string "hidden_by_reason"
|
||||
t.datetime "hidden_by_user_at", precision: nil
|
||||
t.datetime "identity_updated_at", precision: nil
|
||||
t.datetime "last_avis_piece_jointe_updated_at"
|
||||
t.datetime "last_avis_updated_at", precision: nil
|
||||
t.datetime "last_champ_piece_jointe_updated_at"
|
||||
t.datetime "last_champ_private_updated_at", precision: nil
|
||||
|
|
|
@ -4,9 +4,10 @@ require 'rails_helper'
|
|||
|
||||
RSpec.describe Attachment::GalleryItemComponent, type: :component do
|
||||
let(:instructeur) { create(:instructeur) }
|
||||
let(:procedure) { create(:procedure, :published, types_de_champ_public:) }
|
||||
let(:procedure) { create(:procedure, :published, types_de_champ_public:, types_de_champ_private:) }
|
||||
let(:types_de_champ_public) { [{ type: :piece_justificative }] }
|
||||
let(:dossier) { create(:dossier, :with_populated_champs, :en_construction, procedure:) }
|
||||
let(:types_de_champ_private) { [{ type: :piece_justificative }] }
|
||||
let(:dossier) { create(:dossier, :with_populated_champs, :with_populated_annotations, :en_construction, procedure:) }
|
||||
let(:filename) { attachment.blob.filename.to_s }
|
||||
let(:gallery_demande) { false }
|
||||
let(:seen_at) { nil }
|
||||
|
@ -16,8 +17,10 @@ RSpec.describe Attachment::GalleryItemComponent, type: :component do
|
|||
|
||||
subject { render_inline(component).to_html }
|
||||
|
||||
context "when attachment is from a piece justificative champ" do
|
||||
let(:champ) { dossier.champs.first }
|
||||
context "when attachment is from a public piece justificative champ" do
|
||||
let(:champ) do
|
||||
dossier.champs.where(private: false).first
|
||||
end
|
||||
let(:libelle) { champ.libelle }
|
||||
let(:attachment) { champ.piece_justificative_file.attachments.first }
|
||||
|
||||
|
@ -56,6 +59,38 @@ RSpec.describe Attachment::GalleryItemComponent, type: :component do
|
|||
end
|
||||
end
|
||||
|
||||
context "when attachment is from a private piece justificative champ" do
|
||||
let(:annotation) do
|
||||
dossier.champs.where(private: true).first
|
||||
end
|
||||
let(:libelle) { annotation.libelle }
|
||||
let(:attachment) { annotation.piece_justificative_file.attachments.first }
|
||||
|
||||
# Correspond au cas standard où le blob est créé avant le dépôt du dossier
|
||||
before { dossier.touch(:depose_at) }
|
||||
|
||||
it "displays libelle, link, tag and renders title" do
|
||||
expect(subject).to have_text(libelle)
|
||||
expect(subject).to have_link(filename)
|
||||
expect(subject).to have_text('Annotation privée')
|
||||
expect(component.title).to eq("#{libelle} -- #{filename}")
|
||||
end
|
||||
|
||||
it "displays when gallery item has been added" do
|
||||
expect(subject).to have_text('Ajoutée le')
|
||||
expect(subject).not_to have_css('.highlighted')
|
||||
expect(subject).to have_text(component.helpers.try_format_datetime(attachment.record.created_at, format: :veryshort))
|
||||
end
|
||||
|
||||
context "when gallery item is in page Demande" do
|
||||
let(:gallery_demande) { true }
|
||||
|
||||
it "does not display libelle" do
|
||||
expect(subject).not_to have_text(libelle)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when attachment is from a commentaire" do
|
||||
let(:commentaire) { create(:commentaire, :with_file, dossier: dossier) }
|
||||
let(:attachment) { commentaire.piece_jointe.first }
|
||||
|
@ -100,5 +135,75 @@ RSpec.describe Attachment::GalleryItemComponent, type: :component do
|
|||
expect(subject).to have_text('Messagerie (instructeur)')
|
||||
end
|
||||
end
|
||||
|
||||
context 'from an expert' do
|
||||
let(:expert) { create(:expert) }
|
||||
before { commentaire.update!(expert:) }
|
||||
it "displays the right tag" do
|
||||
expect(subject).to have_text('Messagerie (expert)')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when attachment is from a justificatif motivation" do
|
||||
let(:fake_justificatif) { fixture_file_upload('spec/fixtures/files/piece_justificative_0.pdf', 'application/pdf') }
|
||||
let(:attachment) { dossier.justificatif_motivation.attachment }
|
||||
|
||||
before { dossier.update!(justificatif_motivation: fake_justificatif) }
|
||||
|
||||
it "displays a generic libelle, link, tag and renders title" do
|
||||
expect(subject).to have_text('Justificatif de décision')
|
||||
expect(subject).to have_link(filename)
|
||||
expect(subject).to have_text('Pièce jointe à la décision')
|
||||
expect(component.title).to eq("Pièce jointe à la décision -- #{filename}")
|
||||
end
|
||||
end
|
||||
|
||||
context "when attachment is from an avis" do
|
||||
context 'from an instructeur' do
|
||||
let(:avis) { create(:avis, :with_introduction, dossier: dossier) }
|
||||
let(:attachment) { avis.introduction_file.attachment }
|
||||
|
||||
it "displays a generic libelle, link, tag and renders title" do
|
||||
expect(subject).to have_text('Pièce jointe à l’avis')
|
||||
expect(subject).to have_link(filename)
|
||||
expect(subject).to have_text('Avis externe (instructeur)')
|
||||
expect(component.title).to eq("Pièce jointe à l’avis -- #{filename}")
|
||||
end
|
||||
|
||||
context "when instructeur has not seen it yet" do
|
||||
let(:seen_at) { now - 1.day }
|
||||
|
||||
before do
|
||||
attachment.blob.update(created_at: now)
|
||||
end
|
||||
|
||||
it 'displays datetime in the right style' do
|
||||
expect(subject).to have_css('.highlighted')
|
||||
end
|
||||
end
|
||||
|
||||
context "when instructeur has already seen it" do
|
||||
let!(:seen_at) { now }
|
||||
|
||||
before do
|
||||
freeze_time
|
||||
attachment.blob.touch(:created_at)
|
||||
end
|
||||
|
||||
it 'displays datetime in the right style' do
|
||||
expect(subject).not_to have_css('.highlighted')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'from an expert' do
|
||||
let(:avis) { create(:avis, :with_piece_justificative, dossier: dossier) }
|
||||
let(:attachment) { avis.piece_justificative_file.attachment }
|
||||
|
||||
it "displays the right tag" do
|
||||
expect(subject).to have_text('Avis externe (expert)')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1486,6 +1486,9 @@ describe Instructeurs::DossiersController, type: :controller do
|
|||
let(:logo_path) { 'spec/fixtures/files/logo_test_procedure.png' }
|
||||
let(:rib_path) { 'spec/fixtures/files/RIB.pdf' }
|
||||
let(:commentaire) { create(:commentaire, dossier: dossier) }
|
||||
let(:expert) { create(:expert) }
|
||||
let(:experts_procedure) { create(:experts_procedure, expert: expert, procedure: procedure) }
|
||||
let(:avis) { create(:avis, :with_answer, :with_piece_justificative, dossier: dossier, claimant: expert, experts_procedure: experts_procedure) }
|
||||
|
||||
before do
|
||||
dossier.champs.first.piece_justificative_file.attach(
|
||||
|
@ -1502,20 +1505,29 @@ describe Instructeurs::DossiersController, type: :controller do
|
|||
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
||||
)
|
||||
|
||||
avis.piece_justificative_file.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 'returns pieces jointes from champs and from messagerie' do
|
||||
it 'returns pieces jointes from champs, messagerie and avis' 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(:gallery_attachments).count).to eq 3
|
||||
expect(response.body).to include('Pièce jointe au message')
|
||||
expect(response.body).to include('Pièce jointe à l’avis')
|
||||
expect(assigns(:gallery_attachments).count).to eq 4
|
||||
expect(assigns(:gallery_attachments)).to all(be_a(ActiveStorage::Attachment))
|
||||
expect([Champs::PieceJustificativeChamp, Champs::TitreIdentiteChamp, Commentaire]).to include(*assigns(:gallery_attachments).map { _1.record.class })
|
||||
expect([Champs::PieceJustificativeChamp, Champs::TitreIdentiteChamp, Commentaire, Avis]).to include(*assigns(:gallery_attachments).map { _1.record.class })
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue