Bug found in node-red-autolayout-sidebar

As per the github readme, I'm posting here and mentioning @gregorius and @bartbutenaers. I also want give my heartfelt thanks for creating this plugin, it's hugely valuable to me!

I think I found a bug in the node-red-autolayout-sidebar plugin. When I format a sequence of nodes that contains a subflow, the nodes in the subflow get rearrange (badly) as a side effect. I tracked down a point in the code where an intervention may be in order. My little hack seems to have fixed it but I doubt it's the best way to do it. My hope is that this is enough to point the maintainers in the right direction

I changed this code:

        // Convert nodes to flows.json format since all the wires, i.e. links, are 
        // contained in one simple json format.
        var allnodes = RED.nodes.createExportableNodeSet(ns).filter((n) => {
            return n.type != "tab" && n.type != 'subflow' && n.type != "group"
        });

To this:

        // Convert nodes to flows.json format since all the wires, i.e. links, are 
        // contained in one simple json format.
        var firstZ = ""
        var allnodes = RED.nodes.createExportableNodeSet(ns).filter((n) => {
            if(!firstZ){firstZ=n.z}
            return n.type != "tab" && n.type != 'subflow' && n.type != "group" && n.z != firstZ
        });

My first intuition was that it should be "n.z =!== firstZ" instead of "n.z != firstZ" which really makes me suspect this probably only works some of the time. I've only been using Node-Red for about a month so I'm just kinda winging it. I was able to recreate the problem with the following exported flow and subflow on a new instance of node-red.

[
    {
        "id": "460b2f06e68bc30d",
        "type": "subflow",
        "name": "Identify",
        "info": "",
        "category": "",
        "in": [
            {
                "x": 50,
                "y": 30,
                "wires": [
                    {
                        "id": "c964dee06289988b"
                    }
                ]
            }
        ],
        "out": [
            {
                "x": 380,
                "y": 50,
                "wires": [
                    {
                        "id": "c964dee06289988b",
                        "port": 0
                    }
                ]
            }
        ],
        "env": [],
        "meta": {},
        "color": "#DDAA99"
    },
    {
        "id": "c964dee06289988b",
        "type": "function",
        "z": "460b2f06e68bc30d",
        "g": "ad29b377a35eb2b2",
        "name": "Get Env Vars",
        "func": "var np = env.get(\"NR_NODE_PATH\").split(\"/\")\nnp.pop()\nmsg.payload = \n{\n    //NR_NODE_NAME: env.get(\"NR_NODE_NAME\"),\n    //NODE_PATH: np,\n    //FULL_ID: env.get(\"NR_NODE_PATH\"),\n    FLOW_ID: env.get(\"NR_FLOW_ID\"),\n    FLOW_NAME: env.get(\"NR_FLOW_NAME\"),\n    GROUP_ID: env.get(\"NR_GROUP_ID\"),\n    GROUP_NAME: env.get(\"NR_GROUP_NAME\"),\n    NODE_ID: env.get(\"NR_NODE_ID\").split(\"-\")[0],\n    NODE_NAME: env.get(\"NR_SUBFLOW_NAME\"),\n    //NR_SUBFLOW_ID: env.get(\"NR_SUBFLOW_ID\"),\n    //NR_SUBFLOW_PATH: env.get(\"NR_SUBFLOW_PATH\")\n}\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 170,
        "y": 130,
        "wires": [
            [
                "e1ea0a2e9ec34f71"
            ]
        ]
    },
    {
        "id": "e1ea0a2e9ec34f71",
        "type": "change",
        "z": "460b2f06e68bc30d",
        "g": "ad29b377a35eb2b2",
        "name": "",
        "rules": [],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 350,
        "y": 160,
        "wires": [
            [
                "6349cff05362ddc8"
            ]
        ]
    },
    {
        "id": "6349cff05362ddc8",
        "type": "change",
        "z": "460b2f06e68bc30d",
        "g": "ad29b377a35eb2b2",
        "name": "",
        "rules": [],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 526,
        "y": 130,
        "wires": [
            [
                "6c8e2a9ab1fea78a"
            ]
        ]
    },
    {
        "id": "6c8e2a9ab1fea78a",
        "type": "change",
        "z": "460b2f06e68bc30d",
        "g": "ad29b377a35eb2b2",
        "name": "",
        "rules": [],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 709,
        "y": 130,
        "wires": [
            [
                "1db31beec3a47eb3"
            ]
        ]
    },
    {
        "id": "1db31beec3a47eb3",
        "type": "change",
        "z": "460b2f06e68bc30d",
        "g": "ad29b377a35eb2b2",
        "name": "",
        "rules": [],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 892,
        "y": 130,
        "wires": [
            []
        ]
    },
    {
        "id": "ad29b377a35eb2b2",
        "type": "group",
        "z": "460b2f06e68bc30d",
        "style": {
            "stroke": "rgba(171, 178, 191, 0.15)",
            "stroke-opacity": "1",
            "fill": "#21252b",
            "fill-opacity": "0.5",
            "label": true,
            "label-position": "nw",
            "color": "#abb2bf"
        },
        "nodes": [
            "c964dee06289988b",
            "e1ea0a2e9ec34f71",
            "6349cff05362ddc8",
            "6c8e2a9ab1fea78a",
            "1db31beec3a47eb3"
        ],
        "x": 74,
        "y": 89,
        "w": 924,
        "h": 112
    },
    {
        "id": "814b31cc0862f4c6",
        "type": "inject",
        "z": "a73275695c0b7d64",
        "name": "b",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": "0.2",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 332,
        "y": 220,
        "wires": [
            [
                "66e8840034c95f88"
            ]
        ],
        "l": false
    },
    {
        "id": "66e8840034c95f88",
        "type": "subflow:460b2f06e68bc30d",
        "z": "a73275695c0b7d64",
        "name": "subflow node - bb",
        "x": 470,
        "y": 220,
        "wires": [
            [
                "eb42df8b5c23ab64"
            ]
        ]
    },
    {
        "id": "eb42df8b5c23ab64",
        "type": "debug",
        "z": "a73275695c0b7d64",
        "name": "debug 206",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 663.5,
        "y": 220,
        "wires": []
    }
]

Hi @ProgrammerPaul

Thank you for the bug report :+1:

I can confirm that it's an issue - it can be tested in the server-less Node-RED and indeed the subflow gets rearranged incorrectly.

I am not 100% sure using that the first Z value is not a subflow. I'll have a look at it and have a think about the best solution ....

Cheers!

ok, the better solution would be to use the fixedNodeId to find a z value that contains the nodes that needs moving - the fixed node is the node that around which all other nodes are moved and represents the first node of the node selection list.

so replacing this with this:

let fixedNode = RED.nodes.node(fixedNodeId);
var allnodes = RED.nodes.createExportableNodeSet(ns).filter((n) => {
  return n.type != "tab" && n.type != 'subflow' && n.type != "group" && n.z == fixedNode.z
});

would be a more robust solution.

If @BartButenaers is ok with that solution, then if you (@ProgrammerPaul) want to create a pull request, then we fix the bug!

Edit: added links to GitHub

Hi @ProgrammerPaul,
Thank you for testing our sidebar! This kind of feedback is very useful for us to make the sidebar better. And it is even more easy for us since you already did some digging yourself into the code.

@gregorius,
Thanks for reviewing Paul's fix. Faster than my shadow, as usual :wink:
Your improved fix indeed seems to make sense :+1:

The fix from our layout guru @gregorius is available in the palette:

image

@ProgrammerPaul: nice to know that our sidebar is being used. If you have other feedback, please don't hesitate to share it!

2 Likes

Wow! Thanks guys! This is the best Christmas present I've gotten in a while :smiley:
I've been tinkering around with a few quality of life ideas like adding the different sorting algorithms and activating the sidebar as actions so I can assign hotkeys to them. If I get those working would you like to see a pull request?
Thanks again, I love Node-Red, but I can't imagine using it without this plugin.

2 Likes

Yes please! That would superb :+1:

Happy to hear, made my Xmas - thank you :blush:

Also agree with you on loving Node-RED - still trying to find something that I can't do with it!

2 Likes

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.