Der Resource Planning Calendar ist die Grundlage der Erweiterung Schichtplanung.
Der Resource Planning Calendar ermöglicht intuitive Drag-&-Drop Ressourcenplanung direkt in Matrix42. Schichten, Fahrzeuge, Räume oder beliebige andere Ressourcen lassen sich in einer übersichtlichen Kalenderansicht verwalten.
Funktionsumfang
| Funktion | Beschreibung |
|---|---|
| Drag-&-Drop Auswahl | Datumsbereiche durch Ziehen auswählen und Zuweisungen erstellen |
| Drei Ansichten | Jahres-, Monats- und Wochenansicht mit jeweiligen Summierungen |
| Zielstunden-Tracking | Fortschrittsbalken mit konfigurierbaren Zielwerten pro Element |
| Hintergrund-Markierungen | Feiertage, Urlaub oder andere Hintergrundinformationen anzeigen |
| Überschneidungserkennung | Automatische Warnung bei Zeitkonflikten |
| Zusammenfassungszeilen | Aggregierte Ansicht nach konfigurierbaren Kategorien |
| Legende | Farben und Icons der Zuweisungstypen auf ein oder zwei Zeilen erklären |
| Callbacks | Eigene Funktionen nach dem Anlegen, Ändern und Löschen einer Zuweisung ausführen |
| Export | Kalenderansicht als PNG oder JPEG speichern |
Architektur
Die Extension wird als Front-End Workspace in Matrix42 integriert. Das AngularJS-Modul RootITUp.PlanningCalendar nutzt Angular Material für Dialoge und Tippy.js für Tooltips.
Komponenten
| Komponente | Funktion |
|---|---|
rootitup-planning-calendar | Hauptkalender mit Raster und Steuerung |
rootitup-planning-time-inputs | Wiederverwendbare Zeiteingabe in Dialogen |
Genutzte Matrix42-Services
mx.sb.public.service: Benachrichtigungen (Success/Error)mx.SolutionBuilderAgent.DataService: CRUD-Operationen für Zuweisungen
API-Berechtigungen
Der Kalender nutzt die Matrix42 REST-API zum Speichern von Zuweisungen:
| Webservice | Route | Methode |
|---|---|---|
AddObject | api/data/objects/{ciname} | POST |
Sicherheitshinweis:
AddObjectist eine privilegierte Admin-/Integrations-API und standardmäßig auf administrative Rollen beschränkt. Die Freigabe gilt für die gesamte Operation: WerPOST api/data/objects/{ciname}für eine Rolle freischaltet, erlaubt ihr das Anlegen von Objekten für jeden CI-Typ bzw. jede Data Definition, nicht nur für den vom Kalender genutzten. Verlassen Sie sich außerdem nicht darauf, dass objektbezogene Schreibrechte oder Insert-Regeln bei diesem Aufruf erneut geprüft werden. Vergeben Sie die Berechtigung deshalb nur an eine enge, dedizierte Rolle ausschließlich für die Planenden. Der sicherere Weg ist eine eigene Custom Web Operation mit eigener Zielgruppe (Audience), die nur den vom Kalender genutzten CI-Typ akzeptiert und die Berechtigungen selbst prüft. Er ist mit der heutigen Speicherroute des Kalenders nicht nutzbar.
Abhängigkeiten
Das Modul lädt automatisch:
- Tippy.js: Dynamische Tooltips mit HTML-Inhalt
- Angular Material: Dialoge und Formularelemente
Installation
Extension Gallery
- Matrix42 Administration öffnen
- Zu Administration → Extensions → Extension Gallery navigieren
- Nach „Resource Planning Calendar” von RootITUp suchen
- Auf „Install” klicken und warten, bis die Installation abgeschlossen ist
Voraussetzung: Administrative Rechte im Matrix42-System. Kompatibel mit Matrix42 ab Version 11.x.x.
Basiskonfiguration
1. Layout erstellen
Im Layout Builder ein neues Widget-Layout oder eine Page erstellen, auf der die Ressourcenplanung angezeigt werden soll.
2. Kalender einfügen
- In der Toolbox nach „Planning” suchen
- Das Element „Resource Planning Calendar” per Drag-&-Drop platzieren
3. Pflichtfelder konfigurieren
Der Kalender benötigt mindestens drei Eingaben:
| Eigenschaft | Beschreibung |
|---|---|
heading | Überschrift der linken Spalte (z. B. „Mitarbeitende”) |
items | Array der Zeilen (Ressourcen) mit id und title |
choices | Array der zuweisbaren Optionen mit Ergebnis-Funktion |
Datenmodell
Items (Zeilen)
Jede Zeile repräsentiert eine planbare Ressource:
const items = [
{
id: "ec4369f1-7431-4bd0-9277-20c5b32a57f3",
title: "Max Mustermann",
description: "Teamleitung" // optional
},
{
id: "bd967992-1e66-4cea-b711-570f41c6b678",
title: "Dienstwagen A-XY 123",
description: "VW Golf"
}
];
Choices (Zuweisungsoptionen)
Jede Option definiert, was zugewiesen werden kann. Die id sollte die Expression Object ID des Zielobjekts sein (siehe resultType).
Wiederverwendbare Ergebnis-Funktion
Für mehrere Choices mit gleichem Speicherformat empfiehlt sich eine zentrale result-Funktion:
function mapToObject(item, choice, startDate, endDate, notes) {
return {
mP_TimeRecordClass: {
mP_Approved: 1,
mP_CreatedManually: 1,
mP_FullTimeAbsence: 0,
mP_HalfDayAbsence: 0,
mP_NoPauseTaken: 1,
mP_RecordStarted: 0,
mP_RecordStopped: 1,
mP_RecordWasNotStopped: 0,
mP_SmokingBreak: 0,
mP_Minutes: choice.custom.minutes, // Aus custom-Eigenschaft
mP_StartDate: startDate,
},
};
}
Farbpalette
const shiftColors = [
"#4A90E2", "#50E3C2", "#F5A623", "#BD10E0",
"#9013FE", "#B8E986", "#7ED321", "#F8E71C",
];
Vollständiges Beispiel
const choices = [
{
// Expression Object ID der Choice
id: "f852ce66-9b0b-4e4e-9870-0d811ffe21bd",
title: "FR6",
description: "Frühschicht 6",
start: "07:00",
end: "14:00",
color: shiftColors[0],
icon: "wb_sunny",
result: mapToObject,
resultType: "mP_TimeRecordType",
// Custom-Attribute für die result-Funktion
custom: {
minutes: 375, // 6 Stunden 15 Minuten
},
},
{
id: "b1c2d3e4-f5a6-7b8c-9d0e-f1a2b3c4d5e6",
title: "SP",
description: "Spät",
start: "13:30",
end: "22:00",
color: shiftColors[1],
icon: "brightness_3",
result: mapToObject,
resultType: "mP_TimeRecordType",
custom: {
minutes: 510, // 8 Stunden 30 Minuten
},
},
{
id: "c7d8e9f0-a1b2-c3d4-e5f6-7890abcdef12",
title: "URL",
description: "Urlaub",
start: "08:00",
end: "16:00",
color: shiftColors[2],
icon: "beach_access",
result: mapToObject,
resultType: "mP_TimeRecordType",
custom: { minutes: 480 },
isSelectable: false, // Nur Anzeige, nicht auswählbar
},
{
id: "d1e2f3a4-b5c6-d7e8-f9a0-b1c2d3e4f5a6",
title: "KRANK",
description: "Krankheit",
start: "08:00",
end: "16:00",
color: shiftColors[3],
icon: "local_hospital",
result: mapToObject,
resultType: "mP_TimeRecordType",
custom: { minutes: 480 },
isSelectable: false,
isRelevantForTotals: false, // Nicht in Arbeitsstunden-Summe
},
];
Pflichtfelder für Choices
| Feld | Typ | Beschreibung |
|---|---|---|
id | String | Expression Object ID (GUID) der Choice |
title | String | Kurzanzeige im Kalender-Chip |
start | String | Startzeit in HH:mm Format |
end | String | Endzeit in HH:mm Format |
result | Function | Funktion zur Erstellung des Datenobjekts |
resultType | String | CI-Name (Entity Set) für die Speicherung |
Optionale Felder
| Feld | Typ | Standard | Beschreibung |
|---|---|---|---|
description | String | – | Längere Beschreibung im Auswahldialog |
color | String | Primary-Color | CSS-Farbe des Chips |
icon | String | assignment | Material-Icon im Chip |
custom | Object | – | Beliebige Attribute, die an die result-Funktion übergeben werden |
isSelectable | Boolean | true | Bei false wird die Choice nur angezeigt, aber nicht im Auswahldialog angeboten |
duration | Number | auto | Dauer in Minuten (überschreibt automatische Berechnung aus Start/End) |
isRelevantForTotals | Boolean | true | Bei false nicht in Summen/Zielstunden enthalten (z. B. Krankheit) |
Existing Assignments (Bestehende Zuweisungen)
Zum Laden bereits gespeicherter Daten:
const existingAssignments = [
{
objectId: "12345-abcde-67890",
itemId: "ec4369f1-7431-4bd0-9277-20c5b32a57f3",
choiceId: "shift-early-01",
type: "MyExtension_ShiftAssignmentType",
start: "2026-02-15T07:00:00Z",
end: "2026-02-15T13:00:00Z",
notes: "Vertretung für Team B",
isModifiable: true
}
];
| Feld | Typ | Beschreibung |
|---|---|---|
objectId | String | Primärschlüssel der Zuweisung |
itemId | String | Referenz zur Zeile |
choiceId | String | Referenz zur Choice |
type | String | CI-Name des Objekts |
start | Date/String | Start der Zuweisung |
end | Date/String | Ende der Zuweisung |
isRelevant | Boolean | Bei false wird der Chip ausgegraut |
isModifiable | Boolean | Bei false keine Bearbeitung möglich |
notes | String | Notizen (im Tooltip sichtbar) |
Background Assignments (Hintergrundmarkierungen)
Für Feiertage, Urlaub oder andere Hintergrundinformationen:
const backgroundAssignments = [
{
itemId: "ec4369f1-7431-4bd0-9277-20c5b32a57f3",
date: "2026-02-14",
color: "#FF9800",
title: "Urlaub",
shortTitle: "U",
icon: "beach_access"
}
];
Hintergründe werden unabhängig von regulären Zuweisungen angezeigt und nehmen nicht an der Überschneidungsprüfung teil.
Zielstunden-Tracking
Targets konfigurieren
Über das targets-Array lassen sich Soll-Stunden pro Element definieren:
const targets = [
{
itemId: "ec4369f1-7431-4bd0-9277-20c5b32a57f3",
target: {
type: "month", // oder "week"
hours: 160
},
validFrom: "2026-01-01", // optional
validTo: "2026-12-31", // optional
successPercentage: 80 // optional, Standard: 70
}
];
Skalierung
Wird ein Wochen-Ziel in der Monatsansicht angezeigt (oder umgekehrt), skaliert der Kalender automatisch:
| Ansicht | Target-Typ | Faktor |
|---|---|---|
| Monat | week | ×4 |
| Woche | month | ÷4 |
Fortschrittsbalken-Farben
Die Farben des Fortschrittsbalkens sind konfigurierbar:
| Eigenschaft | Anwendung | Standard |
|---|---|---|
progress-bar-color-below-target | Unter Zielwert | --mx-info-color |
progress-bar-color-on-target | Zielwert erreicht | --mx-success-color |
progress-bar-color-over-target | Über Zielwert | --mx-error-color |
Position der Total-Spalte
Die Spalte mit dem Fortschrittsbalken lässt sich links oder rechts positionieren:
<rootitup-planning-calendar
total-column-position="left">
</rootitup-planning-calendar>
Saldo-Anzeige
Über das balances-Array lassen sich Übertragswerte aus Vormonaten anzeigen:
const balances = [
{
itemId: "ec4369f1-7431-4bd0-9277-20c5b32a57f3",
month: "2026-01", // Format YYYY-MM
minutes: -120 // negativ = Minusstunden
}
];
Der Saldo wird in den zwei Folgemonaten nach dem angegebenen Monat angezeigt.
Zusammenfassungszeilen
Mit dem summaries-Array lassen sich aggregierte Zeilen am unteren Rand konfigurieren:
const summaries = [
{
title: "Arbeitsstunden gesamt",
icon: "schedule",
iconColor: "#4CAF50",
choiceIds: ["shift-early-01", "shift-late-01", "shift-night-01"],
emptyText: "Keine Schichten geplant"
}
];
Die Zusammenfassung summiert die Dauer aller Zuweisungen, deren choiceId im Array enthalten ist.
Legende
Über das legend-Array blenden Sie eine Legende ein, die Farben und Icons den Choices (Zuweisungsoptionen) oder Abwesenheitsgründen zuordnet. Die Einträge lassen sich auf zwei Zeilen verteilen, etwa Schichten in der ersten und Abwesenheiten in der zweiten Zeile:
const legend = [
{ title: "Frühschicht", color: shiftColors[0], icon: "wb_sunny", row: 1 },
{ title: "Spätschicht", color: shiftColors[1], icon: "brightness_3", row: 1 },
{ title: "Urlaub", color: shiftColors[2], icon: "beach_access", row: 2 },
{ title: "Krankheit", color: shiftColors[3], icon: "local_hospital", row: 2 }
];
| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
title | String | ja | Beschriftung neben dem Farbfeld |
color | String | ja | CSS-Farbwert des Farbfelds (z. B. Hex, rgb() oder Farbname) |
icon | String | nein | Material-Icon im Farbfeld |
row | Number | nein | Zeile der Legende: 1 oder 2 (Standard: 1) |
Benutzerinteraktion
Neue Zuweisung erstellen
- Zellen auswählen: Mit gedrückter Maustaste über den gewünschten Datumsbereich ziehen
- Dialog öffnet sich: Verfügbare Optionen werden angezeigt
- Option auswählen: Zeiten können angepasst werden
- Speichern: Die Zuweisung wird erstellt und optimistisch angezeigt
Bestehende Zuweisung bearbeiten
- Auf Chip klicken: Der Bearbeitungsdialog öffnet sich
- Zeiten anpassen: Start- und Endzeit können geändert werden
- Notizen hinzufügen: Freitext-Feld für zusätzliche Informationen
- Speichern oder Löschen: Änderungen werden übernommen
Zuweisungen löschen
Im Auswahldialog (Bereichsauswahl) steht die Option „Alle Zuweisungen löschen” zur Verfügung. Diese entfernt alle bearbeitbaren Zuweisungen im ausgewählten Bereich nach Bestätigung.
Überschneidungserkennung
Der Kalender prüft automatisch auf Zeitkonflikte:
- Beim Erstellen: Neue Zuweisungen werden abgelehnt, wenn sie sich mit bestehenden überschneiden
- Beim Bearbeiten: Geänderte Zeiten werden gegen andere Zuweisungen im selben Slot geprüft
- Hintergründe ausgenommen: Background Assignments nehmen nicht an der Prüfung teil
Schreibschutz
Der gesamte Kalender lässt sich in den Nur-Lesen-Modus versetzen:
<rootitup-planning-calendar
is-read-only="true">
</rootitup-planning-calendar>
Im Schreibschutzmodus sind keine Interaktionen möglich. Das eignet sich für Reporting-Ansichten.
Optimistische Updates
Alle Datenbankoperationen verwenden optimistische Updates:
- Die UI wird sofort aktualisiert
- Die API-Anfrage wird im Hintergrund ausgeführt
- Bei Fehler wird der vorherige Zustand wiederhergestellt
Dies sorgt für eine reaktive Benutzererfahrung ohne wahrnehmbare Wartezeiten.
Callbacks
Drei optionale Bindings führen eigene Logik aus, nachdem das Backend das Anlegen, Ändern oder Löschen einer Zuweisung bestätigt hat:
| Binding | Auslöser |
|---|---|
post-creation-callbacks | Zuweisung angelegt |
post-update-callbacks | Zuweisung geändert |
post-deletion-callbacks | Zuweisung gelöscht |
Jedes Binding erwartet ein Array von Funktionen. Der Kalender ruft sie nacheinander auf, nicht schon für die optimistisch angezeigte Änderung. Typische Einsätze sind der Abgleich mit externen Daten, das Anstoßen weiterer Workflows oder Logging.
const postCreationCallbacks = [
function protokolliereZuweisung(params) {
console.info("Zuweisung angelegt:", params.objectId, params.choiceId);
}
];
Jede Funktion erhält genau ein Parameterobjekt:
| Feld | Anlegen | Ändern | Löschen | Beschreibung |
|---|---|---|---|---|
selectedItemId | ja | ja | ja | ID der Zeile (Item) |
choiceId | ja | ja | ja | ID der Choice |
resultType | ja | ja | ja | CI-Name der Zuweisung (resultType der Choice) |
entity | ja | ja | – | Daten der angelegten bzw. geänderten Zuweisung |
objectId | ja | ja | ja | ID des Zuweisungsobjekts |
Wirft eine einzelne Callback-Funktion einen Fehler, wird er abgefangen und protokolliert. Die übrigen Callbacks und der Kalender laufen weiter.
Ansichten
Monatsansicht
Standard-Ansicht mit allen Tagen des Monats. Jeder Tag zeigt:
- Zuweisungs-Chips
- Hintergrundfarben (falls konfiguriert)
- Wochennummer in der Navigation
Wochenansicht
Kompakte 7-Tage-Ansicht der aktuellen Woche. Ideal für detaillierte Tagesplanung.
Jahresansicht
Kompakte Übersicht aller 12 Monate. Jeder Tag wird als farbiger Punkt dargestellt:
- Farbe der ersten Zuweisung oder des Hintergrunds
- Tooltip zeigt alle Zuweisungen
- Klick öffnet die Monatsansicht
Export (PNG/JPEG)
Über die Schaltfläche mit dem Download-Symbol in der Werkzeugleiste oberhalb des Kalenders speichern Sie den Kalender als Bild, wahlweise als PNG oder JPEG. So lässt sich ein Plan etwa aushängen oder per E-Mail verschicken.

Barrierefreiheit
Die Tooltips nutzen Tippy.js mit folgendem Setup:
tippy(element, {
allowHTML: true,
theme: "custom-dark",
animation: "fade"
});
Alle Interaktionen sind tastaturzugänglich über Angular Material Dialoge.
Changelog
Version 2.8.0
- Live-Überlappungserkennung bei Zuweisung und Bearbeitung
- Lifecycle Callbacks (Post-Create, Post-Update, Post-Delete)
- Saldo-Anzeige für Übertragswerte aus Vormonaten
- Export als PNG/JPEG
Version 2.0.0
- Drag-&-Drop Zellauswahl für intuitive Bereichsauswahl
- Drei Ansichten: Jahr, Monat, Woche
- Zielstunden-Tracking mit Fortschrittsbalken
- Hintergrund-Markierungen für Feiertage/Urlaub
- Überschneidungserkennung verhindert Doppelbelegungen
- Zusammenfassungszeilen mit aggregierten Werten
- Notizen-Feld für zusätzliche Informationen pro Zuweisung
Häufig gestellte Fragen
Welche Ressourcentypen werden unterstützt?
Der Kalender ist generisch konzipiert. Jede Entität mit id und title kann als Zeile dargestellt werden, etwa Personal, Fahrzeuge, Räume, Maschinen oder beliebige andere Ressourcen.
Wie werden Zuweisungen gespeichert?
Über die result-Funktion und das resultType-Feld in der Choice-Definition. Die Funktion erzeugt das zu speichernde Objekt, das über den Matrix42 Data Service persistiert wird.
Können Zuweisungen über Mitternacht gehen?
Ja. Bei Zuweisungen, deren Endzeit vor der Startzeit liegt (z. B. 22:00–06:00), wird automatisch der Folgetag angenommen.
Wie funktioniert die Saldo-Berechnung?
Der Saldo wird nicht automatisch berechnet. Das balances-Array muss extern befüllt werden (z. B. aus einem Zeiterfassungssystem). Der Kalender zeigt den übergebenen Wert an.
Werden mehrere Zuweisungen pro Tag unterstützt?
Ja. Pro Zelle (Item × Tag) können beliebig viele Zuweisungen existieren, solange sie sich zeitlich nicht überschneiden.
Wie werden Hintergründe und Zuweisungen kombiniert?
Hintergründe (Background Assignments) bilden die Zellenfarbe. Zuweisungen werden als Chips darauf angezeigt. Beides ist unabhängig voneinander.
Werden zusätzliche Berechtigungen benötigt?
Ja. Der Kalender speichert Zuweisungen über die Matrix42-API AddObject (POST api/data/objects/{ciname}), eine privilegierte Admin-/Integrations-API, die standardmäßig auf administrative Rollen beschränkt ist. Beachten Sie: Die Freigabe dieser Operation gilt für jeden CI-Typ bzw. jede Data Definition, nicht nur für den vom Kalender genutzten. Vergeben Sie sie daher nur an eine enge, dedizierte Rolle für die Planenden. Eine eigene Custom Web Operation mit eigener Zielgruppe (Audience), die nur den Kalender-CI-Typ akzeptiert und die Berechtigungen selbst prüft, wäre der sicherere Weg, ist mit der heutigen Speicherroute des Kalenders aber nicht nutzbar (siehe API-Berechtigungen).