From 78a1323fc29c531d6a9f2a9cab9e12f0ef2c8147 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Tue, 11 Oct 2022 11:33:09 +0200 Subject: [PATCH] refactor(dossier): move dossier submit action in to a new form --- .../controllers/autosave_submit_controller.ts | 61 +++++++++++++++++++ app/javascript/shared/utils.ts | 10 +++ app/views/shared/dossiers/_edit.html.haml | 29 +++++---- 3 files changed, 85 insertions(+), 15 deletions(-) create mode 100644 app/javascript/controllers/autosave_submit_controller.ts diff --git a/app/javascript/controllers/autosave_submit_controller.ts b/app/javascript/controllers/autosave_submit_controller.ts new file mode 100644 index 000000000..9f4021ef1 --- /dev/null +++ b/app/javascript/controllers/autosave_submit_controller.ts @@ -0,0 +1,61 @@ +import { isButtonElement } from '@utils'; + +import { ApplicationController } from './application_controller'; + +export class AutosaveSubmitController extends ApplicationController { + #isSaving = false; + #shouldSubmit = true; + #buttonText?: string; + + connect(): void { + this.onGlobal('autosave:enqueue', () => this.didEnqueue()); + this.onGlobal('autosave:end', () => this.didSucceed()); + this.onGlobal('autosave:error', () => this.didFail()); + this.on('click', (event) => this.onClick(event)); + } + + // Intercept form submit if autosave is still in progress + private onClick(event: Event) { + if (this.#isSaving) { + this.#shouldSubmit = true; + this.disableButton(); + event.preventDefault(); + } + } + + private didEnqueue() { + this.#isSaving = true; + this.#shouldSubmit = false; + } + + // If submit was previously requested, send it, now that autosave have finished + private didSucceed() { + if (this.#shouldSubmit && isButtonElement(this.element)) { + this.element.form?.requestSubmit(this.element); + } + this.#isSaving = false; + this.#shouldSubmit = false; + this.enableButton(); + } + + private didFail() { + this.#isSaving = false; + this.#shouldSubmit = false; + this.enableButton(); + } + + private disableButton() { + if (isButtonElement(this.element)) { + this.#buttonText = this.element.value; + this.element.value = this.element.dataset.disableWith ?? ''; + this.element.disabled = true; + } + } + + private enableButton() { + if (isButtonElement(this.element) && this.#buttonText) { + this.element.value = this.#buttonText; + this.element.disabled = false; + } + } +} diff --git a/app/javascript/shared/utils.ts b/app/javascript/shared/utils.ts index 108280557..9fdd9faca 100644 --- a/app/javascript/shared/utils.ts +++ b/app/javascript/shared/utils.ts @@ -277,6 +277,16 @@ export function isNumeric(s: string) { return !isNaN(n) && isFinite(n); } +export function isButtonElement( + element: Element +): element is HTMLButtonElement { + return ( + element.tagName == 'BUTTON' || + (element.tagName == 'INPUT' && + (element as HTMLInputElement).type == 'submit') + ); +} + export function isSelectElement( element: HTMLElement ): element is HTMLSelectElement { diff --git a/app/views/shared/dossiers/_edit.html.haml b/app/views/shared/dossiers/_edit.html.haml index 1575b43b3..55aabcb46 100644 --- a/app/views/shared/dossiers/_edit.html.haml +++ b/app/views/shared/dossiers/_edit.html.haml @@ -47,21 +47,20 @@ = fields_for champ.input_name, champ do |form| = render EditableChamp::EditableChampComponent.new form: form, champ: champ - - if !dossier.for_procedure_preview? - .dossier-edit-sticky-footer - .send-dossier-actions-bar - = render partial: 'shared/dossiers/autosave', locals: { dossier: dossier } + - if !dossier.for_procedure_preview? + .dossier-edit-sticky-footer + .send-dossier-actions-bar + = render partial: 'shared/dossiers/autosave', locals: { dossier: dossier } - - if dossier.can_transition_to_en_construction? - = f.button t('views.shared.dossiers.edit.submit_dossier'), - name: :submit_draft, - value: true, - class: 'fr-btn fr-btn--sm', - disabled: !current_user.owns?(dossier), - data: { 'disable-with': "Envoi en cours…" } + - if dossier.can_transition_to_en_construction? + = button_to t('views.shared.dossiers.edit.submit_dossier'), brouillon_dossier_url(dossier), + class: 'fr-btn fr-btn--sm', + disabled: !current_user.owns?(dossier), + method: :post, + data: { 'disable-with': "Envoi en cours…", controller: 'autosave-submit' } - - if dossier.brouillon? && !current_user.owns?(dossier) - .send-notice.invite-cannot-submit - En tant qu’invité, vous pouvez remplir ce formulaire – mais le titulaire du dossier doit le déposer lui-même. + - if dossier.brouillon? && !current_user.owns?(dossier) + .send-notice.invite-cannot-submit + En tant qu’invité, vous pouvez remplir ce formulaire – mais le titulaire du dossier doit le déposer lui-même. - = render partial: "shared/dossiers/submit_is_over", locals: { dossier: dossier } + = render partial: "shared/dossiers/submit_is_over", locals: { dossier: dossier }