Event-Export

Um Events aus co*pilot exportieren zu können, wurde ein flexibler Event Export geschaffen. Export 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.

Export-Konfiguration

Beim Anlegen einer neuen Export-Konfiguration in den Einstellungen werden folgende Felder belegt:

(1) Name

Name der Konfiguration

(2) Format

  • Markdown
  • CSV

Markdown

Markdown ist eine sehr einfache Seitenbeschreibungssprache um Text zu formatieren. Dieses Format eignet sich sehr gut, um Detailseiten auszugeben.

Ein Markdown-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) Vorlage

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.

(4) Perspektive

Perspektive auswählen um Events für die Vorschau zu laden.

(5) Vorschau

Vorschau der Ausgabe

(4) Default Vorlagen

Hinterlegte Default Vorlagen laden.

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.

{
  events: Event[]
}

Event

export interface EventExportPayload {
  slug: string
  status: string
  optionEnd?: Date
  kind: string
  start: Date
  name: string
  subTitle?: string
  eventType: string
  memo?: string
  createdAt: Date
  updatedAt: Date
  displayNames: {
    eventTitleWithArtists: string
    eventTitleWithArtistsAndShows: string
    artists: string
    artistsAndShows: string
    rooms: string
    locationsWithRooms: string
    locationsWithCityAndRooms: string
  }
  images?: EventExportPayloadImage[]
  files?: EventExportPayloadFile[]
  links?: EventExportPayloadLink[]
  locations?: {
    name: string
    address: {
      street: string
      addStreet: string
      zip: string
      city: string
      country: string
      lat: string
      lng: string
    }
    operator?: {
      displayName: string
      email: string
      phone: string
    }
    rooms?: {
      name: string
      images?: EventExportPayloadImage[]
      files?: EventExportPayloadFile[]
    }[]
  }[]
  artists?: {
    name: string
    description: string
    show?: {
      slug: string
      name: string
      releasesAt?: Date
      memo?: string
      images?: ArtistExportPayloadImage[]
      files?: ArtistExportPayloadFile[]
      artistShowInformations?: (Information | undefined)[]
    }
    contacts?: {
      role: string
      displayName: string
      address: {
        street: string
        addStreet: string
        zip: string
        city: string
        country: string
        lat: string
        lng: string
      }
      email: string
      phone: string
    }[]
    images?: EventExportPayloadImage[]
    files?: EventExportPayloadFile[]
    links?: EventExportPayloadLink[]
    artistInformations?: (Information | undefined)[]
  }[]
  contacts?: {
    role: string
    displayName: string
    address: {
      street: string
      addStreet: string
      zip: string
      city: string
      country: string
      lat: string
      lng: string
    }
    email: string
    phone: string
  }[]
  schedule?: {
    name: string
    date: Date
  }[]
  eventInformations?: (Information | undefined)[]
  offersOnEvent?: {
    offerStatus: string
    name: string
    description: string
    discount: number
    roomsOnOffer?: {
      room: string
      description: string
      price: number
      discount: number
      vat: number
      sum: number
    }[]
    resourcesOnOffer?: {
      resource: string
      description: string
      amount: number
      unit: string
      price: number
      discount: number
      vat: number
      sum: number
    }[]
  }[]
  ticketing?: {
    ticketOffice: string
    contingent: number
    price: number
    timestamp: Date
    soldTickets: number
    saleTotal: number
  }[]
}

export type EventExportPayloadImage = {
  name: string
  description: string
  tags: string[]
  sizes: Record<string, string>
}

export type EventExportPayloadFile = {
  name: string
  description: string
  path: string
  preview: string
  download: string
  tags: 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}}
# {{{this.name}}}
Datum: {{formatDate this.start "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}}
### {{ this.name }}
{{ 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:

Beispiel
{{ formatDate this.start "P" }}
  => Ausgabe: deutsches Datum, z.B. 03.08.2022

{{ formatDate this.start "E P" }}
  => Ausgabe: deutsches Datum mit Wochentag,
     z.B. Mi. 03.08.2022

{{ formatDate this.start "p" }}
  => Ausgabe: Uhrzeit, z.B. 20:00

{{ formatDate this.start "Pp" }}
  => 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 verlangt 2 Parameter:

  • Den Schedule
  • Den Namen des Schedule-Eintrags
Beispiel
{{ scheduleValueByName this.schedule "Curfew" }}
  => Ausgabe
  22:00

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" }}

Beispiele

Einfaches Markdown Beispiel

{{#each events}}

# {{this.name}}
Type: {{this.eventType}}  
Status: {{this.status}}  
Datum: {{ formatDate this.start "P" }} | {{ formatDate this.start "p" }} Uhr  
Name: {{this.displayNames.eventTitleWithArtistsAndShows}}  
Ort: {{this.displayNames.locationsWithRooms}}

{{/each}}

Einfaches CSV Beispiel

Status;Datum;Titel
{{#each events}}
{{this.status}};{{formatDate this.start "P"}};{{{this.name}}}
{{/each }}

VVK-Zahlen

# Verkäufe
Event:  {{this.name}} | {{ formatDate this.start "P" }}  
Location: {{this.displayNames.locationsWithRooms}}

{{#if this.ticketing}}
## Tickets

<table>
    <thead>
        <tr>
            <th>VVK-Stelle</th>
            <th>Kategory</th>
            <th>Ticketpreis (brutto)</th>
            <th>Kontingent</th>
            <th>Anzahl</th>
            <th>Gesamt</th>
        </tr>
    </thead>
    <tbody>
      {{#each this.ticketing}}
        <tr>
            <td>{{ this.ticketOffice }}</td>
            <td>{{ this.category }}</td>
            <td>{{ formatEuro this.price }}</td>
            <td>{{ this.contingent }}</td>
            <td>{{ this.soldTickets }}</td>
            <td>{{ formatEuro this.saleTotal }}</td> 
        </tr>
        {{/each}}
<tr>
            <th>Summe</th>
            <th></th>
            <th></th>
            <th>{{ sumBy this.ticketing "contingent" }}</th>
            <th>{{ sumBy this.ticketing "soldTickets" }}</th>
            <th>{{ formatEuro (sumBy this.ticketing "saleTotal" ) }}</th>
        </tr>
    </tbody>
</table>

{{/if}}

Event-Informationen

Alle Event-Informationen außer „Gästeliste“ auflisten.

## Event Informationen
{{#each this.eventInformations}}
{{#unless (isEqual name "Gästeliste")}}
 
### {{this.name}}
{{this.value}}
{{/unless}}
{{/each}} 

Artist-Tabelle mit Bilder

## Artists

<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

## Dateien

{{#each this.files}}

### {{this.name}}
<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")}}
### Hotel
{{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>

# Globale Stile

Ein Absatz

- eine
- Liste

## Tabelle
| Spalte A | Spalte B | Spalte C |
| -------- | -------- | -------- |
| A1       | B1       | B3       |
| A2       | B        | B4       |

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>