From 2144b3fe20b9405075c806b8f62a934b5c20b071 Mon Sep 17 00:00:00 2001 From: catborise Date: Wed, 21 Oct 2026 21:13:35 +0300 Subject: [PATCH] fix(templates): each confirmation says what its action does Twenty-five prompts asked only "Are you sure?", and on the storage page one handler asked the same before every button, Start and Enable included. Each destructive button now names its object and says what happens: a stopped network cuts running VMs off, a deleted pool keeps its files, a deleted volume loses its data, a reverted snapshot loses the changes made since. Saves no longer ask, and disabled buttons lose prompts they could not show. The VM QoS messages said to restart the network where the VM has to be powered off and on. Co-Authored-By: Claude Opus 5.5 (1M context) --- instances/templates/create_instance_w2.html | 2 +- .../instances/edit_instance_volume.html | 2 +- .../templates/instances/settings_tab.html | 14 ++++----- .../templates/instances/snapshots_tab.html | 4 +-- instances/views.py | 10 ++----- interfaces/templates/interface.html | 4 +-- networks/templates/network.html | 22 +++++++------- nwfilters/templates/nwfilter.html | 4 +-- nwfilters/templates/nwfilters.html | 2 +- storages/templates/storage.html | 24 +++++++-------- virtsecrets/templates/secrets.html | 2 +- webvirtcloud/tests/test_confirm_prompts.py | 29 +++++++++++++++++++ 12 files changed, 70 insertions(+), 49 deletions(-) create mode 100644 webvirtcloud/tests/test_confirm_prompts.py diff --git a/instances/templates/create_instance_w2.html b/instances/templates/create_instance_w2.html index 22876f10..8b38749f 100644 --- a/instances/templates/create_instance_w2.html +++ b/instances/templates/create_instance_w2.html @@ -323,7 +323,7 @@
{% csrf_token %} -
diff --git a/instances/templates/instances/edit_instance_volume.html b/instances/templates/instances/edit_instance_volume.html index 7e93cff1..d4aff411 100644 --- a/instances/templates/instances/edit_instance_volume.html +++ b/instances/templates/instances/edit_instance_volume.html @@ -109,7 +109,7 @@
diff --git a/instances/templates/instances/settings_tab.html b/instances/templates/instances/settings_tab.html index 09dd4f7d..e8ebf056 100644 --- a/instances/templates/instances/settings_tab.html +++ b/instances/templates/instances/settings_tab.html @@ -312,11 +312,11 @@ {% if instance.status == 5 %} - {% else %} - {% endif %} @@ -328,11 +328,11 @@ {% if instance.status == 5 %} - {% else %} - {% endif %} @@ -478,7 +478,7 @@
{% csrf_token %}
@@ -556,7 +556,7 @@ @@ -566,7 +566,7 @@ diff --git a/instances/templates/instances/snapshots_tab.html b/instances/templates/instances/snapshots_tab.html index 40592410..d21797a2 100755 --- a/instances/templates/instances/snapshots_tab.html +++ b/instances/templates/instances/snapshots_tab.html @@ -107,7 +107,7 @@ {% csrf_token %}{% submission_key %} {% if instance.status == 5 %} - {% else %} @@ -121,7 +121,7 @@
{% csrf_token %} -
diff --git a/instances/views.py b/instances/views.py index e4ed2119..b5be7e12 100755 --- a/instances/views.py +++ b/instances/views.py @@ -1685,10 +1685,7 @@ def set_qos(request, pk): else: messages.success( request, - _( - "%(qos_dir)s QoS is set. Network XML is changed. \ - Stop and start network to activate new config." - ) + _("%(qos_dir)s QoS is set. A running VM gets it after it is powered off and on.") % {"qos_dir": qos_dir.capitalize()}, ) @@ -1714,10 +1711,7 @@ def unset_qos(request, pk): else: messages.success( request, - _( - "%(qos_dir)s QoS is deleted. Network XML is changed. \ - Stop and start network to activate new config." - ) + _("%(qos_dir)s QoS is deleted. A running VM keeps the old limit until it is powered off and on.") % {"qos_dir": qos_dir.capitalize()}, ) return _back(request, pk, "network") diff --git a/interfaces/templates/interface.html b/interfaces/templates/interface.html index 8ae23f8d..21ff5f29 100644 --- a/interfaces/templates/interface.html +++ b/interfaces/templates/interface.html @@ -63,9 +63,9 @@
{% csrf_token %} {% if state == 0 %} - + {% else %} - + {% endif %}
{% endif %} diff --git a/networks/templates/network.html b/networks/templates/network.html index 2d093ebf..b608d4bd 100644 --- a/networks/templates/network.html +++ b/networks/templates/network.html @@ -49,9 +49,9 @@
{% csrf_token %} {% if state == 0 %} - + {% else %} - + {% endif %}
@@ -61,7 +61,7 @@ {% if autostart == 0 %} {% else %} - + {% endif %} @@ -136,7 +136,7 @@ value="Apply" name="modify_dhcp_range" title="{% trans "Edit DHCP Range" %}" - onclick="return confirm('{% trans "Are you sure?" %}')"/> +/> @@ -190,12 +190,12 @@ @@ -251,7 +251,7 @@ value="Apply" name="modify_dhcp_range" title="{% trans "Edit DHCP Range" %}" - onclick="return confirm('{% trans "Are you sure?" %}')"/> +/> @@ -301,12 +301,12 @@ @@ -358,12 +358,12 @@ diff --git a/nwfilters/templates/nwfilter.html b/nwfilters/templates/nwfilter.html index e073a96b..aeb29594 100644 --- a/nwfilters/templates/nwfilter.html +++ b/nwfilters/templates/nwfilter.html @@ -104,7 +104,7 @@
{% csrf_token %} -
@@ -148,7 +148,7 @@ - diff --git a/nwfilters/templates/nwfilters.html b/nwfilters/templates/nwfilters.html index 7f3e08a1..9e56c140 100644 --- a/nwfilters/templates/nwfilters.html +++ b/nwfilters/templates/nwfilters.html @@ -116,7 +116,7 @@
{% csrf_token %} -
diff --git a/storages/templates/storage.html b/storages/templates/storage.html index 214eaace..65dc4ee6 100644 --- a/storages/templates/storage.html +++ b/storages/templates/storage.html @@ -59,24 +59,27 @@
{{ used|filesizeformat }}
{% trans "State" %}
-
{% csrf_token %} + {% csrf_token %} {% if state == 0 %} - + {% else %} - + {% endif %}
{% trans "Autostart" %}
-
{% csrf_token %} + {% csrf_token %} {% if autostart == 0 %} {% else %} + value="{% trans "Disable" %}" + data-confirm="{% blocktrans with name=pool %}Disable autostart of pool {{ name }}? After the host restarts it stays stopped.{% endblocktrans %}" onclick="return confirm(this.dataset.confirm)"> {% endif %}
@@ -172,9 +175,10 @@ {% endif %} -
{% csrf_token %} + {% csrf_token %} -
@@ -221,12 +225,6 @@ }); $(document).ready(function() { - $('.confirm-form').on('submit', function(e) { - if (!confirm('{% trans "Are you sure?"|escapejs %}')) { - e.preventDefault(); - } - }); - var pendingUpload = null; var uploadInProgress = false; // the browser sends the file: leaving the page stops the upload diff --git a/virtsecrets/templates/secrets.html b/virtsecrets/templates/secrets.html index 40d235e4..3648c5ad 100644 --- a/virtsecrets/templates/secrets.html +++ b/virtsecrets/templates/secrets.html @@ -76,7 +76,7 @@ {% bs_icon 'pencil' %} - diff --git a/webvirtcloud/tests/test_confirm_prompts.py b/webvirtcloud/tests/test_confirm_prompts.py new file mode 100644 index 00000000..7595488a --- /dev/null +++ b/webvirtcloud/tests/test_confirm_prompts.py @@ -0,0 +1,29 @@ +"""A confirmation says what its action does: every prompt in a template is the +button's own data-confirm text, shown by return confirm(this.dataset.confirm).""" + +from pathlib import Path + +from django.conf import settings +from django.test import SimpleTestCase + +ONCLICK = 'onclick="return confirm(this.dataset.confirm)"' + + +class ConfirmPromptTests(SimpleTestCase): + def test_every_prompt_is_the_buttons_own_text(self): + base = Path(settings.BASE_DIR) + templates = [*base.glob("*/templates/**/*.html"), *base.glob("templates/**/*.html")] + self.assertTrue(templates) + for path in templates: + text = path.read_text() + at = text.find("confirm(") + while at != -1: + # the tag around it: prompt texts and template tags hold no < or > + tag = text[text.rfind("<", 0, at):text.find(">", at) + 1] + with self.subTest(template=str(path.relative_to(base)), tag=tag[:60]): + self.assertRegex(tag, r"^<(button|input|a)\b") + self.assertIn(ONCLICK, tag) + self.assertIn('data-confirm="', tag) + self.assertNotIn('data-confirm=""', tag) + self.assertNotIn("Are you sure", tag) + at = text.find("confirm(", at + 1)