forked from CGM_Public/pretix_original
WalletLayout now contain layouts for all platforms
This commit is contained in:
@@ -1,35 +1,21 @@
|
||||
from rest_framework import viewsets
|
||||
from django.db import transaction
|
||||
from .styles import PassLayout, AVAILABLE_STYLES_DICT
|
||||
from .models import WalletLayout
|
||||
from .styles import PassLayout, AVAILABLE_STYLES_DICT, AVAILABLE_PLATFORMS
|
||||
from .models import WalletLayout, WalletPlatformLayout
|
||||
from pretix.api.serializers.i18n import I18nAwareModelSerializer
|
||||
import django_filters.rest_framework
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from .views import get_layout_variables
|
||||
from rest_framework import serializers
|
||||
|
||||
|
||||
class WalletLayoutSerializer(I18nAwareModelSerializer):
|
||||
class WalletPlatformLayoutSerializer(I18nAwareModelSerializer):
|
||||
platform = serializers.ChoiceField(choices=[p.identifier for p in AVAILABLE_PLATFORMS])
|
||||
style = serializers.CharField(allow_null=True, required=False)
|
||||
|
||||
class Meta:
|
||||
model = WalletLayout
|
||||
fields = ("id", "platform", "name", "style", "layout")
|
||||
read_only_fields = ("id",)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
if self.instance:
|
||||
self.fields['platform'].read_only = True
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super().save(*args, **kwargs, event=self.context["event"])
|
||||
|
||||
def validate_platform(self, value):
|
||||
if self.instance and value != self.instance.platform:
|
||||
raise ValidationError(_("Platform cannot be changed"))
|
||||
|
||||
if value not in AVAILABLE_STYLES_DICT:
|
||||
raise ValidationError(_("Invalid platform"))
|
||||
return value
|
||||
model = WalletPlatformLayout
|
||||
fields = ("platform", "style", "layout")
|
||||
|
||||
def validate_layout(self, value):
|
||||
if not isinstance(value, dict):
|
||||
@@ -37,11 +23,10 @@ class WalletLayoutSerializer(I18nAwareModelSerializer):
|
||||
return value
|
||||
|
||||
def validate(self, data):
|
||||
if self.instance:
|
||||
platform = self.instance.platform
|
||||
else:
|
||||
platform = data.get('platform', None)
|
||||
if "style" in data and "layout" in data and platform:
|
||||
platform = data.get('platform')
|
||||
style = data.get('style')
|
||||
layout = data.get('layout')
|
||||
if platform and style and layout:
|
||||
platform_styles = AVAILABLE_STYLES_DICT[platform]
|
||||
|
||||
if data["style"] not in platform_styles:
|
||||
@@ -54,20 +39,38 @@ class WalletLayoutSerializer(I18nAwareModelSerializer):
|
||||
return data
|
||||
|
||||
|
||||
class WalletLayoutSerializer(I18nAwareModelSerializer):
|
||||
platform_layouts = WalletPlatformLayoutSerializer(many=True)
|
||||
|
||||
class Meta:
|
||||
model = WalletLayout
|
||||
fields = ("id", "name", "platform_layouts")
|
||||
read_only_fields = ("id",)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super().save(*args, **kwargs, event=self.context["event"])
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
platform_layouts = validated_data.pop('platform_layouts')
|
||||
for layout in platform_layouts:
|
||||
if layout['style']:
|
||||
instance.platform_layouts.update_or_create(platform=layout['platform'], defaults=layout)
|
||||
instance.platform_layouts.exclude(platform__in={layout['platform'] for layout in platform_layouts if layout['style'] is not None}).delete()
|
||||
return super().update(instance, validated_data)
|
||||
|
||||
|
||||
class WalletLayoutViewSet(viewsets.ModelViewSet):
|
||||
model = WalletLayout
|
||||
queryset = WalletLayout.objects.none()
|
||||
serializer_class = WalletLayoutSerializer
|
||||
filter_backends = (django_filters.rest_framework.DjangoFilterBackend,)
|
||||
filterset_fields = ["platform"]
|
||||
permission = "event.settings.general:write"
|
||||
|
||||
def get_queryset(self):
|
||||
return self.request.event.wallet_layouts.all()
|
||||
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
return super().get_serializer(*args, **kwargs)
|
||||
|
||||
def get_serializer_context(self):
|
||||
ctx = super().get_serializer_context()
|
||||
ctx["event"] = self.request.event
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Generated by Django 4.2.28 on 2026-03-17 16:29
|
||||
# Generated by Django 5.2.13 on 2026-05-19 15:39
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import pretix.base.models.base
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
@@ -10,7 +10,7 @@ class Migration(migrations.Migration):
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
("pretixbase", "0297_outgoingmail"),
|
||||
("pretixbase", "0300_alter_customer_locale_alter_user_locale"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
@@ -24,9 +24,6 @@ class Migration(migrations.Migration):
|
||||
),
|
||||
),
|
||||
("name", models.CharField(max_length=190)),
|
||||
("platform", models.CharField(max_length=10)),
|
||||
("style", models.CharField(max_length=255)),
|
||||
("layout", models.TextField()),
|
||||
(
|
||||
"event",
|
||||
models.ForeignKey(
|
||||
@@ -37,7 +34,64 @@ class Migration(migrations.Migration):
|
||||
),
|
||||
],
|
||||
options={
|
||||
"ordering": ("name",),
|
||||
"abstract": False,
|
||||
},
|
||||
bases=(models.Model, pretix.base.models.base.LoggingMixin),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="WalletLayoutItem",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True, primary_key=True, serialize=False
|
||||
),
|
||||
),
|
||||
(
|
||||
"item",
|
||||
models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="walletlayout_assignments",
|
||||
to="pretixbase.item",
|
||||
),
|
||||
),
|
||||
(
|
||||
"layout",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="item_assignments",
|
||||
to="wallet.walletlayout",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"unique_together": {("item", "layout")},
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="WalletPlatformLayout",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True, primary_key=True, serialize=False
|
||||
),
|
||||
),
|
||||
("platform", models.CharField(max_length=10)),
|
||||
("style", models.CharField(max_length=255)),
|
||||
("layout", models.JSONField(default=dict)),
|
||||
(
|
||||
"parent",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="platform_layouts",
|
||||
to="wallet.walletlayout",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"unique_together": {("parent", "platform")},
|
||||
},
|
||||
bases=(models.Model, pretix.base.models.base.LoggingMixin),
|
||||
),
|
||||
|
||||
@@ -24,6 +24,7 @@ from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from pretix.base.models import LoggedModel
|
||||
from django_scopes import ScopedManager
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
|
||||
class WalletLayout(LoggedModel):
|
||||
@@ -36,28 +37,31 @@ class WalletLayout(LoggedModel):
|
||||
max_length=190,
|
||||
verbose_name=_('Name')
|
||||
)
|
||||
|
||||
objects = ScopedManager(organizer='event__organizer')
|
||||
|
||||
|
||||
class WalletPlatformLayout(LoggedModel):
|
||||
parent = models.ForeignKey(WalletLayout, on_delete=models.CASCADE, related_name="platform_layouts")
|
||||
|
||||
platform = models.CharField(max_length=10)
|
||||
style = models.CharField(max_length=255)
|
||||
layout = models.JSONField(default=dict)
|
||||
|
||||
objects = ScopedManager(organizer='event__organizer')
|
||||
objects = ScopedManager(organizer='parent__event__organizer')
|
||||
|
||||
class Meta:
|
||||
ordering = ("name",)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
unique_together = (('parent', 'platform'),)
|
||||
|
||||
|
||||
class WalletLayoutItem(models.Model):
|
||||
item = models.ForeignKey('pretixbase.Item', null=True, blank=True, related_name='walletlayout_assignments',
|
||||
on_delete=models.CASCADE)
|
||||
layout = models.ForeignKey(WalletLayout, on_delete=models.CASCADE, related_name='item_assignments')
|
||||
sales_channel = models.ForeignKey(
|
||||
"pretixbase.SalesChannel",
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
unique_together = (('item', 'layout', 'sales_channel'),)
|
||||
ordering = ("id",)
|
||||
unique_together = (('item', 'layout'),)
|
||||
|
||||
def clean(self):
|
||||
if self.item.event != self.layout.event:
|
||||
raise ValidationError("cannot bind layout to item of different event")
|
||||
|
||||
@@ -9,8 +9,8 @@ const gettext = (window as any).gettext;
|
||||
const isLoading = ref<boolean>(true);
|
||||
const wallet_layout = ref<Layout | null>(null);
|
||||
|
||||
const STYLES: Styles = JSON.parse(
|
||||
document.querySelector("#styles")?.textContent ?? "{}",
|
||||
const PLATFORMS: Platforms = JSON.parse(
|
||||
document.querySelector("#platforms")?.textContent ?? "{}",
|
||||
);
|
||||
const VARIABLES: VariableConfig = JSON.parse(
|
||||
document.querySelector("#variables")?.textContent ?? "{}",
|
||||
@@ -55,11 +55,36 @@ function saveLayout(e: SubmitEvent) {
|
||||
},
|
||||
)
|
||||
.then((x) => x.json())
|
||||
.catch((x) => alert(x))
|
||||
.then((x) => {
|
||||
wallet_layout.value = x;
|
||||
isLoading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
const currentPlatform = ref(PLATFORMS[0].identifier);
|
||||
const currentLayout = computed(() => ({}));
|
||||
const platformStyles = computed(() => {
|
||||
for (const platform of PLATFORMS) {
|
||||
if (platform.identifier === currentPlatform.value) {
|
||||
return platform.styles
|
||||
}
|
||||
}
|
||||
});
|
||||
const platformLayout = computed(() => {
|
||||
for (const layout of wallet_layout.value.platform_layouts) {
|
||||
if (layout.platform === currentPlatform.value) {
|
||||
return layout
|
||||
}
|
||||
}
|
||||
const newLayout = {platform: currentPlatform, style: null, layout: {}};
|
||||
wallet_layout.value.platform_layouts.push(newLayout);
|
||||
return newLayout
|
||||
});
|
||||
const platformChoices = computed(() => {
|
||||
return [[null, "Do not generate pass"], ...Object.values(platformStyles.value).map(x => [x.identifier, x.name])]
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template lang="pug">
|
||||
@@ -68,24 +93,29 @@ function saveLayout(e: SubmitEvent) {
|
||||
// TODO: proper spinner
|
||||
template(v-if="isLoading") {{ gettext("Loading...") }}
|
||||
form(v-else @submit="saveLayout")
|
||||
.row
|
||||
.col-md-8
|
||||
.form-group()
|
||||
Input(label="Name" v-model="wallet_layout.name")
|
||||
.form-group
|
||||
Input(label="Name" v-model="wallet_layout.name")
|
||||
nav
|
||||
ul.nav.nav-tabs
|
||||
li(v-for="platform in PLATFORMS" :class="{'active': currentPlatform === platform.identifier}")
|
||||
a(role="tab" @click="currentPlatform = platform.identifier") {{ platform.name }}
|
||||
.tabbed-form.tab-content
|
||||
.tab-pane.active.row
|
||||
.col-md-8
|
||||
Select.form-group(label="Style" v-model="platformLayout.style" :choices="platformChoices")
|
||||
|
||||
.form-group()
|
||||
Select(label="Style" v-model="wallet_layout.style" :choices="Object.values(STYLES).map(x => [x.identifier, x.name])")
|
||||
|
||||
StyleSettings(v-if="wallet_layout.style" v-model="wallet_layout.layout" :style="STYLES[wallet_layout.style]" :variables="VARIABLES" :locales="LOCALES")
|
||||
.col-md-4
|
||||
.panel.panel-default
|
||||
.panel-heading Preview
|
||||
.panel-body
|
||||
// TODO: Preview
|
||||
pre
|
||||
code {{ wallet_layout }}
|
||||
pre(v-if="wallet_layout.style")
|
||||
code {{ STYLES[wallet_layout.style] }}
|
||||
StyleSettings(v-if="platformLayout.style" v-model="platformLayout.layout" :style="platformStyles[platformLayout.style]" :variables="VARIABLES" :locales="LOCALES")
|
||||
.col-md-4
|
||||
.panel.panel-default
|
||||
.panel-heading Preview
|
||||
.panel-body
|
||||
// TODO: Preview
|
||||
pre
|
||||
code {{ platformLayout }}
|
||||
pre(v-if="wallet_layout.style")
|
||||
code {{ platformStyles[wallet_layout.style] }}
|
||||
pre
|
||||
code {{ wallet_layout }}
|
||||
.form-group.submit-group
|
||||
button.btn.btn-primary.btn-save(type="submit") Submit
|
||||
</template>
|
||||
|
||||
@@ -8,7 +8,8 @@ defineOptions({
|
||||
const props = defineProps<{
|
||||
label?: string
|
||||
choices: Array<[string, string]>
|
||||
errors?: string[]
|
||||
errors?: string[],
|
||||
class: string
|
||||
}>()
|
||||
const modelValue = defineModel<string|null>();
|
||||
const id = useId()
|
||||
@@ -23,7 +24,7 @@ watchEffect(() => {
|
||||
</script>
|
||||
|
||||
<template lang="pug">
|
||||
template(v-if="choices.length >= 1")
|
||||
template(v-if="choices.length >= 1" :class="props.class")
|
||||
label.control-label(v-if="props.label" :for="id") {{ props.label }}
|
||||
select.form-control(:id="id" v-model="modelValue" v-bind="$attrs" required)
|
||||
option(v-for="choice in props.choices" :key="choice[0]" :value="choice[0]") {{ choice[1] }}
|
||||
|
||||
@@ -48,10 +48,16 @@ type Variable = {
|
||||
label: string
|
||||
};
|
||||
|
||||
type Platform = {
|
||||
identifier: string;
|
||||
name: string;
|
||||
styles: Styles;
|
||||
};
|
||||
|
||||
type Styles = Record<string, Style>;
|
||||
type Variables = Record<string, Variable>;
|
||||
type VariableConfig = Record<string, Variables>;
|
||||
|
||||
type Platforms = Record<string, Platform>;
|
||||
|
||||
|
||||
type PlaceholderFieldGroupConfig = {
|
||||
|
||||
@@ -2,7 +2,8 @@ from .apple import ApplePlatform, AppleWalletEventTicket
|
||||
from .google import GooglePlatform, GoogleWalletEventTicket
|
||||
from .base import PassLayout
|
||||
|
||||
AVAILABLE_PLATFORMS = {"apple": ApplePlatform, "google": GooglePlatform}
|
||||
AVAILABLE_PLATFORMS = [ApplePlatform, GooglePlatform]
|
||||
|
||||
AVAILABLE_STYLES = {
|
||||
"apple": [AppleWalletEventTicket()],
|
||||
"google": [
|
||||
|
||||
@@ -19,7 +19,6 @@ import json
|
||||
from django.contrib.staticfiles import finders
|
||||
|
||||
|
||||
|
||||
class ApplePlatform(WalletPlatform):
|
||||
identifier = "apple"
|
||||
name = _("Apple")
|
||||
@@ -236,13 +235,13 @@ class AppleWalletEventTicket(AppleWalletStyle):
|
||||
raise ValueError("Unknown field group")
|
||||
return fields
|
||||
|
||||
def convert_fields(self, strings, fields):
|
||||
def convert_fields(self, strings, fields, prefix):
|
||||
converted = []
|
||||
for i,f in enumerate(fields):
|
||||
converted_field = {**f, "key": f"primary-{i}"}
|
||||
converted_field = {**f, "key": f"{prefix}-{i}"}
|
||||
if "label" in converted_field and isinstance(converted_field['label'], LazyI18nString):
|
||||
strings.add_entry(f"primary-{i}-label", converted_field['label'])
|
||||
converted_field['label'] = f"primary-{i}-label"
|
||||
strings.add_entry(f"{prefix}-{i}-label", converted_field['label'])
|
||||
converted_field['label'] = f"{prefix}-{i}-label"
|
||||
|
||||
converted.append(converted_field)
|
||||
return converted
|
||||
@@ -251,6 +250,6 @@ class AppleWalletEventTicket(AppleWalletStyle):
|
||||
fields = self.get_pass_fields(layout, context)
|
||||
return {
|
||||
"eventTicket": {
|
||||
"primaryFields": self.convert_fields(strings, fields['primary'])
|
||||
"primaryFields": self.convert_fields(strings, fields['primary'], 'primary')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
{% block content %}
|
||||
<h1>{% trans "Edit layout" %} {{ object.name }} </h1>
|
||||
{{ styles|json_script:"styles" }}
|
||||
{{ platforms|json_script:"platforms" }}
|
||||
{{ variables|json_script:"variables" }}
|
||||
{{ locales|json_script:"locales" }}
|
||||
<div id="editor" data-layout-id="{{ object.pk }}"></div>
|
||||
|
||||
@@ -5,79 +5,70 @@
|
||||
{% block title %}{% trans "Wallet layouts" %}{% endblock %}
|
||||
{% block content %}
|
||||
<h1>{% trans "Wallet layouts" %}</h1>
|
||||
<div class="tabbed-form">
|
||||
{% for platform in platforms.values %}
|
||||
<fieldset>
|
||||
<legend>{{platform.name}}</legend>
|
||||
{% with platform_layouts=platform|platform_layouts:request.event %}
|
||||
{% if platform_layouts|length == 0 %}
|
||||
<div class="empty-collection">
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
You haven't created any layouts yet.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
{% if layouts|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 platform_layouts %}
|
||||
<tr>
|
||||
<td>
|
||||
{% if "can_change_event_settings" in request.eventpermset %}
|
||||
<strong><a href="{% url "plugins:wallet: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:wallet: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:wallet: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:wallet:add" organizer=request.event.organizer.slug event=request.event.slug platform=platform.identifier %}?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:wallet: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 %}
|
||||
{% endwith %}
|
||||
</fieldset>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% if "event.settings.general:write" in request.eventpermset %}
|
||||
<a href="{% url "plugins:wallet:add" organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||
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 layouts %}
|
||||
<tr>
|
||||
<td>
|
||||
{% if "can_change_event_settings" in request.eventpermset %}
|
||||
<strong><a href="{% url "plugins:wallet: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:wallet: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:wallet: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:wallet: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:wallet: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 %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -32,7 +32,7 @@ from .api import WalletLayoutViewSet
|
||||
urlpatterns = [
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/wallet/$',
|
||||
LayoutListView.as_view(), name='index'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/wallet/add/(?P<platform>[^/]+)/$',
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/wallet/add/$',
|
||||
LayoutCreateView.as_view(), name='add'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/wallet/edit/(?P<layout>[^/]+)/$',
|
||||
LayoutEditorView.as_view(), name='edit'),
|
||||
|
||||
@@ -31,7 +31,6 @@ def get_editor_variables(event):
|
||||
}
|
||||
|
||||
|
||||
# TODO: should this even be a list view?
|
||||
class LayoutListView(EventPermissionRequiredMixin, ListView):
|
||||
model = WalletLayout
|
||||
permission = "can_change_event_settings"
|
||||
@@ -39,12 +38,7 @@ class LayoutListView(EventPermissionRequiredMixin, ListView):
|
||||
context_object_name = "layouts"
|
||||
|
||||
def get_queryset(self):
|
||||
return self.request.event.wallet_layouts
|
||||
|
||||
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
ctx["platforms"] = AVAILABLE_PLATFORMS
|
||||
return ctx
|
||||
return self.request.event.wallet_layouts.all()
|
||||
|
||||
|
||||
class LayoutEditorView(DetailView):
|
||||
@@ -53,18 +47,19 @@ class LayoutEditorView(DetailView):
|
||||
permission = "event.settings.general:write"
|
||||
pk_url_kwarg = "layout"
|
||||
|
||||
def get_platform_styles(self):
|
||||
if self.object.platform not in AVAILABLE_STYLES:
|
||||
raise Http404(
|
||||
_("Unknown platform '{platform}'").format(platform=self.object.platform)
|
||||
)
|
||||
return AVAILABLE_STYLES[self.object.platform]
|
||||
|
||||
def get_context_data(self, **kwargs) -> dict[str, Any]:
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["styles"] = {
|
||||
style.identifier: style.asdict() for style in self.get_platform_styles()
|
||||
}
|
||||
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)
|
||||
@@ -79,13 +74,11 @@ class WalletLayoutCreateForm(forms.ModelForm):
|
||||
model = WalletLayout
|
||||
fields = ("name",)
|
||||
|
||||
def __init__(self, *args, platform, event, **kwargs):
|
||||
def __init__(self, *args, 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)
|
||||
|
||||
@@ -95,16 +88,8 @@ class LayoutCreateView(CreateView):
|
||||
form_class = WalletLayoutCreateForm
|
||||
permission = "event.settings.general:write"
|
||||
|
||||
@property
|
||||
def platform(self):
|
||||
platform = self.kwargs["platform"]
|
||||
if platform not in AVAILABLE_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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user