@node-red/editor-client 4.0.6 → 4.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/public/red/about +14 -0
- package/public/red/red.js +94 -5
- package/public/red/red.min.js +3 -3
- package/public/tours/first-flow.js +0 -82
package/package.json
CHANGED
package/public/red/about
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
#### 4.0.7: Maintenance Release
|
|
2
|
+
|
|
3
|
+
Editor
|
|
4
|
+
|
|
5
|
+
- Fix config node sort order when importing (#5000) @knolleary
|
|
6
|
+
|
|
7
|
+
#### 4.0.7: Maintenance Release
|
|
8
|
+
|
|
9
|
+
Editor
|
|
10
|
+
|
|
11
|
+
- Fix def can be undefined if the type is missing (#4997) @GogoVega
|
|
12
|
+
- Fix the user list of nested config node (#4995) @GogoVega
|
|
13
|
+
- Support custom login message and button (#4993) @knolleary
|
|
14
|
+
|
|
1
15
|
#### 4.0.6: Maintenance Release
|
|
2
16
|
|
|
3
17
|
Editor
|
package/public/red/red.js
CHANGED
|
@@ -1834,6 +1834,37 @@ RED.user = (function() {
|
|
|
1834
1834
|
}
|
|
1835
1835
|
|
|
1836
1836
|
|
|
1837
|
+
} else {
|
|
1838
|
+
if (data.prompts) {
|
|
1839
|
+
if (data.loginMessage) {
|
|
1840
|
+
const sessionMessages = $("<div/>",{class:"form-row",style:"text-align: center"}).appendTo("#node-dialog-login-fields");
|
|
1841
|
+
$('<div>').text(data.loginMessage).appendTo(sessionMessages);
|
|
1842
|
+
}
|
|
1843
|
+
|
|
1844
|
+
i = 0;
|
|
1845
|
+
for (;i<data.prompts.length;i++) {
|
|
1846
|
+
var field = data.prompts[i];
|
|
1847
|
+
var row = $("<div/>",{class:"form-row",style:"text-align: center"}).appendTo("#node-dialog-login-fields");
|
|
1848
|
+
var loginButton = $('<a href="#" class="red-ui-button"></a>',{style: "padding: 10px"}).appendTo(row).on("click", function() {
|
|
1849
|
+
document.location = field.url;
|
|
1850
|
+
});
|
|
1851
|
+
if (field.image) {
|
|
1852
|
+
$("<img>",{src:field.image}).appendTo(loginButton);
|
|
1853
|
+
} else if (field.label) {
|
|
1854
|
+
var label = $('<span></span>').text(field.label);
|
|
1855
|
+
if (field.icon) {
|
|
1856
|
+
$('<i></i>',{class: "fa fa-2x "+field.icon, style:"vertical-align: middle"}).appendTo(loginButton);
|
|
1857
|
+
label.css({
|
|
1858
|
+
"verticalAlign":"middle",
|
|
1859
|
+
"marginLeft":"8px"
|
|
1860
|
+
});
|
|
1861
|
+
|
|
1862
|
+
}
|
|
1863
|
+
label.appendTo(loginButton);
|
|
1864
|
+
}
|
|
1865
|
+
loginButton.button();
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1837
1868
|
}
|
|
1838
1869
|
if (opts.cancelable) {
|
|
1839
1870
|
$("#node-dialog-login-cancel").button().on("click", function( event ) {
|
|
@@ -5129,12 +5160,15 @@ RED.nodes = (function() {
|
|
|
5129
5160
|
}
|
|
5130
5161
|
n["_"] = RED._;
|
|
5131
5162
|
}
|
|
5163
|
+
|
|
5164
|
+
// Both node and config node can use a config node
|
|
5165
|
+
updateConfigNodeUsers(newNode, { action: "add" });
|
|
5166
|
+
|
|
5132
5167
|
if (n._def.category == "config") {
|
|
5133
5168
|
configNodes[n.id] = newNode;
|
|
5134
5169
|
} else {
|
|
5135
5170
|
if (n.wires && (n.wires.length > n.outputs)) { n.outputs = n.wires.length; }
|
|
5136
5171
|
n.dirty = true;
|
|
5137
|
-
updateConfigNodeUsers(newNode, { action: "add" });
|
|
5138
5172
|
if (n._def.category == "subflows" && typeof n.i === "undefined") {
|
|
5139
5173
|
var nextId = 0;
|
|
5140
5174
|
RED.nodes.eachNode(function(node) {
|
|
@@ -5196,9 +5230,11 @@ RED.nodes = (function() {
|
|
|
5196
5230
|
var removedLinks = [];
|
|
5197
5231
|
var removedNodes = [];
|
|
5198
5232
|
var node;
|
|
5233
|
+
|
|
5199
5234
|
if (id in configNodes) {
|
|
5200
5235
|
node = configNodes[id];
|
|
5201
5236
|
delete configNodes[id];
|
|
5237
|
+
updateConfigNodeUsers(node, { action: "remove" });
|
|
5202
5238
|
RED.events.emit('nodes:remove',node);
|
|
5203
5239
|
RED.workspaces.refresh();
|
|
5204
5240
|
} else if (allNodes.hasNode(id)) {
|
|
@@ -5208,6 +5244,8 @@ RED.nodes = (function() {
|
|
|
5208
5244
|
removedLinks = links.filter(function(l) { return (l.source === node) || (l.target === node); });
|
|
5209
5245
|
removedLinks.forEach(removeLink);
|
|
5210
5246
|
updateConfigNodeUsers(node, { action: "remove" });
|
|
5247
|
+
|
|
5248
|
+
// TODO: Legacy code for exclusive config node
|
|
5211
5249
|
var updatedConfigNode = false;
|
|
5212
5250
|
for (var d in node._def.defaults) {
|
|
5213
5251
|
if (node._def.defaults.hasOwnProperty(d)) {
|
|
@@ -6514,6 +6552,8 @@ RED.nodes = (function() {
|
|
|
6514
6552
|
activeWorkspace = RED.workspaces.active();
|
|
6515
6553
|
}
|
|
6516
6554
|
|
|
6555
|
+
const pendingConfigNodes = []
|
|
6556
|
+
const pendingConfigNodeIds = new Set()
|
|
6517
6557
|
// Find all config nodes and add them
|
|
6518
6558
|
for (i=0;i<newNodes.length;i++) {
|
|
6519
6559
|
n = newNodes[i];
|
|
@@ -6573,7 +6613,8 @@ RED.nodes = (function() {
|
|
|
6573
6613
|
type:n.type,
|
|
6574
6614
|
info: n.info,
|
|
6575
6615
|
users:[],
|
|
6576
|
-
_config:{}
|
|
6616
|
+
_config:{},
|
|
6617
|
+
_configNodeReferences: new Set()
|
|
6577
6618
|
};
|
|
6578
6619
|
if (!n.z) {
|
|
6579
6620
|
delete configNode.z;
|
|
@@ -6588,6 +6629,9 @@ RED.nodes = (function() {
|
|
|
6588
6629
|
if (def.defaults.hasOwnProperty(d)) {
|
|
6589
6630
|
configNode[d] = n[d];
|
|
6590
6631
|
configNode._config[d] = JSON.stringify(n[d]);
|
|
6632
|
+
if (def.defaults[d].type) {
|
|
6633
|
+
configNode._configNodeReferences.add(n[d])
|
|
6634
|
+
}
|
|
6591
6635
|
}
|
|
6592
6636
|
}
|
|
6593
6637
|
if (def.hasOwnProperty('credentials') && n.hasOwnProperty('credentials')) {
|
|
@@ -6604,11 +6648,55 @@ RED.nodes = (function() {
|
|
|
6604
6648
|
configNode.id = getID();
|
|
6605
6649
|
}
|
|
6606
6650
|
node_map[n.id] = configNode;
|
|
6607
|
-
|
|
6651
|
+
pendingConfigNodes.push(configNode);
|
|
6652
|
+
pendingConfigNodeIds.add(configNode.id)
|
|
6608
6653
|
}
|
|
6609
6654
|
}
|
|
6610
6655
|
}
|
|
6611
6656
|
|
|
6657
|
+
// We need to sort new_nodes (which only contains config nodes at this point)
|
|
6658
|
+
// to ensure they get added in the right order. If NodeA depends on NodeB, then
|
|
6659
|
+
// NodeB must be added first.
|
|
6660
|
+
|
|
6661
|
+
// Limit us to 5 full iterations of the list - this should be more than
|
|
6662
|
+
// enough to process the list as config->config node relationships are
|
|
6663
|
+
// not very common
|
|
6664
|
+
let iterationLimit = pendingConfigNodes.length * 5
|
|
6665
|
+
const handledConfigNodes = new Set()
|
|
6666
|
+
while (pendingConfigNodes.length > 0 && iterationLimit > 0) {
|
|
6667
|
+
const node = pendingConfigNodes.shift()
|
|
6668
|
+
let hasPending = false
|
|
6669
|
+
// Loop through the nodes referenced by this node to see if anything
|
|
6670
|
+
// is pending
|
|
6671
|
+
node._configNodeReferences.forEach(id => {
|
|
6672
|
+
if (pendingConfigNodeIds.has(id) && !handledConfigNodes.has(id)) {
|
|
6673
|
+
// This reference is for a node we know is in this import, but
|
|
6674
|
+
// it isn't added yet - flag as pending
|
|
6675
|
+
hasPending = true
|
|
6676
|
+
}
|
|
6677
|
+
})
|
|
6678
|
+
if (!hasPending) {
|
|
6679
|
+
// This node has no pending config node references - safe to add
|
|
6680
|
+
delete node._configNodeReferences
|
|
6681
|
+
new_nodes.push(node)
|
|
6682
|
+
handledConfigNodes.add(node.id)
|
|
6683
|
+
} else {
|
|
6684
|
+
// This node has pending config node references
|
|
6685
|
+
// Put to the back of the queue
|
|
6686
|
+
pendingConfigNodes.push(node)
|
|
6687
|
+
}
|
|
6688
|
+
iterationLimit--
|
|
6689
|
+
}
|
|
6690
|
+
if (pendingConfigNodes.length > 0) {
|
|
6691
|
+
// We exceeded the iteration count. Could be due to reference loops
|
|
6692
|
+
// between the config nodes. At this point, just add the remaining
|
|
6693
|
+
// nodes as-is
|
|
6694
|
+
pendingConfigNodes.forEach(node => {
|
|
6695
|
+
delete node._configNodeReferences
|
|
6696
|
+
new_nodes.push(node)
|
|
6697
|
+
})
|
|
6698
|
+
}
|
|
6699
|
+
|
|
6612
6700
|
// Find regular flow nodes and subflow instances
|
|
6613
6701
|
for (i=0;i<newNodes.length;i++) {
|
|
6614
6702
|
n = newNodes[i];
|
|
@@ -6779,13 +6867,13 @@ RED.nodes = (function() {
|
|
|
6779
6867
|
node.type = "unknown";
|
|
6780
6868
|
}
|
|
6781
6869
|
if (node._def.category != "config") {
|
|
6782
|
-
if (n.hasOwnProperty('inputs') &&
|
|
6870
|
+
if (n.hasOwnProperty('inputs') && node._def.defaults.hasOwnProperty("inputs")) {
|
|
6783
6871
|
node.inputs = parseInt(n.inputs, 10);
|
|
6784
6872
|
node._config.inputs = JSON.stringify(n.inputs);
|
|
6785
6873
|
} else {
|
|
6786
6874
|
node.inputs = node._def.inputs;
|
|
6787
6875
|
}
|
|
6788
|
-
if (n.hasOwnProperty('outputs') &&
|
|
6876
|
+
if (n.hasOwnProperty('outputs') && node._def.defaults.hasOwnProperty("outputs")) {
|
|
6789
6877
|
node.outputs = parseInt(n.outputs, 10);
|
|
6790
6878
|
node._config.outputs = JSON.stringify(n.outputs);
|
|
6791
6879
|
} else {
|
|
@@ -7146,6 +7234,7 @@ RED.nodes = (function() {
|
|
|
7146
7234
|
var property = node._def.defaults[d];
|
|
7147
7235
|
if (property.type) {
|
|
7148
7236
|
var type = registry.getNodeType(property.type);
|
|
7237
|
+
// Need to ensure the type is a config node to not treat links nodes
|
|
7149
7238
|
if (type && type.category == "config") {
|
|
7150
7239
|
var configNode = configNodes[node[d]];
|
|
7151
7240
|
if (configNode) {
|