Skip to content

Commit

Permalink
Merge pull request demarches-simplifiees#9664 from adullact/feature-o…
Browse files Browse the repository at this point in the history
…uidou/admin_creation_delegation_follow_commentaire

ETQ gestionnaire, j'ai un suivi des messages au sein de mes groupes
  • Loading branch information
colinux authored Jan 31, 2024
2 parents 6aabf38 + f3cba93 commit 3ea718a
Show file tree
Hide file tree
Showing 35 changed files with 412 additions and 24 deletions.
12 changes: 12 additions & 0 deletions app/assets/stylesheets/groupe_gestionnaire_cards.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.fr-groupe_gestionnaire_cards {
.fr-h6 {
padding-left: 20px;
padding-right: 20px;
position: relative;
}

.notifications {
top: 3px;
right: 3px;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
class GroupeGestionnaire::Card::AdministrateursComponent < ApplicationComponent
def initialize(groupe_gestionnaire:, path:)
def initialize(groupe_gestionnaire:, path:, is_gestionnaire: true)
@groupe_gestionnaire = groupe_gestionnaire
@path = path
@is_gestionnaire = is_gestionnaire
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
%p.fr-tag= @groupe_gestionnaire.administrateurs.size
%h3.fr-h6
= t('.title', count: @groupe_gestionnaire.administrateurs.size)
%p.fr-btn.fr-btn--tertiary= t('views.shared.actions.edit')
%p.fr-btn.fr-btn--tertiary= @is_gestionnaire ? t('views.shared.actions.edit') : t('views.shared.actions.see')
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
class GroupeGestionnaire::Card::CommentairesComponent < ApplicationComponent
def initialize(groupe_gestionnaire:, administrateur:, path:)
def initialize(groupe_gestionnaire:, administrateur:, path:, unread_commentaires: nil)
@groupe_gestionnaire = groupe_gestionnaire
@administrateur = administrateur
@path = path
@unread_commentaires = unread_commentaires
end

def number_commentaires
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
.fr-col-6.fr-col-md-4.fr-col-lg-3
= link_to @path, id: 'administrateurs', class: 'fr-tile fr-enlarge-link' do
= link_to @path, id: 'commentaires', class: 'fr-tile fr-enlarge-link' do
.fr-tile__body.flex.column.align-center.justify-between
%p.fr-badge.fr-badge--success Validé
%div
.line-count.fr-my-1w
%p.fr-tag= number_commentaires
%h3.fr-h6
- if @unread_commentaires
%span.notifications{ 'aria-label': 'notifications' }
= t('.title', count: number_commentaires)
%p.fr-btn.fr-btn--tertiary= t('views.shared.actions.see')
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
class GroupeGestionnaire::Card::GestionnairesComponent < ApplicationComponent
def initialize(groupe_gestionnaire:, path:)
def initialize(groupe_gestionnaire:, path:, is_gestionnaire: true)
@groupe_gestionnaire = groupe_gestionnaire
@path = path
@is_gestionnaire = is_gestionnaire
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
%p.fr-tag= @groupe_gestionnaire.gestionnaires.size
%h3.fr-h6
= t('.title', count: @groupe_gestionnaire.gestionnaires.size)
%p.fr-btn.fr-btn--tertiary= t('views.shared.actions.edit')
%p.fr-btn.fr-btn--tertiary= @is_gestionnaire ? t('views.shared.actions.edit') : t('views.shared.actions.see')
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
class GroupeGestionnaire::GroupeGestionnaireCommentaires::CommentaireComponent < ApplicationComponent
include ApplicationHelper

def initialize(commentaire:, connected_user:, is_gestionnaire: true)
def initialize(commentaire:, connected_user:, commentaire_seen_at: nil, is_gestionnaire: true)
@commentaire = commentaire
@connected_user = connected_user
@is_gestionnaire = is_gestionnaire
@groupe_gestionnaire = commentaire.groupe_gestionnaire
@commentaire_seen_at = commentaire_seen_at
end

private

def highlight_if_unseen_class
if highlight?
'highlighted'
end
end

def scroll_to_target
if highlight?
{ scroll_to_target: 'to' }
end
end

def commentaire_issuer
if @commentaire.sent_by?(@connected_user)
t('.you')
Expand All @@ -22,4 +35,8 @@ 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 highlight?
@commentaire.persisted? && (@commentaire_seen_at.nil? || @commentaire_seen_at < @commentaire.created_at)
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
%span.mail
= commentaire_issuer

%span.date{ class: ["fr-text--xs", "fr-text-mention--grey", "font-weight-normal"] }
%span.date{ class: ["fr-text--xs", "fr-text-mention--grey", "font-weight-normal", highlight_if_unseen_class], data: scroll_to_target }
= commentaire_date
.rich-text
- if @commentaire.discarded?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,9 @@ def see_button
gestionnaire_groupe_gestionnaire_commentaire_path(@groupe_gestionnaire, @commentaire),
class: 'button'
end

def highlight?
commentaire_seen_at = current_gestionnaire.commentaire_seen_at(@groupe_gestionnaire, @commentaire.sender)
commentaire_seen_at.nil? || commentaire_seen_at < @commentaire.created_at
end
end
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
%tr{ id: dom_id(@commentaire) }
%td= email
%td
= email
- if highlight?
%span.notifications{ 'aria-label': 'notifications' }
%td= created_at
%td= see_button
4 changes: 2 additions & 2 deletions app/controllers/administrateurs/activate_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ def create
reset_password_token: update_administrateur_params[:reset_password_token]
})

if user&.administrateur&.errors&.empty?
if user&.errors&.empty?
sign_in(user, scope: :user)

flash.notice = "Mot de passe enregistré"
redirect_to admin_procedures_path
else
flash.alert = user.administrateur.errors.full_messages
flash.alert = user.errors.full_messages
redirect_to admin_activate_path(token: update_administrateur_params[:reset_password_token])
end
end
Expand Down
52 changes: 52 additions & 0 deletions app/controllers/gestionnaires/activate_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
class Gestionnaires::ActivateController < ApplicationController
include TrustedDeviceConcern

def new
@token = params[:token]

user = User.with_reset_password_token(@token)
@gestionnaire = user&.gestionnaire

if @gestionnaire
# the gestionnaire activates its account from an email
trust_device(Time.zone.now)
else
flash.alert = "Le lien de validation de gestionnaire a expiré, #{helpers.contact_link('contactez-nous', tags: 'lien expiré')} pour obtenir un nouveau lien."
redirect_to root_path
end
end

def create
password = update_gestionnaire_params[:password]

user = User.reset_password_by_token({
password: password,
password_confirmation: password,
reset_password_token: update_gestionnaire_params[:reset_password_token]
})

if user&.errors&.empty?
sign_in(user, scope: :user)

flash.notice = "Mot de passe enregistré"
redirect_to gestionnaire_groupe_gestionnaires_path
else
flash.alert = user.errors.full_messages
redirect_to gestionnaires_activate_path(token: update_gestionnaire_params[:reset_password_token])
end
end

private

def update_gestionnaire_params
params.require(:gestionnaire).permit(:reset_password_token, :password)
end

def try_to_authenticate(klass, email, password)
resource = klass.find_for_database_authentication(email: email)

if resource&.valid_password?(password)
sign_in resource
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ def index
end

def show
@commentaire_seen_at = current_gestionnaire.commentaire_seen_at(@groupe_gestionnaire, @last_commentaire.sender)
@commentaire = CommentaireGroupeGestionnaire.new
current_gestionnaire.mark_commentaire_as_seen(@groupe_gestionnaire, @last_commentaire.sender)
end

def create
Expand All @@ -30,7 +32,6 @@ def destroy
else
flash.alert = t('.alert_acl')
end
# redirect_to gestionnaire_groupe_gestionnaire_commentaire_path(@groupe_gestionnaire, @last_commentaire)
rescue Discard::RecordNotDiscarded
flash.alert = t('.alert_already_discarded')
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ def index
end

def show
@unread_commentaires = current_gestionnaire.unread_commentaires?(@groupe_gestionnaire)
end

def edit
Expand Down
7 changes: 7 additions & 0 deletions app/models/follow_commentaire_groupe_gestionnaire.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class FollowCommentaireGroupeGestionnaire < ApplicationRecord
belongs_to :gestionnaire
belongs_to :groupe_gestionnaire
belongs_to :sender, polymorphic: true, optional: true

validates :gestionnaire_id, uniqueness: { scope: [:groupe_gestionnaire_id, :sender_id, :sender_type, :unfollowed_at] }
end
24 changes: 24 additions & 0 deletions app/models/gestionnaire.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ class Gestionnaire < ApplicationRecord
include UserFindByConcern
has_and_belongs_to_many :groupe_gestionnaires
has_many :commentaire_groupe_gestionnaires
has_many :follow_commentaire_groupe_gestionnaires

belongs_to :user

Expand Down Expand Up @@ -33,4 +34,27 @@ def registration_state
'Expiré'
end
end

def unread_commentaires?(groupe_gestionnaire)
CommentaireGroupeGestionnaire
.joins(:groupe_gestionnaire)
.joins("LEFT JOIN follow_commentaire_groupe_gestionnaires ON follow_commentaire_groupe_gestionnaires.groupe_gestionnaire_id = commentaire_groupe_gestionnaires.groupe_gestionnaire_id AND follow_commentaire_groupe_gestionnaires.sender_id = commentaire_groupe_gestionnaires.sender_id AND follow_commentaire_groupe_gestionnaires.sender_type = commentaire_groupe_gestionnaires.sender_type AND follow_commentaire_groupe_gestionnaires.gestionnaire_id = #{self.id}")
.where(groupe_gestionnaire: groupe_gestionnaire)
.where('follow_commentaire_groupe_gestionnaires.commentaire_seen_at IS NULL OR follow_commentaire_groupe_gestionnaires.commentaire_seen_at < commentaire_groupe_gestionnaires.created_at')
.exists?
end

def commentaire_seen_at(groupe_gestionnaire, sender)
FollowCommentaireGroupeGestionnaire
.where(gestionnaire: self, groupe_gestionnaire:, sender:)
.order(id: :desc)
.last
&.commentaire_seen_at
end

def mark_commentaire_as_seen(groupe_gestionnaire, sender)
FollowCommentaireGroupeGestionnaire
.where(gestionnaire: self, groupe_gestionnaire: groupe_gestionnaire, sender: sender, unfollowed_at: nil)
.first_or_initialize.update(commentaire_seen_at: Time.zone.now)
end
end
1 change: 1 addition & 0 deletions app/models/groupe_gestionnaire.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
class GroupeGestionnaire < ApplicationRecord
has_many :administrateurs
has_many :commentaire_groupe_gestionnaires
has_many :follow_commentaire_groupe_gestionnaires
has_and_belongs_to_many :gestionnaires

has_ancestry
Expand Down
6 changes: 3 additions & 3 deletions app/views/administrateurs/groupe_gestionnaire/show.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
metadatas: true }

.fr-container
%h2= "Gestion du groupe gestionnaire #{@groupe_gestionnaire.id}"
%h2= "Gestion du groupe gestionnaire \"#{@groupe_gestionnaire.name}\""
.fr-grid-row.fr-grid-row--gutters.fr-mb-5w
= render GroupeGestionnaire::Card::GestionnairesComponent.new(groupe_gestionnaire: @groupe_gestionnaire, path: admin_groupe_gestionnaire_gestionnaires_path)
= render GroupeGestionnaire::Card::AdministrateursComponent.new(groupe_gestionnaire: @groupe_gestionnaire, path: admin_groupe_gestionnaire_administrateurs_path)
= render GroupeGestionnaire::Card::GestionnairesComponent.new(groupe_gestionnaire: @groupe_gestionnaire, path: admin_groupe_gestionnaire_gestionnaires_path, is_gestionnaire: false)
= render GroupeGestionnaire::Card::AdministrateursComponent.new(groupe_gestionnaire: @groupe_gestionnaire, path: admin_groupe_gestionnaire_administrateurs_path, is_gestionnaire: false)
= render GroupeGestionnaire::Card::CommentairesComponent.new(groupe_gestionnaire: @groupe_gestionnaire, administrateur: current_administrateur, path: admin_groupe_gestionnaire_commentaires_path)
26 changes: 26 additions & 0 deletions app/views/gestionnaires/activate/new.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
- content_for(:title, t('.title'))

- content_for :footer do
= render partial: "root/footer"

.fr-container.fr-my-5w
.fr-grid-row.fr-grid-row--center
.fr-col-lg-6
= form_for @gestionnaire, url: { controller: 'gestionnaires/activate', action: :create } do |f|
= f.hidden_field :reset_password_token, value: @token

%fieldset.fr-mb-0.fr-fieldset{ aria: { labelledby: 'edit-password-legend' } }
%legend.fr-fieldset__legend#edit-password-legend
%h1.fr-h2= t('.title')

.fr-fieldset__element
= render Dsfr::InputComponent.new(form: f, attribute: :email, opts: { disabled: true })

.fr-fieldset__element
= render Dsfr::InputComponent.new(form: f, attribute: :password, input_type: :password_field,
opts: { autofocus: 'true', autocomplete: 'new-password', data: { controller: 'turbo-input', turbo_input_url_value: show_password_complexity_path }})

#password_complexity
= render PasswordComplexityComponent.new

= f.submit t('.continue'), id: 'submit-password', class: "fr-btn fr-btn--lg fr-mt-2w", data: { disable_with: t('views.users.passwords.edit.submit_loading') }
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@
%ul.messages-list{ data: { controller: 'scroll-to' } }
- @groupe_gestionnaire.commentaire_groupe_gestionnaires.where(sender_id: @last_commentaire.sender_id, sender_type: @last_commentaire.sender_type).each do |commentaire|
%li.message{ class: commentaire_is_from_me_class(commentaire, current_gestionnaire), id: dom_id(commentaire) }
= render(GroupeGestionnaire::GroupeGestionnaireCommentaires::CommentaireComponent.new(commentaire: commentaire, connected_user: current_gestionnaire))
= render(GroupeGestionnaire::GroupeGestionnaireCommentaires::CommentaireComponent.new(commentaire: commentaire, connected_user: current_gestionnaire, commentaire_seen_at: @commentaire_seen_at))
- if @last_commentaire.sender
= render partial: "shared/groupe_gestionnaires/commentaires/form", locals: { commentaire: @commentaire, form_url: gestionnaire_groupe_gestionnaire_commentaires_path(@groupe_gestionnaire) }
6 changes: 3 additions & 3 deletions app/views/gestionnaires/groupe_gestionnaires/show.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@
= t('views.gestionnaires.groupe_gestionnaires.delete')

.fr-container
%h2= "Gestion du groupe gestionnaire #{@groupe_gestionnaire.id}"
%h2= "Gestion du groupe gestionnaire \"#{@groupe_gestionnaire.name}\""
- if @groupe_gestionnaire.groupe_gestionnaire_id.present?
%p
groupe parent :
%a{ href: gestionnaire_groupe_gestionnaire_path(@groupe_gestionnaire.groupe_gestionnaire) }= @groupe_gestionnaire.groupe_gestionnaire.name
.fr-grid-row.fr-grid-row--gutters.fr-mb-5w
.fr-grid-row.fr-grid-row--gutters.fr-mb-5w.fr-groupe_gestionnaire_cards
= render GroupeGestionnaire::Card::GestionnairesComponent.new(groupe_gestionnaire: @groupe_gestionnaire, path: gestionnaire_groupe_gestionnaire_gestionnaires_path(@groupe_gestionnaire))
= render GroupeGestionnaire::Card::AdministrateursComponent.new(groupe_gestionnaire: @groupe_gestionnaire, path: gestionnaire_groupe_gestionnaire_administrateurs_path(@groupe_gestionnaire))
= render GroupeGestionnaire::Card::ChildrenComponent.new(groupe_gestionnaire: @groupe_gestionnaire, path: gestionnaire_groupe_gestionnaire_children_path(@groupe_gestionnaire))
= render GroupeGestionnaire::Card::CommentairesComponent.new(groupe_gestionnaire: @groupe_gestionnaire, administrateur: nil, path: gestionnaire_groupe_gestionnaire_commentaires_path(@groupe_gestionnaire))
= render GroupeGestionnaire::Card::CommentairesComponent.new(groupe_gestionnaire: @groupe_gestionnaire, administrateur: nil, path: gestionnaire_groupe_gestionnaire_commentaires_path(@groupe_gestionnaire), unread_commentaires: @unread_commentaires)

2 changes: 1 addition & 1 deletion app/views/user_mailer/invite_gestionnaire.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@

%p
Votre compte a été créé pour l'adresse email #{@user.email}. Pour l’activer, nous vous invitons à cliquer sur le lien suivant : 
= link_to(users_activate_url(token: @reset_password_token), users_activate_url(token: @reset_password_token))
= link_to(gestionnaires_activate_url(token: @reset_password_token), gestionnaires_activate_url(token: @reset_password_token))

= render partial: "layouts/mailers/signature"
5 changes: 5 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,11 @@ en:
updated_at: updated at
closed_at: closed at
auto_archive_on: will close at
gestionnaires:
activate:
new:
title: Pick a password
continue: Continue
users:
dossiers:
test_procedure: "This file is submitted on a test procedure. Any modification of the procedure by the administrator (addition of a field, publication of the procedure, etc.) will result in the removal of the file."
Expand Down
5 changes: 5 additions & 0 deletions config/locales/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -895,6 +895,11 @@ fr:
explication_html: "<p>API Particulier facilite l’accès des administrations aux données familiales (CAF), aux données fiscales (DGFiP), au statut pôle-emploi et au statut étudiant d’un citoyen pour simplifier les démarches administratives mises en œuvre par les collectivités et les administrations.<br> Cela permet aux administrations d’accéder à des informations certifiées à la source et ainsi : </p> <ul> <li>de s’affranchir des pièces justificatives lors des démarches en ligne,</li> <li>de réduire le nombre d’erreurs de saisie,</li> <li>d’écarter le risque de fraude documentaire.</li> </ul> <p> <strong>Important&nbsp;:</strong> les disposition de l’article <a href='https://www.legifrance.gouv.fr/affichCodeArticle.do?cidTexte=LEGITEXT000031366350&amp;idArticle=LEGIARTI000031367412&amp;dateTexte=&amp;categorieLien=cid'>L144-8</a> n’autorisent que l’échange des informations strictement nécessaires pour traiter une démarche.<br /><br />En conséquence, ne sélectionnez ici que les données auxquelles vous aurez accès d’un point de vue légal.</p>"
update:
sources_ok: 'Mise à jour effectuée'
gestionnaires:
activate:
new:
title: Choix du mot de passe
continue: Continuer
zones:
ministeres: Ministères
france_connect:
Expand Down
5 changes: 5 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,11 @@
resources :commentaires, controller: 'groupe_gestionnaire_commentaires', only: [:index, :show, :create, :destroy]
end
end

namespace :gestionnaires do
get 'activate' => '/gestionnaires/activate#new'
patch 'activate' => '/gestionnaires/activate#create'
end
end

#
Expand Down
Loading

0 comments on commit 3ea718a

Please sign in to comment.