mirror of
https://github.com/The-Low-Code-Foundation/OpenNoodl.git
synced 2026-01-12 15:22:55 +01:00
Co-Authored-By: Eric Tuvesson <eric.tuvesson@gmail.com> Co-Authored-By: mikaeltellhed <2311083+mikaeltellhed@users.noreply.github.com> Co-Authored-By: kotte <14197736+mrtamagotchi@users.noreply.github.com> Co-Authored-By: Anders Larsson <64838990+anders-topp@users.noreply.github.com> Co-Authored-By: Johan <4934465+joolsus@users.noreply.github.com> Co-Authored-By: Tore Knudsen <18231882+torekndsn@users.noreply.github.com> Co-Authored-By: victoratndl <99176179+victoratndl@users.noreply.github.com>
285 lines
12 KiB
JavaScript
285 lines
12 KiB
JavaScript
"use strict";
|
|
|
|
function difference(array1, array2) {
|
|
const valueSet = new Set(array2);
|
|
return array1.filter(e => !valueSet.has(e));
|
|
}
|
|
|
|
async function handleEvent(context, graphModel, event) {
|
|
|
|
function applyPortDelta(nodeModel, newPorts) {
|
|
var inputPorts = {};
|
|
var outputPorts = {};
|
|
|
|
newPorts.forEach(function(port) {
|
|
//some ports are incorrectly named outputs instead of output, patch it here so
|
|
//the rest of the code doesn't need to care
|
|
if(port && port.plug === "outputs") {
|
|
port.plug = "output";
|
|
}
|
|
|
|
if(port.plug === 'input' || port.plug === 'input/output') {
|
|
inputPorts[port.name] = port;
|
|
}
|
|
if(port.plug === 'output' || port.plug === 'input/output') {
|
|
outputPorts[port.name] = port;
|
|
}
|
|
});
|
|
|
|
var existingInputs = Object.keys(nodeModel.getInputPorts());
|
|
|
|
var inputPortsToRemove = difference(existingInputs, Object.keys(inputPorts));
|
|
var inputPortsToAdd = difference(Object.keys(inputPorts), existingInputs);
|
|
|
|
// Update port types if it has changed
|
|
nodeModel.updateInputPortTypes(inputPorts);
|
|
|
|
// Remove and add input ports
|
|
inputPortsToRemove.forEach(nodeModel.removeInputPortWithName.bind(nodeModel));
|
|
inputPortsToAdd.forEach(function(portName) {
|
|
nodeModel.addInputPort(inputPorts[portName]);
|
|
if(nodeModel.parameters && nodeModel.parameters.hasOwnProperty(portName)) {
|
|
setInputValueOnNodeInstancesWithModel(context.rootComponent.nodeScope, nodeModel, portName, nodeModel.parameters[portName]);
|
|
}
|
|
});
|
|
|
|
// Update port types if it has changed
|
|
nodeModel.updateOutputPortTypes(outputPorts);
|
|
|
|
// Remove and add output ports
|
|
var existingOutputs = Object.keys(nodeModel.getOutputPorts());
|
|
|
|
var outputPortsToRemove = difference(existingOutputs, Object.keys(outputPorts));
|
|
var outputPortsToAdd = difference(Object.keys(outputPorts), existingOutputs);
|
|
|
|
outputPortsToRemove.forEach(nodeModel.removeOutputPortWithName.bind(nodeModel));
|
|
outputPortsToAdd.forEach(function(portName) {
|
|
nodeModel.addOutputPort(outputPorts[portName]);
|
|
});
|
|
}
|
|
|
|
function setInputValueOnNodeInstancesWithModel(nodeScope, nodeModel, port, value) {
|
|
var nodes = nodeScope.getNodesWithIdRecursive(nodeModel.id);
|
|
nodes.forEach(function(node) {
|
|
node.queueInput(port, value);
|
|
});
|
|
}
|
|
|
|
var componentModel;
|
|
if(event.componentName) {
|
|
componentModel = graphModel.getComponentWithName(event.componentName);
|
|
if(!componentModel) {
|
|
//if we haven't received this component yet, just ignore the delta update
|
|
return;
|
|
}
|
|
}
|
|
|
|
//some ports are incorrectly named outputs instead of output, patch it here so
|
|
//the rest of the code doesn't need to care
|
|
if(event.port && event.port.plug === "outputs") {
|
|
event.port.plug = "output";
|
|
}
|
|
|
|
var eventHandlers = {
|
|
nodeAdded: function(event) {
|
|
componentModel.importEditorNodeData(event.model, event.parentId, event.childIndex);
|
|
},
|
|
nodeRemoved: async function(event) {
|
|
if(componentModel.hasNodeWithId(event.model.id)) {
|
|
await componentModel.removeNodeWithId(event.model.id);
|
|
}
|
|
},
|
|
connectionAdded: function(event) {
|
|
componentModel.addConnection(event.model);
|
|
},
|
|
connectionRemoved: function(event) {
|
|
componentModel.removeConnection(event.model);
|
|
|
|
//revert to default value or parameter if this was the last connection to that port
|
|
var targetNodeModel = componentModel.getNodeWithId(event.model.targetId);
|
|
if(componentModel.getConnectionsToPort(targetNodeModel.id, event.model.targetId).length === 0) {
|
|
var value = targetNodeModel.parameters[event.model.targetPort];
|
|
if(value === undefined) {
|
|
value = context.getDefaultValueForInput(targetNodeModel.type, event.model.targetPort);
|
|
}
|
|
|
|
setInputValueOnNodeInstancesWithModel(context.rootComponent.nodeScope, targetNodeModel, event.model.targetPort, value);
|
|
}
|
|
|
|
},
|
|
parameterChanged: function(event) {
|
|
|
|
const nodeModel = componentModel.getNodeWithId(event.nodeId);
|
|
if(nodeModel === undefined) {
|
|
console.log("parameterChanged: Unknown node id",event);
|
|
return;
|
|
}
|
|
|
|
//did we get a bunch of parameters at once?
|
|
if(event.parameters) {
|
|
//note: some props might be deleted, then they only exist in oldParameters
|
|
const allParams = new Set(Object.keys(event.parameters).concat(Object.keys(event.oldParameters)));
|
|
for(const param of allParams) {
|
|
nodeModel.setParameter(param, event.parameters[param]);
|
|
}
|
|
}
|
|
|
|
//did we get a single parameters?
|
|
if(event.parameterName) {
|
|
nodeModel.setParameter(event.parameterName, event.parameterValue, event.state);
|
|
}
|
|
},
|
|
nodeAttached: function(event) {
|
|
componentModel.setNodeParent(componentModel.getNodeWithId(event.nodeId), componentModel.getNodeWithId(event.parentId), event.childIndex);
|
|
},
|
|
nodeDetached: function(event) {
|
|
componentModel.setNodeParent(componentModel.getNodeWithId(event.nodeId), null);
|
|
componentModel.addRootId(event.nodeId);
|
|
},
|
|
componentAdded: function(event) {
|
|
graphModel.importComponentFromEditorData(event.model);
|
|
},
|
|
componentRemoved: async function(event) {
|
|
await graphModel.removeComponentWithName(event.componentName);
|
|
},
|
|
rootAdded: function(event) {
|
|
componentModel.addRootId(event.nodeId);
|
|
},
|
|
portAdded: function(event) {
|
|
var nodeModel = componentModel.getNodeWithId(event.nodeId);
|
|
if(event.port.plug === "input" || event.port.plug === "input/output") {
|
|
nodeModel.addInputPort(event.port);
|
|
|
|
//if node already has an old value for this port, set that value on all instances of the node
|
|
//example: expression a+b, a=1, b=2. User removes b and then adds it again, the value 2 should be restored since it's still in the model
|
|
if(nodeModel.parameters.hasOwnProperty(event.port)) {
|
|
setInputValueOnNodeInstancesWithModel(context.rootComponent.nodeScope, nodeModel, event.port, nodeModel.parameters[event.port]);
|
|
}
|
|
}
|
|
if(event.port.plug === "output" || event.port.plug === "input/output") {
|
|
nodeModel.addOutputPort(event.port);
|
|
}
|
|
},
|
|
portRemoved: function(event) {
|
|
var nodeModel = componentModel.getNodeWithId(event.nodeId);
|
|
if(event.port.plug === "input" || event.port.plug === "input/output") {
|
|
nodeModel.removeInputPortWithName(event.port.name);
|
|
}
|
|
if(event.port.plug === "output" || event.port.plug === "input/output") {
|
|
nodeModel.removeOutputPortWithName(event.port.name);
|
|
}
|
|
},
|
|
nodePortRenamed: function(event) {
|
|
if(event.port.plug === "input" || event.port.plug === "input/output") {
|
|
componentModel.renameInputPortOnNodeWithId(event.nodeId, event.oldName, event.port.name);
|
|
}
|
|
if(event.port.plug === "output" || event.port.plug === "input/output") {
|
|
componentModel.renameOutputPortOnNodeWithId(event.nodeId, event.oldName, event.port.name);
|
|
}
|
|
var node = componentModel.getNodeWithId(event.nodeId);
|
|
if(node.type === "Component Inputs") {
|
|
componentModel.addInputPort(event.port);
|
|
graphModel.getNodesWithType(componentModel.name).forEach(function(componentInstance) {
|
|
componentInstance.component.renameInputPortOnNodeWithId(componentInstance.id, event.oldName, event.port.name);
|
|
});
|
|
componentModel.removeInputPortWithName(event.oldName);
|
|
}
|
|
else if(node.type === "Component Outputs") {
|
|
componentModel.addOutputPort(event.port);
|
|
graphModel.getNodesWithType(componentModel.name).forEach(function(componentInstance) {
|
|
componentInstance.component.renameOutputPortOnNodeWithId(componentInstance.id, event.oldName, event.port.name);
|
|
});
|
|
componentModel.removeOutputPortWithName(event.oldName);
|
|
}
|
|
},
|
|
componentPortsUpdated: function(event) {
|
|
applyPortDelta(componentModel, event.ports);
|
|
},
|
|
instancePortsChanged: function(event) {
|
|
if(!componentModel.hasNodeWithId(event.nodeId)) return;
|
|
var nodeModel = componentModel.getNodeWithId(event.nodeId);
|
|
applyPortDelta(nodeModel, event.ports);
|
|
},
|
|
componentRenamed: function(event) {
|
|
graphModel.renameComponent(event.oldName, event.newName);
|
|
},
|
|
settingsChanged: function(event) {
|
|
graphModel.setSettings(event.settings);
|
|
},
|
|
metadataChanged: function(event) {
|
|
graphModel.setMetaData(event.key,event.data);
|
|
},
|
|
componentMetadataChanged: function(event) {
|
|
const c = graphModel.getComponentWithName(event.componentName);
|
|
if(!c) return;
|
|
c.setMetadata(event.key, event.data);
|
|
},
|
|
variantParametersChanged: function(event) {
|
|
if(event.variant) {
|
|
//we got the whole variant
|
|
graphModel.updateVariant(event.variant);
|
|
}
|
|
else {
|
|
//we got a specific value to update
|
|
graphModel.updateVariantParameter(event.variantName, event.variantTypeName, event.parameterName, event.parameterValue, event.state);
|
|
|
|
//check if value has been deleted from the variant
|
|
if(event.parameterValue === undefined) {
|
|
//all active nodes with this variant will have to revert back to the default value, if they don't have local overrides
|
|
const variant = graphModel.getVariant(event.variantTypeName, event.variantName);
|
|
const nodes = context.rootComponent.nodeScope.getAllNodesWithVariantRecursive(variant);
|
|
nodes.forEach(node => {
|
|
node.queueInput(event.parameterName, node.getParameter(event.parameterName));
|
|
});
|
|
}
|
|
}
|
|
},
|
|
variantDeleted: function(event) {
|
|
graphModel.deleteVariant(event.variantTypeName, event.variantName);
|
|
},
|
|
variantChanged: function(event) {
|
|
const nodeModel = componentModel.getNodeWithId(event.nodeId);
|
|
const variant = graphModel.getVariant(nodeModel.type, event.variantName);
|
|
|
|
nodeModel.setVariant(variant);
|
|
},
|
|
variantRenamed: function(event) {
|
|
const variant = graphModel.getVariant(event.variantTypeName, event.oldVariantName);
|
|
if(variant) {
|
|
variant.name = variant.variantName;
|
|
}
|
|
},
|
|
defaultStateTransitionChanged: function(event) {
|
|
const nodeModel = componentModel.getNodeWithId(event.nodeId);
|
|
nodeModel.setDefaultStateTransition(event.curve, event.state);
|
|
},
|
|
stateTransitionsChanged: function(event) {
|
|
const nodeModel = componentModel.getNodeWithId(event.nodeId);
|
|
if(event.parameterName) {
|
|
nodeModel.setStateTransitionParamter(event.parameterName, event.curve, event.state);
|
|
}
|
|
},
|
|
variantDefaultStateTransitionChanged: function(event) {
|
|
graphModel.updateVariantDefaultStateTransition(event.variantName, event.variantTypeName, event.curve, event.state);
|
|
},
|
|
variantStateTransitionsChanged: function(event) {
|
|
graphModel.updateVariantStateTransition(event);
|
|
},
|
|
routerIndexChanged: function(event) {
|
|
graphModel.routerIndex = event.data;
|
|
}
|
|
};
|
|
|
|
if(eventHandlers.hasOwnProperty(event.type)) {
|
|
await eventHandlers[event.type](event);
|
|
context.scheduleUpdate();
|
|
}
|
|
else {
|
|
console.log('Unknown event', event);
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
handleEvent: handleEvent
|
|
};
|