From af53a9b9dbde867a84bf927d7a21e0efc530d09a Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Wed, 15 Nov 2023 09:53:07 +0100 Subject: [PATCH] attestation_template v2: edit / update --- .../attestation_template_2_edit.scss | 16 ++ .../attestation_template_v2s_controller.rb | 13 ++ .../controllers/attestation_controller.ts | 175 ++++++++++++++++++ .../attestation_template_v2s/edit.html.haml | 10 + config/routes.rb | 2 +- 5 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 app/assets/stylesheets/attestation_template_2_edit.scss create mode 100644 app/javascript/controllers/attestation_controller.ts create mode 100644 app/views/administrateurs/attestation_template_v2s/edit.html.haml diff --git a/app/assets/stylesheets/attestation_template_2_edit.scss b/app/assets/stylesheets/attestation_template_2_edit.scss new file mode 100644 index 000000000..2ac705fe1 --- /dev/null +++ b/app/assets/stylesheets/attestation_template_2_edit.scss @@ -0,0 +1,16 @@ +#attestation-edit { + .mention { + border: 1px solid var(--text-default-grey); + padding: 8px; + } + + .selected { + border: 1px solid #000000; + } + + .tiptap { + padding: 8px; + + min-height: 300px; + } +} diff --git a/app/controllers/administrateurs/attestation_template_v2s_controller.rb b/app/controllers/administrateurs/attestation_template_v2s_controller.rb index 747da384a..6783ba8f8 100644 --- a/app/controllers/administrateurs/attestation_template_v2s_controller.rb +++ b/app/controllers/administrateurs/attestation_template_v2s_controller.rb @@ -9,9 +9,22 @@ module Administrateurs render layout: 'attestation' end + def edit + end + + def update + @attestation_template + .update(json_body: editor_params) + end + private def retrieve_attestation_template @attestation_template = @procedure.attestation_template || @procedure.build_attestation_template end + + def editor_params + params.permit(content: [:type, content: [:type, :text, attrs: [:id, :label]]]) + end + end end diff --git a/app/javascript/controllers/attestation_controller.ts b/app/javascript/controllers/attestation_controller.ts new file mode 100644 index 000000000..5731105a1 --- /dev/null +++ b/app/javascript/controllers/attestation_controller.ts @@ -0,0 +1,175 @@ +import { ApplicationController } from './application_controller'; +import { Editor } from '@tiptap/core'; +import StarterKit from '@tiptap/starter-kit'; +import Mention from '@tiptap/extension-mention'; +import tippy from 'tippy.js'; +import { httpRequest } from '@utils'; + +export class AttestationController extends ApplicationController { + static values = { + tags: Array, + url: String + }; + + static targets = ['editor', 'bold']; + + declare readonly tagsValue: string[]; + declare readonly urlValue: string; + declare editor: Editor; + declare editorTarget: HTMLElement; + declare boldTarget: HTMLButtonElement; + + connect() { + const conf = { + element: this.editorTarget, + editorProps: { + attributes: { + class: 'fr-input' + } + }, + extensions: [ + StarterKit, + Mention.configure({ + HTMLAttributes: { + class: 'mention' + }, + suggestion: { + items: ({ query }) => { + return this.tagsValue + .filter((item) => + item.toLowerCase().startsWith(query.toLowerCase()) + ) + .slice(0, 5); + }, + + render: () => { + let popup: { setProps: Function, hide: Function, destroy: Function }[]; + let div: HTMLElement; + let selectedIndex = 0; + let items: string[]; + let command: (props: object) => void; + + const makeList = () => { + return items + .map((item, i) => { + if (i == selectedIndex) { + return `
  • ${item}
  • `; + } else { + return `
  • ${item}
  • `; + } + }) + .join(''); + }; + + return { + onStart: (props) => { + items = props.items; + command = props.command; + + div = document.createElement('UL'); + div.innerHTML = makeList(); + + if (!props.clientRect) { + return; + } + + let body: Element = document.body; + + popup = tippy(body, { + getReferenceClientRect: props.clientRect, + appendTo: () => this.element, + content: div, + showOnCreate: true, + interactive: true, + trigger: 'manual', + placement: 'bottom-start' + }); + }, + + onUpdate(props) { + command = props.command; + items = props.items; + + div.innerHTML = makeList(); + + if (!props.clientRect) { + return; + } + + popup[0].setProps({ + getReferenceClientRect: props.clientRect + }); + }, + + onKeyDown(props) { + if (props.event.key === 'Escape') { + popup[0].hide(); + + return true; + } + + if (props.event.key === 'ArrowDown') { + selectedIndex = (selectedIndex + 1) % items.length; + div.innerHTML = makeList(); + return true; + } + + if (props.event.key === 'ArrowUp') { + selectedIndex = + (selectedIndex + items.length - 1) % items.length; + div.innerHTML = makeList(); + return true; + } + + if (props.event.key === 'Enter') { + const item = items[selectedIndex]; + + if (item) { + command({ id: item }); + } + return true; + } + + return false; + }, + + onExit() { + popup[0].destroy(); + div.remove(); + } + }; + } + } + }) + ], + content: + '

    La situation de M. dont la demande de logement social

    ' + }; + + this.editor = new Editor(conf); + + this.editor.on('transaction', () => { + this.boldTarget.disabled = !this.editor + .can() + .chain() + .focus() + .toggleBold() + .run(); + + if (this.editor.isActive('bold')) { + this.boldTarget.classList.add('fr-btn--secondary'); + } else { + this.boldTarget.classList.remove('fr-btn--secondary'); + } + }); + } + + bold() { + this.editor.chain().focus().toggleBold().run(); + } + + send() { + const json = this.editor.getJSON(); + httpRequest(this.urlValue, { method: 'put', json }).json(); + } +} diff --git a/app/views/administrateurs/attestation_template_v2s/edit.html.haml b/app/views/administrateurs/attestation_template_v2s/edit.html.haml new file mode 100644 index 000000000..592c89661 --- /dev/null +++ b/app/views/administrateurs/attestation_template_v2s/edit.html.haml @@ -0,0 +1,10 @@ +#attestation-edit.fr-container.mt-2{ + data: { + controller: 'attestation', + attestation_tags_value: @attestation_template.tags.map { _1[:libelle] }, + attestation_url_value: admin_procedure_attestation_template_v2_path(@procedure)} } + + %button.fr-btn{ data: { action: 'click->attestation#bold', attestation_target: 'bold' } } Gras + .editor.mt-2{ data: { attestation_target: 'editor' } } + + %button.fr-btn.mt-2{ data: { action: 'click->attestation#send' } } Envoyer diff --git a/config/routes.rb b/config/routes.rb index 08004cbe5..0399382cc 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -626,7 +626,7 @@ Rails.application.routes.draw do get 'add_champ_engagement_juridique' end - resource :attestation_template_v2, only: [:show] + resource :attestation_template_v2, only: [:show, :edit, :update] resource :dossier_submitted_message, only: [:edit, :update, :create] # ADDED TO ACCESS IT FROM THE IFRAME