Added confirmation dialog to delete forms

This commit is contained in:
Igor Scheller 2023-11-05 01:27:12 +01:00
parent 1b21bcf769
commit ff179360cc
10 changed files with 102 additions and 14 deletions

View File

@ -275,6 +275,71 @@ ready(() => {
document.querySelectorAll('.modal').forEach((element) => new bootstrap.Modal(element)); document.querySelectorAll('.modal').forEach((element) => new bootstrap.Modal(element));
}); });
/**
* Show confirmation modal before submitting form
*
* Uses the buttons data attributes to show in the modal:
* - data-confirm_title: Optional title of the modal
* - data-confirm_submit: Body of the modal
*
* The class, title and content of the requesting button gets copied for confirmation
*
*/
ready(() => {
document.querySelectorAll('[data-confirm_submit_title], [data-confirm_submit_text]').forEach((element) => {
let modalOpen = false;
let oldType = element.type;
if (element.type !== 'submit') {
return;
}
element.type = 'button';
element.addEventListener('click', (event) => {
if (modalOpen) {
return;
}
event.preventDefault();
document.getElementById('confirmation-modal')?.remove();
document.body.insertAdjacentHTML(
'beforeend',
`
<div class="modal" tabindex="-1" id="confirmation-modal">
<div class="modal-dialog">
<div class="modal-content ${document.body.dataset.theme_type === 'light' ? 'bg-white' : 'bg-dark'}">
<div class="modal-header">
<h5 class="modal-title">${element.dataset.confirm_submit_title ?? ''}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body${element.dataset.confirm_submit_text ? '' : ' d-none'}">
<p>${element.dataset.confirm_submit_text ?? ''}</p>
</div>
<div class="modal-footer">
<button type="button" class="${element.className}"
title="${element.title}" data-submit="">${element.innerHTML}</button>
</div>
</div>
</div>
</div>
`
);
let modal = document.getElementById('confirmation-modal');
modal.addEventListener('hide.bs.modal', () => {
modalOpen = false;
});
modal.querySelector('[data-submit]').addEventListener('click', (event) => {
element.type = oldType;
element.click();
});
modalOpen = true;
let bootstrapModal = new bootstrap.Modal(modal);
bootstrapModal.show();
});
});
});
/** /**
* Show oauth buttons on welcome title click * Show oauth buttons on welcome title click
*/ */

View File

@ -1989,3 +1989,6 @@ msgstr "Was möchtest Du machen?"
msgid "registration.register" msgid "registration.register"
msgstr "Registrieren" msgstr "Registrieren"
msgid "confirmation.delete"
msgstr "Möchtest du es wirklich löschen?"

View File

@ -644,3 +644,6 @@ msgstr "Please enter a lastname in your settings!"
msgid "mobile.required.hint" msgid "mobile.required.hint"
msgstr "Please enter a mobile number in your settings!" msgstr "Please enter a mobile number in your settings!"
msgid "confirmation.delete"
msgstr "Do you really want to delete it?"

View File

@ -57,7 +57,7 @@
<form method="post" class="ps-1"> <form method="post" class="ps-1">
{{ csrf() }} {{ csrf() }}
{{ f.hidden('id', location.id) }} {{ f.hidden('id', location.id) }}
{{ f.button(m.icon('trash'), {'title': __('form.delete'), 'name': 'delete', 'type': 'submit', 'btn_type': 'danger', 'size': 'sm'}) }} {{ f.delete(null, {'size': 'sm','confirm_title': location.name|e}) }}
</form> </form>
</div> </div>

View File

@ -23,7 +23,7 @@
{% endblock %} {% endblock %}
</head> </head>
<body> <body data-theme_type="{{ theme.type }}">
{% block body %} {% block body %}
{% block header %} {% block header %}

View File

@ -261,6 +261,8 @@ Renders a button.
Must be a Bootstrap icon class without prefix, such as "info" or "check". Must be a Bootstrap icon class without prefix, such as "info" or "check".
@param {string} [opt.icon_right] - Optional icon to be added after the button label. @param {string} [opt.icon_right] - Optional icon to be added after the button label.
Must be a Bootstrap icon class without prefix, such as "info" or "check". Must be a Bootstrap icon class without prefix, such as "info" or "check".
@param {string} [opt.confirm_title] - Optional value for the confirmation title.
@param {string} [opt.confirm_text] - Optional value for the confirmation text.
#} #}
{% macro button(label, opt) %} {% macro button(label, opt) %}
<button <button
@ -270,6 +272,8 @@ Renders a button.
{%- if opt.name is defined %} name="{{ opt.name }}"{% endif %} {%- if opt.name is defined %} name="{{ opt.name }}"{% endif %}
{%- if opt.title is defined %} title="{{ opt.title }}"{% endif %} {%- if opt.title is defined %} title="{{ opt.title }}"{% endif %}
{%- if opt.value is defined or opt.name is defined %} value="{{ opt.value|default('1') }}"{% endif -%} {%- if opt.value is defined or opt.name is defined %} value="{{ opt.value|default('1') }}"{% endif -%}
{%- if opt.confirm_title is defined %} data-confirm_submit_title="{{ opt.confirm_title }}"{% endif -%}
{%- if opt.confirm_text is defined %} data-confirm_submit_text="{{ opt.confirm_text }}"{% endif -%}
> >
{%- if opt.icon_left is defined %}<span class="bi bi-{{ opt.icon_left }}"></span>{% endif %} {%- if opt.icon_left is defined %}<span class="bi bi-{{ opt.icon_left }}"></span>{% endif %}
{{ label }} {{ label }}
@ -281,6 +285,16 @@ Renders a button.
{{ _self.button(label|default(__('form.submit')), {'type': 'submit', 'btn_type': 'primary'}|merge(opt|default({}))) }} {{ _self.button(label|default(__('form.submit')), {'type': 'submit', 'btn_type': 'primary'}|merge(opt|default({}))) }}
{%- endmacro %} {%- endmacro %}
{% macro delete(label, opt) %}
{{ _self.submit(label|default(' '), {
'icon_left': 'trash',
'title': __('form.delete'),
'name': 'delete',
'btn_type': 'danger',
'confirm_text': __('confirmation.delete')
}|merge(opt|default({}))) }}
{%- endmacro %}
{# {#
Renders a "checkbox" element that will be styled as switch. Renders a "checkbox" element that will be styled as switch.

View File

@ -354,10 +354,14 @@
'title': 'Click me!', 'title': 'Click me!',
}) }} }) }}
</div> </div>
<code>f.submit(label)</code> <code>f.submit(label, opt)</code>
<form id="form"> <form class="prevent-default">
{{ f.submit('Go!') }} {{ f.submit('Go!') }}
</form> </form>
<code>f.delete(label, opt)</code>
<form class="prevent-default">
{{ f.delete('Delete it', {'confirm_title': 'Delete some item'}) }}
</form>
</div> </div>
<div id="checkboxes" class="col-md-3 col-lg-2"> <div id="checkboxes" class="col-md-3 col-lg-2">
@ -529,9 +533,11 @@ Por scientie, musica, sport etc, litot Europa usa li sam vocabular.</code></pre>
</div> </div>
</div> </div>
<script> <script>
document.getElementById('form').addEventListener('submit', (e) => { [...document.getElementsByClassName('prevent-default')].forEach((element) => {
e.preventDefault(); element.addEventListener('submit', (e) => {
return false; e.preventDefault();
}); return false;
});
})
</script> </script>
{% endblock %} {% endblock %}

View File

@ -33,7 +33,7 @@
action="{{ url('/news/comment/' ~ comment.id) }}" enctype="multipart/form-data" action="{{ url('/news/comment/' ~ comment.id) }}" enctype="multipart/form-data"
method="post"> method="post">
{{ csrf() }} {{ csrf() }}
{{ f.submit(m.icon('trash'), {'name': 'delete', 'btn_type': 'danger', 'size': 'sm', 'title': __('form.delete')}) }} {{ f.delete(null, {'size': 'sm', 'confirm_title': comment.text[:40]|e}) }}
</form> </form>
</div> </div>
{% endif %} {% endif %}

View File

@ -54,7 +54,7 @@
> >
{{ csrf() }} {{ csrf() }}
{{ f.hidden('id', question.id) }} {{ f.hidden('id', question.id) }}
{{ f.submit(m.icon('trash'), {'name': 'delete', 'btn_type': 'danger', 'size': 'sm', 'title': __('form.delete')}) }} {{ f.delete(null, {'size': 'sm', 'confirm_title': question.text[:40]|e}) }}
</form> </form>
{% endif %} {% endif %}

View File

@ -20,10 +20,7 @@
<form action="" enctype="multipart/form-data" method="post"> <form action="" enctype="multipart/form-data" method="post">
{{ csrf() }} {{ csrf() }}
{{ f.hidden('id', 'all') }} {{ f.hidden('id', 'all') }}
{{ f.submit( {{ f.delete(__('form.delete_all'), {'size': 'sm', 'confirm_title': __('form.delete_all')}) }}
__('form.delete_all'),
{'name': 'delete', 'btn_type': 'danger', 'size': 'sm', 'icon_left': 'trash'}
) }}
</form> </form>
{% endif %} {% endif %}
</th> </th>