From 4db98def79f844fdf9658cc4b8a140e029792c8b Mon Sep 17 00:00:00 2001 From: Lukas Bockstaller Date: Thu, 7 May 2026 10:53:52 +0200 Subject: [PATCH] add js to prevent illegal inputs --- src/pretix/base/reldate.py | 3 +- .../pretixbase/forms/widgets/reldate.html | 2 + .../pretixbase/forms/widgets/reldatetime.html | 2 + src/pretix/static/pretixbase/js/reldate.js | 44 +++++++++++++++++++ 4 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 src/pretix/static/pretixbase/js/reldate.js diff --git a/src/pretix/base/reldate.py b/src/pretix/base/reldate.py index 1f609bc1d0..b16cb7907b 100644 --- a/src/pretix/base/reldate.py +++ b/src/pretix/base/reldate.py @@ -21,7 +21,7 @@ # import datetime from collections import namedtuple -from typing import Union +from typing import Tuple, Union from zoneinfo import ZoneInfo from dateutil import parser @@ -42,6 +42,7 @@ EVENT_CHOICES = ( ('presale_end', _('Presale end')), ) +# extend NO_BEFORE_VALUES in reldate.js if changed ORDER_CHOICES = ( ('datetime', _('Moment of order')), ) diff --git a/src/pretix/base/templates/pretixbase/forms/widgets/reldate.html b/src/pretix/base/templates/pretixbase/forms/widgets/reldate.html index 73b8ff7c3d..b3113e2584 100644 --- a/src/pretix/base/templates/pretixbase/forms/widgets/reldate.html +++ b/src/pretix/base/templates/pretixbase/forms/widgets/reldate.html @@ -1,4 +1,6 @@ {% load i18n %} +{% load static %} +
{% for group_name, group_choices, group-index in widget.subwidgets.0.optgroups %} {% for selopt in group_choices %} diff --git a/src/pretix/base/templates/pretixbase/forms/widgets/reldatetime.html b/src/pretix/base/templates/pretixbase/forms/widgets/reldatetime.html index 3e618d0910..31acdf0614 100644 --- a/src/pretix/base/templates/pretixbase/forms/widgets/reldatetime.html +++ b/src/pretix/base/templates/pretixbase/forms/widgets/reldatetime.html @@ -1,4 +1,6 @@ {% load i18n %} +{% load static %} +
{% for group_name, group_choices, group-index in widget.subwidgets.0.optgroups %} {% for selopt in group_choices %} diff --git a/src/pretix/static/pretixbase/js/reldate.js b/src/pretix/static/pretixbase/js/reldate.js new file mode 100644 index 0000000000..9539a50f86 --- /dev/null +++ b/src/pretix/static/pretixbase/js/reldate.js @@ -0,0 +1,44 @@ +if (!window.__reldateInitialized) { + window.__reldateInitialized = true; + document.addEventListener('DOMContentLoaded', () => { + const NO_BEFORE_VALUES = ['datetime']; + + document.querySelectorAll('.reldatetime, .reldate').forEach(container => { + const groups = container.querySelectorAll('.radio'); + + groups.forEach(group => { + const selects = group.querySelectorAll('select'); + if (selects.length < 2) return; + + let referenceSelect = null; + let beforeAfterSelect = null; + + selects.forEach(sel => { + const values = Array.from(sel.options).map(o => o.value); + // only attach to selects that contain problematic values + if (NO_BEFORE_VALUES.some(v => values.includes(v))) { + referenceSelect = sel; + } else if (values.includes('before') && values.includes('after')) { + beforeAfterSelect = sel; + } + }); + if (!referenceSelect || !beforeAfterSelect) return; + + const beforeOption = beforeAfterSelect.querySelector('option[value="before"]'); + const updateBeforeOption = () => { + if (NO_BEFORE_VALUES.includes(referenceSelect.value)) { + beforeOption.disabled = true; + if (beforeAfterSelect.value === 'before') { + beforeAfterSelect.value = 'after'; + beforeAfterSelect.dispatchEvent(new Event('change', { bubbles: true })); + } + } else { + beforeOption.disabled = false; + } + }; + referenceSelect.addEventListener('change', updateBeforeOption); + updateBeforeOption(); + }); + }); + }); +}