Merge pull request #7657 from tchak/feat-validate-tags
feat(emails): validate tags in notification emails
This commit is contained in:
commit
55a2db2cb0
31 changed files with 437 additions and 65 deletions
|
@ -1,10 +1,12 @@
|
||||||
class Dsfr::CardVerticalComponent < ApplicationComponent
|
class Dsfr::CardVerticalComponent < ApplicationComponent
|
||||||
renders_many :footer_buttons
|
renders_many :footer_buttons
|
||||||
|
|
||||||
attr_reader :title, :desc
|
attr_reader :title, :desc, :tags, :error
|
||||||
|
|
||||||
def initialize(title: nil, desc: nil)
|
def initialize(title: nil, desc: nil, tags: nil, error: nil)
|
||||||
@title = title
|
@title = title
|
||||||
@desc = desc
|
@desc = desc
|
||||||
|
@tags = tags
|
||||||
|
@error = error
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,6 +7,16 @@
|
||||||
- if desc
|
- if desc
|
||||||
%p.fr-card__desc
|
%p.fr-card__desc
|
||||||
= desc
|
= desc
|
||||||
|
.fr-card__start
|
||||||
|
- if tags
|
||||||
|
%ul.fr-tags-group
|
||||||
|
- tags.each do |tag|
|
||||||
|
%li
|
||||||
|
%p.fr-tag=tag
|
||||||
|
.fr-card__end
|
||||||
|
- if error
|
||||||
|
.fr-card__detail.fr-alert.fr-alert--error
|
||||||
|
%p=error
|
||||||
|
|
||||||
- if footer_buttons?
|
- if footer_buttons?
|
||||||
.fr-card__footer
|
.fr-card__footer
|
||||||
|
|
|
@ -11,6 +11,9 @@ class Procedure::Card::ChampsComponent < ApplicationComponent
|
||||||
end
|
end
|
||||||
|
|
||||||
def error_messages
|
def error_messages
|
||||||
@procedure.errors.messages_for(:draft_types_de_champ).to_sentence
|
[
|
||||||
|
@procedure.errors.messages_for(:draft_types_de_champ),
|
||||||
|
@procedure.errors.messages_for(:draft_revision)
|
||||||
|
].flatten.to_sentence
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,4 +2,16 @@ class Procedure::Card::EmailsComponent < ApplicationComponent
|
||||||
def initialize(procedure:)
|
def initialize(procedure:)
|
||||||
@procedure = procedure
|
@procedure = procedure
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def error_messages
|
||||||
|
[
|
||||||
|
@procedure.errors.messages_for(:initiated_mail),
|
||||||
|
@procedure.errors.messages_for(:received_mail),
|
||||||
|
@procedure.errors.messages_for(:closed_mail),
|
||||||
|
@procedure.errors.messages_for(:refused_mail),
|
||||||
|
@procedure.errors.messages_for(:without_continuation_mail)
|
||||||
|
].flatten.to_sentence
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
= link_to admin_procedure_mail_templates_path(@procedure), class: 'fr-tile fr-enlarge-link' do
|
= link_to admin_procedure_mail_templates_path(@procedure), class: 'fr-tile fr-enlarge-link' do
|
||||||
.fr-tile__body.flex.justify-between
|
.fr-tile__body.flex.justify-between
|
||||||
%div
|
%div
|
||||||
|
- if error_messages.present?
|
||||||
|
%span.icon.refuse
|
||||||
|
%p.fr-tile-status-error À modifier
|
||||||
|
- else
|
||||||
%span.icon.clock
|
%span.icon.clock
|
||||||
%p.fr-tile-status-todo À configurer
|
%p.fr-tile-status-todo À configurer
|
||||||
%div
|
%div
|
||||||
|
|
35
app/components/procedure/email_template_card_component.rb
Normal file
35
app/components/procedure/email_template_card_component.rb
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
class Procedure::EmailTemplateCardComponent < ApplicationComponent
|
||||||
|
def initialize(email_template:)
|
||||||
|
@email_template = email_template
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def title
|
||||||
|
@email_template.class.const_get(:DISPLAYED_NAME)
|
||||||
|
end
|
||||||
|
|
||||||
|
def desc
|
||||||
|
@email_template.subject if edited?
|
||||||
|
end
|
||||||
|
|
||||||
|
def error
|
||||||
|
@email_template.errors.full_messages.first if @email_template.errors.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def tag
|
||||||
|
if edited?
|
||||||
|
"modifié le #{@email_template.updated_at.strftime('%d-%m-%Y')}"
|
||||||
|
else
|
||||||
|
"Modèle standard"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def edited?
|
||||||
|
@email_template.updated_at.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit_path
|
||||||
|
edit_admin_procedure_mail_template_path(@email_template.procedure, @email_template.class.const_get(:SLUG))
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,3 @@
|
||||||
|
= render Dsfr::CardVerticalComponent.new(title: title, desc: desc, error: error, tags: [tag]) do |c|
|
||||||
|
- c.with_footer_button do
|
||||||
|
= link_to 'Modifier', edit_path, class: 'fr-btn'
|
|
@ -4,34 +4,43 @@ module Administrateurs
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@mail_templates = mail_templates
|
@mail_templates = mail_templates
|
||||||
|
@mail_templates.each(&:validate)
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
@procedure = procedure
|
|
||||||
@mail_template = find_mail_template_by_slug(params[:id])
|
@mail_template = find_mail_template_by_slug(params[:id])
|
||||||
|
if !@mail_template.valid?
|
||||||
|
flash.now.alert = @mail_template.errors.full_messages
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
redirect_to edit_admin_procedure_mail_template_path(procedure.id, params[:id])
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@procedure = procedure
|
|
||||||
mail_template = find_mail_template_by_slug(params[:id])
|
mail_template = find_mail_template_by_slug(params[:id])
|
||||||
|
|
||||||
if mail_template.update(update_params)
|
if mail_template.update(update_params)
|
||||||
flash.notice = "Email mis à jour"
|
flash.notice = "Email mis à jour"
|
||||||
else
|
|
||||||
flash.alert = mail_template.errors.full_messages
|
|
||||||
end
|
|
||||||
|
|
||||||
redirect_to edit_admin_procedure_mail_template_path(mail_template.procedure_id, params[:id])
|
redirect_to edit_admin_procedure_mail_template_path(mail_template.procedure_id, params[:id])
|
||||||
|
else
|
||||||
|
flash.now.alert = mail_template.errors.full_messages
|
||||||
|
mail_template.rich_body = mail_template.body
|
||||||
|
|
||||||
|
@mail_template = mail_template
|
||||||
|
render :edit
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def preview
|
def preview
|
||||||
mail_template = find_mail_template_by_slug(params[:id])
|
mail_template = find_mail_template_by_slug(params[:id])
|
||||||
dossier = Dossier.new(id: '1', procedure: procedure)
|
dossier = procedure.active_revision.dossier_for_preview(current_user)
|
||||||
|
|
||||||
@dossier = dossier
|
@dossier = dossier
|
||||||
@logo_url = procedure.logo_url
|
@logo_url = procedure.logo_url
|
||||||
@service = procedure.service
|
@service = procedure.service
|
||||||
@rendered_template = sanitize(mail_template.rich_body.body.to_html)
|
@rendered_template = sanitize(mail_template.body_for_dossier(dossier))
|
||||||
@actions = mail_template.actions_for_dossier(dossier)
|
@actions = mail_template.actions_for_dossier(dossier)
|
||||||
|
|
||||||
render(template: 'notification_mailer/send_notification', layout: 'mailers/notifications_layout')
|
render(template: 'notification_mailer/send_notification', layout: 'mailers/notifications_layout')
|
||||||
|
|
|
@ -181,7 +181,7 @@ module TagsSubstitutionConcern
|
||||||
{
|
{
|
||||||
libelle: 'groupe instructeur',
|
libelle: 'groupe instructeur',
|
||||||
description: 'Le groupe instructeur en charge du dossier',
|
description: 'Le groupe instructeur en charge du dossier',
|
||||||
lambda: -> (d) { d.groupe_instructeur.label },
|
lambda: -> (d) { d.groupe_instructeur&.label },
|
||||||
available_for_states: Dossier::SOUMIS
|
available_for_states: Dossier::SOUMIS
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -15,6 +15,9 @@ module Mails
|
||||||
|
|
||||||
belongs_to :procedure, optional: false
|
belongs_to :procedure, optional: false
|
||||||
|
|
||||||
|
validates :subject, tags: true
|
||||||
|
validates :body, tags: true
|
||||||
|
|
||||||
SLUG = "closed_mail"
|
SLUG = "closed_mail"
|
||||||
DISPLAYED_NAME = "Accusé d’acceptation"
|
DISPLAYED_NAME = "Accusé d’acceptation"
|
||||||
DEFAULT_SUBJECT = 'Votre dossier nº --numéro du dossier-- a été accepté (--libellé démarche--)'
|
DEFAULT_SUBJECT = 'Votre dossier nº --numéro du dossier-- a été accepté (--libellé démarche--)'
|
||||||
|
|
|
@ -15,6 +15,9 @@ module Mails
|
||||||
|
|
||||||
belongs_to :procedure, optional: false
|
belongs_to :procedure, optional: false
|
||||||
|
|
||||||
|
validates :subject, tags: true
|
||||||
|
validates :body, tags: true
|
||||||
|
|
||||||
SLUG = "initiated_mail"
|
SLUG = "initiated_mail"
|
||||||
DEFAULT_TEMPLATE_NAME = "notification_mailer/default_templates/initiated_mail"
|
DEFAULT_TEMPLATE_NAME = "notification_mailer/default_templates/initiated_mail"
|
||||||
DISPLAYED_NAME = I18n.t('activerecord.models.mail.initiated_mail.proof_of_receipt')
|
DISPLAYED_NAME = I18n.t('activerecord.models.mail.initiated_mail.proof_of_receipt')
|
||||||
|
|
|
@ -15,6 +15,9 @@ module Mails
|
||||||
|
|
||||||
belongs_to :procedure, optional: false
|
belongs_to :procedure, optional: false
|
||||||
|
|
||||||
|
validates :subject, tags: true
|
||||||
|
validates :body, tags: true
|
||||||
|
|
||||||
SLUG = "received_mail"
|
SLUG = "received_mail"
|
||||||
DEFAULT_TEMPLATE_NAME = "notification_mailer/default_templates/received_mail"
|
DEFAULT_TEMPLATE_NAME = "notification_mailer/default_templates/received_mail"
|
||||||
DISPLAYED_NAME = I18n.t('activerecord.models.mail.received_mail.under_instruction')
|
DISPLAYED_NAME = I18n.t('activerecord.models.mail.received_mail.under_instruction')
|
||||||
|
|
|
@ -15,6 +15,9 @@ module Mails
|
||||||
|
|
||||||
belongs_to :procedure, optional: false
|
belongs_to :procedure, optional: false
|
||||||
|
|
||||||
|
validates :subject, tags: true
|
||||||
|
validates :body, tags: true
|
||||||
|
|
||||||
SLUG = "refused_mail"
|
SLUG = "refused_mail"
|
||||||
DEFAULT_TEMPLATE_NAME = "notification_mailer/default_templates/refused_mail"
|
DEFAULT_TEMPLATE_NAME = "notification_mailer/default_templates/refused_mail"
|
||||||
DISPLAYED_NAME = 'Accusé de rejet du dossier'
|
DISPLAYED_NAME = 'Accusé de rejet du dossier'
|
||||||
|
|
|
@ -15,6 +15,9 @@ module Mails
|
||||||
|
|
||||||
belongs_to :procedure, optional: false
|
belongs_to :procedure, optional: false
|
||||||
|
|
||||||
|
validates :subject, tags: true
|
||||||
|
validates :body, tags: true
|
||||||
|
|
||||||
SLUG = "without_continuation"
|
SLUG = "without_continuation"
|
||||||
DEFAULT_TEMPLATE_NAME = "notification_mailer/default_templates/without_continuation_mail"
|
DEFAULT_TEMPLATE_NAME = "notification_mailer/default_templates/without_continuation_mail"
|
||||||
DISPLAYED_NAME = 'Accusé de classement sans suite'
|
DISPLAYED_NAME = 'Accusé de classement sans suite'
|
||||||
|
|
|
@ -181,6 +181,14 @@ class Procedure < ApplicationRecord
|
||||||
types_de_champ_for_tags.private_only
|
types_de_champ_for_tags.private_only
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def revision_ids_with_pending_dossiers
|
||||||
|
dossiers
|
||||||
|
.where.not(revision_id: [draft_revision_id, published_revision_id].compact)
|
||||||
|
.state_en_construction_ou_instruction
|
||||||
|
.distinct(:revision_id)
|
||||||
|
.pluck(:revision_id)
|
||||||
|
end
|
||||||
|
|
||||||
has_many :administrateurs_procedures, dependent: :delete_all
|
has_many :administrateurs_procedures, dependent: :delete_all
|
||||||
has_many :administrateurs, through: :administrateurs_procedures, after_remove: -> (procedure, _admin) { procedure.validate! }
|
has_many :administrateurs, through: :administrateurs_procedures, after_remove: -> (procedure, _admin) { procedure.validate! }
|
||||||
has_many :groupe_instructeurs, dependent: :destroy
|
has_many :groupe_instructeurs, dependent: :destroy
|
||||||
|
@ -264,11 +272,11 @@ class Procedure < ApplicationRecord
|
||||||
validates :draft_types_de_champ,
|
validates :draft_types_de_champ,
|
||||||
'types_de_champ/no_empty_block': true,
|
'types_de_champ/no_empty_block': true,
|
||||||
'types_de_champ/no_empty_drop_down': true,
|
'types_de_champ/no_empty_drop_down': true,
|
||||||
if: :validate_for_publication?
|
on: :publication
|
||||||
validates :draft_types_de_champ_private,
|
validates :draft_types_de_champ_private,
|
||||||
'types_de_champ/no_empty_block': true,
|
'types_de_champ/no_empty_block': true,
|
||||||
'types_de_champ/no_empty_drop_down': true,
|
'types_de_champ/no_empty_drop_down': true,
|
||||||
if: :validate_for_publication?
|
on: :publication
|
||||||
validate :check_juridique
|
validate :check_juridique
|
||||||
validates :path, presence: true, format: { with: /\A[a-z0-9_\-]{3,200}\z/ }, uniqueness: { scope: [:path, :closed_at, :hidden_at, :unpublished_at], case_sensitive: false }
|
validates :path, presence: true, format: { with: /\A[a-z0-9_\-]{3,200}\z/ }, uniqueness: { scope: [:path, :closed_at, :hidden_at, :unpublished_at], case_sensitive: false }
|
||||||
validates :duree_conservation_dossiers_dans_ds, allow_nil: false,
|
validates :duree_conservation_dossiers_dans_ds, allow_nil: false,
|
||||||
|
@ -287,6 +295,13 @@ class Procedure < ApplicationRecord
|
||||||
validates :lien_dpo, email_or_link: true, allow_nil: true
|
validates :lien_dpo, email_or_link: true, allow_nil: true
|
||||||
validates_with MonAvisEmbedValidator
|
validates_with MonAvisEmbedValidator
|
||||||
|
|
||||||
|
validates_associated :draft_revision, on: :publication
|
||||||
|
validates_associated :initiated_mail, on: :publication
|
||||||
|
validates_associated :received_mail, on: :publication
|
||||||
|
validates_associated :closed_mail, on: :publication
|
||||||
|
validates_associated :refused_mail, on: :publication
|
||||||
|
validates_associated :without_continuation_mail, on: :publication
|
||||||
|
|
||||||
FILE_MAX_SIZE = 20.megabytes
|
FILE_MAX_SIZE = 20.megabytes
|
||||||
validates :notice, content_type: [
|
validates :notice, content_type: [
|
||||||
"application/msword",
|
"application/msword",
|
||||||
|
@ -790,8 +805,12 @@ class Procedure < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def publish_revision!
|
def publish_revision!
|
||||||
update!(draft_revision: create_new_revision, published_revision: draft_revision)
|
transaction do
|
||||||
|
self.published_revision = draft_revision
|
||||||
|
self.draft_revision = create_new_revision
|
||||||
|
save!(context: :publication)
|
||||||
published_revision.touch(:published_at)
|
published_revision.touch(:published_at)
|
||||||
|
end
|
||||||
dossiers
|
dossiers
|
||||||
.state_not_termine
|
.state_not_termine
|
||||||
.find_each { |dossier| DossierRebaseJob.perform_later(dossier) }
|
.find_each { |dossier| DossierRebaseJob.perform_later(dossier) }
|
||||||
|
@ -851,16 +870,15 @@ class Procedure < ApplicationRecord
|
||||||
new_draft.revision_types_de_champ.reload
|
new_draft.revision_types_de_champ.reload
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_for_publication?
|
|
||||||
validation_context == :publication || publiee?
|
|
||||||
end
|
|
||||||
|
|
||||||
def before_publish
|
def before_publish
|
||||||
assign_attributes(closed_at: nil, unpublished_at: nil)
|
assign_attributes(closed_at: nil, unpublished_at: nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
def after_publish(canonical_procedure = nil)
|
def after_publish(canonical_procedure = nil)
|
||||||
update!(canonical_procedure: canonical_procedure, draft_revision: create_new_revision, published_revision: draft_revision)
|
self.canonical_procedure = canonical_procedure
|
||||||
|
self.published_revision = draft_revision
|
||||||
|
self.draft_revision = create_new_revision
|
||||||
|
save!(context: :publication)
|
||||||
touch(:published_at)
|
touch(:published_at)
|
||||||
published_revision.touch(:published_at)
|
published_revision.touch(:published_at)
|
||||||
end
|
end
|
||||||
|
|
64
app/validators/tags_validator.rb
Normal file
64
app/validators/tags_validator.rb
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
class TagsValidator < ActiveModel::EachValidator
|
||||||
|
def validate_each(record, attribute, value)
|
||||||
|
procedure = record.procedure
|
||||||
|
tags = record.used_type_de_champ_tags(value || '')
|
||||||
|
|
||||||
|
invalid_tags = tags.filter_map do |(tag, stable_id)|
|
||||||
|
tag if stable_id.nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
invalid_for_draft_revision = invalid_tags_for_revision(record, attribute, tags, procedure.draft_revision_id)
|
||||||
|
|
||||||
|
invalid_for_published_revision = if procedure.published_revision_id.present?
|
||||||
|
invalid_tags_for_revision(record, attribute, tags, procedure.published_revision_id)
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
|
||||||
|
invalid_for_previous_revision = procedure
|
||||||
|
.revision_ids_with_pending_dossiers
|
||||||
|
.flat_map do |revision_id|
|
||||||
|
invalid_tags_for_revision(record, attribute, tags, revision_id)
|
||||||
|
end.uniq
|
||||||
|
|
||||||
|
# champ is added in draft revision but not yet published
|
||||||
|
champ_missing_in_published_revision = (invalid_for_published_revision - invalid_for_draft_revision)
|
||||||
|
add_errors(record, attribute, :champ_missing_in_published_revision, champ_missing_in_published_revision)
|
||||||
|
|
||||||
|
# champ is removed but the removal is not yet published
|
||||||
|
champ_missing_in_draft_revision = (invalid_for_draft_revision - invalid_for_published_revision)
|
||||||
|
add_errors(record, attribute, :champ_missing_in_draft_revision, champ_missing_in_draft_revision)
|
||||||
|
|
||||||
|
# champ is removed and the removal is published
|
||||||
|
champ_missing_in_published_and_draft_revision = invalid_for_published_revision.intersection(invalid_for_draft_revision)
|
||||||
|
add_errors(record, attribute, :champ_missing_in_published_and_draft_revision, champ_missing_in_published_and_draft_revision)
|
||||||
|
|
||||||
|
# champ is missing from one of the revisions in pending dossiers
|
||||||
|
add_errors(record, attribute, :champ_missing_in_previous_revision, invalid_for_previous_revision)
|
||||||
|
|
||||||
|
# unknown champ
|
||||||
|
add_errors(record, attribute, :champ_missing, invalid_tags)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def add_errors(record, attribute, message, tags)
|
||||||
|
tags.each do |tag|
|
||||||
|
record.errors.add(attribute, message, tag: tag)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def invalid_tags_for_revision(record, attribute, tags, revision_id)
|
||||||
|
revision_stable_ids = TypeDeChamp
|
||||||
|
.joins(:revision_types_de_champ)
|
||||||
|
.where(procedure_revision_types_de_champ: { revision_id: revision_id, parent_id: nil })
|
||||||
|
.distinct(:stable_id)
|
||||||
|
.pluck(:stable_id)
|
||||||
|
|
||||||
|
tags.filter_map do |(tag, stable_id)|
|
||||||
|
if stable_id.present? && !stable_id.in?(revision_stable_ids)
|
||||||
|
tag
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -17,7 +17,7 @@
|
||||||
.tag Balise
|
.tag Balise
|
||||||
.description Description
|
.description Description
|
||||||
.items
|
.items
|
||||||
- @mail_template.tags.each do |tag|
|
- tags.each do |tag|
|
||||||
.item
|
.item
|
||||||
%code.tag
|
%code.tag
|
||||||
= "--#{tag[:libelle]}--"
|
= "--#{tag[:libelle]}--"
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
= render partial: 'administrateurs/breadcrumbs',
|
= render partial: 'administrateurs/breadcrumbs',
|
||||||
locals: { steps: [['Démarches', admin_procedures_path],
|
locals: { steps: [['Démarches', admin_procedures_path],
|
||||||
[@procedure.libelle.truncate_words(10), admin_procedure_path(@procedure)],
|
[@procedure.libelle.truncate_words(10), admin_procedure_path(@procedure)],
|
||||||
["Emails", admin_procedure_mail_templates_path(@procedure)],
|
["Configuration des emails", admin_procedure_mail_templates_path(@procedure)],
|
||||||
[@mail_template.class.const_get(:DISPLAYED_NAME)]] }
|
[@mail_template.class.const_get(:DISPLAYED_NAME)]] }
|
||||||
|
|
||||||
.procedure-form
|
.procedure-form
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
html: { class: 'form procedure-form__column--form' } do |f|
|
html: { class: 'form procedure-form__column--form' } do |f|
|
||||||
|
|
||||||
%h1.page-title= @mail_template.class.const_get(:DISPLAYED_NAME)
|
%h1.page-title= @mail_template.class.const_get(:DISPLAYED_NAME)
|
||||||
= render partial: 'form', locals: { f: f }
|
= render partial: 'form', locals: { f: f, tags: @mail_template.tags }
|
||||||
.procedure-form__actions.sticky--bottom
|
.procedure-form__actions.sticky--bottom
|
||||||
.actions-right
|
.actions-right
|
||||||
= f.submit 'Enregistrer', class: 'button primary send'
|
= f.submit 'Enregistrer', class: 'button primary send'
|
||||||
|
@ -30,4 +30,4 @@
|
||||||
.notice
|
.notice
|
||||||
Cet aperçu est mis à jour après chaque sauvegarde.
|
Cet aperçu est mis à jour après chaque sauvegarde.
|
||||||
.procedure-preview
|
.procedure-preview
|
||||||
= render partial: 'apercu', locals: { procedure: @procedure }
|
= render partial: 'apercu', locals: { procedure: @mail_template.procedure }
|
||||||
|
|
|
@ -4,15 +4,7 @@
|
||||||
["Configuration des emails"]] }
|
["Configuration des emails"]] }
|
||||||
|
|
||||||
.container
|
.container
|
||||||
|
.fr-grid-row.fr-grid-row--gutters.fr-py-5w
|
||||||
- @mail_templates.each do |mail_template|
|
- @mail_templates.each do |mail_template|
|
||||||
.card
|
.fr-col-md-6.fr-col-12
|
||||||
.flex.justify-between
|
= render Procedure::EmailTemplateCardComponent.new(email_template: mail_template)
|
||||||
%div
|
|
||||||
.card-title= mail_template.class.const_get(:DISPLAYED_NAME)
|
|
||||||
- if mail_template.updated_at.blank?
|
|
||||||
%p.notice= mail_template.class.const_get(:DISPLAYED_NAME) === 'Accusé de réception' ? 'Personnalisé' : 'Modèle standard'
|
|
||||||
- else
|
|
||||||
%span.badge.baseline modifié le #{mail_template.updated_at.strftime('%d-%m-%Y')}
|
|
||||||
|
|
||||||
%div
|
|
||||||
= link_to 'Modifier', edit_admin_procedure_mail_template_path(@procedure, mail_template.class.const_get(:SLUG)), class: 'fr-btn'
|
|
||||||
|
|
|
@ -22,4 +22,4 @@
|
||||||
= render partial: 'publication_form_inputs', locals: { procedure: procedure, closed_procedures: @closed_procedures }
|
= render partial: 'publication_form_inputs', locals: { procedure: procedure, closed_procedures: @closed_procedures }
|
||||||
|
|
||||||
.flex.justify-end
|
.flex.justify-end
|
||||||
= submit_tag procedure_publish_label(procedure, :submit), { disabled: publication_errors.present?, class: "button primary", id: 'publish' }
|
= submit_tag procedure_publish_label(procedure, :submit), { disabled: publication_errors.present?, class: "fr-btn fr-btn--primary", id: 'publish' }
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
.container
|
.container
|
||||||
= render TypesDeChampEditor::ErrorsSummary.new(revision: @procedure.draft_revision)
|
= render TypesDeChampEditor::ErrorsSummary.new(revision: @procedure.draft_revision)
|
||||||
|
|
||||||
- if @procedure.draft_changed? && @procedure.draft_revision.valid?
|
- if @procedure.draft_changed?
|
||||||
.container
|
.container
|
||||||
.card.featured
|
.card.featured
|
||||||
.card-title
|
.card-title
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
= render partial: 'revision_changes', locals: { changes: @procedure.revision_changes }
|
= render partial: 'revision_changes', locals: { changes: @procedure.revision_changes }
|
||||||
.flex.mt-2.justify-end
|
.flex.mt-2.justify-end
|
||||||
= button_to "Réinitialiser les modifications", admin_procedure_reset_draft_path(@procedure), class: 'fr-btn fr-btn--secondary fr-mr-2w', method: :put
|
= button_to "Réinitialiser les modifications", admin_procedure_reset_draft_path(@procedure), class: 'fr-btn fr-btn--secondary fr-mr-2w', method: :put
|
||||||
= link_to 'Publier les modifications', admin_procedure_publication_path(@procedure), class: 'fr-btn', id: 'publish-procedure-link', data: { disable_with: "Publication..." }
|
= button_to 'Publier les modifications', admin_procedure_publication_path(@procedure), class: 'fr-btn', id: 'publish-procedure-link', data: { disable_with: "Publication..." }, disabled: !@procedure.draft_revision.valid?, method: :get
|
||||||
|
|
||||||
- if !@procedure.procedure_expires_when_termine_enabled?
|
- if !@procedure.procedure_expires_when_termine_enabled?
|
||||||
= render partial: 'administrateurs/procedures/suggest_expires_when_termine', locals: { procedure: @procedure }
|
= render partial: 'administrateurs/procedures/suggest_expires_when_termine', locals: { procedure: @procedure }
|
||||||
|
|
20
config/locales/models/attestation_template/fr.yml
Normal file
20
config/locales/models/attestation_template/fr.yml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
fr:
|
||||||
|
activerecord:
|
||||||
|
errors:
|
||||||
|
models:
|
||||||
|
attestation_template:
|
||||||
|
attributes:
|
||||||
|
title:
|
||||||
|
format: Le titre du modèle de l’attestation %{message}
|
||||||
|
champ_missing: réfère au champ "%{tag}" qui n’existe pas
|
||||||
|
champ_missing_in_draft_revision: réfère au champ "%{tag}" qui à été supprimé mais la suppression n’est pas encore publiée
|
||||||
|
champ_missing_in_published_revision: réfère au champ "%{tag}" qui n’est pas encore publié
|
||||||
|
champ_missing_in_published_and_draft_revision: réfère au champ "%{tag}" qui a été supprimé
|
||||||
|
champ_missing_in_previous_revision: réfère au champ "%{tag}" qui n’existe pas sur un des dossiers en cours de traitement
|
||||||
|
body:
|
||||||
|
format: Le contenu du modèle de l’attestation %{message}
|
||||||
|
champ_missing: réfère au champ "%{tag}" qui n’existe pas
|
||||||
|
champ_missing_in_draft_revision: réfère au champ "%{tag}" qui a été supprimé mais la suppression n’est pas encore publiée
|
||||||
|
champ_missing_in_published_revision: réfère au champ "%{tag}" qui n’est pas encore publié
|
||||||
|
champ_missing_in_published_and_draft_revision: réfère au champ "%{tag}" qui a été supprimé
|
||||||
|
champ_missing_in_previous_revision: réfère au champ "%{tag}" qui n’existe pas sur un des dossiers en cours de traitement
|
20
config/locales/models/closed_mail/fr.yml
Normal file
20
config/locales/models/closed_mail/fr.yml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
fr:
|
||||||
|
activerecord:
|
||||||
|
errors:
|
||||||
|
models:
|
||||||
|
mails/closed_mail:
|
||||||
|
attributes:
|
||||||
|
subject:
|
||||||
|
format: Le titre de l’email de notification d’acceptation de dossier %{message}
|
||||||
|
champ_missing: réfère au champ "%{tag}" qui n’existe pas
|
||||||
|
champ_missing_in_draft_revision: réfère au champ "%{tag}" qui a été supprimé mais la suppression n’est pas encore publiée
|
||||||
|
champ_missing_in_published_revision: réfère au champ "%{tag}" qui n’est pas encore publié
|
||||||
|
champ_missing_in_published_and_draft_revision: réfère au champ "%{tag}" qui a été supprimé
|
||||||
|
champ_missing_in_previous_revision: réfère au champ "%{tag}" qui n’existe pas sur un des dossiers en cours de traitement
|
||||||
|
body:
|
||||||
|
format: Le contenu de l’email de notification d’acceptation de dossier %{message}
|
||||||
|
champ_missing: réfère au champ "%{tag}" qui n’existe pas
|
||||||
|
champ_missing_in_draft_revision: réfère au champ "%{tag}" qui a été supprimé mais la suppression n’est pas encore publiée
|
||||||
|
champ_missing_in_published_revision: réfère au champ "%{tag}" qui n’est pas encore publié
|
||||||
|
champ_missing_in_published_and_draft_revision: réfère au champ "%{tag}" qui a été supprimé
|
||||||
|
champ_missing_in_previous_revision: réfère au champ "%{tag}" qui n’existe pas sur un des dossiers en cours de traitement
|
20
config/locales/models/initiated_mail/fr.yml
Normal file
20
config/locales/models/initiated_mail/fr.yml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
fr:
|
||||||
|
activerecord:
|
||||||
|
errors:
|
||||||
|
models:
|
||||||
|
mails/initiated_mail:
|
||||||
|
attributes:
|
||||||
|
subject:
|
||||||
|
format: Le titre de l’email de notification de passage du dossier en instruction %{message}
|
||||||
|
champ_missing: réfère au champ "%{tag}" qui n’existe pas
|
||||||
|
champ_missing_in_draft_revision: réfère au champ "%{tag}" qui a été supprimé mais la suppression n’est pas encore publiée
|
||||||
|
champ_missing_in_published_revision: réfère au champ "%{tag}" qui n’est pas encore publié
|
||||||
|
champ_missing_in_published_and_draft_revision: réfère au champ "%{tag}" qui a été supprimé
|
||||||
|
champ_missing_in_previous_revision: réfère au champ "%{tag}" qui n’existe pas sur un des dossiers en cours de traitement
|
||||||
|
body:
|
||||||
|
format: Le contenu de l’email de notification de passage du dossier en instruction %{message}
|
||||||
|
champ_missing: réfère au champ "%{tag}" qui n’existe pas
|
||||||
|
champ_missing_in_draft_revision: réfère au champ "%{tag}" qui a été supprimé mais la suppression n’est pas encore publiée
|
||||||
|
champ_missing_in_published_revision: réfère au champ "%{tag}" qui n’est pas encore publié
|
||||||
|
champ_missing_in_published_and_draft_revision: réfère au champ "%{tag}" qui a été supprimé
|
||||||
|
champ_missing_in_previous_revision: réfère au champ "%{tag}" qui n’existe pas sur un des dossiers en cours de traitement
|
20
config/locales/models/received_mail/fr.yml
Normal file
20
config/locales/models/received_mail/fr.yml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
fr:
|
||||||
|
activerecord:
|
||||||
|
errors:
|
||||||
|
models:
|
||||||
|
mails/received_mail:
|
||||||
|
attributes:
|
||||||
|
subject:
|
||||||
|
format: Le titre de l’email de notification de dépot de dossier %{message}
|
||||||
|
champ_missing: réfère au champ "%{tag}" qui n’existe pas
|
||||||
|
champ_missing_in_draft_revision: réfère au champ "%{tag}" qui a été supprimé mais la suppression n’est pas encore publiée
|
||||||
|
champ_missing_in_published_revision: réfère au champ "%{tag}" qui n’est pas encore publié
|
||||||
|
champ_missing_in_published_and_draft_revision: réfère au champ "%{tag}" qui a été supprimé
|
||||||
|
champ_missing_in_previous_revision: réfère au champ "%{tag}" qui n’existe pas sur un des dossiers en cours de traitement
|
||||||
|
body:
|
||||||
|
format: Le contenu de l’email de notification de dépot de dossier %{message}
|
||||||
|
champ_missing: réfère au champ "%{tag}" qui n’existe pas
|
||||||
|
champ_missing_in_draft_revision: réfère au champ "%{tag}" qui a été supprimé mais la suppression n’est pas encore publiée
|
||||||
|
champ_missing_in_published_revision: réfère au champ "%{tag}" qui n’est pas encore publié
|
||||||
|
champ_missing_in_published_and_draft_revision: réfère au champ "%{tag}" qui a été supprimé
|
||||||
|
champ_missing_in_previous_revision: réfère au champ "%{tag}" qui n’existe pas sur un des dossiers en cours de traitement
|
20
config/locales/models/refused_mail/fr.yml
Normal file
20
config/locales/models/refused_mail/fr.yml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
fr:
|
||||||
|
activerecord:
|
||||||
|
errors:
|
||||||
|
models:
|
||||||
|
mails/refused_mail:
|
||||||
|
attributes:
|
||||||
|
subject:
|
||||||
|
format: Le titre de l’email de notification de refus de dossier %{message}
|
||||||
|
champ_missing: réfère au champ "%{tag}" qui n’existe pas
|
||||||
|
champ_missing_in_draft_revision: réfère au champ "%{tag}" qui a été supprimé mais la suppression n’est pas encore publiée
|
||||||
|
champ_missing_in_published_revision: réfère au champ "%{tag}" qui n’est pas encore publié
|
||||||
|
champ_missing_in_published_and_draft_revision: réfère au champ "%{tag}" qui a été supprimé
|
||||||
|
champ_missing_in_previous_revision: réfère au champ "%{tag}" qui n’existe pas sur un des dossiers en cours de traitement
|
||||||
|
body:
|
||||||
|
format: Le contenu de l’email de notification de refus de dossier %{message}
|
||||||
|
champ_missing: réfère au champ "%{tag}" qui n’existe pas
|
||||||
|
champ_missing_in_draft_revision: réfère au champ "%{tag}" qui a été supprimé mais la suppression n’est pas encore publiée
|
||||||
|
champ_missing_in_published_revision: réfère au champ "%{tag}" qui n’est pas encore publiée
|
||||||
|
champ_missing_in_published_and_draft_revision: réfère au champ "%{tag}" qui a été supprimé
|
||||||
|
champ_missing_in_previous_revision: réfère au champ "%{tag}" qui n’existe pas sur un des dossiers en cours de traitement
|
20
config/locales/models/without_continuation_mail/fr.yml
Normal file
20
config/locales/models/without_continuation_mail/fr.yml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
fr:
|
||||||
|
activerecord:
|
||||||
|
errors:
|
||||||
|
models:
|
||||||
|
mails/without_continuation_mail:
|
||||||
|
attributes:
|
||||||
|
subject:
|
||||||
|
format: Le titre de l’email de notification de classement sans suite de dossier %{message}
|
||||||
|
champ_missing: réfère au champ "%{tag}" qui n’existe pas
|
||||||
|
champ_missing_in_draft_revision: réfère au champ "%{tag}" qui a été supprimé mais la suppression n’est pas encore publiée
|
||||||
|
champ_missing_in_published_revision: réfère au champ "%{tag}" qui n’est pas encore publié
|
||||||
|
champ_missing_in_published_and_draft_revision: réfère au champ "%{tag}" qui a été supprimé
|
||||||
|
champ_missing_in_previous_revision: réfère au champ "%{tag}" qui n’existe pas sur un des dossiers en cours de traitement
|
||||||
|
body:
|
||||||
|
format: Le contenu de l’email de notification de classement sans suite de dossier %{message}
|
||||||
|
champ_missing: réfère au champ "%{tag}" qui n’existe pas
|
||||||
|
champ_missing_in_draft_revision: réfère au champ "%{tag}" qui a été supprimé mais la suppression n’est pas encore publiée
|
||||||
|
champ_missing_in_published_revision: réfère au champ "%{tag}" qui n’est pas encore publié
|
||||||
|
champ_missing_in_published_and_draft_revision: réfère au champ "%{tag}" qui a été supprimé
|
||||||
|
champ_missing_in_previous_revision: réfère au champ "%{tag}" qui n’existe pas sur un des dossiers en cours de traitement
|
|
@ -468,7 +468,7 @@ Rails.application.routes.draw do
|
||||||
get 'transfert' => 'procedures#transfert', as: :transfert
|
get 'transfert' => 'procedures#transfert', as: :transfert
|
||||||
get 'close' => 'procedures#close', as: :close
|
get 'close' => 'procedures#close', as: :close
|
||||||
post 'transfer' => 'procedures#transfer', as: :transfer
|
post 'transfer' => 'procedures#transfer', as: :transfer
|
||||||
resources :mail_templates, only: [:edit, :update]
|
resources :mail_templates, only: [:edit, :update, :show]
|
||||||
|
|
||||||
resources :groupe_instructeurs, only: [:index, :show, :create, :update, :destroy] do
|
resources :groupe_instructeurs, only: [:index, :show, :create, :update, :destroy] do
|
||||||
member do
|
member do
|
||||||
|
|
|
@ -45,7 +45,7 @@ describe Administrateurs::MailTemplatesController, type: :controller do
|
||||||
|
|
||||||
describe 'PATCH update' do
|
describe 'PATCH update' do
|
||||||
let(:mail_subject) { 'Mise à jour de votre démarche' }
|
let(:mail_subject) { 'Mise à jour de votre démarche' }
|
||||||
let(:mail_body) { '<div>Une mise à jour a été effectuée sur votre démarche n° --demarche-id--.</div>' }
|
let(:mail_body) { '<div>Une mise à jour a été effectuée sur votre démarche n° --numéro du dossier--.</div>' }
|
||||||
|
|
||||||
before :each do
|
before :each do
|
||||||
patch :update,
|
patch :update,
|
||||||
|
@ -58,11 +58,23 @@ describe Administrateurs::MailTemplatesController, type: :controller do
|
||||||
|
|
||||||
it { expect(response).to redirect_to edit_admin_procedure_mail_template_path(procedure, initiated_mail.class.const_get(:SLUG)) }
|
it { expect(response).to redirect_to edit_admin_procedure_mail_template_path(procedure, initiated_mail.class.const_get(:SLUG)) }
|
||||||
|
|
||||||
context 'the mail template' do
|
context 'with valid email template' do
|
||||||
subject { procedure.reload; procedure.initiated_mail_template }
|
subject { procedure.reload; procedure.initiated_mail_template }
|
||||||
|
|
||||||
it { expect(subject.subject).to eq(mail_subject) }
|
it do
|
||||||
it { expect(subject.body).to eq(mail_body) }
|
expect(subject.subject).to eq(mail_subject)
|
||||||
|
expect(subject.body).to eq(mail_body)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with invalid email template' do
|
||||||
|
subject { procedure.reload; procedure.initiated_mail_template }
|
||||||
|
let(:mail_body) { '<div>Une mise à jour a été effectuée sur votre démarche n° --numéro--.</div>' }
|
||||||
|
|
||||||
|
it do
|
||||||
|
expect(subject.body).not_to eq(mail_body)
|
||||||
|
expect(response.body).to match("Le contenu de l’email de notification de passage du dossier en instruction réfère au champ \"numéro\" qui n’existe pas")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
87
spec/models/mail_template_spec.rb
Normal file
87
spec/models/mail_template_spec.rb
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
describe Mails::InitiatedMail, type: :model do
|
||||||
|
let(:procedure) { create(:procedure, :published, types_de_champ_public: [{ type: :text, libelle: 'nom' }]) }
|
||||||
|
let(:type_de_champ) { procedure.draft_revision.types_de_champ_public.first }
|
||||||
|
let(:mail) { described_class.default_for_procedure(procedure) }
|
||||||
|
|
||||||
|
let(:email_subject) { '' }
|
||||||
|
let(:email_body) { '' }
|
||||||
|
|
||||||
|
subject do
|
||||||
|
mail.subject = email_subject
|
||||||
|
mail.body = email_body
|
||||||
|
mail.validate
|
||||||
|
mail
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'body' do
|
||||||
|
context 'empty template' do
|
||||||
|
it { expect(subject.errors).to be_empty }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'template with valid tag' do
|
||||||
|
let(:email_body) { 'foo --numéro du dossier-- bar' }
|
||||||
|
|
||||||
|
it { expect(subject.errors).to be_empty }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'template with new valid tag' do
|
||||||
|
let(:email_body) { 'foo --age-- bar' }
|
||||||
|
|
||||||
|
before do
|
||||||
|
procedure.draft_revision.add_type_de_champ(type_champ: :integer_number, libelle: 'age')
|
||||||
|
procedure.publish_revision!
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect(subject.errors).to be_empty }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'template with invalid tag' do
|
||||||
|
let(:email_body) { 'foo --numéro du -- bar' }
|
||||||
|
|
||||||
|
it { expect(subject.errors.full_messages).to eq(["Le contenu de l’email de notification de passage du dossier en instruction réfère au champ \"numéro du \" qui n’existe pas"]) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'template with unpublished tag' do
|
||||||
|
let(:email_body) { 'foo --age-- bar' }
|
||||||
|
|
||||||
|
before do
|
||||||
|
procedure.draft_revision.add_type_de_champ(type_champ: :integer_number, libelle: 'age')
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect(subject.errors.full_messages).to eq(["Le contenu de l’email de notification de passage du dossier en instruction réfère au champ \"age\" qui n’est pas encore publié"]) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'template with removed but unpublished tag' do
|
||||||
|
let(:email_body) { 'foo --nom-- bar' }
|
||||||
|
|
||||||
|
before do
|
||||||
|
procedure.draft_revision.remove_type_de_champ(type_de_champ.stable_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect(subject.errors.full_messages).to eq(["Le contenu de l’email de notification de passage du dossier en instruction réfère au champ \"nom\" qui a été supprimé mais la suppression n’est pas encore publiée"]) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'template with removed tag' do
|
||||||
|
let(:email_body) { 'foo --nom-- bar' }
|
||||||
|
|
||||||
|
before do
|
||||||
|
procedure.draft_revision.remove_type_de_champ(type_de_champ.stable_id)
|
||||||
|
procedure.publish_revision!
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect(subject.errors.full_messages).to eq(["Le contenu de l’email de notification de passage du dossier en instruction réfère au champ \"nom\" qui a été supprimé"]) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'template with new tag and old dossier' do
|
||||||
|
let(:email_body) { 'foo --age-- bar' }
|
||||||
|
|
||||||
|
before do
|
||||||
|
create(:dossier, :en_construction, procedure: procedure)
|
||||||
|
procedure.draft_revision.add_type_de_champ(type_champ: :integer_number, libelle: 'age')
|
||||||
|
procedure.publish_revision!
|
||||||
|
end
|
||||||
|
|
||||||
|
it { expect(subject.errors.full_messages).to eq(["Le contenu de l’email de notification de passage du dossier en instruction réfère au champ \"age\" qui n’existe pas sur un des dossiers en cours de traitement"]) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -327,11 +327,9 @@ describe Procedure do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'on a published procedure' do
|
context 'when validating for publication' do
|
||||||
before { procedure.publish }
|
|
||||||
|
|
||||||
it 'validates that no repetition type de champ is empty' do
|
it 'validates that no repetition type de champ is empty' do
|
||||||
procedure.validate
|
procedure.validate(:publication)
|
||||||
expect(procedure.errors.full_messages_for(:draft_types_de_champ)).to include(invalid_repetition_error_message)
|
expect(procedure.errors.full_messages_for(:draft_types_de_champ)).to include(invalid_repetition_error_message)
|
||||||
|
|
||||||
new_draft = procedure.draft_revision
|
new_draft = procedure.draft_revision
|
||||||
|
@ -339,32 +337,20 @@ describe Procedure do
|
||||||
parent_coordinate = new_draft.revision_types_de_champ.find_by(type_de_champ: repetition)
|
parent_coordinate = new_draft.revision_types_de_champ.find_by(type_de_champ: repetition)
|
||||||
new_draft.revision_types_de_champ.create(type_de_champ: create(:type_de_champ), position: 0, parent: parent_coordinate)
|
new_draft.revision_types_de_champ.create(type_de_champ: create(:type_de_champ), position: 0, parent: parent_coordinate)
|
||||||
|
|
||||||
procedure.validate
|
procedure.validate(:publication)
|
||||||
expect(procedure.errors.full_messages_for(:draft_types_de_champ)).not_to include(invalid_repetition_error_message)
|
expect(procedure.errors.full_messages_for(:draft_types_de_champ)).not_to include(invalid_repetition_error_message)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'validates that no drop-down type de champ is empty' do
|
it 'validates that no drop-down type de champ is empty' do
|
||||||
procedure.validate
|
procedure.validate(:publication)
|
||||||
expect(procedure.errors.full_messages_for(:draft_types_de_champ)).to include(invalid_drop_down_error_message)
|
expect(procedure.errors.full_messages_for(:draft_types_de_champ)).to include(invalid_drop_down_error_message)
|
||||||
|
|
||||||
drop_down.update!(drop_down_list_value: "--title--\r\nsome value")
|
drop_down.update!(drop_down_list_value: "--title--\r\nsome value")
|
||||||
procedure.reload.validate
|
procedure.reload.validate(:publication)
|
||||||
expect(procedure.errors.full_messages_for(:draft_types_de_champ)).not_to include(invalid_drop_down_error_message)
|
expect(procedure.errors.full_messages_for(:draft_types_de_champ)).not_to include(invalid_drop_down_error_message)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when validating for publication' do
|
|
||||||
it 'validates that no repetition type de champ is empty' do
|
|
||||||
procedure.validate(:publication)
|
|
||||||
expect(procedure.errors.full_messages_for(:draft_types_de_champ)).to include(invalid_repetition_error_message)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'validates that no drop-down type de champ is empty' do
|
|
||||||
procedure.validate(:publication)
|
|
||||||
expect(procedure.errors.full_messages_for(:draft_types_de_champ)).to include(invalid_drop_down_error_message)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when the champ is private' do
|
context 'when the champ is private' do
|
||||||
before do
|
before do
|
||||||
repetition.update(private: true)
|
repetition.update(private: true)
|
||||||
|
|
Loading…
Reference in a new issue