feat(dossier_submitted_message): add a new system to customize the standby page (/merci) after an user created his folder. this is a basic feature that will come with more options asap

wip(dossier_created_hook): add tile to administrateurs/procedure#show in order to crud dossier_created_hook

refactor(css.utilities): remove merge helpers.scss within utils.scss (same purpose). use scss each for spacer modifiers

refactor(dossiers/_merci.html): extract partial _merci so we can re-use it in preview of dossier_created_hook.

feat(wip): current progress
This commit is contained in:
Martin 2022-02-04 14:40:16 +01:00
parent 7c45589ae6
commit 85a588541b
20 changed files with 322 additions and 193 deletions

View file

@ -1,42 +0,0 @@
@import "constants";
.m-0 {
margin: 0px !important;
}
.mb-1 {
margin-bottom: $default-spacer;
}
.mr-1 {
margin-right: $default-spacer !important;
}
.mb-4 {
margin-bottom: 4 * $default-spacer !important;
}
.ml-1 {
margin-left: $default-spacer;
}
.pl-0 {
padding-left: 0px !important;
}
.p-0 {
padding: 0px !important;
}
.bold {
font-weight: bold;
}
.numbers-delimiter {
display: inline-block;
width: 5px;
}
.text-center {
text-align: center;
}

View file

@ -2,38 +2,8 @@
@import "common";
@import "constants";
.merci {
text-align: center;
margin-bottom: 60px;
.merci .monavis {
img {
margin-top: 4 * $default-padding;
}
h1 {
margin: (2 * $default-padding) 0;
}
b {
font-weight: bold;
}
.send {
margin-bottom: 2 * $default-padding;
font-size: 20px;
}
p {
margin: $default-padding;
}
a {
margin-top: 40px;
}
.monavis {
img {
margin-top: 2 * $default-padding;
}
margin-top: 2 * $default-padding;
}
}

View file

@ -1,6 +1,7 @@
@import "colors";
@import "constants";
// floats
.pull-left {
float: left;
}
@ -13,6 +14,9 @@
clear: both;
}
// text
.text-center,
.center {
text-align: center;
}
@ -21,12 +25,21 @@
text-align: right;
}
.hidden {
display: none;
.text-sm {
font-size: 14px;
}
.width-100 {
width: 100%;
.text-lg {
font-size: 18px;
}
.bold {
font-weight: bold;
}
.numbers-delimiter {
display: inline-block;
width: 5px;
}
.empty-text {
@ -45,95 +58,42 @@
}
}
// display
.hidden {
display: none;
}
// sizing
.width-100 {
width: 100%;
}
// who known
.highlighted {
background: $orange-bg;
color: $black;
}
.text-sm {
font-size: 14px;
}
// generate spacer utility like bootstrap my-2 -> margin-left/right: 2 * $default-spacer
// using $direction.key as css modifier, $direction.values to set css properties
// scale it using $steps
$directions: (
"t": ("margin-top"),
"r": ("margin-right"),
"b": ("margin-bottom"),
"l": ("margin-left"),
"x": ("margin-left", "margin-right"),
"y": ("margin-top", "margin-bottom"),
"": ("margin")
);
$steps: (0, 1, 2, 3, 4, 5, 6, 7, 8);
.text-lg {
font-size: 18px;
}
.mt-1 {
margin-top: $default-spacer;
}
.mt-2 {
margin-top: 2 * $default-spacer;
}
.mt-3 {
margin-top: 3 * $default-spacer;
}
.mt-4 {
margin-top: 4 * $default-spacer;
}
.mt-8 {
margin-top: 8 * $default-spacer;
}
.mb-1 {
margin-bottom: $default-spacer;
}
.mb-2 {
margin-bottom: 2 * $default-spacer;
}
.mb-3 {
margin-bottom: 3 * $default-spacer;
}
.mb-4 {
margin-bottom: 4 * $default-spacer;
}
.mb-8 {
margin-bottom: 8 * $default-spacer;
}
.pt-1 {
padding-top: $default-spacer;
}
.pt-2 {
padding-top: 2 * $default-spacer;
}
.pt-3 {
padding-top: 3 * $default-spacer;
}
.pt-4 {
padding-top: 4 * $default-spacer;
}
.pt-8 {
padding-top: 8 * $default-spacer;
}
.pb-1 {
padding-bottom: $default-spacer;
}
.pb-2 {
padding-bottom: 2 * $default-spacer;
}
.pb-3 {
padding-bottom: 3 * $default-spacer;
}
.pb-4 {
padding-bottom: 4 * $default-spacer;
}
.pb-8 {
padding-bottom: 8 * $default-spacer;
@each $modifier, $properties in $directions {
@each $step in $steps {
@each $property in $properties {
.m#{$modifier}-#{$step} {
#{$property}: $step * $default-spacer;
}
}
}
}

View file

@ -0,0 +1,45 @@
module Administrateurs
class DossierSubmittedMessagesController < AdministrateurController
before_action :retrieve_procedure
def edit
@dossier_submitted_message = build_dossier_submitted_message
end
def update
@dossier_submitted_message = build_dossier_submitted_message(dossier_submitted_message_params)
if @dossier_submitted_message.save
redirect_to admin_procedure_path(@procedure), flash: { notice: "Les informations de fin de dépot ont bien été sauvegardées." }
else
flash.alert = "Impossible de sauvegarder les informations de fin de dépot, veuillez ré-essayer."
render :edit, status: 400
end
end
def create
@dossier_submitted_message = build_dossier_submitted_message(dossier_submitted_message_params)
if @dossier_submitted_message.save
redirect_to admin_procedure_path(@procedure), flash: { notice: "Les informations de fin de dépot ont bien été sauvegardées." }
else
flash.alert = "Impossible de sauvegarder les informations de \"fin de dépot\", veuillez ré-essayer."
render :edit, status: 400
end
end
private
# for now, only works on active revision no matter the procedure_revision_policy
def build_dossier_submitted_message(attributes = {})
dossier_submitted_message = @procedure.active_revision.dossier_submitted_message || @procedure.active_revision.build_dossier_submitted_message(procedure_id: @procedure.id)
dossier_submitted_message.attributes = attributes unless attributes.empty?
dossier_submitted_message
end
def dossier_submitted_message_params
params.require(:dossier_submitted_message)
.permit(:message_on_submit_by_usager)
end
end
end

View file

@ -6,6 +6,7 @@
# data :jsonb
# fetch_external_data_exceptions :string is an Array
# private :boolean default(FALSE), not null
# rebased_at :datetime
# row :integer
# type :string
# value :string

View file

@ -0,0 +1,14 @@
# == Schema Information
#
# Table name: dossier_submitted_messages
#
# id :bigint not null, primary key
# message_on_submit_by_usager :string
# created_at :datetime not null
# updated_at :datetime not null
# procedure_id :bigint not null
#
class DossierSubmittedMessage < ApplicationRecord
belongs_to :procedure
has_many :revisions, class_name: 'ProcedureRevision', inverse_of: :dossier_submitted_message, dependent: :nullify
end

View file

@ -18,7 +18,6 @@
# description :string
# direction :string
# duree_conservation_dossiers_dans_ds :integer
# duree_conservation_dossiers_hors_ds :integer
# durees_conservation_required :boolean default(TRUE)
# encrypted_api_particulier_token :string
# euro_flag :boolean default(FALSE)
@ -80,6 +79,10 @@ class Procedure < ApplicationRecord
has_one :draft_attestation_template, through: :draft_revision, source: :attestation_template
has_one :published_attestation_template, through: :published_revision, source: :attestation_template
has_one :published_dossier_submitted_message, dependent: :destroy, through: :published_revision, source: :dossier_submitted_message
has_one :draft_dossier_submitted_message, dependent: :destroy, through: :draft_revision, source: :dossier_submitted_message
has_many :dossier_submitted_messages, through: :revisions, source: :dossier_submitted_message
has_many :experts_procedures, dependent: :destroy
has_many :experts, through: :experts_procedures
@ -92,6 +95,10 @@ class Procedure < ApplicationRecord
belongs_to :service, optional: true
belongs_to :zone, optional: true
def active_dossier_submitted_message
published_dossier_submitted_message || draft_dossier_submitted_message
end
def active_revision
brouillon? ? draft_revision : published_revision
end
@ -441,7 +448,8 @@ class Procedure < ApplicationRecord
revision_types_de_champ_private: {
type_de_champ: :types_de_champ
},
attestation_template: []
attestation_template: [],
dossier_submitted_message: []
}
}
include_list[:groupe_instructeurs] = :instructeurs if !is_different_admin

View file

@ -7,12 +7,14 @@
# created_at :datetime not null
# updated_at :datetime not null
# attestation_template_id :bigint
# procedure_id :bigint not null
# dossier_submitted_message_id :bigint
# procedure_id :bigint not null
#
class ProcedureRevision < ApplicationRecord
self.implicit_order_column = :created_at
belongs_to :procedure, -> { with_discarded }, inverse_of: :revisions, optional: false
belongs_to :attestation_template, inverse_of: :revisions, optional: true, dependent: :destroy
belongs_to :dossier_submitted_message, inverse_of: :revisions, optional: true, dependent: :destroy
has_many :dossiers, inverse_of: :revision, foreign_key: :revision_id

View file

@ -3,7 +3,7 @@
# Table name: zones
#
# id :bigint not null, primary key
# acronym :string
# acronym :string not null
# label :string
# created_at :datetime not null
# updated_at :datetime not null

View file

@ -0,0 +1,3 @@
= f.label :message_on_submit_by_usager do
Message affiché après l'envoie du dossier
= f.text_area :message_on_submit_by_usager, placeholder: "Merci votre dossier sera traité dans les plus bref delais"

View file

@ -0,0 +1,34 @@
- content_for(:root_class, 'scroll-margins-for-sticky-footer')
= render partial: 'administrateurs/breadcrumbs',
locals: { steps: [link_to('Démarches', admin_procedures_path),
link_to(@procedure.libelle, admin_procedure_path(@procedure)),
'Fin de dépot'] }
.procedure-form
.procedure-form__columns.container
= form_for @dossier_submitted_message,
url: url_for({ controller: 'administrateurs/dossier_submitted_messages', action: :update, id: @procedure.id }),
html: { class: 'form procedure-form__column--form' } do |f|
%h1.page-title
Fin du dépot
%p.notice
L'utilisateur se vera afficher ce message une fois le dossier envoyé
= render partial: 'administrateurs/dossier_submitted_messages/informations', locals: { f: f }
.procedure-form__actions
.actions-left
= f.submit 'Enregistrer', class: 'button primary send'
.procedure-form__column--preview
%h3
.procedure-form__preview-title
Aperçu
.notice
Cet aperçu est mis à jour après chaque sauvegarde.
.procedure-preview
= render partial: 'users/dossiers/merci', locals: { procedure: @procedure, dossier: nil}

View file

@ -234,3 +234,18 @@
%p.card-admin-title MonAvis
%p.card-admin-subtitle Avis des usagers sur votre démarche
%p.button Modifier
= link_to edit_admin_procedure_dossier_submitted_message_path(@procedure), class: 'card-admin' do
- if @procedure.active_dossier_submitted_message.present?
%div
%span.icon.accept
%p.card-admin-status-accept Validé
- else
%div
%span.icon.clock
%p.card-admin-status-todo À configurer
%div
%p.card-admin-title Fin de dépot
%p.card-admin-subtitle Orienter l'usager suite à l'envoie de son dossier
%p.button Modifier

View file

@ -0,0 +1,26 @@
.merci.text-center.mb-7
.container
= image_tag('user/envoi-dossier.svg', alt: '', class: 'mt-8')
%h1.mt-4.mb-3.mx-0= t('views.users.dossiers.merci.thanks')
%p.send.m-2.text-lg
= t('views.users.dossiers.merci.dossier_send_l1')
%strong= procedure.libelle
= t('views.users.dossiers.merci.dossier_send_l2')
%p.m-2
= t('views.users.dossiers.merci.dossier_acces_l1')
%strong= t('views.users.dossiers.merci.dossier_acces_l2')
%p.m-2
= t('views.users.dossiers.merci.dossier_edit_l1')
- if !dossier&.read_only?
%strong= t('views.users.dossiers.merci.dossier_edit_l2')
= t('views.users.dossiers.merci.dossier_edit_l3')
%strong= t('views.users.dossiers.merci.dossier_edit_l4')
- if procedure.active_dossier_submitted_message
%p.m-2= procedure.active_dossier_submitted_message.message_on_submit_by_usager
.flex.column.align-center
= link_to t('views.users.dossiers.merci.acces_dossier'), dossier ? dossier_path(dossier) : "#dossier" , class: 'button large primary mt-4'
= link_to t('views.users.dossiers.merci.submit_dossier'), procedure_lien(procedure), class: 'mt-4'
.monavis
!= procedure.monavis_embed

View file

@ -3,26 +3,4 @@
- content_for :footer do
= render partial: "users/procedure_footer", locals: { procedure: @dossier.procedure, dossier: @dossier }
.merci
.container
= image_tag('user/envoi-dossier.svg', alt: '')
%h1= t('views.users.dossiers.merci.thanks')
%p.send
= t('views.users.dossiers.merci.dossier_send_l1')
%b= @dossier.procedure.libelle
= t('views.users.dossiers.merci.dossier_send_l2')
%p
= t('views.users.dossiers.merci.dossier_acces_l1')
%b= t('views.users.dossiers.merci.dossier_acces_l2')
%p
= t('views.users.dossiers.merci.dossier_edit_l1')
- if !@dossier.read_only?
%b= t('views.users.dossiers.merci.dossier_edit_l2')
= t('views.users.dossiers.merci.dossier_edit_l3')
%b= t('views.users.dossiers.merci.dossier_edit_l4')
.flex.column.align-center
= link_to t('views.users.dossiers.merci.acces_dossier'), dossier_path(@dossier), class: 'button large primary'
= link_to t('views.users.dossiers.merci.submit_dossier'), procedure_lien(@dossier.procedure)
.monavis
!= @dossier.procedure.monavis_embed
= render partial: 'users/dossiers/merci', locals: { dossier: @dossier, procedure: @dossier.procedure}

View file

@ -466,6 +466,7 @@ Rails.application.routes.draw do
resource :attestation_template, only: [:edit, :update, :create] do
get 'preview', on: :member
end
resource :dossier_submitted_message, only: [:edit, :update, :create]
# ADDED TO ACCESS IT FROM THE IFRAME
get 'attestation_template/preview' => 'attestation_templates#preview'
end

View file

@ -0,0 +1,10 @@
class CreateDossierSubmittedMessages < ActiveRecord::Migration[6.1]
def change
create_table :dossier_submitted_messages do |t|
t.string :message_on_submit_by_usager
t.references :procedure, null: false, index: true
t.timestamps
end
add_reference :procedure_revisions, :dossier_submitted_message, foreign_key: { to_table: :dossier_submitted_messages }, null: true, index: true
end
end

View file

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2022_02_04_093401) do
ActiveRecord::Schema.define(version: 2022_02_04_130722) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -275,6 +275,14 @@ ActiveRecord::Schema.define(version: 2022_02_04_093401) do
t.index ["keep_until"], name: "index_dossier_operation_logs_on_keep_until"
end
create_table "dossier_submitted_messages", force: :cascade do |t|
t.string "message_on_submit_by_usager"
t.bigint "procedure_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["procedure_id"], name: "index_dossier_submitted_messages_on_procedure_id"
end
create_table "dossier_transfer_logs", force: :cascade do |t|
t.string "from", null: false
t.string "to", null: false
@ -324,10 +332,10 @@ ActiveRecord::Schema.define(version: 2022_02_04_093401) do
t.datetime "identity_updated_at"
t.datetime "depose_at"
t.datetime "hidden_by_user_at"
t.datetime "hidden_by_administration_at"
t.string "hidden_by_reason"
t.index "to_tsvector('french'::regconfig, (search_terms || private_search_terms))", name: "index_dossiers_on_search_terms_private_search_terms", using: :gin
t.index "to_tsvector('french'::regconfig, search_terms)", name: "index_dossiers_on_search_terms", using: :gin
t.datetime "hidden_by_administration_at"
t.index ["archived"], name: "index_dossiers_on_archived"
t.index ["dossier_transfer_id"], name: "index_dossiers_on_dossier_transfer_id"
t.index ["groupe_instructeur_id"], name: "index_dossiers_on_groupe_instructeur_id"
@ -594,8 +602,10 @@ ActiveRecord::Schema.define(version: 2022_02_04_093401) do
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "published_at"
t.bigint "dossier_submitted_message_id"
t.bigint "attestation_template_id"
t.index ["attestation_template_id"], name: "index_procedure_revisions_on_attestation_template_id"
t.index ["dossier_submitted_message_id"], name: "index_procedure_revisions_on_dossier_submitted_message_id"
t.index ["procedure_id"], name: "index_procedure_revisions_on_procedure_id"
end
@ -876,6 +886,7 @@ ActiveRecord::Schema.define(version: 2022_02_04_093401) do
add_foreign_key "procedure_revision_types_de_champ", "procedure_revisions", column: "revision_id"
add_foreign_key "procedure_revision_types_de_champ", "types_de_champ"
add_foreign_key "procedure_revisions", "attestation_templates"
add_foreign_key "procedure_revisions", "dossier_submitted_messages"
add_foreign_key "procedure_revisions", "procedures"
add_foreign_key "procedures", "procedure_revisions", column: "draft_revision_id"
add_foreign_key "procedures", "procedure_revisions", column: "published_revision_id"

View file

@ -0,0 +1,81 @@
include ActionDispatch::TestProcess
describe Administrateurs::DossierSubmittedMessagesController, type: :controller do
let(:administrateur) { create(:administrateur) }
before { sign_in(administrateur.user) }
describe '#create' do
context 'when procedure is not published' do
let(:procedure) { create(:procedure, administrateur: administrateur) }
it 'creates a DossierSubmittedMessage on draft_revision' do
message_on_submit_by_usager = "hello"
expect {
post(:create, params: { procedure_id: procedure.id, dossier_submitted_message: { message_on_submit_by_usager: message_on_submit_by_usager } })
}.to change { DossierSubmittedMessage.count }.by(1)
expect(response).to redirect_to admin_procedure_path(procedure)
expect(procedure.reload.draft_revision.dossier_submitted_message).to eq(DossierSubmittedMessage.first)
end
end
context 'when procedure is published' do
let(:procedure) { create(:procedure, :published, administrateur: administrateur) }
it 'creates a DossierSubmittedMessage on published_revision' do
message_on_submit_by_usager = "hello"
expect {
post(:create, params: { procedure_id: procedure.id, dossier_submitted_message: { message_on_submit_by_usager: message_on_submit_by_usager } })
}.to change { DossierSubmittedMessage.count }.by(1)
expect(response).to redirect_to admin_procedure_path(procedure)
expect(procedure.reload.published_revision.dossier_submitted_message).to eq(DossierSubmittedMessage.first)
end
end
end
describe '#edit' do
context 'when procedure is draft and have a DossierSubmittedMessage' do
let(:procedure) { create(:procedure, :with_dossier_submitted_message, administrateur: administrateur) }
it 'assigns the existing DossierSubmittedMessage' do
get(:edit, params: { procedure_id: procedure.id })
expect(response).to have_http_status(200)
expect(assigns(:dossier_submitted_message)).to eq(procedure.active_dossier_submitted_message)
end
end
context 'when draft procedure does not have dossier_submitted_message' do
let(:procedure) { create(:procedure, administrateur: administrateur) }
it 'builds a new DossierSubmittedMessage' do
get(:edit, params: { procedure_id: procedure.id })
expect(response).to have_http_status(200)
expect(assigns(:dossier_submitted_message).persisted?).to eq(false)
expect(assigns(:dossier_submitted_message)).to be_an_instance_of(DossierSubmittedMessage)
end
end
end
describe '#update' do
context 'when procedure is draft' do
let(:procedure) { create(:procedure, :with_dossier_submitted_message, administrateur: administrateur) }
it 'updates the existing DossierSubmittedMessage on draft_revision' do
new_message_on_submit_by_usager = "hello"
patch(:update, params: { procedure_id: procedure.id, dossier_submitted_message: { message_on_submit_by_usager: new_message_on_submit_by_usager } })
expect(response).to redirect_to admin_procedure_path(procedure)
expect(procedure.draft_revision.dossier_submitted_message.message_on_submit_by_usager).to eq(new_message_on_submit_by_usager)
end
end
context 'when draft procedure is published' do
let(:procedure) { create(:procedure, :published, :with_dossier_submitted_message, administrateur: administrateur) }
it 'updates the existing DossierSubmittedMessage on published_revision' do
new_message_on_submit_by_usager = "hello"
patch(:update, params: { procedure_id: procedure.id, dossier_submitted_message: { message_on_submit_by_usager: new_message_on_submit_by_usager } })
expect(response).to redirect_to admin_procedure_path(procedure)
expect(procedure.published_revision.dossier_submitted_message.message_on_submit_by_usager).to eq(new_message_on_submit_by_usager)
end
end
end
end

View file

@ -0,0 +1,5 @@
FactoryBot.define do
factory :dossier_submitted_message do
message_on_submit_by_usager { "BAM !" }
end
end

View file

@ -24,10 +24,11 @@ FactoryBot.define do
types_de_champ_private { [] }
updated_at { nil }
attestation_template { nil }
dossier_submitted_message { nil }
end
after(:build) do |procedure, evaluator|
initial_revision = build(:procedure_revision, procedure: procedure, attestation_template: evaluator.attestation_template)
initial_revision = build(:procedure_revision, procedure: procedure, attestation_template: evaluator.attestation_template, dossier_submitted_message: evaluator.dossier_submitted_message)
add_types_de_champs(evaluator.types_de_champ, to: initial_revision, scope: :public)
add_types_de_champs(evaluator.types_de_champ_private, to: initial_revision, scope: :private)
@ -319,6 +320,12 @@ FactoryBot.define do
end
end
end
trait :with_dossier_submitted_message do
after(:build) do |procedure, _evaluator|
build(:dossier_submitted_message, procedure: procedure, revisions: [procedure.active_revision])
end
end
end
end