feat: guard to prevent premature form submissions while uploading
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import { Controller } from '@hotwired/stimulus'
|
||||
|
||||
export default class extends Controller {
|
||||
|
||||
static targets = ['submit']
|
||||
|
||||
connect () {
|
||||
this.uploading = false
|
||||
this.boundOnUploading = this.onUploading.bind(this)
|
||||
this.boundOnComplete = this.onComplete.bind(this)
|
||||
window.addEventListener('dropzone:uploading', this.boundOnUploading)
|
||||
window.addEventListener('dropzone:complete', this.boundOnComplete)
|
||||
}
|
||||
|
||||
onUploading () {
|
||||
this.uploading = true
|
||||
this.submitTargets.forEach(button => {
|
||||
button.disabled = true
|
||||
})
|
||||
}
|
||||
|
||||
onComplete () {
|
||||
this.uploading = false
|
||||
this.submitTargets.forEach(button => {
|
||||
button.disabled = false
|
||||
})
|
||||
}
|
||||
|
||||
guard (event) {
|
||||
if (this.uploading) {
|
||||
event.preventDefault()
|
||||
event.stopImmediatePropagation()
|
||||
}
|
||||
}
|
||||
|
||||
disconnect () {
|
||||
window.removeEventListener('dropzone:uploading', this.boundOnUploading)
|
||||
window.removeEventListener('dropzone:complete', this.boundOnComplete)
|
||||
}
|
||||
}
|
||||
@@ -73,7 +73,7 @@ export default class extends Controller {
|
||||
})
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
disconnect () {
|
||||
this.dropzone.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.btn {
|
||||
@apply inline-flex space-x-1 justify-center rounded-lg text-sm uppercase font-semibold py-2.5 px-4;
|
||||
@apply bg-primary text-white hover:bg-primary/80 shadow-md;
|
||||
@apply bg-primary text-white hover:bg-primary/80 shadow-md disabled:opacity-50 disabled:cursor-not-allowed;
|
||||
}
|
||||
|
||||
.btn--small {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{{ form_start(form, { 'attr': { 'hx-post': app.request.uri, 'hx-target': '#htmx-modal', 'hx-swap': 'outerHTML' } }) }}
|
||||
{% set formAttr = stimulus_controller('form-upload-guard')|stimulus_action('form-upload-guard', 'guard', 'submit') %}
|
||||
{{ form_start(form, { 'attr': { 'hx-post': app.request.uri, 'hx-target': '#htmx-modal', 'hx-swap': 'outerHTML' }|merge(formAttr.toArray()) }) }}
|
||||
<div class="flex flex-col space-y-4 pb-4">
|
||||
{{ form_row(form.category) }}
|
||||
{{ form_row(form.name) }}
|
||||
@@ -18,7 +19,7 @@
|
||||
{{ form_errors(form) }}
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn">
|
||||
<button type="submit" class="btn" {{ stimulus_target('form-upload-guard', 'submit') }}>
|
||||
speichern
|
||||
</button>
|
||||
{{ form_rest(form) }}
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
{% block title %}{{ modalTitle }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{{ form_start(form, { 'attr': { 'hx-post': app.request.uri, 'hx-target': '#htmx-modal', 'hx-swap': 'outerHTML' }}) }}
|
||||
{% set formAttr = stimulus_controller('form-upload-guard')|stimulus_action('form-upload-guard', 'guard', 'submit') %}
|
||||
{{ form_start(form, { 'attr': { 'hx-post': app.request.uri, 'hx-target': '#htmx-modal', 'hx-swap': 'outerHTML' }|merge(formAttr.toArray()) }) }}
|
||||
<div class="pb-4">
|
||||
{% include '_partials/_upload_collection_form.html.twig' with {
|
||||
'endpoint_upload': path('_uploader_upload_contract'),
|
||||
@@ -12,7 +13,7 @@
|
||||
'accepted_files': 'image/jpg,image/jpeg,application/pdf',
|
||||
} %}
|
||||
</div>
|
||||
<button type="submit" class="btn">
|
||||
<button type="submit" class="btn" {{ stimulus_target('form-upload-guard', 'submit') }}>
|
||||
Upload speichern
|
||||
</button>
|
||||
{{ form_rest(form) }}
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
{% block title %}Dokument ersetzen{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{{ form_start(form, { 'attr': { 'hx-post': app.request.uri, 'hx-target': '#htmx-modal', 'hx-swap': 'outerHTML' } }) }}
|
||||
{% set formAttr = stimulus_controller('form-upload-guard')|stimulus_action('form-upload-guard', 'guard', 'submit') %}
|
||||
{{ form_start(form, { 'attr': { 'hx-post': app.request.uri, 'hx-target': '#htmx-modal', 'hx-swap': 'outerHTML' }|merge(formAttr.toArray()) }) }}
|
||||
<div class="pb-4">
|
||||
{% include '_partials/_upload_collection_form.html.twig' with {
|
||||
'endpoint_upload': path('_uploader_upload_document'),
|
||||
@@ -12,7 +13,7 @@
|
||||
'accepted_files': 'application/pdf',
|
||||
} %}
|
||||
</div>
|
||||
<button type="submit" class="btn">
|
||||
<button type="submit" class="btn" {{ stimulus_target('form-upload-guard', 'submit') }}>
|
||||
ersetzen
|
||||
</button>
|
||||
{{ form_rest(form) }}
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
{% block title %}Dokumente hinzufügen{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{{ form_start(form, { 'attr': { 'hx-post': app.request.uri, 'hx-target': '#htmx-modal', 'hx-swap': 'outerHTML' }}) }}
|
||||
{% set formAttr = stimulus_controller('form-upload-guard')|stimulus_action('form-upload-guard', 'guard', 'submit') %}
|
||||
{{ form_start(form, { 'attr': { 'hx-post': app.request.uri, 'hx-target': '#htmx-modal', 'hx-swap': 'outerHTML' }|merge(formAttr.toArray()) }) }}
|
||||
<div class="pb-4">
|
||||
{% include '_partials/_upload_collection_form.html.twig' with {
|
||||
'endpoint_upload': path('_uploader_upload_document'),
|
||||
@@ -11,7 +12,7 @@
|
||||
'accepted_files': 'application/pdf',
|
||||
} %}
|
||||
</div>
|
||||
<button type="submit" class="btn">
|
||||
<button type="submit" class="btn" {{ stimulus_target('form-upload-guard', 'submit') }}>
|
||||
Uploads speichern
|
||||
</button>
|
||||
{{ form_rest(form) }}
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
{{ icon('check') }}
|
||||
</button>
|
||||
{% endif %}
|
||||
{% if teamer.user.disabled %}
|
||||
{% if teamer.user is not null and teamer.user.disabled %}
|
||||
{% if is_granted('ROLE_ADMIN') %}
|
||||
<button type="button"
|
||||
role="menuitem"
|
||||
@@ -134,7 +134,7 @@
|
||||
{{ icon('user') }}
|
||||
</a>
|
||||
</div>
|
||||
{% if teamer.user.disabled %}
|
||||
{% if teamer.user is not null and teamer.user.disabled %}
|
||||
<div class="py-1 px-2 mt-2 text-xs bg-red-500 text-white">
|
||||
gesp. am {{ teamer.user.disabledAt | date('d.m.Y') }}
|
||||
</div>
|
||||
|
||||
@@ -47,7 +47,8 @@
|
||||
|
||||
{# New upload #}
|
||||
{% if workflow_can(disposition, 'upload_contract') %}
|
||||
{{ form_start(form) }}
|
||||
{% set formAttr = stimulus_controller('form-upload-guard')|stimulus_action('form-upload-guard', 'guard', 'submit') %}
|
||||
{{ form_start(form, { 'attr': formAttr.toArray() }) }}
|
||||
<div class="flex flex-col space-y-4">
|
||||
<a href="{{ path('app_teamer_disposition_contractpdf', { 'uuid': disposition.uuid }) }}" target="_blank" class="inline-block">
|
||||
<img src="{{ asset('build/images/contract_thumb.jpg') }}" alt="Honorarvertrag" class="block w-32 h-auto shadow-md">
|
||||
@@ -62,7 +63,7 @@
|
||||
{% if form.pickup is defined %}
|
||||
{{ form_row(form.pickup) }}
|
||||
{% endif %}
|
||||
<button type="submit" class="btn">
|
||||
<button type="submit" class="btn" {{ stimulus_target('form-upload-guard', 'submit') }}>
|
||||
Aktualisieren
|
||||
</button>
|
||||
</div>
|
||||
@@ -94,7 +95,8 @@
|
||||
|
||||
{# New invoice #}
|
||||
{% if workflow_can(disposition, 'upload_invoice') %}
|
||||
{{ form_start(form) }}
|
||||
{% set formAttr = stimulus_controller('form-upload-guard')|stimulus_action('form-upload-guard', 'guard', 'submit') %}
|
||||
{{ form_start(form, { 'attr': formAttr.toArray() }) }}
|
||||
<div class="flex flex-col space-y-4">
|
||||
<a href="{{ path('app_teamer_disposition_invoicepdf', { 'uuid': disposition.uuid }) }}" target="_blank" class="inline-block">
|
||||
<img src="{{ asset('build/images/invoice_thumb.jpg') }}" alt="Honorarnote" class="block w-32 h-auto shadow-md">
|
||||
@@ -106,7 +108,7 @@
|
||||
'endpoint_upload': path('_uploader_upload_invoice'),
|
||||
'accepted_files': 'image/jpg,image/jpeg,application/pdf',
|
||||
} %}
|
||||
<button type="submit" class="btn">
|
||||
<button type="submit" class="btn" {{ stimulus_target('form-upload-guard', 'submit') }}>
|
||||
Aktualisieren
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
{% endmacro %}
|
||||
|
||||
{% block content %}
|
||||
{{ form_start(form) }}
|
||||
{% set formAttr = stimulus_controller('form-upload-guard')|stimulus_action('form-upload-guard', 'guard', 'submit') %}
|
||||
{{ form_start(form, { 'attr': formAttr.toArray() }) }}
|
||||
|
||||
<div {{ stimulus_controller('tabs', {}, { 'buttonActive': 'bg-gray-50' }) }}>
|
||||
<div class="grid lg:grid-cols-3 gap-y-8 lg:gap-y-0 lg:gap-x-16">
|
||||
@@ -167,7 +168,7 @@
|
||||
} %}
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn">
|
||||
<button type="submit" class="btn" {{ stimulus_target('form-upload-guard', 'submit') }}>
|
||||
Aktualisieren
|
||||
</button>
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
{% block title %}Lizenz hinzufügen{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{{ form_start(form, { 'attr': { 'hx-post': app.request.uri, 'hx-target': '#htmx-modal', 'hx-swap': 'outerHTML' } }) }}
|
||||
{% set formAttr = stimulus_controller('form-upload-guard')|stimulus_action('form-upload-guard', 'guard', 'submit') %}
|
||||
{{ form_start(form, { 'attr': { 'hx-post': app.request.uri, 'hx-target': '#htmx-modal', 'hx-swap': 'outerHTML' }|merge(formAttr.toArray()) }) }}
|
||||
{% if not form.vars.valid %}
|
||||
<div class="border border-red-500 rounded-md p-4 text-red-500 mb-4">
|
||||
{% include '_partials/_form_errors.html.twig' with { 'form': form } %}
|
||||
@@ -23,7 +24,7 @@
|
||||
} %}
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn">
|
||||
<button type="submit" class="btn" {{ stimulus_target('form-upload-guard', 'submit') }}>
|
||||
Speichern
|
||||
</button>
|
||||
{{ form_rest(form) }}
|
||||
|
||||
Reference in New Issue
Block a user