I'm writing this post to garner feedback on some ideas I have to improve the node authoring experience in NodeRED (not expecting any sort of implementation from anyone).
Automatic HTML Generation
Why: When creating nodes, the editor inputs often use known data types (number, string, bool, URL, etc) and the help text details each of them. This means that the HTML config object, editor input, and help text to describe them follow the same structure somewhat redundantly - the authoring process is repetitive.
Proposed Solution: Allow the registerType()
method called in the node's .js
file to accept an optional third parameter that contains the object normally seen in the .html
file. Each item in the defaults
attribute could have extra data for helpText
, label
, types
, and buttons
. A function in the NR runtime could then generate the HTML for these inputs using it's standard input types and classes.
Known blocks: It needs to be backwards compatible with existing nodes and complex inputs still need to be supported. For this reason, checking for a HTML file should be done before processing the new UI object. The UI object could then be ignored if a HTML file is present.
Example (lower-case):
//lower-case.js
module.exports = function(RED) {
function LowerCaseNode(config) {
RED.nodes.createNode(this,config);
var node = this;
node.on('input', function(msg) {
msg.payload = msg.payload.toLowerCase();
node.send(msg);
});
}
const LowerCaseUI = {
category: 'function',
color: '#a6bbcf',
defaults: {
name: {value:"",
helpText:"The display name of the node",
label: "Name",
icon: "fa-tag",
types:["str","num","bool"]
}
},
inputs:1,
outputs:1,
icon: "file.png",
label: function() {
return this.name||"lower-case";
}
};
RED.nodes.registerType("lower-case",LowerCaseNode, LowerCaseUI);
}
Rendering Extra Information
Why: The blocks used in Blender and Unreal Blueprints, display extra information that makes them easier to use, such as IO labels, text, thumbnails, or parameter inputs. The status text of a node can be used for a similar purpose, but it's limited to one line of text.
Proposed Solution: image-tools renders image previews by manipulating the editor DOM, but I think it would be more useful to make this available behind an attribute in the same way the color, icon, and label already are. My thinking with inputs is to allow them to be togglable for 'quick change' from the editor sidebar, so only items the user is changing frequently would appear on the flow and these could then automatically trigger a re-deploy when they are changed. When authoring a new node, a quick-change
attribute could be set to 1
for enabled by default, 0
for disabled by default, or -1
for not available to quick-change
.
Known blocks: Complexity.
Type-checking (wires)
Why: The current msg
object can be completely free-form in it's structure, which is great when you know what data to expect across a flow. However, when working with custom nodes, complex data, or large flows it's possible to connect blocks that would pass messages with incompatible data structures.
Proposed Solution: In order to avoid this, a types
attribute could be added to nodes (perhaps in the UI object as mentioned above), that contains an array of either schema.org strings or URLs to custom types. When joining nodes with wires, the appearance of the wire could change based on the result of the type check: from solid to dashed if there might be a type mismatch, or from solid to dotted if there are no matching types. A tooltip to explain the mismatch could also be provided as well. This would be a client-side editor check and not affect runtime behaviour, though similar to bad node configurations, a warning that lists the incompatible wires could be displayed when a deploy is triggered.
Known blocks: backwards-compatibility. To overcome this, types
must be specified on both ends of a wire in order for its appearance to change.
Example:
<!-- custom-node.html-->
<script type="text/javascript">
RED.nodes.registerType('custom-node',{
// ... node definition
inputTypes: ["Text","*"], //an empty string or an asterisk could be used for 'any' type
outputTypes: ["Text"]
});
</script>
Multiple Inputs
Why: msg
attributes can be used to provide everything needed to a node, however it can be difficult to visualise this flow of data when transforms are obscured inside a function
block, or the single output of a node. As in Unreal, being able to visualize which msg
attributes are being set by which other nodes would make understanding complex flows much easier.
Proposed Solution: Allow data attributes to be made available as inputs for the node, possibly by supplying a process
function to the UI object above that would handle parsing a msg
and storing information against the node instance.
Known blocks: backwards compatibility, complexity. How best to get data into these inputs: If msg
objects are used then a race condition could occur where the an input attribute is not set by one message before the msg
that triggers outputs is received. This requires more thought as another solution could be to allow nodes to provide 'constant' outputs that can be read at will rather than only passed through a message, but that is a complex change to make to the current structure.
I'm aware of the complexity of the last three, but I think these ideas together could vastly improve the experience of creating nodes & using nodes and using the automatic HTML generation as a starting point could be a good way to work towards the other extensions.