@node-red/editor-client 2.2.2 → 2.2.3

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/public/red/red.js CHANGED
@@ -343,8 +343,21 @@ var RED = (function() {
343
343
  if (/^#flow\/.+$/.test(currentHash)) {
344
344
  RED.workspaces.show(currentHash.substring(6),true);
345
345
  }
346
- if (RED.workspaces.active() === 0 && RED.workspaces.count() > 0) {
347
- RED.workspaces.show(RED.nodes.getWorkspaceOrder()[0])
346
+ if (RED.workspaces.count() > 0) {
347
+ const hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}");
348
+ const workspaces = RED.nodes.getWorkspaceOrder();
349
+ if (RED.workspaces.active() === 0) {
350
+ for (let index = 0; index < workspaces.length; index++) {
351
+ const ws = workspaces[index];
352
+ if (!hiddenTabs[ws]) {
353
+ RED.workspaces.show(ws);
354
+ break;
355
+ }
356
+ }
357
+ }
358
+ if (RED.workspaces.active() === 0) {
359
+ RED.workspaces.show(workspaces[0]);
360
+ }
348
361
  }
349
362
  } catch(err) {
350
363
  console.warn(err);
@@ -552,7 +565,7 @@ var RED = (function() {
552
565
  var parts = topic.split("/");
553
566
  var node = RED.nodes.node(parts[1]);
554
567
  if (node) {
555
- if (msg.hasOwnProperty("text") && msg.text !== null && /^[a-zA-Z]/.test(msg.text)) {
568
+ if (msg.hasOwnProperty("text") && msg.text !== null && /^[@a-zA-Z]/.test(msg.text)) {
556
569
  msg.text = node._(msg.text.toString(),{defaultValue:msg.text.toString()});
557
570
  }
558
571
  node.status = msg;
@@ -5725,7 +5738,7 @@ RED.nodes = (function() {
5725
5738
  n = new_nodes[i];
5726
5739
  if (n.wires) {
5727
5740
  for (var w1=0;w1<n.wires.length;w1++) {
5728
- var wires = (n.wires[w1] instanceof Array)?n.wires[w1]:[n.wires[w1]];
5741
+ var wires = (Array.isArray(n.wires[w1]))?n.wires[w1]:[n.wires[w1]];
5729
5742
  for (var w2=0;w2<wires.length;w2++) {
5730
5743
  if (node_map.hasOwnProperty(wires[w2])) {
5731
5744
  if (n.z === node_map[wires[w2]].z) {
@@ -12987,7 +13000,7 @@ RED.tabs = (function() {
12987
13000
  }
12988
13001
 
12989
13002
  // link.attr("title",tab.label);
12990
- RED.popover.tooltip(link,function() { return tab.label})
13003
+ RED.popover.tooltip(link,function() { return RED.utils.sanitize(tab.label); });
12991
13004
 
12992
13005
  if (options.onadd) {
12993
13006
  options.onadd(tab);
@@ -15240,205 +15253,208 @@ RED.deploy = (function() {
15240
15253
  },delta);
15241
15254
  });
15242
15255
  }
15243
- function save(skipValidation,force) {
15244
- if (!$("#red-ui-header-button-deploy").hasClass("disabled")) {
15245
- if (!RED.user.hasPermission("flows.write")) {
15246
- RED.notify(RED._("user.errors.deploy"),"error");
15247
- return;
15248
- }
15249
- if (!skipValidation) {
15250
- var hasUnknown = false;
15251
- var hasInvalid = false;
15252
- var hasUnusedConfig = false;
15253
-
15254
- var unknownNodes = [];
15255
- var invalidNodes = [];
15256
+ function save(skipValidation, force) {
15257
+ if ($("#red-ui-header-button-deploy").hasClass("disabled")) {
15258
+ return; //deploy is disabled
15259
+ }
15260
+ if ($("#red-ui-header-shade").is(":visible")) {
15261
+ return; //deploy is shaded
15262
+ }
15263
+ if (!RED.user.hasPermission("flows.write")) {
15264
+ RED.notify(RED._("user.errors.deploy"), "error");
15265
+ return;
15266
+ }
15267
+ let hasUnusedConfig = false;
15268
+ if (!skipValidation) {
15269
+ let hasUnknown = false;
15270
+ let hasInvalid = false;
15271
+ const unknownNodes = [];
15272
+ const invalidNodes = [];
15256
15273
 
15257
- RED.nodes.eachConfig(function(node) {
15258
- if (node.valid === undefined) {
15259
- RED.editor.validateNode(node);
15274
+ RED.nodes.eachConfig(function (node) {
15275
+ if (node.valid === undefined) {
15276
+ RED.editor.validateNode(node);
15277
+ }
15278
+ if (!node.valid && !node.d) {
15279
+ invalidNodes.push(getNodeInfo(node));
15280
+ }
15281
+ if (node.type === "unknown") {
15282
+ if (unknownNodes.indexOf(node.name) == -1) {
15283
+ unknownNodes.push(node.name);
15260
15284
  }
15261
- if (!node.valid && !node.d) {
15262
- invalidNodes.push(getNodeInfo(node));
15285
+ }
15286
+ });
15287
+ RED.nodes.eachNode(function (node) {
15288
+ if (!node.valid && !node.d) {
15289
+ invalidNodes.push(getNodeInfo(node));
15290
+ }
15291
+ if (node.type === "unknown") {
15292
+ if (unknownNodes.indexOf(node.name) == -1) {
15293
+ unknownNodes.push(node.name);
15263
15294
  }
15264
- if (node.type === "unknown") {
15265
- if (unknownNodes.indexOf(node.name) == -1) {
15266
- unknownNodes.push(node.name);
15295
+ }
15296
+ });
15297
+ hasUnknown = unknownNodes.length > 0;
15298
+ hasInvalid = invalidNodes.length > 0;
15299
+
15300
+ const unusedConfigNodes = [];
15301
+ RED.nodes.eachConfig(function (node) {
15302
+ if ((node._def.hasUsers !== false) && (node.users.length === 0)) {
15303
+ unusedConfigNodes.push(getNodeInfo(node));
15304
+ hasUnusedConfig = true;
15305
+ }
15306
+ });
15307
+
15308
+ let showWarning = false;
15309
+ let notificationMessage;
15310
+ let notificationButtons = [];
15311
+ let notification;
15312
+ if (hasUnknown && !ignoreDeployWarnings.unknown) {
15313
+ showWarning = true;
15314
+ notificationMessage = "<p>" + RED._('deploy.confirm.unknown') + "</p>" +
15315
+ '<ul class="red-ui-deploy-dialog-confirm-list"><li>' + cropList(unknownNodes).map(function (n) { return sanitize(n) }).join("</li><li>") + "</li></ul><p>" +
15316
+ RED._('deploy.confirm.confirm') +
15317
+ "</p>";
15318
+
15319
+ notificationButtons = [
15320
+ {
15321
+ id: "red-ui-deploy-dialog-confirm-deploy-deploy",
15322
+ text: RED._("deploy.confirm.button.confirm"),
15323
+ class: "primary",
15324
+ click: function () {
15325
+ save(true);
15326
+ notification.close();
15267
15327
  }
15268
- }
15269
- });
15270
- RED.nodes.eachNode(function(node) {
15271
- if (!node.valid && !node.d) {
15272
- invalidNodes.push(getNodeInfo(node));
15273
15328
  }
15274
- if (node.type === "unknown") {
15275
- if (unknownNodes.indexOf(node.name) == -1) {
15276
- unknownNodes.push(node.name);
15329
+ ];
15330
+ } else if (hasInvalid && !ignoreDeployWarnings.invalid) {
15331
+ showWarning = true;
15332
+ invalidNodes.sort(sortNodeInfo);
15333
+
15334
+ notificationMessage = "<p>" + RED._('deploy.confirm.improperlyConfigured') + "</p>" +
15335
+ '<ul class="red-ui-deploy-dialog-confirm-list"><li>' + cropList(invalidNodes.map(function (A) { return sanitize((A.tab ? "[" + A.tab + "] " : "") + A.label + " (" + A.type + ")") })).join("</li><li>") + "</li></ul><p>" +
15336
+ RED._('deploy.confirm.confirm') +
15337
+ "</p>";
15338
+ notificationButtons = [
15339
+ {
15340
+ id: "red-ui-deploy-dialog-confirm-deploy-deploy",
15341
+ text: RED._("deploy.confirm.button.confirm"),
15342
+ class: "primary",
15343
+ click: function () {
15344
+ save(true);
15345
+ notification.close();
15277
15346
  }
15278
15347
  }
15279
- });
15280
- hasUnknown = unknownNodes.length > 0;
15281
- hasInvalid = invalidNodes.length > 0;
15282
-
15283
- var unusedConfigNodes = [];
15284
- RED.nodes.eachConfig(function(node) {
15285
- if ((node._def.hasUsers !== false) && (node.users.length === 0)) {
15286
- unusedConfigNodes.push(getNodeInfo(node));
15287
- hasUnusedConfig = true;
15348
+ ];
15349
+ }
15350
+ if (showWarning) {
15351
+ notificationButtons.unshift(
15352
+ {
15353
+ text: RED._("common.label.cancel"),
15354
+ click: function () {
15355
+ notification.close();
15356
+ }
15288
15357
  }
15358
+ );
15359
+ notification = RED.notify(notificationMessage, {
15360
+ modal: true,
15361
+ fixed: true,
15362
+ buttons: notificationButtons
15289
15363
  });
15290
-
15291
- var showWarning = false;
15292
- var notificationMessage;
15293
- var notificationButtons = [];
15294
- var notification;
15295
- if (hasUnknown && !ignoreDeployWarnings.unknown) {
15296
- showWarning = true;
15297
- notificationMessage = "<p>"+RED._('deploy.confirm.unknown')+"</p>"+
15298
- '<ul class="red-ui-deploy-dialog-confirm-list"><li>'+cropList(unknownNodes).map(function(n) { return sanitize(n) }).join("</li><li>")+"</li></ul><p>"+
15299
- RED._('deploy.confirm.confirm')+
15300
- "</p>";
15301
-
15302
- notificationButtons= [
15303
- {
15304
- id: "red-ui-deploy-dialog-confirm-deploy-deploy",
15305
- text: RED._("deploy.confirm.button.confirm"),
15306
- class: "primary",
15307
- click: function() {
15308
- save(true);
15309
- notification.close();
15310
- }
15311
- }
15312
- ];
15313
- } else if (hasInvalid && !ignoreDeployWarnings.invalid) {
15314
- showWarning = true;
15315
- invalidNodes.sort(sortNodeInfo);
15316
-
15317
- notificationMessage = "<p>"+RED._('deploy.confirm.improperlyConfigured')+"</p>"+
15318
- '<ul class="red-ui-deploy-dialog-confirm-list"><li>'+cropList(invalidNodes.map(function(A) { return sanitize( (A.tab?"["+A.tab+"] ":"")+A.label+" ("+A.type+")")})).join("</li><li>")+"</li></ul><p>"+
15319
- RED._('deploy.confirm.confirm')+
15320
- "</p>";
15321
- notificationButtons= [
15322
- {
15323
- id: "red-ui-deploy-dialog-confirm-deploy-deploy",
15324
- text: RED._("deploy.confirm.button.confirm"),
15325
- class: "primary",
15326
- click: function() {
15327
- save(true);
15328
- notification.close();
15329
- }
15330
- }
15331
- ];
15332
- }
15333
- if (showWarning) {
15334
- notificationButtons.unshift(
15335
- {
15336
- text: RED._("common.label.cancel"),
15337
- click: function() {
15338
- notification.close();
15339
- }
15340
- }
15341
- );
15342
- notification = RED.notify(notificationMessage,{
15343
- modal: true,
15344
- fixed: true,
15345
- buttons:notificationButtons
15346
- });
15347
- return;
15348
- }
15364
+ return;
15349
15365
  }
15366
+ }
15350
15367
 
15351
- var nns = RED.nodes.createCompleteNodeSet();
15368
+ const nns = RED.nodes.createCompleteNodeSet();
15369
+ const startTime = Date.now();
15352
15370
 
15353
- var startTime = Date.now();
15354
- $(".red-ui-deploy-button-content").css('opacity',0);
15355
- $(".red-ui-deploy-button-spinner").show();
15356
- $("#red-ui-header-button-deploy").addClass("disabled");
15371
+ $(".red-ui-deploy-button-content").css('opacity', 0);
15372
+ $(".red-ui-deploy-button-spinner").show();
15373
+ $("#red-ui-header-button-deploy").addClass("disabled");
15357
15374
 
15358
- var data = {flows:nns};
15375
+ const data = { flows: nns };
15359
15376
 
15360
- if (!force) {
15361
- data.rev = RED.nodes.version();
15362
- }
15377
+ if (!force) {
15378
+ data.rev = RED.nodes.version();
15379
+ }
15363
15380
 
15364
- deployInflight = true;
15365
- $("#red-ui-header-shade").show();
15366
- $("#red-ui-editor-shade").show();
15367
- $("#red-ui-palette-shade").show();
15368
- $("#red-ui-sidebar-shade").show();
15369
- $.ajax({
15370
- url:"flows",
15371
- type: "POST",
15372
- data: JSON.stringify(data),
15373
- contentType: "application/json; charset=utf-8",
15374
- headers: {
15375
- "Node-RED-Deployment-Type":deploymentType
15381
+ deployInflight = true;
15382
+ $("#red-ui-header-shade").show();
15383
+ $("#red-ui-editor-shade").show();
15384
+ $("#red-ui-palette-shade").show();
15385
+ $("#red-ui-sidebar-shade").show();
15386
+ $.ajax({
15387
+ url: "flows",
15388
+ type: "POST",
15389
+ data: JSON.stringify(data),
15390
+ contentType: "application/json; charset=utf-8",
15391
+ headers: {
15392
+ "Node-RED-Deployment-Type": deploymentType
15393
+ }
15394
+ }).done(function (data, textStatus, xhr) {
15395
+ RED.nodes.dirty(false);
15396
+ RED.nodes.version(data.rev);
15397
+ RED.nodes.originalFlow(nns);
15398
+ if (hasUnusedConfig) {
15399
+ RED.notify(
15400
+ '<p>' + RED._("deploy.successfulDeploy") + '</p>' +
15401
+ '<p>' + RED._("deploy.unusedConfigNodes") + ' <a href="#" onclick="RED.sidebar.config.show(true); return false;">' + RED._("deploy.unusedConfigNodesLink") + '</a></p>', "success", false, 6000);
15402
+ } else {
15403
+ RED.notify('<p>' + RED._("deploy.successfulDeploy") + '</p>', "success");
15404
+ }
15405
+ RED.nodes.eachNode(function (node) {
15406
+ if (node.changed) {
15407
+ node.dirty = true;
15408
+ node.changed = false;
15376
15409
  }
15377
- }).done(function(data,textStatus,xhr) {
15378
- RED.nodes.dirty(false);
15379
- RED.nodes.version(data.rev);
15380
- RED.nodes.originalFlow(nns);
15381
- if (hasUnusedConfig) {
15382
- RED.notify(
15383
- '<p>'+RED._("deploy.successfulDeploy")+'</p>'+
15384
- '<p>'+RED._("deploy.unusedConfigNodes")+' <a href="#" onclick="RED.sidebar.config.show(true); return false;">'+RED._("deploy.unusedConfigNodesLink")+'</a></p>',"success",false,6000);
15385
- } else {
15386
- RED.notify('<p>'+RED._("deploy.successfulDeploy")+'</p>',"success");
15410
+ if (node.moved) {
15411
+ node.dirty = true;
15412
+ node.moved = false;
15387
15413
  }
15388
- RED.nodes.eachNode(function(node) {
15389
- if (node.changed) {
15390
- node.dirty = true;
15391
- node.changed = false;
15392
- }
15393
- if (node.moved) {
15394
- node.dirty = true;
15395
- node.moved = false;
15396
- }
15397
- if(node.credentials) {
15398
- delete node.credentials;
15399
- }
15400
- });
15401
- RED.nodes.eachConfig(function (confNode) {
15402
- confNode.changed = false;
15403
- if (confNode.credentials) {
15404
- delete confNode.credentials;
15405
- }
15406
- });
15407
- RED.nodes.eachSubflow(function(subflow) {
15408
- subflow.changed = false;
15409
- });
15410
- RED.nodes.eachWorkspace(function(ws) {
15411
- ws.changed = false;
15412
- });
15413
- // Once deployed, cannot undo back to a clean state
15414
- RED.history.markAllDirty();
15415
- RED.view.redraw();
15416
- RED.events.emit("deploy");
15417
- }).fail(function(xhr,textStatus,err) {
15418
- RED.nodes.dirty(true);
15419
- $("#red-ui-header-button-deploy").removeClass("disabled");
15420
- if (xhr.status === 401) {
15421
- RED.notify(RED._("deploy.deployFailed",{message:RED._("user.notAuthorized")}),"error");
15422
- } else if (xhr.status === 409) {
15423
- resolveConflict(nns, true);
15424
- } else if (xhr.responseText) {
15425
- RED.notify(RED._("deploy.deployFailed",{message:xhr.responseText}),"error");
15426
- } else {
15427
- RED.notify(RED._("deploy.deployFailed",{message:RED._("deploy.errors.noResponse")}),"error");
15414
+ if (node.credentials) {
15415
+ delete node.credentials;
15428
15416
  }
15429
- }).always(function() {
15430
- deployInflight = false;
15431
- var delta = Math.max(0,300-(Date.now()-startTime));
15432
- setTimeout(function() {
15433
- $(".red-ui-deploy-button-content").css('opacity',1);
15434
- $(".red-ui-deploy-button-spinner").hide();
15435
- $("#red-ui-header-shade").hide();
15436
- $("#red-ui-editor-shade").hide();
15437
- $("#red-ui-palette-shade").hide();
15438
- $("#red-ui-sidebar-shade").hide();
15439
- },delta);
15440
15417
  });
15441
- }
15418
+ RED.nodes.eachConfig(function (confNode) {
15419
+ confNode.changed = false;
15420
+ if (confNode.credentials) {
15421
+ delete confNode.credentials;
15422
+ }
15423
+ });
15424
+ RED.nodes.eachSubflow(function (subflow) {
15425
+ subflow.changed = false;
15426
+ });
15427
+ RED.nodes.eachWorkspace(function (ws) {
15428
+ ws.changed = false;
15429
+ });
15430
+ // Once deployed, cannot undo back to a clean state
15431
+ RED.history.markAllDirty();
15432
+ RED.view.redraw();
15433
+ RED.events.emit("deploy");
15434
+ }).fail(function (xhr, textStatus, err) {
15435
+ RED.nodes.dirty(true);
15436
+ $("#red-ui-header-button-deploy").removeClass("disabled");
15437
+ if (xhr.status === 401) {
15438
+ RED.notify(RED._("deploy.deployFailed", { message: RED._("user.notAuthorized") }), "error");
15439
+ } else if (xhr.status === 409) {
15440
+ resolveConflict(nns, true);
15441
+ } else if (xhr.responseText) {
15442
+ RED.notify(RED._("deploy.deployFailed", { message: xhr.responseText }), "error");
15443
+ } else {
15444
+ RED.notify(RED._("deploy.deployFailed", { message: RED._("deploy.errors.noResponse") }), "error");
15445
+ }
15446
+ }).always(function () {
15447
+ deployInflight = false;
15448
+ const delta = Math.max(0, 300 - (Date.now() - startTime));
15449
+ setTimeout(function () {
15450
+ $(".red-ui-deploy-button-content").css('opacity', 1);
15451
+ $(".red-ui-deploy-button-spinner").hide();
15452
+ $("#red-ui-header-shade").hide();
15453
+ $("#red-ui-editor-shade").hide();
15454
+ $("#red-ui-palette-shade").hide();
15455
+ $("#red-ui-sidebar-shade").hide();
15456
+ }, delta);
15457
+ });
15442
15458
  }
15443
15459
  return {
15444
15460
  init: init,
@@ -18661,9 +18677,22 @@ RED.workspaces = (function() {
18661
18677
  onselect: "core:show-last-hidden-flow"
18662
18678
  }
18663
18679
  ]
18664
- if (hideStack.length > 0) {
18680
+ let hiddenFlows = new Set()
18681
+ for (let i = 0; i < hideStack.length; i++) {
18682
+ let ids = hideStack[i]
18683
+ if (!Array.isArray(ids)) {
18684
+ ids = [ids]
18685
+ }
18686
+ ids.forEach(id => {
18687
+ if (RED.nodes.workspace(id)) {
18688
+ hiddenFlows.add(id)
18689
+ }
18690
+ })
18691
+ }
18692
+ const flowCount = hiddenFlows.size;
18693
+ if (flowCount > 0) {
18665
18694
  menuItems.unshift({
18666
- label: RED._("workspace.hiddenFlows",{count: hideStack.length}),
18695
+ label: RED._("workspace.hiddenFlows",{count: flowCount}),
18667
18696
  onselect: "core:list-hidden-flows"
18668
18697
  })
18669
18698
  }
@@ -19258,6 +19287,7 @@ RED.view = (function() {
19258
19287
  .on("mousedown", canvasMouseDown)
19259
19288
  .on("mouseup", canvasMouseUp)
19260
19289
  .on("mouseenter", function() {
19290
+ d3.select(document).on('mouseup.red-ui-workspace-tracker', null)
19261
19291
  if (lasso) {
19262
19292
  if (d3.event.buttons !== 1) {
19263
19293
  lasso.remove();
@@ -19273,6 +19303,7 @@ RED.view = (function() {
19273
19303
  }
19274
19304
  }
19275
19305
  })
19306
+ .on("mouseleave", canvasMouseLeave)
19276
19307
  .on("touchend", function() {
19277
19308
  d3.event.preventDefault();
19278
19309
  clearTimeout(touchStartTime);
@@ -19412,6 +19443,9 @@ RED.view = (function() {
19412
19443
  drag_lines = [];
19413
19444
 
19414
19445
  RED.events.on("workspace:change",function(event) {
19446
+ // Just in case the mouse left the workspace whilst doing an action,
19447
+ // put us back into default mode so the refresh works
19448
+ mouse_mode = 0
19415
19449
  if (event.old !== 0) {
19416
19450
  workspaceScrollPositions[event.old] = {
19417
19451
  left:chart.scrollLeft(),
@@ -20775,10 +20809,19 @@ RED.view = (function() {
20775
20809
  redraw();
20776
20810
  }
20777
20811
  }
20778
-
20812
+ function canvasMouseLeave() {
20813
+ if (mouse_mode !== 0 && d3.event.buttons !== 0) {
20814
+ d3.select(document).on('mouseup.red-ui-workspace-tracker', function() {
20815
+ d3.select(document).on('mouseup.red-ui-workspace-tracker', null)
20816
+ canvasMouseUp.call(this)
20817
+ })
20818
+ }
20819
+ }
20779
20820
  function canvasMouseUp() {
20780
20821
  lastClickPosition = [d3.event.offsetX/scaleFactor,d3.event.offsetY/scaleFactor];
20781
- if (RED.view.DEBUG) { console.warn("canvasMouseUp", mouse_mode); }
20822
+ if (RED.view.DEBUG) {
20823
+ console.warn("canvasMouseUp", { mouse_mode, point: d3.mouse(this), event: d3.event });
20824
+ }
20782
20825
  var i;
20783
20826
  var historyEvent;
20784
20827
  if (mouse_mode === RED.state.PANNING) {
@@ -21418,7 +21461,7 @@ RED.view = (function() {
21418
21461
  var removedEntities = RED.nodes.remove(node.id);
21419
21462
  removedNodes.push(node);
21420
21463
  removedNodes = removedNodes.concat(removedEntities.nodes);
21421
- addToRemovedLinks(removedNodes.removedLinks);
21464
+ addToRemovedLinks(removedEntities.links);
21422
21465
  if (node.g) {
21423
21466
  var group = RED.nodes.group(node.g);
21424
21467
  if (selectedGroups.indexOf(group) === -1) {
@@ -22622,6 +22665,9 @@ RED.view = (function() {
22622
22665
  function portMouseOutProxy(e) { portMouseOut(d3.select(this), this.__data__,this.__portType__,this.__portIndex__, e); }
22623
22666
 
22624
22667
  function linkMouseDown(d) {
22668
+ if (RED.view.DEBUG) {
22669
+ console.warn("linkMouseDown", { mouse_mode, point: d3.mouse(this), event: d3.event });
22670
+ }
22625
22671
  if (mouse_mode === RED.state.SELECTING_NODE) {
22626
22672
  d3.event.stopPropagation();
22627
22673
  return;
@@ -24655,7 +24701,7 @@ RED.view = (function() {
24655
24701
  node.dirty = true;
24656
24702
  RED.workspaces.show(node.z);
24657
24703
 
24658
- var screenSize = [chart.width()/scaleFactor,chart.height()/scaleFactor];
24704
+ var screenSize = [chart[0].clientWidth/scaleFactor,chart[0].clientHeight/scaleFactor];
24659
24705
  var scrollPos = [chart.scrollLeft()/scaleFactor,chart.scrollTop()/scaleFactor];
24660
24706
  var cx = node.x;
24661
24707
  var cy = node.y;
@@ -26496,7 +26542,7 @@ RED.palette = (function() {
26496
26542
  }
26497
26543
 
26498
26544
  function escapeCategory(category) {
26499
- return category.replace(/[ /.]/g,"_");
26545
+ return category.replace(/[\x00-\x2c\x2e-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]/g,"_");
26500
26546
  }
26501
26547
  function addNodeType(nt,def) {
26502
26548
  if (getPaletteNode(nt).length) {
@@ -29072,7 +29118,7 @@ RED.sidebar.config = (function() {
29072
29118
  refreshConfigNodeList();
29073
29119
  }
29074
29120
  });
29075
- RED.popover.tooltip($('#red-ui-sidebar-config-filter-all'), RED._("sidebar.config.showAllUnusedConfigNodes"));
29121
+ RED.popover.tooltip($('#red-ui-sidebar-config-filter-all'), RED._("sidebar.config.showAllConfigNodes"));
29076
29122
  RED.popover.tooltip($('#red-ui-sidebar-config-filter-unused'), RED._("sidebar.config.showAllUnusedConfigNodes"));
29077
29123
 
29078
29124
  }
@@ -32673,8 +32719,7 @@ RED.editor = (function() {
32673
32719
  if (!node._def.defaults || !node._def.defaults.hasOwnProperty("icon")) {
32674
32720
  var icon = $("#red-ui-editor-node-icon").val()||"";
32675
32721
  if (!this.isDefaultIcon) {
32676
- if ((icon !== node.icon) &&
32677
- (icon !== "")) {
32722
+ if ((node.icon && icon !== node.icon) || (!node.icon && icon !== "")) {
32678
32723
  editState.changes.icon = node.icon;
32679
32724
  node.icon = icon;
32680
32725
  editState.changed = true;
@@ -33478,7 +33523,7 @@ RED.editor = (function() {
33478
33523
  newValue = "";
33479
33524
  }
33480
33525
  }
33481
- if (node[d] != newValue) {
33526
+ if (!isEqual(node[d], newValue)) {
33482
33527
  if (node._def.defaults[d].type) {
33483
33528
  // Change to a related config node
33484
33529
  var configNode = RED.nodes.node(node[d]);
@@ -33510,6 +33555,23 @@ RED.editor = (function() {
33510
33555
  }
33511
33556
  });
33512
33557
 
33558
+ /**
33559
+ * Compares `newValue` with `originalValue` for equality.
33560
+ * @param {*} originalValue Original value
33561
+ * @param {*} newValue New value
33562
+ * @returns {boolean} true if originalValue equals newValue, otherwise false
33563
+ */
33564
+ function isEqual(originalValue, newValue) {
33565
+ try {
33566
+ if(originalValue == newValue) {
33567
+ return true;
33568
+ }
33569
+ return JSON.stringify(originalValue) === JSON.stringify(newValue);
33570
+ } catch (err) {
33571
+ return false;
33572
+ }
33573
+ }
33574
+
33513
33575
  /**
33514
33576
  * Update the node credentials from the edit form
33515
33577
  * @param node - the node containing the credentials
@@ -34296,8 +34358,12 @@ RED.editor = (function() {
34296
34358
  style: "width:100%",
34297
34359
  class: "node-input-env-value",
34298
34360
  type: "text",
34299
- }).attr("autocomplete","disable").appendTo(envRow)
34300
- valueField.typedInput({default:'str',types:isTemplateNode?DEFAULT_ENV_TYPE_LIST:DEFAULT_ENV_TYPE_LIST_INC_CRED});
34361
+ }).attr("autocomplete","disable").appendTo(envRow);
34362
+ var types = (opt.ui && opt.ui.opts && opt.ui.opts.types);
34363
+ if (!types) {
34364
+ types = isTemplateNode ? DEFAULT_ENV_TYPE_LIST : DEFAULT_ENV_TYPE_LIST_INC_CRED;
34365
+ }
34366
+ valueField.typedInput({default:'str',types:types});
34301
34367
  valueField.typedInput('type', opt.type);
34302
34368
  if (opt.type === "cred") {
34303
34369
  if (opt.value) {
@@ -34349,6 +34415,11 @@ RED.editor = (function() {
34349
34415
  }
34350
34416
  opt.ui.label = opt.ui.label || {};
34351
34417
  opt.ui.type = opt.ui.type || "input";
34418
+ if ((opt.ui.type === "cred") &&
34419
+ opt.ui.opts &&
34420
+ opt.ui.opts.types) {
34421
+ opt.ui.type = "input";
34422
+ }
34352
34423
 
34353
34424
  var uiRow = $('<div/>').appendTo(container).hide();
34354
34425
  // save current info for reverting on cancel
@@ -36218,7 +36289,7 @@ RED.editor = (function() {
36218
36289
  'b': { before:"**", after: "**", tooltip: RED._("markdownEditor.bold")},
36219
36290
  'i': { before:"_", after: "_", tooltip: RED._("markdownEditor.italic")},
36220
36291
  'code': { before:"`", after: "`", tooltip: RED._("markdownEditor.code")},
36221
- 'ol': { before:" * ", newline: true, tooltip: RED._("markdownEditor.ordered-list")},
36292
+ 'ol': { before:" 1. ", newline: true, tooltip: RED._("markdownEditor.ordered-list")},
36222
36293
  'ul': { before:" - ", newline: true, tooltip: RED._("markdownEditor.unordered-list")},
36223
36294
  'bq': { before:"> ", newline: true, tooltip: RED._("markdownEditor.quote")},
36224
36295
  'link': { before:"[", after: "]()", tooltip: RED._("markdownEditor.link")},
@@ -40033,106 +40104,112 @@ RED.library = (function() {
40033
40104
  options.onconfirm(item);
40034
40105
  }
40035
40106
  });
40036
- var itemTools = $("<div>").css({position: "absolute",bottom:"6px",right:"8px"});
40037
- var menuButton = $('<button class="red-ui-button red-ui-button-small" type="button"><i class="fa fa-ellipsis-h"></i></button>')
40038
- .on("click", function(evt) {
40039
- evt.preventDefault();
40040
- evt.stopPropagation();
40041
- var elementPos = menuButton.offset();
40042
-
40043
- var menuOptionMenu = RED.menu.init({id:"red-ui-library-browser-menu",
40044
- options: [
40045
- {id:"red-ui-library-browser-menu-addFolder",label:RED._("library.newFolder"), onselect: function() {
40046
- var defaultFolderName = "new-folder";
40047
- var defaultFolderNameMatches = {};
40048
-
40049
- var selected = dirList.treeList('selected');
40050
- if (!selected.children) {
40051
- selected = selected.parent;
40052
- }
40053
- var complete = function() {
40054
- selected.children.forEach(function(c) {
40055
- if (/^new-folder/.test(c.label)) {
40056
- defaultFolderNameMatches[c.label] = true
40057
- }
40058
- });
40059
- var folderIndex = 2;
40060
- while(defaultFolderNameMatches[defaultFolderName]) {
40061
- defaultFolderName = "new-folder-"+(folderIndex++)
40062
- }
40063
-
40064
- selected.treeList.expand();
40065
- var input = $('<input type="text" class="red-ui-treeList-input">').val(defaultFolderName);
40066
- var newItem = {
40067
- icon: "fa fa-folder-o",
40068
- children:[],
40069
- path: selected.path,
40070
- element: input
40071
- }
40072
- var confirmAdd = function() {
40073
- var val = input.val().trim();
40074
- if (val === "") {
40075
- cancelAdd();
40076
- return;
40077
- } else {
40078
- for (var i=0;i<selected.children.length;i++) {
40079
- if (selected.children[i].label === val) {
40080
- cancelAdd();
40081
- return;
40082
- }
40083
- }
40084
- }
40085
- newItem.treeList.remove();
40086
- var finalItem = {
40087
- library: selected.library,
40088
- type: selected.type,
40089
- icon: "fa fa-folder",
40090
- children:[],
40091
- label: val,
40092
- path: newItem.path+val+"/"
40093
- }
40094
- selected.treeList.addChild(finalItem,true);
40095
- }
40096
- var cancelAdd = function() {
40097
- newItem.treeList.remove();
40098
- }
40099
- input.on('keydown', function(evt) {
40100
- evt.stopPropagation();
40101
- if (evt.keyCode === 13) {
40102
- confirmAdd();
40103
- } else if (evt.keyCode === 27) {
40104
- cancelAdd();
40105
- }
40106
- })
40107
- input.on("blur", function() {
40108
- confirmAdd();
40109
- })
40110
- selected.treeList.addChild(newItem);
40111
- setTimeout(function() {
40112
- input.trigger("focus");
40113
- input.select();
40114
- },400);
40115
- }
40116
- selected.treeList.expand(complete);
40117
-
40118
- } },
40119
- // null,
40120
- // {id:"red-ui-library-browser-menu-rename",label:"Rename", onselect: function() {} },
40121
- // {id:"red-ui-library-browser-menu-delete",label:"Delete", onselect: function() {} }
40122
- ]
40123
- }).on('mouseleave', function(){ $(this).remove(); dirList.focus() })
40124
- .on('mouseup', function() { var self = $(this);self.hide(); dirList.focus(); setTimeout(function() { self.remove() },100)})
40125
- .appendTo("body");
40126
- menuOptionMenu.css({
40127
- position: "absolute",
40128
- top: elementPos.top+"px",
40129
- left: (elementPos.left - menuOptionMenu.width() + 20)+"px"
40130
- }).show();
40131
-
40132
- }).appendTo(itemTools);
40107
+ var itemTools = null;
40133
40108
  if (options.folderTools) {
40134
40109
  dirList.on('treelistselect', function(event, item) {
40135
40110
  if (item.writable !== false && item.treeList) {
40111
+ if (itemTools) {
40112
+ itemTools.remove();
40113
+ }
40114
+ itemTools = $("<div>").css({position: "absolute",bottom:"6px",right:"8px"});
40115
+ var menuButton = $('<button class="red-ui-button red-ui-button-small" type="button"><i class="fa fa-ellipsis-h"></i></button>')
40116
+ .on("click", function(evt) {
40117
+ evt.preventDefault();
40118
+ evt.stopPropagation();
40119
+ var elementPos = menuButton.offset();
40120
+
40121
+ var menuOptionMenu
40122
+ = RED.menu.init({id:"red-ui-library-browser-menu",
40123
+ options: [
40124
+ {id:"red-ui-library-browser-menu-addFolder",label:RED._("library.newFolder"), onselect: function() {
40125
+ var defaultFolderName = "new-folder";
40126
+ var defaultFolderNameMatches = {};
40127
+
40128
+ var selected = dirList.treeList('selected');
40129
+ if (!selected.children) {
40130
+ selected = selected.parent;
40131
+ }
40132
+ var complete = function() {
40133
+ selected.children.forEach(function(c) {
40134
+ if (/^new-folder/.test(c.label)) {
40135
+ defaultFolderNameMatches[c.label] = true
40136
+ }
40137
+ });
40138
+ var folderIndex = 2;
40139
+ while(defaultFolderNameMatches[defaultFolderName]) {
40140
+ defaultFolderName = "new-folder-"+(folderIndex++)
40141
+ }
40142
+
40143
+ selected.treeList.expand();
40144
+ var input = $('<input type="text" class="red-ui-treeList-input">').val(defaultFolderName);
40145
+ var newItem = {
40146
+ icon: "fa fa-folder-o",
40147
+ children:[],
40148
+ path: selected.path,
40149
+ element: input
40150
+ }
40151
+ var confirmAdd = function() {
40152
+ var val = input.val().trim();
40153
+ if (val === "") {
40154
+ cancelAdd();
40155
+ return;
40156
+ } else {
40157
+ for (var i=0;i<selected.children.length;i++) {
40158
+ if (selected.children[i].label === val) {
40159
+ cancelAdd();
40160
+ return;
40161
+ }
40162
+ }
40163
+ }
40164
+ newItem.treeList.remove();
40165
+ var finalItem = {
40166
+ library: selected.library,
40167
+ type: selected.type,
40168
+ icon: "fa fa-folder",
40169
+ children:[],
40170
+ label: val,
40171
+ path: newItem.path+val+"/"
40172
+ }
40173
+ selected.treeList.addChild(finalItem,true);
40174
+ }
40175
+ var cancelAdd = function() {
40176
+ newItem.treeList.remove();
40177
+ }
40178
+ input.on('keydown', function(evt) {
40179
+ evt.stopPropagation();
40180
+ if (evt.keyCode === 13) {
40181
+ confirmAdd();
40182
+ } else if (evt.keyCode === 27) {
40183
+ cancelAdd();
40184
+ }
40185
+ })
40186
+ input.on("blur", function() {
40187
+ confirmAdd();
40188
+ })
40189
+ selected.treeList.addChild(newItem);
40190
+ setTimeout(function() {
40191
+ input.trigger("focus");
40192
+ input.select();
40193
+ },400);
40194
+ }
40195
+ selected.treeList.expand(complete);
40196
+
40197
+ } },
40198
+ // null,
40199
+ // {id:"red-ui-library-browser-menu-rename",label:"Rename", onselect: function() {} },
40200
+ // {id:"red-ui-library-browser-menu-delete",label:"Delete", onselect: function() {} }
40201
+ ]
40202
+ }).on('mouseleave', function(){ $(this).remove(); dirList.focus() })
40203
+ .on('mouseup', function() { var self = $(this);self.hide(); dirList.focus(); setTimeout(function() { self.remove() },100)})
40204
+ .appendTo("body");
40205
+ menuOptionMenu.css({
40206
+ position: "absolute",
40207
+ top: elementPos.top+"px",
40208
+ left: (elementPos.left - menuOptionMenu.width() + 20)+"px"
40209
+ }).show();
40210
+
40211
+ }).appendTo(itemTools);
40212
+
40136
40213
  itemTools.appendTo(item.treeList.label);
40137
40214
  }
40138
40215
  });
@@ -41007,7 +41084,7 @@ RED.search = (function() {
41007
41084
  var key = keys[i];
41008
41085
  var kpos = keys[i].indexOf(val);
41009
41086
  if (kpos > -1) {
41010
- var ids = Object.keys(index[key]);
41087
+ var ids = Object.keys(index[key]||{});
41011
41088
  for (j=0;j<ids.length;j++) {
41012
41089
  var node = index[key][ids[j]];
41013
41090
  var isConfigNode = node.node._def.category === "config" && node.node.type !== 'group';
@@ -41113,7 +41190,7 @@ RED.search = (function() {
41113
41190
  }
41114
41191
  currentResults = search(value);
41115
41192
  if (currentResults.length > 0) {
41116
- for (i=0;i<Math.min(currentResults.length,25);i++) {
41193
+ for (let i=0;i<Math.min(currentResults.length,25);i++) {
41117
41194
  searchResults.editableList('addItem',currentResults[i])
41118
41195
  }
41119
41196
  if (currentResults.length > 25) {
@@ -43024,6 +43101,17 @@ RED.subflow = (function() {
43024
43101
  default: inputType
43025
43102
  })
43026
43103
  input.typedInput('value',val.value)
43104
+ if (inputType === 'cred') {
43105
+ if (node.credentials) {
43106
+ if (node.credentials[tenv.name]) {
43107
+ input.typedInput('value', node.credentials[tenv.name]);
43108
+ } else if (node.credentials['has_'+tenv.name]) {
43109
+ input.typedInput('value', "__PWRD__")
43110
+ } else {
43111
+ input.typedInput('value', "");
43112
+ }
43113
+ }
43114
+ }
43027
43115
  } else {
43028
43116
  input.val(val.value)
43029
43117
  }
@@ -43680,9 +43768,6 @@ RED.group = (function() {
43680
43768
  groups: [ ],
43681
43769
  dirty: RED.nodes.dirty()
43682
43770
  }
43683
- RED.history.push(historyEvent);
43684
-
43685
-
43686
43771
  groups.forEach(function(g) {
43687
43772
  newSelection = newSelection.concat(ungroup(g))
43688
43773
  historyEvent.groups.push(g);