mirror of
https://github.com/pretix/pretix.git
synced 2026-06-11 01:25:13 +00:00
216 lines
7.7 KiB
Python
216 lines
7.7 KiB
Python
import copy
|
|
import json
|
|
from typing import Any
|
|
|
|
from django.db import transaction
|
|
from django import forms
|
|
from django.core.exceptions import BadRequest
|
|
from django.db.models.query import QuerySet
|
|
from django.urls import reverse
|
|
from django.http import HttpResponse, HttpResponseRedirect
|
|
from django.utils.translation import gettext_lazy as _
|
|
from django.views.generic import CreateView, DetailView, ListView, DeleteView, View
|
|
from pretix.base.i18n import language
|
|
from pretix.base.pdf import get_images, get_variables
|
|
from pretix.base.services.tickets import get_preview_position
|
|
from pretix.control.permissions import EventPermissionRequiredMixin
|
|
from django.conf import settings
|
|
from django.shortcuts import redirect
|
|
from pretix.helpers.database import rolledback_transaction
|
|
from pretix.helpers.models import modelclone
|
|
from .models import WalletLayout
|
|
from .styles import AVAILABLE_STYLES, AVAILABLE_PLATFORMS, AVAILABLE_STYLES_DICT, PassLayout
|
|
from django.contrib import messages
|
|
from django.contrib.staticfiles import finders
|
|
from django.utils.functional import cached_property
|
|
|
|
def get_layout_variables(event):
|
|
return {
|
|
"text": get_variables(event),
|
|
"image": get_images(event)
|
|
| {"poweredby": {"label": _("pretix-Logo"), "evaluate": lambda *_: open(finders.find("pretix_passbook/logo.png"), "rb")},
|
|
"poweredby_icon": {"label": _("pretix-Icon"), "evaluate": lambda *_: open(finders.find("pretix_passbook/icon.png"), "rb")}}, # TODO: image upload
|
|
}
|
|
|
|
|
|
def get_editor_variables(event):
|
|
return {
|
|
t: {
|
|
vid: {"label": v.get("label"), "editor_sample": v.get("editor_sample")}
|
|
for vid, v in vs.items()
|
|
}
|
|
for t, vs in get_layout_variables(event).items()
|
|
}
|
|
|
|
class WalletLayoutMixin:
|
|
model = WalletLayout
|
|
permission = "event.settings.general:write"
|
|
pk_url_kwarg = "layout"
|
|
context_object_name = "layouts"
|
|
|
|
def get_queryset(self):
|
|
return self.request.event.wallet_layouts.all()
|
|
|
|
class LayoutListView(WalletLayoutMixin, EventPermissionRequiredMixin, ListView):
|
|
template_name = "pretixplugins/wallet/layout_list.html"
|
|
|
|
|
|
class LayoutDetailView(WalletLayoutMixin, EventPermissionRequiredMixin, DetailView):
|
|
pass
|
|
|
|
|
|
class LayoutEditorView(LayoutDetailView):
|
|
template_name = "pretixplugins/wallet/edit.html"
|
|
|
|
def get_context_data(self, **kwargs) -> dict[str, Any]:
|
|
context = super().get_context_data(**kwargs)
|
|
context['platforms'] = [{
|
|
"identifier": platform.identifier,
|
|
"name": platform.name,
|
|
"styles": {
|
|
style.identifier: style.asdict() for style in AVAILABLE_STYLES.get(platform.identifier)
|
|
}
|
|
} for platform in AVAILABLE_PLATFORMS
|
|
]
|
|
# context["styles"] = {
|
|
# style.identifier: style.asdict() for style in self.get_platform_styles()
|
|
# }
|
|
context["variables"] = get_editor_variables(self.request.event)
|
|
context["locales"] = {
|
|
l: dict(settings.LANGUAGES).get(l, l)
|
|
for l in self.request.event.settings.get("locales")
|
|
}
|
|
|
|
return context
|
|
|
|
|
|
class WalletLayoutCreateForm(forms.ModelForm):
|
|
class Meta:
|
|
model = WalletLayout
|
|
fields = ("name",)
|
|
|
|
def __init__(self, *args, event, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.event = event
|
|
|
|
def save(self, *args, **kwargs) -> Any:
|
|
self.instance.event = self.event
|
|
return super().save(*args, **kwargs)
|
|
|
|
|
|
class LayoutCreateView(WalletLayoutMixin, EventPermissionRequiredMixin, CreateView):
|
|
template_name = "pretixplugins/wallet/create.html"
|
|
form_class = WalletLayoutCreateForm
|
|
permission = "event.settings.general:write"
|
|
|
|
def form_valid(self, form):
|
|
self.object = form.save()
|
|
if self.copy_from:
|
|
for pl in self.copy_from.platform_layouts.all():
|
|
modelclone(pl, parent=self.object).save()
|
|
return HttpResponseRedirect(self.get_success_url())
|
|
|
|
def get_form_kwargs(self) -> dict[str, Any]:
|
|
kwargs = super().get_form_kwargs()
|
|
kwargs["event"] = self.request.event
|
|
|
|
if self.copy_from:
|
|
kwargs['instance'] = modelclone(self.copy_from, default=False)
|
|
kwargs.setdefault('initial', {})
|
|
|
|
return kwargs
|
|
|
|
def get_success_url(self) -> str:
|
|
return reverse(
|
|
"plugins:wallet:edit",
|
|
kwargs={
|
|
"organizer": self.request.event.organizer.slug,
|
|
"event": self.request.event.slug,
|
|
"layout": self.object.pk,
|
|
},
|
|
)
|
|
|
|
@cached_property
|
|
def copy_from(self) -> WalletLayout | None:
|
|
if self.request.GET.get("copy_from"):
|
|
try:
|
|
return self.get_queryset().get(pk=self.request.GET.get("copy_from"))
|
|
except WalletLayout.DoesNotExist:
|
|
pass
|
|
|
|
class LayoutPreviewView(EventPermissionRequiredMixin, View):
|
|
permission = "event.settings.general:write"
|
|
|
|
def post(self, request, **kwargs):
|
|
event = request.event
|
|
platform_id = request.POST.get("platform")
|
|
style_id = request.POST.get("style")
|
|
layout = request.POST.get("layout")
|
|
|
|
platform = None
|
|
for p in AVAILABLE_PLATFORMS:
|
|
if p.identifier == platform_id:
|
|
platform = p
|
|
if not platform:
|
|
raise BadRequest("Unknown platform")
|
|
if style_id not in AVAILABLE_STYLES_DICT[platform_id]:
|
|
raise BadRequest("Unknown style")
|
|
style = AVAILABLE_STYLES_DICT[platform_id][style_id]
|
|
|
|
layout = json.loads(layout)
|
|
with rolledback_transaction(), language(request.event.settings.locale, request.event.settings.region):
|
|
p = get_preview_position(request.event)
|
|
layout = PassLayout(style=style, layout=layout)
|
|
context = {"placeholders": get_layout_variables(event)}
|
|
layout.validate(context=context)
|
|
|
|
fname, mimet, data = platform.generate(layout, p)
|
|
resp = HttpResponse(data, content_type=mimet)
|
|
ftype = fname.split(".")[-1]
|
|
resp['Content-Disposition'] = 'attachment; filename="ticket-preview.{}"'.format(ftype)
|
|
return resp
|
|
|
|
|
|
|
|
class LayoutSetDefault(LayoutDetailView):
|
|
@transaction.atomic
|
|
def post(self, request, *args, **kwargs):
|
|
obj = self.get_object()
|
|
request.event.wallet_layouts.exclude(pk=obj.pk).update(default=False)
|
|
obj.default = True
|
|
obj.save(update_fields=['default'])
|
|
messages.success(self.request, _('Your changes have been saved.'))
|
|
return redirect(self.get_success_url())
|
|
|
|
def get_success_url(self) -> str:
|
|
return reverse('plugins:wallet:index', kwargs={
|
|
'organizer': self.request.event.organizer.slug,
|
|
'event': self.request.event.slug,
|
|
})
|
|
|
|
|
|
|
|
class LayoutDelete(WalletLayoutMixin, DeleteView):
|
|
template_name = 'pretixplugins/wallet/delete.html'
|
|
|
|
def get_success_url(self) -> str:
|
|
return reverse('plugins:wallet:index', kwargs={
|
|
'organizer': self.request.event.organizer.slug,
|
|
'event': self.request.event.slug,
|
|
})
|
|
|
|
@transaction.atomic
|
|
def form_valid(self, form):
|
|
self.object = self.get_object()
|
|
self.object.log_action(action='pretix.plugins.wallet.layout.deleted', user=self.request.user)
|
|
self.object.delete()
|
|
|
|
if not self.request.event.wallet_layouts.filter(default=True).exists():
|
|
f = self.request.event.wallet_layouts.first()
|
|
if f:
|
|
f.default = True
|
|
f.save(update_fields=['default'])
|
|
|
|
messages.success(self.request, _('The selected layout been deleted.'))
|
|
return redirect(self.get_success_url())
|