feat(attestation): can toggle optional champs tags visibility
This commit is contained in:
parent
c5174f7d43
commit
8ba1c0e481
7 changed files with 112 additions and 6 deletions
|
@ -75,4 +75,14 @@
|
||||||
background-color: var(--background-action-low-blue-france);
|
background-color: var(--background-action-low-blue-france);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// scss-lint:disable SelectorFormat
|
||||||
|
#show_maybe_null + label {
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
|
||||||
|
.fr-hint-text {
|
||||||
|
position: absolute;
|
||||||
|
top: 1.15rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,4 +14,18 @@ class TagsButtonListComponent < ApplicationComponent
|
||||||
def button_title(tag)
|
def button_title(tag)
|
||||||
tag[:description].presence || tag[:libelle]
|
tag[:description].presence || tag[:libelle]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def each_category
|
||||||
|
tags.each_pair do |category, tags|
|
||||||
|
yield category, tags, can_toggle_nullable?(category)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def can_toggle_nullable?(category)
|
||||||
|
return false if category != :champ_public
|
||||||
|
|
||||||
|
tags[category].any? { _1[:maybe_null] }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,8 +1,18 @@
|
||||||
- tags.each_pair do |category, tags|
|
- each_category do |category, tags, can_toggle_nullable|
|
||||||
%p.fr-label.fr-text--sm.fr-text--bold.fr-mb-1w= t(category, scope: ".categories")
|
.flex
|
||||||
%ul.fr-tags-group
|
%p.fr-label.fr-text--sm.fr-text--bold.fr-mb-1w= t(category, scope: ".categories")
|
||||||
|
|
||||||
|
- if can_toggle_nullable
|
||||||
|
.fr-fieldset__element.fr-ml-4w
|
||||||
|
.fr-checkbox-group.fr-checkbox-group--sm
|
||||||
|
= check_box_tag("show_maybe_null", 1, false, data: { "no-autosubmit" => true, action: "change->attestation#toggleMaybeNull"})
|
||||||
|
= label_tag "show_maybe_null", for: :show_maybe_null do
|
||||||
|
Voir les champs facultatifs
|
||||||
|
%span.hidden.fr-hint-text Un champ non rempli restera vide dans l’attestation.
|
||||||
|
|
||||||
|
%ul.fr-tags-group{ data: { category: category } }
|
||||||
- tags.each do |tag|
|
- tags.each do |tag|
|
||||||
%li
|
%li{ class: class_names("hidden" => can_toggle_nullable && tag[:maybe_null]), data: { "maybe-null" => can_toggle_nullable && tag[:maybe_null].present? } }
|
||||||
- label = button_label(tag)
|
- label = button_label(tag)
|
||||||
%button.fr-tag.fr-tag--sm{ type: "button", title: button_title(tag), data: { action: 'click->tiptap#insertTag', tiptap_target: 'tag', tag_id: tag[:id], tag_label: label } }
|
%button.fr-tag.fr-tag--sm{ type: "button", title: button_title(tag), data: { action: 'click->tiptap#insertTag', tiptap_target: 'tag', tag_id: tag[:id], tag_label: label } }
|
||||||
= label
|
= label
|
||||||
|
|
|
@ -32,6 +32,20 @@ export class AttestationController extends ApplicationController {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleMaybeNull(event: Event) {
|
||||||
|
const checkbox = event.target as HTMLInputElement;
|
||||||
|
const visible = checkbox.checked;
|
||||||
|
|
||||||
|
// toggle hidden class on next label element
|
||||||
|
checkbox.nextElementSibling
|
||||||
|
?.querySelector('.fr-hint-text')
|
||||||
|
?.classList?.toggle('hidden', !visible);
|
||||||
|
|
||||||
|
document.querySelectorAll('li[data-maybe-null]').forEach((tag) => {
|
||||||
|
tag.classList.toggle('hidden', !visible);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private get isStateLayout() {
|
private get isStateLayout() {
|
||||||
return this.layoutToggleTarget.checked;
|
return this.layoutToggleTarget.checked;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
class TypesDeChamp::TypeDeChampBase
|
class TypesDeChamp::TypeDeChampBase
|
||||||
include ActiveModel::Validations
|
include ActiveModel::Validations
|
||||||
|
|
||||||
delegate :description, :libelle, :mandatory, :stable_id, :fillable?, to: :@type_de_champ
|
delegate :description, :libelle, :mandatory, :mandatory?, :stable_id, :fillable?, :public?, to: :@type_de_champ
|
||||||
|
|
||||||
FILL_DURATION_SHORT = 10.seconds
|
FILL_DURATION_SHORT = 10.seconds
|
||||||
FILL_DURATION_MEDIUM = 1.minute
|
FILL_DURATION_MEDIUM = 1.minute
|
||||||
|
@ -19,6 +19,7 @@ class TypesDeChamp::TypeDeChampBase
|
||||||
libelle: TagsSubstitutionConcern::TagsParser.normalize(libelle),
|
libelle: TagsSubstitutionConcern::TagsParser.normalize(libelle),
|
||||||
id: "tdc#{stable_id}",
|
id: "tdc#{stable_id}",
|
||||||
description: description,
|
description: description,
|
||||||
|
maybe_null: public? && !mandatory?,
|
||||||
lambda: -> (champs) {
|
lambda: -> (champs) {
|
||||||
champs.find { |champ| champ.stable_id == stable_id }&.for_tag
|
champs.find { |champ| champ.stable_id == stable_id }&.for_tag
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,8 @@ class TagsButtonListComponentPreview < ViewComponent::Preview
|
||||||
{
|
{
|
||||||
id: 'tdc13',
|
id: 'tdc13',
|
||||||
libelle: 'Votre avis très ' + 'long ' * 12,
|
libelle: 'Votre avis très ' + 'long ' * 12,
|
||||||
description: 'Ce libellé a été tronqué'
|
description: 'Ce libellé a été tronqué',
|
||||||
|
maybe_null: true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
56
spec/components/tags_button_list_component_spec.rb
Normal file
56
spec/components/tags_button_list_component_spec.rb
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
RSpec.describe TagsButtonListComponent, type: :component do
|
||||||
|
let(:tags) do
|
||||||
|
{
|
||||||
|
individual: TagsSubstitutionConcern::INDIVIDUAL_TAGS,
|
||||||
|
etablissement: TagsSubstitutionConcern::ENTREPRISE_TAGS,
|
||||||
|
dossier: TagsSubstitutionConcern::DOSSIER_TAGS,
|
||||||
|
champ_public: [
|
||||||
|
{
|
||||||
|
id: 'tdc12',
|
||||||
|
libelle: 'Votre avis',
|
||||||
|
description: 'Détaillez votre avis'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'tdc13',
|
||||||
|
libelle: 'Un champ avec un nom très ' + 'long ' * 12,
|
||||||
|
description: 'Ce libellé a été tronqué',
|
||||||
|
maybe_null:
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
champ_private: [
|
||||||
|
{
|
||||||
|
id: 'tdc22',
|
||||||
|
libelle: 'Montant accordé'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
let(:maybe_null) { true }
|
||||||
|
|
||||||
|
let(:component) do
|
||||||
|
described_class.new(tags:)
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { render_inline(component).to_html }
|
||||||
|
|
||||||
|
it 'renders' do
|
||||||
|
expect(subject).to have_text("Identité")
|
||||||
|
expect(subject).to have_text("civilité")
|
||||||
|
expect(subject).to have_text("Votre avis")
|
||||||
|
expect(subject).to have_text("Montant accordé")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "hide nullable tag" do
|
||||||
|
expect(subject).to have_selector(".hidden button.fr-tag", text: "Un champ avec un nom")
|
||||||
|
expect(subject).to have_selector(":not(.hidden) button.fr-tag", text: "Votre avis")
|
||||||
|
expect(subject).to have_text("Voir les champs facultatifs")
|
||||||
|
end
|
||||||
|
|
||||||
|
context "all champs are visible" do
|
||||||
|
let(:maybe_null) { false }
|
||||||
|
it {
|
||||||
|
expect(subject).not_to have_text("Voir les champs facultatifs")
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue