Skip to content

Commit

Permalink
poc(erreur): sur les champs
Browse files Browse the repository at this point in the history
  • Loading branch information
Martin committed Jun 20, 2023
1 parent 2cfa5a9 commit 8047e0e
Show file tree
Hide file tree
Showing 35 changed files with 220 additions and 221 deletions.
5 changes: 0 additions & 5 deletions app/assets/stylesheets/dossier_edit.scss
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,6 @@ $dossier-actions-bar-border-width: 1px;
}
}

.characters-count {
position: relative;
top: -1rem;
}

.warning {
margin-bottom: 20px;
background-color: #f9b91666;
Expand Down
52 changes: 11 additions & 41 deletions app/assets/stylesheets/forms.scss
Original file line number Diff line number Diff line change
Expand Up @@ -166,15 +166,16 @@
font-weight: normal;
}
}

input[type=text],
input[type=email],
.fr-label {
// la description d'un champ peut contenir du markup (markdown->html),
// 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=date],
input[type=datetime-local],
input[type=number],
input[type=tel],
textarea,
select {
display: block;
margin-bottom: $default-fields-spacer;
Expand All @@ -201,13 +202,6 @@
}

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 {
border-radius: 4px;
border: solid 1px $border-grey;
Expand Down Expand Up @@ -249,8 +243,8 @@
input[type=date],
input[type=number],
input[type=datetime-local],
input[type=tel],
textarea {
textarea,
input[type=tel], {
@media (max-width: $two-columns-breakpoint) {
width: 100%;
}
Expand Down Expand Up @@ -426,16 +420,6 @@
color: $dark-grey;
}

.datetime {
input[type=date] {
display: inline-block;
}

select {
display: inline-block;
}
}

.header-subsection {
font-size: 22px;
color: $blue-france-500;
Expand All @@ -458,20 +442,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 {
display: flex;
width: 100%;
Expand Down
65 changes: 6 additions & 59 deletions app/components/dsfr/input_component.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
class Dsfr::InputComponent < ApplicationComponent
include Dsfr::InputErrorable

delegate :object, to: :@form
delegate :errors, to: :object

Expand All @@ -18,10 +20,10 @@ def initialize(form:, attribute:, input_type: :text_field, opts: {}, required: t
# and and valid on input only if another input is invalid
def input_group_opts
opts = {
class: class_names('fr-input-group': true,
'fr-password': password?,
"fr-input-group--error": errors_on_attribute?,
"fr-input-group--valid": !errors_on_attribute? && errors_on_another_attribute?)
class: class_names({
'fr-input-group': true,
'fr-password': password?
}.merge(input_group_error_class_names))
}
if email?
opts[:data] = { controller: 'email-input' }
Expand All @@ -33,38 +35,7 @@ def label_opts
{ class: class_names('fr-label': true, 'fr-password__label': password?) }
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
def errors_on_attribute?
errors.has_key?(attribute_or_rich_body)
end

def error_messages
errors.full_messages_for(attribute_or_rich_body)
end
Expand All @@ -78,9 +49,6 @@ def label
object.class.human_attribute_name(@attribute)
end

def hint
I18n.t("activerecord.attributes.#{object.class.name.underscore}.hints.#{@attribute}")
end

# kind of input helpers
def password?
Expand All @@ -97,26 +65,5 @@ def show_password_id

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
106 changes: 106 additions & 0 deletions app/components/dsfr/input_errorable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
module Dsfr
module InputErrorable
extend ActiveSupport::Concern
included do
delegate :object, to: :@form
delegate :errors, to: :object

# 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
3 changes: 3 additions & 0 deletions app/components/editable_champ/champ_label_component.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
class EditableChamp::ChampLabelComponent < ApplicationComponent
include Dsfr::InputErrorable

def initialize(form:, champ:, seen_at: nil)
@form, @champ, @seen_at = form, champ, seen_at
@attribute = :value
end
end
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
= # we do this trick because some html elements should use 'label' and some should be plain paragraphs
- if @champ.html_label?
= @form.label @champ.main_value_name, id: @champ.labelledby_id, for: @champ.input_id do
- render EditableChamp::ChampLabelContentComponent.new champ: @champ, seen_at: @seen_at
= @form.label @champ.main_value_name, id: @champ.labelledby_id, for: @champ.input_id, class: 'fr-label' do
- render EditableChamp::ChampLabelContentComponent.new form: @form, champ: @champ, seen_at: @seen_at
- else
.form-label.mb-4{ id: @champ.labelledby_id }
= render EditableChamp::ChampLabelContentComponent.new champ: @champ, seen_at: @seen_at
.fr-label.mb-4{ id: @champ.labelledby_id }
= 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)
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
class EditableChamp::ChampLabelContentComponent < ApplicationComponent
include ApplicationHelper
include Dsfr::InputErrorable

def initialize(champ:, seen_at: nil)
@champ, @seen_at = champ, seen_at
def initialize(form:, champ:, seen_at: nil)
@form, @champ, @seen_at = form, champ, seen_at
@attribute = :value
end

def highlight_if_unseen_class
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ en:
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.
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.
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ fr:
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.
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é.
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,15 @@
- if @champ.rebased_at.present? && @champ.rebased_at > (@seen_at || @champ.updated_at) && current_user.owns_or_invite?(@champ.dossier)
%span.updated-at.highlighted
= 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)
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
= @form.date_field :value,
id: @champ.input_id,
input_opts(id: @champ.input_id,
aria: { describedby: @champ.describedby_id },
value: @champ.value,
required: @champ.required?,
placeholder: 'aaaa-mm-jj',
class: "width-33-desktop"
placeholder: 'aaaa-mm-jj', class: "width-33-desktop")
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
.datetime
= @form.datetime_field(:value, value: formatted_value_for_datetime_locale, id: @champ.input_id, aria: { describedby: @champ.describedby_id }, data: { controller: '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' }))
Original file line number Diff line number Diff line change
@@ -1,6 +1 @@
= @form.number_field :value,
id: @champ.input_id,
aria: { describedby: @champ.describedby_id },
step: :any,
placeholder: "3.14",
required: @champ.required?
= @form.number_field(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, step: :any, placeholder: "3.14", required: @champ.required?))
Loading

0 comments on commit 8047e0e

Please sign in to comment.