+
type FieldEntry = {
type: 'placeholder' | 'text';
- label: string; // TODO i18n
- content: string;
+ label?: I18nString; // TODO i18n
+ content?: string;
}
type FieldConfig = {
diff --git a/src/pretix/plugins/wallet/styles.py b/src/pretix/plugins/wallet/styles.py
index a4329b2cc3..6e0bac9d59 100644
--- a/src/pretix/plugins/wallet/styles.py
+++ b/src/pretix/plugins/wallet/styles.py
@@ -24,29 +24,36 @@ class GooglePlatform(WalletPlatform):
name = _("Google")
-class PlaceholderFieldType(enum.Enum):
+class FieldType(enum.Enum):
TEXT = "text"
CODE = "qr"
IMAGE = "image"
PREDEFINED = "predefined"
# TODO: POWERED_BY ?
-
-@dataclass
-class PlaceholderField:
- type: PlaceholderFieldType
+class BaseField:
+ type: str
label: LazyI18nString
content: str
- def asdict(self):
- return {"type": self.type.value, "label": self.label.data, "value": self.content}
+ def __init__(self, label: LazyI18nString, content: str):
+ self.label = label
+ self.content = content
+ def asdict(self):
+ return {"type": self.type, "label": self.label.data, "content": self.content}
+
+class PlaceholderField(BaseField):
+ type = "placeholder"
+
+class TextField(BaseField):
+ type = "text"
@dataclass
class FieldGroupDefinition:
name: str
identifier: str
- entry_type: PlaceholderFieldType
+ entry_type: FieldType
min_entries: int | None = None
max_entries: int | None = None
@@ -62,8 +69,8 @@ class FieldGroupDefinition:
@dataclass
class PlaceholderFieldGroup(FieldGroupDefinition):
- entry_type: PlaceholderFieldType = PlaceholderFieldType.TEXT
- default_entries: list[PlaceholderField] = field(default_factory=list)
+ entry_type: FieldType = FieldType.TEXT
+ default_entries: list[PlaceholderField | TextField] = field(default_factory=list) # TODO: TextField seems wrong here
def asdict(self):
asdict = super().asdict()
@@ -73,7 +80,7 @@ class PlaceholderFieldGroup(FieldGroupDefinition):
@dataclass
class PredefinedFieldGroup(FieldGroupDefinition):
- entry_type: PlaceholderFieldType = PlaceholderFieldType.PREDEFINED
+ entry_type: FieldType = FieldType.PREDEFINED
min_entries = 0
max_entries = 1
@@ -107,9 +114,9 @@ class AppleWalletEventTicket(PassStyle):
min_entries=1,
max_entries=1,
default_entries=[
- PlaceholderField(PlaceholderFieldType.IMAGE, LazyI18nString("logo"), "event:image")
+ PlaceholderField(LazyI18nString("logo"), "event:image")
],
- entry_type=PlaceholderFieldType.IMAGE,
+ entry_type=FieldType.IMAGE,
),
PlaceholderFieldGroup(
identifier="primary",
@@ -117,7 +124,7 @@ class AppleWalletEventTicket(PassStyle):
min_entries=1,
max_entries=1,
default_entries=[
- PlaceholderField(PlaceholderFieldType.TEXT, LazyI18nString("Ticket type"), "item")
+ PlaceholderField(LazyI18nString("Ticket type"), "item")
],
),
PlaceholderFieldGroup(
@@ -141,7 +148,7 @@ class GoogleWalletEventTicket(PassStyle):
fields = [
PredefinedFieldGroup(identifier="seating", name=_("Seating")),
PlaceholderFieldGroup(
- identifier="qrcode", name=_("QR-Code"), entry_type=PlaceholderFieldType.CODE
+ identifier="qrcode", name=_("QR-Code"), entry_type=FieldType.CODE
),
]
diff --git a/src/pretix/plugins/wallet/templates/pretixplugins/wallet/create.html b/src/pretix/plugins/wallet/templates/pretixplugins/wallet/create.html
new file mode 100644
index 0000000000..144de85e76
--- /dev/null
+++ b/src/pretix/plugins/wallet/templates/pretixplugins/wallet/create.html
@@ -0,0 +1,35 @@
+{% extends "pretixcontrol/event/base.html" %}
+{% load i18n %}
+{% load money %}
+{% load bootstrap3 %}
+{% load vite %}
+{% load static %}
+{% load compress %}
+
+
+{% block title %}{% trans "Wallet layouts" %}{% endblock %}
+
+{% block content %}
+ {% trans "New layout" %}
+
+{% endblock %}
diff --git a/src/pretix/plugins/wallet/templates/pretixplugins/wallet/edit.html b/src/pretix/plugins/wallet/templates/pretixplugins/wallet/edit.html
index a2b79b7a81..048610077b 100644
--- a/src/pretix/plugins/wallet/templates/pretixplugins/wallet/edit.html
+++ b/src/pretix/plugins/wallet/templates/pretixplugins/wallet/edit.html
@@ -11,14 +11,9 @@
{% block content %}
{% trans "Edit layout" %} {{ object.name }}
- {{ styles|json_script:"styles" }}
- {{ variables|json_script:"variables" }}
- {{ form.errors|json_script:"form_errors" }}
- {{ layout|json_script:"layout" }}
-
+ {{ styles|json_script:"styles" }}
+ {{ variables|json_script:"variables" }}
+
{% vite_hmr %}
{% vite_asset "src/pretix/plugins/wallet/static/pretixplugins/wallet/main.ts" %}
{% csrf_token %}
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 cfe685a565..102e5f93fd 100644
--- a/src/pretix/plugins/wallet/templates/pretixplugins/wallet/layout_list.html
+++ b/src/pretix/plugins/wallet/templates/pretixplugins/wallet/layout_list.html
@@ -39,7 +39,7 @@
|
{% if "can_change_event_settings" in request.eventpermset %}
-
+
{{ l.name }}
{% else %}
@@ -54,7 +54,7 @@
{% elif "can_change_event_settings" in request.eventpermset %}
|
{% if "can_change_event_settings" in request.eventpermset %}
-
-
+
-
+
{% endif %}
|
diff --git a/src/pretix/plugins/wallet/urls.py b/src/pretix/plugins/wallet/urls.py
index 7d945f8bbb..956aa86d45 100644
--- a/src/pretix/plugins/wallet/urls.py
+++ b/src/pretix/plugins/wallet/urls.py
@@ -20,18 +20,26 @@
# .
#
from django.urls import re_path
+from pretix.api.urls import event_router
from .views import (
LayoutEditorView,
LayoutCreateView,
LayoutListView
)
+from .api import WalletLayoutViewSet
urlpatterns = [
re_path(r'^control/event/(?P[^/]+)/(?P[^/]+)/wallet/$',
LayoutListView.as_view(), name='index'),
- re_path(r'^control/event/(?P[^/]+)/(?P[^/]+)/wallet/edit/(?P[^/]+)/$',
+ re_path(r'^control/event/(?P[^/]+)/(?P[^/]+)/wallet/add/(?P[^/]+)/$',
LayoutCreateView.as_view(), name='add'),
- re_path(r'^control/event/(?P[^/]+)/(?P[^/]+)/wallet/edit/(?P[^/]+)/(?P[^/]+)/$',
+ re_path(r'^control/event/(?P[^/]+)/(?P[^/]+)/wallet/edit/(?P[^/]+)/$',
LayoutEditorView.as_view(), name='edit'),
+ re_path(r'^control/event/(?P[^/]+)/(?P[^/]+)/wallet/default/(?P[^/]+)/$', # TODO
+ LayoutEditorView.as_view(), name='default'),
+ re_path(r'^control/event/(?P[^/]+)/(?P[^/]+)/wallet/delete/(?P[^/]+)/$', # TODO
+ LayoutEditorView.as_view(), name='delete'),
]
+
+event_router.register('walletlayouts', WalletLayoutViewSet)
diff --git a/src/pretix/plugins/wallet/views.py b/src/pretix/plugins/wallet/views.py
index cb346289b5..636e31b52b 100644
--- a/src/pretix/plugins/wallet/views.py
+++ b/src/pretix/plugins/wallet/views.py
@@ -1,22 +1,20 @@
+import json
from typing import Any
+from django import forms
from django.http import Http404
-from django.shortcuts import redirect
from django.urls import reverse
-from django.views.generic import FormView, ListView, CreateView, UpdateView
+from django.utils.translation import gettext_lazy as _
+from django.views.generic import (
+ CreateView, DetailView, ListView
+)
from pretix.base.pdf import get_images, get_variables
from pretix.control.permissions import EventPermissionRequiredMixin
-from .styles import PassLayout, get_platform_styles, get_platforms
+
from .models import WalletLayout
-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
-from pretix.api.serializers.i18n import I18nAwareModelSerializer
-from rest_framework import serializers
-from rest_framework.renderers import JSONRenderer
+from .styles import get_platform_styles, get_platforms
+
+
# TODO: should this even be a list view?
class LayoutListView(EventPermissionRequiredMixin, ListView):
model = WalletLayout
@@ -33,102 +31,24 @@ class LayoutListView(EventPermissionRequiredMixin, ListView):
return ctx
-
-class LayoutEditForm(forms.ModelForm):
- style = forms.ChoiceField()
-
- def __init__(self, **kwargs):
- self.platform = kwargs.pop('platform')
- super().__init__(**kwargs)
-
- class Meta:
- model = WalletLayout
- fields = ("name","style","layout")
-
- def __init__(self, event, platform, **kwargs):
- super().__init__(**kwargs)
- self.event = event
- self.platform = platform
- self.platform_styles = get_platform_styles(platform)
- self.fields["style"].choices = [
- (id, style.name) for id, style in self.platform_styles.items()
- ]
-
- def coerce_style(self, value):
- return self.platform_styles[value]
-
- def clean_layout(self):
- layout = self.cleaned_data["layout"]
-
- if not isinstance(layout, dict):
- raise ValidationError(_("Layout must be a dict"))
- return layout
-
- def clean(self):
- if "style" in self.cleaned_data and "layout" in self.cleaned_data:
- layout = PassLayout(
- style=self.coerce_style(self.cleaned_data["style"]), layout=self.cleaned_data["layout"]
- )
- layout.validate(self.event)
- return self.cleaned_data
-
-class LayoutSerializer(I18nAwareModelSerializer):
- # # TODO: only necessary if we save through this serializer
- # style = serializers.ChoiceField(choices={})
-
- # def __init__(self, *args, platform, **kwargs):
- # super().__init__(*args, **kwargs)
- # self.platform = platform
- # self.platform_styles = get_platform_styles(platform)
- # self.fields["style"].choices = [
- # (id, style.name) for id, style in self.platform_styles.items()
- # ]
-
-
- class Meta:
- model = WalletLayout
- fields = ("name","style","layout")
-
-class LayoutEditorView(EventPermissionRequiredMixin, UpdateView):
+class LayoutEditorView(DetailView):
template_name = "pretixplugins/wallet/edit.html"
- form_class = LayoutEditForm
model = WalletLayout
- permission = "can_change_event_settings" # TODO: new permission name
+ permission = "event.settings.general:write"
pk_url_kwarg = "layout"
- @property
- def platform(self):
- return self.kwargs["platform"]
-
- def get_form_kwargs(self) -> dict[str, Any]:
- kwargs = super().get_form_kwargs()
- kwargs['event'] = self.request.event
- kwargs["platform"] = self.platform
- return kwargs
-
def get_platform_styles(self):
- if self.platform not in get_platforms():
+ if self.object.platform not in get_platforms():
raise Http404(
- _("Unknown platform '{platform}'").format(platform=self.platform)
+ _("Unknown platform '{platform}'").format(platform=self.object.platform)
)
- return get_platform_styles(self.platform)
+ return get_platform_styles(self.object.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()
}
- if self.request.method == "POST":
- form = self.get_form()
- if not form.is_valid():
- layout_data = LayoutSerializer(self.object).data
- layout_data.update(form.cleaned_data)
- context['layout'] = layout_data
- else:
- context["layout"] = LayoutSerializer(self.object).data
- else:
- context["layout"] = LayoutSerializer(self.object).data
-
context["variables"] = {
"text": {
varname: {"label": var["label"], "editor_sample": var["editor_sample"]}
@@ -140,18 +60,47 @@ class LayoutEditorView(EventPermissionRequiredMixin, UpdateView):
}
return context
+class WalletLayoutCreateForm(forms.ModelForm):
+ class Meta:
+ model = WalletLayout
+ fields = ("name",)
+
+ def __init__(self, *args, platform, event, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.platform = platform
+ self.event = event
+
+ def save(self, *args, **kwargs) -> Any:
+ self.instance.platform = self.platform
+ self.instance.event = self.event
+ return super().save(*args, **kwargs)
+
+class LayoutCreateView(CreateView):
+ template_name = "pretixplugins/wallet/create.html"
+ form_class = WalletLayoutCreateForm
+ permission = "event.settings.general:write"
+
+ @property
+ def platform(self):
+ platform = self.kwargs['platform']
+ if platform not in get_platforms():
+ raise Http404(
+ _("Unknown platform '{platform}'").format(platform=platform)
+ )
+ return platform
+
+ def get_form_kwargs(self) -> dict[str, Any]:
+ kwargs = super().get_form_kwargs()
+ kwargs['platform'] = self.platform
+ kwargs['event'] = self.request.event
+ 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,
- "platform": self.platform,
"layout": self.object.pk,
},
- )
-
-
-class LayoutCreateView(LayoutEditorView):
- def get_object(self, queryset=None):
- return WalletLayout(event=self.request.event, platform=self.platform)
\ No newline at end of file
+ )
\ No newline at end of file