admin can modify procedure labels
This commit is contained in:
parent
35dee477ea
commit
725a97da7e
16 changed files with 388 additions and 5 deletions
7
app/components/procedure/card/labels_component.rb
Normal file
7
app/components/procedure/card/labels_component.rb
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Procedure::Card::LabelsComponent < ApplicationComponent
|
||||||
|
def initialize(procedure:)
|
||||||
|
@procedure = procedure
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
fr:
|
||||||
|
title: Labels
|
|
@ -0,0 +1,17 @@
|
||||||
|
.fr-col-6.fr-col-md-4.fr-col-lg-3
|
||||||
|
= link_to admin_procedure_procedure_labels_path(@procedure), class: 'fr-tile fr-enlarge-link' do
|
||||||
|
.fr-tile__body.flex.column.align-center.justify-between
|
||||||
|
- if @procedure.procedure_labels.present?
|
||||||
|
%p.fr-badge.fr-badge--info
|
||||||
|
Configuré
|
||||||
|
%div
|
||||||
|
.line-count.fr-my-1w
|
||||||
|
%p.fr-tag= @procedure.procedure_labels.size
|
||||||
|
- else
|
||||||
|
%p.fr-badge
|
||||||
|
Non configuré
|
||||||
|
|
||||||
|
%h3.fr-h6
|
||||||
|
= t('.title')
|
||||||
|
%p.fr-tile-subtitle Gérer les labels utilisables par les instructeurs
|
||||||
|
%p.fr-btn.fr-btn--tertiary= t('views.shared.actions.edit')
|
|
@ -0,0 +1,66 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Administrateurs
|
||||||
|
class ProcedureLabelsController < AdministrateurController
|
||||||
|
before_action :retrieve_procedure
|
||||||
|
before_action :set_colors_collection, only: [:edit, :new, :create, :update]
|
||||||
|
|
||||||
|
def index
|
||||||
|
@labels = @procedure.procedure_labels
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
@label = label
|
||||||
|
end
|
||||||
|
|
||||||
|
def new
|
||||||
|
@label = ProcedureLabel.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
@label = @procedure.procedure_labels.build(procedure_label_params)
|
||||||
|
|
||||||
|
if @label.save
|
||||||
|
flash.notice = 'Le label a bien été créé'
|
||||||
|
redirect_to admin_procedure_procedure_labels_path(@procedure)
|
||||||
|
else
|
||||||
|
flash.alert = @label.errors.full_messages
|
||||||
|
render :new
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
@label = label
|
||||||
|
@label.update(procedure_label_params)
|
||||||
|
|
||||||
|
if @label.valid?
|
||||||
|
flash.notice = 'Le label a bien été modifié'
|
||||||
|
redirect_to admin_procedure_procedure_labels_path(@procedure)
|
||||||
|
else
|
||||||
|
flash.alert = @label.errors.full_messages
|
||||||
|
render :edit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
@label = label
|
||||||
|
@label.destroy!
|
||||||
|
flash.notice = 'Le label a bien été supprimé'
|
||||||
|
redirect_to admin_procedure_procedure_labels_path(@procedure)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def procedure_label_params
|
||||||
|
params.require(:procedure_label).permit(:name, :color)
|
||||||
|
end
|
||||||
|
|
||||||
|
def label
|
||||||
|
@procedure.procedure_labels.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_colors_collection
|
||||||
|
@colors_collection = ProcedureLabel.colors.values
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -130,7 +130,7 @@ module DossierHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def tag_label(name, color)
|
def tag_label(name, color)
|
||||||
tag.span(name, class: "fr-tag fr-tag--sm fr-tag--#{color}")
|
tag.span(name, class: "fr-tag fr-tag--sm fr-tag--#{ProcedureLabel.colors.fetch(color.underscore)}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def demandeur_dossier(dossier)
|
def demandeur_dossier(dossier)
|
||||||
|
|
|
@ -4,11 +4,33 @@ class Label < ApplicationRecord
|
||||||
belongs_to :procedure
|
belongs_to :procedure
|
||||||
has_many :dossier_labels, dependent: :destroy
|
has_many :dossier_labels, dependent: :destroy
|
||||||
|
|
||||||
|
NAME_MAX_LENGTH = 30
|
||||||
GENERIC_LABELS = [
|
GENERIC_LABELS = [
|
||||||
{ name: 'à relancer', color: 'brown-caramel' },
|
{ name: 'à relancer', color: 'brown_caramel' },
|
||||||
{ name: 'complet', color: 'green-bourgeon' },
|
{ name: 'complet', color: 'green_bourgeon' },
|
||||||
{ name: 'prêt pour validation', color: 'green-archipel' }
|
{ name: 'prêt pour validation', color: 'green_archipel' }
|
||||||
]
|
]
|
||||||
|
|
||||||
|
enum color: {
|
||||||
|
green_tilleul_verveine: "green-tilleul-verveine",
|
||||||
|
green_bourgeon: "green-bourgeon",
|
||||||
|
green_emeraude: "green-emeraude",
|
||||||
|
green_menthe: "green-menthe",
|
||||||
|
green_archipel: "green-archipel",
|
||||||
|
blue_ecume: "blue-ecume",
|
||||||
|
blue_cumulus: "blue-cumulus",
|
||||||
|
purple_glycine: "purple-glycine",
|
||||||
|
pink_macaron: "pink-macaron",
|
||||||
|
pink_tuile: "pink-tuile",
|
||||||
|
yellow_tournesol: "yellow-tournesol",
|
||||||
|
yellow_moutarde: "yellow-moutarde",
|
||||||
|
orange_terre_battue: "orange-terre-battue",
|
||||||
|
brown_cafe_creme: "brown-cafe-creme",
|
||||||
|
brown_caramel: "brown-caramel",
|
||||||
|
brown_opera: "brown-opera",
|
||||||
|
beige_gris_galet: "beige-gris-galet"
|
||||||
|
}
|
||||||
|
|
||||||
validates :name, :color, presence: true
|
validates :name, :color, presence: true
|
||||||
|
validates :name, length: { maximum: NAME_MAX_LENGTH }
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
= form_with model: label, url: admin_procedure_procedure_labels_path(@procedure, id: @label.id), local: true do |f|
|
||||||
|
= render Dsfr::InputComponent.new(form: f, attribute: :name, input_type: :text_field, opts: { maxlength: ProcedureLabel::NAME_MAX_LENGTH})
|
||||||
|
= f.label :color, class: 'fr-label' do
|
||||||
|
= t('activerecord.attributes.procedure_label.color')
|
||||||
|
= render EditableChamp::AsteriskMandatoryComponent.new
|
||||||
|
= f.select :color, options_for_select(@colors_collection, selected: @label.color), {prompt: 'Choisir une couleur'}, {class: 'fr-select'}
|
||||||
|
|
||||||
|
= render Procedure::FixedFooterComponent.new(procedure: @procedure, form: f)
|
16
app/views/administrateurs/procedure_labels/edit.html.haml
Normal file
16
app/views/administrateurs/procedure_labels/edit.html.haml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
= render partial: 'administrateurs/breadcrumbs',
|
||||||
|
locals: { steps: [['Démarches', admin_procedures_path],
|
||||||
|
[@procedure.libelle.truncate_words(10), admin_procedure_path(@procedure)],
|
||||||
|
['gestion des labels', admin_procedure_procedure_labels_path(procedure_id: @procedure.id)],
|
||||||
|
['Modifier le label']] }
|
||||||
|
|
||||||
|
|
||||||
|
.fr-container
|
||||||
|
.fr-mb-3w
|
||||||
|
= link_to "Liste de tous les labels", admin_procedure_procedure_labels_path(procedure_id: @procedure.id), class: "fr-link fr-icon-arrow-left-line fr-link--icon-left"
|
||||||
|
|
||||||
|
%h1.fr-h2
|
||||||
|
Modifier le label
|
||||||
|
|
||||||
|
= render partial: 'form',
|
||||||
|
locals: { label: @label, procedure_id: @procedure.id }
|
35
app/views/administrateurs/procedure_labels/index.html.haml
Normal file
35
app/views/administrateurs/procedure_labels/index.html.haml
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
= render partial: 'administrateurs/breadcrumbs',
|
||||||
|
locals: { steps: [['Démarches', admin_procedures_path],
|
||||||
|
[@procedure.libelle.truncate_words(10), admin_procedure_path(@procedure)],
|
||||||
|
['Labels']] }
|
||||||
|
|
||||||
|
.fr-container
|
||||||
|
%h1.fr-h2 Labels
|
||||||
|
|
||||||
|
= link_to "Nouveau label", new_admin_procedure_procedure_label_path(procedure_id: @procedure.id), class: "fr-btn fr-btn--primary fr-btn--icon-left fr-icon-add-circle-line mb-3"
|
||||||
|
|
||||||
|
- if @procedure.procedure_labels.present?
|
||||||
|
.fr-table.fr-table--layout-fixed.fr-table--bordered
|
||||||
|
%table
|
||||||
|
%caption Liste des labels
|
||||||
|
%thead
|
||||||
|
%tr
|
||||||
|
%th{ scope: "col" }
|
||||||
|
Nom
|
||||||
|
%th.change{ scope: "col" }
|
||||||
|
Actions
|
||||||
|
|
||||||
|
%tbody
|
||||||
|
- @labels.each do |label|
|
||||||
|
%tr
|
||||||
|
%td
|
||||||
|
= tag_label(label.name, label.color)
|
||||||
|
%td.change
|
||||||
|
= link_to('Modifier', edit_admin_procedure_procedure_label_path(procedure_id: @procedure.id, id: label.id), class: 'fr-btn fr-btn--sm fr-btn--secondary fr-btn--icon-left fr-icon-pencil-line')
|
||||||
|
= link_to 'Supprimer',
|
||||||
|
admin_procedure_procedure_label_path(procedure_id: @procedure.id, id: label.id),
|
||||||
|
method: :delete,
|
||||||
|
data: { confirm: "Confirmez vous la suppression de #{label.name}" },
|
||||||
|
class: 'fr-btn fr-btn--sm fr-btn--secondary fr-btn--icon-left fr-icon-delete-line fr-ml-1w'
|
||||||
|
|
||||||
|
= render Procedure::FixedFooterComponent.new(procedure: @procedure)
|
16
app/views/administrateurs/procedure_labels/new.html.haml
Normal file
16
app/views/administrateurs/procedure_labels/new.html.haml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
= render partial: 'administrateurs/breadcrumbs',
|
||||||
|
locals: { steps: [['Démarches', admin_procedures_path],
|
||||||
|
[@procedure.libelle.truncate_words(10), admin_procedure_path(@procedure)],
|
||||||
|
['gestion des labels', admin_procedure_procedure_labels_path(procedure_id: @procedure.id)],
|
||||||
|
['Nouveau label']] }
|
||||||
|
|
||||||
|
|
||||||
|
.fr-container
|
||||||
|
.fr-mb-3w
|
||||||
|
= link_to "Liste de tous les labels", admin_procedure_procedure_labels_path(procedure_id: @procedure.id), class: "fr-link fr-icon-arrow-left-line fr-link--icon-left"
|
||||||
|
|
||||||
|
%h1.fr-h2
|
||||||
|
Créer un nouveau label
|
||||||
|
|
||||||
|
= render partial: 'form',
|
||||||
|
locals: { label: @label, procedure_id: @procedure.id }
|
|
@ -98,3 +98,4 @@
|
||||||
= render Procedure::Card::DossierSubmittedMessageComponent.new(procedure: @procedure)
|
= render Procedure::Card::DossierSubmittedMessageComponent.new(procedure: @procedure)
|
||||||
= render Procedure::Card::ChorusComponent.new(procedure: @procedure)
|
= render Procedure::Card::ChorusComponent.new(procedure: @procedure)
|
||||||
= render Procedure::Card::AccuseLectureComponent.new(procedure: @procedure)
|
= render Procedure::Card::AccuseLectureComponent.new(procedure: @procedure)
|
||||||
|
= render Procedure::Card::LabelsComponent.new(procedure: @procedure)
|
||||||
|
|
|
@ -44,4 +44,11 @@
|
||||||
.fr-fieldset__element
|
.fr-fieldset__element
|
||||||
.fr-checkbox-group.fr-checkbox-group--sm.fr-mb-1w
|
.fr-checkbox-group.fr-checkbox-group--sm.fr-mb-1w
|
||||||
= b.check_box(checked: DossierLabel.find_by(dossier_id: dossier.id, label_id: b.value).present? )
|
= b.check_box(checked: DossierLabel.find_by(dossier_id: dossier.id, label_id: b.value).present? )
|
||||||
= b.label(class: "fr-label fr-tag fr-tag--sm fr-tag--#{b.object.color}") { b.text }
|
= b.label(class: "fr-label fr-tag fr-tag--sm fr-tag--#{Label.colors.fetch(b.object.color)}") { b.text }
|
||||||
|
|
||||||
|
%hr
|
||||||
|
%p.fr-text--sm.fr-text-mention--grey.fr-mb-0
|
||||||
|
%b Besoin d'autres labels ?
|
||||||
|
%br
|
||||||
|
Contactez les
|
||||||
|
= link_to 'administrateurs de la démarche', administrateurs_instructeur_procedure_path(dossier.procedure), class: 'fr-link fr-link--sm', **external_link_attributes
|
||||||
|
|
6
config/locales/models/procedure_label/fr.yml
Normal file
6
config/locales/models/procedure_label/fr.yml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
fr:
|
||||||
|
activerecord:
|
||||||
|
attributes:
|
||||||
|
procedure_label:
|
||||||
|
color: Couleur
|
||||||
|
name: Nom
|
|
@ -708,6 +708,8 @@ Rails.application.routes.draw do
|
||||||
get 'preview', on: :member
|
get 'preview', on: :member
|
||||||
end
|
end
|
||||||
|
|
||||||
|
resources :procedure_labels, controller: 'procedure_labels'
|
||||||
|
|
||||||
resource :attestation_template, only: [:show, :edit, :update, :create] do
|
resource :attestation_template, only: [:show, :edit, :update, :create] do
|
||||||
get 'preview', on: :member
|
get 'preview', on: :member
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,168 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
describe Administrateurs::ProcedureLabelsController, type: :controller do
|
||||||
|
let(:admin) { administrateurs(:default_admin) }
|
||||||
|
let(:procedure) { create(:procedure, administrateur: admin) }
|
||||||
|
let(:admin_2) { create(:administrateur) }
|
||||||
|
let(:procedure_2) { create(:procedure, administrateur: admin_2) }
|
||||||
|
|
||||||
|
describe '#index' do
|
||||||
|
render_views
|
||||||
|
let!(:label_1) { create(:procedure_label, procedure:) }
|
||||||
|
let!(:label_2) { create(:procedure_label, procedure:) }
|
||||||
|
let!(:label_3) { create(:procedure_label, procedure:) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
sign_in(admin.user)
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { get :index, params: { procedure_id: procedure.id } }
|
||||||
|
|
||||||
|
it 'displays all procedure labels' do
|
||||||
|
subject
|
||||||
|
expect(response.body).to have_link("Nouveau label")
|
||||||
|
expect(response.body).to have_link("Modifier", count: 3)
|
||||||
|
expect(response.body).to have_link("Supprimer", count: 3)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#create' do
|
||||||
|
before do
|
||||||
|
sign_in(admin.user)
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { post :create, params: params }
|
||||||
|
|
||||||
|
context 'when submitting a new label' do
|
||||||
|
let(:params) do
|
||||||
|
{
|
||||||
|
procedure_label: {
|
||||||
|
name: 'Nouveau label',
|
||||||
|
color: 'green-bourgeon'
|
||||||
|
},
|
||||||
|
procedure_id: procedure.id
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect { subject }.to change { ProcedureLabel.count } .by(1) }
|
||||||
|
|
||||||
|
it 'creates a new label' do
|
||||||
|
subject
|
||||||
|
expect(flash.alert).to be_nil
|
||||||
|
expect(flash.notice).to eq('Le label a bien été créé')
|
||||||
|
expect(ProcedureLabel.last.name).to eq('Nouveau label')
|
||||||
|
expect(ProcedureLabel.last.color).to eq('green_bourgeon')
|
||||||
|
expect(procedure.procedure_labels.last).to eq(ProcedureLabel.last)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when submitting an invalid label' do
|
||||||
|
let(:params) { { procedure_label: { name: 'Nouveau label' }, procedure_id: procedure.id } }
|
||||||
|
|
||||||
|
it { expect { subject }.not_to change { ProcedureLabel.count } }
|
||||||
|
|
||||||
|
it 'does not create a new label' do
|
||||||
|
subject
|
||||||
|
expect(flash.alert).to eq(["Le champ « Couleur » doit être rempli"])
|
||||||
|
expect(response).to render_template(:new)
|
||||||
|
expect(assigns(:label).name).to eq('Nouveau label')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when submitting a label for a not own procedure' do
|
||||||
|
let(:params) do
|
||||||
|
{
|
||||||
|
procedure_label: {
|
||||||
|
name: 'Nouveau label',
|
||||||
|
color: 'green-bourgeon'
|
||||||
|
},
|
||||||
|
procedure_id: procedure_2.id
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect { subject }.not_to change { ProcedureLabel.count } }
|
||||||
|
|
||||||
|
it 'does not create a new label' do
|
||||||
|
subject
|
||||||
|
expect(flash.alert).to eq("Démarche inexistante")
|
||||||
|
expect(response.status).to eq(404)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#update' do
|
||||||
|
let!(:label) { create(:procedure_label, procedure:) }
|
||||||
|
let(:label_params) { { name: 'Nouveau nom' } }
|
||||||
|
let(:params) { { id: label.id, procedure_label: label_params, procedure_id: procedure.id } }
|
||||||
|
|
||||||
|
before do
|
||||||
|
sign_in(admin.user)
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { patch :update, params: }
|
||||||
|
|
||||||
|
context 'when updating a label' do
|
||||||
|
it 'updates correctly' do
|
||||||
|
subject
|
||||||
|
expect(flash.alert).to be_nil
|
||||||
|
expect(flash.notice).to eq('Le label a bien été modifié')
|
||||||
|
expect(label.reload.name).to eq('Nouveau nom')
|
||||||
|
expect(label.reload.color).to eq('green_bourgeon')
|
||||||
|
expect(label.reload.updated_at).not_to eq(label.reload.created_at)
|
||||||
|
expect(response).to redirect_to(admin_procedure_procedure_labels_path(procedure_id: procedure.id))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when updating a service with invalid data' do
|
||||||
|
let(:label_params) { { name: '' } }
|
||||||
|
|
||||||
|
it 'does not update' do
|
||||||
|
subject
|
||||||
|
expect(flash.alert).not_to be_nil
|
||||||
|
expect(response).to render_template(:edit)
|
||||||
|
expect(label.reload.updated_at).to eq(label.reload.created_at)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when updating a label for a not own procedure' do
|
||||||
|
let(:params) { { id: label.id, procedure_label: label_params, procedure_id: procedure_2.id } }
|
||||||
|
|
||||||
|
it 'does not update' do
|
||||||
|
subject
|
||||||
|
expect(label.reload.updated_at).to eq(label.reload.created_at)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#destroy' do
|
||||||
|
let(:label) { create(:procedure_label, procedure:) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
sign_in(admin.user)
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { delete :destroy, params: }
|
||||||
|
|
||||||
|
context "when deleting a label" do
|
||||||
|
let(:params) { { id: label.id, procedure_id: procedure.id } }
|
||||||
|
|
||||||
|
it "delete the label" do
|
||||||
|
subject
|
||||||
|
expect { label.reload }.to raise_error(ActiveRecord::RecordNotFound)
|
||||||
|
expect(flash.notice).to eq('Le label a bien été supprimé')
|
||||||
|
expect(response).to redirect_to((admin_procedure_procedure_labels_path(procedure_id: procedure.id)))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when deleting a label for a not own procedure' do
|
||||||
|
let(:params) { { id: label.id, procedure_id: procedure_2.id } }
|
||||||
|
|
||||||
|
it 'does not delete' do
|
||||||
|
subject
|
||||||
|
expect(flash.alert).to eq("Démarche inexistante")
|
||||||
|
expect(response.status).to eq(404)
|
||||||
|
expect { label.reload }.not_to raise_error(ActiveRecord::RecordNotFound)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
9
spec/factories/procedure_label.rb
Normal file
9
spec/factories/procedure_label.rb
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
FactoryBot.define do
|
||||||
|
factory :procedure_label do
|
||||||
|
name { 'Un label' }
|
||||||
|
color { 'green-bourgeon' }
|
||||||
|
association :procedure
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue