mirror of
https://github.com/pretix/pretix.git
synced 2026-08-07 10:17:49 +00:00
WIP
This commit is contained in:
@@ -10,49 +10,48 @@ const store = inject(StoreKey)!;
|
||||
const gettext = (window as any).gettext;
|
||||
|
||||
function openForm(url: string, data: Record<string, string>) {
|
||||
let form = document.createElement("form");
|
||||
form.target = "_blank";
|
||||
form.method = "POST";
|
||||
form.action = url;
|
||||
form.style.display = "none";
|
||||
let form = document.createElement("form");
|
||||
form.target = "_blank";
|
||||
form.method = "POST";
|
||||
form.action = url;
|
||||
form.style.display = "none";
|
||||
|
||||
for (var key in data) {
|
||||
var input = document.createElement("input");
|
||||
input.type = "hidden";
|
||||
input.name = key;
|
||||
input.value = data[key];
|
||||
form.appendChild(input);
|
||||
}
|
||||
document.body.appendChild(form);
|
||||
form.submit();
|
||||
document.body.removeChild(form);
|
||||
for (var key in data) {
|
||||
var input = document.createElement("input");
|
||||
input.type = "hidden";
|
||||
input.name = key;
|
||||
input.value = data[key];
|
||||
form.appendChild(input);
|
||||
}
|
||||
document.body.appendChild(form);
|
||||
form.submit();
|
||||
document.body.removeChild(form);
|
||||
}
|
||||
|
||||
function openPreview(e: SubmitEvent) {
|
||||
e.preventDefault();
|
||||
openForm("../../preview/", {
|
||||
csrfmiddlewaretoken: store.csrfToken,
|
||||
platform: store.currentPlatform,
|
||||
style: store.currentPlatformLayout.style,
|
||||
layout: JSON.stringify(store.currentPlatformLayout.layout),
|
||||
});
|
||||
e.preventDefault();
|
||||
openForm("../../preview/", {
|
||||
csrfmiddlewaretoken: store.csrfToken,
|
||||
platform: store.currentPlatform,
|
||||
style: store.currentPlatformLayout.style,
|
||||
layout: JSON.stringify(store.currentPlatformLayout.layout),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
const platformChoices = computed(() => {
|
||||
return [
|
||||
[null, "Do not generate pass"],
|
||||
...Object.values(store.currentPlatformStyles).map((x) => [
|
||||
x.identifier,
|
||||
x.name,
|
||||
]),
|
||||
];
|
||||
return [
|
||||
[null, "Do not generate pass"],
|
||||
...Object.values(store.currentPlatformStyles).map((x) => [
|
||||
x.identifier,
|
||||
x.name,
|
||||
]),
|
||||
];
|
||||
});
|
||||
|
||||
const preview_layout = computed(() => {
|
||||
return JSON.parse(store.currentPlatformStyles[store.currentPlatformLayout.style].preview_layout)
|
||||
})
|
||||
return store.currentPlatformStyles[store.currentPlatformLayout.style]
|
||||
.preview_layout;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template lang="pug">
|
||||
|
||||
+4
-3
@@ -6,7 +6,7 @@ import PlaceholderFieldgroupPreview from "./placeholder-fieldgroup-preview.vue";
|
||||
const store = inject(StoreKey)!
|
||||
|
||||
const props = defineProps<{
|
||||
config: Record<string, string>;
|
||||
config: PreviewFieldgroup;
|
||||
}>();
|
||||
|
||||
const style_def = Object.fromEntries(store.currentPlatformStyles[store.currentPlatformLayout.style].fieldgroups.map(x => [x.identifier, x]))[props.config.fieldgroup]
|
||||
@@ -14,7 +14,8 @@ const style_def = Object.fromEntries(store.currentPlatformStyles[store.currentPl
|
||||
</script>
|
||||
|
||||
<template lang="pug">
|
||||
PlaceholderFieldgroupPreview(v-if="style_def.type == 'placeholder'" :config="config" :style_def="style_def")
|
||||
PlaceholderFieldgroupPreview(v-if="style_def && style_def.type == 'placeholder'" :config="config" :style_def="style_def")
|
||||
PlaceholderFieldgroupPreview(v-else-if="style_def && style_def.type == 'predefined'" :config="config" :style_def="style_def")
|
||||
//- // TODO: support predefined group
|
||||
//- div(:style="{'flex-grow': config.relSize}")
|
||||
//- div(style="background-color: gray; display: flex; flex-direction: row;")
|
||||
@@ -33,4 +34,4 @@ const style_def = Object.fromEntries(store.currentPlatformStyles[store.currentPl
|
||||
//- div(style="position: absolute; background-color: red; top: 4.75cm; left: 0cm; height: 1cm; width: 10cm;") Secondary
|
||||
//- div(style="position: absolute; background-color: red; top: 7cm; left: 0cm; height: 1cm; width: 10cm;") Auxiliary
|
||||
//- div(style="position: absolute; background-color: red; top: 10cm; left: 3cm; height: 4cm; width: 4cm;")
|
||||
</template>
|
||||
</template>
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{
|
||||
config: {value: string; label?: string; display?: string};
|
||||
}>();
|
||||
|
||||
</script>
|
||||
|
||||
<template lang="pug">
|
||||
div.fieldgroup-item
|
||||
div.fieldgroup-label.nowrap(v-if="!!config.label") {{ config.label }}
|
||||
div.nowrap.content(:class="config.display") {{ config.value }}
|
||||
</template>
|
||||
|
||||
|
||||
<style lang="css" scoped>
|
||||
.fieldgroup-label {
|
||||
font-weight: bold;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.fieldgroup-item {
|
||||
flex: 0 1 100%;
|
||||
min-width: 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
.fieldgroup-item-image {
|
||||
max-height: 3lh;
|
||||
}
|
||||
.fieldgroup-item-qrcode {
|
||||
font-weight: bold;
|
||||
background-color: lightgray;
|
||||
width: 50%;
|
||||
aspect-ratio: 1;
|
||||
margin: auto;
|
||||
/* center content */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
padding: 1em;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.nowrap {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
text-wrap: nowrap;
|
||||
}
|
||||
.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
.large {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
.tight {
|
||||
line-height: 1;
|
||||
}
|
||||
</style>
|
||||
+2
-1
@@ -11,8 +11,9 @@ const props = defineProps<{ layout: Array<PreviewLayout> }>();
|
||||
<template lang="pug">
|
||||
div.pass-container
|
||||
div.pass-content
|
||||
RowPreview(v-for="row in layout" :config="row")
|
||||
RowPreview(v-for="row of layout" :config="row")
|
||||
</template>
|
||||
|
||||
<style lang="css" scoped>
|
||||
.pass-container {
|
||||
margin: 1em;
|
||||
|
||||
+2
-3
@@ -14,7 +14,7 @@ const props = defineProps<{
|
||||
<template lang="pug">
|
||||
// TODO: support predefined group
|
||||
div.fieldgroup-container(:style="{'flex-grow': config.relSize, 'flex-direction': config.direction || 'row'}")
|
||||
div.fieldgroup-item(v-for="{ entry, label, content } in store.currentLayoutFieldContent[config.fieldgroup]")
|
||||
div.fieldgroup-item(v-for="{ entry, label, content } of store.currentLayoutFieldContent[config.fieldgroup]")
|
||||
div.fieldgroup-item-qrcode(v-if="style_def.display == 'code'") {{ label }}
|
||||
|
||||
template(v-else)
|
||||
@@ -60,7 +60,6 @@ const props = defineProps<{
|
||||
padding: 1em;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.nowrap {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
@@ -75,4 +74,4 @@ const props = defineProps<{
|
||||
.tight {
|
||||
line-height: 1;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, inject, reactive, watchEffect } from "vue";
|
||||
import { StoreKey } from "../../walletStore";
|
||||
import { i18nstringLocalize } from "../../helpers";
|
||||
|
||||
const store = inject(StoreKey)!;
|
||||
|
||||
const props = defineProps<{
|
||||
config: PreviewFieldgroup;
|
||||
style_def: PredefinedFieldGroupDefinition;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template lang="pug">
|
||||
div {{ config.fieldgroup }}
|
||||
// TODO: support predefined group
|
||||
div.fieldgroup-container(:style="{'flex-grow': config.relSize, 'flex-direction': config.direction || 'row'}")
|
||||
div.fieldgroup-item(v-for="{ entry, label, content } of store.currentLayoutFieldContent[config.fieldgroup]")
|
||||
div.fieldgroup-item-qrcode(v-if="style_def.display == 'code'") {{ label }}
|
||||
|
||||
template(v-else)
|
||||
div.fieldgroup-label.nowrap(v-if="style_def.display == 'with_label'") {{ label }}
|
||||
div.nowrap.content(v-if="style_def.content_type == 'text'" :class="config.display") {{ content }}
|
||||
img.fieldgroup-item-image(v-else-if="style_def.content_type == 'image' && content" :src="i18nstringLocalize(content)")
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<style lang="css" scoped>
|
||||
.fieldgroup-container {
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
gap: 0.5em;
|
||||
min-height: 2lh;
|
||||
}
|
||||
.fieldgroup-label {
|
||||
font-weight: bold;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.fieldgroup-item {
|
||||
flex: 0 1 100%;
|
||||
min-width: 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
.fieldgroup-item-image {
|
||||
max-height: 3lh;
|
||||
}
|
||||
.fieldgroup-item-qrcode {
|
||||
font-weight: bold;
|
||||
background-color: lightgray;
|
||||
width: 50%;
|
||||
aspect-ratio: 1;
|
||||
margin: auto;
|
||||
/* center content */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
padding: 1em;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.nowrap {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
text-wrap: nowrap;
|
||||
}
|
||||
.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
.large {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
.tight {
|
||||
line-height: 1;
|
||||
}
|
||||
</style>
|
||||
+12
-4
@@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import FieldgroupPreview from './fieldgroup-preview.vue';
|
||||
import FixedPreview from './fixed-preview.vue';
|
||||
|
||||
const props = defineProps<{
|
||||
config: Record<string, string>;
|
||||
@@ -8,7 +9,14 @@ const props = defineProps<{
|
||||
</script>
|
||||
|
||||
<template lang="pug">
|
||||
div(v-if="'children' in config" style="width: 100%; display: flex; gap: 1em")
|
||||
RowPreview(v-for="child in config.children" :config="child")
|
||||
FieldgroupPreview(v-else :config="config")
|
||||
</template>
|
||||
div.preview-row(v-if="'children' in config" :style="{flexDirection: config.direction || 'row'}")
|
||||
RowPreview(v-for="child of config.children" :config="child")
|
||||
FieldgroupPreview(v-else-if="'fieldgroup' in config" :config="config")
|
||||
FixedPreview(v-else-if="'value' in config" :config="config")
|
||||
|
||||
</template>
|
||||
<style lang="css" scoped>
|
||||
.preview-row {
|
||||
width: 100%; display: flex; gap: 1em; display: flex
|
||||
}
|
||||
</style>
|
||||
@@ -219,6 +219,7 @@ class AppleWalletStyle(PassStyle):
|
||||
pkpass.add_file("pass.json", json.dumps(pass_json))
|
||||
return pkpass.finish()
|
||||
|
||||
|
||||
class AppleWalletEventTicket(AppleWalletStyle):
|
||||
identifier = "event_1"
|
||||
name = _("Event Ticket Layout 1")
|
||||
@@ -283,7 +284,30 @@ class AppleWalletEventTicket(AppleWalletStyle):
|
||||
),
|
||||
TextFieldGroup(identifier="back", name=_("Back")),
|
||||
]
|
||||
preview_layout = '[[{"children":[{"fieldgroup":"logo","relSize":1},{"fieldgroup":"logo_text","relSize":3,"display":["bold","large","centered"]},{"fieldgroup":"header","relSize":2,"display":["large", "tight"]}]},{"fieldgroup":"primary","display":"large"},{"fieldgroup":"secondary"},{"fieldgroup":"auxiliary"},{"fieldgroup":"code"}],[{"fieldgroup":"back","direction":"column"}]]'
|
||||
preview_layout = [
|
||||
[
|
||||
{
|
||||
"children": [
|
||||
{"fieldgroup": "logo", "relSize": 1},
|
||||
{
|
||||
"fieldgroup": "logo_text",
|
||||
"relSize": 3,
|
||||
"display": ["bold", "large", "centered"],
|
||||
},
|
||||
{
|
||||
"fieldgroup": "header",
|
||||
"relSize": 2,
|
||||
"display": ["large", "tight"],
|
||||
},
|
||||
]
|
||||
},
|
||||
{"fieldgroup": "primary", "display": "large"},
|
||||
{"fieldgroup": "secondary"},
|
||||
{"fieldgroup": "auxiliary"},
|
||||
{"fieldgroup": "code"},
|
||||
],
|
||||
[{"fieldgroup": "back", "direction": "column"}],
|
||||
]
|
||||
|
||||
def convert_fields(self, strings, fields, prefix):
|
||||
converted = []
|
||||
@@ -314,7 +338,9 @@ class AppleWalletEventTicket(AppleWalletStyle):
|
||||
strings, fields["auxiliary"], "auxiliary"
|
||||
),
|
||||
"backFields": self.convert_fields(strings, fields["back"], "back"),
|
||||
"headerFields": self.convert_fields(strings, fields["header"], "header"),
|
||||
"headerFields": self.convert_fields(
|
||||
strings, fields["header"], "header"
|
||||
),
|
||||
},
|
||||
}
|
||||
if fields["logo_text"]:
|
||||
@@ -322,11 +348,13 @@ class AppleWalletEventTicket(AppleWalletStyle):
|
||||
strings, fields["logo_text"], "logo_text"
|
||||
)[0]["value"]
|
||||
|
||||
if fields['code']:
|
||||
content["barcodes"] = [{
|
||||
"format": "PKBarcodeFormatQR",
|
||||
"message": str(fields["code"][0]["value"]),
|
||||
"messageEncoding": "utf-8",
|
||||
"altText": str(fields["code"][0]["value"])
|
||||
}]
|
||||
if fields["code"]:
|
||||
content["barcodes"] = [
|
||||
{
|
||||
"format": "PKBarcodeFormatQR",
|
||||
"message": str(fields["code"][0]["value"]),
|
||||
"messageEncoding": "utf-8",
|
||||
"altText": str(fields["code"][0]["value"]),
|
||||
}
|
||||
]
|
||||
return content
|
||||
|
||||
@@ -232,7 +232,7 @@ class PassStyle:
|
||||
# order here limits in what order users can configure field "overspilling" (if too many fields are defined, where should the rest go) -> can only go down in the list
|
||||
# we evaluate the fields in this order, so they overspill in this order as well (fields from primary are appended to the overspilling field before fields from secondary are etc)
|
||||
fieldgroups: list[FieldGroup]
|
||||
preview_layout: str | None
|
||||
preview_layout: list | None
|
||||
|
||||
def asdict(self):
|
||||
return {
|
||||
|
||||
@@ -1,40 +1,71 @@
|
||||
from pretix.base.models import Event, OrderPosition
|
||||
|
||||
from .base import FieldGroupDisplay, PassLayout, PassStyle, PredefinedFieldGroup, TextFieldGroup, WalletPlatform
|
||||
from .base import (
|
||||
FieldGroupDisplay,
|
||||
ImageFieldGroup,
|
||||
PassLayout,
|
||||
PassStyle,
|
||||
PlaceholderFieldEntry,
|
||||
PredefinedFieldGroup,
|
||||
TextFieldGroup,
|
||||
WalletPlatform,
|
||||
)
|
||||
from django.utils.translation import gettext_lazy as _, gettext
|
||||
import json
|
||||
|
||||
from walletobjects import ButtonJWT, EventTicketClass, EventTicketObject
|
||||
from walletobjects.comms import Comms
|
||||
from walletobjects.constants import (
|
||||
Barcode, ClassType, ConfirmationCode, DoorsOpen,
|
||||
MultipleDevicesAndHoldersAllowedStatus, ObjectState, ObjectType,
|
||||
ReviewStatus, Seat,
|
||||
Barcode,
|
||||
ClassType,
|
||||
ConfirmationCode,
|
||||
DoorsOpen,
|
||||
MultipleDevicesAndHoldersAllowedStatus,
|
||||
ObjectState,
|
||||
ObjectType,
|
||||
ReviewStatus,
|
||||
Seat,
|
||||
)
|
||||
from pretix.base.settings import GlobalSettingsObject
|
||||
import uuid
|
||||
from pretix.multidomain.urlreverse import eventreverse_absolute
|
||||
from django.utils import translation
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
def _get_instance_uuid():
|
||||
gs = GlobalSettingsObject()
|
||||
if not gs.settings.wallet_google_instance_uuid:
|
||||
gs.settings.wallet_google_instance_uuid = str(uuid.uuid4())
|
||||
return gs.settings.get("wallet_google_instance_uuid")
|
||||
|
||||
return gs.settings.wallet_google_instance_uuid
|
||||
|
||||
|
||||
def get_class_id(event: Event):
|
||||
# TODO: add layout id somewhere
|
||||
instance_uuid = _get_instance_uuid()
|
||||
issuer_id = event.settings.get('wallet_google_issuer_id')
|
||||
return "%s.pretix-%s-%s-%s" % (issuer_id, instance_uuid, event.organizer.slug, event.slug)
|
||||
issuer_id = event.settings.get("wallet_google_issuer_id")
|
||||
return "%s.pretix-%s-%s-%s" % (
|
||||
issuer_id,
|
||||
instance_uuid,
|
||||
event.organizer.slug,
|
||||
event.slug,
|
||||
)
|
||||
|
||||
|
||||
def get_object_id(op: OrderPosition):
|
||||
instance_uuid = _get_instance_uuid()
|
||||
issuer_id = op.order.event.settings.get('wallet_google_issuer_id')
|
||||
issuer_id = op.order.event.settings.get("wallet_google_issuer_id")
|
||||
|
||||
return "%s.pretix-%s-%s-%s-%s-%s" % (
|
||||
issuer_id,
|
||||
instance_uuid,
|
||||
op.order.event.organizer.slug,
|
||||
op.order.event.slug,
|
||||
op.order.code,
|
||||
op.positionid,
|
||||
)
|
||||
|
||||
return "%s.pretix-%s-%s-%s-%s-%s" % (issuer_id, instance_uuid,
|
||||
op.order.event.organizer.slug, op.order.event.slug,
|
||||
op.order.code, op.positionid)
|
||||
|
||||
def get_translated_dict(string, locales):
|
||||
translated = {}
|
||||
@@ -54,35 +85,69 @@ def get_translated_string(string, locale):
|
||||
|
||||
return translated
|
||||
|
||||
|
||||
class GooglePlatform(WalletPlatform):
|
||||
identifier = "google"
|
||||
name = _("Google")
|
||||
|
||||
@classmethod
|
||||
def generate(cls, layout: PassLayout, op: OrderPosition):
|
||||
class_object = cls._generate_class(op.order.event)
|
||||
from ..views import get_layout_variables
|
||||
|
||||
# ticket_object = cls._get_object(op)
|
||||
order = op.order
|
||||
event = order.event
|
||||
|
||||
# if not ticket_object:
|
||||
# return False
|
||||
context = {
|
||||
"placeholders": get_layout_variables(event), # TODO: move to higher class
|
||||
"evaluation_context": [op, order, event],
|
||||
"credentials": event.settings.get("wallet_google_credentials").read(),
|
||||
"locale": event.settings.locale,
|
||||
"locales": event.settings.locales,
|
||||
"issuerName": event.organizer.name,
|
||||
"eventName": event.name,
|
||||
"classId": get_class_id(event),
|
||||
"objectId": get_object_id(op),
|
||||
"homepageUrl": eventreverse_absolute(event, "presale:event.index"),
|
||||
# TODO: add webhook view & register in pass
|
||||
"webhookUrl": "", # eventreverse_absolute(event.organizer,"plugins:wallet:google_webhook",))
|
||||
}
|
||||
|
||||
# generated_jwt = self._comms().sign_jwt(
|
||||
# ButtonJWT(
|
||||
# origins=[django_settings.SITE_URL],
|
||||
# issuer=self._comms().client_email,
|
||||
# event_ticket_objects=[ticket_object],
|
||||
# skinny=True
|
||||
# )
|
||||
# )
|
||||
data = layout.generate(context)
|
||||
return "pass", "text/plain", data
|
||||
|
||||
# if generated_jwt:
|
||||
# return 'googlepaypass', 'text/uri-list', 'https://pay.google.com/gp/v/save/%s' % generated_jwt
|
||||
# else:
|
||||
# return False
|
||||
|
||||
data = {"class": class_object}
|
||||
return 'pass.json', 'application/json', json.dumps(data)
|
||||
class GoogleWalletStyle(PassStyle):
|
||||
platform = GooglePlatform
|
||||
|
||||
@classmethod
|
||||
def _comms(cls, event: Event):
|
||||
return Comms()
|
||||
|
||||
def _generate_class(self, layout, context, fields):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _generate_object(self, layout, context, fields):
|
||||
raise NotImplementedError()
|
||||
|
||||
def generate(self, layout, context):
|
||||
comms = Comms(context["credentials"])
|
||||
fields = self.get_pass_fields(layout, context)
|
||||
|
||||
class_object = self._generate_class(layout, context, fields)
|
||||
ticket_object = self._generate_object(layout, context, fields)
|
||||
|
||||
generated_jwt = comms.sign_jwt(
|
||||
ButtonJWT(
|
||||
origins=[settings.SITE_URL],
|
||||
issuer=comms.client_email,
|
||||
event_ticket_classes=[class_object],
|
||||
event_ticket_objects=[ticket_object],
|
||||
skinny=False,
|
||||
)
|
||||
)
|
||||
|
||||
return "https://pay.google.com/gp/v/save/%s" % generated_jwt
|
||||
|
||||
# from ..views import get_layout_variables
|
||||
|
||||
# order = op.order
|
||||
@@ -120,27 +185,84 @@ class GooglePlatform(WalletPlatform):
|
||||
# data = layout.generate(context)
|
||||
# return filename, "application/vnd.apple.pkpass", data
|
||||
|
||||
@classmethod
|
||||
def _generate_class(cls, event: Event):
|
||||
class_name = get_class_id(event)
|
||||
|
||||
class GoogleWalletEventTicket(GoogleWalletStyle):
|
||||
identifier = "event"
|
||||
name = "Event Ticket"
|
||||
fieldgroups = [
|
||||
ImageFieldGroup(
|
||||
identifier="logo",
|
||||
name=_("Logo"),
|
||||
min_entries=0,
|
||||
max_entries=1,
|
||||
default_entries=[
|
||||
PlaceholderFieldEntry(
|
||||
content="poweredby",
|
||||
)
|
||||
],
|
||||
),
|
||||
PredefinedFieldGroup(identifier="seating", name=_("Seating")),
|
||||
TextFieldGroup(
|
||||
identifier="code",
|
||||
name=_("QR-Code"),
|
||||
max_entries=1,
|
||||
display=FieldGroupDisplay.CODE,
|
||||
default_entries=[
|
||||
PlaceholderFieldEntry(
|
||||
content="secret",
|
||||
)
|
||||
],
|
||||
),
|
||||
]
|
||||
preview_layout = [
|
||||
[
|
||||
{
|
||||
"children": [
|
||||
{"fieldgroup": "logo", "relSize": 1},
|
||||
{
|
||||
"value": "issuerName",
|
||||
"relSize": 3,
|
||||
"display": ["large", "centered"],
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
"children": [
|
||||
{"value": "venueName", "display": "small"},
|
||||
{"value": "eventName", "display": "large"},
|
||||
],
|
||||
"direction": "column",
|
||||
},
|
||||
{
|
||||
"children": [
|
||||
{"value": "01/01/1970", "label": "Date"},
|
||||
{"value": "12:34", "label": "Time"},
|
||||
]
|
||||
},
|
||||
{"fieldgroup": "seating"},
|
||||
{"fieldgroup": "code"},
|
||||
]
|
||||
]
|
||||
|
||||
def _generate_class(self, layout: PassLayout, context, fields):
|
||||
output_class = EventTicketClass(
|
||||
event.organizer.name,
|
||||
class_name,
|
||||
context["issuerName"],
|
||||
context["classId"],
|
||||
MultipleDevicesAndHoldersAllowedStatus.multipleHolders, # TODO: Make configurable
|
||||
event.name,
|
||||
ReviewStatus.draft, # TODO: ReviewStatus.underReview,
|
||||
event.settings.locale
|
||||
context["eventName"],
|
||||
ReviewStatus.underReview,
|
||||
context["locale"],
|
||||
)
|
||||
|
||||
output_class.homepage_uri(
|
||||
eventreverse_absolute(event, 'presale:event.index'),
|
||||
get_translated_string('Website', event.settings.locale),
|
||||
get_translated_dict('Website', event.settings.locales)
|
||||
context["homepageUrl"],
|
||||
get_translated_string("Website", context["locale"]),
|
||||
get_translated_dict("Website", context["locales"]),
|
||||
)
|
||||
# TODO: add webhook view & register in pass
|
||||
# output_class.callback_url(context['webhookUrl'])
|
||||
|
||||
# output_class.callback_url(eventreverse_absolute(event.organizer, 'plugins:pretix_googlepaypasses:webhook'))
|
||||
|
||||
# TODO: move to pass settings or set defaults
|
||||
# if (event.settings.get('ticketoutput_googlepaypasses_latitude')
|
||||
# and event.settings.get('ticketoutput_googlepaypasses_longitude')):
|
||||
# output_class.locations(
|
||||
@@ -153,9 +275,7 @@ class GooglePlatform(WalletPlatform):
|
||||
# event.geo_lon
|
||||
# )
|
||||
|
||||
output_class.country_code(event.settings.locale)
|
||||
|
||||
output_class.hide_barcode(False)
|
||||
# output_class.country_code(event.settings.locale)
|
||||
|
||||
# if event.settings.get('ticketoutput_googlepaypasses_hero'):
|
||||
# output_class.hero_image(
|
||||
@@ -205,17 +325,43 @@ class GooglePlatform(WalletPlatform):
|
||||
# return self._comms().put_item(ClassType.eventTicketClass, class_name, output_class)
|
||||
return output_class._eventTicketClass
|
||||
|
||||
def _generate_object(self, layout: PassLayout, context, fields):
|
||||
class_id = context["classId"]
|
||||
object_id = context["objectId"]
|
||||
output_object = EventTicketObject(
|
||||
object_id, class_id, ObjectState.active, context["locale"]
|
||||
)
|
||||
|
||||
class GoogleWalletStyle(PassStyle):
|
||||
platform = GooglePlatform
|
||||
# output_object.barcode(Barcode.qrCode, op.secret, op.secret)
|
||||
|
||||
# output_object.reservation_info("%s-%s" % (op.order.event.slug, op.order.code))
|
||||
# output_object.ticket_holder_name(op.attendee_name or (op.addon_to.attendee_name if op.addon_to else ''))
|
||||
# output_object.ticket_number(op.secret)
|
||||
# output_object.ticket_type(
|
||||
# get_translated_dict(
|
||||
# str(op.item) + (" – " + str(op.variation.value) if op.variation else ""),
|
||||
# op.order.event.settings.get('locales')
|
||||
# )
|
||||
# )
|
||||
|
||||
class GoogleWalletEventTicket(PassStyle):
|
||||
identifier = "event"
|
||||
name = "Event Ticket"
|
||||
platform = GooglePlatform
|
||||
fieldgroups = [
|
||||
PredefinedFieldGroup(identifier="seating", name=_("Seating")),
|
||||
TextFieldGroup(identifier="qrcode", name=_("QR-Code"), display=FieldGroupDisplay.PLAIN),
|
||||
]
|
||||
preview_layout = None
|
||||
# places = django_settings.CURRENCY_PLACES.get(op.order.event.currency, 2)
|
||||
# output_object.face_value(int(op.price * 1000 ** places), op.order.event.currency)
|
||||
|
||||
# if op.order.event.seating_plan_id is not None:
|
||||
# if op.seat:
|
||||
# output_object.seat(
|
||||
# get_translated_dict(
|
||||
# _(str(op.seat)),
|
||||
# op.order.event.settings.get('locales')
|
||||
# )
|
||||
# )
|
||||
# else:
|
||||
# output_object.seat(
|
||||
# get_translated_dict(
|
||||
# _('General admission'),
|
||||
# op.order.event.settings.get('locales')
|
||||
# )
|
||||
# )
|
||||
|
||||
# return self._comms().put_item(ObjectType.eventTicketObject, object_name, output_object)
|
||||
return output_object._eventTicketObject
|
||||
|
||||
@@ -91,6 +91,7 @@ class GoogleWalletTicketOutput(WalletOutput):
|
||||
forms.CharField(
|
||||
label=_("Google Wallet Issuer/Merchant ID"),
|
||||
help_text=_(
|
||||
# TODO: update text
|
||||
"After getting accepted by Google into the Google Pay API for Passes program, "
|
||||
"your Issuer ID can be found in the Merchant center at "
|
||||
"https://wallet.google.com/merchant/walletobjects/"
|
||||
@@ -108,6 +109,7 @@ class GoogleWalletTicketOutput(WalletOutput):
|
||||
"for Passes Issuer ID"
|
||||
),
|
||||
required=False,
|
||||
# TODO: add validator
|
||||
# validators=[validate_json_credentials]
|
||||
),
|
||||
),
|
||||
@@ -190,17 +192,4 @@ class AppleWalletTicketOutput(WalletOutput):
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
# settings_hierarkey.add_default("wallet_apple_certificate_file", None, File)
|
||||
# settings_hierarkey.add_default("wallet_apple_wwdr_certificate_file", None, File)
|
||||
# settings_hierarkey.add_default("ticketoutput_wallet_apple_background", None, File)
|
||||
# settings_hierarkey.add_default("ticketoutput_wallet_apple_background2x", None, File)
|
||||
# settings_hierarkey.add_default("ticketoutput_wallet_apple_background3x", None, File)
|
||||
# settings_hierarkey.add_default("ticketoutput_wallet_apple_icon", None, File)
|
||||
# settings_hierarkey.add_default("ticketoutput_wallet_apple_icon2x", None, File)
|
||||
# settings_hierarkey.add_default("ticketoutput_wallet_apple_icon3x", None, File)
|
||||
# settings_hierarkey.add_default("ticketoutput_wallet_apple_logo", None, File)
|
||||
# settings_hierarkey.add_default("ticketoutput_wallet_apple_logo2x", None, File)
|
||||
# settings_hierarkey.add_default("ticketoutput_wallet_apple_logo3x", None, File)
|
||||
|
||||
OUTPUTS = [WalletSettingsHolder, GoogleWalletTicketOutput, AppleWalletTicketOutput]
|
||||
|
||||
Reference in New Issue
Block a user