create and update export templates

This commit is contained in:
Christophe Robillard 2024-03-03 11:30:41 +01:00 committed by simon lehericey
parent 95c308dc51
commit f5813b4e55
No known key found for this signature in database
GPG key ID: CDE670D827C7B3C5
8 changed files with 288 additions and 3 deletions

View file

@ -0,0 +1,82 @@
module Instructeurs
class ExportTemplatesController < InstructeurController
before_action :set_procedure
before_action :set_groupe_instructeur, only: [:create, :update]
before_action :set_export_template, only: [:edit, :update, :destroy]
before_action :set_groupe_instructeurs
before_action :set_all_pj
def new
@export_template = ExportTemplate.new(kind: 'zip', groupe_instructeur: @groupe_instructeurs.first)
@export_template.set_default_values
end
def create
@export_template = @groupe_instructeur.export_templates.build(export_template_params)
@export_template.assign_pj_names(pj_params)
if @export_template.save
redirect_to exports_instructeur_procedure_path(procedure: @procedure), notice: "Le modèle d'export #{@export_template.name} a bien été créé"
else
flash[:alert] = @export_template.errors.full_messages
render :new
end
end
def edit
end
def update
@export_template.assign_attributes(export_template_params)
@export_template.groupe_instructeur = @groupe_instructeur
@export_template.assign_pj_names(pj_params)
if @export_template.save
redirect_to exports_instructeur_procedure_path(procedure: @procedure), notice: "Le modèle d'export #{@export_template.name} a bien été modifié"
else
flash[:alert] = @export_template.errors.full_messages
render :edit
end
end
private
def export_template_params
params.require(:export_template).permit(*export_params)
end
def set_procedure
@procedure = current_instructeur.procedures.find params[:procedure_id]
Sentry.configure_scope do |scope|
scope.set_tags(procedure: @procedure.id)
end
end
def set_export_template
@export_template = current_instructeur.export_templates.find(params[:id])
end
def set_groupe_instructeur
@groupe_instructeur = @procedure.groupe_instructeurs.find(params.require(:export_template)[:groupe_instructeur_id])
end
def set_groupe_instructeurs
@groupe_instructeurs = current_instructeur.groupe_instructeurs.where(procedure: @procedure)
end
def set_all_pj
@all_pj ||= @procedure.pieces_jointes_exportables_list
end
def export_params
[:name, :kind, :tiptap_default_dossier_directory, :tiptap_pdf_name]
end
def pj_params
@procedure = current_instructeur.procedures.find params[:procedure_id]
pj_params = []
@all_pj.each do |pj|
pj_params << "tiptap_pj_#{pj.stable_id}".to_sym
end
params.require(:export_template).permit(*pj_params)
end
end
end

View file

@ -37,9 +37,11 @@ class ExportTemplate < ApplicationRecord
content_for_pj_id(pj.stable_id)&.to_json content_for_pj_id(pj.stable_id)&.to_json
end end
def content_for_pj_id(stable_id) def assign_pj_names(pj_params)
content_for_stable_id = content["pjs"].find { _1.symbolize_keys[:stable_id] == stable_id.to_s } self.content["pjs"] = []
content_for_stable_id.symbolize_keys.fetch(:path) pj_params.each do |pj_param|
self.content["pjs"] << { stable_id: pj_param[0].delete_prefix("tiptap_pj_"), path: JSON.parse(pj_param[1]) }
end
end end
def attachment_and_path(dossier, attachment, index: 0, row_index: nil) def attachment_and_path(dossier, attachment, index: 0, row_index: nil)

View file

@ -0,0 +1,59 @@
.fr-grid-row.fr-grid-row--gutters
.fr-col-12.fr-col-md-8
= form_with url: form_url, model: @export_template, local: true do |f|
= render Dsfr::InputComponent.new(form: f, attribute: :name, input_type: :text_field) do |c|
- c.with_hint do
Indiquez le nom à utiliser pour ce modèle d'export
- if groupe_instructeurs.many?
.fr-input-group
= f.label :groupe_instructeur_id, class: 'fr-label' do
= f.object.class.human_attribute_name(:groupe_instructeur_id)
= render EditableChamp::AsteriskMandatoryComponent.new
%span.fr-hint-text
Avec quel groupe instructeur souhaitez-vous partager ce modèle d'export ?
= f.collection_select :groupe_instructeur_id, groupe_instructeurs, :id, :label, {}, class: 'fr-select'
- else
= f.hidden_field :groupe_instructeur_id
= f.hidden_field :kind
.fr-input-group{ data: { controller: 'tiptap' } }
= f.label :tiptap_default_dossier_directory, class: "fr-label"
.editor.mt-2{ data: { tiptap_target: 'editor' } }
= f.hidden_field :tiptap_default_dossier_directory, data: { tiptap_target: 'input' }
%ul.mt-2.flex.wrap.flex-gap-1
- @export_template.specific_tags.each do |tag|
%li.fr-badge.fr-badge--sm{ role: 'button', title: tag[:description], data: { action: 'click->tiptap#insertTag', tiptap_target: 'tag', tag_id: tag[:id], tag_label: tag[:libelle] } }
= tag[:libelle]
.fr-input-group{ data: { controller: 'tiptap' } }
= f.label :tiptap_pdf_name, class: "fr-label"
.editor.mt-2{ data: { tiptap_target: 'editor' } }
= f.hidden_field :tiptap_pdf_name, data: { tiptap_target: 'input' }
%ul.mt-2.flex.wrap.flex-gap-1
- @export_template.specific_tags.each do |tag|
%li.fr-badge.fr-badge--sm{ role: 'button', title: tag[:description], data: { action: 'click->tiptap#insertTag', tiptap_target: 'tag', tag_id: tag[:id], tag_label: tag[:libelle] } }
= tag[:libelle]
- if @all_pj.any?
%h3 Pieces justificatives
- @all_pj.each do |pj|
.fr-input-group{ data: { controller: 'tiptap' } }
= label_tag pj.libelle, nil, name: field_name(:export_template, "tiptap_pj_#{pj.stable_id}"), class: "fr-label"
.editor.mt-2{ data: { tiptap_target: 'editor' } }
= hidden_field_tag field_name(:export_template, "tiptap_pj_#{pj.stable_id}"), "#{@export_template.content_for_pj(pj)}" , data: { tiptap_target: 'input' }
%ul.mt-2.flex.wrap.flex-gap-1
- @export_template.specific_tags.each do |tag|
%li.fr-badge.fr-badge--sm{ role: 'button', title: tag[:description], data: { action: 'click->tiptap#insertTag', tiptap_target: 'tag', tag_id: tag[:id], tag_label: tag[:libelle] } }
= tag[:libelle]
.fixed-footer
.fr-container
%ul.fr-btns-group.fr-btns-group--inline-md
%li
= f.submit "Enregistrer", class: "fr-btn"
%li
= link_to "Annuler", instructeur_procedure_path(@procedure), class: "fr-btn fr-btn--secondary"

View file

@ -0,0 +1,7 @@
= render partial: 'administrateurs/breadcrumbs',
locals: { steps: [[@procedure.libelle.truncate_words(10), instructeur_procedure_path(@procedure)],
[t('.title')]] }
.fr-container
%h1 Mise à jour modèle d'export
= render partial: 'form', locals: { form_url: instructeur_export_template_path(@procedure, @export_template), groupe_instructeurs: @groupe_instructeurs }

View file

@ -0,0 +1,6 @@
= render partial: 'administrateurs/breadcrumbs',
locals: { steps: [[@procedure.libelle.truncate_words(10), instructeur_procedure_path(@procedure)],
[t('.title')]] }
.fr-container
%h1 Nouveau modèle d'export
= render partial: 'form', locals: { form_url: instructeur_export_templates_path, groupe_instructeurs: @groupe_instructeurs }

View file

@ -0,0 +1,8 @@
fr:
instructeurs:
export_templates:
new:
title: Nouveau modèle d'export
edit:
title: Modèle d'export

View file

@ -450,6 +450,7 @@ Rails.application.routes.draw do
resources :procedures, only: [:index, :show], param: :procedure_id do resources :procedures, only: [:index, :show], param: :procedure_id do
member do member do
resources :archives, only: [:index, :create] resources :archives, only: [:index, :create]
resources :export_templates, only: [:new, :create, :edit, :update]
resources :groupes, only: [:index, :show], controller: 'groupe_instructeurs' do resources :groupes, only: [:index, :show], controller: 'groupe_instructeurs' do
resource :contact_information resource :contact_information

View file

@ -0,0 +1,120 @@
describe Instructeurs::ExportTemplatesController, type: :controller do
before { sign_in(instructeur.user) }
let(:tiptap_pdf_name) {
{
"type" => "doc",
"content" => [
{ "type" => "paragraph", "content" => [{ "text" => "mon_export_", "type" => "text" }, { "type" => "mention", "attrs" => { "id" => "dossier_number", "label" => "numéro du dossier" } }] }
]
}.to_json
}
let(:export_template_params) do
{
name: "coucou",
kind: "zip",
groupe_instructeur_id: groupe_instructeur.id,
tiptap_pdf_name: tiptap_pdf_name,
tiptap_default_dossier_directory: {
"type" => "doc",
"content" => [
{ "type" => "paragraph", "content" => [{ "text" => "DOSSIER_", "type" => "text" }, { "type" => "mention", "attrs" => { "id" => "dossier_number", "label" => "numéro du dossier" } }, { "text" => " ", "type" => "text" }] }
]
}.to_json,
"pjs" =>
[
{ path: { "type" => "doc", "content" => [{ "type" => "paragraph", "content" => [{ "type" => "mention", "attrs" => { "id" => "dossier_number", "label" => "numéro du dossier" } }, { "text" => " _justif", "type" => "text" }] }] }, stable_id: "3" },
{
path:
{ "type" => "doc", "content" => [{ "type" => "paragraph", "content" => [{ "text" => "cni_", "type" => "text" }, { "type" => "mention", "attrs" => { "id" => "dossier_number", "label" => "numéro du dossier" } }, { "text" => " ", "type" => "text" }] }] },
stable_id: "5"
},
{
path: { "type" => "doc", "content" => [{ "type" => "paragraph", "content" => [{ "text" => "pj_repet_", "type" => "text" }, { "type" => "mention", "attrs" => { "id" => "dossier_number", "label" => "numéro du dossier" } }, { "text" => " ", "type" => "text" }] }] },
stable_id: "10"
}
]
}
end
let(:instructeur) { create(:instructeur) }
let(:procedure) { create(:procedure, instructeurs: [instructeur]) }
let(:groupe_instructeur) { procedure.defaut_groupe_instructeur }
describe '#create' do
let(:subject) { post :create, params: { procedure_id: procedure.id, export_template: export_template_params } }
context 'with valid params' do
it 'redirect to some page' do
subject
expect(response).to redirect_to(exports_instructeur_procedure_path(procedure:))
expect(flash.notice).to eq "Le modèle d'export coucou a bien été créé"
end
end
context 'with invalid params' do
let(:tiptap_pdf_name) { { content: "invalid" }.to_json }
it 'display error notification' do
subject
expect(flash.alert).to be_present
end
end
context 'with procedure not accessible by current instructeur' do
let(:another_procedure) { create(:procedure) }
let(:subject) { post :create, params: { procedure_id: another_procedure.id, export_template: export_template_params } }
it 'raise exception' do
expect { subject }.to raise_error(ActiveRecord::RecordNotFound)
end
end
end
describe '#edit' do
let(:export_template) { create(:export_template, groupe_instructeur:) }
let(:subject) { get :edit, params: { procedure_id: procedure.id, id: export_template.id } }
it 'render edit' do
subject
expect(response).to render_template(:edit)
end
context "with export_template not accessible by current instructeur" do
let(:another_groupe_instructeur) { create(:groupe_instructeur) }
let(:export_template) { create(:export_template, groupe_instructeur: another_groupe_instructeur) }
it 'raise exception' do
expect { subject }.to raise_error(ActiveRecord::RecordNotFound)
end
end
end
describe '#update' do
let(:export_template) { create(:export_template, groupe_instructeur:) }
let(:tiptap_pdf_name) {
{
"type" => "doc",
"content" => [
{ "type" => "paragraph", "content" => [{ "text" => "exPort_", "type" => "text" }, { "type" => "mention", "attrs" => { "id" => "dossier_number", "label" => "numéro du dossier" } }] }
]
}.to_json
}
let(:subject) { put :update, params: { procedure_id: procedure.id, id: export_template.id, export_template: export_template_params } }
context 'with valid params' do
it 'redirect to some page' do
subject
expect(response).to redirect_to(exports_instructeur_procedure_path(procedure:))
expect(flash.notice).to eq "Le modèle d'export coucou a bien été modifié"
end
end
context 'with invalid params' do
let(:tiptap_pdf_name) { { content: "invalid" }.to_json }
it 'display error notification' do
subject
expect(flash.alert).to be_present
end
end
end
end