mirror of
https://github.com/pretix/pretix.git
synced 2026-05-05 15:14:04 +00:00
Event list: Autocomplete meta values
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
from datetime import datetime, time
|
from datetime import datetime, time
|
||||||
|
from urllib.parse import urlencode
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
@@ -583,7 +584,16 @@ class EventFilterForm(FilterForm):
|
|||||||
continue
|
continue
|
||||||
seen.add(p.name)
|
seen.add(p.name)
|
||||||
self.fields['meta_{}'.format(p.name)] = forms.CharField(
|
self.fields['meta_{}'.format(p.name)] = forms.CharField(
|
||||||
label=p.name, required=False
|
label=p.name,
|
||||||
|
required=False,
|
||||||
|
widget=forms.TextInput(
|
||||||
|
attrs={
|
||||||
|
'data-typeahead-url': reverse('control:events.meta.typeahead') + '?' + urlencode({
|
||||||
|
'property': p.name,
|
||||||
|
'organizer': self.organizer.slug if self.organizer else ''
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
)
|
)
|
||||||
if self.organizer:
|
if self.organizer:
|
||||||
del self.fields['organizer']
|
del self.fields['organizer']
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ urlpatterns = [
|
|||||||
url(r'^events/$', main.EventList.as_view(), name='events'),
|
url(r'^events/$', main.EventList.as_view(), name='events'),
|
||||||
url(r'^events/add$', main.EventWizard.as_view(), name='events.add'),
|
url(r'^events/add$', main.EventWizard.as_view(), name='events.add'),
|
||||||
url(r'^events/typeahead/$', typeahead.event_list, name='events.typeahead'),
|
url(r'^events/typeahead/$', typeahead.event_list, name='events.typeahead'),
|
||||||
|
url(r'^events/typeahead/meta/$', typeahead.meta_values, name='events.meta.typeahead'),
|
||||||
url(r'^search/orders/$', search.OrderSearch.as_view(), name='search.orders'),
|
url(r'^search/orders/$', search.OrderSearch.as_view(), name='search.orders'),
|
||||||
url(r'^event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/', include([
|
url(r'^event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/', include([
|
||||||
url(r'^$', dashboards.event_index, name='event.index'),
|
url(r'^$', dashboards.event_index, name='event.index'),
|
||||||
|
|||||||
@@ -6,12 +6,16 @@ from django.core.exceptions import PermissionDenied
|
|||||||
from django.db.models import Max, Min, Q
|
from django.db.models import Max, Min, Q
|
||||||
from django.db.models.functions import Coalesce, Greatest
|
from django.db.models.functions import Coalesce, Greatest
|
||||||
from django.http import JsonResponse
|
from django.http import JsonResponse
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.formats import get_format
|
from django.utils.formats import get_format
|
||||||
from django.utils.timezone import make_aware
|
from django.utils.timezone import make_aware
|
||||||
from django.utils.translation import pgettext, ugettext as _
|
from django.utils.translation import pgettext, ugettext as _
|
||||||
|
|
||||||
from pretix.base.models import Order, Organizer, SubEvent, User, Voucher
|
from pretix.base.models import (
|
||||||
|
EventMetaProperty, EventMetaValue, Order, Organizer, SubEvent, User,
|
||||||
|
Voucher,
|
||||||
|
)
|
||||||
from pretix.control.forms.event import EventWizardCopyForm
|
from pretix.control.forms.event import EventWizardCopyForm
|
||||||
from pretix.control.permissions import event_permission_required
|
from pretix.control.permissions import event_permission_required
|
||||||
from pretix.helpers.daterange import daterange
|
from pretix.helpers.daterange import daterange
|
||||||
@@ -547,3 +551,52 @@ def users_select2(request):
|
|||||||
}
|
}
|
||||||
|
|
||||||
return JsonResponse(doc)
|
return JsonResponse(doc)
|
||||||
|
|
||||||
|
|
||||||
|
def meta_values(request):
|
||||||
|
q = request.GET.get('q')
|
||||||
|
propname = request.GET.get('property')
|
||||||
|
organizer = request.GET.get('organizer')
|
||||||
|
|
||||||
|
matches = EventMetaValue.objects.filter(
|
||||||
|
value__icontains=q,
|
||||||
|
property__name=propname
|
||||||
|
)
|
||||||
|
defaults = EventMetaProperty.objects.filter(
|
||||||
|
name=propname,
|
||||||
|
default__icontains=q
|
||||||
|
)
|
||||||
|
|
||||||
|
if organizer:
|
||||||
|
organizer = get_object_or_404(Organizer, slug=organizer)
|
||||||
|
if not request.user.has_organizer_permission(organizer, request=request):
|
||||||
|
raise PermissionDenied()
|
||||||
|
|
||||||
|
defaults = defaults.filter(organizer_id=organizer.pk)
|
||||||
|
matches = matches.filter(event__organizer_id=organizer.pk)
|
||||||
|
all_access = (
|
||||||
|
(request and request.user.has_active_staff_session(request.session.session_key))
|
||||||
|
or request.user.teams.filter(all_events=True, organizer=organizer).exists()
|
||||||
|
)
|
||||||
|
if not all_access:
|
||||||
|
matches = matches.filter(event__id__in=request.user.teams.values_list('limit_events__id', flat=True))
|
||||||
|
|
||||||
|
else:
|
||||||
|
# We ignore superuser permissions here. This is intentional – we do not want to show super
|
||||||
|
# users a form with all meta properties ever assigned.
|
||||||
|
defaults = defaults.filter(
|
||||||
|
organizer_id__in=request.user.teams.values_list('organizer', flat=True),
|
||||||
|
)
|
||||||
|
|
||||||
|
if not (request and request.user.has_active_staff_session(request.session.session_key)):
|
||||||
|
matches = matches.filter(
|
||||||
|
Q(event__organizer_id__in=request.user.teams.filter(all_events=True).values_list('organizer', flat=True))
|
||||||
|
| Q(event__id__in=request.user.teams.values_list('limit_events__id', flat=True))
|
||||||
|
)
|
||||||
|
|
||||||
|
return JsonResponse({
|
||||||
|
'results': [
|
||||||
|
{'name': v, 'id': v}
|
||||||
|
for v in sorted(set(defaults.values_list('default', flat=True)[:10]) | set(matches.values_list('value', flat=True)[:10]))
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|||||||
@@ -373,6 +373,38 @@ var form_handlers = function (el) {
|
|||||||
language: $("body").attr("data-select2-locale"),
|
language: $("body").attr("data-select2-locale"),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
el.find('input[data-typeahead-url]').each(function () {
|
||||||
|
var $inp = $(this);
|
||||||
|
$inp.typeahead(null, {
|
||||||
|
minLength: 1,
|
||||||
|
highlight: true,
|
||||||
|
source: new Bloodhound({
|
||||||
|
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
|
||||||
|
queryTokenizer: Bloodhound.tokenizers.whitespace,
|
||||||
|
remote: {
|
||||||
|
url: $inp.attr("data-typeahead-url"),
|
||||||
|
prepare: function (query, settings) {
|
||||||
|
var sep = (settings.url.indexOf('?') > 0) ? '&' : '?';
|
||||||
|
settings.url = settings.url + sep + 'q=' + encodeURIComponent(query);
|
||||||
|
return settings;
|
||||||
|
},
|
||||||
|
transform: function (object) {
|
||||||
|
var results = object.results;
|
||||||
|
var suggs = [];
|
||||||
|
var reslen = results.length;
|
||||||
|
for (var i = 0; i < reslen; i++) {
|
||||||
|
suggs.push(results[i]);
|
||||||
|
}
|
||||||
|
return suggs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
display: function (obj) {
|
||||||
|
return obj.name;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
el.find('[data-model-select2=generic]').each(function () {
|
el.find('[data-model-select2=generic]').each(function () {
|
||||||
var $s = $(this);
|
var $s = $(this);
|
||||||
$s.select2({
|
$s.select2({
|
||||||
|
|||||||
Reference in New Issue
Block a user