gateway/modules/features/graphicalEditor/nodeDefinitions/flow.py

283 lines
9.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Copyright (c) 2025 Patrick Motsch
# Flow control node definitions.
from modules.shared.i18nRegistry import t
LOOP_DONE_DATA_PICK_OPTIONS = [
{
"path": ["bodyResults"],
"pickerLabel": t("Alle Schleifen-Ergebnisse"),
"detail": t(
"Ausgabe des letzten Schrittes im Schleifen-Rumpf pro Iteration als Liste, "
"ein Eintrag pro Durchlauf. Ideal als Eingabe fuer Kontext zusammenfuehren."
),
"recommended": True,
"type": "List[Any]",
},
{
"path": ["items"],
"pickerLabel": t("Iterierte Elemente"),
"detail": t(
"Liste der Schleifen-Elemente nach gewähltem Iterationsmodus (Kopie der Eingabeliste, gefiltert)."
),
"recommended": False,
"type": "List[Any]",
},
{
"path": ["count"],
"pickerLabel": t("Anzahl Durchläufe"),
"detail": t("Wie viele Iterationen die Schleife ausgeführt hat."),
"recommended": False,
"type": "int",
},
]
LOOP_ITEM_DATA_PICK_OPTIONS = [
{
"path": ["currentItem"],
"pickerLabel": t("Aktuelles Element"),
"detail": t("Das aktuelle Iterationselement."),
"recommended": True,
"type": "Any",
},
{
"path": ["currentIndex"],
"pickerLabel": t("Aktueller Index"),
"detail": t("0-basierter Index der aktuellen Iteration."),
"recommended": False,
"type": "int",
},
{
"path": ["items"],
"pickerLabel": t("Alle Elemente"),
"detail": t("Die vollständige Quellliste."),
"recommended": False,
"type": "List[Any]",
},
{
"path": ["count"],
"pickerLabel": t("Gesamtanzahl"),
"detail": t("Anzahl der Elemente in der Schleife."),
"recommended": False,
"type": "int",
},
]
MERGE_RESULT_DATA_PICK_OPTIONS = [
{
"path": ["merged"],
"pickerLabel": t("Zusammengeführt"),
"detail": t("Zusammengeführtes Ergebnis (je nach Modus)."),
"recommended": True,
"type": "Dict",
},
{
"path": ["first"],
"pickerLabel": t("Erster Zweig"),
"detail": t("Daten vom ersten verbundenen Eingang (Modus „first“)."),
"recommended": False,
"type": "Any",
},
{
"path": ["inputs"],
"pickerLabel": t("Alle Eingänge"),
"detail": t("Dict der Eingabeobjekte nach Port-Index."),
"recommended": False,
"type": "Dict[int,Any]",
},
]
# Extended picker for ``context.mergeContext`` (ActionResult + ``surfaceDataAsTopLevel``): same
# merge keys as ``flow.merge`` plus ``count`` from the action payload.
CONTEXT_MERGE_ACTION_RESULT_DATA_PICK_OPTIONS = [
*MERGE_RESULT_DATA_PICK_OPTIONS,
{
"path": ["count"],
"pickerLabel": t("Anzahl Einträge"),
"detail": t("Wie viele Einträge zusammengeführt wurden."),
"recommended": False,
"type": "int",
},
]
# Ports, die typische Schritt-Ausgaben durchreichen (nicht nur leerer Transit).
_FLOW_INPUT_SCHEMAS = [
"Transit",
"FormPayload",
"AiResult",
"TextResult",
"ActionResult",
"DocumentList",
"FileList",
"EmailList",
"TaskList",
"QueryResult",
"MergeResult",
"LoopItem",
"BoolResult",
"UdmDocument",
]
FLOW_NODES = [
{
"id": "flow.ifElse",
"category": "flow",
"label": t("Wenn / Sonst"),
"description": t(
"Verzweigt anhand einer Bedingung auf ein vorheriges Feld oder einen Ausdruck. "
"Die Daten vom Eingangskanal werden an den gewählten Ausgang durchgereicht."
),
"parameters": [
{
"name": "condition",
"type": "json",
"required": True,
"frontendType": "condition",
"description": t("Bedingung: Feld aus einem vorherigen Schritt und Vergleich"),
},
],
"inputs": 1,
"outputs": 2,
"outputLabels": [t("Ja"), t("Nein")],
"inputPorts": {0: {"accepts": list(_FLOW_INPUT_SCHEMAS)}},
"outputPorts": {0: {"schema": "Transit"}, 1: {"schema": "Transit"}},
"executor": "flow",
"meta": {"icon": "mdi-source-branch", "color": "#FF9800", "usesAi": False},
},
{
"id": "flow.switch",
"category": "flow",
"label": t("Switch"),
"description": t(
"Mehrere Zweige nach einem Wert aus einem vorherigen Schritt (Data Picker). "
"Definiere Fälle mit Vergleichsoperator; der Eingang wird an den ersten passenden Zweig durchgereicht."
),
"parameters": [
{
"name": "value",
"type": "Any",
"required": True,
"frontendType": "dataRef",
"description": t("Wert zum Vergleichen (Feld aus einem vorherigen Schritt)"),
},
{
"name": "cases",
"type": "array",
"required": False,
"frontendType": "caseList",
"description": t("Fälle: Operator und Vergleichswert"),
},
],
"inputs": 1,
"outputs": 1,
"inputPorts": {0: {"accepts": list(_FLOW_INPUT_SCHEMAS)}},
"outputPorts": {0: {"schema": "Transit"}},
"executor": "flow",
"meta": {"icon": "mdi-swap-horizontal", "color": "#FF9800", "usesAi": False},
},
{
"id": "flow.loop",
"category": "flow",
"label": t("Schleife / Für jedes"),
"description": t(
"Zwei Ausgänge: „Schleife“ verbindet den Rumpf (pro Element); optional führt der Rumpf "
"mit einem Rücklauf-Pfeil wieder zum **gleichen Eingang** wie der vorherige Schritt (wie in n8n). "
"„Fertig“ führt genau einmal fort, wenn alle Iterationen beendet sind. "
"Die zu durchlaufende Liste wählen Sie wie bisher; UDM-/Strukturdaten werden automatisch sinnvoll in Elemente aufgelöst."
),
"parameters": [
{
"name": "items",
"type": "Any",
"required": True,
"frontendType": "dataRef",
"description": t("Liste oder Sammlung zum Durchlaufen (im Data Picker wählen)"),
},
{
"name": "iterationMode",
"type": "str",
"required": False,
"frontendType": "select",
"frontendOptions": {
"options": ["all", "first", "last", "every_second", "every_third", "every_nth"],
},
"description": t(
"Welche Elemente die Schleife besucht: alle, nur das erste/letzte, jedes zweite/dritte "
"oder jedes n-te (Schritt dann unter „Schrittweite“)."
),
"default": "all",
},
{
"name": "iterationStride",
"type": "int",
"required": False,
"frontendType": "number",
"frontendOptions": {"min": 2, "max": 100},
"description": t("Nur bei „jedes n-te“: Schrittweite (z. B. 5 = jedes 5. Element ab Index 0)."),
"default": 2,
},
{
"name": "concurrency",
"type": "int",
"required": False,
"frontendType": "number",
"frontendOptions": {"min": 1, "max": 20},
"description": t("Parallele Durchläufe (1 = nacheinander)"),
"default": 1,
},
],
"inputs": 1,
"outputs": 2,
"outputLabels": [t("Schleife"), t("Fertig")],
"inputPorts": {
0: {"accepts": [
"Transit", "UdmDocument", "EmailList", "DocumentList", "FileList", "TaskList",
"ActionResult", "AiResult", "QueryResult", "FormPayload", "LoopItem",
]},
},
"outputPorts": {
0: {"schema": "LoopItem", "dataPickOptions": LOOP_ITEM_DATA_PICK_OPTIONS},
1: {"schema": "Transit", "dataPickOptions": LOOP_DONE_DATA_PICK_OPTIONS},
},
"executor": "flow",
"meta": {"icon": "mdi-repeat", "color": "#FF9800", "usesAi": False},
},
{
"id": "flow.merge",
"category": "flow",
"label": t("Zusammenführen"),
"description": t(
"Führt 25 Zweige zusammen, wenn alle verbunden sind. "
"Modus legt fest, wie die Eingabeobjekte im Ergebnis kombiniert werden."
),
"parameters": [
{
"name": "mode",
"type": "str",
"required": False,
"frontendType": "select",
"frontendOptions": {"options": ["first", "all", "append"]},
"description": t("first: erster Zweig; all: Dict-Felder zusammenführen; append: Listen anhängen"),
"default": "first",
},
{
"name": "inputCount",
"type": "int",
"required": False,
"frontendType": "number",
"frontendOptions": {"min": 2, "max": 5},
"description": t("Anzahl Eingänge dieses Nodes (25)"),
"default": 2,
},
],
"inputs": 2,
"outputs": 1,
"inputPorts": {
0: {"accepts": list(_FLOW_INPUT_SCHEMAS)},
1: {"accepts": list(_FLOW_INPUT_SCHEMAS)},
},
"outputPorts": {0: {"schema": "MergeResult", "dataPickOptions": MERGE_RESULT_DATA_PICK_OPTIONS}},
"executor": "flow",
"meta": {"icon": "mdi-call-merge", "color": "#FF9800", "usesAi": False},
},
]