mirror of
https://github.com/pretix/pretix.git
synced 2026-05-18 17:24:03 +00:00
WIP
This commit is contained in:
@@ -4,7 +4,23 @@ import enum
|
|||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from i18nfield.strings import LazyI18nString
|
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):
|
class PlaceholderFieldType(enum.Enum):
|
||||||
TEXT = "text"
|
TEXT = "text"
|
||||||
CODE = "qr"
|
CODE = "qr"
|
||||||
@@ -108,6 +124,7 @@ class GoogleWalletEventTicket(PassStyle):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
AVAILABLE_PLATFORMS = {"apple": ApplePlatform, "google": GooglePlatform}
|
||||||
AVAILABLE_STYLES = [AppleWalletEventTicket(), GoogleWalletEventTicket()]
|
AVAILABLE_STYLES = [AppleWalletEventTicket(), GoogleWalletEventTicket()]
|
||||||
|
|
||||||
def get_platforms_with_styles():
|
def get_platforms_with_styles():
|
||||||
@@ -127,7 +144,7 @@ def get_platform_styles(platform):
|
|||||||
return platform_styles
|
return platform_styles
|
||||||
|
|
||||||
def get_platforms():
|
def get_platforms():
|
||||||
return sorted(set(style.platform for style in AVAILABLE_STYLES))
|
return AVAILABLE_PLATFORMS
|
||||||
|
|
||||||
class PassLayout:
|
class PassLayout:
|
||||||
style: PassStyle
|
style: PassStyle
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
{% extends "pretixcontrol/event/base.html" %}
|
{% extends "pretixcontrol/event/base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load money %}
|
{% load money %}
|
||||||
|
{% load bootstrap3 %}
|
||||||
|
|
||||||
{% block title %}{% trans "Wallet layouts" %}{% endblock %}
|
{% block title %}{% trans "Wallet layouts" %}{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<pre><code>{{ styles }}</code></pre>
|
<pre><code>{{ styles }}</code></pre>
|
||||||
@@ -9,7 +11,7 @@
|
|||||||
{{ variables|json_script:"variables" }}
|
{{ variables|json_script:"variables" }}
|
||||||
<form method="post">
|
<form method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{form}}
|
{% bootstrap_form form %}
|
||||||
<button type="submit" class="btn btn-default">
|
<button type="submit" class="btn btn-default">
|
||||||
{% trans "Submit " %}
|
{% trans "Submit " %}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -5,62 +5,76 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>{% trans "Wallet layouts" %}</h1>
|
<h1>{% trans "Wallet layouts" %}</h1>
|
||||||
<div class="tabbed-form">
|
<div class="tabbed-form">
|
||||||
{% for platform in platforms %}
|
{% for platform in platforms.values %}
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>{{platform}}</legend>
|
<legend>{{platform.name}}</legend>
|
||||||
|
{% if platforms.get_layout_qs|length == 0 %}
|
||||||
|
<div class="empty-collection">
|
||||||
|
<p>
|
||||||
|
{% blocktrans trimmed %}
|
||||||
|
You haven't created any layouts yet.
|
||||||
|
{% endblocktrans %}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{% if "event.settings.general:write" in request.eventpermset %}
|
||||||
|
<a href="{% url "plugins:wallet:add" organizer=request.event.organizer.slug event=request.event.slug platform=platform.identifier %}"
|
||||||
|
class="btn btn-primary btn-lg"><i class="fa fa-plus"></i> {% trans "Create a new layout" %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover table-quotas">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{% trans "Name" %}</th>
|
||||||
|
<th>{% trans "Default" %}</th>
|
||||||
|
<th class="action-col-2"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for l in platforms.get_layout_qs %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
{% if "can_change_event_settings" in request.eventpermset %}
|
||||||
|
<strong><a href="{% url "plugins:ticketoutputpdf:edit" organizer=request.event.organizer.slug event=request.event.slug layout=l.id %}">
|
||||||
|
{{ l.name }}
|
||||||
|
</a></strong>
|
||||||
|
{% else %}
|
||||||
|
<strong>{{ l.name }}</strong>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% if l.default %}
|
||||||
|
<span class="text-success">
|
||||||
|
<span class="fa fa-check"></span>
|
||||||
|
{% trans "Default" %}
|
||||||
|
</span>
|
||||||
|
{% elif "can_change_event_settings" in request.eventpermset %}
|
||||||
|
<form class="form-inline" method="post"
|
||||||
|
action="{% url "plugins:ticketoutputpdf:default" organizer=request.event.organizer.slug event=request.event.slug layout=l.id %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
<button class="btn btn-default btn-sm">
|
||||||
|
{% trans "Make default" %}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td class="text-right flip">
|
||||||
|
{% if "can_change_event_settings" in request.eventpermset %}
|
||||||
|
<a href="{% url "plugins:ticketoutputpdf:edit" organizer=request.event.organizer.slug event=request.event.slug layout=l.id %}" class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
|
||||||
|
<a href="{% url "plugins:ticketoutputpdf:add" organizer=request.event.organizer.slug event=request.event.slug %}?copy_from={{ l.id }}"
|
||||||
|
class="btn btn-default btn-sm" title="{% trans "Clone" %}" data-toggle="tooltip"><i class="fa fa-copy"></i></a>
|
||||||
|
<a href="{% url "plugins:ticketoutputpdf:delete" organizer=request.event.organizer.slug event=request.event.slug layout=l.id %}" class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% comment %} <div class="table-responsive">
|
|
||||||
<table class="table table-hover table-quotas">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>{% trans "Name" %}</th>
|
|
||||||
<th>{% trans "Default" %}</th>
|
|
||||||
<th class="action-col-2"></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for l in layouts %}
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
{% if "can_change_event_settings" in request.eventpermset %}
|
|
||||||
<strong><a href="{% url "plugins:ticketoutputpdf:edit" organizer=request.event.organizer.slug event=request.event.slug layout=l.id %}">
|
|
||||||
{{ l.name }}
|
|
||||||
</a></strong>
|
|
||||||
{% else %}
|
|
||||||
<strong>{{ l.name }}</strong>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{% if l.default %}
|
|
||||||
<span class="text-success">
|
|
||||||
<span class="fa fa-check"></span>
|
|
||||||
{% trans "Default" %}
|
|
||||||
</span>
|
|
||||||
{% elif "can_change_event_settings" in request.eventpermset %}
|
|
||||||
<form class="form-inline" method="post"
|
|
||||||
action="{% url "plugins:ticketoutputpdf:default" organizer=request.event.organizer.slug event=request.event.slug layout=l.id %}">
|
|
||||||
{% csrf_token %}
|
|
||||||
<button class="btn btn-default btn-sm">
|
|
||||||
{% trans "Make default" %}
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<td class="text-right flip">
|
|
||||||
{% if "can_change_event_settings" in request.eventpermset %}
|
|
||||||
<a href="{% url "plugins:ticketoutputpdf:edit" organizer=request.event.organizer.slug event=request.event.slug layout=l.id %}" class="btn btn-default btn-sm"><i class="fa fa-edit"></i></a>
|
|
||||||
<a href="{% url "plugins:ticketoutputpdf:add" organizer=request.event.organizer.slug event=request.event.slug %}?copy_from={{ l.id }}"
|
|
||||||
class="btn btn-default btn-sm" title="{% trans "Clone" %}" data-toggle="tooltip"><i class="fa fa-copy"></i></a>
|
|
||||||
<a href="{% url "plugins:ticketoutputpdf:delete" organizer=request.event.organizer.slug event=request.event.slug layout=l.id %}" class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{% endcomment %}
|
|
||||||
{% include "pretixcontrol/pagination.html" %}
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
<p>
|
||||||
|
<a class="btn btn-primary btn-lg" target="_blank"
|
||||||
|
href="{% url "plugins:wallet:index" organizer=request.organizer.slug event=request.event.slug %}">
|
||||||
|
<span class="fa fa-paint-brush"></span>
|
||||||
|
{% trans "Edit layouts" %}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
@@ -24,34 +24,48 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
from pretix.base.ticketoutput import BaseTicketOutput
|
from pretix.base.ticketoutput import BaseTicketOutput
|
||||||
from pretix.base.models import Event
|
from pretix.base.models import Event
|
||||||
from pretix.base.settings import SettingsSandbox
|
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):
|
class WalletSettingsHolder(BaseTicketOutput):
|
||||||
identifier = 'wallet'
|
identifier = "wallet"
|
||||||
verbose_name = _('Wallet Output')
|
verbose_name = _("Wallet Output")
|
||||||
|
|
||||||
is_meta = True
|
is_meta = True
|
||||||
is_enabled = False
|
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):
|
class WalletOutput(BaseTicketOutput):
|
||||||
settings_form_fields = []
|
settings_form_fields = []
|
||||||
|
|
||||||
def __init__(self, event: Event):
|
def __init__(self, event: Event):
|
||||||
super().__init__(event)
|
super().__init__(event)
|
||||||
self.settings = SettingsSandbox('ticketoutput', WalletSettingsHolder.identifier, event)
|
self.settings = SettingsSandbox(
|
||||||
|
"ticketoutput", WalletSettingsHolder.identifier, event
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class GoogleWalletTicketOutput(WalletOutput):
|
class GoogleWalletTicketOutput(WalletOutput):
|
||||||
identifier = 'wallet_google'
|
identifier = "wallet_google"
|
||||||
verbose_name = _('Google')
|
verbose_name = _("Google")
|
||||||
download_button_text = "Add to Google Wallet"
|
download_button_text = "Add to Google Wallet"
|
||||||
|
|
||||||
|
|
||||||
class AppleWalletTicketOutput(WalletOutput):
|
class AppleWalletTicketOutput(WalletOutput):
|
||||||
identifier = 'wallet_apple'
|
identifier = "wallet_apple"
|
||||||
verbose_name = _('Apple')
|
verbose_name = _("Apple")
|
||||||
download_button_text = "Add to Apple Wallet"
|
download_button_text = "Add to Apple Wallet"
|
||||||
|
|
||||||
|
|
||||||
OUTPUTS = [WalletSettingsHolder, GoogleWalletTicketOutput, AppleWalletTicketOutput]
|
OUTPUTS = [WalletSettingsHolder, GoogleWalletTicketOutput, AppleWalletTicketOutput]
|
||||||
|
|||||||
@@ -22,7 +22,8 @@
|
|||||||
from django.urls import re_path
|
from django.urls import re_path
|
||||||
|
|
||||||
from .views import (
|
from .views import (
|
||||||
EditorView,
|
LayoutEditorView,
|
||||||
|
LayoutCreateView,
|
||||||
LayoutListView
|
LayoutListView
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -30,7 +31,7 @@ urlpatterns = [
|
|||||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/wallet/$',
|
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/wallet/$',
|
||||||
LayoutListView.as_view(), name='index'),
|
LayoutListView.as_view(), name='index'),
|
||||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/wallet/edit/(?P<platform>[^/]+)/$',
|
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/wallet/edit/(?P<platform>[^/]+)/$',
|
||||||
EditorView.as_view(), name='edit'),
|
LayoutCreateView.as_view(), name='add'),
|
||||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/wallet/edit/(?P<platform>[^/]+)/(?P<layout>[^/]+)/$',
|
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/wallet/edit/(?P<platform>[^/]+)/(?P<layout>[^/]+)/$',
|
||||||
EditorView.as_view(), name='edit'),
|
LayoutEditorView.as_view(), name='edit'),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from typing import Any
|
|||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.urls import reverse
|
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.base.pdf import get_variables
|
||||||
from pretix.control.permissions import EventPermissionRequiredMixin
|
from pretix.control.permissions import EventPermissionRequiredMixin
|
||||||
from .styles import PassLayout, get_platform_styles, get_platforms
|
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.utils.translation import gettext_lazy as _
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.core.exceptions import ValidationError
|
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):
|
class LayoutListView(EventPermissionRequiredMixin, ListView):
|
||||||
model = WalletLayout
|
model = WalletLayout
|
||||||
permission = "can_change_event_settings"
|
permission = "can_change_event_settings"
|
||||||
@@ -29,11 +31,19 @@ class LayoutListView(EventPermissionRequiredMixin, ListView):
|
|||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
|
||||||
class EditorForm(forms.Form):
|
|
||||||
name = forms.CharField()
|
class LayoutEditForm(forms.ModelForm):
|
||||||
style = forms.TypedChoiceField()
|
style = forms.TypedChoiceField()
|
||||||
layout = forms.JSONField(initial={})
|
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):
|
def __init__(self, platform, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self.platform = platform
|
self.platform = platform
|
||||||
@@ -60,13 +70,12 @@ class EditorForm(forms.Form):
|
|||||||
)
|
)
|
||||||
layout.validate()
|
layout.validate()
|
||||||
return self.cleaned_data
|
return self.cleaned_data
|
||||||
|
|
||||||
|
class LayoutCreateView(EventPermissionRequiredMixin, FormView):
|
||||||
class EditorView(EventPermissionRequiredMixin, FormView):
|
|
||||||
template_name = "pretixplugins/wallet/edit.html"
|
template_name = "pretixplugins/wallet/edit.html"
|
||||||
form_class = EditorForm
|
form_class = LayoutEditForm
|
||||||
success_url = ""
|
model = WalletLayout
|
||||||
permission = "can_change_event_settings"
|
permission = "can_change_event_settings" # TODO: new permission name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def platform(self):
|
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
|
||||||
Reference in New Issue
Block a user