I have created a flow with a node that has a configurable component for example a server connection.
If I then import a flow that contains configuration settings that have the same name as the one I have just created I end up with duplicate configuration settings.
Is there a way to auto increment the names of imported configuration node settings if one of the same name already exists? Or alternatively if configuration settings of the same name already exist allow these to be over written with the newly imported settings of the same name.
The node name is purely visual and should not be used to identify a node in the code. This is the job of the id.
It's possible to increment but only if you have developed the node. Otherwise you have to add an "nodes:add" event which when you add this node, updates the name by modifying the node properties.
RED.events.on("nodes:add", (node) => {
// Skip if not your node
if (node.type !== "your-type") return;
// check if name exist with
// RED.nodes.eachNode
// then update it
node.name = "new name"
});
Thanks for the response, I figured out a way of getting the nodes.add event listener to update the configuration nodes name on import. I just called RED.nodes.eachConfig(function (node: object) {});from within the listener. It worked well, however I am wondering if when an example flow is imported and if that flow contains a configuration node of a name of one that already exists the configuration node in the imported flow can be replaced with the already installed one.
I don't understand fully but when you import a flow, it triggers the event and therefore acts as if you had added a node. I'm not sure but that's normally how it works.
Yes I am developing a node. What I tried to do was based on Node name switch the id of the node fr one that already exists. This however seems to leave (temporarily) two nodes in the configuration nodes settings until the browser is refreshed.
RED.events.on("nodes:add", (node: NodeDef) => {
if (node.type !== NODE_NAME) return;
const result: string[] = [];
const id = node.id;
const name = node.name;
RED.nodes.eachConfig(function (node: object) {
const _node = node as NodeDef;
if (_node.type === NODE_NAME && id !== _node.id && name === _node.name) {
result.push(_node.id);
}
return true;
});
if (result.length == 1) {
node.id = result[0];
}
});
I then need to find a way of updating the configuration id in the imported flow. Not sure if it is possible...
I went that way at first and it worked okay. However if there was a way of switching the imported config node for one of the same name then the system would be more efficient.
However I do not think that this is possible without looking into the scripts associated with the import process.
Listen for the type of config node being added and keep track of duplicates, deleting them but keeping a list of the old and new ID's. Then listen for the node itself being added and check its config node to see if it is in the duplicate list, replacing the new reference with the old.
BTW, I have a standard process for working out whether a node instance has been copy/pasted or imported. I need this to prevent duplicate URL's in UIBUILDER.
RED.events.on('nodes:add', function(node) {
// For any newly added uib node, track what type of addition this is
if ( uibuilder.uibNodeTypes.includes(node.type) ) {
if (node.changed === false && !('moved' in node)) node.addType = 'load'
else if (!('_config' in node)) node.addType = 'new'
else if (node.changed === true && ('_config' in node)) node.addType = 'paste/import'
}
if ( node.type === 'uibuilder') {
// Remove the URL on paste or import
if (node.addType === 'paste/import') {
delete node.url
delete node.oldUrl
// We have to change this if we want the display version to change (if the prop is part of the label)
delete node._config.url
}
// Keep a list of ALL uibuilder nodes in the editor incl disabled, undeployed, etc. Different to the deployed list
if (node.url) uibuilder.editorUibInstances[node.id] = node.url
// Inform interested functions that something was added (and why)
RED.events.emit('uibuilder:node-added', node)
// -- IF uibuilderInstances <> editorInstances THEN there are undeployed instances. OR Disabled nodes/flows --
// uibuilder.log('[uibuilder] node added:', node)
}
})
Some of these nodes require a configuration node, for example an API connection
This API connection could be named 'My API Connection'
Example flows are also available for import
These example flows contain a config node with the same name for example 'My API Connection'
On import of the example flows we are ending up with duplicate config nodes i.e. two My API Connection nodes.
Iterating helps remove the duplicate names, for example the imported config node name becomes 'MY API Connection #2' if a config node with the name already exists.
However an ideal situation would be one where an imported config node in a flow is replaced by a config node of the same name if it is already installed.
In writing this I have had an idea...why not force the ID of the config node to be the same as the ID of the config nodes in the examples if it has a certain name....