feat(type_de_champ_editor): add SelectChampTemplatePosition which feeds SelectChampPositionComponent options

This commit is contained in:
Martin 2024-01-03 11:06:29 +01:00
parent 11de4bdfb6
commit dce06f22a0
6 changed files with 103 additions and 3 deletions

View file

@ -1,3 +1,6 @@
%ul.types-de-champ-block{ id: block_id, data: sortable_options } - c = TypesDeChampEditor::SelectChampTemplatePositionComponent.new(block: @block, coordinates: @coordinates)
%ul.types-de-champ-block{ id: block_id, data: sortable_options.merge(controller: 'select-champ-position-template', 'select-champ-position-template-template-id-value': c.block_id ) }
%li.hidden= render c
- @coordinates.each do |coordinate| - @coordinates.each do |coordinate|
= render TypesDeChampEditor::ChampComponent.new(coordinate: coordinate, upper_coordinates: coordinate.upper_coordinates) = render TypesDeChampEditor::ChampComponent.new(coordinate:, upper_coordinates: coordinate.upper_coordinates)

View file

@ -1,3 +1,3 @@
.fr-ml-3w.flex.select-position .fr-ml-3w.flex.select-position
= label_tag :target_stable_id, "Déplacer le champ", for: describedby_id, class: 'flex align-center flex-no-shrink fr-mr-3w' = label_tag :target_stable_id, "Déplacer le champ", for: describedby_id, class: 'flex align-center flex-no-shrink fr-mr-3w'
= select_tag :target_stable_id, options_for_select(options), id: describedby_id, class: 'fr-select', aria: { discribedby: describedby_id }, data: { action: 'change->type-de-champ-editor#onMoveAndMorphChange', selected: @coordinate.stable_id } = select_tag :target_stable_id, options_for_select(options), id: describedby_id, class: 'fr-select', aria: { discribedby: describedby_id }, data: { 'select-champ-position-template-target': 'select', action: 'change->type-de-champ-editor#onMoveAndMorphChange', selected: @coordinate.stable_id }

View file

@ -0,0 +1,10 @@
class TypesDeChampEditor::SelectChampTemplatePositionComponent < ApplicationComponent
def initialize(block:, coordinates:)
@block = block
@coordinates = coordinates
end
def block_id
dom_id(@block, :types_de_champ_editor_select_champ_template)
end
end

View file

@ -0,0 +1,5 @@
%div{ id: block_id, data: { 'select-champ-position-template-target': 'template', turbo_force: :server } }
%select
%option{ selected: :selected } Selectionner une option
- @coordinates.each do |coordinate|
%option{ value: coordinate.stable_id }= "#{coordinate.position} #{coordinate.libelle}"

View file

@ -0,0 +1,74 @@
import { ApplicationController } from './application_controller';
export class SelectChampPositionTemplateController extends ApplicationController {
static targets = ['select', 'template'];
static values = {
templateId: String
};
// this element is updated via turbostream as the source of truth for all select
declare readonly templateIdValue: string;
declare readonly selectTargets: HTMLSelectElement[];
selectTargetConnected(selectElement: HTMLSelectElement) {
selectElement.addEventListener('blur', this);
selectElement.addEventListener('focus', this);
selectElement.addEventListener('change', this);
}
selectTargetDisconnected(selectElement: HTMLSelectElement) {
console.log('selectTargetDisconnected');
selectElement.removeEventListener('blur', this);
selectElement.removeEventListener('focus', this);
selectElement.removeEventListener('change', this);
}
handleEvent(event: Event) {
switch (event.type) {
case 'focus':
this.onFocus(event);
break;
case 'change':
this.onChange(event);
break;
}
}
private onFocus(event: Event): void {
const focusedSelect = event.target as HTMLSelectElement;
const focusedSelectStableId = this.getStableIdForSelect(focusedSelect);
const template = this.element.querySelector<HTMLElement>(
`#${this.templateIdValue}`
);
if (template) {
const fragment = template.cloneNode(true) as HTMLSelectElement;
const options = Array.from(fragment.querySelectorAll('option'))
.map((option) => {
if (option.value == focusedSelectStableId) {
option.setAttribute('selected', 'selected');
}
return option.outerHTML;
})
.join('');
focusedSelect.innerHTML = options;
}
}
private onChange(event: Event): void {
const changedSelectTarget = event.target as HTMLSelectElement;
const stableIdDidChange =
changedSelectTarget.value !=
this.getStableIdForSelect(changedSelectTarget);
if (!stableIdDidChange) {
// prevent to bulble up
event.stopImmediatePropagation();
}
}
private getStableIdForSelect(select: HTMLSelectElement): string | null {
return select.getAttribute('data-selected');
}
}

View file

@ -1,3 +1,11 @@
- if @coordinate.present?
- if @coordinate.parent.present?
- c = TypesDeChampEditor::SelectChampTemplatePositionComponent.new(block: @coordinate.parent, coordinates: @coordinate.parent.revision_types_de_champ)
- else
- c = TypesDeChampEditor::SelectChampTemplatePositionComponent.new(block: @coordinate.revision, coordinates: @coordinate.private? ? @coordinate.revision.revision_types_de_champ_private : @coordinate.revision.revision_types_de_champ_public)
= turbo_stream.replace(c.block_id) do
= render c
= turbo_stream.replace 'breadcrumbs' , render(partial: 'administrateurs/breadcrumbs', = turbo_stream.replace '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)],