Merge pull request #9664 from adullact/feature-ouidou/admin_creation_delegation_follow_commentaire
ETQ gestionnaire, j'ai un suivi des messages au sein de mes groupes
This commit is contained in:
commit
3ea718a3f5
35 changed files with 412 additions and 24 deletions
12
app/assets/stylesheets/groupe_gestionnaire_cards.scss
Normal file
12
app/assets/stylesheets/groupe_gestionnaire_cards.scss
Normal file
|
@ -0,0 +1,12 @@
|
|||
.fr-groupe_gestionnaire_cards {
|
||||
.fr-h6 {
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.notifications {
|
||||
top: 3px;
|
||||
right: 3px;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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')
|
||||
|
@ -22,4 +35,8 @@ class GroupeGestionnaire::GroupeGestionnaireCommentaires::CommentaireComponent <
|
|||
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
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -23,4 +23,9 @@ class GroupeGestionnaire::GroupeGestionnaireListCommentaires::CommentaireCompone
|
|||
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -25,13 +25,13 @@ class Administrateurs::ActivateController < ApplicationController
|
|||
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
|
||||
|
|
52
app/controllers/gestionnaires/activate_controller.rb
Normal file
52
app/controllers/gestionnaires/activate_controller.rb
Normal file
|
@ -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
|
|
@ -7,7 +7,9 @@ module Gestionnaires
|
|||
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
|
||||
|
@ -30,7 +32,6 @@ module Gestionnaires
|
|||
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
|
||||
|
|
|
@ -7,6 +7,7 @@ module Gestionnaires
|
|||
end
|
||||
|
||||
def show
|
||||
@unread_commentaires = current_gestionnaire.unread_commentaires?(@groupe_gestionnaire)
|
||||
end
|
||||
|
||||
def edit
|
||||
|
|
7
app/models/follow_commentaire_groupe_gestionnaire.rb
Normal file
7
app/models/follow_commentaire_groupe_gestionnaire.rb
Normal file
|
@ -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
|
|
@ -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
|
||||
|
||||
|
@ -33,4 +34,27 @@ class Gestionnaire < ApplicationRecord
|
|||
'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,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
|
||||
|
|
|
@ -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
app/views/gestionnaires/activate/new.html.haml
Normal file
26
app/views/gestionnaires/activate/new.html.haml
Normal file
|
@ -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') }
|
|
@ -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) }
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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."
|
||||
|
|
|
@ -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 :</strong> les disposition de l’article <a href='https://www.legifrance.gouv.fr/affichCodeArticle.do?cidTexte=LEGITEXT000031366350&idArticle=LEGIARTI000031367412&dateTexte=&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:
|
||||
|
|
|
@ -517,6 +517,11 @@ Rails.application.routes.draw do
|
|||
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
|
||||
|
||||
#
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
class CreateFollowCommentaireGroupeGestionnaires < ActiveRecord::Migration[6.1]
|
||||
disable_ddl_transaction!
|
||||
|
||||
def change
|
||||
create_table "follow_commentaire_groupe_gestionnaires" do |t|
|
||||
t.references :groupe_gestionnaire, index: { name: :index_follow_commentaire_on_groupe_gestionnaire }
|
||||
t.references :gestionnaire, null: false, index: { name: :index_follow_commentaire_on_gestionnaire }
|
||||
t.string "sender_type", null: true
|
||||
t.bigint "sender_id", null: true
|
||||
t.datetime "commentaire_seen_at"
|
||||
t.datetime "unfollowed_at"
|
||||
t.timestamps
|
||||
t.index [:gestionnaire_id, :groupe_gestionnaire_id, :sender_id, :sender_type, :unfollowed_at], name: :index_follow_commentaire_on_groupe_gestionnaire_unfollow, unique: true
|
||||
end
|
||||
end
|
||||
end
|
14
db/schema.rb
14
db/schema.rb
|
@ -609,6 +609,20 @@ ActiveRecord::Schema[7.0].define(version: 2024_01_23_085909) do
|
|||
t.index ["feature_key", "key", "value"], name: "index_flipper_gates_on_feature_key_and_key_and_value", unique: true
|
||||
end
|
||||
|
||||
create_table "follow_commentaire_groupe_gestionnaires", force: :cascade do |t|
|
||||
t.datetime "commentaire_seen_at", precision: 6
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.bigint "gestionnaire_id", null: false
|
||||
t.bigint "groupe_gestionnaire_id"
|
||||
t.bigint "sender_id"
|
||||
t.string "sender_type"
|
||||
t.datetime "unfollowed_at", precision: 6, precision: nil
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.index ["gestionnaire_id", "groupe_gestionnaire_id", "sender_id", "sender_type", "unfollowed_at"], name: "index_follow_commentaire_on_groupe_gestionnaire_unfollow", unique: true
|
||||
t.index ["gestionnaire_id"], name: "index_follow_commentaire_on_gestionnaire"
|
||||
t.index ["groupe_gestionnaire_id"], name: "index_follow_commentaire_on_groupe_gestionnaire"
|
||||
end
|
||||
|
||||
create_table "follows", id: :serial, force: :cascade do |t|
|
||||
t.datetime "annotations_privees_seen_at", precision: nil, null: false
|
||||
t.datetime "avis_seen_at", precision: nil, null: false
|
||||
|
|
|
@ -17,4 +17,31 @@ describe Administrateurs::ActivateController, type: :controller do
|
|||
it { expect(controller).not_to have_received(:trust_device) }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#create' do
|
||||
let!(:administrateur) { create(:administrateur) }
|
||||
let(:token) { administrateur.user.send(:set_reset_password_token) }
|
||||
let(:password) { 'Another-password-ok!@#123?' }
|
||||
|
||||
before { post :create, params: { administrateur: { reset_password_token: token, password: password } } }
|
||||
|
||||
context 'when the token is ok' do
|
||||
it { expect(administrateur.user.reload.valid_password?(password)).to be true }
|
||||
it { expect(response).to redirect_to(admin_procedures_path) }
|
||||
end
|
||||
|
||||
context 'when the password is not strong' do
|
||||
let(:password) { 'another-password-ok?' }
|
||||
|
||||
it { expect(administrateur.user.reload.valid_password?(password)).to be false }
|
||||
it { expect(response).to redirect_to(admin_activate_path(token: token)) }
|
||||
end
|
||||
|
||||
context 'when the token is bad' do
|
||||
let(:token) { 'bad' }
|
||||
|
||||
it { expect(administrateur.user.reload.valid_password?(password)).to be false }
|
||||
it { expect(response).to redirect_to(admin_activate_path(token: token)) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
40
spec/controllers/gestionnaires/activate_controller_spec.rb
Normal file
40
spec/controllers/gestionnaires/activate_controller_spec.rb
Normal file
|
@ -0,0 +1,40 @@
|
|||
describe Gestionnaires::ActivateController, type: :controller do
|
||||
describe '#new' do
|
||||
let(:gestionnaire) { create(:gestionnaire) }
|
||||
let(:token) { gestionnaire.user.send(:set_reset_password_token) }
|
||||
|
||||
before { allow(controller).to receive(:trust_device) }
|
||||
|
||||
context 'when the token is ok' do
|
||||
before { get :new, params: { token: token } }
|
||||
|
||||
it { expect(controller).to have_received(:trust_device) }
|
||||
end
|
||||
|
||||
context 'when the token is bad' do
|
||||
before { get :new, params: { token: 'bad' } }
|
||||
|
||||
it { expect(controller).not_to have_received(:trust_device) }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#create' do
|
||||
let!(:gestionnaire) { create(:gestionnaire) }
|
||||
let(:token) { gestionnaire.user.send(:set_reset_password_token) }
|
||||
let(:password) { 'another-password-ok?' }
|
||||
|
||||
before { post :create, params: { gestionnaire: { reset_password_token: token, password: password } } }
|
||||
|
||||
context 'when the token is ok' do
|
||||
it { expect(gestionnaire.user.reload.valid_password?(password)).to be true }
|
||||
it { expect(response).to redirect_to(gestionnaire_groupe_gestionnaires_path) }
|
||||
end
|
||||
|
||||
context 'when the token is bad' do
|
||||
let(:token) { 'bad' }
|
||||
|
||||
it { expect(gestionnaire.user.reload.valid_password?(password)).to be false }
|
||||
it { expect(response).to redirect_to(gestionnaires_activate_path(token: token)) }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -4,7 +4,7 @@ describe Gestionnaires::GroupeGestionnaireCommentairesController, type: :control
|
|||
let(:groupe_gestionnaire) { create(:groupe_gestionnaire, gestionnaires: [gestionnaire], administrateurs: [administrateur]) }
|
||||
let!(:commentaire) { create(:commentaire_groupe_gestionnaire, groupe_gestionnaire: groupe_gestionnaire, sender: administrateur) }
|
||||
|
||||
describe "yyyy#index" do
|
||||
describe "#index" do
|
||||
render_views
|
||||
subject { get :index, params: { groupe_gestionnaire_id: groupe_gestionnaire.id } }
|
||||
|
||||
|
@ -27,7 +27,7 @@ describe Gestionnaires::GroupeGestionnaireCommentairesController, type: :control
|
|||
end
|
||||
end
|
||||
|
||||
describe "yyyy#show" do
|
||||
describe "#show" do
|
||||
render_views
|
||||
subject { get :show, params: { groupe_gestionnaire_id: groupe_gestionnaire.id, id: commentaire.id } }
|
||||
|
||||
|
@ -50,7 +50,7 @@ describe Gestionnaires::GroupeGestionnaireCommentairesController, type: :control
|
|||
end
|
||||
end
|
||||
|
||||
describe "yyyy#create" do
|
||||
describe "#create" do
|
||||
before do
|
||||
sign_in(gestionnaire.user)
|
||||
post :create,
|
||||
|
@ -69,7 +69,7 @@ describe Gestionnaires::GroupeGestionnaireCommentairesController, type: :control
|
|||
end
|
||||
end
|
||||
|
||||
describe "yyyy#destroy" do
|
||||
describe "#destroy" do
|
||||
before do
|
||||
sign_in(gestionnaire.user)
|
||||
end
|
||||
|
|
6
spec/factories/follow_commentaire_groupe_gestionnaire.rb
Normal file
6
spec/factories/follow_commentaire_groupe_gestionnaire.rb
Normal file
|
@ -0,0 +1,6 @@
|
|||
FactoryBot.define do
|
||||
factory :follow_commentaire_groupe_gestionnaire do
|
||||
association :groupe_gestionnaire
|
||||
association :gestionnaire
|
||||
end
|
||||
end
|
|
@ -0,0 +1,7 @@
|
|||
describe FollowCommentaireGroupeGestionnaire, type: :model do
|
||||
describe 'associations' do
|
||||
it { is_expected.to belong_to(:gestionnaire) }
|
||||
it { is_expected.to belong_to(:groupe_gestionnaire) }
|
||||
it { is_expected.to belong_to(:sender).optional }
|
||||
end
|
||||
end
|
|
@ -1,6 +1,7 @@
|
|||
describe Gestionnaire, type: :model do
|
||||
describe 'associations' do
|
||||
it { is_expected.to have_many(:commentaire_groupe_gestionnaires) }
|
||||
it { is_expected.to have_many(:follow_commentaire_groupe_gestionnaires) }
|
||||
it { is_expected.to have_and_belong_to_many(:groupe_gestionnaires) }
|
||||
end
|
||||
|
||||
|
@ -78,4 +79,111 @@ describe Gestionnaire, type: :model do
|
|||
it { is_expected.to eq [gestionnaire] }
|
||||
end
|
||||
end
|
||||
|
||||
describe "#unread_commentaires?" do
|
||||
context "over three different groupe_gestionnaire" do
|
||||
let(:gestionnaire) { create(:gestionnaire) }
|
||||
let(:administrateur) { create(:administrateur) }
|
||||
let(:groupe_gestionnaire) { create(:groupe_gestionnaire, gestionnaires: [gestionnaire]) }
|
||||
let!(:commentaire_groupe_gestionnaire) { create(:commentaire_groupe_gestionnaire, groupe_gestionnaire: groupe_gestionnaire, sender: administrateur, created_at: 12.hours.ago) }
|
||||
let!(:follow_commentaire_groupe_gestionnaire) { create(:follow_commentaire_groupe_gestionnaire, groupe_gestionnaire: groupe_gestionnaire, gestionnaire: gestionnaire, sender: administrateur, commentaire_seen_at: Time.zone.now) }
|
||||
|
||||
let(:gestionnaire_unread_commentaire_cause_never_seen) { create(:gestionnaire) }
|
||||
let(:administrateur_unread_commentaire_cause_never_seen) { create(:administrateur) }
|
||||
let(:groupe_gestionnaire_unread_commentaire_cause_never_seen) { create(:groupe_gestionnaire, gestionnaires: [gestionnaire_unread_commentaire_cause_never_seen]) }
|
||||
let!(:commentaire_groupe_gestionnaire_unread_commentaire_cause_never_seen) { create(:commentaire_groupe_gestionnaire, groupe_gestionnaire: groupe_gestionnaire_unread_commentaire_cause_never_seen, sender: administrateur_unread_commentaire_cause_never_seen, created_at: 12.hours.ago) }
|
||||
|
||||
let(:gestionnaire_unread_commentaire_cause_seen_at_before_last_commentaire) { create(:gestionnaire) }
|
||||
let(:administrateur_unread_commentaire_cause_seen_at_before_last_commentaire) { create(:administrateur) }
|
||||
let(:groupe_gestionnaire_unread_commentaire_cause_seen_at_before_last_commentaire) { create(:groupe_gestionnaire, gestionnaires: [gestionnaire_unread_commentaire_cause_seen_at_before_last_commentaire]) }
|
||||
let!(:commentaire_groupe_gestionnaire_unread_commentaire_cause_seen_at_before_last_commentaire) { create(:commentaire_groupe_gestionnaire, groupe_gestionnaire: groupe_gestionnaire_unread_commentaire_cause_seen_at_before_last_commentaire, sender: administrateur_unread_commentaire_cause_seen_at_before_last_commentaire, created_at: 12.hours.ago) }
|
||||
let!(:follow_commentaire_groupe_gestionnaire_unread_commentaire_cause_seen_at_before_last_commentaire) { create(:follow_commentaire_groupe_gestionnaire, groupe_gestionnaire: groupe_gestionnaire_unread_commentaire_cause_seen_at_before_last_commentaire, gestionnaire: gestionnaire_unread_commentaire_cause_seen_at_before_last_commentaire, sender: administrateur_unread_commentaire_cause_seen_at_before_last_commentaire, commentaire_seen_at: 1.day.ago) }
|
||||
|
||||
it do
|
||||
expect(gestionnaire.unread_commentaires?(groupe_gestionnaire)).to eq false
|
||||
expect(gestionnaire_unread_commentaire_cause_never_seen.unread_commentaires?(groupe_gestionnaire_unread_commentaire_cause_never_seen)).to eq true
|
||||
expect(gestionnaire_unread_commentaire_cause_seen_at_before_last_commentaire.unread_commentaires?(groupe_gestionnaire_unread_commentaire_cause_seen_at_before_last_commentaire)).to eq true
|
||||
end
|
||||
end
|
||||
|
||||
context "over same groupe_gestionnaire" do
|
||||
let(:gestionnaire) { create(:gestionnaire) }
|
||||
let(:gestionnaire_unread_commentaire_cause_never_seen) { create(:gestionnaire) }
|
||||
let(:gestionnaire_unread_commentaire_cause_seen_at_before_last_commentaire) { create(:gestionnaire) }
|
||||
let(:administrateur) { create(:administrateur) }
|
||||
let(:groupe_gestionnaire) { create(:groupe_gestionnaire, gestionnaires: [gestionnaire, gestionnaire_unread_commentaire_cause_never_seen, gestionnaire_unread_commentaire_cause_seen_at_before_last_commentaire]) }
|
||||
let!(:commentaire_groupe_gestionnaire) { create(:commentaire_groupe_gestionnaire, groupe_gestionnaire: groupe_gestionnaire, sender: administrateur, created_at: 12.hours.ago) }
|
||||
|
||||
let!(:follow_commentaire_groupe_gestionnaire) { create(:follow_commentaire_groupe_gestionnaire, groupe_gestionnaire: groupe_gestionnaire, gestionnaire: gestionnaire, sender: administrateur, commentaire_seen_at: Time.zone.now) }
|
||||
let!(:follow_commentaire_groupe_gestionnaire_unread_commentaire_cause_seen_at_before_last_commentaire) { create(:follow_commentaire_groupe_gestionnaire, groupe_gestionnaire: groupe_gestionnaire, gestionnaire: gestionnaire_unread_commentaire_cause_seen_at_before_last_commentaire, sender: administrateur, commentaire_seen_at: 1.day.ago) }
|
||||
|
||||
it do
|
||||
expect(gestionnaire.unread_commentaires?(groupe_gestionnaire)).to eq false
|
||||
expect(gestionnaire_unread_commentaire_cause_never_seen.unread_commentaires?(groupe_gestionnaire)).to eq true
|
||||
expect(gestionnaire_unread_commentaire_cause_seen_at_before_last_commentaire.unread_commentaires?(groupe_gestionnaire)).to eq true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#commentaire_seen_at" do
|
||||
context "when already seen commentaire" do
|
||||
let(:gestionnaire) { create(:gestionnaire) }
|
||||
let(:administrateur) { create(:administrateur) }
|
||||
let(:groupe_gestionnaire) { create(:groupe_gestionnaire, gestionnaires: [gestionnaire]) }
|
||||
let!(:commentaire_groupe_gestionnaire) { create(:commentaire_groupe_gestionnaire, groupe_gestionnaire: groupe_gestionnaire, sender: administrateur, created_at: 12.hours.ago) }
|
||||
let!(:follow_commentaire_groupe_gestionnaire) { create(:follow_commentaire_groupe_gestionnaire, groupe_gestionnaire: groupe_gestionnaire, gestionnaire: gestionnaire, sender: administrateur, commentaire_seen_at: Time.zone.now) }
|
||||
|
||||
it { expect(gestionnaire.commentaire_seen_at(groupe_gestionnaire, administrateur).to_date).to eq Date.current }
|
||||
end
|
||||
|
||||
context "when never seen commentaire" do
|
||||
let(:gestionnaire) { create(:gestionnaire) }
|
||||
let(:administrateur) { create(:administrateur) }
|
||||
let(:groupe_gestionnaire) { create(:groupe_gestionnaire, gestionnaires: [gestionnaire]) }
|
||||
let!(:commentaire_groupe_gestionnaire) { create(:commentaire_groupe_gestionnaire, groupe_gestionnaire: groupe_gestionnaire, sender: administrateur, created_at: 12.hours.ago) }
|
||||
|
||||
it { expect(gestionnaire.commentaire_seen_at(groupe_gestionnaire, administrateur)).to eq nil }
|
||||
end
|
||||
end
|
||||
|
||||
describe "#mark_commentaire_as_seen" do
|
||||
context "when already seen commentaire" do
|
||||
let(:now) { Time.zone.now.beginning_of_minute }
|
||||
let(:gestionnaire) { create(:gestionnaire) }
|
||||
let(:administrateur) { create(:administrateur) }
|
||||
let(:groupe_gestionnaire) { create(:groupe_gestionnaire, gestionnaires: [gestionnaire]) }
|
||||
let!(:commentaire_groupe_gestionnaire) { create(:commentaire_groupe_gestionnaire, groupe_gestionnaire: groupe_gestionnaire, sender: administrateur, created_at: 12.hours.ago) }
|
||||
let!(:follow_commentaire_groupe_gestionnaire) { create(:follow_commentaire_groupe_gestionnaire, groupe_gestionnaire: groupe_gestionnaire, gestionnaire: gestionnaire, sender: administrateur, commentaire_seen_at: 12.hours.ago) }
|
||||
|
||||
subject do
|
||||
travel_to(now) do
|
||||
gestionnaire.mark_commentaire_as_seen(groupe_gestionnaire, administrateur)
|
||||
end
|
||||
end
|
||||
|
||||
it do
|
||||
subject
|
||||
expect(gestionnaire.commentaire_seen_at(groupe_gestionnaire, administrateur)).to eq now
|
||||
end
|
||||
end
|
||||
|
||||
context "when never seen commentaire" do
|
||||
let(:now) { Time.zone.now.beginning_of_minute }
|
||||
let(:gestionnaire) { create(:gestionnaire) }
|
||||
let(:administrateur) { create(:administrateur) }
|
||||
let(:groupe_gestionnaire) { create(:groupe_gestionnaire, gestionnaires: [gestionnaire]) }
|
||||
let!(:commentaire_groupe_gestionnaire) { create(:commentaire_groupe_gestionnaire, groupe_gestionnaire: groupe_gestionnaire, sender: administrateur, created_at: 12.hours.ago) }
|
||||
|
||||
subject do
|
||||
travel_to(now) do
|
||||
gestionnaire.mark_commentaire_as_seen(groupe_gestionnaire, administrateur)
|
||||
end
|
||||
end
|
||||
|
||||
it do
|
||||
subject
|
||||
expect(gestionnaire.commentaire_seen_at(groupe_gestionnaire, administrateur)).to eq now
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,6 +2,7 @@ describe GroupeGestionnaire, type: :model do
|
|||
describe 'associations' do
|
||||
it { is_expected.to have_many(:administrateurs) }
|
||||
it { is_expected.to have_many(:commentaire_groupe_gestionnaires) }
|
||||
it { is_expected.to have_many(:follow_commentaire_groupe_gestionnaires) }
|
||||
it { is_expected.to have_and_belong_to_many(:gestionnaires) }
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue