attestation_template v2: edit / update
This commit is contained in:
parent
f6001c8eae
commit
af53a9b9db
5 changed files with 215 additions and 1 deletions
16
app/assets/stylesheets/attestation_template_2_edit.scss
Normal file
16
app/assets/stylesheets/attestation_template_2_edit.scss
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
175
app/javascript/controllers/attestation_controller.ts
Normal file
175
app/javascript/controllers/attestation_controller.ts
Normal file
|
@ -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 `<li class='selected'>${item}</li>`;
|
||||
} else {
|
||||
return `<li>${item}</li>`;
|
||||
}
|
||||
})
|
||||
.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:
|
||||
'<p>La situation de M. <span data-type="mention" data-id="nom"></span> dont la demande de logement social</p>'
|
||||
};
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue