feat(message): replace message partial with MessageComponent
This commit is contained in:
parent
91879b89ce
commit
d2ab8b5593
22 changed files with 182 additions and 131 deletions
58
app/components/dossiers/message_component.rb
Normal file
58
app/components/dossiers/message_component.rb
Normal file
|
@ -0,0 +1,58 @@
|
|||
class Dossiers::MessageComponent < ApplicationComponent
|
||||
def initialize(commentaire:, connected_user:, messagerie_seen_at: nil, show_reply_button: false)
|
||||
@commentaire = commentaire
|
||||
@connected_user = connected_user
|
||||
@messagerie_seen_at = messagerie_seen_at
|
||||
@show_reply_button = show_reply_button
|
||||
end
|
||||
|
||||
attr_reader :commentaire, :connected_user, :messagerie_seen_at
|
||||
|
||||
private
|
||||
|
||||
def show_reply_button?
|
||||
@show_reply_button
|
||||
end
|
||||
|
||||
def highlight_if_unseen_class
|
||||
helpers.highlight_if_unseen_class(@messagerie_seen_at, commentaire.created_at)
|
||||
end
|
||||
|
||||
def icon_path
|
||||
if commentaire.sent_by_system?
|
||||
'icons/mail.svg'
|
||||
elsif commentaire.sent_by?(connected_user)
|
||||
'icons/account-circle.svg'
|
||||
else
|
||||
'icons/blue-person.svg'
|
||||
end
|
||||
end
|
||||
|
||||
def commentaire_issuer
|
||||
if commentaire.sent_by_system?
|
||||
t('.automatic_email')
|
||||
elsif commentaire.sent_by?(connected_user)
|
||||
t('.you')
|
||||
else
|
||||
commentaire.redacted_email
|
||||
end
|
||||
end
|
||||
|
||||
def commentaire_from_guest?
|
||||
commentaire.dossier.invites.map(&:email).include?(commentaire.email)
|
||||
end
|
||||
|
||||
def commentaire_date
|
||||
is_current_year = (commentaire.created_at.year == Time.zone.today.year)
|
||||
l(commentaire.created_at, format: is_current_year ? :message_date : :message_date_with_year)
|
||||
end
|
||||
|
||||
def commentaire_body
|
||||
if commentaire.discarded?
|
||||
t('.deleted_body')
|
||||
else
|
||||
body_formatted = commentaire.sent_by_system? ? commentaire.body : simple_format(commentaire.body)
|
||||
sanitize(body_formatted)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
en:
|
||||
reply: Reply
|
||||
guest: Guest
|
||||
delete_button: Delete this message
|
||||
confirm: Are you sure you want to delete this message ?
|
||||
automatic_email: Automatic email
|
||||
you: You
|
||||
deleted_body: Message deleted
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
fr:
|
||||
reply: Répondre
|
||||
guest: Invité
|
||||
delete_button: Supprimer le message
|
||||
confirm: Êtes-vous sûr de vouloir supprimer ce message ?
|
||||
automatic_email: Email automatique
|
||||
you: Vous
|
||||
deleted_body: Message supprimé
|
|
@ -1,14 +1,14 @@
|
|||
= render partial: 'shared/dossiers/messages/message_icon', locals: { commentaire: commentaire, connected_user: connected_user }
|
||||
= image_tag(icon_path, class: 'person-icon', alt: '')
|
||||
|
||||
.width-100
|
||||
%h2
|
||||
%span.mail
|
||||
= render partial: 'shared/dossiers/messages/message_issuer', locals: { commentaire: commentaire, connected_user: connected_user }
|
||||
- if commentaire_is_from_guest(commentaire)
|
||||
= commentaire_issuer
|
||||
- if commentaire_from_guest?
|
||||
%span.guest= t('.guest')
|
||||
%span.date{ class: highlight_if_unseen_class(messagerie_seen_at, commentaire.created_at) }
|
||||
= commentaire_date(commentaire)
|
||||
.rich-text= pretty_commentaire(commentaire)
|
||||
%span.date{ class: highlight_if_unseen_class }
|
||||
= commentaire_date
|
||||
.rich-text= commentaire_body
|
||||
|
||||
.message-extras.flex.justify-start
|
||||
- if commentaire.soft_deletable?(connected_user)
|
||||
|
@ -20,7 +20,7 @@
|
|||
.attachment-link
|
||||
= render partial: "shared/attachment/show", locals: { attachment: commentaire.piece_jointe.attachment }
|
||||
|
||||
- if show_reply_button
|
||||
- if show_reply_button?
|
||||
= button_tag type: 'button', class: 'button small message-answer-button', onclick: 'document.querySelector("#commentaire_body").focus()' do
|
||||
%span.icon.reply
|
||||
= t('.reply')
|
|
@ -12,20 +12,4 @@ module CommentaireHelper
|
|||
I18n.t('helpers.commentaire.reply_in_mailbox')
|
||||
end
|
||||
end
|
||||
|
||||
def commentaire_is_from_guest(commentaire)
|
||||
commentaire.dossier.invites.map(&:email).include?(commentaire.email)
|
||||
end
|
||||
|
||||
def commentaire_date(commentaire)
|
||||
is_current_year = (commentaire.created_at.year == Time.zone.today.year)
|
||||
template = is_current_year ? :message_date : :message_date_with_year
|
||||
I18n.l(commentaire.created_at, format: template)
|
||||
end
|
||||
|
||||
def pretty_commentaire(commentaire)
|
||||
return t('views.shared.commentaires.destroy.deleted_body') if commentaire.discarded?
|
||||
body_formatted = commentaire.sent_by_system? ? commentaire.body : simple_format(commentaire.body)
|
||||
sanitize(body_formatted)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
- if @commentaire.discarded?
|
||||
= turbo_stream.update @commentaire, partial: "shared/dossiers/messages/message", locals: { commentaire: @commentaire, connected_user: @commentaire.instructeur || @commentaire.expert, messagerie_seen_at: nil, show_reply_button: false }
|
||||
= turbo_stream.update @commentaire do
|
||||
= render Dossiers::MessageComponent.new(commentaire: @commentaire, connected_user: @commentaire.instructeur || @commentaire.expert)
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
%ul.messages-list
|
||||
- @dossier.commentaires.with_attached_piece_jointe.each do |commentaire|
|
||||
%li
|
||||
= render partial: "shared/dossiers/messages/message", locals: { commentaire: commentaire, connected_user: current_instructeur, messagerie_seen_at: nil, show_reply_button: false }
|
||||
= render Dossiers::MessageComponent.new(commentaire: commentaire, connected_user: current_instructeur)
|
||||
|
||||
%script{ type: "text/javascript" }
|
||||
window.print();
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
%ul.messages-list
|
||||
- dossier.commentaires.with_attached_piece_jointe.each do |commentaire|
|
||||
%li.message{ class: commentaire_is_from_me_class(commentaire, connected_user), id: dom_id(commentaire) }
|
||||
= render partial: "shared/dossiers/messages/message", locals: { commentaire: commentaire, connected_user: connected_user, messagerie_seen_at: messagerie_seen_at, show_reply_button: show_reply_button(commentaire, connected_user) }
|
||||
= render Dossiers::MessageComponent.new(commentaire: commentaire, connected_user: connected_user, messagerie_seen_at: messagerie_seen_at, show_reply_button: show_reply_button(commentaire, connected_user))
|
||||
|
||||
- if dossier.messagerie_available?
|
||||
= render partial: "shared/dossiers/messages/form", locals: { commentaire: new_commentaire, form_url: form_url, dossier: dossier }
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
- if commentaire.sent_by_system?
|
||||
= image_tag('icons/mail.svg', class: 'person-icon', alt: '')
|
||||
- elsif commentaire.sent_by?(connected_user)
|
||||
= image_tag('icons/account-circle.svg', class: 'person-icon', alt: '')
|
||||
- else
|
||||
= image_tag('icons/blue-person.svg', class: 'person-icon', alt: '')
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
- if commentaire.sent_by_system?
|
||||
= t('views.shared.dossiers.messages.message_issuer.automatic_email')
|
||||
- elsif commentaire.sent_by?(connected_user)
|
||||
= t('views.shared.dossiers.messages.message_issuer.you')
|
||||
- else
|
||||
= commentaire.redacted_email
|
|
@ -4,7 +4,7 @@
|
|||
%h3.tab-title= t('views.users.dossiers.show.latest_message.latest_message')
|
||||
|
||||
.message.inverted-background
|
||||
= render partial: "shared/dossiers/messages/message", locals: { commentaire: latest_message, connected_user: current_user, messagerie_seen_at: nil, show_reply_button: false }
|
||||
= render Dossiers::MessageComponent.new(commentaire: latest_message, connected_user: current_user)
|
||||
|
||||
= link_to messagerie_dossier_url(dossier, anchor: 'new_commentaire'), class: 'button send' do
|
||||
%span.icon.reply
|
||||
|
|
|
@ -127,9 +127,6 @@ en:
|
|||
submit_dossier: Submit the file
|
||||
save_changes: Save the changes of the file
|
||||
messages:
|
||||
message_issuer:
|
||||
automatic_email: "Automatic email"
|
||||
you: "You"
|
||||
form:
|
||||
send_message: "Send message"
|
||||
attachment_size: "(attachment size max : 20 Mo)"
|
||||
|
|
|
@ -122,9 +122,6 @@ fr:
|
|||
submit_dossier: Déposer le dossier
|
||||
save_changes: Enregistrer les modifications du dossier
|
||||
messages:
|
||||
message_issuer:
|
||||
automatic_email: "Email automatique"
|
||||
you: "Vous"
|
||||
form:
|
||||
send_message: "Envoyer le message"
|
||||
attachment_size: "(taille max : 20 Mo)"
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
en:
|
||||
instructeurs:
|
||||
commentaires_controller:
|
||||
alert_already_discarded: "Can not destroy message: it was already destroyed"
|
||||
procedure:
|
||||
archive_pending_html: Archive creation pending<br>(requested %{created_period} ago)
|
||||
archive_ready_html: Download archive<br>(requested %{generated_period} ago)
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
fr:
|
||||
instructeurs:
|
||||
commentaires_controller:
|
||||
alert_already_discarded: Ce message a déjà été supprimé
|
||||
procedure:
|
||||
archive_pending_html: Archive en cours de création<br>(demandée il y a %{created_period})
|
||||
archive_ready_html: Télécharger l’archive<br>(demandée il y a %{generated_period})
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
en:
|
||||
shared:
|
||||
dossiers:
|
||||
messages:
|
||||
message:
|
||||
reply: Reply
|
||||
guest: Guest
|
||||
delete_button: Delete this message
|
||||
confirm: Are you sure you want to delete this message ?
|
|
@ -1,9 +0,0 @@
|
|||
fr:
|
||||
shared:
|
||||
dossiers:
|
||||
messages:
|
||||
message:
|
||||
reply: Répondre
|
||||
guest: Invité
|
||||
delete_button: Supprimer le message
|
||||
confirm: Êtes-vous sûr de vouloir supprimer ce message ?
|
|
@ -20,6 +20,3 @@ en:
|
|||
already_user: "I already have an account"
|
||||
create: 'Create an account'
|
||||
signin: 'Sign in'
|
||||
commentaires:
|
||||
destroy:
|
||||
deleted_body: Message deleted
|
||||
|
|
|
@ -20,6 +20,3 @@ fr:
|
|||
already_user: 'J’ai déjà un compte'
|
||||
create: 'Créer un compte'
|
||||
signin: 'Connexion'
|
||||
commentaires:
|
||||
destroy:
|
||||
deleted_body: Message supprimé
|
||||
|
|
|
@ -1,21 +1,28 @@
|
|||
describe 'shared/dossiers/messages/message.html.haml', type: :view do
|
||||
before { view.extend DossierHelper }
|
||||
|
||||
subject { render 'shared/dossiers/messages/message.html.haml', commentaire: commentaire, messagerie_seen_at: seen_at, connected_user: dossier.user, show_reply_button: true }
|
||||
|
||||
RSpec.describe Dossiers::MessageComponent, type: :component do
|
||||
let(:component) do
|
||||
described_class.new(
|
||||
commentaire: commentaire,
|
||||
connected_user: connected_user,
|
||||
messagerie_seen_at: seen_at,
|
||||
show_reply_button: true
|
||||
)
|
||||
end
|
||||
let(:dossier) { create(:dossier, :en_construction) }
|
||||
let(:commentaire) { create(:commentaire, dossier: dossier) }
|
||||
let(:connected_user) { dossier.user }
|
||||
let(:seen_at) { commentaire.created_at + 1.hour }
|
||||
|
||||
subject { render_inline(component).to_html }
|
||||
|
||||
it { is_expected.to have_button("Répondre") }
|
||||
|
||||
context "with a seen_at after commentaire created_at" do
|
||||
context 'with a seen_at after commentaire created_at' do
|
||||
let(:seen_at) { commentaire.created_at + 1.hour }
|
||||
|
||||
it { is_expected.not_to have_css(".highlighted") }
|
||||
end
|
||||
|
||||
context "with a seen_at after commentaire created_at" do
|
||||
context 'with a seen_at after commentaire created_at' do
|
||||
let(:seen_at) { commentaire.created_at - 1.hour }
|
||||
|
||||
it { is_expected.to have_css(".highlighted") }
|
||||
|
@ -51,8 +58,8 @@ describe 'shared/dossiers/messages/message.html.haml', type: :view do
|
|||
let(:instructeur) { create(:instructeur) }
|
||||
let(:procedure) { create(:procedure) }
|
||||
let(:dossier) { create(:dossier, :en_construction, commentaires: [commentaire], procedure: procedure) }
|
||||
subject { render 'shared/dossiers/messages/message.html.haml', commentaire: commentaire, messagerie_seen_at: seen_at, connected_user: instructeur, show_reply_button: true }
|
||||
let(:form_url) { instructeur_commentaire_path(commentaire.dossier.procedure, commentaire.dossier, commentaire) }
|
||||
let(:connected_user) { instructeur }
|
||||
let(:form_url) { component.helpers.instructeur_commentaire_path(commentaire.dossier.procedure, commentaire.dossier, commentaire) }
|
||||
|
||||
context 'on a procedure where commentaire had been written by connected instructeur' do
|
||||
let(:commentaire) { create(:commentaire, instructeur: instructeur, body: 'Second message') }
|
||||
|
@ -64,7 +71,7 @@ describe 'shared/dossiers/messages/message.html.haml', type: :view do
|
|||
let(:commentaire) { create(:commentaire, instructeur: instructeur, body: 'Second message', discarded_at: 2.days.ago) }
|
||||
|
||||
it { is_expected.not_to have_selector("form[action=\"#{form_url}\"]") }
|
||||
it { is_expected.not_to have_selector(".rich-text", text: I18n.t(t('views.shared.commentaires.destroy.deleted_body'))) }
|
||||
it { is_expected.to have_selector(".rich-text", text: component.t('.deleted_body')) }
|
||||
end
|
||||
|
||||
context 'on a procedure where commentaire had been written by connected an user' do
|
||||
|
@ -86,4 +93,50 @@ describe 'shared/dossiers/messages/message.html.haml', type: :view do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#commentaire_from_guest?' do
|
||||
let!(:guest) { create(:invite, dossier: dossier) }
|
||||
|
||||
subject { component.send(:commentaire_from_guest?) }
|
||||
|
||||
context 'when the commentaire sender is not a guest' do
|
||||
let(:commentaire) { create(:commentaire, dossier: dossier, email: "michel@pref.fr") }
|
||||
it { is_expected.to be false }
|
||||
end
|
||||
|
||||
context 'when the commentaire sender is a guest on this dossier' do
|
||||
let(:commentaire) { create(:commentaire, dossier: dossier, email: guest.email) }
|
||||
it { is_expected.to be true }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#commentaire_date' do
|
||||
let(:present_date) { Time.zone.local(2018, 9, 2, 10, 5, 0) }
|
||||
let(:creation_date) { present_date }
|
||||
let(:commentaire) do
|
||||
Timecop.freeze(creation_date) { create(:commentaire, email: "michel@pref.fr") }
|
||||
end
|
||||
|
||||
subject do
|
||||
Timecop.freeze(present_date) { component.send(:commentaire_date) }
|
||||
end
|
||||
|
||||
it 'doesn’t include the creation year' do
|
||||
expect(subject).to eq 'le 2 septembre à 10 h 05'
|
||||
end
|
||||
|
||||
context 'when displaying a commentaire created on a previous year' do
|
||||
let(:creation_date) { present_date.prev_year }
|
||||
it 'includes the creation year' do
|
||||
expect(subject).to eq 'le 2 septembre 2017 à 10 h 05'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when formatting the first day of the month' do
|
||||
let(:present_date) { Time.zone.local(2018, 9, 1, 10, 5, 0) }
|
||||
it 'includes the ordinal' do
|
||||
expect(subject).to eq 'le 1er septembre à 10 h 05'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,31 @@
|
|||
class Dossiers::MessageComponentPreview < ViewComponent::Preview
|
||||
def with_default_commentaire
|
||||
render Dossiers::MessageComponent.new(commentaire: commentaire, connected_user: user)
|
||||
end
|
||||
|
||||
def with_discarded_commentaire
|
||||
render Dossiers::MessageComponent.new(commentaire: discarded_commentaire, connected_user: user)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def user
|
||||
User.new email: "usager@example.com", locale: I18n.locale
|
||||
end
|
||||
|
||||
def commentaire
|
||||
Commentaire.new body: 'Hello world!', email: user.email, dossier: dossier, created_at: 2.days.ago
|
||||
end
|
||||
|
||||
def discarded_commentaire
|
||||
Commentaire.new body: 'Hello world!', email: user.email, dossier: dossier, created_at: 2.days.ago, discarded_at: 1.day.ago
|
||||
end
|
||||
|
||||
def dossier
|
||||
Dossier.new(id: 47882, state: :en_instruction, procedure: procedure, user: user)
|
||||
end
|
||||
|
||||
def procedure
|
||||
Procedure.new id: 1234, libelle: 'Dotation d’Équipement des Territoires Ruraux - Exercice 2019'
|
||||
end
|
||||
end
|
|
@ -28,51 +28,4 @@ RSpec.describe CommentaireHelper, type: :helper do
|
|||
it { is_expected.to include('Répondre') }
|
||||
end
|
||||
end
|
||||
|
||||
describe '.commentaire_is_from_guest' do
|
||||
let(:dossier) { create(:dossier, :en_instruction) }
|
||||
let!(:guest) { create(:invite, dossier: dossier) }
|
||||
|
||||
subject { commentaire_is_from_guest(commentaire) }
|
||||
|
||||
context 'when the commentaire sender is not a guest' do
|
||||
let(:commentaire) { create(:commentaire, dossier: dossier, email: "michel@pref.fr") }
|
||||
it { is_expected.to be false }
|
||||
end
|
||||
|
||||
context 'when the commentaire sender is a guest on this dossier' do
|
||||
let(:commentaire) { create(:commentaire, dossier: dossier, email: guest.email) }
|
||||
it { is_expected.to be true }
|
||||
end
|
||||
end
|
||||
|
||||
describe '.commentaire_date' do
|
||||
let(:present_date) { Time.zone.local(2018, 9, 2, 10, 5, 0) }
|
||||
let(:creation_date) { present_date }
|
||||
let(:commentaire) do
|
||||
Timecop.freeze(creation_date) { create(:commentaire, email: "michel@pref.fr") }
|
||||
end
|
||||
|
||||
subject do
|
||||
Timecop.freeze(present_date) { commentaire_date(commentaire) }
|
||||
end
|
||||
|
||||
it 'doesn’t include the creation year' do
|
||||
expect(subject).to eq 'le 2 septembre à 10 h 05'
|
||||
end
|
||||
|
||||
context 'when displaying a commentaire created on a previous year' do
|
||||
let(:creation_date) { present_date.prev_year }
|
||||
it 'includes the creation year' do
|
||||
expect(subject).to eq 'le 2 septembre 2017 à 10 h 05'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when formatting the first day of the month' do
|
||||
let(:present_date) { Time.zone.local(2018, 9, 1, 10, 5, 0) }
|
||||
it 'includes the ordinal' do
|
||||
expect(subject).to eq 'le 1er septembre à 10 h 05'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue