Zum Inhalt

Planungstafel

Die Planungstafel stellt Zeilen und Zeit gegenüber: links Mitarbeiter, Räume, Maschinen oder Projekte, oben eine Zeitachse, dazwischen Einträge als Balken, Punkte oder Zellen. Sie zeigt, wer wann da ist, was wann belegt ist und wo eine Mindestbesetzung reißt. Alle Daten kommen aus SQL-Abfragen, alle Reaktionen auf Klicks sind konfigurierte Aktionen.


Typische Einsatzbereiche

Einsatz Zeilen Einträge
Abwesenheitsplaner Mitarbeiter nach Team Urlaub, Krankheit, Fortbildung, Homeoffice
Teilzeit- und Schichtplan Mitarbeiter Schichten, freie Tage
Raum-, Fahrzeug-, Maschinenbelegung Räume, Fahrzeuge, Maschinen Buchungen, Wartungsfenster
Projekt- und Phasenplan Projekte Phasen, Meilensteine
Prüffristen Anlagen, Verträge Fälligkeiten als Punkte

Erste Schritte

Die Tafel braucht mindestens eine Ebene: eine SQL-Abfrage, die je Balken eine Zeile liefert, mit Spalten für die Zeile (wer oder was), den Start und das Ende. Die Zeilen der Tafel kommen entweder aus einer eigenen Abfrage oder werden aus den Einträgen abgeleitet. Danach sagst du im Dialog nur noch, welche Spalte was ist.

Schnellster Weg mit der App „Urlaubsantrag“ (aus dem Marketplace):

  1. Widget „Planungstafel“ in ein Dashboard ziehen und Konfigurieren klicken.
  2. Reiter Zeilen: Herkunft „Aus den Einträgen ableiten“ wählen.
  3. Reiter Ebenen: Ebene hinzufügen, dann Beispiel einsetzen → Urlaubsanträge aus der App „Urlaubsantrag“. Abfrage, Einstellungen der Ebene, Spaltenzuordnung und passende Stilregeln sind damit gesetzt.
  4. Testlauf klicken, Übernehmen, Dashboard speichern.

Mit eigenen Stammdaten: Reiter Zeilen, Musterschema „Mitarbeiter“ anlegen. Reiter Ebenen, Musterschema „Abwesenheiten“ anlegen. Beide Dialoge tragen nach dem Anlegen gleich die passende Abfrage und Zuordnung ein. Danach im Data Lake Mitarbeiter und Abwesenheiten erfassen. Die Felder der Musterschemas stehen unter Musterschemas.

Jeder Reiter des Dialogs hat einen Info-Button, der den passenden Abschnitt dieser Seite öffnet.


Bausteine

  • Zeilen: eine SQL-Abfrage mit Id, Anzeigename, optional Untertitel, Gruppe, Untergruppe, Kapazität und Arbeitstagen. Zeilen erscheinen auch ohne Einträge.
  • Ebenen: je Ebene eine Abfrage der Einträge. Jede Ebene legt fest, ob sie Zeitspannen oder Zeitpunkte enthält, ob Datum oder Zeitstempel, ob die Ende-Spalte den letzten Tag meint, und was ein leeres Ende bedeutet. Fehlt eine Angabe, zeigt die Tafel den Fehler statt eines geratenen Bildes.
  • Verfügbarkeit: Arbeitstage je Zeile (Spalte wie 1,2,3,4,5), Feiertage je Bundesland, optional eine Abfrage für Sperr- und Sonderzeiten.
  • Stilregeln: Feld plus Wert ergibt Farbe, Muster (voll, schraffiert, gestrichelt, gepunktet, gestreift, Rahmen), Kürzel für den Zellmodus oder Ausblenden. Beispiel: Status „Beantragt“ schraffiert, „Abgelehnt“ ausgeblendet.
  • Gruppen: Rahmen um Zeilen mit „anwesend/gesamt“ je Tag oder als Heatmap.
  • Ergebnisspalten: Werte aus der Zeilen-Abfrage rechts neben der Tafel, zum Beispiel genommener Urlaub, Resturlaub als Fortschrittsbalken, Status als Badge. Summen rechnet die Datenbank, die Tafel zeigt sie an.
  • Regeln: Mindestbesetzung je Gruppe (Personen, Prozent oder Vollzeitäquivalente), Überschneidungen, abwesende Vertretungen. Jeder Hinweis hat einen Schweregrad und einen Satz.
  • Markierungen: Daten und Zeiträume ohne Zeile, etwa Messe, Release oder Betriebsferien.
  • Aktionen: Klick, Rechtsklick, Auswahl von Zellen, Verschieben oder Schaltfläche führen zu Datensatz öffnen, Prozess starten, Feld setzen, Kanal veröffentlichen oder Adresse öffnen.

Konfiguration

Der Dialog hat acht Reiter. Bei den Abfragen gilt überall: Testlauf führt die Abfrage mit fünf Zeilen aus und zeigt die gefundenen Spalten, danach bieten die Zuordnungsfelder diese Spalten zur Auswahl an. Die Platzhalter funktionieren wie in allen SQL-Widgets.

Zeilen

Herkunft der Zeilen: SQL-Abfrage (eine Zeile je Mitarbeiter, Raum, Maschine) oder aus den Einträgen ableiten (jeder Zeilen-Schlüssel der Ebenen wird eine Zeile, ohne Gruppen und Kapazität).

Spalten der Zeilen-Abfrage:

Zuordnung Pflicht Bedeutung
id ja Zeilen-Schlüssel. Die Ebenen verweisen mit ihrer Spalte „Zeile“ auf genau diesen Wert, zum Beispiel die E-Mail des Benutzers.
label ja Anzeigename
sublabel Untertitel, etwa Rolle oder E-Mail
groupId, groupLabel Gruppe (Team, Abteilung, Gebäude)
group2Id, group2Label Untergruppe
sort Sortierung innerhalb der Gruppe
capacity Stellenanteil 0 bis 1 für Anwesenheit in Vollzeitäquivalenten
workdays Arbeitstage als Kommaliste, 1 = Montag … 7 = Sonntag; andere Tage werden grau

Weitere Spalten der Abfrage stehen als Ergebnisspalten zur Verfügung.

Beispiel einsetzen bietet zwei Abfragen. Antragsteller aus der App „Urlaubsantrag“:

SELECT DISTINCT app_beantragt_von AS id,
       app_beantragt_von AS label
FROM app_vacation_requests
WHERE app_beantragt_von IS NOT NULL AND app_beantragt_von <> ''
ORDER BY 1

Mitarbeiter aus dem Musterschema (Tabelle mitarbeiter):

SELECT COALESCE(email, id) AS id,
       name AS label,
       email AS sublabel,
       team AS group_id,
       team AS group_label,
       arbeitstage AS workdays,
       fte AS capacity
FROM mitarbeiter
WHERE COALESCE(aktiv, true) = true
ORDER BY team, name

Zuordnung: id → id, label → label, sublabel → sublabel, groupId → group_id, groupLabel → group_label, workdays → workdays, capacity → capacity.

Verfügbarkeit im selben Reiter: Feiertage je Bundesland per Auswahl, dazu eine optionale Abfrage für Sperr- und Sonderzeiten mit den Spalten row (leer = alle Zeilen), start, end (letzter Tag), state (unavailable, partial, available), capacity (0 bis 1 bei partial) und label. Beispiel Betriebsferien für alle Zeilen:

SELECT CAST(NULL AS varchar) AS row_key,
       CAST(concat(CAST(year(current_date) AS varchar), '-12-24') AS date) AS start_day,
       CAST(concat(CAST(year(current_date) AS varchar), '-12-31') AS date) AS end_day,
       'unavailable' AS state,
       'Betriebsferien' AS label

Ebenen

Jede Ebene hat vier Pflichtangaben, die nichts erraten lassen:

Einstellung Werte Bedeutung
Art Zeitspanne, Zeitpunkt Balken mit Start und Ende oder ein Punkt
Zeitmodus Datum, Zeitstempel YYYY-MM-DD oder Zeitstempel mit Uhrzeit
Ende inklusiv an, aus Bei Datum: die Ende-Spalte nennt den letzten Tag (an) oder den Tag danach (aus)
Leeres Ende Fehler, bis jetzt, bis zum Rand Was gilt, wenn die Ende-Spalte leer ist

Dazu die Farbe (Kategorie aus der Palette, feste Farbe der Ebene oder nur Stilregeln), die Kapazitätswirkung (1 = der Eintrag macht die Zeile abwesend, 0 = keine Wirkung, etwa Arbeitszeit) und die Einheit der Menge.

Spalten der Ebenen-Abfrage:

Zuordnung Pflicht Bedeutung
row ja Zeilen-Schlüssel, muss zum id der Zeilen passen
start ja Datum oder Zeitstempel
end bei Zeitspannen Datum oder Zeitstempel; bei „Ende inklusiv“ der letzte Tag
dayPart am, pm oder full für Halbtage (nur Datum)
quantity Menge in der Einheit der Ebene, etwa angerechnete Tage oder Stunden
category Kategorie für Farbe und Legende
status Status für Stilregeln, Sperren und Bedingungen
label Text auf dem Balken
linkRow Zeilen-Schlüssel der Vertretung; die Regel „Vertretung prüfen“ warnt, wenn sie selbst abwesend ist
id, dataSchemaId für Aktionen Datensatz-Id und Datenschema-Id, damit „Datensatz öffnen“, „Feld setzen“ und Verschieben funktionieren
updatedAt Änderungszeitpunkt für den Abgleich nach Schreibvorgängen

Zeitstempel kommen als ISO-Text mit Zeitzone an (2026-10-09T08:00:00+02:00) oder als Athena-Zeitstempel, der als UTC gelesen wird.

Beispiel einsetzen bietet drei Abfragen. Urlaubsanträge aus der App „Urlaubsantrag“ (Zeitspanne, Datum, Ende inklusiv):

SELECT id,
       data_schema_id,
       updated_at,
       app_beantragt_von AS row_key,
       app_erster_tag AS start_day,
       COALESCE(app_letzter_tag, app_erster_tag) AS end_day,
       CASE WHEN app_erster_tag = COALESCE(app_letzter_tag, app_erster_tag)
             AND app_erster_tag_vollhalb = 'Halb' THEN 'am' ELSE 'full' END AS day_part,
       app_urlaubskategorie AS category,
       CASE app_freigabe WHEN 'Genehmigen' THEN 'Genehmigt'
                         WHEN 'Ablehnen' THEN 'Abgelehnt'
                         ELSE 'Beantragt' END AS status,
       app_anmerkung AS label
FROM app_vacation_requests
WHERE app_beantragt_von IS NOT NULL
  AND app_erster_tag < CAST(@periodEnd AS date)
  AND COALESCE(app_letzter_tag, app_erster_tag) >= CAST(@periodStart AS date)

Zuordnung: row → row_key, start → start_day, end → end_day, dayPart → day_part, category, status, label, id, dataSchemaId → data_schema_id, updatedAt → updated_at. Das Beispiel setzt Stilregeln für die Kategorien sowie „Beantragt“ schraffiert und „Abgelehnt“ ausgeblendet, falls noch keine Stilregeln vorhanden sind.

Abwesenheiten aus dem Musterschema (Tabellen abwesenheiten und mitarbeiter; die Referenzfelder enthalten die Id des Mitarbeiter-Datensatzes):

SELECT a.id,
       a.data_schema_id,
       a.updated_at,
       COALESCE(m.email, m.id) AS row_key,
       a.erster_tag AS start_day,
       a.letzter_tag AS end_day,
       CASE WHEN a.erster_tag = a.letzter_tag AND a.erster_tag_vollhalb = 'Halb' THEN 'am' ELSE 'full' END AS day_part,
       a.kategorie AS category,
       a.status AS status,
       a.tage AS quantity,
       a.bemerkung AS label,
       COALESCE(v.email, v.id) AS link_row
FROM abwesenheiten a
LEFT JOIN mitarbeiter m ON m.id = a.mitarbeiter
LEFT JOIN mitarbeiter v ON v.id = a.vertretung
WHERE a.erster_tag < CAST(@periodEnd AS date)
  AND a.letzter_tag >= CAST(@periodStart AS date)

Zeiteinträge aus der App „Zeiterfassung“ (Zeitspanne, Zeitstempel, Kapazitätswirkung 0, Einheit Stunden). Datum und Uhrzeit werden zu einem Zeitstempel in Europe/Berlin zusammengesetzt:

SELECT id,
       data_schema_id,
       updated_at,
       app_mitarbeiter AS row_key,
       to_iso8601(with_timezone(date_parse(concat(CAST(app_datum AS varchar), ' ', app_arbeitsbeginn), '%Y-%m-%d %H:%i'), 'Europe/Berlin')) AS start_at,
       to_iso8601(with_timezone(date_parse(concat(CAST(app_datum AS varchar), ' ', app_arbeitsende), '%Y-%m-%d %H:%i'), 'Europe/Berlin')) AS end_at,
       app_kategorie AS category,
       app_arbeitsstunden AS quantity,
       app_bemerkung AS label
FROM app_time_entries
WHERE app_datum < CAST(@periodEnd AS date)
  AND app_datum >= CAST(@periodStart AS date)

Der Zeitraumfilter der Tafel lädt nur den sichtbaren Ausschnitt, deshalb gehört die Bedingung mit @periodStart und @periodEnd in jede Ebenen-Abfrage.

Darstellung

Balken oder Zellen (Zellmodus zeigt im Tagesmaßstab je Tag ein Kürzel), Dichte, Theme (hell, weich, Mitternacht, Kontrast, Pantarey oder automatisch nach Systemeinstellung), Legende, erlaubte Maßstäbe und Standard, Kalenderwochen, Jetzt-Linie, Minimap, Gesamtzeile mit Köpfen oder Vollzeitäquivalenten, Zebrastreifen, Suchfeld, Kontextmenü, Unterzeilen je Zeile, Breite der Namensspalte, Zeitraumfilter mit angebotenen Zeiträumen, Bearbeiten per Maus (Verschieben, Verlängern, Einrasten, gesperrte Status).

Gruppen und Regeln

Gruppierung nach der Gruppe aus der Zeilen-Abfrage mit Gruppenzeile je Tag (anwesend/gesamt oder Heatmap) und Reihenfolge. Arbeitstage der Tafel. Regeln mit Schweregrad Info, Warnung oder Blockierend: Mindestbesetzung je Gruppe oder für die ganze Tafel in Personen, Prozent oder Vollzeitäquivalenten; Überschneidungen innerhalb einer Zeile, wahlweise nur für bestimmte Ebenen; Vertretung abwesend.

Ergebnisspalten

Je Spalte: Spalte der Zeilen-Abfrage, Überschrift, Format (Zahl, Fortschritt mit Maximum-Spalte, Badge, Text), Einheit, Nachkommastellen, Summen (keine oder Zeilen summieren), Breite. Werte wie „Urlaub genommen im Jahr“ rechnet die Zeilen-Abfrage, zum Beispiel mit SUM(...) FILTER (WHERE ...) und einem LEFT JOIN auf die Abwesenheiten.

Stilregeln

Regeln in Reihenfolge, spätere übersteuern frühere. Feld ist category, status, layerId, label oder eine Spalte der Abfrage; Wert eine Kommaliste oder *. Wirkung: Farbe, Muster, Kürzel für den Zellmodus, Deckkraft, Ausblenden. Optional nur für bestimmte Ebenen.

Markierungen

Zeitpunkte (Datum) und Zeiträume (Start, Ende exklusiv) mit Beschriftung und Farbe, die ohne Zeile über die ganze Tafel gezeichnet werden.

Aktionen

Je Aktion: Ziel (Eintrag, Zeile, Auswahl, Tafel), Auslöser (Klick, Kontextmenü, Schaltfläche, Verschieben, Verlängern), Beschriftung und Symbol, optional nur für bestimmte Ebenen, eine Bedingung als JSONata über entry, row, range und user (true erlaubt, false blendet aus, ein Text deaktiviert mit Begründung), eine Rückfrage. Arten:

Art Wirkung
Datensatz öffnen öffnet den Datensatz im Data Lake; braucht id und dataSchemaId in der Ebene
Prozess starten öffnet das Startformular des gewählten Prozesses im Dialog oder in einem neuen Tab
Feld setzen schreibt einen festen Wert in ein Feld des Datensatzes, etwa Status „Genehmigt“
Eintrag verschieben schreibt Start- und Endfeld nach dem Ziehen; bei „Ende inklusiv“ wieder als letzter Tag
Auf Kanal veröffentlichen sendet Eintrag oder Auswahl an andere Widgets des Dashboards
Adresse öffnen öffnet eine URL mit Platzhaltern wie $(entry.id), $(row.id), $(range.start)
Aktualisieren lädt die Tafel neu

Die Standardkonfiguration enthält „Öffnen“ bei Klick auf einen Eintrag.


Platzhalter

In allen Abfragen der Tafel:

Platzhalter Wird zu
@periodStart, @periodEnd Grenzen des gewählten Zeitraums als Zeitstempel-Ausdruck; mit CAST(@periodEnd AS date) mit Datumsspalten vergleichen. @periodEnd ist der erste Tag nach dem Zeitraum.
@currentUserEmail, @currentUserSub angemeldeter Benutzer, zum Beispiel für „nur meine Zeile“
@currentDate, @currentYear, @currentMonth, @currentTimeStamp heutiges Datum, Jahr, Monat, Zeitpunkt
$(parameter) Wert aus dem umgebenden Filtercontainer

Musterschemas

Die beiden Dialoge „Musterschema anlegen“ erzeugen normale Datenschemas, die du im Data Designer beliebig erweitern kannst. Der technische Name ist zugleich der Tabellenname in SQL.

Mitarbeiter (Vorschlag mitarbeiter):

Feld Typ Verwendung auf der Tafel
email Pantarey-Benutzer Zeilen-Schlüssel; passt zu app_beantragt_von der App „Urlaubsantrag“
name Text, Pflicht Anzeigename
team Text Gruppe
arbeitstage Text, Standard 1,2,3,4,5 Arbeitstage, Teilzeit zum Beispiel 1,2,4
fte Zahl, Standard 1 Stellenanteil für Vollzeitäquivalente
bundesland Auswahl Feiertage
aktiv Ja/Nein, Standard ja ausgeschiedene Mitarbeiter ausblenden

Abwesenheiten (Vorschlag abwesenheiten):

Feld Typ Verwendung auf der Tafel
mitarbeiter Referenz auf Mitarbeiter, Pflicht Zeile
erster_tag, letzter_tag Datum, Pflicht Start und Ende (inklusiv)
erster_tag_vollhalb, letzter_tag_vollhalb Voll/Halb Halbtage
kategorie Jahresurlaub, Krank, Fortbildung, Homeoffice Farbe und Legende
status Beantragt, Genehmigt, Abgelehnt Stilregeln, Sperren, Bedingungen
tage Zahl Menge
vertretung Referenz auf Mitarbeiter Vertretungsprüfung
bemerkung Text Text auf dem Balken

Referenzfelder speichern die Id des verknüpften Datensatzes. In SQL wird deshalb über m.id = a.mitarbeiter verknüpft.


Bedienung

  • Maßstab oben rechts umschalten, Heute springt zur Jetzt-Linie, die Minimap unter der Toolbar zeigt das ganze Jahr und springt per Klick.
  • Tooltip mit Zeitraum, Status, Menge und Hinweisen beim Überfahren eines Balkens.
  • Legende unten: Klick blendet eine Kategorie aus.
  • Gruppen auf- und zuklappen; die Gruppenzeile zählt je Tag, Unterschreitungen der Mindestbesetzung sind farbig.
  • Ziehen: Balken verschieben, an den Kanten verlängern. Während des Ziehens zeigt ein Hinweis, wie sich die Anwesenheit des Teams am kritischsten Tag ändert. Gesperrte Status verweigern mit Begründung.
  • Auswahl: über leere Zellen ziehen, dann erscheinen die konfigurierten Aktionen mit Anzahl Tage und Arbeitstage.
  • Suche filtert Zeilen und Einträge; Escape hebt die Auswahl auf; Tab wandert durch die Balken.

Hinweise

  • Die Tafel ändert nie selbst Daten. Beim Verschieben oder bei „Feld setzen“ schreibt das Widget die konfigurierten Felder und zeigt den Eintrag gestreift, bis die Datenbank den neuen Stand liefert.
  • Geladen wird der gewählte Zeitraum. Ergebnisspalten wie „Urlaub genommen im Jahr“ gehören deshalb in die Zeilen-Abfrage, nicht in die Ebene.
  • Wer welche Zeilen sieht, entscheidet die Abfrage: WHERE m.email = @currentUserEmail zeigt nur die eigene Zeile, eine Bedingung auf das Team nur die Kollegen.
  • Einträge, deren Zeilen-Schlüssel keine Zeile trifft, werden nicht gezeichnet. Im Designer zeigt die Vorschau ihre Anzahl.