From a521956aca41b4481070cfb7095bb93512cd50b3 Mon Sep 17 00:00:00 2001 From: Kara Engelhardt Date: Fri, 20 Mar 2026 12:46:48 +0100 Subject: [PATCH] WIP --- src/pretix/plugins/wallet/styles.py | 19 ++- .../templates/pretixplugins/wallet/edit.html | 4 +- .../pretixplugins/wallet/layout_list.html | 122 ++++++++++-------- .../wallet/settings_content.html | 8 ++ src/pretix/plugins/wallet/ticketoutput.py | 34 +++-- src/pretix/plugins/wallet/urls.py | 7 +- src/pretix/plugins/wallet/views.py | 64 +++++++-- 7 files changed, 179 insertions(+), 79 deletions(-) create mode 100644 src/pretix/plugins/wallet/templates/pretixplugins/wallet/settings_content.html diff --git a/src/pretix/plugins/wallet/styles.py b/src/pretix/plugins/wallet/styles.py index e2cc6b233..42a1146d9 100644 --- a/src/pretix/plugins/wallet/styles.py +++ b/src/pretix/plugins/wallet/styles.py @@ -4,7 +4,23 @@ import enum from django.utils.translation import gettext_lazy as _ from django.core.exceptions import ValidationError from i18nfield.strings import LazyI18nString +from .models import WalletLayout +class WalletPlatform: + identifier: str + name: str + + def get_layout_qs(self): + return WalletLayout.objects.filter(platform=self.identifier) + +class ApplePlatform(WalletPlatform): + identifier = "apple" + name = _("Apple") + +class GooglePlatform(WalletPlatform): + identifier = "apple" + name = _("Google") + class PlaceholderFieldType(enum.Enum): TEXT = "text" CODE = "qr" @@ -108,6 +124,7 @@ class GoogleWalletEventTicket(PassStyle): ] +AVAILABLE_PLATFORMS = {"apple": ApplePlatform, "google": GooglePlatform} AVAILABLE_STYLES = [AppleWalletEventTicket(), GoogleWalletEventTicket()] def get_platforms_with_styles(): @@ -127,7 +144,7 @@ def get_platform_styles(platform): return platform_styles def get_platforms(): - return sorted(set(style.platform for style in AVAILABLE_STYLES)) + return AVAILABLE_PLATFORMS class PassLayout: style: PassStyle diff --git a/src/pretix/plugins/wallet/templates/pretixplugins/wallet/edit.html b/src/pretix/plugins/wallet/templates/pretixplugins/wallet/edit.html index 955ce9cc1..4bd6c08e4 100644 --- a/src/pretix/plugins/wallet/templates/pretixplugins/wallet/edit.html +++ b/src/pretix/plugins/wallet/templates/pretixplugins/wallet/edit.html @@ -1,6 +1,8 @@ {% extends "pretixcontrol/event/base.html" %} {% load i18n %} {% load money %} +{% load bootstrap3 %} + {% block title %}{% trans "Wallet layouts" %}{% endblock %} {% block content %}
{{ styles }}
@@ -9,7 +11,7 @@ {{ variables|json_script:"variables" }}
{% csrf_token %} - {{form}} + {% bootstrap_form form %} diff --git a/src/pretix/plugins/wallet/templates/pretixplugins/wallet/layout_list.html b/src/pretix/plugins/wallet/templates/pretixplugins/wallet/layout_list.html index e29cce4e4..07e52663a 100644 --- a/src/pretix/plugins/wallet/templates/pretixplugins/wallet/layout_list.html +++ b/src/pretix/plugins/wallet/templates/pretixplugins/wallet/layout_list.html @@ -5,62 +5,76 @@ {% block content %}

{% trans "Wallet layouts" %}

- {% for platform in platforms %} + {% for platform in platforms.values %}
- {{platform}} + {{platform.name}} + {% if platforms.get_layout_qs|length == 0 %} +
+

+ {% blocktrans trimmed %} + You haven't created any layouts yet. + {% endblocktrans %} +

+ + {% if "event.settings.general:write" in request.eventpermset %} + {% trans "Create a new layout" %} + + {% endif %} +
+ {% else %} +
+ + + + + + + + + + {% for l in platforms.get_layout_qs %} + + + + + + {% endfor %} + +
{% trans "Name" %}{% trans "Default" %}
+ {% if "can_change_event_settings" in request.eventpermset %} + + {{ l.name }} + + {% else %} + {{ l.name }} + {% endif %} + + {% if l.default %} + + + {% trans "Default" %} + + {% elif "can_change_event_settings" in request.eventpermset %} + + {% csrf_token %} + + + {% endif %} + + {% if "can_change_event_settings" in request.eventpermset %} + + + + {% endif %} +
+
+ {% endif %}
{% endfor %}
- {% comment %}
- - - - - - - - - - {% for l in layouts %} - - - - - - {% endfor %} - -
{% trans "Name" %}{% trans "Default" %}
- {% if "can_change_event_settings" in request.eventpermset %} - - {{ l.name }} - - {% else %} - {{ l.name }} - {% endif %} - - {% if l.default %} - - - {% trans "Default" %} - - {% elif "can_change_event_settings" in request.eventpermset %} -
- {% csrf_token %} - -
- {% endif %} -
- {% if "can_change_event_settings" in request.eventpermset %} - - - - {% endif %} -
-
- {% endcomment %} - {% include "pretixcontrol/pagination.html" %} {% endblock %} diff --git a/src/pretix/plugins/wallet/templates/pretixplugins/wallet/settings_content.html b/src/pretix/plugins/wallet/templates/pretixplugins/wallet/settings_content.html new file mode 100644 index 000000000..2ba7f4ccc --- /dev/null +++ b/src/pretix/plugins/wallet/templates/pretixplugins/wallet/settings_content.html @@ -0,0 +1,8 @@ +{% load i18n %} +

+ + + {% trans "Edit layouts" %} + +

diff --git a/src/pretix/plugins/wallet/ticketoutput.py b/src/pretix/plugins/wallet/ticketoutput.py index f76a764c5..a0dad0bdc 100644 --- a/src/pretix/plugins/wallet/ticketoutput.py +++ b/src/pretix/plugins/wallet/ticketoutput.py @@ -24,34 +24,48 @@ from django.utils.translation import gettext_lazy as _ from pretix.base.ticketoutput import BaseTicketOutput from pretix.base.models import Event from pretix.base.settings import SettingsSandbox +from django.template.loader import render_to_string -logger = logging.getLogger('pretix.plugins.wallet') +logger = logging.getLogger("pretix.plugins.wallet") class WalletSettingsHolder(BaseTicketOutput): - identifier = 'wallet' - verbose_name = _('Wallet Output') - + identifier = "wallet" + verbose_name = _("Wallet Output") + is_meta = True is_enabled = False - preview_allowed = False # TODO: implement own preview view or hide button for meta-outputs + preview_allowed = ( + False # TODO: implement own preview view or hide button for meta-outputs + ) + + def settings_content_render(self, request) -> str: + return render_to_string( + "pretixplugins/wallet/settings_content.html", {"request": request} + ) + class WalletOutput(BaseTicketOutput): settings_form_fields = [] def __init__(self, event: Event): super().__init__(event) - self.settings = SettingsSandbox('ticketoutput', WalletSettingsHolder.identifier, event) + self.settings = SettingsSandbox( + "ticketoutput", WalletSettingsHolder.identifier, event + ) + class GoogleWalletTicketOutput(WalletOutput): - identifier = 'wallet_google' - verbose_name = _('Google') + identifier = "wallet_google" + verbose_name = _("Google") download_button_text = "Add to Google Wallet" + class AppleWalletTicketOutput(WalletOutput): - identifier = 'wallet_apple' - verbose_name = _('Apple') + identifier = "wallet_apple" + verbose_name = _("Apple") download_button_text = "Add to Apple Wallet" + OUTPUTS = [WalletSettingsHolder, GoogleWalletTicketOutput, AppleWalletTicketOutput] diff --git a/src/pretix/plugins/wallet/urls.py b/src/pretix/plugins/wallet/urls.py index 5e11ecde2..7d945f8bb 100644 --- a/src/pretix/plugins/wallet/urls.py +++ b/src/pretix/plugins/wallet/urls.py @@ -22,7 +22,8 @@ from django.urls import re_path from .views import ( - EditorView, + LayoutEditorView, + LayoutCreateView, LayoutListView ) @@ -30,7 +31,7 @@ urlpatterns = [ re_path(r'^control/event/(?P[^/]+)/(?P[^/]+)/wallet/$', LayoutListView.as_view(), name='index'), re_path(r'^control/event/(?P[^/]+)/(?P[^/]+)/wallet/edit/(?P[^/]+)/$', - EditorView.as_view(), name='edit'), + LayoutCreateView.as_view(), name='add'), re_path(r'^control/event/(?P[^/]+)/(?P[^/]+)/wallet/edit/(?P[^/]+)/(?P[^/]+)/$', - EditorView.as_view(), name='edit'), + LayoutEditorView.as_view(), name='edit'), ] diff --git a/src/pretix/plugins/wallet/views.py b/src/pretix/plugins/wallet/views.py index 02e6d8637..8e2b6eceb 100644 --- a/src/pretix/plugins/wallet/views.py +++ b/src/pretix/plugins/wallet/views.py @@ -3,7 +3,7 @@ from typing import Any from django.http import Http404 from django.shortcuts import redirect from django.urls import reverse -from django.views.generic import FormView, ListView, TemplateView +from django.views.generic import FormView, ListView, CreateView, UpdateView from pretix.base.pdf import get_variables from pretix.control.permissions import EventPermissionRequiredMixin from .styles import PassLayout, get_platform_styles, get_platforms @@ -12,8 +12,10 @@ import json from django.utils.translation import gettext_lazy as _ from django import forms from django.core.exceptions import ValidationError +from i18nfield.fields import I18nCharField +from i18nfield.forms import I18nModelForm - +# TODO: should this even be a list view? class LayoutListView(EventPermissionRequiredMixin, ListView): model = WalletLayout permission = "can_change_event_settings" @@ -29,11 +31,19 @@ class LayoutListView(EventPermissionRequiredMixin, ListView): return ctx -class EditorForm(forms.Form): - name = forms.CharField() + +class LayoutEditForm(forms.ModelForm): style = forms.TypedChoiceField() layout = forms.JSONField(initial={}) + def __init__(self, **kwargs): + self.platform = kwargs.pop('platform') + super().__init__(**kwargs) + + class Meta: + model = WalletLayout + fields = ("name","style","layout") + def __init__(self, platform, **kwargs): super().__init__(**kwargs) self.platform = platform @@ -60,13 +70,12 @@ class EditorForm(forms.Form): ) layout.validate() return self.cleaned_data - - -class EditorView(EventPermissionRequiredMixin, FormView): + +class LayoutCreateView(EventPermissionRequiredMixin, FormView): template_name = "pretixplugins/wallet/edit.html" - form_class = EditorForm - success_url = "" - permission = "can_change_event_settings" + form_class = LayoutEditForm + model = WalletLayout + permission = "can_change_event_settings" # TODO: new permission name @property def platform(self): @@ -116,3 +125,38 @@ class EditorView(EventPermissionRequiredMixin, FormView): }, ) ) + +class LayoutEditorView(EventPermissionRequiredMixin, UpdateView): + template_name = "pretixplugins/wallet/edit.html" + form_class = LayoutEditForm + success_url = "" + permission = "can_change_event_settings" + + @property + def platform(self): + return self.kwargs["platform"] + + def get_form_kwargs(self) -> dict[str, Any]: + kwargs = super().get_form_kwargs() + kwargs["platform"] = self.platform + return kwargs + + def get_platform_styles(self): + if self.platform not in get_platforms(): + raise Http404( + _("Unknown platform '{platform}'").format(platform=self.platform) + ) + return get_platform_styles(self.platform) + + def get_context_data(self, **kwargs) -> dict[str, Any]: + context = super().get_context_data(**kwargs) + context["styles"] = { + id: style.asdict() for id, style in self.get_platform_styles().items() + } + context["variables"] = { + "text": { + varname: {"label": var["label"], "editor_sample": var["editor_sample"]} + for varname, var in get_variables(self.request.event).items() + } + } + return context \ No newline at end of file