Steveorevo/node-maker

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

Opened this issue · 2 comments

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

  • the user places our new node on a flow tab
  • before opening the property panel, they wire it’s input to an existing node
  • when opening our node’s property panel for the first time, the defaults are shown based on the nodes our node is wired too.

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.

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();

          }
        }

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