diff --git a/src/pretix/control/forms/filter.py b/src/pretix/control/forms/filter.py
index 3f103f23cc..4e3651d0bb 100644
--- a/src/pretix/control/forms/filter.py
+++ b/src/pretix/control/forms/filter.py
@@ -10,8 +10,8 @@ from django.utils.translation import pgettext_lazy, ugettext_lazy as _
from pretix.base.forms.widgets import DatePickerWidget
from pretix.base.models import (
- Checkin, Event, Invoice, Item, Order, OrderPayment, OrderPosition,
- OrderRefund, Organizer, Question, QuestionAnswer, SubEvent,
+ Checkin, Event, EventMetaValue, Invoice, Item, Order, OrderPayment,
+ OrderPosition, OrderRefund, Organizer, Question, QuestionAnswer, SubEvent,
)
from pretix.base.signals import register_payment_providers
from pretix.control.forms.widgets import Select2
@@ -573,13 +573,21 @@ class EventFilterForm(FilterForm):
def __init__(self, *args, **kwargs):
request = kwargs.pop('request')
+ self.organizer = kwargs.pop('organizer', None)
super().__init__(*args, **kwargs)
- if request.user.has_active_staff_session(request.session.session_key):
- self.fields['organizer'].queryset = Organizer.objects.all()
+ if self.organizer:
+ del self.fields['organizer']
+ for p in self.organizer.meta_properties.all():
+ self.fields['meta_{}'.format(p.name)] = forms.CharField(
+ label=p.name, required=False
+ )
else:
- self.fields['organizer'].queryset = Organizer.objects.filter(
- pk__in=request.user.teams.values_list('organizer', flat=True)
- )
+ if request.user.has_active_staff_session(request.session.session_key):
+ self.fields['organizer'].queryset = Organizer.objects.all()
+ else:
+ self.fields['organizer'].queryset = Organizer.objects.filter(
+ pk__in=request.user.teams.values_list('organizer', flat=True)
+ )
def filter_qs(self, qs):
fdata = self.cleaned_data
@@ -628,6 +636,26 @@ class EventFilterForm(FilterForm):
Q(name__icontains=i18ncomp(query)) | Q(slug__icontains=query)
)
+ if self.organizer:
+ for i, p in enumerate(self.organizer.meta_properties.all()):
+ d = fdata.get('meta_{}'.format(p.name))
+ if d:
+ emv_with_value = EventMetaValue.objects.filter(
+ event=OuterRef('pk'),
+ property__name=p.name,
+ value=d
+ )
+ emv_with_any_value = EventMetaValue.objects.filter(
+ event=OuterRef('pk'),
+ property__name=p.name,
+ )
+ qs = qs.annotate(**{'attr_{}'.format(i): Exists(emv_with_value)})
+ filters = Q(**{'attr_{}'.format(i): True})
+ if p.default == d:
+ qs = qs.annotate(**{'attr_{}_any'.format(i): Exists(emv_with_any_value)})
+ filters |= Q(**{'attr_{}_any'.format(i): False})
+ qs = qs.filter(filters)
+
if fdata.get('ordering'):
qs = qs.order_by(self.get_order_by())
diff --git a/src/pretix/control/templates/pretixcontrol/events/index.html b/src/pretix/control/templates/pretixcontrol/events/index.html
index e2d078dde5..d94d28228a 100644
--- a/src/pretix/control/templates/pretixcontrol/events/index.html
+++ b/src/pretix/control/templates/pretixcontrol/events/index.html
@@ -89,7 +89,7 @@
{{ e.slug }}
{% for k, v in e.meta_data.items %}
{% if v %}
- · {{ k }}: {{ v }}
+ · {{ k }}: {{ v }}
{% endif %}
{% endfor %}
diff --git a/src/pretix/control/templates/pretixcontrol/organizers/detail.html b/src/pretix/control/templates/pretixcontrol/organizers/detail.html
index 2fad61474f..0846f87d4b 100644
--- a/src/pretix/control/templates/pretixcontrol/organizers/detail.html
+++ b/src/pretix/control/templates/pretixcontrol/organizers/detail.html
@@ -7,17 +7,46 @@
{% if "can_create_events" in request.orgapermset %}
- + {% trans "Create a new event" %}
{% endif %} - {% if events|length == 0 %} + {% if events|length == 0 and not filter_form.filtered %}{% trans "You currently do not have access to any events." %}
{% else %} +|
{{ e.name }}
+ {{ e.slug }} + {% for k, v in e.meta_data.items %} + {% if v %} + · {{ k }}: {{ v }} + {% endif %} + {% endfor %} |
{% if e.has_subevents %} @@ -62,9 +97,9 @@ | {% if not e.live %} {% trans "Shop disabled" %} - {% elif e.presale_has_ended %} + {% elif e.presale_has_ended %} {% trans "Presale over" %} - {% elif not e.presale_is_running %} + {% elif not e.presale_is_running %} {% trans "Presale not started" %} {% else %} {% trans "On sale" %} @@ -72,13 +107,13 @@ | + class="btn btn-sm btn-default" title="{% trans "Open event dashboard" %}" + data-toggle="tooltip"> {% if "can_create_events" in request.orgapermset %} + title="{% trans "Clone event" %}" data-toggle="tooltip"> {% endif %} diff --git a/src/pretix/control/views/organizer.py b/src/pretix/control/views/organizer.py index 3d9a5a0b07..cf250d9bed 100644 --- a/src/pretix/control/views/organizer.py +++ b/src/pretix/control/views/organizer.py @@ -7,7 +7,9 @@ from django.contrib import messages from django.core.exceptions import PermissionDenied, ValidationError from django.core.files import File from django.db import transaction -from django.db.models import Count, DecimalField, Max, Min, ProtectedError, Sum +from django.db.models import ( + Count, DecimalField, Max, Min, Prefetch, ProtectedError, Sum, +) from django.db.models.functions import Coalesce, Greatest from django.forms import inlineformset_factory from django.http import JsonResponse @@ -25,10 +27,12 @@ from pretix.base.auth import get_auth_backends from pretix.base.models import ( Device, GiftCard, Organizer, Team, TeamInvite, User, ) -from pretix.base.models.event import Event, EventMetaProperty +from pretix.base.models.event import Event, EventMetaProperty, EventMetaValue from pretix.base.models.organizer import TeamAPIToken from pretix.base.services.mail import SendMailException, mail -from pretix.control.forms.filter import GiftCardFilterForm, OrganizerFilterForm +from pretix.control.forms.filter import ( + EventFilterForm, GiftCardFilterForm, OrganizerFilterForm, +) from pretix.control.forms.organizer import ( DeviceForm, EventMetaPropertyForm, GiftCardCreateForm, OrganizerDeleteForm, OrganizerForm, OrganizerSettingsForm, OrganizerUpdateForm, TeamForm, @@ -105,7 +109,13 @@ class OrganizerDetail(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin def get_queryset(self): qs = self.request.user.get_events_with_any_permission(self.request).select_related('organizer').prefetch_related( - '_settings_objects', 'organizer___settings_objects' + 'organizer', '_settings_objects', 'organizer___settings_objects', + 'organizer__meta_properties', + Prefetch( + 'meta_values', + EventMetaValue.objects.select_related('property'), + to_attr='meta_values_cached' + ) ).filter(organizer=self.request.organizer).order_by('-date_from') qs = qs.annotate( min_from=Min('subevents__date_from'), @@ -116,10 +126,20 @@ class OrganizerDetail(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin order_from=Coalesce('min_from', 'date_from'), order_to=Coalesce('max_fromto', 'max_to', 'max_from', 'date_to', 'date_from'), ) + if self.filter_form.is_valid(): + qs = self.filter_form.filter_qs(qs) return qs + @cached_property + def filter_form(self): + return EventFilterForm(data=self.request.GET, request=self.request, organizer=self.organizer) + def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) + ctx['filter_form'] = self.filter_form + ctx['meta_fields'] = [ + self.filter_form['meta_{}'.format(p.name)] for p in self.organizer.meta_properties.all() + ] return ctx |