@node-red/editor-client 4.1.0-beta.1 → 4.1.0
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/locales/en-US/editor.json +2 -1
- package/locales/en-US/infotips.json +1 -1
- package/locales/es-ES/infotips.json +1 -1
- package/locales/fr/editor.json +1 -1
- package/locales/fr/infotips.json +1 -1
- package/locales/ja/editor.json +26 -1
- package/locales/ru/infotips.json +3 -3
- package/package.json +1 -1
- package/public/red/about +37 -0
- package/public/red/red.js +435 -102
- package/public/red/red.min.js +3 -3
- package/public/red/tours/4.0/welcome.js +8 -8
- package/public/red/tours/welcome.js +23 -3
- package/public/vendor/jquery/css/base/images/ui-icons_444444_256x240.png +0 -0
- package/public/vendor/jquery/css/base/images/ui-icons_555555_256x240.png +0 -0
- package/public/vendor/jquery/css/base/images/ui-icons_777620_256x240.png +0 -0
- package/public/vendor/jquery/css/base/images/ui-icons_777777_256x240.png +0 -0
- package/public/vendor/jquery/css/base/images/ui-icons_cc0000_256x240.png +0 -0
- package/public/vendor/jquery/css/base/images/ui-icons_ffffff_256x240.png +0 -0
- package/public/vendor/jquery/css/base/jquery-ui.min.css +6 -6
- package/public/vendor/mermaid/mermaid.min.js +369 -317
- package/public/vendor/vendor.js +9 -11
package/public/red/red.js
CHANGED
|
@@ -6341,6 +6341,7 @@ RED.nodes = (function() {
|
|
|
6341
6341
|
* - id:replace - import over the top of existing
|
|
6342
6342
|
* - modules: map of module:version - hints for unknown nodes
|
|
6343
6343
|
* - applyNodeDefaults - whether to apply default values to the imported nodes (default: false)
|
|
6344
|
+
* - eventContext - context to include in the `nodes:add` event
|
|
6344
6345
|
*/
|
|
6345
6346
|
function importNodes(newNodesObj,options) { // createNewIds,createMissingWorkspace) {
|
|
6346
6347
|
const defOpts = {
|
|
@@ -6349,7 +6350,8 @@ RED.nodes = (function() {
|
|
|
6349
6350
|
markChanged: false,
|
|
6350
6351
|
reimport: false,
|
|
6351
6352
|
importMap: {},
|
|
6352
|
-
applyNodeDefaults: false
|
|
6353
|
+
applyNodeDefaults: false,
|
|
6354
|
+
eventContext: null
|
|
6353
6355
|
}
|
|
6354
6356
|
options = Object.assign({}, defOpts, options)
|
|
6355
6357
|
options.importMap = options.importMap || {}
|
|
@@ -6501,29 +6503,29 @@ RED.nodes = (function() {
|
|
|
6501
6503
|
// Provide option to install missing modules
|
|
6502
6504
|
notificationOptions.buttons = [
|
|
6503
6505
|
{
|
|
6504
|
-
text: RED._("palette.editor.
|
|
6506
|
+
text: RED._("palette.editor.installAll"),
|
|
6505
6507
|
class: "primary",
|
|
6506
6508
|
click: function(e) {
|
|
6507
6509
|
unknownNotification.close();
|
|
6508
6510
|
|
|
6509
6511
|
RED.actions.invoke('core:manage-palette', {
|
|
6510
|
-
|
|
6511
|
-
|
|
6512
|
+
autoInstall: true,
|
|
6513
|
+
modules: missingModules.reduce((modules, moduleName) => {
|
|
6514
|
+
modules[moduleName] = options.modules[moduleName];
|
|
6515
|
+
return modules;
|
|
6516
|
+
}, {}),
|
|
6512
6517
|
});
|
|
6513
6518
|
}
|
|
6514
6519
|
},
|
|
6515
6520
|
{
|
|
6516
|
-
text: RED._("palette.editor.
|
|
6521
|
+
text: RED._("palette.editor.manageModules"),
|
|
6517
6522
|
class: "pull-left",
|
|
6518
6523
|
click: function(e) {
|
|
6519
6524
|
unknownNotification.close();
|
|
6520
6525
|
|
|
6521
6526
|
RED.actions.invoke('core:manage-palette', {
|
|
6522
|
-
|
|
6523
|
-
|
|
6524
|
-
modules[moduleName] = options.modules[moduleName];
|
|
6525
|
-
return modules;
|
|
6526
|
-
}, {}),
|
|
6527
|
+
view: 'install',
|
|
6528
|
+
filter: '"' + missingModules.join('", "') + '"'
|
|
6527
6529
|
});
|
|
6528
6530
|
}
|
|
6529
6531
|
}
|
|
@@ -7225,7 +7227,7 @@ RED.nodes = (function() {
|
|
|
7225
7227
|
|
|
7226
7228
|
// Now the nodes have been fully updated, add them.
|
|
7227
7229
|
for (i=0;i<new_nodes.length;i++) {
|
|
7228
|
-
new_nodes[i] = addNode(new_nodes[i])
|
|
7230
|
+
new_nodes[i] = addNode(new_nodes[i], options.eventContext)
|
|
7229
7231
|
node_map[new_nodes[i].id] = new_nodes[i]
|
|
7230
7232
|
}
|
|
7231
7233
|
|
|
@@ -9864,7 +9866,7 @@ RED.utils = (function() {
|
|
|
9864
9866
|
|
|
9865
9867
|
renderer.code = function (code, lang) {
|
|
9866
9868
|
if(lang === "mermaid") {
|
|
9867
|
-
return `<pre class='mermaid'>${code}</pre>`;
|
|
9869
|
+
return `<pre style='word-break: unset;' data-c64='${btoa(code)}' class='mermaid'>${code}</pre>`;
|
|
9868
9870
|
} else {
|
|
9869
9871
|
return "<pre><code>" +code +"</code></pre>";
|
|
9870
9872
|
}
|
|
@@ -17310,14 +17312,25 @@ RED.stack = (function() {
|
|
|
17310
17312
|
* The function must either return auto-complete options, or pass them
|
|
17311
17313
|
* to the optional 'done' parameter.
|
|
17312
17314
|
* If the function signature includes 'done', it must be used
|
|
17315
|
+
* The auto-complete options can either be an array of strings, or an array of objects in the form:
|
|
17316
|
+
* {
|
|
17317
|
+
* value: String : the value to insert if selected
|
|
17318
|
+
* label: String|DOM Element : the label to display in the dropdown.
|
|
17319
|
+
* }
|
|
17320
|
+
*
|
|
17313
17321
|
* minLength: number
|
|
17314
17322
|
* If `minLength` is 0, pressing down arrow will show the list
|
|
17323
|
+
*
|
|
17324
|
+
* completionPluginType: String
|
|
17325
|
+
* If provided instead of `search`, this will look for any plugins
|
|
17326
|
+
* registered with the given type that implement the `getCompletions` function. This
|
|
17327
|
+
* can be an async function that returns an array of string completions. It does not support
|
|
17328
|
+
* the full options object as above.
|
|
17315
17329
|
*
|
|
17316
|
-
*
|
|
17317
|
-
*
|
|
17318
|
-
*
|
|
17319
|
-
*
|
|
17320
|
-
* }
|
|
17330
|
+
* node: Node
|
|
17331
|
+
* If provided, this will be passed to the `getCompletions` function of the plugin
|
|
17332
|
+
* to allow the plugin to provide context-aware completions.
|
|
17333
|
+
*
|
|
17321
17334
|
*
|
|
17322
17335
|
*/
|
|
17323
17336
|
|
|
@@ -17326,6 +17339,54 @@ RED.stack = (function() {
|
|
|
17326
17339
|
const that = this;
|
|
17327
17340
|
this.completionMenuShown = false;
|
|
17328
17341
|
this.options.minLength = parseInteger(this.options.minLength, 1, 0);
|
|
17342
|
+
if (!this.options.search) {
|
|
17343
|
+
// No search function provided; nothing to provide completions
|
|
17344
|
+
if (this.options.completionPluginType) {
|
|
17345
|
+
const plugins = RED.plugins.getPluginsByType(this.options.completionPluginType)
|
|
17346
|
+
if (plugins.length > 0) {
|
|
17347
|
+
this.options.search = async function (value, done) {
|
|
17348
|
+
// for now, only support a single plugin
|
|
17349
|
+
const promises = plugins.map(plugin => plugin.getCompletions(value, that.options.context))
|
|
17350
|
+
const completions = (await Promise.all(promises)).flat()
|
|
17351
|
+
const results = []
|
|
17352
|
+
completions.forEach(completion => {
|
|
17353
|
+
const element = $('<div>',{style: "display: flex"})
|
|
17354
|
+
const valEl = $('<div/>',{ class: "red-ui-autoComplete-completion" })
|
|
17355
|
+
const valMatch = getMatch(completion, value)
|
|
17356
|
+
if (valMatch.found) {
|
|
17357
|
+
valEl.append(generateSpans(valMatch))
|
|
17358
|
+
valEl.appendTo(element)
|
|
17359
|
+
results.push({
|
|
17360
|
+
value: completion,
|
|
17361
|
+
label: element,
|
|
17362
|
+
match: valMatch
|
|
17363
|
+
})
|
|
17364
|
+
}
|
|
17365
|
+
results.sort((a, b) => {
|
|
17366
|
+
if (a.match.exact && !b.match.exact) {
|
|
17367
|
+
return -1;
|
|
17368
|
+
} else if (!a.match.exact && b.match.exact) {
|
|
17369
|
+
return 1;
|
|
17370
|
+
} else if (a.match.index < b.match.index) {
|
|
17371
|
+
return -1;
|
|
17372
|
+
} else if (a.match.index > b.match.index) {
|
|
17373
|
+
return 1;
|
|
17374
|
+
} else {
|
|
17375
|
+
return 0;
|
|
17376
|
+
}
|
|
17377
|
+
})
|
|
17378
|
+
})
|
|
17379
|
+
done(results)
|
|
17380
|
+
}
|
|
17381
|
+
} else {
|
|
17382
|
+
// No search function and no plugins found
|
|
17383
|
+
return
|
|
17384
|
+
}
|
|
17385
|
+
} else {
|
|
17386
|
+
// No search function and no plugin type provided
|
|
17387
|
+
return
|
|
17388
|
+
}
|
|
17389
|
+
}
|
|
17329
17390
|
this.options.search = this.options.search || function() { return [] };
|
|
17330
17391
|
this.element.addClass("red-ui-autoComplete");
|
|
17331
17392
|
this.element.on("keydown.red-ui-autoComplete", function(evt) {
|
|
@@ -17387,6 +17448,11 @@ RED.stack = (function() {
|
|
|
17387
17448
|
}
|
|
17388
17449
|
return
|
|
17389
17450
|
}
|
|
17451
|
+
if (typeof completions[0] === "string") {
|
|
17452
|
+
completions = completions.map(function(c) {
|
|
17453
|
+
return { value: c, label: c };
|
|
17454
|
+
});
|
|
17455
|
+
}
|
|
17390
17456
|
if (that.completionMenuShown) {
|
|
17391
17457
|
that.menu.options(completions);
|
|
17392
17458
|
} else {
|
|
@@ -17418,6 +17484,27 @@ RED.stack = (function() {
|
|
|
17418
17484
|
if(isNaN(n) || n < min || n > max) { n = def || 0; }
|
|
17419
17485
|
return n;
|
|
17420
17486
|
}
|
|
17487
|
+
// TODO: this is copied from typedInput - should be a shared utility
|
|
17488
|
+
function getMatch(value, searchValue) {
|
|
17489
|
+
const idx = value.toLowerCase().indexOf(searchValue.toLowerCase());
|
|
17490
|
+
const len = idx > -1 ? searchValue.length : 0;
|
|
17491
|
+
return {
|
|
17492
|
+
index: idx,
|
|
17493
|
+
found: idx > -1,
|
|
17494
|
+
pre: value.substring(0,idx),
|
|
17495
|
+
match: value.substring(idx,idx+len),
|
|
17496
|
+
post: value.substring(idx+len),
|
|
17497
|
+
exact: idx === 0 && value.length === searchValue.length
|
|
17498
|
+
}
|
|
17499
|
+
}
|
|
17500
|
+
// TODO: this is copied from typedInput - should be a shared utility
|
|
17501
|
+
function generateSpans(match) {
|
|
17502
|
+
const els = [];
|
|
17503
|
+
if(match.pre) { els.push($('<span/>').text(match.pre)); }
|
|
17504
|
+
if(match.match) { els.push($('<span/>',{style:"font-weight: bold; color: var(--red-ui-text-color-link);"}).text(match.match)); }
|
|
17505
|
+
if(match.post) { els.push($('<span/>').text(match.post)); }
|
|
17506
|
+
return els;
|
|
17507
|
+
}
|
|
17421
17508
|
})(jQuery);
|
|
17422
17509
|
;RED.actions = (function() {
|
|
17423
17510
|
var actions = {
|
|
@@ -20657,6 +20744,7 @@ RED.keyboard = (function() {
|
|
|
20657
20744
|
"backspace": 8,
|
|
20658
20745
|
"delete": 46,
|
|
20659
20746
|
"space": 32,
|
|
20747
|
+
"tab": 9,
|
|
20660
20748
|
";":186,
|
|
20661
20749
|
"=":187,
|
|
20662
20750
|
"+":187, // <- QWERTY specific
|
|
@@ -20923,23 +21011,27 @@ RED.keyboard = (function() {
|
|
|
20923
21011
|
return resolveKeyEvent(evt);
|
|
20924
21012
|
}
|
|
20925
21013
|
}
|
|
20926
|
-
d3.select(window).on("keydown",
|
|
21014
|
+
d3.select(window).on("keydown", () => {
|
|
21015
|
+
handleEvent(d3.event)
|
|
21016
|
+
})
|
|
21017
|
+
|
|
21018
|
+
function handleEvent (evt) {
|
|
20927
21019
|
if (!handlersActive) {
|
|
20928
21020
|
return;
|
|
20929
21021
|
}
|
|
20930
|
-
if (metaKeyCodes[
|
|
21022
|
+
if (metaKeyCodes[evt]) {
|
|
20931
21023
|
return;
|
|
20932
21024
|
}
|
|
20933
|
-
var handler = resolveKeyEvent(
|
|
21025
|
+
var handler = resolveKeyEvent(evt);
|
|
20934
21026
|
if (handler && handler.ondown) {
|
|
20935
21027
|
if (typeof handler.ondown === "string") {
|
|
20936
21028
|
RED.actions.invoke(handler.ondown);
|
|
20937
21029
|
} else {
|
|
20938
21030
|
handler.ondown();
|
|
20939
21031
|
}
|
|
20940
|
-
|
|
20941
|
-
}
|
|
20942
|
-
}
|
|
21032
|
+
evt.preventDefault();
|
|
21033
|
+
}
|
|
21034
|
+
}
|
|
20943
21035
|
|
|
20944
21036
|
function addHandler(scope,key,modifiers,ondown) {
|
|
20945
21037
|
var mod = modifiers;
|
|
@@ -21321,7 +21413,8 @@ RED.keyboard = (function() {
|
|
|
21321
21413
|
formatKey: formatKey,
|
|
21322
21414
|
validateKey: validateKey,
|
|
21323
21415
|
disable: disable,
|
|
21324
|
-
enable: enable
|
|
21416
|
+
enable: enable,
|
|
21417
|
+
handle: handleEvent
|
|
21325
21418
|
}
|
|
21326
21419
|
|
|
21327
21420
|
})();
|
|
@@ -23195,7 +23288,9 @@ RED.view = (function() {
|
|
|
23195
23288
|
return;
|
|
23196
23289
|
}
|
|
23197
23290
|
var historyEvent = result.historyEvent;
|
|
23198
|
-
|
|
23291
|
+
const linkToSplice = $(ui.helper).data("splice");
|
|
23292
|
+
|
|
23293
|
+
var nn = RED.nodes.add(result.node, { source: 'palette', splice: !!linkToSplice });
|
|
23199
23294
|
|
|
23200
23295
|
var showLabel = RED.utils.getMessageProperty(RED.settings.get('editor'),"view.view-node-show-label");
|
|
23201
23296
|
if (showLabel !== undefined && (nn._def.hasOwnProperty("showLabel")?nn._def.showLabel:true) && !nn._def.defaults.hasOwnProperty("l")) {
|
|
@@ -23254,7 +23349,6 @@ RED.view = (function() {
|
|
|
23254
23349
|
nn.y -= gridOffset.y;
|
|
23255
23350
|
}
|
|
23256
23351
|
|
|
23257
|
-
var linkToSplice = $(ui.helper).data("splice");
|
|
23258
23352
|
if (linkToSplice) {
|
|
23259
23353
|
spliceLink(linkToSplice, nn, historyEvent)
|
|
23260
23354
|
}
|
|
@@ -23327,7 +23421,11 @@ RED.view = (function() {
|
|
|
23327
23421
|
if (RED.workspaces.isLocked()) {
|
|
23328
23422
|
return
|
|
23329
23423
|
}
|
|
23330
|
-
importNodes(clipboard,{
|
|
23424
|
+
importNodes(clipboard, {
|
|
23425
|
+
generateIds: clipboardSource === 'copy',
|
|
23426
|
+
generateDefaultNames: clipboardSource === 'copy',
|
|
23427
|
+
eventContext: { source: 'clipboard' }
|
|
23428
|
+
});
|
|
23331
23429
|
});
|
|
23332
23430
|
|
|
23333
23431
|
RED.actions.add("core:detach-selected-nodes", function() { detachSelectedNodes() })
|
|
@@ -23937,10 +24035,12 @@ RED.view = (function() {
|
|
|
23937
24035
|
var lastAddedX;
|
|
23938
24036
|
var lastAddedWidth;
|
|
23939
24037
|
|
|
23940
|
-
const context = {
|
|
24038
|
+
const context = {
|
|
24039
|
+
workspace: RED.workspaces.active()
|
|
24040
|
+
}
|
|
23941
24041
|
|
|
23942
24042
|
if (quickAddLink) {
|
|
23943
|
-
context.source = quickAddLink.node
|
|
24043
|
+
context.source = quickAddLink.node;
|
|
23944
24044
|
context.sourcePort = quickAddLink.port;
|
|
23945
24045
|
context.sourcePortType = quickAddLink.portType;
|
|
23946
24046
|
if (quickAddLink?.virtualLink) {
|
|
@@ -23956,6 +24056,7 @@ RED.view = (function() {
|
|
|
23956
24056
|
y:clientY-mainPos.top+ node_height/2 + 5 - (oy-point[1]),
|
|
23957
24057
|
disableFocus: touchTrigger,
|
|
23958
24058
|
filter: filter,
|
|
24059
|
+
context,
|
|
23959
24060
|
move: function(dx,dy) {
|
|
23960
24061
|
if (ghostNode) {
|
|
23961
24062
|
var pos = d3.transform(ghostNode.attr("transform")).translate;
|
|
@@ -23996,7 +24097,8 @@ RED.view = (function() {
|
|
|
23996
24097
|
touchImport: true,
|
|
23997
24098
|
notify: false,
|
|
23998
24099
|
// Ensure the node gets all of its defaults applied
|
|
23999
|
-
applyNodeDefaults: true
|
|
24100
|
+
applyNodeDefaults: true,
|
|
24101
|
+
eventContext: { source: 'typeSearch' }
|
|
24000
24102
|
})
|
|
24001
24103
|
quickAddActive = false;
|
|
24002
24104
|
ghostNode.remove();
|
|
@@ -24004,8 +24106,9 @@ RED.view = (function() {
|
|
|
24004
24106
|
if (quickAddLink) {
|
|
24005
24107
|
// Need to attach the link to the suggestion. This is assumed to be the first
|
|
24006
24108
|
// node in the array - as that's the one we've focussed on.
|
|
24007
|
-
|
|
24008
|
-
|
|
24109
|
+
// We need to map from the suggested node's id to the imported node's id,
|
|
24110
|
+
// and then get the proxy object for the node
|
|
24111
|
+
const targetNode = RED.nodes.node(importResult.nodeMap[type.nodes[0].id].id)
|
|
24009
24112
|
const drag_line = quickAddLink;
|
|
24010
24113
|
let src = null, dst, src_port;
|
|
24011
24114
|
if (drag_line.portType === PORT_TYPE_OUTPUT && (targetNode.inputs > 0 || drag_line.virtualLink) ) {
|
|
@@ -24045,6 +24148,7 @@ RED.view = (function() {
|
|
|
24045
24148
|
}
|
|
24046
24149
|
var nn;
|
|
24047
24150
|
var historyEvent;
|
|
24151
|
+
let addHistoryEvent;
|
|
24048
24152
|
if (/^_action_:/.test(type)) {
|
|
24049
24153
|
const actionName = type.substring(9)
|
|
24050
24154
|
quickAddActive = false;
|
|
@@ -24078,6 +24182,7 @@ RED.view = (function() {
|
|
|
24078
24182
|
nn = result.node;
|
|
24079
24183
|
historyEvent = result.historyEvent;
|
|
24080
24184
|
}
|
|
24185
|
+
addHistoryEvent = historyEvent;
|
|
24081
24186
|
if (keepAdding) {
|
|
24082
24187
|
mouse_mode = RED.state.QUICK_JOINING;
|
|
24083
24188
|
}
|
|
@@ -24091,7 +24196,7 @@ RED.view = (function() {
|
|
|
24091
24196
|
if (nn.type === 'junction') {
|
|
24092
24197
|
nn = RED.nodes.addJunction(nn);
|
|
24093
24198
|
} else {
|
|
24094
|
-
nn = RED.nodes.add(nn, { source: 'typeSearch' });
|
|
24199
|
+
nn = RED.nodes.add(nn, { source: 'typeSearch', splice: !!linkToSplice });
|
|
24095
24200
|
}
|
|
24096
24201
|
if (quickAddLink) {
|
|
24097
24202
|
var drag_line = quickAddLink;
|
|
@@ -24232,7 +24337,8 @@ RED.view = (function() {
|
|
|
24232
24337
|
|
|
24233
24338
|
if (linkToSplice) {
|
|
24234
24339
|
resetMouseVars();
|
|
24235
|
-
|
|
24340
|
+
// Add any history event data to the original add event
|
|
24341
|
+
spliceLink(linkToSplice, nn, addHistoryEvent)
|
|
24236
24342
|
}
|
|
24237
24343
|
RED.history.push(historyEvent);
|
|
24238
24344
|
RED.nodes.dirty(true);
|
|
@@ -24276,17 +24382,14 @@ RED.view = (function() {
|
|
|
24276
24382
|
}
|
|
24277
24383
|
},
|
|
24278
24384
|
suggest: function (suggestion) {
|
|
24385
|
+
// TypeSearch only provides one suggestion at a time
|
|
24279
24386
|
if (suggestion?.nodes?.length > 0) {
|
|
24280
24387
|
// Reposition the suggestion relative to the existing ghost node position
|
|
24281
|
-
const deltaX = suggestion.nodes[0].x - point[0]
|
|
24282
|
-
const deltaY = suggestion.nodes[0].y - point[1]
|
|
24388
|
+
const deltaX = (suggestion.nodes[0].x || 0) - point[0]
|
|
24389
|
+
const deltaY = (suggestion.nodes[0].y || 0) - point[1]
|
|
24283
24390
|
suggestion.nodes.forEach(node => {
|
|
24284
|
-
|
|
24285
|
-
|
|
24286
|
-
}
|
|
24287
|
-
if (Object.hasOwn(node, 'y')) {
|
|
24288
|
-
node.y = node.y - deltaY
|
|
24289
|
-
}
|
|
24391
|
+
node.x = (node.x || 0) - deltaX
|
|
24392
|
+
node.y = (node.y || 0) - deltaY
|
|
24290
24393
|
})
|
|
24291
24394
|
}
|
|
24292
24395
|
setSuggestedFlow(suggestion);
|
|
@@ -27297,6 +27400,10 @@ RED.view = (function() {
|
|
|
27297
27400
|
.on("touchend",nodeTouchEnd)
|
|
27298
27401
|
.on("mouseover",nodeMouseOver)
|
|
27299
27402
|
.on("mouseout",nodeMouseOut);
|
|
27403
|
+
} else if (d.__ghostClick) {
|
|
27404
|
+
d3.select(mainRect)
|
|
27405
|
+
.on("mousedown",d.__ghostClick)
|
|
27406
|
+
.on("touchstart",d.__ghostClick)
|
|
27300
27407
|
}
|
|
27301
27408
|
nodeContents.appendChild(mainRect);
|
|
27302
27409
|
//node.append("rect").attr("class", "node-gradient-top").attr("rx", 6).attr("ry", 6).attr("height",30).attr("stroke","none").attr("fill","url(#gradient-top)").style("pointer-events","none");
|
|
@@ -27539,6 +27646,10 @@ RED.view = (function() {
|
|
|
27539
27646
|
.on("mouseover",function(d){portMouseOver(d3.select(this),d,PORT_TYPE_INPUT,0);})
|
|
27540
27647
|
.on("mouseout",function(d) {portMouseOut(d3.select(this),d,PORT_TYPE_INPUT,0);});
|
|
27541
27648
|
RED.hooks.trigger("viewAddPort",{node:d,el: this, port: inputGroup[0][0], portType: "input", portIndex: 0})
|
|
27649
|
+
} else if (d.__ghostClick) {
|
|
27650
|
+
inputGroupPorts
|
|
27651
|
+
.on("mousedown",d.__ghostClick)
|
|
27652
|
+
.on("touchstart",d.__ghostClick)
|
|
27542
27653
|
}
|
|
27543
27654
|
}
|
|
27544
27655
|
var numOutputs = d.outputs;
|
|
@@ -27597,6 +27708,9 @@ RED.view = (function() {
|
|
|
27597
27708
|
portPort.addEventListener("touchend", portTouchEndProxy);
|
|
27598
27709
|
portPort.addEventListener("mouseover", portMouseOverProxy);
|
|
27599
27710
|
portPort.addEventListener("mouseout", portMouseOutProxy);
|
|
27711
|
+
} else if (d.__ghostClick) {
|
|
27712
|
+
portPort.addEventListener("mousedown", d.__ghostClick)
|
|
27713
|
+
portPort.addEventListener("touchstart", d.__ghostClick)
|
|
27600
27714
|
}
|
|
27601
27715
|
|
|
27602
27716
|
this.appendChild(portGroup);
|
|
@@ -27898,6 +28012,10 @@ RED.view = (function() {
|
|
|
27898
28012
|
}
|
|
27899
28013
|
}
|
|
27900
28014
|
})
|
|
28015
|
+
} else if (d.__ghostClick) {
|
|
28016
|
+
d3.select(pathBack)
|
|
28017
|
+
.on("mousedown",d.__ghostClick)
|
|
28018
|
+
.on("touchstart",d.__ghostClick)
|
|
27901
28019
|
}
|
|
27902
28020
|
|
|
27903
28021
|
var pathOutline = document.createElementNS("http://www.w3.org/2000/svg","path");
|
|
@@ -28369,7 +28487,8 @@ RED.view = (function() {
|
|
|
28369
28487
|
generateIds: false,
|
|
28370
28488
|
generateDefaultNames: false,
|
|
28371
28489
|
notify: true,
|
|
28372
|
-
applyNodeDefaults: false
|
|
28490
|
+
applyNodeDefaults: false,
|
|
28491
|
+
eventContext: null
|
|
28373
28492
|
}
|
|
28374
28493
|
const addNewFlow = options.addFlow
|
|
28375
28494
|
const touchImport = options.touchImport;
|
|
@@ -28459,7 +28578,8 @@ RED.view = (function() {
|
|
|
28459
28578
|
importMap: options.importMap,
|
|
28460
28579
|
markChanged: true,
|
|
28461
28580
|
modules: modules,
|
|
28462
|
-
applyNodeDefaults: applyNodeDefaults
|
|
28581
|
+
applyNodeDefaults: applyNodeDefaults,
|
|
28582
|
+
eventContext: options.eventContext
|
|
28463
28583
|
});
|
|
28464
28584
|
if (importResult) {
|
|
28465
28585
|
var new_nodes = importResult.nodes;
|
|
@@ -28914,10 +29034,10 @@ RED.view = (function() {
|
|
|
28914
29034
|
nn.w = RED.view.node_width;
|
|
28915
29035
|
nn.h = Math.max(RED.view.node_height, (nn.outputs || 0) * 15);
|
|
28916
29036
|
nn.resize = true;
|
|
28917
|
-
if (x != null && typeof x == "number"
|
|
29037
|
+
if (x != null && typeof x == "number") {
|
|
28918
29038
|
nn.x = x;
|
|
28919
29039
|
}
|
|
28920
|
-
if (y != null && typeof y == "number"
|
|
29040
|
+
if (y != null && typeof y == "number") {
|
|
28921
29041
|
nn.y = y;
|
|
28922
29042
|
}
|
|
28923
29043
|
var historyEvent = {
|
|
@@ -29007,7 +29127,9 @@ RED.view = (function() {
|
|
|
29007
29127
|
* x: 0,
|
|
29008
29128
|
* y: 0,
|
|
29009
29129
|
* }
|
|
29010
|
-
*
|
|
29130
|
+
* ],
|
|
29131
|
+
* "source": <sourceNode>,
|
|
29132
|
+
* "sourcePort": <sourcePort>,
|
|
29011
29133
|
* }
|
|
29012
29134
|
* If `nodes` is a single node without an id property, it will be generated
|
|
29013
29135
|
* using its default properties.
|
|
@@ -29015,6 +29137,9 @@ RED.view = (function() {
|
|
|
29015
29137
|
* If `nodes` has multiple, they must all have ids and will be assumed to be 'importable'.
|
|
29016
29138
|
* In other words, a piece of valid flow json.
|
|
29017
29139
|
*
|
|
29140
|
+
* `source`/`sourcePort` are option and used to indicate a node the suggestion should be connected to.
|
|
29141
|
+
* If provided, a ghost wire will be added between the source and the first node in the suggestion.
|
|
29142
|
+
*
|
|
29018
29143
|
* Limitations:
|
|
29019
29144
|
* - does not support groups, subflows or whole tabs
|
|
29020
29145
|
* - does not support config nodes
|
|
@@ -29025,6 +29150,9 @@ RED.view = (function() {
|
|
|
29025
29150
|
* @param {Object} suggestion - The suggestion object
|
|
29026
29151
|
*/
|
|
29027
29152
|
function setSuggestedFlow (suggestion) {
|
|
29153
|
+
$(window).off('keydown.suggestedFlow')
|
|
29154
|
+
$(window).off('mousedown.suggestedFlow');
|
|
29155
|
+
RED.keyboard.enable()
|
|
29028
29156
|
if (!currentSuggestion && !suggestion) {
|
|
29029
29157
|
// Avoid unnecessary redraws
|
|
29030
29158
|
return
|
|
@@ -29032,18 +29160,57 @@ RED.view = (function() {
|
|
|
29032
29160
|
// Clear up any existing suggestion state
|
|
29033
29161
|
clearSuggestedFlow()
|
|
29034
29162
|
currentSuggestion = suggestion
|
|
29035
|
-
if (suggestion
|
|
29163
|
+
if (suggestion && suggestion.nodes) {
|
|
29164
|
+
// If suggestion.nodes is an array of arrays, then there are multiple suggestions being provided
|
|
29165
|
+
// Normalise the shape of the suggestion.nodes to be an array of arrays
|
|
29166
|
+
if (!Array.isArray(suggestion.nodes[0])) {
|
|
29167
|
+
suggestion.nodes = [suggestion.nodes]
|
|
29168
|
+
}
|
|
29169
|
+
suggestion.count = suggestion.nodes.length
|
|
29170
|
+
suggestion.currentIndex = 0
|
|
29171
|
+
suggestion.current = suggestion.nodes[suggestion.currentIndex]
|
|
29172
|
+
refreshSuggestedFlow()
|
|
29173
|
+
} else {
|
|
29174
|
+
redraw()
|
|
29175
|
+
}
|
|
29176
|
+
}
|
|
29177
|
+
|
|
29178
|
+
function refreshSuggestedFlow () {
|
|
29179
|
+
const suggestion = currentSuggestion
|
|
29180
|
+
suggestedNodes = []
|
|
29181
|
+
suggestedLinks = []
|
|
29182
|
+
|
|
29183
|
+
currentSuggestion.current = currentSuggestion.nodes[currentSuggestion.currentIndex]
|
|
29184
|
+
if (suggestion.current.length > 0) {
|
|
29036
29185
|
const nodeMap = {}
|
|
29037
29186
|
const links = []
|
|
29038
|
-
|
|
29187
|
+
const positionOffset = { x: 0, y: 0 }
|
|
29188
|
+
if (suggestion.source && suggestion.position === 'relative') {
|
|
29189
|
+
// If the suggestion is relative to a source node, use its position plus a suitable offset
|
|
29190
|
+
let targetX = suggestion.source.x + (suggestion.source.w || 120) + (3 * gridSize)
|
|
29191
|
+
const targetY = suggestion.source.y
|
|
29192
|
+
// Keep targetY where it is, but ensure targetX is grid aligned
|
|
29193
|
+
if (snapGrid) {
|
|
29194
|
+
// This isn't a perfect grid snap, as we don't have the true node width at this point.
|
|
29195
|
+
// TODO: defer grid snapping until the node is created?
|
|
29196
|
+
const gridOffset = RED.view.tools.calculateGridSnapOffsets({ x: targetX, y: targetY, w: node_width, h: node_height });
|
|
29197
|
+
targetX += gridOffset.x
|
|
29198
|
+
}
|
|
29199
|
+
|
|
29200
|
+
positionOffset.x = targetX - (suggestion.current[0].x || 0)
|
|
29201
|
+
positionOffset.y = targetY - (suggestion.current[0].y || 0)
|
|
29202
|
+
}
|
|
29203
|
+
|
|
29204
|
+
suggestion.current.forEach(nodeConfig => {
|
|
29039
29205
|
if (!nodeConfig.type || nodeConfig.type === 'group' || nodeConfig.type === 'subflow' || nodeConfig.type === 'tab') {
|
|
29040
29206
|
// A node type we don't support previewing
|
|
29041
29207
|
return
|
|
29042
29208
|
}
|
|
29043
29209
|
|
|
29044
29210
|
let node
|
|
29045
|
-
|
|
29046
29211
|
if (nodeConfig.type === 'junction') {
|
|
29212
|
+
nodeConfig.x = (nodeConfig.x || 0) + positionOffset.x
|
|
29213
|
+
nodeConfig.y = (nodeConfig.y || 0) + positionOffset.y
|
|
29047
29214
|
node = {
|
|
29048
29215
|
_def: {defaults:{}},
|
|
29049
29216
|
type: 'junction',
|
|
@@ -29064,6 +29231,8 @@ RED.view = (function() {
|
|
|
29064
29231
|
// TODO: unknown node types could happen...
|
|
29065
29232
|
return
|
|
29066
29233
|
}
|
|
29234
|
+
nodeConfig.x = (nodeConfig.x || 0) + positionOffset.x
|
|
29235
|
+
nodeConfig.y = (nodeConfig.y || 0) + positionOffset.y
|
|
29067
29236
|
const result = createNode(nodeConfig.type, nodeConfig.x, nodeConfig.y)
|
|
29068
29237
|
if (!result) {
|
|
29069
29238
|
return
|
|
@@ -29086,6 +29255,11 @@ RED.view = (function() {
|
|
|
29086
29255
|
node.id = nodeConfig.id || node.id
|
|
29087
29256
|
node.__ghost = true;
|
|
29088
29257
|
node.dirty = true;
|
|
29258
|
+
if (suggestion.clickToApply) {
|
|
29259
|
+
node.__ghostClick = function () {
|
|
29260
|
+
applySuggestedFlow()
|
|
29261
|
+
}
|
|
29262
|
+
}
|
|
29089
29263
|
nodeMap[node.id] = node
|
|
29090
29264
|
|
|
29091
29265
|
if (nodeConfig.wires) {
|
|
@@ -29114,6 +29288,56 @@ RED.view = (function() {
|
|
|
29114
29288
|
suggestedLinks.push(link)
|
|
29115
29289
|
}
|
|
29116
29290
|
})
|
|
29291
|
+
if (suggestion.source && suggestedNodes[0]?._def?.inputs > 0) {
|
|
29292
|
+
suggestedLinks.push({
|
|
29293
|
+
source: suggestion.source,
|
|
29294
|
+
sourcePort: suggestion.sourcePort || 0,
|
|
29295
|
+
target: suggestedNodes[0],
|
|
29296
|
+
targetPort: 0,
|
|
29297
|
+
__ghost: true
|
|
29298
|
+
})
|
|
29299
|
+
}
|
|
29300
|
+
if (!RED.typeSearch.isVisible()) {
|
|
29301
|
+
// Disable the core keyboard handling so we get priority.
|
|
29302
|
+
// Ideally we'd be able to do this via actions, but we can't currently scope
|
|
29303
|
+
// actions finely enough to only be handled when the suggested flow is active.
|
|
29304
|
+
RED.keyboard.disable()
|
|
29305
|
+
$(window).on('keydown.suggestedFlow', function (evt) {
|
|
29306
|
+
$(window).off('keydown.suggestedFlow')
|
|
29307
|
+
RED.keyboard.enable()
|
|
29308
|
+
if (evt.keyCode === 9) { // tab; apply suggestion
|
|
29309
|
+
evt.stopPropagation();
|
|
29310
|
+
evt.preventDefault();
|
|
29311
|
+
applySuggestedFlow();
|
|
29312
|
+
} else if (evt.keyCode === 38 && currentSuggestion.count > 1) { // up arrow
|
|
29313
|
+
evt.stopPropagation();
|
|
29314
|
+
evt.preventDefault();
|
|
29315
|
+
currentSuggestion.currentIndex--
|
|
29316
|
+
if (currentSuggestion.currentIndex < 0) {
|
|
29317
|
+
currentSuggestion.currentIndex = currentSuggestion.count - 1
|
|
29318
|
+
}
|
|
29319
|
+
refreshSuggestedFlow();
|
|
29320
|
+
} else if (evt.keyCode === 40 && currentSuggestion.count > 1) { // down arrow
|
|
29321
|
+
evt.stopPropagation();
|
|
29322
|
+
evt.preventDefault();
|
|
29323
|
+
currentSuggestion.currentIndex++
|
|
29324
|
+
if (currentSuggestion.currentIndex === currentSuggestion.count) {
|
|
29325
|
+
currentSuggestion.currentIndex = 0
|
|
29326
|
+
}
|
|
29327
|
+
refreshSuggestedFlow();
|
|
29328
|
+
} else { // Anything else; clear the suggestion
|
|
29329
|
+
clearSuggestedFlow();
|
|
29330
|
+
RED.view.redraw(true);
|
|
29331
|
+
// manually push the event to the keyboard handler
|
|
29332
|
+
RED.keyboard.handle(evt)
|
|
29333
|
+
}
|
|
29334
|
+
});
|
|
29335
|
+
}
|
|
29336
|
+
if (suggestion.clickToApply) {
|
|
29337
|
+
$(window).on('mousedown.suggestedFlow', function (evnt) {
|
|
29338
|
+
clearSuggestedFlow();
|
|
29339
|
+
})
|
|
29340
|
+
}
|
|
29117
29341
|
}
|
|
29118
29342
|
if (ghostNode) {
|
|
29119
29343
|
if (suggestedNodes.length > 0) {
|
|
@@ -29122,26 +29346,62 @@ RED.view = (function() {
|
|
|
29122
29346
|
ghostNode.style('opacity', 1)
|
|
29123
29347
|
}
|
|
29124
29348
|
}
|
|
29125
|
-
|
|
29349
|
+
if (currentSuggestion.count > 1 && suggestedNodes.length > 0) {
|
|
29350
|
+
suggestedNodes[0].status = {
|
|
29351
|
+
text: `${currentSuggestion.currentIndex + 1} / ${currentSuggestion.count}`,
|
|
29352
|
+
}
|
|
29353
|
+
suggestedNodes[0].dirtyStatus = true
|
|
29354
|
+
}
|
|
29355
|
+
redraw()
|
|
29126
29356
|
}
|
|
29127
29357
|
|
|
29128
29358
|
function clearSuggestedFlow () {
|
|
29359
|
+
$(window).off('mousedown.suggestedFlow');
|
|
29360
|
+
$(window).off('keydown.suggestedFlow')
|
|
29361
|
+
RED.keyboard.enable()
|
|
29129
29362
|
currentSuggestion = null
|
|
29130
29363
|
suggestedNodes = []
|
|
29131
29364
|
suggestedLinks = []
|
|
29132
29365
|
}
|
|
29133
29366
|
|
|
29134
29367
|
function applySuggestedFlow () {
|
|
29135
|
-
if (currentSuggestion && currentSuggestion.
|
|
29136
|
-
const nodesToImport = currentSuggestion.
|
|
29368
|
+
if (currentSuggestion && currentSuggestion.current) {
|
|
29369
|
+
const nodesToImport = currentSuggestion.current
|
|
29370
|
+
const sourceNode = currentSuggestion.source
|
|
29371
|
+
const sourcePort = currentSuggestion.sourcePort || 0
|
|
29137
29372
|
setSuggestedFlow(null)
|
|
29138
|
-
|
|
29373
|
+
const result = importNodes(nodesToImport, {
|
|
29139
29374
|
generateIds: true,
|
|
29140
29375
|
touchImport: true,
|
|
29141
29376
|
notify: false,
|
|
29142
29377
|
// Ensure the node gets all of its defaults applied
|
|
29143
|
-
applyNodeDefaults: true
|
|
29378
|
+
applyNodeDefaults: true,
|
|
29379
|
+
eventContext: { source: 'suggestion' }
|
|
29144
29380
|
})
|
|
29381
|
+
if (sourceNode) {
|
|
29382
|
+
const firstNode = result.nodeMap[nodesToImport[0].id]
|
|
29383
|
+
if (firstNode && firstNode._def?.inputs > 0) {
|
|
29384
|
+
// Connect the source node to the first node in the suggestion
|
|
29385
|
+
const link = {
|
|
29386
|
+
source: sourceNode,
|
|
29387
|
+
target: RED.nodes.node(firstNode.id),
|
|
29388
|
+
sourcePort: sourcePort,
|
|
29389
|
+
targetPort: 0
|
|
29390
|
+
};
|
|
29391
|
+
RED.nodes.addLink(link)
|
|
29392
|
+
let historyEvent = RED.history.peek();
|
|
29393
|
+
if (historyEvent.t === "multi") {
|
|
29394
|
+
historyEvent = historyEvent.events.find(e => e.t === "add")
|
|
29395
|
+
}
|
|
29396
|
+
if (historyEvent) {
|
|
29397
|
+
historyEvent.links = historyEvent.links || [];
|
|
29398
|
+
historyEvent.links.push(link);
|
|
29399
|
+
}
|
|
29400
|
+
RED.view.redraw(true);
|
|
29401
|
+
}
|
|
29402
|
+
}
|
|
29403
|
+
|
|
29404
|
+
return result
|
|
29145
29405
|
}
|
|
29146
29406
|
}
|
|
29147
29407
|
|
|
@@ -30121,6 +30381,8 @@ RED.view.tools = (function() {
|
|
|
30121
30381
|
|
|
30122
30382
|
|
|
30123
30383
|
function gotoNearestNode(direction) {
|
|
30384
|
+
// Do not select a nearest node if move is active
|
|
30385
|
+
if (RED.view.state() === RED.state.MOVING_ACTIVE) { return }
|
|
30124
30386
|
var selection = RED.view.selection();
|
|
30125
30387
|
if (selection.nodes && selection.nodes.length === 1) {
|
|
30126
30388
|
var origin = selection.nodes[0];
|
|
@@ -30900,8 +31162,8 @@ RED.view.tools = (function() {
|
|
|
30900
31162
|
t: 'multi',
|
|
30901
31163
|
events: historyEvents
|
|
30902
31164
|
})
|
|
31165
|
+
RED.nodes.dirty(true)
|
|
30903
31166
|
}
|
|
30904
|
-
RED.nodes.dirty(true)
|
|
30905
31167
|
RED.view.redraw()
|
|
30906
31168
|
}
|
|
30907
31169
|
}
|
|
@@ -31562,7 +31824,7 @@ RED.palette = (function() {
|
|
|
31562
31824
|
getNodeCount: function (visibleOnly) {
|
|
31563
31825
|
const nodes = catDiv.find(".red-ui-palette-node")
|
|
31564
31826
|
if (visibleOnly) {
|
|
31565
|
-
return nodes.filter(function() { return $(this).
|
|
31827
|
+
return nodes.filter(function() { return $(this).attr("data-filter") !== "true"}).length
|
|
31566
31828
|
} else {
|
|
31567
31829
|
return nodes.length
|
|
31568
31830
|
}
|
|
@@ -32054,8 +32316,10 @@ RED.palette = (function() {
|
|
|
32054
32316
|
var currentLabel = $(el).attr("data-palette-label");
|
|
32055
32317
|
var type = $(el).attr("data-palette-type");
|
|
32056
32318
|
if (val === "" || re.test(type) || re.test(currentLabel)) {
|
|
32319
|
+
$(el).attr("data-filter", null)
|
|
32057
32320
|
$(this).show();
|
|
32058
32321
|
} else {
|
|
32322
|
+
$(el).attr("data-filter", "true")
|
|
32059
32323
|
$(this).hide();
|
|
32060
32324
|
}
|
|
32061
32325
|
});
|
|
@@ -35691,6 +35955,11 @@ RED.palette.editor = (function() {
|
|
|
35691
35955
|
});
|
|
35692
35956
|
|
|
35693
35957
|
RED.events.on('registry:module-updated', function(ns) {
|
|
35958
|
+
if (nodeEntries[ns.module]) {
|
|
35959
|
+
// Set the node/plugin as updated
|
|
35960
|
+
nodeEntries[ns.module].info.pending_version = ns.version;
|
|
35961
|
+
}
|
|
35962
|
+
|
|
35694
35963
|
refreshNodeModule(ns.module);
|
|
35695
35964
|
refreshUpdateStatus();
|
|
35696
35965
|
});
|
|
@@ -37827,6 +38096,7 @@ RED.editor = (function() {
|
|
|
37827
38096
|
|
|
37828
38097
|
function showEditDialog(node, defaultTab) {
|
|
37829
38098
|
if (buildingEditDialog) { return }
|
|
38099
|
+
if (editStack.includes(node)) { return }
|
|
37830
38100
|
buildingEditDialog = true;
|
|
37831
38101
|
if (node.z && RED.workspaces.isLocked(node.z)) { return }
|
|
37832
38102
|
var editing_node = node;
|
|
@@ -38144,6 +38414,7 @@ RED.editor = (function() {
|
|
|
38144
38414
|
var editing_config_node = RED.nodes.node(id);
|
|
38145
38415
|
var activeEditPanes = [];
|
|
38146
38416
|
|
|
38417
|
+
if (editStack.includes(editing_config_node)) { return }
|
|
38147
38418
|
if (editing_config_node && editing_config_node.z && RED.workspaces.isLocked(editing_config_node.z)) { return }
|
|
38148
38419
|
|
|
38149
38420
|
var configNodeScope = ""; // default to global
|
|
@@ -38587,6 +38858,7 @@ RED.editor = (function() {
|
|
|
38587
38858
|
|
|
38588
38859
|
function showEditSubflowDialog(subflow, defaultTab) {
|
|
38589
38860
|
if (buildingEditDialog) { return }
|
|
38861
|
+
if (editStack.includes(subflow)) { return }
|
|
38590
38862
|
buildingEditDialog = true;
|
|
38591
38863
|
|
|
38592
38864
|
editStack.push(subflow);
|
|
@@ -38803,6 +39075,7 @@ RED.editor = (function() {
|
|
|
38803
39075
|
|
|
38804
39076
|
function showEditGroupDialog(group, defaultTab) {
|
|
38805
39077
|
if (buildingEditDialog) { return }
|
|
39078
|
+
if (editStack.includes(group)) { return }
|
|
38806
39079
|
buildingEditDialog = true;
|
|
38807
39080
|
if (group.z && RED.workspaces.isLocked(group.z)) { return }
|
|
38808
39081
|
var editing_node = group;
|
|
@@ -38917,6 +39190,7 @@ RED.editor = (function() {
|
|
|
38917
39190
|
|
|
38918
39191
|
function showEditFlowDialog(workspace, defaultTab) {
|
|
38919
39192
|
if (buildingEditDialog) { return }
|
|
39193
|
+
if (editStack.includes(workspace)) { return }
|
|
38920
39194
|
buildingEditDialog = true;
|
|
38921
39195
|
var activeEditPanes = [];
|
|
38922
39196
|
RED.view.state(RED.state.EDITING);
|
|
@@ -43208,7 +43482,7 @@ RED.editor = (function() {
|
|
|
43208
43482
|
|
|
43209
43483
|
nodes.forEach(async node => {
|
|
43210
43484
|
if (!node.getAttribute('mermaid-processed')) {
|
|
43211
|
-
const mermaidContent = node.
|
|
43485
|
+
const mermaidContent = atob($(node).data('c64'))
|
|
43212
43486
|
node.setAttribute('mermaid-processed', true)
|
|
43213
43487
|
try {
|
|
43214
43488
|
const { svg } = await mermaid.render('mermaid-render-'+Date.now()+'-'+(diagramIds++), mermaidContent);
|
|
@@ -44949,6 +45223,15 @@ RED.editor.codeEditor.monaco = (function() {
|
|
|
44949
45223
|
ed.gotoLine(row, col);
|
|
44950
45224
|
}
|
|
44951
45225
|
ed.type = type;
|
|
45226
|
+
|
|
45227
|
+
ed.onKeyDown((event) => {
|
|
45228
|
+
if (event.keyCode === monaco.KeyCode.Escape) {
|
|
45229
|
+
if (monacoWidgetsAreOpen(ed)) {
|
|
45230
|
+
event.preventDefault();
|
|
45231
|
+
}
|
|
45232
|
+
}
|
|
45233
|
+
})
|
|
45234
|
+
|
|
44952
45235
|
return ed;
|
|
44953
45236
|
}
|
|
44954
45237
|
|
|
@@ -44958,6 +45241,16 @@ RED.editor.codeEditor.monaco = (function() {
|
|
|
44958
45241
|
return true;
|
|
44959
45242
|
}
|
|
44960
45243
|
|
|
45244
|
+
function monacoWidgetsAreOpen(editor) {
|
|
45245
|
+
/** @type {HTMLElement} */
|
|
45246
|
+
const editorDomNode = editor.getDomNode()
|
|
45247
|
+
const suggestVisible = !!editorDomNode.querySelector('.monaco-editor .suggest-widget.visible');
|
|
45248
|
+
const parameterHintsVisible = !!editorDomNode.querySelector('.monaco-editor .parameter-hints-widget.visible');
|
|
45249
|
+
const findWidgetVisible = !!editorDomNode.querySelector('.monaco-editor .find-widget.visible');
|
|
45250
|
+
const renameInputVisible = !!editorDomNode.querySelector('.monaco-editor .rename-box');
|
|
45251
|
+
return suggestVisible || parameterHintsVisible || findWidgetVisible || renameInputVisible
|
|
45252
|
+
}
|
|
45253
|
+
|
|
44961
45254
|
return {
|
|
44962
45255
|
/**
|
|
44963
45256
|
* Editor type
|
|
@@ -45000,11 +45293,14 @@ RED.editor.codeEditor.monaco = (function() {
|
|
|
45000
45293
|
**/
|
|
45001
45294
|
RED.eventLog = (function() {
|
|
45002
45295
|
|
|
45003
|
-
|
|
45296
|
+
const template = '<script type="text/x-red" data-template-name="_eventLog"><div class="form-row node-text-editor-row"><div style="height: 100%;min-height: 150px;" class="node-text-editor" id="red-ui-event-log-editor"></div></div></script>';
|
|
45297
|
+
|
|
45298
|
+
let eventLogEditor;
|
|
45299
|
+
let backlog = [];
|
|
45300
|
+
let shown = false;
|
|
45301
|
+
|
|
45302
|
+
const activeLogs = new Set()
|
|
45004
45303
|
|
|
45005
|
-
var eventLogEditor;
|
|
45006
|
-
var backlog = [];
|
|
45007
|
-
var shown = false;
|
|
45008
45304
|
|
|
45009
45305
|
function appendLogLine(line) {
|
|
45010
45306
|
backlog.push(line);
|
|
@@ -45023,6 +45319,18 @@ RED.eventLog = (function() {
|
|
|
45023
45319
|
init: function() {
|
|
45024
45320
|
$(template).appendTo("#red-ui-editor-node-configs");
|
|
45025
45321
|
RED.actions.add("core:show-event-log",RED.eventLog.show);
|
|
45322
|
+
|
|
45323
|
+
const statusWidget = $('<button type="button" class="red-ui-footer-button red-ui-event-log-status" style="line-height: normal"><img style="width: 80%" src="red/images/spin.svg"/></div></button>');
|
|
45324
|
+
statusWidget.on("click", function(evt) {
|
|
45325
|
+
RED.actions.invoke("core:show-event-log");
|
|
45326
|
+
})
|
|
45327
|
+
RED.statusBar.add({
|
|
45328
|
+
id: "red-ui-event-log-status",
|
|
45329
|
+
align: "right",
|
|
45330
|
+
element: statusWidget
|
|
45331
|
+
});
|
|
45332
|
+
RED.statusBar.hide("red-ui-event-log-status");
|
|
45333
|
+
|
|
45026
45334
|
},
|
|
45027
45335
|
show: function() {
|
|
45028
45336
|
if (shown) {
|
|
@@ -45083,6 +45391,12 @@ RED.eventLog = (function() {
|
|
|
45083
45391
|
},
|
|
45084
45392
|
log: function(id,payload) {
|
|
45085
45393
|
var ts = (new Date(payload.ts)).toISOString()+" ";
|
|
45394
|
+
if (!payload.end) {
|
|
45395
|
+
activeLogs.add(id)
|
|
45396
|
+
} else {
|
|
45397
|
+
activeLogs.delete(id);
|
|
45398
|
+
}
|
|
45399
|
+
|
|
45086
45400
|
if (payload.type) {
|
|
45087
45401
|
ts += "["+payload.type+"] "
|
|
45088
45402
|
}
|
|
@@ -45096,6 +45410,11 @@ RED.eventLog = (function() {
|
|
|
45096
45410
|
appendLogLine(ts+line);
|
|
45097
45411
|
})
|
|
45098
45412
|
}
|
|
45413
|
+
if (activeLogs.size > 0) {
|
|
45414
|
+
RED.statusBar.show("red-ui-event-log-status");
|
|
45415
|
+
} else {
|
|
45416
|
+
RED.statusBar.hide("red-ui-event-log-status");
|
|
45417
|
+
}
|
|
45099
45418
|
},
|
|
45100
45419
|
startEvent: function(name) {
|
|
45101
45420
|
backlog.push("");
|
|
@@ -45337,14 +45656,6 @@ RED.eventLog = (function() {
|
|
|
45337
45656
|
editorStack = $("#red-ui-editor-stack");
|
|
45338
45657
|
$(window).on("resize", handleWindowResize);
|
|
45339
45658
|
RED.events.on("sidebar:resize",handleWindowResize);
|
|
45340
|
-
$("#red-ui-editor-shade").on("click", function() {
|
|
45341
|
-
if (!openingTray) {
|
|
45342
|
-
var tray = stack[stack.length-1];
|
|
45343
|
-
if (tray && tray.primaryButton) {
|
|
45344
|
-
tray.primaryButton.click();
|
|
45345
|
-
}
|
|
45346
|
-
}
|
|
45347
|
-
});
|
|
45348
45659
|
},
|
|
45349
45660
|
show: function show(options) {
|
|
45350
45661
|
lowerTrayZ();
|
|
@@ -49422,7 +49733,6 @@ RED.actionList = (function() {
|
|
|
49422
49733
|
addItem: function(container, i, nodeItem) {
|
|
49423
49734
|
// nodeItem can take multiple forms
|
|
49424
49735
|
// - A node type: {type: "inject", def: RED.nodes.getType("inject"), label: "Inject"}
|
|
49425
|
-
// - A flow suggestion: { suggestion: true, nodes: [] }
|
|
49426
49736
|
// - A placeholder suggestion: { suggestionPlaceholder: true, label: 'loading suggestions...' }
|
|
49427
49737
|
|
|
49428
49738
|
let nodeDef = nodeItem.def;
|
|
@@ -49502,7 +49812,17 @@ RED.actionList = (function() {
|
|
|
49502
49812
|
|
|
49503
49813
|
}
|
|
49504
49814
|
|
|
49815
|
+
let activeSuggestion
|
|
49505
49816
|
function updateSuggestion(nodeItem) {
|
|
49817
|
+
if (nodeItem === activeSuggestion) {
|
|
49818
|
+
return
|
|
49819
|
+
}
|
|
49820
|
+
if (!visible && nodeItem) {
|
|
49821
|
+
// Do not update suggestion if the dialog is not visible
|
|
49822
|
+
// - for example, whilst the dialog is closing and the user mouses over a new item
|
|
49823
|
+
return
|
|
49824
|
+
}
|
|
49825
|
+
activeSuggestion = nodeItem
|
|
49506
49826
|
if (suggestCallback) {
|
|
49507
49827
|
if (!nodeItem) {
|
|
49508
49828
|
suggestCallback(null);
|
|
@@ -49524,6 +49844,14 @@ RED.actionList = (function() {
|
|
|
49524
49844
|
}
|
|
49525
49845
|
}
|
|
49526
49846
|
function confirm(def) {
|
|
49847
|
+
if (!activeSuggestion) {
|
|
49848
|
+
// The user has hit Enter without selecting an entry in the list.
|
|
49849
|
+
// This means no suggestion has been shown yet - and the position recalculation
|
|
49850
|
+
// has not been done.
|
|
49851
|
+
// Trigger an update of the suggestion to get the position right before
|
|
49852
|
+
// applying.
|
|
49853
|
+
updateSuggestion(def)
|
|
49854
|
+
}
|
|
49527
49855
|
hide();
|
|
49528
49856
|
if (!def.nodes && !/^_action_:/.test(def.type)) {
|
|
49529
49857
|
typesUsed[def.type] = Date.now();
|
|
@@ -49559,6 +49887,7 @@ RED.actionList = (function() {
|
|
|
49559
49887
|
}
|
|
49560
49888
|
visible = true;
|
|
49561
49889
|
} else {
|
|
49890
|
+
updateSuggestion(null)
|
|
49562
49891
|
dialog.hide();
|
|
49563
49892
|
searchResultsDiv.hide();
|
|
49564
49893
|
}
|
|
@@ -49599,9 +49928,7 @@ RED.actionList = (function() {
|
|
|
49599
49928
|
},200);
|
|
49600
49929
|
}
|
|
49601
49930
|
function hide(fast) {
|
|
49602
|
-
|
|
49603
|
-
suggestCallback(null);
|
|
49604
|
-
}
|
|
49931
|
+
updateSuggestion(null)
|
|
49605
49932
|
if (visible) {
|
|
49606
49933
|
visible = false;
|
|
49607
49934
|
if (dialog !== null) {
|
|
@@ -49700,32 +50027,37 @@ RED.actionList = (function() {
|
|
|
49700
50027
|
|
|
49701
50028
|
let index = 0;
|
|
49702
50029
|
|
|
49703
|
-
|
|
49704
|
-
|
|
49705
|
-
|
|
49706
|
-
|
|
49707
|
-
|
|
49708
|
-
|
|
49709
|
-
|
|
49710
|
-
|
|
49711
|
-
|
|
49712
|
-
|
|
49713
|
-
|
|
49714
|
-
|
|
49715
|
-
|
|
49716
|
-
|
|
49717
|
-
|
|
49718
|
-
|
|
49719
|
-
|
|
49720
|
-
|
|
49721
|
-
|
|
49722
|
-
|
|
49723
|
-
|
|
49724
|
-
|
|
49725
|
-
|
|
49726
|
-
|
|
49727
|
-
|
|
49728
|
-
|
|
50030
|
+
if (!opts.context?.virtualLink) {
|
|
50031
|
+
// Check for suggestion plugins
|
|
50032
|
+
const suggestionPlugins = RED.plugins.getPluginsByType('node-red-flow-suggestion-source');
|
|
50033
|
+
if (suggestionPlugins.length > 0) {
|
|
50034
|
+
const suggestionItem = {
|
|
50035
|
+
suggestionPlaceholder: true,
|
|
50036
|
+
label: RED._('palette.loadingSuggestions'),
|
|
50037
|
+
separator: true,
|
|
50038
|
+
i: index++
|
|
50039
|
+
}
|
|
50040
|
+
searchResults.editableList('addItem', suggestionItem);
|
|
50041
|
+
suggestionPlugins[0].getSuggestions(opts.context).then(function (suggestedFlows) {
|
|
50042
|
+
searchResults.editableList('removeItem', suggestionItem);
|
|
50043
|
+
if (!Array.isArray(suggestedFlows)) {
|
|
50044
|
+
suggestedFlows = [suggestedFlows];
|
|
50045
|
+
}
|
|
50046
|
+
suggestedFlows.forEach(function(suggestion, index) {
|
|
50047
|
+
const suggestedItem = {
|
|
50048
|
+
suggestion: true,
|
|
50049
|
+
separator: index === suggestedFlows.length - 1,
|
|
50050
|
+
i: suggestionItem.i,
|
|
50051
|
+
...suggestion
|
|
50052
|
+
}
|
|
50053
|
+
if (!suggestion.label && suggestion.nodes && suggestion.nodes.length === 1 && suggestion.nodes[0].type) {
|
|
50054
|
+
suggestedItem.label = getTypeLabel(suggestion.nodes[0].type, RED.nodes.getType(suggestion.nodes[0].type));
|
|
50055
|
+
}
|
|
50056
|
+
searchResults.editableList('addItem', suggestedItem);
|
|
50057
|
+
})
|
|
50058
|
+
})
|
|
50059
|
+
}
|
|
50060
|
+
}
|
|
49729
50061
|
|
|
49730
50062
|
for(i=0;i<common.length;i++) {
|
|
49731
50063
|
let itemDef
|
|
@@ -49776,9 +50108,10 @@ RED.actionList = (function() {
|
|
|
49776
50108
|
}
|
|
49777
50109
|
|
|
49778
50110
|
return {
|
|
49779
|
-
show
|
|
50111
|
+
show,
|
|
49780
50112
|
refresh: refreshTypeList,
|
|
49781
|
-
hide
|
|
50113
|
+
hide,
|
|
50114
|
+
isVisible: () => visible
|
|
49782
50115
|
};
|
|
49783
50116
|
|
|
49784
50117
|
})();
|