poc(erreur): sur les champs
This commit is contained in:
parent
aed4791b3c
commit
b88b537518
35 changed files with 223 additions and 221 deletions
|
@ -42,11 +42,6 @@ $dossier-actions-bar-border-width: 1px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.characters-count {
|
|
||||||
position: relative;
|
|
||||||
top: -1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.warning {
|
.warning {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
background-color: #f9b91666;
|
background-color: #f9b91666;
|
||||||
|
|
|
@ -183,15 +183,16 @@
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.fr-label {
|
||||||
input[type=text],
|
// la description d'un champ peut contenir du markup (markdown->html),
|
||||||
input[type=email],
|
// on herite donc la fontsize/mrgin/padding du fr-hint-text
|
||||||
|
.fr-hint-text > *{
|
||||||
|
font-size: inherit;
|
||||||
|
margin: inherit;
|
||||||
|
padding: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
input[type=password],
|
input[type=password],
|
||||||
input[type=date],
|
|
||||||
input[type=datetime-local],
|
|
||||||
input[type=number],
|
|
||||||
input[type=tel],
|
|
||||||
textarea,
|
|
||||||
select {
|
select {
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: $default-fields-spacer;
|
margin-bottom: $default-fields-spacer;
|
||||||
|
@ -218,13 +219,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=text]:not([data-address='true']),
|
input[type=text]:not([data-address='true']),
|
||||||
input[type=email],
|
|
||||||
input[type=password],
|
|
||||||
input[type=date],
|
|
||||||
input[type=number],
|
|
||||||
input[type=tel],
|
|
||||||
input[type=datetime-local],
|
|
||||||
textarea,
|
|
||||||
select {
|
select {
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border: solid 1px $border-grey;
|
border: solid 1px $border-grey;
|
||||||
|
@ -266,8 +260,8 @@
|
||||||
input[type=date],
|
input[type=date],
|
||||||
input[type=number],
|
input[type=number],
|
||||||
input[type=datetime-local],
|
input[type=datetime-local],
|
||||||
input[type=tel],
|
textarea,
|
||||||
textarea {
|
input[type=tel], {
|
||||||
@media (max-width: $two-columns-breakpoint) {
|
@media (max-width: $two-columns-breakpoint) {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
@ -413,16 +407,6 @@
|
||||||
color: $dark-grey;
|
color: $dark-grey;
|
||||||
}
|
}
|
||||||
|
|
||||||
.datetime {
|
|
||||||
input[type=date] {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-subsection {
|
.header-subsection {
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
color: $blue-france-500;
|
color: $blue-france-500;
|
||||||
|
@ -445,20 +429,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.siret-info {
|
|
||||||
margin-top: -$default-fields-spacer;
|
|
||||||
margin-bottom: $default-fields-spacer;
|
|
||||||
// Ensure the bottom-margin is not collapsed when the element is empty
|
|
||||||
min-height: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rna-info {
|
|
||||||
margin-top: -$default-fields-spacer;
|
|
||||||
margin-bottom: $default-fields-spacer;
|
|
||||||
// Ensure the bottom-margin is not collapsed when the element is empty
|
|
||||||
min-height: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.send-wrapper {
|
.send-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
class Dsfr::InputComponent < ApplicationComponent
|
class Dsfr::InputComponent < ApplicationComponent
|
||||||
|
include Dsfr::InputErrorable
|
||||||
|
|
||||||
delegate :object, to: :@form
|
delegate :object, to: :@form
|
||||||
delegate :errors, to: :object
|
delegate :errors, to: :object
|
||||||
|
|
||||||
|
@ -18,10 +20,10 @@ class Dsfr::InputComponent < ApplicationComponent
|
||||||
# and and valid on input only if another input is invalid
|
# and and valid on input only if another input is invalid
|
||||||
def input_group_opts
|
def input_group_opts
|
||||||
opts = {
|
opts = {
|
||||||
class: class_names('fr-input-group': true,
|
class: class_names({
|
||||||
'fr-password': password?,
|
'fr-input-group': true,
|
||||||
"fr-input-group--error": errors_on_attribute?,
|
'fr-password': password?
|
||||||
"fr-input-group--valid": !errors_on_attribute? && errors_on_another_attribute?)
|
}.merge(input_group_error_class_names))
|
||||||
}
|
}
|
||||||
if email?
|
if email?
|
||||||
opts[:data] = { controller: 'email-input' }
|
opts[:data] = { controller: 'email-input' }
|
||||||
|
@ -33,38 +35,7 @@ class Dsfr::InputComponent < ApplicationComponent
|
||||||
{ class: class_names('fr-label': true, 'fr-password__label': password?) }
|
{ class: class_names('fr-label': true, 'fr-password__label': password?) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def input_opts
|
|
||||||
@opts[:class] = class_names(map_array_to_hash_with_true(@opts[:class])
|
|
||||||
.merge('fr-password__input': password?,
|
|
||||||
'fr-input': true,
|
|
||||||
'fr-mb-0': true,
|
|
||||||
'fr-input--error': errors_on_attribute?))
|
|
||||||
|
|
||||||
if errors_on_attribute? || describedby?
|
|
||||||
@opts.deep_merge!(aria: {
|
|
||||||
describedby: describedby_id,
|
|
||||||
invalid: errors_on_attribute?
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
if @required
|
|
||||||
@opts[:required] = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if email?
|
|
||||||
@opts.deep_merge!(data: {
|
|
||||||
action: "blur->email-input#checkEmail",
|
|
||||||
'email-input-target': 'input'
|
|
||||||
})
|
|
||||||
end
|
|
||||||
@opts
|
|
||||||
end
|
|
||||||
|
|
||||||
# errors helpers
|
# errors helpers
|
||||||
def errors_on_attribute?
|
|
||||||
errors.has_key?(attribute_or_rich_body)
|
|
||||||
end
|
|
||||||
|
|
||||||
def error_messages
|
def error_messages
|
||||||
errors.full_messages_for(attribute_or_rich_body)
|
errors.full_messages_for(attribute_or_rich_body)
|
||||||
end
|
end
|
||||||
|
@ -78,9 +49,6 @@ class Dsfr::InputComponent < ApplicationComponent
|
||||||
object.class.human_attribute_name(@attribute)
|
object.class.human_attribute_name(@attribute)
|
||||||
end
|
end
|
||||||
|
|
||||||
def hint
|
|
||||||
I18n.t("activerecord.attributes.#{object.class.name.underscore}.hints.#{@attribute}")
|
|
||||||
end
|
|
||||||
|
|
||||||
# kind of input helpers
|
# kind of input helpers
|
||||||
def password?
|
def password?
|
||||||
|
@ -97,26 +65,5 @@ class Dsfr::InputComponent < ApplicationComponent
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def hint?
|
|
||||||
I18n.exists?("activerecord.attributes.#{object.class.name.underscore}.hints.#{@attribute}")
|
|
||||||
end
|
|
||||||
|
|
||||||
def errors_on_another_attribute?
|
|
||||||
!errors.empty?
|
|
||||||
end
|
|
||||||
|
|
||||||
# lookup for edge case from `form.rich_text_area`
|
|
||||||
# rich text uses _rich_#{attribute}, but it is saved on #{attribute}, as well as error messages
|
|
||||||
def attribute_or_rich_body
|
|
||||||
case @input_type
|
|
||||||
when :rich_text_area
|
|
||||||
@attribute.to_s.sub(/\Arich_/, '').to_sym
|
|
||||||
else
|
|
||||||
@attribute
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def map_array_to_hash_with_true(array_or_string_or_nil)
|
|
||||||
Array(array_or_string_or_nil).to_h { [_1, true] }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
109
app/components/dsfr/input_errorable.rb
Normal file
109
app/components/dsfr/input_errorable.rb
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
module Dsfr
|
||||||
|
module InputErrorable
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
included do
|
||||||
|
delegate :object, to: :@form
|
||||||
|
delegate :errors, to: :object
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# lookup for edge case from `form.rich_text_area`
|
||||||
|
# rich text uses _rich_#{attribute}, but it is saved on #{attribute}, as well as error messages
|
||||||
|
def attribute_or_rich_body
|
||||||
|
case @input_type
|
||||||
|
when :rich_text_area
|
||||||
|
@attribute.to_s.sub(/\Arich_/, '').to_sym
|
||||||
|
else
|
||||||
|
@attribute
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def input_group_error_class_names
|
||||||
|
{
|
||||||
|
"fr-input-group--error": errors_on_attribute?,
|
||||||
|
"fr-input-group--valid": !errors_on_attribute? && errors_on_another_attribute?
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def input_error_class_names
|
||||||
|
{ 'fr-input--error': errors_on_attribute? }
|
||||||
|
end
|
||||||
|
|
||||||
|
def input_error_opts
|
||||||
|
{
|
||||||
|
aria: {
|
||||||
|
describedby: describedby_id,
|
||||||
|
invalid: errors_on_attribute?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def input_opts(other_opts = {})
|
||||||
|
@opts = @opts.deep_merge!(other_opts)
|
||||||
|
@opts[:class] = class_names(map_array_to_hash_with_true(@opts[:class])
|
||||||
|
.merge({
|
||||||
|
'fr-password__input': password?,
|
||||||
|
'fr-input': true,
|
||||||
|
'fr-mb-0': true
|
||||||
|
}.merge(input_error_class_names)))
|
||||||
|
|
||||||
|
if errors_on_attribute?
|
||||||
|
@opts.deep_merge!(aria: {
|
||||||
|
describedby: describedby_id,
|
||||||
|
invalid: errors_on_attribute?
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
if @required
|
||||||
|
@opts[:required] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if email?
|
||||||
|
@opts.deep_merge!(data: {
|
||||||
|
action: "blur->email-input#checkEmail",
|
||||||
|
'email-input-target': 'input'
|
||||||
|
})
|
||||||
|
end
|
||||||
|
@opts
|
||||||
|
end
|
||||||
|
|
||||||
|
def describedby_id
|
||||||
|
dom_id(@champ, :error_messages)
|
||||||
|
end
|
||||||
|
|
||||||
|
def errors_on_another_attribute?
|
||||||
|
!errors.empty?
|
||||||
|
end
|
||||||
|
|
||||||
|
def errors_on_attribute?
|
||||||
|
errors.has_key?(attribute_or_rich_body)
|
||||||
|
end
|
||||||
|
|
||||||
|
# errors helpers
|
||||||
|
def error_messages
|
||||||
|
errors.full_messages_for(attribute_or_rich_body)
|
||||||
|
end
|
||||||
|
|
||||||
|
def map_array_to_hash_with_true(array_or_string_or_nil)
|
||||||
|
Array(array_or_string_or_nil).to_h { [_1, true] }
|
||||||
|
end
|
||||||
|
|
||||||
|
def hint
|
||||||
|
I18n.t("activerecord.attributes.#{object.class.name.underscore}.hints.#{@attribute}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def password?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def email?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def hint?
|
||||||
|
I18n.exists?("activerecord.attributes.#{object.class.name.underscore}.hints.#{@attribute}")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,5 +1,8 @@
|
||||||
class EditableChamp::ChampLabelComponent < ApplicationComponent
|
class EditableChamp::ChampLabelComponent < ApplicationComponent
|
||||||
|
include Dsfr::InputErrorable
|
||||||
|
|
||||||
def initialize(form:, champ:, seen_at: nil)
|
def initialize(form:, champ:, seen_at: nil)
|
||||||
@form, @champ, @seen_at = form, champ, seen_at
|
@form, @champ, @seen_at = form, champ, seen_at
|
||||||
|
@attribute = :value
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
= # we do this trick because some html elements should use 'label' and some should be plain paragraphs
|
= # we do this trick because some html elements should use 'label' and some should be plain paragraphs
|
||||||
- if @champ.html_label?
|
- if @champ.html_label?
|
||||||
= @form.label @champ.main_value_name, id: @champ.labelledby_id, for: @champ.input_id do
|
= @form.label @champ.main_value_name, id: @champ.labelledby_id, for: @champ.input_id, class: 'fr-label' do
|
||||||
- render EditableChamp::ChampLabelContentComponent.new champ: @champ, seen_at: @seen_at
|
- render EditableChamp::ChampLabelContentComponent.new form: @form, champ: @champ, seen_at: @seen_at
|
||||||
- else
|
- else
|
||||||
.form-label.mb-4{ id: @champ.labelledby_id }
|
.fr-label.mb-4{ id: @champ.labelledby_id }
|
||||||
= render EditableChamp::ChampLabelContentComponent.new champ: @champ, seen_at: @seen_at
|
= render EditableChamp::ChampLabelContentComponent.new form: @form, champ: @champ, seen_at: @seen_at
|
||||||
|
|
||||||
|
|
||||||
- if @champ.description.present?
|
|
||||||
.notice{ id: @champ.describedby_id }= render SimpleFormatComponent.new(@champ.description, allow_a: true)
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
class EditableChamp::ChampLabelContentComponent < ApplicationComponent
|
class EditableChamp::ChampLabelContentComponent < ApplicationComponent
|
||||||
include ApplicationHelper
|
include ApplicationHelper
|
||||||
|
include Dsfr::InputErrorable
|
||||||
|
|
||||||
def initialize(champ:, seen_at: nil)
|
def initialize(form:, champ:, seen_at: nil)
|
||||||
@champ, @seen_at = champ, seen_at
|
@form, @champ, @seen_at = form, champ, seen_at
|
||||||
|
@attribute = :value
|
||||||
end
|
end
|
||||||
|
|
||||||
def highlight_if_unseen_class
|
def highlight_if_unseen_class
|
||||||
|
|
|
@ -4,3 +4,5 @@ en:
|
||||||
modified_at: "modified on %{datetime}"
|
modified_at: "modified on %{datetime}"
|
||||||
check_content_rebased: The type of this field or its description has been modified by the administration. Check its content.
|
check_content_rebased: The type of this field or its description has been modified by the administration. Check its content.
|
||||||
optional_champ: (optional)
|
optional_champ: (optional)
|
||||||
|
recommended_size: The recommended maximum size is %{size} characters.
|
||||||
|
titre_identite_notice: National identity card (front side only), passport, residency permit or other proof of identity.
|
||||||
|
|
|
@ -4,3 +4,5 @@ fr:
|
||||||
modified_at: "modifié le %{datetime}"
|
modified_at: "modifié le %{datetime}"
|
||||||
check_content_rebased: Le type de ce champ ou sa description ont été modifiés par l'administration. Vérifier son contenu.
|
check_content_rebased: Le type de ce champ ou sa description ont été modifiés par l'administration. Vérifier son contenu.
|
||||||
optional_champ: (facultatif)
|
optional_champ: (facultatif)
|
||||||
|
recommended_size: La taille maximale conseillée est de %{size} caractères.
|
||||||
|
titre_identite_notice: Carte nationale d’identité (uniquement le recto), passeport, titre de séjour ou autre justificatif d’identité.
|
||||||
|
|
|
@ -18,3 +18,15 @@
|
||||||
- if @champ.rebased_at.present? && @champ.rebased_at > (@seen_at || @champ.updated_at) && current_user.owns_or_invite?(@champ.dossier)
|
- if @champ.rebased_at.present? && @champ.rebased_at > (@seen_at || @champ.updated_at) && current_user.owns_or_invite?(@champ.dossier)
|
||||||
%span.updated-at.highlighted
|
%span.updated-at.highlighted
|
||||||
= t('.check_content_rebased')
|
= t('.check_content_rebased')
|
||||||
|
|
||||||
|
- if @champ.titre_identite?
|
||||||
|
%span.fr-hint-text= t('.titre_identite_notice')
|
||||||
|
|
||||||
|
- if hint?
|
||||||
|
%span.fr-hint-text= hint
|
||||||
|
|
||||||
|
- if @champ.description.present?
|
||||||
|
%span.fr-hint-text{ id: @champ.describedby_id }= render SimpleFormatComponent.new(@champ.description, allow_a: true)
|
||||||
|
|
||||||
|
- if @champ.textarea?
|
||||||
|
%span.sr-only= t('.recommended_size', size: @champ.character_limit_base)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
= @form.date_field :value,
|
= @form.date_field :value,
|
||||||
id: @champ.input_id,
|
input_opts(id: @champ.input_id,
|
||||||
aria: { describedby: @champ.describedby_id },
|
aria: { describedby: @champ.describedby_id },
|
||||||
value: @champ.value,
|
value: @champ.value,
|
||||||
required: @champ.required?,
|
required: @champ.required?,
|
||||||
placeholder: 'aaaa-mm-jj',
|
placeholder: 'aaaa-mm-jj', class: "width-33-desktop")
|
||||||
class: "width-33-desktop"
|
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
.datetime
|
= @form.datetime_field(:value, input_opts(value: formatted_value_for_datetime_locale, id: @champ.input_id, aria: { describedby: @champ.describedby_id }, data: { controller: 'datetime' }))
|
||||||
= @form.datetime_field(:value, value: formatted_value_for_datetime_locale, id: @champ.input_id, aria: { describedby: @champ.describedby_id }, data: { controller: 'datetime' })
|
|
||||||
|
|
|
@ -1,6 +1 @@
|
||||||
= @form.number_field :value,
|
= @form.number_field(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, step: :any, placeholder: "3.14", required: @champ.required?))
|
||||||
id: @champ.input_id,
|
|
||||||
aria: { describedby: @champ.describedby_id },
|
|
||||||
step: :any,
|
|
||||||
placeholder: "3.14",
|
|
||||||
required: @champ.required?
|
|
||||||
|
|
|
@ -1,18 +1,8 @@
|
||||||
.dossier-link
|
= @form.text_field(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, inputmode: :numeric, min: 1, pattern: "[0-9]{1,12}", placeholder: "Numéro de dossier", autocomplete: 'off', required: @champ.required?, class: "width-33-desktop #{@champ.blank? ? '' : 'small-margin'}"))
|
||||||
= @form.text_field :value,
|
|
||||||
id: @champ.input_id,
|
|
||||||
aria: { describedby: @champ.describedby_id },
|
|
||||||
inputmode: :numeric,
|
|
||||||
min: 1,
|
|
||||||
pattern: "[0-9]{1,12}",
|
|
||||||
placeholder: "Numéro de dossier",
|
|
||||||
autocomplete: 'off',
|
|
||||||
required: @champ.required?,
|
|
||||||
class: "width-33-desktop #{@champ.blank? ? '' : 'small-margin'}"
|
|
||||||
|
|
||||||
- if !@champ.blank?
|
- if !@champ.blank?
|
||||||
- if dossier.blank?
|
- if dossier.blank?
|
||||||
.fr-error-text.fr-mb-4w
|
.fr-error-text.fr-mb-4w
|
||||||
= t('.not_found')
|
= t('.not_found')
|
||||||
- else
|
- else
|
||||||
.fr-info-text.fr-mb-4w= sanitize(dossier.text_summary)
|
.fr-info-text.fr-mb-4w= sanitize(dossier.text_summary)
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
class EditableChamp::EditableChampBaseComponent < ApplicationComponent
|
class EditableChamp::EditableChampBaseComponent < ApplicationComponent
|
||||||
def initialize(form:, champ:, seen_at: nil)
|
include Dsfr::InputErrorable
|
||||||
@form, @champ, @seen_at = form, champ, seen_at
|
|
||||||
|
def initialize(form:, champ:, seen_at: nil, opts: {})
|
||||||
|
@form, @champ, @seen_at, @opts = form, champ, seen_at, opts
|
||||||
|
@attribute = :value
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
class EditableChamp::EditableChampComponent < ApplicationComponent
|
class EditableChamp::EditableChampComponent < ApplicationComponent
|
||||||
|
include Dsfr::InputErrorable
|
||||||
|
|
||||||
def initialize(form:, champ:, seen_at: nil)
|
def initialize(form:, champ:, seen_at: nil)
|
||||||
@form, @champ, @seen_at = form, champ, seen_at
|
@form, @champ, @seen_at = form, champ, seen_at
|
||||||
|
@attribute = :value
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -21,8 +24,12 @@ class EditableChamp::EditableChampComponent < ApplicationComponent
|
||||||
def html_options
|
def html_options
|
||||||
{
|
{
|
||||||
class: class_names(
|
class: class_names(
|
||||||
"editable-champ-#{@champ.type_champ}": true,
|
{
|
||||||
"hidden": !@champ.visible?
|
'editable-champ': true,
|
||||||
|
"editable-champ-#{@champ.type_champ}": true,
|
||||||
|
"hidden": !@champ.visible?,
|
||||||
|
"fr-input-group": true,
|
||||||
|
}.merge(input_group_error_class_names)
|
||||||
),
|
),
|
||||||
id: @champ.input_group_id,
|
id: @champ.input_group_id,
|
||||||
data: { controller: stimulus_controller, **data_dependent_conditions, **stimulus_values }
|
data: { controller: stimulus_controller, **data_dependent_conditions, **stimulus_values }
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
---
|
---
|
||||||
en:
|
en:
|
||||||
titre_identite_notice: National identity card (front side only), passport, residency permit or other proof of identity.
|
titre_identite_notice: National identity card (front side only), passport, residency permit or other proof of identity.
|
||||||
datetime_notice: "Expected format : dd/mm/yyyy hh:mm"
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
---
|
---
|
||||||
fr:
|
fr:
|
||||||
titre_identite_notice: Carte nationale d’identité (uniquement le recto), passeport, titre de séjour ou autre justificatif d’identité.
|
titre_identite_notice: Carte nationale d’identité (uniquement le recto), passeport, titre de séjour ou autre justificatif d’identité.
|
||||||
datetime_notice: "Format attendu : jj/mm/aaaa hh:mm"
|
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
.editable-champ{ html_options }
|
= content_tag(:div, html_options) do
|
||||||
- if has_label?(@champ)
|
- if has_label?(@champ)
|
||||||
= render EditableChamp::ChampLabelComponent.new form: @form, champ: @champ, seen_at: @seen_at
|
= render EditableChamp::ChampLabelComponent.new form: @form, champ: @champ, seen_at: @seen_at
|
||||||
- if @champ.titre_identite?
|
= render component_class.new(form: @form, champ: @champ, seen_at: @seen_at)
|
||||||
%p.notice= t('.titre_identite_notice')
|
|
||||||
- elsif @champ.datetime?
|
- if errors_on_attribute?
|
||||||
%p.notice= t('.datetime_notice')
|
- if error_messages.size == 1
|
||||||
|
%p.fr-error-text{ id: describedby_id }= error_messages.first
|
||||||
|
- else
|
||||||
|
.fr-error-text{ id: describedby_id }
|
||||||
|
%ul.list-style-type-none.fr-pl-0
|
||||||
|
- error_messages.map do |error_message|
|
||||||
|
%li= error_message
|
||||||
|
|
||||||
= @form.hidden_field :id, value: @champ.id
|
= @form.hidden_field :id, value: @champ.id
|
||||||
= render component_class.new(form: @form, champ: @champ, seen_at: @seen_at)
|
|
||||||
|
|
|
@ -1,2 +1,5 @@
|
||||||
class EditableChamp::EmailComponent < EditableChamp::EditableChampBaseComponent
|
class EditableChamp::EmailComponent < EditableChamp::EditableChampBaseComponent
|
||||||
|
def email?
|
||||||
|
true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1 @@
|
||||||
= @form.email_field :value,
|
= @form.email_field(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, placeholder: t(".placeholder"), required: @champ.required?))
|
||||||
id: @champ.input_id,
|
|
||||||
aria: { describedby: @champ.describedby_id },
|
|
||||||
placeholder: t(".placeholder"),
|
|
||||||
required: @champ.required?
|
|
||||||
|
|
|
@ -1,8 +1 @@
|
||||||
= @form.text_field :value,
|
= @form.text_field(:value, input_opts(id: @champ.input_id, placeholder: t(".placeholder"), required: @champ.required?, aria: { describedby: @champ.describedby_id }, data: { controller: 'format', format: 'iban' }, class: "width-66-desktop", maxlength: 34 + 9)) # count space separator of 4 digits-groups
|
||||||
id: @champ.input_id,
|
|
||||||
placeholder: t(".placeholder"),
|
|
||||||
required: @champ.required?,
|
|
||||||
aria: { describedby: @champ.describedby_id },
|
|
||||||
data: { controller: 'format', format: 'iban' },
|
|
||||||
class: "width-66-desktop",
|
|
||||||
maxlength: 34 + 9 # count space separator of 4 digits-groups
|
|
||||||
|
|
|
@ -1,5 +1 @@
|
||||||
= @form.number_field :value,
|
= @form.number_field(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, placeholder: 5, required: @champ.required?))
|
||||||
id: @champ.input_id,
|
|
||||||
aria: { describedby: @champ.describedby_id },
|
|
||||||
placeholder: 5,
|
|
||||||
required: @champ.required?
|
|
||||||
|
|
|
@ -1,5 +1 @@
|
||||||
= @form.number_field :value,
|
= @form.number_field(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, placeholder: @champ.libelle, required: @champ.required?))
|
||||||
id: @champ.input_id,
|
|
||||||
aria: { describedby: @champ.describedby_id },
|
|
||||||
placeholder: @champ.libelle,
|
|
||||||
required: @champ.required?
|
|
||||||
|
|
|
@ -1,9 +1,4 @@
|
||||||
-# Allowed @formats:
|
-# Allowed @formats:
|
||||||
-# very light validation is made client-side
|
-# very light validation is made client-side
|
||||||
-# stronger validation is made server-side
|
-# stronger validation is made server-side
|
||||||
= @form.phone_field :value,
|
= @form.phone_field(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, placeholder: t(".placeholder"), required: @champ.required?, pattern: "[^a-z^A-Z]+"))
|
||||||
id: @champ.input_id,
|
|
||||||
aria: { describedby: @champ.describedby_id },
|
|
||||||
placeholder: t(".placeholder"),
|
|
||||||
required: @champ.required?,
|
|
||||||
pattern: "[^a-z^A-Z]+"
|
|
||||||
|
|
|
@ -1,12 +1,3 @@
|
||||||
= @form.text_field :value,
|
= @form.text_field(:value, input_opts( id: @champ.input_id, aria: { describedby: @champ.describedby_id }, placeholder: t(".placeholder"), data: { controller: 'turbo-input', turbo_input_load_on_connect_value: @champ.prefilled? && @champ.value.present? && @champ.data.blank?, turbo_input_url_value: champs_rna_path(@champ.id) }, required: @champ.required?, pattern: "W[0-9]{9}", title: t(".title"), class: "width-33-desktop", maxlength: 10))
|
||||||
id: @champ.input_id,
|
|
||||||
aria: { describedby: @champ.describedby_id },
|
|
||||||
placeholder: t(".placeholder"),
|
|
||||||
data: { controller: 'turbo-input', turbo_input_load_on_connect_value: @champ.prefilled? && @champ.value.present? && @champ.data.blank?, turbo_input_url_value: champs_rna_path(@champ.id) },
|
|
||||||
required: @champ.required?,
|
|
||||||
pattern: "W[0-9]{9}",
|
|
||||||
title: t(".title"),
|
|
||||||
class: "width-33-desktop",
|
|
||||||
maxlength: 10
|
|
||||||
.rna-info{ id: dom_id(@champ, :rna_info) }
|
.rna-info{ id: dom_id(@champ, :rna_info) }
|
||||||
= render 'shared/champs/rna/association', champ: @champ, error: nil
|
= render 'shared/champs/rna/association', champ: @champ, error: nil
|
||||||
|
|
|
@ -1,13 +1,4 @@
|
||||||
= @form.text_field :value,
|
= @form.text_field(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, placeholder: t(".placeholder"), data: { controller: 'turbo-input', turbo_input_load_on_connect_value: @champ.prefilled? && @champ.value.present? && @champ.etablissement.blank?, turbo_input_url_value: champs_siret_path(@champ.id) }, required: @champ.required?, pattern: "[0-9]{14}", title: t(".title"), class: "width-33-desktop", maxlength: 14))
|
||||||
id: @champ.input_id,
|
|
||||||
aria: { describedby: @champ.describedby_id },
|
|
||||||
placeholder: t(".placeholder"),
|
|
||||||
data: { controller: 'turbo-input', turbo_input_load_on_connect_value: @champ.prefilled? && @champ.value.present? && @champ.etablissement.blank?, turbo_input_url_value: champs_siret_path(@champ.id) },
|
|
||||||
required: @champ.required?,
|
|
||||||
pattern: "[0-9]{14}",
|
|
||||||
title: t(".title"),
|
|
||||||
class: "width-33-desktop",
|
|
||||||
maxlength: 14
|
|
||||||
.spinner.right.hidden
|
.spinner.right.hidden
|
||||||
.siret-info{ id: dom_id(@champ, :siret_info) }
|
.siret-info{ id: dom_id(@champ, :siret_info) }
|
||||||
- if @champ.etablissement.present?
|
- if @champ.etablissement.present?
|
||||||
|
|
|
@ -1,4 +1 @@
|
||||||
= @form.text_field :value,
|
= @form.text_field(:value, input_opts(id: @champ.input_id, required: @champ.required?, aria: { describedby: @champ.describedby_id }))
|
||||||
id: @champ.input_id,
|
|
||||||
required: @champ.required?,
|
|
||||||
aria: { describedby: @champ.describedby_id }
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
en:
|
en:
|
||||||
remaining_characters: You have %{remaining_words} characters remaining.
|
remaining_characters: You have %{remaining_words} characters remaining.
|
||||||
excess_characters: You have %{excess_words} characters too many.
|
excess_characters: You have %{excess_words} characters too many.
|
||||||
recommended_size: The recommended maximum size is %{size} characters.
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
fr:
|
fr:
|
||||||
remaining_characters: Il vous reste %{remaining_words} caractères.
|
remaining_characters: Il vous reste %{remaining_words} caractères.
|
||||||
excess_characters: Vous avez dépassé la taille conseillée de %{excess_words} caractères. Réduire le nombre de caractères.
|
excess_characters: Vous avez dépassé la taille conseillée de %{excess_words} caractères. Réduire le nombre de caractères.
|
||||||
recommended_size: La taille maximale conseillée est de %{size} caractères.
|
|
||||||
|
|
|
@ -1,16 +1,9 @@
|
||||||
%span.sr-only= t('.recommended_size', size: @champ.character_limit_base)
|
~ @form.text_area(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, rows: 6, required: @champ.required?, value: html_to_string(@champ.value)))
|
||||||
|
|
||||||
~ @form.text_area :value,
|
|
||||||
id: @champ.input_id,
|
|
||||||
aria: { describedby: @champ.describedby_id },
|
|
||||||
rows: 6,
|
|
||||||
required: @champ.required?,
|
|
||||||
value: html_to_string(@champ.value)
|
|
||||||
|
|
||||||
- if @champ.character_limit_info?
|
- if @champ.character_limit_info?
|
||||||
%span.fr-icon-information-fill.fr-text-default--info.characters-count
|
%span.fr-icon-information-fill.fr-text-default--info.characters-count
|
||||||
= t('.remaining_characters', remaining_words: @champ.remaining_characters)
|
= t('.remaining_characters', remaining_words: @champ.remaining_characters)
|
||||||
|
|
||||||
- if @champ.character_limit_warning?
|
- if @champ.character_limit_warning?
|
||||||
%span.fr-icon-warning-fill.fr-text-default--warning.characters-count
|
%p.fr-icon-warning-fill.fr-text-default--warning.characters-count
|
||||||
= t('.excess_characters', excess_words: @champ.excess_characters)
|
= t('.excess_characters', excess_words: @champ.excess_characters)
|
||||||
|
|
|
@ -57,6 +57,7 @@ class Champ < ApplicationRecord
|
||||||
:dossier_link?,
|
:dossier_link?,
|
||||||
:departement?,
|
:departement?,
|
||||||
:region?,
|
:region?,
|
||||||
|
:textarea?,
|
||||||
:titre_identite?,
|
:titre_identite?,
|
||||||
:header_section?,
|
:header_section?,
|
||||||
:checkbox?,
|
:checkbox?,
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
- case error
|
- case error
|
||||||
- when :invalid
|
- when :invalid
|
||||||
%p.pt-1
|
%p.fr-pt-1.fr-pb-0
|
||||||
Le numéro RNA doit commencer par un W majuscule suivi de 9 chiffres
|
Le numéro RNA doit commencer par un W majuscule suivi de 9 chiffres
|
||||||
- when :not_found
|
- when :not_found
|
||||||
%p.pt-1= t('.not_found')
|
%p.fr-pt-1.fr-pb-0= t('.not_found')
|
||||||
- when :network_error
|
- when :network_error
|
||||||
%p.pt-1= t('.network_error')
|
%p.fr-pt-1.fr-pb-0= t('.network_error')
|
||||||
- else
|
- else
|
||||||
- if champ.value.present?
|
- if champ.value.present?
|
||||||
%p.pt-1= t('.data_fetched', title: champ.title)
|
%p.fr-pt-1.fr-pb-0= t('.data_fetched', title: champ.title)
|
||||||
|
|
7
config/locales/models/champs/datetime_champ/en.yml
Normal file
7
config/locales/models/champs/datetime_champ/en.yml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
en:
|
||||||
|
activerecord:
|
||||||
|
attributes:
|
||||||
|
champs/datetime_champ:
|
||||||
|
hints:
|
||||||
|
value: "Expected format : dd/mm/yyyy hh:mm"
|
||||||
|
|
7
config/locales/models/champs/datetime_champ/fr.yml
Normal file
7
config/locales/models/champs/datetime_champ/fr.yml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
fr:
|
||||||
|
activerecord:
|
||||||
|
attributes:
|
||||||
|
champs/datetime_champ:
|
||||||
|
hints:
|
||||||
|
value: "Format attendu : jj/mm/aaaa hh:mm"
|
||||||
|
|
Loading…
Add table
Reference in a new issue