diff --git a/src/pretix/control/forms/__init__.py b/src/pretix/control/forms/__init__.py index 8793da50ad..6eff11a8c9 100644 --- a/src/pretix/control/forms/__init__.py +++ b/src/pretix/control/forms/__init__.py @@ -42,8 +42,11 @@ from django.core.files import File from django.core.files.uploadedfile import UploadedFile from django.forms.utils import from_current_timezone from django.urls import reverse +from django.utils.html import escape +from django.utils.safestring import mark_safe from django.utils.timezone import now from django.utils.translation import gettext_lazy as _ +from django_scopes.forms import SafeModelMultipleChoiceField from ...base.forms import I18nModelForm, SecretKeySettingsField @@ -411,3 +414,8 @@ class SMTPSettingsMixin(forms.Form): if data.get('smtp_use_tls') and data.get('smtp_use_ssl'): raise ValidationError(_('You can activate either SSL or STARTTLS security, but not both at the same time.')) return data + + +class ItemMultipleChoiceField(SafeModelMultipleChoiceField): + def label_from_instance(self, obj): + return str(obj) if obj.active else mark_safe(f'{escape(obj)}') diff --git a/src/pretix/control/forms/checkin.py b/src/pretix/control/forms/checkin.py index 4cd0a1e6d4..e8e38e0b3a 100644 --- a/src/pretix/control/forms/checkin.py +++ b/src/pretix/control/forms/checkin.py @@ -31,6 +31,7 @@ from django_scopes.forms import ( from pretix.base.channels import get_all_sales_channels from pretix.base.models.checkin import CheckinList +from pretix.control.forms import ItemMultipleChoiceField from pretix.control.forms.widgets import Select2 @@ -120,7 +121,7 @@ class CheckinListForm(forms.ModelForm): 'exit_all_at': NextTimeInput(attrs={'class': 'timepickerfield'}), } field_classes = { - 'limit_products': SafeModelMultipleChoiceField, + 'limit_products': ItemMultipleChoiceField, 'gates': SafeModelMultipleChoiceField, 'subevent': SafeModelChoiceField, 'exit_all_at': NextTimeField, @@ -164,7 +165,7 @@ class SimpleCheckinListForm(forms.ModelForm): }), } field_classes = { - 'limit_products': SafeModelMultipleChoiceField, + 'limit_products': ItemMultipleChoiceField, 'subevent': SafeModelChoiceField, 'gates': SafeModelMultipleChoiceField, } diff --git a/src/pretix/control/forms/item.py b/src/pretix/control/forms/item.py index 1ee1e44aad..d145d97b11 100644 --- a/src/pretix/control/forms/item.py +++ b/src/pretix/control/forms/item.py @@ -41,6 +41,8 @@ from django.core.exceptions import ValidationError from django.db.models import Max from django.forms.formsets import DELETION_FIELD_NAME from django.urls import reverse +from django.utils.html import escape +from django.utils.safestring import mark_safe from django.utils.translation import ( gettext as __, gettext_lazy as _, pgettext_lazy, ) @@ -57,7 +59,9 @@ from pretix.base.models import ( ) from pretix.base.models.items import ItemAddOn, ItemBundle, ItemMetaValue from pretix.base.signals import item_copy_data -from pretix.control.forms import SplitDateTimeField, SplitDateTimePickerWidget +from pretix.control.forms import ( + ItemMultipleChoiceField, SplitDateTimeField, SplitDateTimePickerWidget, +) from pretix.control.forms.widgets import Select2 from pretix.helpers.models import modelcopy from pretix.helpers.money import change_decimal_field @@ -168,7 +172,7 @@ class QuestionForm(I18nModelForm): field_classes = { 'valid_datetime_min': SplitDateTimeField, 'valid_datetime_max': SplitDateTimeField, - 'items': SafeModelMultipleChoiceField, + 'items': ItemMultipleChoiceField, 'dependency_question': SafeModelChoiceField, } @@ -200,9 +204,12 @@ class QuotaForm(I18nModelForm): for item in items: if len(item.variations.all()) > 0: for v in item.variations.all(): - choices.append(('{}-{}'.format(item.pk, v.pk), '{} – {}'.format(item, v.value))) + choices.append(( + '{}-{}'.format(item.pk, v.pk), + '{} – {}'.format(item, v.value) if item.active else mark_safe(f'{escape(item)} – {escape(v.value)}') + )) else: - choices.append(('{}'.format(item.pk), str(item))) + choices.append(('{}'.format(item.pk), str(item) if item.active else mark_safe(f'{escape(item)}'))) self.fields['itemvars'] = forms.MultipleChoiceField( label=_('Products'), diff --git a/src/pretix/control/templates/pretixcontrol/items/index.html b/src/pretix/control/templates/pretixcontrol/items/index.html index ec00e86d6a..92847f61e9 100644 --- a/src/pretix/control/templates/pretixcontrol/items/index.html +++ b/src/pretix/control/templates/pretixcontrol/items/index.html @@ -44,11 +44,10 @@ {% regroup items by category as cat_list %} {% for c in cat_list %} {% for i in c.list %} - + {% if not i.active %}{% endif %} - {{ i }} + {{ i }} {% if not i.active %}{% endif %}
@@ -109,7 +108,7 @@ - + diff --git a/src/pretix/control/views/typeahead.py b/src/pretix/control/views/typeahead.py index 3f4280ff7c..f22729ddc3 100644 --- a/src/pretix/control/views/typeahead.py +++ b/src/pretix/control/views/typeahead.py @@ -583,17 +583,17 @@ def itemvarquota_select2(request, **kwargs): if variations: choices.append((str(i.pk), _('{product} – Any variation').format(product=i), '')) for v in variations: - choices.append(('%d-%d' % (i.pk, v.pk), '%s – %s' % (i, v.value), '')) + choices.append(('%d-%d' % (i.pk, v.pk), '%s – %s' % (i, v.value), '', not i.active)) else: - choices.append((str(i.pk), str(i), '')) + choices.append((str(i.pk), str(i), '', not i.active)) for q in quotaqs: if request.event.has_subevents: choices.append(('q-%d' % q.pk, _('Any product in quota "{quota}"').format( quota=q - ), str(q.subevent))) + ), str(q.subevent), False)) else: - choices.append(('q-%d' % q.pk, _('Any product in quota "{quota}"').format(quota=q), '')) + choices.append(('q-%d' % q.pk, _('Any product in quota "{quota}"').format(quota=q), '', False)) doc = { 'results': [ @@ -601,8 +601,9 @@ def itemvarquota_select2(request, **kwargs): 'id': k, 'text': str(v), 'event': str(t), + 'inactive': d } - for k, v, t in choices + for k, v, t, d in choices ], 'pagination': { "more": more diff --git a/src/pretix/static/pretixbase/scss/_theme.scss b/src/pretix/static/pretixbase/scss/_theme.scss index 6f23e97391..f991aedb8d 100644 --- a/src/pretix/static/pretixbase/scss/_theme.scss +++ b/src/pretix/static/pretixbase/scss/_theme.scss @@ -184,6 +184,14 @@ svg.svg-icon { top: 2px; } +.link-muted a, a.link-muted { + color: $text-muted; +} + +.row-muted td:not(.col-actions) { + opacity: 0.7; +} + @include table-row-variant('success', lighten($brand-success, 40%)); @include table-row-variant('info', lighten($brand-info, 30%)); @include table-row-variant('warning', lighten($brand-warning, 40%)); diff --git a/src/pretix/static/pretixcontrol/js/ui/main.js b/src/pretix/static/pretixcontrol/js/ui/main.js index 020e1d0be9..c0a7048985 100644 --- a/src/pretix/static/pretixcontrol/js/ui/main.js +++ b/src/pretix/static/pretixcontrol/js/ui/main.js @@ -483,7 +483,7 @@ var form_handlers = function (el) { return res.text; } var $ret = $("").append( - $("").addClass("primary").append($("
").text(res.text).html()) + $(res.inactive ? "" : "").addClass("primary").append($("
").text(res.text).html()) ); if (res.event) { $ret.append( diff --git a/src/pretix/static/pretixpresale/scss/_theme.scss b/src/pretix/static/pretixpresale/scss/_theme.scss index 9e270cfaca..ac832b219a 100644 --- a/src/pretix/static/pretixpresale/scss/_theme.scss +++ b/src/pretix/static/pretixpresale/scss/_theme.scss @@ -60,6 +60,7 @@ h2.content-header { margin-top: 0; } + @media (max-width: $screen-xs-max) { h2.content-header small { display: block;