UNPKG

processcube.apptemplate

Version:

A AppTemplate for a App build with and for the ProcessCube Plattform

310 lines (264 loc) 8.11 kB
/** * Prüft, ob ein External Task Input Node mit dem angegebenen Topic bereits existiert * @param {string} topic - External Task Topic * @returns {object|null} Existierender Node oder null */ function findExistingExternalTaskByTopic(topic) { if (!topic) { return null; } var externalTaskInputNodes = RED.nodes.filterNodes({type: "externaltask-input"}); return externalTaskInputNodes.find(function(node) { return node.topic === topic; }) || null; } /** * Sucht einen Flow anhand seines Namens * @param {string} flowName - Name des zu suchenden Flows * @returns {{flow: object|null, shouldCreate: boolean}} Flow-Objekt und Flag ob ein neuer Flow erstellt werden muss */ function findOrPrepareFlow(flowName) { if (!flowName) { return { flow: null, shouldCreate: false }; } var targetFlow = null; // Suche in Workspaces RED.nodes.eachWorkspace(function(ws) { if (ws.label === flowName) { targetFlow = ws; } }); // Suche in Subflows falls nicht gefunden if (!targetFlow) { RED.nodes.eachSubflow(function(sf) { if (sf.name === flowName) { targetFlow = sf; } }); } return { flow: targetFlow, shouldCreate: !targetFlow }; } /** * Findet die ProcessCube Engine-Konfiguration * @returns {object} Engine-Konfiguration */ function getEngineConfig() { var engineConfigs = []; RED.nodes.eachConfig(function(node) { if (node.type === "processcube-engine-config") { engineConfigs.push(node); } }); return engineConfigs.find(node => node.url === 'ENGINE_URL'); } /** * Berechnet die Y-Position für eine neue Gruppe im Flow * @param {object} targetFlow - Der Ziel-Flow * @param {boolean} shouldCreateFlow - Flag ob ein neuer Flow erstellt wird * @returns {number} Y-Position für die neue Gruppe */ function calculateGroupYPosition(targetFlow, shouldCreateFlow) { var yPosition = 50; if (targetFlow && !shouldCreateFlow) { var maxY = 0; var groupHeight = 0; RED.nodes.eachGroup(function(group) { if (group.z === targetFlow.id) { if (group.y > maxY) { maxY = group.y; groupHeight = group.h || 0; } } }); yPosition = maxY > 0 ? maxY + groupHeight + 20 : 20; console.log("Berechnete Y-Position für neue Gruppe:", yPosition, "MaxY war:", maxY); } return yPosition; } /** * Erstellt die Nodes für einen External Task Worker * @param {string} topic - External Task Topic * @param {object} engineConfig - Engine-Konfiguration * @param {number} yPosition - Y-Position für die Nodes * @returns {{nodes: object[], group: object}} Erstellte Nodes und Gruppe */ function createExternalTaskNodes(topic, engineConfig, yPosition) { // Output Node var etwOutput = { id: RED.nodes.id(), type: "externaltask-output", x: 726, y: yPosition + 50 }; // Delay Node var delay = { id: RED.nodes.id(), type: "delay", x: 426, y: yPosition + 50, pauseType: "delay", timeout: "5", timeoutUnits: "seconds", wires: [[etwOutput.id]] }; // Input Node var etwInput = { id: RED.nodes.id(), type: "externaltask-input", x: 126, y: yPosition + 50, wires: [[delay.id]], topic: topic, engine: engineConfig.id }; // Error Node var etwError = { id: RED.nodes.id(), type: "externaltask-error", x: 526, y: yPosition + 100 }; // Catch Node var catchNode = { id: RED.nodes.id(), type: "catch", x: 326, y: yPosition + 100, scope: 'group', wires: [[etwError.id]] }; // Group var group = { id: RED.nodes.id(), type: "group", name: `ETW: ${topic}`, x: 34, y: yPosition, nodes: [etwInput.id, delay.id, etwOutput.id, catchNode.id, etwError.id], style: { "label": true } }; return { nodes: [etwInput, delay, etwOutput, catchNode, etwError], group: group }; } /** * Setzt die Flow-Zugehörigkeit (z-Property) für alle Nodes * @param {object[]} nodes - Array von Nodes * @param {object} group - Gruppen-Objekt * @param {string} flowId - Flow-ID */ function assignNodesToFlow(nodes, group, flowId) { if (!flowId) { return; } group.z = flowId; nodes.forEach(function(node) { node.z = flowId; }); } /** * Erstellt einen neuen Flow * @param {string} flowName - Name des neuen Flows * @returns {object} Flow-Objekt */ function createNewFlow(flowName) { return { id: RED.nodes.id(), type: "tab", label: flowName, disabled: false, info: "" }; } /** * Erstellt einen neuen Flow und zeigt ihn an * @param {object} flowObject - Das Flow-Objekt * @returns {string} Die ID des erstellten Flows */ function createAndShowFlow(flowObject) { // Importiere nur den Flow RED.view.importNodes([flowObject], { addFlow: true, touchImport: true, applyNodeDefaults: true }); // Wechsle zum neuen Flow RED.workspaces.show(flowObject.id); return flowObject.id; } /** * Importiert Nodes in einen existierenden Flow * @param {object[]} nodes - Zu importierende Nodes * @param {object} group - Gruppe */ function importNodesIntoFlow(nodes, group) { var nodesToImport = [group].concat(nodes); var importOptions = { addFlow: false, touchImport: true, applyNodeDefaults: true }; RED.view.importNodes(nodesToImport, importOptions); // Markiere Workspace als dirty, um Deploy-Button zu aktivieren RED.nodes.dirty(true); } var addExternalTask = function(params) { 'use strict'; console.log("Füge neuen ExternalTask-Node hinzu"); // Prüfe, ob External Task mit diesem Topic bereits existiert var existingNode = findExistingExternalTaskByTopic(params.externalTaskTopic); if (existingNode) { console.log("External Task mit Topic bereits vorhanden:", params.externalTaskTopic); // Verwende die fokusExternalTask Funktion if (typeof focusExternalTask === 'function') { focusExternalTask({externalTaskTopic: params.externalTaskTopic}); } return; } // Flow-Management var flowInfo = findOrPrepareFlow(params.flowName); var targetFlow = flowInfo.flow; var shouldCreateFlow = flowInfo.shouldCreate; // Engine-Konfiguration laden var engineConfig = getEngineConfig(); // Y-Position berechnen var yPosition = calculateGroupYPosition(targetFlow, shouldCreateFlow); // Nodes und Gruppe erstellen var externalTaskSetup = createExternalTaskNodes( params.externalTaskTopic, engineConfig, yPosition ); var nodes = externalTaskSetup.nodes; var group = externalTaskSetup.group; // Flow-Zuweisung und Import if (shouldCreateFlow) { // 1. Neuen Flow erstellen var newFlow = createNewFlow(params.flowName); // 2. Flow anzeigen (leerer Flow) createAndShowFlow(newFlow); // 3. Nodes dem Flow zuweisen assignNodesToFlow(nodes, group, newFlow.id); // 4. Nodes in den jetzt sichtbaren Flow importieren setTimeout(function() { importNodesIntoFlow(nodes, group); }, 100); // Kurze Verzögerung, damit der Flow-Wechsel abgeschlossen ist } else { // In existierenden Flow einfügen var flowId = targetFlow ? targetFlow.id : null; // Zum Ziel-Flow wechseln falls vorhanden if (targetFlow) { RED.workspaces.show(targetFlow.id); } assignNodesToFlow(nodes, group, flowId); setTimeout(function() { importNodesIntoFlow(nodes, group); }, 100); } };