@node-red/editor-client 4.0.7 → 4.0.9
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 +32 -0
- package/public/red/red.js +235 -110
- package/public/red/red.min.js +3 -3
- package/public/red/style.min.css +1 -1
package/public/red/red.js
CHANGED
|
@@ -2017,10 +2017,10 @@ RED.user = (function() {
|
|
|
2017
2017
|
userIcon.css({
|
|
2018
2018
|
backgroundImage: "url("+user.image+")",
|
|
2019
2019
|
})
|
|
2020
|
-
} else if (user.anonymous) {
|
|
2020
|
+
} else if (user.anonymous || (!user.username && !user.email)) {
|
|
2021
2021
|
$('<i class="fa fa-user"></i>').appendTo(userIcon);
|
|
2022
2022
|
} else {
|
|
2023
|
-
$('<span>').text(user.username.substring(0,2)).appendTo(userIcon);
|
|
2023
|
+
$('<span>').text((user.username || user.email).substring(0,2)).appendTo(userIcon);
|
|
2024
2024
|
}
|
|
2025
2025
|
if (user.profileColor !== undefined) {
|
|
2026
2026
|
userIcon.addClass('red-ui-user-profile-color-' + user.profileColor)
|
|
@@ -2715,14 +2715,13 @@ RED.comms = (function() {
|
|
|
2715
2715
|
anonIconBody.setAttribute("d",`M ${radius/2} ${radius/2 + 5} h -2.5 c -2 1 -2 -5 0.5 -4.5 c 2 1 2 1 4 0 c 2.5 -0.5 2.5 5.5 0 4.5 z`);
|
|
2716
2716
|
group.appendChild(anonIconBody)
|
|
2717
2717
|
} else {
|
|
2718
|
-
const labelText = user.username ? user.username.substring(0,2) : user
|
|
2719
2718
|
const label = document.createElementNS("http://www.w3.org/2000/svg","text");
|
|
2720
|
-
if (user.username) {
|
|
2719
|
+
if (user.username || user.email) {
|
|
2721
2720
|
label.setAttribute("class","red-ui-multiplayer-annotation-label");
|
|
2722
|
-
label.textContent = user.username.substring(0,2)
|
|
2721
|
+
label.textContent = (user.username || user.email).substring(0,2)
|
|
2723
2722
|
} else {
|
|
2724
2723
|
label.setAttribute("class","red-ui-multiplayer-annotation-label red-ui-multiplayer-user-count")
|
|
2725
|
-
label.textContent =
|
|
2724
|
+
label.textContent = 'nr'
|
|
2726
2725
|
}
|
|
2727
2726
|
label.setAttribute("text-anchor", "middle")
|
|
2728
2727
|
label.setAttribute("x",radius/2);
|
|
@@ -6552,6 +6551,8 @@ RED.nodes = (function() {
|
|
|
6552
6551
|
activeWorkspace = RED.workspaces.active();
|
|
6553
6552
|
}
|
|
6554
6553
|
|
|
6554
|
+
const pendingConfigNodes = []
|
|
6555
|
+
const pendingConfigNodeIds = new Set()
|
|
6555
6556
|
// Find all config nodes and add them
|
|
6556
6557
|
for (i=0;i<newNodes.length;i++) {
|
|
6557
6558
|
n = newNodes[i];
|
|
@@ -6611,7 +6612,8 @@ RED.nodes = (function() {
|
|
|
6611
6612
|
type:n.type,
|
|
6612
6613
|
info: n.info,
|
|
6613
6614
|
users:[],
|
|
6614
|
-
_config:{}
|
|
6615
|
+
_config:{},
|
|
6616
|
+
_configNodeReferences: new Set()
|
|
6615
6617
|
};
|
|
6616
6618
|
if (!n.z) {
|
|
6617
6619
|
delete configNode.z;
|
|
@@ -6626,6 +6628,9 @@ RED.nodes = (function() {
|
|
|
6626
6628
|
if (def.defaults.hasOwnProperty(d)) {
|
|
6627
6629
|
configNode[d] = n[d];
|
|
6628
6630
|
configNode._config[d] = JSON.stringify(n[d]);
|
|
6631
|
+
if (def.defaults[d].type) {
|
|
6632
|
+
configNode._configNodeReferences.add(n[d])
|
|
6633
|
+
}
|
|
6629
6634
|
}
|
|
6630
6635
|
}
|
|
6631
6636
|
if (def.hasOwnProperty('credentials') && n.hasOwnProperty('credentials')) {
|
|
@@ -6642,25 +6647,54 @@ RED.nodes = (function() {
|
|
|
6642
6647
|
configNode.id = getID();
|
|
6643
6648
|
}
|
|
6644
6649
|
node_map[n.id] = configNode;
|
|
6645
|
-
|
|
6650
|
+
pendingConfigNodes.push(configNode);
|
|
6651
|
+
pendingConfigNodeIds.add(configNode.id)
|
|
6646
6652
|
}
|
|
6647
6653
|
}
|
|
6648
6654
|
}
|
|
6649
6655
|
|
|
6650
|
-
//
|
|
6651
|
-
//
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6656
|
+
// We need to sort new_nodes (which only contains config nodes at this point)
|
|
6657
|
+
// to ensure they get added in the right order. If NodeA depends on NodeB, then
|
|
6658
|
+
// NodeB must be added first.
|
|
6659
|
+
|
|
6660
|
+
// Limit us to 5 full iterations of the list - this should be more than
|
|
6661
|
+
// enough to process the list as config->config node relationships are
|
|
6662
|
+
// not very common
|
|
6663
|
+
let iterationLimit = pendingConfigNodes.length * 5
|
|
6664
|
+
const handledConfigNodes = new Set()
|
|
6665
|
+
while (pendingConfigNodes.length > 0 && iterationLimit > 0) {
|
|
6666
|
+
const node = pendingConfigNodes.shift()
|
|
6667
|
+
let hasPending = false
|
|
6668
|
+
// Loop through the nodes referenced by this node to see if anything
|
|
6669
|
+
// is pending
|
|
6670
|
+
node._configNodeReferences.forEach(id => {
|
|
6671
|
+
if (pendingConfigNodeIds.has(id) && !handledConfigNodes.has(id)) {
|
|
6672
|
+
// This reference is for a node we know is in this import, but
|
|
6673
|
+
// it isn't added yet - flag as pending
|
|
6674
|
+
hasPending = true
|
|
6659
6675
|
}
|
|
6660
|
-
}
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6676
|
+
})
|
|
6677
|
+
if (!hasPending) {
|
|
6678
|
+
// This node has no pending config node references - safe to add
|
|
6679
|
+
delete node._configNodeReferences
|
|
6680
|
+
new_nodes.push(node)
|
|
6681
|
+
handledConfigNodes.add(node.id)
|
|
6682
|
+
} else {
|
|
6683
|
+
// This node has pending config node references
|
|
6684
|
+
// Put to the back of the queue
|
|
6685
|
+
pendingConfigNodes.push(node)
|
|
6686
|
+
}
|
|
6687
|
+
iterationLimit--
|
|
6688
|
+
}
|
|
6689
|
+
if (pendingConfigNodes.length > 0) {
|
|
6690
|
+
// We exceeded the iteration count. Could be due to reference loops
|
|
6691
|
+
// between the config nodes. At this point, just add the remaining
|
|
6692
|
+
// nodes as-is
|
|
6693
|
+
pendingConfigNodes.forEach(node => {
|
|
6694
|
+
delete node._configNodeReferences
|
|
6695
|
+
new_nodes.push(node)
|
|
6696
|
+
})
|
|
6697
|
+
}
|
|
6664
6698
|
|
|
6665
6699
|
// Find regular flow nodes and subflow instances
|
|
6666
6700
|
for (i=0;i<newNodes.length;i++) {
|
|
@@ -9760,7 +9794,7 @@ RED.utils = (function() {
|
|
|
9760
9794
|
var pinnedPaths = {};
|
|
9761
9795
|
var formattedPaths = {};
|
|
9762
9796
|
|
|
9763
|
-
function addMessageControls(obj,sourceId,key,msg,rootPath,strippedKey,extraTools) {
|
|
9797
|
+
function addMessageControls(obj,sourceId,key,msg,rootPath,strippedKey,extraTools,enablePinning) {
|
|
9764
9798
|
if (!pinnedPaths.hasOwnProperty(sourceId)) {
|
|
9765
9799
|
pinnedPaths[sourceId] = {}
|
|
9766
9800
|
}
|
|
@@ -9780,7 +9814,7 @@ RED.utils = (function() {
|
|
|
9780
9814
|
RED.clipboard.copyText(msg,copyPayload,"clipboard.copyMessageValue");
|
|
9781
9815
|
})
|
|
9782
9816
|
RED.popover.tooltip(copyPayload,RED._("node-red:debug.sidebar.copyPayload"));
|
|
9783
|
-
if (strippedKey !== undefined && strippedKey !== '') {
|
|
9817
|
+
if (enablePinning && strippedKey !== undefined && strippedKey !== '') {
|
|
9784
9818
|
var isPinned = pinnedPaths[sourceId].hasOwnProperty(strippedKey);
|
|
9785
9819
|
|
|
9786
9820
|
var pinPath = $('<button class="red-ui-button red-ui-button-small red-ui-debug-msg-tools-pin"><i class="fa fa-map-pin"></i></button>').appendTo(tools).on("click", function(e) {
|
|
@@ -9811,13 +9845,16 @@ RED.utils = (function() {
|
|
|
9811
9845
|
}
|
|
9812
9846
|
}
|
|
9813
9847
|
}
|
|
9814
|
-
function checkExpanded(strippedKey,expandPaths,minRange,maxRange) {
|
|
9848
|
+
function checkExpanded(strippedKey, expandPaths, { minRange, maxRange, expandLeafNodes }) {
|
|
9815
9849
|
if (expandPaths && expandPaths.length > 0) {
|
|
9816
9850
|
if (strippedKey === '' && minRange === undefined) {
|
|
9817
9851
|
return true;
|
|
9818
9852
|
}
|
|
9819
9853
|
for (var i=0;i<expandPaths.length;i++) {
|
|
9820
9854
|
var p = expandPaths[i];
|
|
9855
|
+
if (expandLeafNodes && p === strippedKey) {
|
|
9856
|
+
return true
|
|
9857
|
+
}
|
|
9821
9858
|
if (p.indexOf(strippedKey) === 0 && (p[strippedKey.length] === "." || p[strippedKey.length] === "[") ) {
|
|
9822
9859
|
|
|
9823
9860
|
if (minRange !== undefined && p[strippedKey.length] === "[") {
|
|
@@ -9924,6 +9961,8 @@ RED.utils = (function() {
|
|
|
9924
9961
|
var sourceId = options.sourceId;
|
|
9925
9962
|
var rootPath = options.rootPath;
|
|
9926
9963
|
var expandPaths = options.expandPaths;
|
|
9964
|
+
const enablePinning = options.enablePinning
|
|
9965
|
+
const expandLeafNodes = options.expandLeafNodes;
|
|
9927
9966
|
var ontoggle = options.ontoggle;
|
|
9928
9967
|
var exposeApi = options.exposeApi;
|
|
9929
9968
|
var tools = options.tools;
|
|
@@ -9946,11 +9985,11 @@ RED.utils = (function() {
|
|
|
9946
9985
|
}
|
|
9947
9986
|
header = $('<span class="red-ui-debug-msg-row"></span>').appendTo(element);
|
|
9948
9987
|
if (sourceId) {
|
|
9949
|
-
addMessageControls(header,sourceId,path,obj,rootPath,strippedKey,tools);
|
|
9988
|
+
addMessageControls(header,sourceId,path,obj,rootPath,strippedKey,tools, enablePinning);
|
|
9950
9989
|
}
|
|
9951
9990
|
if (!key) {
|
|
9952
9991
|
element.addClass("red-ui-debug-msg-top-level");
|
|
9953
|
-
if (sourceId) {
|
|
9992
|
+
if (sourceId && !expandPaths) {
|
|
9954
9993
|
var pinned = pinnedPaths[sourceId];
|
|
9955
9994
|
expandPaths = [];
|
|
9956
9995
|
if (pinned) {
|
|
@@ -10006,7 +10045,7 @@ RED.utils = (function() {
|
|
|
10006
10045
|
$('<span class="red-ui-debug-msg-type-meta red-ui-debug-msg-object-type-header"></span>').text(typeHint||'string').appendTo(header);
|
|
10007
10046
|
var row = $('<div class="red-ui-debug-msg-object-entry collapsed"></div>').appendTo(element);
|
|
10008
10047
|
$('<pre class="red-ui-debug-msg-type-string"></pre>').text(obj).appendTo(row);
|
|
10009
|
-
},function(state) {if (ontoggle) { ontoggle(path,state);}}, checkExpanded(strippedKey,expandPaths));
|
|
10048
|
+
},function(state) {if (ontoggle) { ontoggle(path,state);}}, checkExpanded(strippedKey, expandPaths, { expandLeafNodes }));
|
|
10010
10049
|
}
|
|
10011
10050
|
e = $('<span class="red-ui-debug-msg-type-string red-ui-debug-msg-object-header"></span>').html('"'+formatString(sanitize(obj))+'"').appendTo(entryObj);
|
|
10012
10051
|
if (/^#[0-9a-f]{6}$/i.test(obj)) {
|
|
@@ -10122,14 +10161,16 @@ RED.utils = (function() {
|
|
|
10122
10161
|
typeHint: type==='buffer'?'hex':false,
|
|
10123
10162
|
hideKey: false,
|
|
10124
10163
|
path: path+"["+i+"]",
|
|
10125
|
-
sourceId
|
|
10126
|
-
rootPath
|
|
10127
|
-
expandPaths
|
|
10128
|
-
|
|
10129
|
-
|
|
10164
|
+
sourceId,
|
|
10165
|
+
rootPath,
|
|
10166
|
+
expandPaths,
|
|
10167
|
+
expandLeafNodes,
|
|
10168
|
+
ontoggle,
|
|
10169
|
+
exposeApi,
|
|
10130
10170
|
// tools: tools // Do not pass tools down as we
|
|
10131
10171
|
// keep them attached to the top-level header
|
|
10132
10172
|
nodeSelector: options.nodeSelector,
|
|
10173
|
+
enablePinning
|
|
10133
10174
|
}
|
|
10134
10175
|
).appendTo(row);
|
|
10135
10176
|
}
|
|
@@ -10153,21 +10194,23 @@ RED.utils = (function() {
|
|
|
10153
10194
|
typeHint: type==='buffer'?'hex':false,
|
|
10154
10195
|
hideKey: false,
|
|
10155
10196
|
path: path+"["+i+"]",
|
|
10156
|
-
sourceId
|
|
10157
|
-
rootPath
|
|
10158
|
-
expandPaths
|
|
10159
|
-
|
|
10160
|
-
|
|
10197
|
+
sourceId,
|
|
10198
|
+
rootPath,
|
|
10199
|
+
expandPaths,
|
|
10200
|
+
expandLeafNodes,
|
|
10201
|
+
ontoggle,
|
|
10202
|
+
exposeApi,
|
|
10161
10203
|
// tools: tools // Do not pass tools down as we
|
|
10162
10204
|
// keep them attached to the top-level header
|
|
10163
10205
|
nodeSelector: options.nodeSelector,
|
|
10206
|
+
enablePinning
|
|
10164
10207
|
}
|
|
10165
10208
|
).appendTo(row);
|
|
10166
10209
|
}
|
|
10167
10210
|
}
|
|
10168
10211
|
})(),
|
|
10169
10212
|
(function() { var path = path+"["+i+"]"; return function(state) {if (ontoggle) { ontoggle(path,state);}}})(),
|
|
10170
|
-
checkExpanded(strippedKey,expandPaths,minRange,Math.min(fullLength-1,(minRange+9))));
|
|
10213
|
+
checkExpanded(strippedKey,expandPaths,{ minRange, maxRange: Math.min(fullLength-1,(minRange+9)), expandLeafNodes}));
|
|
10171
10214
|
$('<span class="red-ui-debug-msg-object-key"></span>').html("["+minRange+" … "+Math.min(fullLength-1,(minRange+9))+"]").appendTo(header);
|
|
10172
10215
|
}
|
|
10173
10216
|
if (fullLength < originalLength) {
|
|
@@ -10176,7 +10219,7 @@ RED.utils = (function() {
|
|
|
10176
10219
|
}
|
|
10177
10220
|
},
|
|
10178
10221
|
function(state) {if (ontoggle) { ontoggle(path,state);}},
|
|
10179
|
-
checkExpanded(strippedKey,expandPaths));
|
|
10222
|
+
checkExpanded(strippedKey, expandPaths, { expandLeafNodes }));
|
|
10180
10223
|
}
|
|
10181
10224
|
} else if (typeof obj === 'object') {
|
|
10182
10225
|
element.addClass('collapsed');
|
|
@@ -10210,14 +10253,16 @@ RED.utils = (function() {
|
|
|
10210
10253
|
typeHint: false,
|
|
10211
10254
|
hideKey: false,
|
|
10212
10255
|
path: newPath,
|
|
10213
|
-
sourceId
|
|
10214
|
-
rootPath
|
|
10215
|
-
expandPaths
|
|
10216
|
-
|
|
10217
|
-
|
|
10256
|
+
sourceId,
|
|
10257
|
+
rootPath,
|
|
10258
|
+
expandPaths,
|
|
10259
|
+
expandLeafNodes,
|
|
10260
|
+
ontoggle,
|
|
10261
|
+
exposeApi,
|
|
10218
10262
|
// tools: tools // Do not pass tools down as we
|
|
10219
10263
|
// keep them attached to the top-level header
|
|
10220
10264
|
nodeSelector: options.nodeSelector,
|
|
10265
|
+
enablePinning
|
|
10221
10266
|
}
|
|
10222
10267
|
).appendTo(row);
|
|
10223
10268
|
}
|
|
@@ -10226,7 +10271,7 @@ RED.utils = (function() {
|
|
|
10226
10271
|
}
|
|
10227
10272
|
},
|
|
10228
10273
|
function(state) {if (ontoggle) { ontoggle(path,state);}},
|
|
10229
|
-
checkExpanded(strippedKey,expandPaths));
|
|
10274
|
+
checkExpanded(strippedKey, expandPaths, { expandLeafNodes }));
|
|
10230
10275
|
}
|
|
10231
10276
|
if (key) {
|
|
10232
10277
|
$('<span class="red-ui-debug-msg-type-meta"></span>').text(type).appendTo(entryObj);
|
|
@@ -15254,6 +15299,7 @@ RED.stack = (function() {
|
|
|
15254
15299
|
pre: value.substring(0,idx),
|
|
15255
15300
|
match: value.substring(idx,idx+len),
|
|
15256
15301
|
post: value.substring(idx+len),
|
|
15302
|
+
exact: idx === 0 && value.length === searchValue.length
|
|
15257
15303
|
}
|
|
15258
15304
|
}
|
|
15259
15305
|
function generateSpans(match) {
|
|
@@ -15274,7 +15320,7 @@ RED.stack = (function() {
|
|
|
15274
15320
|
const srcMatch = getMatch(optSrc, val);
|
|
15275
15321
|
if (valMatch.found || srcMatch.found) {
|
|
15276
15322
|
const element = $('<div>',{style: "display: flex"});
|
|
15277
|
-
const valEl = $('<div/>',{
|
|
15323
|
+
const valEl = $('<div/>',{ class: "red-ui-autoComplete-completion" });
|
|
15278
15324
|
valEl.append(generateSpans(valMatch));
|
|
15279
15325
|
valEl.appendTo(element);
|
|
15280
15326
|
if (optSrc) {
|
|
@@ -15350,7 +15396,7 @@ RED.stack = (function() {
|
|
|
15350
15396
|
if (valMatch.found) {
|
|
15351
15397
|
const optSrc = envVarsMap[v]
|
|
15352
15398
|
const element = $('<div>',{style: "display: flex"});
|
|
15353
|
-
const valEl = $('<div/>',{
|
|
15399
|
+
const valEl = $('<div/>',{ class: "red-ui-autoComplete-completion" });
|
|
15354
15400
|
valEl.append(generateSpans(valMatch))
|
|
15355
15401
|
valEl.appendTo(element)
|
|
15356
15402
|
|
|
@@ -15392,7 +15438,7 @@ RED.stack = (function() {
|
|
|
15392
15438
|
const that = this
|
|
15393
15439
|
const getContextKeysFromRuntime = function(scope, store, searchKey, done) {
|
|
15394
15440
|
contextKnownKeys[scope] = contextKnownKeys[scope] || {}
|
|
15395
|
-
contextKnownKeys[scope][store] = contextKnownKeys[scope][store] || new
|
|
15441
|
+
contextKnownKeys[scope][store] = contextKnownKeys[scope][store] || new Map()
|
|
15396
15442
|
if (searchKey.length > 0) {
|
|
15397
15443
|
try {
|
|
15398
15444
|
RED.utils.normalisePropertyExpression(searchKey)
|
|
@@ -15414,11 +15460,12 @@ RED.stack = (function() {
|
|
|
15414
15460
|
const result = data[store] || {}
|
|
15415
15461
|
const keys = result.keys || []
|
|
15416
15462
|
const keyPrefix = searchKey + (searchKey.length > 0 ? '.' : '')
|
|
15417
|
-
keys.forEach(
|
|
15463
|
+
keys.forEach(keyInfo => {
|
|
15464
|
+
const key = keyInfo.key
|
|
15418
15465
|
if (/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(key)) {
|
|
15419
|
-
contextKnownKeys[scope][store].
|
|
15466
|
+
contextKnownKeys[scope][store].set(keyPrefix + key, keyInfo)
|
|
15420
15467
|
} else {
|
|
15421
|
-
contextKnownKeys[scope][store].
|
|
15468
|
+
contextKnownKeys[scope][store].set(searchKey + "[\""+key.replace(/"/,"\\\"")+"\"]", keyInfo)
|
|
15422
15469
|
}
|
|
15423
15470
|
})
|
|
15424
15471
|
done()
|
|
@@ -15433,14 +15480,14 @@ RED.stack = (function() {
|
|
|
15433
15480
|
// Get the flow id of the node we're editing
|
|
15434
15481
|
const editStack = RED.editor.getEditStack()
|
|
15435
15482
|
if (editStack.length === 0) {
|
|
15436
|
-
done(
|
|
15483
|
+
done(new Map())
|
|
15437
15484
|
return
|
|
15438
15485
|
}
|
|
15439
15486
|
const editingNode = editStack.pop()
|
|
15440
15487
|
if (editingNode.z) {
|
|
15441
15488
|
scope = `${scope}/${editingNode.z}`
|
|
15442
15489
|
} else {
|
|
15443
|
-
done(
|
|
15490
|
+
done(new Map())
|
|
15444
15491
|
return
|
|
15445
15492
|
}
|
|
15446
15493
|
}
|
|
@@ -15460,17 +15507,29 @@ RED.stack = (function() {
|
|
|
15460
15507
|
return function(val, done) {
|
|
15461
15508
|
getContextKeys(val, function (keys) {
|
|
15462
15509
|
const matches = []
|
|
15463
|
-
keys.forEach(v => {
|
|
15510
|
+
keys.forEach((keyInfo, v) => {
|
|
15464
15511
|
let optVal = v
|
|
15465
15512
|
let valMatch = getMatch(optVal, val);
|
|
15466
|
-
if (!valMatch.found && val.length > 0
|
|
15467
|
-
|
|
15468
|
-
|
|
15469
|
-
|
|
15513
|
+
if (!valMatch.found && val.length > 0) {
|
|
15514
|
+
if (val.endsWith('.')) {
|
|
15515
|
+
// Search key ends in '.' - but doesn't match. Check again
|
|
15516
|
+
// with [" at the end instead so we match bracket notation
|
|
15517
|
+
valMatch = getMatch(optVal, val.substring(0, val.length - 1) + '["')
|
|
15518
|
+
// } else if (val.endsWith('[') && /^array/.test(keyInfo.format)) {
|
|
15519
|
+
// console.log('this case')
|
|
15520
|
+
}
|
|
15470
15521
|
}
|
|
15471
15522
|
if (valMatch.found) {
|
|
15472
15523
|
const element = $('<div>',{style: "display: flex"});
|
|
15473
|
-
const valEl = $('<div/>',{
|
|
15524
|
+
const valEl = $('<div/>',{ class: "red-ui-autoComplete-completion" });
|
|
15525
|
+
// if (keyInfo.format) {
|
|
15526
|
+
// valMatch.post += ' ' + keyInfo.format
|
|
15527
|
+
// }
|
|
15528
|
+
if (valMatch.exact && /^array/.test(keyInfo.format)) {
|
|
15529
|
+
valMatch.post += `[0-${keyInfo.length}]`
|
|
15530
|
+
optVal += '['
|
|
15531
|
+
|
|
15532
|
+
}
|
|
15474
15533
|
valEl.append(generateSpans(valMatch))
|
|
15475
15534
|
valEl.appendTo(element)
|
|
15476
15535
|
matches.push({
|
|
@@ -16758,7 +16817,8 @@ RED.stack = (function() {
|
|
|
16758
16817
|
if (tooltip) {
|
|
16759
16818
|
tooltip.setContent(valid);
|
|
16760
16819
|
} else {
|
|
16761
|
-
|
|
16820
|
+
const target = this.typeMap[type]?.options ? this.optionSelectLabel : this.elementDiv;
|
|
16821
|
+
tooltip = RED.popover.tooltip(target, valid);
|
|
16762
16822
|
this.element.data("tooltip", tooltip);
|
|
16763
16823
|
}
|
|
16764
16824
|
}
|
|
@@ -16990,7 +17050,7 @@ RED.stack = (function() {
|
|
|
16990
17050
|
}
|
|
16991
17051
|
this.menu = RED.popover.menu({
|
|
16992
17052
|
tabSelect: true,
|
|
16993
|
-
width: 300,
|
|
17053
|
+
width: Math.max(300, this.element.width()),
|
|
16994
17054
|
maxHeight: 200,
|
|
16995
17055
|
class: "red-ui-autoComplete-container",
|
|
16996
17056
|
options: completions,
|
|
@@ -17193,6 +17253,7 @@ RED.deploy = (function() {
|
|
|
17193
17253
|
/**
|
|
17194
17254
|
* options:
|
|
17195
17255
|
* type: "default" - Button with drop-down options - no further customisation available
|
|
17256
|
+
* label: the text to display - default: "Deploy"
|
|
17196
17257
|
* type: "simple" - Button without dropdown. Customisations:
|
|
17197
17258
|
* label: the text to display - default: "Deploy"
|
|
17198
17259
|
* icon : the icon to use. Null removes the icon. default: "red/images/deploy-full-o.svg"
|
|
@@ -17200,13 +17261,14 @@ RED.deploy = (function() {
|
|
|
17200
17261
|
function init(options) {
|
|
17201
17262
|
options = options || {};
|
|
17202
17263
|
var type = options.type || "default";
|
|
17264
|
+
var label = options.label || RED._("deploy.deploy");
|
|
17203
17265
|
|
|
17204
17266
|
if (type == "default") {
|
|
17205
17267
|
$('<li><span class="red-ui-deploy-button-group button-group">'+
|
|
17206
17268
|
'<a id="red-ui-header-button-deploy" class="red-ui-deploy-button disabled" href="#">'+
|
|
17207
17269
|
'<span class="red-ui-deploy-button-content">'+
|
|
17208
17270
|
'<img id="red-ui-header-button-deploy-icon" src="red/images/deploy-full-o.svg"> '+
|
|
17209
|
-
'<span>'+
|
|
17271
|
+
'<span>'+label+'</span>'+
|
|
17210
17272
|
'</span>'+
|
|
17211
17273
|
'<span class="red-ui-deploy-button-spinner hide">'+
|
|
17212
17274
|
'<img src="red/images/spin.svg"/>'+
|
|
@@ -17227,7 +17289,6 @@ RED.deploy = (function() {
|
|
|
17227
17289
|
mainMenuItems.push({id:"deploymenu-item-reload", icon:"red/images/deploy-reload.svg",label:RED._("deploy.restartFlows"),sublabel:RED._("deploy.restartFlowsDesc"),onselect:"core:restart-flows"})
|
|
17228
17290
|
RED.menu.init({id:"red-ui-header-button-deploy-options", options: mainMenuItems });
|
|
17229
17291
|
} else if (type == "simple") {
|
|
17230
|
-
var label = options.label || RED._("deploy.deploy");
|
|
17231
17292
|
var icon = 'red/images/deploy-full-o.svg';
|
|
17232
17293
|
if (options.hasOwnProperty('icon')) {
|
|
17233
17294
|
icon = options.icon;
|
|
@@ -23410,11 +23471,6 @@ RED.view = (function() {
|
|
|
23410
23471
|
var targetGroup = options.group;
|
|
23411
23472
|
var touchTrigger = options.touchTrigger;
|
|
23412
23473
|
|
|
23413
|
-
if (targetGroup) {
|
|
23414
|
-
selectedGroups.add(targetGroup,false);
|
|
23415
|
-
RED.view.redraw();
|
|
23416
|
-
}
|
|
23417
|
-
|
|
23418
23474
|
// `point` is the place in the workspace the mouse has clicked.
|
|
23419
23475
|
// This takes into account scrolling and scaling of the workspace.
|
|
23420
23476
|
var ox = point[0];
|
|
@@ -23736,9 +23792,6 @@ RED.view = (function() {
|
|
|
23736
23792
|
// auto select dropped node - so info shows (if visible)
|
|
23737
23793
|
clearSelection();
|
|
23738
23794
|
nn.selected = true;
|
|
23739
|
-
if (targetGroup) {
|
|
23740
|
-
selectedGroups.add(targetGroup,false);
|
|
23741
|
-
}
|
|
23742
23795
|
movingSet.add(nn);
|
|
23743
23796
|
updateActiveNodes();
|
|
23744
23797
|
updateSelection();
|
|
@@ -24323,19 +24376,24 @@ RED.view = (function() {
|
|
|
24323
24376
|
n.n.moved = true;
|
|
24324
24377
|
}
|
|
24325
24378
|
}
|
|
24326
|
-
|
|
24327
|
-
//
|
|
24379
|
+
// If a node has moved and ends up being spliced into a link, keep
|
|
24380
|
+
// track of which historyEvent to add the splice info to
|
|
24381
|
+
let targetSpliceEvent = null
|
|
24328
24382
|
if (moveEvent.nodes.length > 0) {
|
|
24329
24383
|
historyEvent.events.push(moveEvent)
|
|
24330
|
-
|
|
24331
|
-
var linkToSplice = d3.select(activeSpliceLink).data()[0];
|
|
24332
|
-
spliceLink(linkToSplice, movingSet.get(0).n, moveEvent)
|
|
24333
|
-
}
|
|
24384
|
+
targetSpliceEvent = moveEvent
|
|
24334
24385
|
}
|
|
24335
24386
|
if (moveAndChangedGroupEvent.nodes.length > 0) {
|
|
24336
24387
|
historyEvent.events.push(moveAndChangedGroupEvent)
|
|
24388
|
+
targetSpliceEvent = moveAndChangedGroupEvent
|
|
24337
24389
|
}
|
|
24338
|
-
|
|
24390
|
+
// activeSpliceLink will only be set if the movingSet has a single
|
|
24391
|
+
// node that is able to splice.
|
|
24392
|
+
if (targetSpliceEvent && activeSpliceLink) {
|
|
24393
|
+
var linkToSplice = d3.select(activeSpliceLink).data()[0];
|
|
24394
|
+
spliceLink(linkToSplice, movingSet.get(0).n, targetSpliceEvent)
|
|
24395
|
+
}
|
|
24396
|
+
|
|
24339
24397
|
// Only continue if something has moved
|
|
24340
24398
|
if (historyEvent.events.length > 0) {
|
|
24341
24399
|
RED.nodes.dirty(true);
|
|
@@ -33794,8 +33852,6 @@ RED.sidebar.context = (function() {
|
|
|
33794
33852
|
var content;
|
|
33795
33853
|
var sections;
|
|
33796
33854
|
|
|
33797
|
-
var localCache = {};
|
|
33798
|
-
|
|
33799
33855
|
var flowAutoRefresh;
|
|
33800
33856
|
var nodeAutoRefresh;
|
|
33801
33857
|
var nodeSection;
|
|
@@ -33803,6 +33859,8 @@ RED.sidebar.context = (function() {
|
|
|
33803
33859
|
var flowSection;
|
|
33804
33860
|
var globalSection;
|
|
33805
33861
|
|
|
33862
|
+
const expandedPaths = {}
|
|
33863
|
+
|
|
33806
33864
|
var currentNode;
|
|
33807
33865
|
var currentFlow;
|
|
33808
33866
|
|
|
@@ -33988,14 +34046,41 @@ RED.sidebar.context = (function() {
|
|
|
33988
34046
|
var l = keys.length;
|
|
33989
34047
|
for (var i = 0; i < l; i++) {
|
|
33990
34048
|
sortedData[keys[i]].forEach(function(v) {
|
|
33991
|
-
|
|
33992
|
-
|
|
33993
|
-
|
|
33994
|
-
|
|
34049
|
+
const k = keys[i];
|
|
34050
|
+
let payload = v.msg;
|
|
34051
|
+
let format = v.format;
|
|
34052
|
+
const tools = $('<span class="button-group"></span>');
|
|
34053
|
+
expandedPaths[id + "." + k] = expandedPaths[id + "." + k] || new Set()
|
|
34054
|
+
const objectElementOptions = {
|
|
34055
|
+
typeHint: format,
|
|
34056
|
+
sourceId: id + "." + k,
|
|
34057
|
+
tools,
|
|
34058
|
+
path: k,
|
|
34059
|
+
rootPath: k,
|
|
34060
|
+
exposeApi: true,
|
|
34061
|
+
ontoggle: function(path,state) {
|
|
34062
|
+
path = path.substring(k.length+1)
|
|
34063
|
+
if (state) {
|
|
34064
|
+
expandedPaths[id+"."+k].add(path)
|
|
34065
|
+
} else {
|
|
34066
|
+
// if 'a' has been collapsed, we want to remove 'a.b' and 'a[0]...' from the set
|
|
34067
|
+
// of collapsed paths
|
|
34068
|
+
for (let expandedPath of expandedPaths[id+"."+k]) {
|
|
34069
|
+
if (expandedPath.startsWith(path+".") || expandedPath.startsWith(path+"[")) {
|
|
34070
|
+
expandedPaths[id+"."+k].delete(expandedPath)
|
|
34071
|
+
}
|
|
34072
|
+
}
|
|
34073
|
+
expandedPaths[id+"."+k].delete(path)
|
|
34074
|
+
}
|
|
34075
|
+
},
|
|
34076
|
+
expandPaths: [ ...expandedPaths[id+"."+k] ].sort(),
|
|
34077
|
+
expandLeafNodes: true
|
|
34078
|
+
}
|
|
34079
|
+
const propRow = $('<tr class="red-ui-help-info-row"><td class="red-ui-sidebar-context-property"></td><td></td></tr>').appendTo(container);
|
|
34080
|
+
const obj = $(propRow.children()[0]);
|
|
33995
34081
|
obj.text(k);
|
|
33996
|
-
var tools = $('<span class="button-group"></span>');
|
|
33997
34082
|
const urlSafeK = encodeURIComponent(k)
|
|
33998
|
-
|
|
34083
|
+
const refreshItem = $('<button class="red-ui-button red-ui-button-small"><i class="fa fa-refresh"></i></button>').appendTo(tools).on("click", function(e) {
|
|
33999
34084
|
e.preventDefault();
|
|
34000
34085
|
e.stopPropagation();
|
|
34001
34086
|
$.getJSON(baseUrl+"/"+urlSafeK+"?store="+v.store, function(data) {
|
|
@@ -34005,16 +34090,14 @@ RED.sidebar.context = (function() {
|
|
|
34005
34090
|
tools.detach();
|
|
34006
34091
|
$(propRow.children()[1]).empty();
|
|
34007
34092
|
RED.utils.createObjectElement(RED.utils.decodeObject(payload,format), {
|
|
34093
|
+
...objectElementOptions,
|
|
34008
34094
|
typeHint: data.format,
|
|
34009
|
-
sourceId: id+"."+k,
|
|
34010
|
-
tools: tools,
|
|
34011
|
-
path: k
|
|
34012
34095
|
}).appendTo(propRow.children()[1]);
|
|
34013
34096
|
}
|
|
34014
34097
|
})
|
|
34015
34098
|
});
|
|
34016
34099
|
RED.popover.tooltip(refreshItem,RED._("sidebar.context.refrsh"));
|
|
34017
|
-
|
|
34100
|
+
const deleteItem = $('<button class="red-ui-button red-ui-button-small"><i class="fa fa-trash"></i></button>').appendTo(tools).on("click", function(e) {
|
|
34018
34101
|
e.preventDefault();
|
|
34019
34102
|
e.stopPropagation();
|
|
34020
34103
|
var popover = RED.popover.create({
|
|
@@ -34022,7 +34105,7 @@ RED.sidebar.context = (function() {
|
|
|
34022
34105
|
target: propRow,
|
|
34023
34106
|
direction: "left",
|
|
34024
34107
|
content: function() {
|
|
34025
|
-
|
|
34108
|
+
const content = $('<div>');
|
|
34026
34109
|
$('<p data-i18n="sidebar.context.deleteConfirm"></p>').appendTo(content);
|
|
34027
34110
|
var row = $('<p>').appendTo(content);
|
|
34028
34111
|
var bg = $('<span class="button-group"></span>').appendTo(row);
|
|
@@ -34045,16 +34128,15 @@ RED.sidebar.context = (function() {
|
|
|
34045
34128
|
if (container.children().length === 0) {
|
|
34046
34129
|
$('<tr class="red-ui-help-info-row red-ui-search-empty blank" colspan="2"><td data-i18n="sidebar.context.empty"></td></tr>').appendTo(container).i18n();
|
|
34047
34130
|
}
|
|
34131
|
+
delete expandedPaths[id + "." + k]
|
|
34048
34132
|
} else {
|
|
34049
34133
|
payload = data.msg;
|
|
34050
34134
|
format = data.format;
|
|
34051
34135
|
tools.detach();
|
|
34052
34136
|
$(propRow.children()[1]).empty();
|
|
34053
34137
|
RED.utils.createObjectElement(RED.utils.decodeObject(payload,format), {
|
|
34054
|
-
|
|
34055
|
-
|
|
34056
|
-
tools: tools,
|
|
34057
|
-
path: k
|
|
34138
|
+
...objectElementOptions,
|
|
34139
|
+
typeHint: data.format
|
|
34058
34140
|
}).appendTo(propRow.children()[1]);
|
|
34059
34141
|
}
|
|
34060
34142
|
});
|
|
@@ -34069,14 +34151,7 @@ RED.sidebar.context = (function() {
|
|
|
34069
34151
|
|
|
34070
34152
|
});
|
|
34071
34153
|
RED.popover.tooltip(deleteItem,RED._("sidebar.context.delete"));
|
|
34072
|
-
|
|
34073
|
-
var format = v.format;
|
|
34074
|
-
RED.utils.createObjectElement(RED.utils.decodeObject(payload,format), {
|
|
34075
|
-
typeHint: v.format,
|
|
34076
|
-
sourceId: id+"."+k,
|
|
34077
|
-
tools: tools,
|
|
34078
|
-
path: k
|
|
34079
|
-
}).appendTo(propRow.children()[1]);
|
|
34154
|
+
RED.utils.createObjectElement(RED.utils.decodeObject(payload,format), objectElementOptions).appendTo(propRow.children()[1]);
|
|
34080
34155
|
if (contextStores.length > 1) {
|
|
34081
34156
|
$("<span>",{class:"red-ui-sidebar-context-property-storename"}).text(v.store).appendTo($(propRow.children()[0]))
|
|
34082
34157
|
}
|
|
@@ -37414,8 +37489,18 @@ RED.editor = (function() {
|
|
|
37414
37489
|
}
|
|
37415
37490
|
});
|
|
37416
37491
|
}
|
|
37417
|
-
|
|
37492
|
+
let envToRemove = new Set()
|
|
37418
37493
|
if (!isSameObj(old_env, new_env)) {
|
|
37494
|
+
// Get a list of env properties that have been removed
|
|
37495
|
+
// by comparing old_env and new_env
|
|
37496
|
+
if (old_env) {
|
|
37497
|
+
old_env.forEach(env => { envToRemove.add(env.name) })
|
|
37498
|
+
}
|
|
37499
|
+
if (new_env) {
|
|
37500
|
+
new_env.forEach(env => {
|
|
37501
|
+
envToRemove.delete(env.name)
|
|
37502
|
+
})
|
|
37503
|
+
}
|
|
37419
37504
|
editState.changes.env = editing_node.env;
|
|
37420
37505
|
editing_node.env = new_env;
|
|
37421
37506
|
editState.changed = true;
|
|
@@ -37424,10 +37509,11 @@ RED.editor = (function() {
|
|
|
37424
37509
|
|
|
37425
37510
|
|
|
37426
37511
|
if (editState.changed) {
|
|
37427
|
-
|
|
37512
|
+
let wasChanged = editing_node.changed;
|
|
37428
37513
|
editing_node.changed = true;
|
|
37429
37514
|
validateNode(editing_node);
|
|
37430
|
-
|
|
37515
|
+
let subflowInstances = [];
|
|
37516
|
+
let instanceHistoryEvents = []
|
|
37431
37517
|
RED.nodes.eachNode(function(n) {
|
|
37432
37518
|
if (n.type == "subflow:"+editing_node.id) {
|
|
37433
37519
|
subflowInstances.push({
|
|
@@ -37437,13 +37523,35 @@ RED.editor = (function() {
|
|
|
37437
37523
|
n._def.color = editing_node.color;
|
|
37438
37524
|
n.changed = true;
|
|
37439
37525
|
n.dirty = true;
|
|
37526
|
+
if (n.env) {
|
|
37527
|
+
const oldEnv = n.env
|
|
37528
|
+
const newEnv = []
|
|
37529
|
+
let envChanged = false
|
|
37530
|
+
n.env.forEach((env, index) => {
|
|
37531
|
+
if (envToRemove.has(env.name)) {
|
|
37532
|
+
envChanged = true
|
|
37533
|
+
} else {
|
|
37534
|
+
newEnv.push(env)
|
|
37535
|
+
}
|
|
37536
|
+
})
|
|
37537
|
+
if (envChanged) {
|
|
37538
|
+
instanceHistoryEvents.push({
|
|
37539
|
+
t: 'edit',
|
|
37540
|
+
node: n,
|
|
37541
|
+
changes: { env: oldEnv },
|
|
37542
|
+
dirty: n.dirty,
|
|
37543
|
+
changed: n.changed
|
|
37544
|
+
})
|
|
37545
|
+
n.env = newEnv
|
|
37546
|
+
}
|
|
37547
|
+
}
|
|
37440
37548
|
updateNodeProperties(n);
|
|
37441
37549
|
validateNode(n);
|
|
37442
37550
|
}
|
|
37443
37551
|
});
|
|
37444
37552
|
RED.events.emit("subflows:change",editing_node);
|
|
37445
37553
|
RED.nodes.dirty(true);
|
|
37446
|
-
|
|
37554
|
+
let historyEvent = {
|
|
37447
37555
|
t:'edit',
|
|
37448
37556
|
node:editing_node,
|
|
37449
37557
|
changes:editState.changes,
|
|
@@ -37453,7 +37561,13 @@ RED.editor = (function() {
|
|
|
37453
37561
|
instances:subflowInstances
|
|
37454
37562
|
}
|
|
37455
37563
|
};
|
|
37456
|
-
|
|
37564
|
+
if (instanceHistoryEvents.length > 0) {
|
|
37565
|
+
historyEvent = {
|
|
37566
|
+
t: 'multi',
|
|
37567
|
+
events: [ historyEvent, ...instanceHistoryEvents ],
|
|
37568
|
+
dirty: wasDirty
|
|
37569
|
+
}
|
|
37570
|
+
}
|
|
37457
37571
|
RED.history.push(historyEvent);
|
|
37458
37572
|
}
|
|
37459
37573
|
editing_node.dirty = true;
|
|
@@ -42899,6 +43013,7 @@ RED.editor.codeEditor.monaco = (function() {
|
|
|
42899
43013
|
2322, //Type 'unknown' is not assignable to type 'string'
|
|
42900
43014
|
2339, //property does not exist on
|
|
42901
43015
|
2345, //Argument of type xxx is not assignable to parameter of type 'DateTimeFormatOptions'
|
|
43016
|
+
2538, //Ignore symbols as index property error.
|
|
42902
43017
|
7043, //i forget what this one is,
|
|
42903
43018
|
80001, //Convert to ES6 module
|
|
42904
43019
|
80004, //JSDoc types may be moved to TypeScript types.
|
|
@@ -45748,10 +45863,15 @@ RED.library = (function() {
|
|
|
45748
45863
|
if (lib.types && lib.types.indexOf(options.url) === -1) {
|
|
45749
45864
|
return;
|
|
45750
45865
|
}
|
|
45866
|
+
let icon = 'fa fa-hdd-o';
|
|
45867
|
+
if (lib.icon) {
|
|
45868
|
+
const fullIcon = RED.utils.separateIconPath(lib.icon);
|
|
45869
|
+
icon = (fullIcon.module==="font-awesome"?"fa ":"")+fullIcon.file;
|
|
45870
|
+
}
|
|
45751
45871
|
listing.push({
|
|
45752
45872
|
library: lib.id,
|
|
45753
45873
|
type: options.url,
|
|
45754
|
-
icon
|
|
45874
|
+
icon,
|
|
45755
45875
|
label: RED._(lib.label||lib.id),
|
|
45756
45876
|
path: "",
|
|
45757
45877
|
expanded: true,
|
|
@@ -45806,10 +45926,15 @@ RED.library = (function() {
|
|
|
45806
45926
|
if (lib.types && lib.types.indexOf(options.url) === -1) {
|
|
45807
45927
|
return;
|
|
45808
45928
|
}
|
|
45929
|
+
let icon = 'fa fa-hdd-o';
|
|
45930
|
+
if (lib.icon) {
|
|
45931
|
+
const fullIcon = RED.utils.separateIconPath(lib.icon);
|
|
45932
|
+
icon = (fullIcon.module==="font-awesome"?"fa ":"")+fullIcon.file;
|
|
45933
|
+
}
|
|
45809
45934
|
listing.push({
|
|
45810
45935
|
library: lib.id,
|
|
45811
45936
|
type: options.url,
|
|
45812
|
-
icon
|
|
45937
|
+
icon,
|
|
45813
45938
|
label: RED._(lib.label||lib.id),
|
|
45814
45939
|
path: "",
|
|
45815
45940
|
expanded: true,
|