Skip to content

Commit

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

Delégation de compte admin: ETQ admin je peux contacter mon/mes gestionnaires de groupe
  • Loading branch information
colinux authored Jan 11, 2024
2 parents e2cb833 + 210df8a commit 0dd3b16
Show file tree
Hide file tree
Showing 28 changed files with 382 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class GroupeGestionnaire::Card::CommentairesComponent < ApplicationComponent
def initialize(groupe_gestionnaire:, administrateur:, path:)
@groupe_gestionnaire = groupe_gestionnaire
@administrateur = administrateur
@path = path
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
fr:
title:
one: Message
other: Messages
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.fr-col-6.fr-col-md-4.fr-col-lg-3
= link_to @path, id: 'administrateurs', class: 'fr-tile fr-enlarge-link' do
.fr-tile__body.flex.column.align-center.justify-between
%div
.line-count.fr-my-1w
%p.fr-tag= @administrateur.commentaire_groupe_gestionnaires.size
%h3.fr-h6
= t('.title', count: @administrateur.commentaire_groupe_gestionnaires.size)
%p.fr-btn.fr-btn--tertiary= t('views.shared.actions.see')
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,4 @@ def destroy_button
class: 'fr-btn fr-btn--sm fr-btn--tertiary',
form: { data: { turbo: true, turbo_confirm: "Supprimer « #{@administrateur.email} » en tant qu'administrateurs ?" } }
end

def is_there_at_least_another_active_admin?
if @administrateur.active?
@groupe_gestionnaire.administrateurs.count(&:active?) > 1
else
@groupe_gestionnaire.administrateurs.count(&:active?) >= 1
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
class GroupeGestionnaire::GroupeGestionnaireCommentaires::CommentaireComponent < ApplicationComponent
include ApplicationHelper

def initialize(commentaire:, connected_user:, is_gestionnaire: true)
@commentaire = commentaire
@connected_user = connected_user
@is_gestionnaire = is_gestionnaire
end

private

def commentaire_issuer
if @commentaire.sent_by?(@connected_user)
t('.you')
else
(@commentaire.gestionnaire || @commentaire.sender).email
end
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
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
en:
reply: Reply
delete_button: Delete this message
confirm: Are you sure you want to delete this message ?
you: You
deleted_body: Message deleted
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
fr:
reply: Répondre
delete_button: Supprimer le message
confirm: Êtes-vous sûr de vouloir supprimer ce message ?
you: Vous
deleted_body: Message supprimé
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.width-100
%h2.fr-h6
%span.mail
= commentaire_issuer

%span.date{ class: ["fr-text--xs", "fr-text-mention--grey", "font-weight-normal"] }
= commentaire_date
.rich-text
- if @commentaire.discarded?
%p= t('.deleted_body')
- else
= render SimpleFormatComponent.new(@commentaire.body, allow_a: false)
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module Administrateurs
class GroupeGestionnaireController < AdministrateurController
before_action :retrieve_groupe_gestionnaire, only: [:show, :administrateurs, :gestionnaires]
before_action :retrieve_groupe_gestionnaire, only: [:show, :administrateurs, :gestionnaires, :commentaires, :create_commentaire]

def show
end
Expand All @@ -11,6 +11,22 @@ def administrateurs
def gestionnaires
end

def commentaires
@commentaire = Commentaire.new
end

def create_commentaire
@commentaire = @groupe_gestionnaire.commentaire_groupe_gestionnaires.create(commentaire_params.merge(sender: current_administrateur))

if @commentaire.errors.empty?
flash.notice = "Message envoyé"
redirect_to admin_groupe_gestionnaire_commentaires_path
else
flash.alert = @commentaire.errors.full_messages
render :commentaires
end
end

private

def retrieve_groupe_gestionnaire
Expand All @@ -24,5 +40,9 @@ def retrieve_groupe_gestionnaire
flash.alert = 'Groupe inexistant'
redirect_to admin_procedures_path, status: 404
end

def commentaire_params
params.require(:commentaire).permit(:body)
end
end
end
1 change: 1 addition & 0 deletions app/models/administrateur.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class Administrateur < ApplicationRecord
has_many :procedures, through: :administrateurs_procedures
has_many :services
has_many :api_tokens, inverse_of: :administrateur, dependent: :destroy
has_many :commentaire_groupe_gestionnaires, as: :sender
has_and_belongs_to_many :default_zones, class_name: 'Zone', join_table: 'default_zones_administrateurs'

belongs_to :user
Expand Down
28 changes: 28 additions & 0 deletions app/models/commentaire_groupe_gestionnaire.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
class CommentaireGroupeGestionnaire < ApplicationRecord
include Discard::Model
belongs_to :groupe_gestionnaire
belongs_to :gestionnaire, optional: true
belongs_to :sender, polymorphic: true

validates :body, presence: { message: "ne peut être vide" }

def soft_deletable?(connected_user)
sent_by?(connected_user) && sent_by_gestionnaire? && !discarded?
end

def soft_delete!
discard!
end

def sent_by_gestionnaire?
gestionnaire_id.present?
end

def sent_by?(someone)
if gestionnaire
someone == gestionnaire
else
someone == sender
end
end
end
1 change: 1 addition & 0 deletions app/models/gestionnaire.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
class Gestionnaire < ApplicationRecord
include UserFindByConcern
has_and_belongs_to_many :groupe_gestionnaires
has_many :commentaire_groupe_gestionnaires

belongs_to :user

Expand Down
1 change: 1 addition & 0 deletions app/models/groupe_gestionnaire.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
class GroupeGestionnaire < ApplicationRecord
has_many :administrateurs
has_many :commentaire_groupe_gestionnaires
has_and_belongs_to_many :gestionnaires

has_ancestry
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
= render partial: 'gestionnaires/breadcrumbs',
locals: { steps: [['Mon groupe gestionnaire', admin_groupe_gestionnaire_path],
['Messagerie']], preview: false }

.container
%h1 Messagerie de « #{@groupe_gestionnaire.name} »
.messagerie.container
- if current_administrateur.commentaire_groupe_gestionnaires.where(groupe_gestionnaire: @groupe_gestionnaire).present?
%ul.messages-list{ data: { controller: 'scroll-to' } }
- current_administrateur.commentaire_groupe_gestionnaires.where(groupe_gestionnaire: @groupe_gestionnaire).each do |commentaire|
%li.message{ class: commentaire_is_from_me_class(commentaire, current_administrateur), id: dom_id(commentaire) }
= render(GroupeGestionnaire::GroupeGestionnaireCommentaires::CommentaireComponent.new(commentaire: commentaire, connected_user: current_administrateur, is_gestionnaire: false))
= render partial: "shared/groupe_gestionnaires/commentaires/form", locals: { commentaire: @commentaire, form_url: admin_groupe_gestionnaire_create_commentaire_path }
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
.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::CommentairesComponent.new(groupe_gestionnaire: @groupe_gestionnaire, administrateur: current_administrateur, path: admin_groupe_gestionnaire_commentaires_path)
12 changes: 12 additions & 0 deletions app/views/shared/groupe_gestionnaires/commentaires/_form.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
= render NestedForms::FormOwnerComponent.new
= form_for(commentaire, url: form_url) do |f|
- dossier = commentaire.dossier
- placeholder = t('views.shared.dossiers.messages.form.write_message_to_administration_placeholder')
- if instructeur_signed_in? || administrateur_signed_in? || expert_signed_in?
- placeholder = t('views.shared.dossiers.messages.form.write_message_placeholder')
%p.mandatory-explanation= t('asterisk_html', scope: [:utils])

= render Dsfr::InputComponent.new(form: f, attribute: :body, input_type: :text_area, opts: { rows: 5, placeholder: placeholder, title: placeholder, class: 'fr-input message-textarea'})

.fr-mt-3w
= f.submit t('views.shared.dossiers.messages.form.send_message'), class: 'fr-btn', data: { disable: true }
1 change: 1 addition & 0 deletions config/locales/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ fr:
actions:
save: Enregistrer
edit: Modifier
see: Voir
greetings:
hello: Bonjour,
best_regards: Cordialement,
Expand Down
4 changes: 2 additions & 2 deletions config/locales/models/groupe_gestionnaire/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ fr:
one: "%{emails} est déjà gestionnaire de ce groupe"
other: "%{emails} sont déjà gestionnaires de ce groupe"
administrateurs_already_in_groupe_gestionnaire:
one: Cet administrateur est déjà dans un groupe gestionnaire dont vous n'avez pas la gestion.
other: Ces administrateurs sont déjà dans un groupe gestionnaire dont vous n'avez pas la gestion.
one: Ajout impossible. Cet administrateur fait déjà partie d'un groupe.
other: Ajout impossible. Ces administrateurs font déjà partie d'un groupe.
wrong_address:
one: "%{emails} n’est pas une adresse email valide"
other: "%{emails} ne sont pas des adresses emails valides"
Expand Down
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,8 @@
get 'mon-groupe' => 'groupe_gestionnaire#show', as: :groupe_gestionnaire
get 'mon-groupe/administrateurs' => 'groupe_gestionnaire#administrateurs', as: :groupe_gestionnaire_administrateurs
get 'mon-groupe/gestionnaires' => 'groupe_gestionnaire#gestionnaires', as: :groupe_gestionnaire_gestionnaires
get 'mon-groupe/commentaires' => 'groupe_gestionnaire#commentaires', as: :groupe_gestionnaire_commentaires
post 'mon-groupe/create_commentaire' => 'groupe_gestionnaire#create_commentaire', as: :groupe_gestionnaire_create_commentaire

resources :services, except: [:show] do
collection do
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class CreateCommentaireGroupeGestionnaires < ActiveRecord::Migration[6.1]
disable_ddl_transaction!

def change
create_table "commentaire_groupe_gestionnaires" do |t|
t.references :groupe_gestionnaire, index: { name: :index_commentaire_groupe_gestionnaires_on_groupe_gestionnaire }
t.references "gestionnaire", null: true
t.string "sender_type", null: false
t.bigint "sender_id", null: false
t.string "body"
t.datetime "discarded_at"
t.timestamps
end
end
end
13 changes: 13 additions & 0 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,19 @@
t.index ["procedure_id"], name: "index_closed_mails_on_procedure_id"
end

create_table "commentaire_groupe_gestionnaires", force: :cascade do |t|
t.string "body"
t.datetime "created_at", precision: 6, null: false
t.datetime "discarded_at", precision: 6
t.bigint "gestionnaire_id"
t.bigint "groupe_gestionnaire_id"
t.bigint "sender_id", null: false
t.string "sender_type", null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["gestionnaire_id"], name: "index_commentaire_groupe_gestionnaires_on_gestionnaire_id"
t.index ["groupe_gestionnaire_id"], name: "index_commentaire_groupe_gestionnaires_on_groupe_gestionnaire"
end

create_table "commentaires", id: :serial, force: :cascade do |t|
t.string "body"
t.datetime "created_at", precision: nil, null: false
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
RSpec.describe GroupeGestionnaire::GroupeGestionnaireCommentaires::CommentaireComponent, type: :component do
let!(:component) do
described_class.new(
commentaire: commentaire,
connected_user: connected_user
)
end
let(:connected_user) { create(:administrateur) }
let(:commentaire) { create(:commentaire_groupe_gestionnaire, sender: connected_user) }

subject { render_inline(component).to_html }

it do
is_expected.to include("plop")
is_expected.to include("Vous")
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_groupe_gestionnaire, sender: connected_user) }
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

describe '#commentaire_issuer' do
let(:gestionnaire) { create(:gestionnaire) }
let(:commentaire) { create(:commentaire_groupe_gestionnaire, sender: connected_user, gestionnaire: gestionnaire) }

subject { component.send(:commentaire_issuer) }

context 'issuer is connected_user' do
it 'returns gestionnaire s email' do
expect(subject).to eq gestionnaire.email
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,55 @@
it { expect(assigns(:groupe_gestionnaire)).to eq(groupe_gestionnaire) }
end
end

describe '#commentaires' do
let(:gestionnaire) { create(:gestionnaire) }
let!(:groupe_gestionnaire) { create(:groupe_gestionnaire, gestionnaires: [gestionnaire], administrateurs: [admin]) }
subject { get :commentaires }

context "when not logged" do
before { subject }
it { expect(response).to redirect_to(new_user_session_path) }
end

context "when logged in" do
before do
sign_in(admin.user)
end

it { expect(subject).to have_http_status(:ok) }
end
end

describe "#create_commentaire" do
let(:gestionnaire) { create(:gestionnaire) }
let!(:groupe_gestionnaire) { create(:groupe_gestionnaire, gestionnaires: [gestionnaire], administrateurs: [admin]) }
let(:body) { "avant\napres" }

subject {
post :create_commentaire, params: {
commentaire: {
body: body
}
}
}

context "when not logged" do
before { subject }
it { expect(response).to redirect_to(new_user_session_path) }
end

context "when logged in" do
before do
sign_in(admin.user)
end

it "creates a commentaire" do
expect { subject }.to change(CommentaireGroupeGestionnaire, :count).by(1)

expect(response).to redirect_to(admin_groupe_gestionnaire_commentaires_path)
expect(flash.notice).to be_present
end
end
end
end
Loading

0 comments on commit 0dd3b16

Please sign in to comment.