Steveorevo / node-maker

A set of subflows that can be used to quickly create a new Node-RED node, its property panels, and initial behavior.
GNU Lesser General Public License v2.1
20 stars 4 forks source link

Low-code/no-code “Magic Defaults” possible? #3

Open Steveorevo opened 1 year ago

Steveorevo commented 1 year ago

A truly low-code/no-code environment would support the enhanced concept of “magic defaults”; whereby we use hooks to analyze the node graph to set defaults based on what a newly added node is wired to and before the node’s property panel is first opened:

User Scenario

For starters, we could simply support a routine entry point template/subflow node that tells us what node we’re wired to. Advanced would be to accommodate/trace back junctions and/or an array of upstream nodes that we’re wired to.

Given this functionality; a node can change its default setting based on context.

Use case

A “meta node” is used to fetch meta data based on an index. This index is supplied by other nodes as a property of the msg object. the other nodes could be a “user node” (that supplies an index on its outgoing msg.user_id property) or a video node (that has an outgoing msg.video_id), or a news article node (that supplies a msg.post_id).

The meta node has a msg input type textbox in its property panel that one can enter “user_id”, “video_id”, or “post_id”.

It would be great if this was automatically set the first time the property panel was opened because the meta node knows what other node it is wired to (user node, video node, or news node).

For this to happen, a “magic default” would need to be implemented so that the meta node knows what other node it was wired to so that it can pre-populate its input type textbox.

lgrkvst commented 1 year ago

My target group does not code so I solved this the following way:

First we need a utility function:

function getLeftNodes(node, type) {
var arr = RED.nodes
  .filterLinks({
    target: node,
  })
  .map((e) => e.source);
if (!type) return arr;
return arr.filter((n) => n.type == type);
}

Then we'll put this inside oneditprepare:

var node = this;
var leftNodes = getLeftNodes(node);

if (leftNodes.length > 1) {
    // multiple left nodes – see next block
} else if (leftNode[0].type == "user") {
    $("#node-input-metamenu").typedInput("value", "user_id");
} else if (leftNode[0].type == "video") {
    $("#node-input-metamenu").typedInput("value", "video_id");
} else if (leftNode[0].type == "news") {
    $("#node-input-metamenu").typedInput("value", "news_id");
}

Regarding stopping the user from piping in multiple nodes, put the following inside a script tag at the top of the html file:

    RED.events.on("links:add", function (l) {
      // interactive mode only
      if (!RED.nodes.node(l.target.id)) return;
      if (l.target.type == "meta_node") {
          var sources = getLeftNodes(l.target);
          if (sources.length > 1) {
            RED.nodes.removeLink(l);
            l.target.status = {
                fill: "red",
                shape: "dot",
                text: "Error: meta_node cannot have multiple inputs",
            };
           node.dirtyStatus = true;
           RED.view.redraw();

          }
        }
Steveorevo commented 1 year ago

Perfect! That’s exactly along the lines of what I’m looking for.