Um Events aus co*pilot exportieren zu können, wurde ein flexibler Event-Export geschaffen. Hiermit lassen sich sowohl Dokumente wie z.B. Production Sheets auf Basis einzelner Events wie auch Auswertungen über mehrere Events hinweg generieren. Exporte werden auf Basis von Export-Konfigurationen durchgeführt. In einer solchen Export-Konfiguration wird festgelegt, welche Daten eines Events in welchem Format ausgespielt werden.
Über den Unterpunkt „Exporte“ des Event-Menus können im Anschluss Events selektiert und exportiert werden. Zudem lassen sich einzelne Events auch über die Event-Detail-Seite exportieren.
Wir haben einige Beispiel-Exporte ausgearbeitet, die du als Grundlage für deine Anforderungen verwenden kannst. Komplexere Anpassungen oder komplett neuartige Exporte erfordern grundlegende Kenntnisse in Markdown/CSS und ggfs. JavaScript. Gerne können wir das für euch im Auftrag erledigen.
Export-Konfiguration
Beim Anlegen einer neuen Export-Konfiguration in den Einstellungen werden folgende Felder belegt:
(1) Name
Name der Konfiguration
(2) Format
- HTML
- CSV
HTML
HTML ist eine Seitenbeschreibungssprache um Inhalte zu formatieren. Dieses Format eignet sich sehr gut, um Detailseiten auszugeben.
Ein HTML-Export kann als Word oder PDF File ausgegeben werden.
CSV
CSV ist ein gängiges Format um Informationen tabellarisch darzustellen. Hierbei werden Spalten mittels Komma oder Semikolon separiert.
- https://de.wikipedia.org/wiki/CSV_(Dateiformat)
(3) Default Seitenlayout
Das Seitenlayout ost für die Darstellung der Exporte nötig. Für Daten,, wie z.B. größere Tabellen, die nur angezeigt werden sollen, bietet sich das „freie“ Format an.
- A4 Hochformat
- A4 Querformat
- frei
(4) Beispiel Template laden
Hinterlegte Vorlagen laden.
(5) Preprocessing Script (Fortgeschritten)
Hier können die Input-Daten via JavaScript transformiert werden. Der Rückgabewert dieses Scripts ersetzt die eigentlichen Input-Daten des Exports. Es ist nur der Funktions-Rumpf anzugeben, wobei die Input-Daten als ctx
zur Verfügung stehen.
Hier ein Beispiel:
return { ...ctx,
// Folgende Zeile ersetzt
// die ursprünglichen Events
events: ctx.events.map(e => e.start),
foo: "bar"
}
(6) Template
Die Vorlage wird in der Templating Language Handlebars verfasst. Auf Basis dieser Vorlage und den Input-Daten wird die Ausgabe generiert. Daten werden mittels Platzhalter (= „Handlebars Expressions“) übergeben, die in „{{ }}“ eingeschlossen sind.
(7) Vertraulich
Wird ein Export als „vertraulich“ deklariert, werden zudem vertrauliche Daten (wie z.B. vertrauliche Benutzerfelder, Deals und Angebote) im Export verfügbar.
Vertrauliche Exporte können nur von Benutzer:innen mit der Berechtigung „ACCESS_CONFIDENTIAL“ oder „ADMIN“ erzeugt werden.
(8) Perspektive
Perspektive auswählen um Events für die Vorschau zu laden.
(9) Event suchen
Bestimmten Event anhand des Namens suchen, um diesen für die Vorschau zu laden.
(10) Vorschau
Vorschau der Ausgabe
(11) Code
Erzeugten Code anzeigen
(12) Input-Daten
Geladene Beispiel-Daten anzeigen
Beispiel-Exporte
https://support.ov2b.de/docs-category/exporte/
Input-Daten
Aktuell steht die Liste an Events in der Vorlage zur Verfügung. Das können die selektierten Events auf der Export-Seite sein, alle Events, die eine Perspektive zurückliefert oder auch nur ein einzelnes Event, wenn ein Export von einer Event-Detail-Seite aus gestartet wird.
{
baseData: BaseDataPayload,
events: EventExportPayload[]
}
BaseData (Stammdaten)
BaseDataPayload {
name: string
additionalName: string
department: string
memo: string
addresses: EventExportPayloadAdress[]
links: EventExportPayloadLink[]
email: string
phone: string
web: string
images: ExportPayloadImage[]
}
Event
EventExportPayload {
copilotUrl: string
id: string
slug: string
status: string
optionEnd?: Date
kind: string
start: Date
name: string
subTitle?: string
eventType: string
memo?: string
createdAt: Date
updatedAt: Date
displayNames: {
title: string
eventTitleWithArtists: string
eventTitleWithArtistsAndShows: string
artists: string
artistsAndShows: string
rooms: string
locationsWithRooms: string
locationsWithCityAndRooms: string
locationsWithAddressAndRooms: string
}
activePromotions: { name: string }[]
images?: ExportPayloadImage[]
files?: ExportPayloadFile[]
links?: EventExportPayloadLink[]
locations?: {
name: string
address: EventExportPayloadAdress
operator?: {
displayName: string
email: string
phone: string
}
contacts?: {
role: string
displayName: string
firstName?: string
lastName?: string
email: string
phone: string
}[]
images: ExportPayloadImage[]
files: ExportPayloadFile[]
rooms?: {
name: string
images?: ExportPayloadImage[]
files?: ExportPayloadFile[]
}[]
}[]
artists?: {
name: string
description: string
deals?: {
name: string
description: string
guarantee: number
artistPercentage: number
breakEvenSales: number
}[]
show?: {
slug: string
name: string
releasesAt?: Date
memo?: string
images?: ExportPayloadImage[]
files?: ExportPayloadFile[]
artistShowInformations?: PublicCustomField[]
}
contacts?: {
role: string
displayName: string
firstName?: string
lastName?: string
address: EventExportPayloadAdress
email: string
phone: string
contactInformations?: PublicCustomField[]
bankAccounts?: EventExportPayloadBankAccount[]
}[]
images: ExportPayloadImage[]
files: ExportPayloadFile[]
links?: EventExportPayloadLink[]
artistInformations?: PublicCustomField[]
}[]
contacts?: {
role: string
displayName: string
firstName?: string
lastName?: string
address: EventExportPayloadAdress
email: string
phone: string
contactInformations?: PublicCustomField[]
images?: ExportPayloadImage[]
files?: ExportPayloadFile[]
}[]
schedule?: {
name: string
date: Date
}[]
eventInformations?: PublicCustomField[]
offersOnEvent?: {
offerStatus: string
name: string
description: string
discount: number
netTotal: number
grossTotal: number
netTotalByVat: Record<number, number>
roomsOnOffer?: {
room: string
description: string
price: number
discount: number
vat: number
netTotal: number
grossTotal: number
commodityGroup?:{
name: string
vatBusiness: number
vatPrivate: number
}
}[]
resourcesOnOffer?: {
resource: string
description: string
amount: number
unit: string
price: number
discount: number
vat: number
netTotal: number
grossTotal: number
categories?: string[]
commodityGroup?:{
name: string
vatBusiness: number
vatPrivate: number
}
}[]
ticketing?: {
ticketOffice: string
category: string
contingent: number
vat: number
netPrice: number
grossPrice: number
timestamp: Date
soldTickets: number
saleTotal: number
}[]
shopEvent?: {
start: Date
name: string
subTitle?: string
description?: string
location?: string
image?: ExportPayloadImage
url?: string
}
}
export type EventExportPayloadBankAccount = {
bankAccountType: string
institute: string | null
username: string | null
owner: string | null
iban: string | null
bic: string | null
}
export type EventExportPayloadAdress = {
street: string
addStreet: string
zip: string
city: string
country: string
lat: string
lng: string
}
export type EventExportPayloadLink = {
type: string
value: string
}
Helper-Funktionen
Standard
Folgend ein Auszug der zur Verfügung stehenden Standar-Helper. Siehe https://handlebarsjs.com/guide/builtin-helpers.html für weitere und Details.
each
Die each Funktion iteriert (Schleife) über ein angegebenes Array. Sie beginnt immer mit {{#each}} und endet mit {{/each}}
Sie verlangt das Array als Parameter.
Beispiel
Eine Schleife über alle events. Die Daten eines Events müssen dann mit this.* angesprochen werden
{{#each events}}
<h1>{{{this.name}}}</h1>
<p>Datum: {{formatDate this.start "d.m.Y"}}</p>
{{/each }}
if
Die if Funktion überprüft, ob ein Element vorhanden ist. Sie beginnt immer mit {{#if}} und endet mit {{/if}}
Sie verlangt das zu prüfende Element als Parameter.
Beispiel
Alle Event Informationen ausgeben, sofern ein Wert gesetzt ist:
{{#each this.eventInformations}}
{{#if this.value}}
<p>{{ this.name }}</p>
{{ this.value }}
{{/if}}
{{/each}}
lookup
Funktion, um Elemente aus einem Objekt zu extrahieren.
Die Funktion verlangt 2 Parameter:
- Ein Objekt, z.B. einen Kontakt
- den Namen des Elements
Beispiel
{{ lookup (contactByRole this.contacts "Mieter") "displayName" }}
Custom
formatDate
Funktion um Datum und Uhrzeit spezifisch auszugeben.
Die Funktion verlangt 2 Parameter:
- das Datum (Date ISO)
- das Datumsformat (Die Optionen sind hier gelistet)
Beispiel
{{ formatDate this.start "d.m.Y" }}
=> Ausgabe: deutsches Datum, z.B. 03.08.2022
{{ formatDate this.start "D d.m.Y" }}
=> Ausgabe: deutsches Datum mit Wochentag,
z.B. Mi. 03.08.2022
{{ formatDate this.start "H:i" }}
=> Ausgabe: Uhrzeit, z.B. 20:00
{{ formatDate this.start "d.m.Y H:i" }}
=> Ausgabe: Datum mit Uhrzeit, z.B. 20.11.2021 20:00
contactByRole
Funktion, um einen Kontakt aus einem Array anhand seiner Rolle zu extrahieren.
Die Funktion verlangt 2 Parameter:
- Ein Array mit Kontakten
- Den Namen der Rolle
Beispiel
{{#each (contactByRole this.contacts "Veranstalter:in")}}
{{@key}}: {{this}}
{{/each}}
=> Ausgabe
role: Veranstalter:in
displayName: ABC Firma
email: info@abc.de
phone: +030 8877665
{{ lookup (contactByRole this.contacts "Veranstalter:in") "displayName" }}
=> Ausgabe: ABC Firma
scheduleValueByName
Funktion, um einen Schedule-Eintrag anhand des Namens zu extrahieren.
Die Funktion hat 3 Parameter:
- Den Schedule
- Den Namen des Schedule-Eintrags
- Datum einblenden (optional): default true, auf false setzen um nur Uhrzeit anzuzeigen
Beispiel
{{ scheduleValueByName this.schedule "Curfew" }}
=> Ausgabe
20.09.2023 22:00
{{ scheduleValueByName this.schedule "Curfew" false }}
=> Ausgabe
22:00
linkByType
Funktion, um einen Eintrag der Links anhand des Typs zu extrahieren.
Die Funktion verlangt 2 Parameter:
- Die Links
- Den Typ des Eintrags (z.B. Web, Facebook)
{{ linkByType @root.baseData.links "Web" }}
eventInformationByName
Funktion, um einen Eintrag der Event Informationen anhand des Namens zu extrahieren.
Die Funktion verlangt 2 Parameter:
- Die Event Informationen
- Den Namen des Eintrags
{{ eventInformationByName this.eventInformations "Hotel" }}
md2html
Konvertiert Markdown to HTML
{{md2html memo}}
csvQuote
Tauchen in CSV Exporten Spalten mit Anführungszeichen auf, müssen diese Spalten mit dem Helper `csvQuote` escaped werden: z.B.
{{ start }};{{ csvQuote name }}
currentDate
Aktuellles Datum
Die Funktion verlangt 1 Parameter:
- das Datumsformat im Unicode Technical Standard
https://date-fns.org/v2.9.0/docs/format
{{ currentDate "P" }}
Beispiele
Einfaches Markdown Beispiel
{{#each events}}
<h1>{{this.name}}</h1>
<p>Type: {{this.eventType}}</p>
<p>Status: {{this.status}}</p>
<p>Datum: {{ formatDate this.start "P" }} | {{ formatDate this.start "p" }} Uhr </p>
<p>Name: {{this.displayNames.eventTitleWithArtistsAndShows}} </p>
<p>Ort: {{this.displayNames.locationsWithRooms}}</p>
{{/each}}
Einfaches CSV Beispiel
Status;Datum;Titel
{{#each events}}
{{this.status}};{{formatDate this.start "P"}};{{{this.name}}}
{{/each }}
VVK-Zahlen
<h1>Verkäufe</h1>
<p>Event: {{this.name}} | {{ formatDate this.start "P" }}</p>
<p>Location: {{this.displayNames.locationsWithRooms}}</p>
{{#if this.ticketing}}
<h2>Tickets</h2>
<table>
<thead>
<tr>
<th>VVK-Stelle</th>
<th>Kategory</th>
<th>Ticketpreis (brutto)</th>
<th>Verkauft</th>
<th>Kontingent</th>
<th>Gesamt (brutto)</th>
</tr>
</thead>
<tbody>
{{#each this.ticketing}}
<tr>
<td>{{ this.ticketOffice }}</td>
<td>{{ this.category }}</td>
<td>{{ formatEuro this.grossPrice }}</td>
<td>{{ this.soldTickets }}</td>
<td>{{ this.contingent }}</td>
<td>{{ formatEuro this.saleTotal }}</td>
</tr>
{{/each}}
<tr>
<th>Summe</th>
<th></th>
<th></th>
<th>{{ sumBy this.ticketing "soldTickets" }}</th>
<th>{{ sumBy this.ticketing "contingent" }}</th>
<th>{{ formatEuro (sumBy this.ticketing "saleTotal" ) }}</th>
</tr>
</tbody>
</table>
{{/if}}
Event-Informationen
Alle Event-Informationen außer „Gästeliste“ auflisten.
<h2>Event Informationen</h2>
{{#each this.eventInformations}}
{{#unless (isEqual name "Gästeliste")}}
<h3>{{this.name}}</h3>
{{this.value}}
{{/unless}}
{{/each}}
Artist-Tabelle mit Bilder
<h2>Artists</h2>
<table class="artistTable">
<thead>
<tr>
<th>Pic</th>
<th>Name</th>
</tr>
</thead>
<tbody>
{{#each this.artists}}
<tr>
<td><img src="{{ lookup this.images.0.sizes "640" }}" /></td>
<td>
<h3>{{ this.name }}</h3>
<p>{{ this.description }}</p>
</td>
</tr>
{{/each}}
</tbody>
</table>
Dateien verlinken
<h2>Dateien</h2>
{{#each this.files}}
<h3>{{this.name}}</h3>
<a href="{{this.path}}">{{this.path}}</a>
{{/each}}
Anmerkung: Nur als „öffentlich“ gekennzeichnete Dateien können im Export eingebunden werden. „Öffentlich“ bedeutet hierbei lediglich, dass eine Datei ohne Login verfügbar wird. Ohne die URL bzw. konkreter die zufallsgenerierte ID besteht aber trotzdem keine Zugriffsmöglichkeit. D.h. es können durchaus Dateien wie Tech Rider auf öffentlich gesetzt und somit in einen Export eingebunden werden.
Tipps
Bedingte Darstellung
Um eine Sektion nur anzuzeigen, wenn das entsprechende Feld gesetzt ist, kann sie mit einem #if Block-Helper umschlossen werden:
{{#if (eventInformationByName this.eventInformations "Hotel")}}
<h3>Hotel</h3>
{{eventInformationByName this.eventInformations "Hotel"}}
{{/if}}
Seitenumbruch
Für PDF-Exporte können Seitenumbrüche eingefügt werden. Bei Word-Exporten hat das allerdings keinen Effekt.
Inhalt vor dem Seitenumbruch
{{pagebreak}}
Inhalt nach dem Seitenumbruch
Die Leerzeile vor {{pagebreak}}
ist notwendig.
Styling
Styling von Exporten ist via CSS möglich. Globale Stile können ganz am Anfang einer Exportvorlage in einem Style-Tag angegeben werden:
<style>
...
</style>
Alternativ sind auch Inline-Stile auf z.B. einzelnen Absätzen oder Paragraphen anwendbar. Hierfür muss die entsprechende Passage dann allerdings in HTML statt Markdown geschrieben werden:
<p style="...">...</p>
Schriften
Folgende Schriftarten stehen zur Verfügung:
Beispiel: Überschriften mit Serifen, Absätze serifenlos
<style>
h1, h2, h3, h4 {
font-family: DM Serif Display;
}
body, p, th, td {
font-family: Ubuntu;
}
</style>
<h1>Globale Stile</h1>
<p>Ein Absatz</p>
<ul>
<li>eine</li>
<li>Liste</li>
</ul>
<h2>Tabelle</h2>
<table>
<thead>
<tr>
<th>Spalte A</th>
<th>Spalte B</th>
<th>Spalte C</th>
</tr>
</thead>
<tbody>
<tr>
<td>A1</td>
<td>B1</td>
<td>C1</td>
</tr>
<tr>
<td>A2</td>
<td>B2</td>
<td>C2</td>
</tr>
</tbody>
</table>
Beispiel: Einzelner Absatz in anderer Schriftart
Erster Absatz
<p style="font-family: Indie Flower">Zweiter Absatz</p>
Weitere Möglichkeiten
<p style="color: blue">blau</p>
<p style="color: blue; font-weight: bold;">blau & fettgedruckt</p>
<mark>highlighted</mark>
<p style="text-decoration: underline;">unterstrichen</p>