User Interfaces erstellen
Mit Dashboard-2 (@flowfuse/node-red-dashboard) erstellen Sie direkt aus Ihren Flows moderne, responsive Web-Oberflächen. LowCode erweitert Dashboard-2 um spezielle Widgets für die Arbeit mit der Engine, wie Dynamic Forms und Dynamic Tables.
Dashboard-2 Grundlagen
Dashboard-2 organisiert die Oberfläche in einer klaren Hierarchie:
| Ebene | Beschreibung | Konfiguration |
|---|---|---|
| UI Base | Die gesamte Dashboard-Anwendung | Theme, Titel, Pfad |
| UI Page | Eine einzelne Seite/Route | Name, Icon, Pfad |
| UI Group | Ein Container auf der Seite | Name, Breite, Seite |
| UI Widget | Ein einzelnes UI-Element | Typ, Gruppe, Optionen |
Aufbau einer Seite
Jedes Widget wird einer Group zugeordnet, jede Group einer Page, und jede Page gehört zur UI Base:
UI Base: "Meine App" (/dashboard)
├── Page: "Startseite" (/dashboard/home)
│ ├── Group: "Übersicht"
│ │ ├── Widget: ui-text (Willkommen)
│ │ └── Widget: ui-chart (Statistiken)
│ └── Group: "Aktionen"
│ └── Widget: ui-button (Neuer Vorgang)
└── Page: "Aufgaben" (/dashboard/tasks)
└── Group: "Offene Aufgaben"
└── Widget: ui-table (Aufgabenliste)Wichtige Widgets
ui-text — Texte anzeigen
Zeigt dynamischen Text an, der sich bei neuen Messages aktualisiert:
// Function Node: Text vorbereiten
msg.payload = `Aktuell ${flow.get("openTasks") || 0} offene Aufgaben`;
return msg;ui-button — Aktionen auslösen
Buttons senden beim Klick eine Message an den nächsten Node:
[ui-button: "Prozess starten"]
→ [fn: prepareStart]
→ [process-start: MyProcess]
→ [fn: showResult]
→ [ui-notification: "Prozess gestartet"]ui-form — Formulare
Formulare sammeln strukturierte Eingaben vom Benutzer:
Konfiguration des ui-form Nodes:
Formular-Elemente:
- Name (Text, required)
- E-Mail (Email, required)
- Abteilung (Dropdown: IT, HR, Finance)
- Priorität (Dropdown: Hoch, Mittel, Niedrig)
- Beschreibung (Multiline Text)Verarbeitung der Formulardaten:
// Function Node: Formulardaten verarbeiten
const formData = msg.payload;
// Formulardaten stehen als Objekt zur Verfügung
const request = {
name: formData.Name,
email: formData["E-Mail"],
department: formData.Abteilung,
priority: formData.Priorität,
description: formData.Beschreibung,
createdAt: new Date().toISOString()
};
msg.payload = request;
return msg;ui-table — Tabellen
Zeigt Daten in tabellarischer Form mit Sortierung und Paginierung:
// Function Node: Tabellendaten vorbereiten
const tasks = flow.get("tasks") || [];
msg.payload = tasks.map(t => ({
"Aufgabe": t.name,
"Status": t.state === "running" ? "Offen" : "Erledigt",
"Erstellt": new Date(t.createdAt).toLocaleDateString("de-DE"),
"Priorität": t.priority
}));
return msg;ui-chart — Diagramme
Erstellt Linien-, Balken- und Kreisdiagramme:
// Function Node: Chartdaten vorbereiten (Balkendiagramm)
msg.payload = [
{ x: "Montag", y: 12 },
{ x: "Dienstag", y: 8 },
{ x: "Mittwoch", y: 15 },
{ x: "Donnerstag", y: 6 },
{ x: "Freitag", y: 10 }
];
msg.topic = "Erledigte Aufgaben";
return msg;ProcessCube®-spezifische Widgets
Das Enterprise Image enthält spezialisierte Widgets für die Arbeit mit der Engine.
Dynamic Form
Der Dynamic Form-Widget rendert Formulare dynamisch basierend auf den FormFields eines UserTasks. Die Formularstruktur wird direkt aus dem BPMN-Prozess abgeleitet.
[usertask-event-listener: userTaskCreated]
→ [fn: prepareFormData]
→ [ui-dynamic-form: Formular anzeigen]
→ [fn: processResult]
→ [usertask-output: UserTask beenden]// Function Node: prepareFormData
const userTask = msg.payload;
// Die FormFields des UserTasks werden automatisch als Formular gerendert
msg.userTaskConfig = {
userTaskInstanceId: userTask.id,
processInstanceId: userTask.processInstanceId,
formFields: userTask.formFields
};
return msg;Dynamic Table
Der Dynamic Table-Widget zeigt tabellarische Daten mit konfigurierbaren Spalten, Filterung und Aktionen an:
// Function Node: Dynamic Table konfigurieren
msg.payload = {
columns: [
{ key: "name", label: "Name", sortable: true },
{ key: "status", label: "Status", sortable: true },
{ key: "date", label: "Datum", type: "date" },
{ key: "actions", label: "Aktionen", type: "actions" }
],
data: flow.get("processInstances") || [],
pagination: { page: 1, pageSize: 10 }
};
return msg;UI Page Navigation
Der UI Page Navigation-Widget ermöglicht das programmgesteuerte Navigieren zwischen Dashboard-Seiten:
// Function Node: Zur Detailseite navigieren
msg.payload = {
page: "/dashboard/task-detail",
params: { taskId: msg.taskId }
};
return msg;Vollständiges Dashboard-Beispiel
Das folgende Beispiel zeigt ein komplettes Task-Management-Dashboard mit Übersicht, Formular und Detail-Ansicht.
Seite 1: Aufgaben-Übersicht
Page: "Aufgaben" (/dashboard/tasks)
Group: "Statistiken" (Breite: 6)
[inject: Alle 30s] → [fn: loadStats] → [ui-text: Offene Tasks]
[inject: Alle 30s] → [fn: loadStats] → [ui-chart: Tasks pro Tag]
Group: "Aufgabenliste" (Breite: 6)
[inject: Alle 10s] → [fn: loadTasks] → [ui-table: Aufgaben]
[ui-table: Klick] → [fn: navigateToDetail] → [ui-page-navigation]// Function Node: loadStats
const tasks = flow.get("tasks") || [];
const openCount = tasks.filter(t => t.state === "running").length;
const doneCount = tasks.filter(t => t.state === "finished").length;
msg.payload = `${openCount} offen / ${doneCount} erledigt`;
return msg;// Function Node: loadTasks
const tasks = flow.get("tasks") || [];
msg.payload = tasks
.filter(t => t.state === "running")
.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))
.map(t => ({
"ID": t.id.substring(0, 8),
"Aufgabe": t.name,
"Prozess": t.processModelId,
"Erstellt": new Date(t.createdAt).toLocaleDateString("de-DE")
}));
return msg;Seite 2: Neue Aufgabe erstellen
Page: "Neue Aufgabe" (/dashboard/new-task)
Group: "Aufgabe erfassen" (Breite: 6)
[ui-form: Aufgabenformular]
→ [fn: validateInput]
→ [process-start: CreateTask]
→ [fn: showSuccess]
→ [ui-notification: "Aufgabe erstellt"]// Function Node: validateInput
const formData = msg.payload;
if (!formData.Titel || formData.Titel.length < 3) {
msg.error = "Titel muss mindestens 3 Zeichen lang sein";
node.warn(msg.error);
return null; // Flow stoppen
}
// Daten für Prozessstart vorbereiten
msg.processModelId = "CreateTask_v1";
msg.payload = {
title: formData.Titel,
description: formData.Beschreibung || "",
priority: formData.Priorität || "Mittel",
assignee: formData.Verantwortlich
};
return msg;Responsive Design
Dashboard-2 unterstützt responsive Layouts. Die Breite einer Group wird in Grid-Einheiten angegeben (1-12, analog zu CSS Grid):
| Breite | Desktop | Tablet | Mobil |
|---|---|---|---|
| 12 | Volle Breite | Volle Breite | Volle Breite |
| 6 | Halbe Breite | Halbe Breite | Volle Breite |
| 4 | Ein Drittel | Halbe Breite | Volle Breite |
| 3 | Ein Viertel | Halbe Breite | Volle Breite |
Empfohlene Layouts
- Formulare: Breite 6 (halbe Seite auf Desktop)
- Tabellen: Breite 12 (volle Breite)
- Statistik-Kacheln: Breite 3 (vier nebeneinander)
- Charts: Breite 6 (zwei nebeneinander)
Theming
Dashboard-2 unterstützt Light Mode und Dark Mode. Das Theme wird in der UI-Base konfiguriert:
Standard-Farben anpassen
In den Dashboard-2 Einstellungen können Sie die Hauptfarben anpassen:
| Eigenschaft | ProcessCube® Standard | Beschreibung |
|---|---|---|
| Primary | #f7a823 | Hauptfarbe (ProcessCube® Orange) |
| Accent | #333333 | Akzentfarbe |
| Background | #ffffff / #1a1a1a | Hintergrund (Light/Dark) |
| Surface | #f5f5f5 / #2d2d2d | Oberflächen (Light/Dark) |
Eigenes CSS
Für fortgeschrittene Anpassungen können Sie Custom CSS über einen ui-template-Node einbinden:
<style>
/* ProcessCube® Branding */
.v-toolbar {
background-color: #f7a823 !important;
}
.v-btn--variant-elevated {
background-color: #f7a823 !important;
color: #000000 !important;
}
</style>Best Practices
1. Daten serverseitig filtern
Senden Sie nur die Daten an das Dashboard, die tatsächlich angezeigt werden:
// Korrekt: Gefilterte Daten senden
msg.payload = allTasks.filter(t => t.state === "running").slice(0, 50);2. Updates begrenzen
Vermeiden Sie zu häufige Updates, um die Performance zu schonen:
[inject: Alle 10s] → [fn: loadData] → [ui-table]3. Feedback geben
Zeigen Sie dem Benutzer immer Feedback nach Aktionen:
// ui-notification Node für Bestätigungen
msg.payload = "Aufgabe erfolgreich erstellt";
msg.topic = "success"; // success, info, warning, error
return msg;4. Navigation konsistent halten
Verwenden Sie eine einheitliche Seitenstruktur mit klarer Navigation. Die Sidebar wird automatisch aus den konfigurierten Pages generiert.
Nächste Schritte
- Workflow-Integration — UserTask-Formulare mit Prozessen verbinden
- Portal-Integration — Dashboard-Apps als Portal-Anwendungen bereitstellen
- UI-Nodes — Alle verfügbaren UI-Nodes im Detail
- REST-APIs entwickeln — Backend-APIs für Ihre Dashboards