@kumologica/sdk 3.6.0-beta5 → 3.6.0-beta7

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.
@@ -23,33 +23,33 @@ jQuery.propHooks.disabled = {
23
23
  let disableComms = false;
24
24
 
25
25
  function appendNodeConfig(nodeConfig, done) {
26
- done = done || function () { };
26
+ done = done || function () {};
27
27
  var m = /<!-- --- \[red-module:(\S+)\] --- -->/.exec(nodeConfig.trim());
28
28
  var moduleId;
29
29
  if (m) {
30
30
  moduleId = m[1];
31
31
  } else {
32
- moduleId = 'unknown';
32
+ moduleId = "unknown";
33
33
  }
34
34
  try {
35
35
  var hasDeferred = false;
36
36
 
37
- var nodeConfigEls = $('<div>' + nodeConfig + '</div>');
38
- var scripts = nodeConfigEls.find('script');
37
+ var nodeConfigEls = $("<div>" + nodeConfig + "</div>");
38
+ var scripts = nodeConfigEls.find("script");
39
39
  var scriptCount = scripts.length;
40
40
  scripts.each(function (i, el) {
41
- var srcUrl = $(el).attr('src');
41
+ var srcUrl = $(el).attr("src");
42
42
  if (srcUrl && !/^\s*(https?:|\/|\.)/.test(srcUrl)) {
43
43
  $(el).remove();
44
- var newScript = document.createElement('script');
44
+ var newScript = document.createElement("script");
45
45
  newScript.onload = function () {
46
46
  scriptCount--;
47
47
  if (scriptCount === 0) {
48
- $('body').append(nodeConfigEls);
48
+ $("body").append(nodeConfigEls);
49
49
  done();
50
50
  }
51
51
  };
52
- $('body').append(newScript);
52
+ $("body").append(newScript);
53
53
  newScript.src = RED.settings.apiRootUrl + srcUrl;
54
54
  hasDeferred = true;
55
55
  } else {
@@ -61,24 +61,25 @@ jQuery.propHooks.disabled = {
61
61
  // break the version of ace included in the editor.
62
62
  // At the time of commit, the contrib-python nodes did this.
63
63
  // This is a crude fix until the python nodes are fixed.
64
- console.warn('Blocked attempt to load', srcUrl, 'by', moduleId);
64
+ console.warn("Blocked attempt to load", srcUrl, "by", moduleId);
65
65
  $(el).remove();
66
66
  }
67
67
  scriptCount--;
68
68
  }
69
69
  });
70
70
  if (!hasDeferred) {
71
- $('body').append(nodeConfigEls);
71
+ $("body").append(nodeConfigEls);
72
72
  done();
73
73
  }
74
74
  } catch (err) {
75
- RED.notify(`<p>Failed to load '${moduleId}'</p><p>${err.toString()}</p>`,
75
+ RED.notify(
76
+ `<p>Failed to load '${moduleId}'</p><p>${err.toString()}</p>`,
76
77
  {
77
- type: 'error',
78
+ type: "error",
78
79
  timeout: 10000,
79
80
  }
80
81
  );
81
- console.log('[' + moduleId + '] ' + err.toString());
82
+ console.log("[" + moduleId + "] " + err.toString());
82
83
  done();
83
84
  }
84
85
  }
@@ -86,10 +87,10 @@ jQuery.propHooks.disabled = {
86
87
  function loadNodeList() {
87
88
  $.ajax({
88
89
  headers: {
89
- Accept: 'application/json',
90
+ Accept: "application/json",
90
91
  },
91
92
  cache: false,
92
- url: 'nodes',
93
+ url: "nodes",
93
94
  success: function (data) {
94
95
  RED.nodes.setNodeList(data);
95
96
  // RED.i18n.loadNodeCatalogs(function () {
@@ -102,10 +103,10 @@ jQuery.propHooks.disabled = {
102
103
  function loadIconList(done) {
103
104
  $.ajax({
104
105
  headers: {
105
- Accept: 'application/json',
106
+ Accept: "application/json",
106
107
  },
107
108
  cache: false,
108
- url: '__icons',
109
+ url: "__icons",
109
110
  success: function (data) {
110
111
  RED.nodes.setIconSets(data);
111
112
  if (done) {
@@ -118,28 +119,28 @@ jQuery.propHooks.disabled = {
118
119
  function loadNodes() {
119
120
  $.ajax({
120
121
  headers: {
121
- Accept: 'text/html',
122
+ Accept: "text/html",
122
123
  },
123
124
  cache: false,
124
- url: 'nodes',
125
+ url: "nodes",
125
126
  success: function (data) {
126
127
  var configs = data
127
128
  .trim()
128
129
  .split(/(?=<!-- --- \[red-module:\S+\] --- -->)/);
129
130
  var stepConfig = function () {
130
131
  if (configs.length === 0) {
131
- $('body').i18n();
132
- $('#palette > .palette-spinner').hide();
133
- $('.palette-scroll').removeClass('hide');
134
- $('#palette-search').removeClass('hide');
132
+ $("body").i18n();
133
+ $("#palette > .palette-spinner").hide();
134
+ $(".palette-scroll").removeClass("hide");
135
+ $("#palette-search").removeClass("hide");
135
136
  loadFlows(function () {
136
- if (RED.settings.theme('projects.enabled', false)) {
137
+ if (RED.settings.theme("projects.enabled", false)) {
137
138
  RED.projects.refresh(function (activeProject) {
138
139
  RED.sidebar.info.refresh();
139
140
  if (!activeProject) {
140
141
  // Projects enabled but no active project
141
- RED.menu.setDisabled('menu-item-projects-open', true);
142
- RED.menu.setDisabled('menu-item-projects-settings', true);
142
+ RED.menu.setDisabled("menu-item-projects-open", true);
143
+ RED.menu.setDisabled("menu-item-projects-settings", true);
143
144
  if (activeProject === false) {
144
145
  // User previously decline the migration to projects.
145
146
  } else {
@@ -168,10 +169,10 @@ jQuery.propHooks.disabled = {
168
169
  function loadFlows(done) {
169
170
  $.ajax({
170
171
  headers: {
171
- Accept: 'application/json',
172
+ Accept: "application/json",
172
173
  },
173
174
  cache: false,
174
- url: 'flows',
175
+ url: "flows",
175
176
  success: function (nodes) {
176
177
  if (nodes) {
177
178
  var currentHash = window.location.hash;
@@ -190,18 +191,18 @@ jQuery.propHooks.disabled = {
190
191
 
191
192
  function completeLoad() {
192
193
  var persistentNotifications = {};
193
- RED.comms.subscribe('notification/#', function (topic, msg) {
194
- var parts = topic.split('/');
194
+ RED.comms.subscribe("notification/#", function (topic, msg) {
195
+ var parts = topic.split("/");
195
196
  var notificationId = parts[1];
196
- if (notificationId === 'runtime-deploy') {
197
+ if (notificationId === "runtime-deploy") {
197
198
  // handled in ui/deploy.js
198
199
  return;
199
200
  }
200
- if (notificationId === 'node') {
201
+ if (notificationId === "node") {
201
202
  // handled below
202
203
  return;
203
204
  }
204
- if (notificationId === 'project-update') {
205
+ if (notificationId === "project-update") {
205
206
  RED.nodes.clear();
206
207
  RED.history.clear();
207
208
  RED.view.redraw(true);
@@ -222,28 +223,28 @@ jQuery.propHooks.disabled = {
222
223
  timeout: msg.timeout,
223
224
  id: notificationId,
224
225
  };
225
- if (notificationId === 'runtime-state') {
226
- if (msg.error === 'safe-mode') {
226
+ if (notificationId === "runtime-state") {
227
+ if (msg.error === "safe-mode") {
227
228
  options.buttons = [
228
229
  {
229
- text: 'Close',
230
+ text: "Close",
230
231
  click: function () {
231
232
  persistentNotifications[notificationId].hideNotification();
232
233
  },
233
234
  },
234
235
  ];
235
- } else if (msg.error === 'missing-types') {
236
+ } else if (msg.error === "missing-types") {
236
237
  text +=
237
- '<ul><li>' +
238
- msg.types.map(RED.utils.sanitize).join('</li><li>') +
239
- '</li></ul>';
238
+ "<ul><li>" +
239
+ msg.types.map(RED.utils.sanitize).join("</li><li>") +
240
+ "</li></ul>";
240
241
  if (!!RED.projects.getActiveProject()) {
241
242
  options.buttons = [
242
243
  {
243
- text: 'Manage project dependencies',
244
+ text: "Manage project dependencies",
244
245
  click: function () {
245
246
  persistentNotifications[notificationId].hideNotification();
246
- RED.projects.settings.show('deps');
247
+ RED.projects.settings.show("deps");
247
248
  },
248
249
  },
249
250
  ];
@@ -251,20 +252,20 @@ jQuery.propHooks.disabled = {
251
252
  } else {
252
253
  options.buttons = [
253
254
  {
254
- text: 'Close',
255
+ text: "Close",
255
256
  click: function () {
256
257
  persistentNotifications[notificationId].hideNotification();
257
258
  },
258
259
  },
259
260
  ];
260
261
  }
261
- } else if (msg.error === 'credentials_load_failed') {
262
- if (RED.settings.theme('projects.enabled', false)) {
262
+ } else if (msg.error === "credentials_load_failed") {
263
+ if (RED.settings.theme("projects.enabled", false)) {
263
264
  // projects enabled
264
- if (RED.user.hasPermission('projects.write')) {
265
+ if (RED.user.hasPermission("projects.write")) {
265
266
  options.buttons = [
266
267
  {
267
- text: 'Setup credentials',
268
+ text: "Setup credentials",
268
269
  click: function () {
269
270
  persistentNotifications[
270
271
  notificationId
@@ -277,18 +278,18 @@ jQuery.propHooks.disabled = {
277
278
  } else {
278
279
  options.buttons = [
279
280
  {
280
- text: 'Close',
281
+ text: "Close",
281
282
  click: function () {
282
283
  persistentNotifications[notificationId].hideNotification();
283
284
  },
284
285
  },
285
286
  ];
286
287
  }
287
- } else if (msg.error === 'missing_flow_file') {
288
- if (RED.user.hasPermission('projects.write')) {
288
+ } else if (msg.error === "missing_flow_file") {
289
+ if (RED.user.hasPermission("projects.write")) {
289
290
  options.buttons = [
290
291
  {
291
- text: 'Setup credentials',
292
+ text: "Setup credentials",
292
293
  click: function () {
293
294
  persistentNotifications[notificationId].hideNotification();
294
295
  RED.projects.showFilesPrompt();
@@ -296,11 +297,11 @@ jQuery.propHooks.disabled = {
296
297
  },
297
298
  ];
298
299
  }
299
- } else if (msg.error === 'missing_package_file') {
300
- if (RED.user.hasPermission('projects.write')) {
300
+ } else if (msg.error === "missing_package_file") {
301
+ if (RED.user.hasPermission("projects.write")) {
301
302
  options.buttons = [
302
303
  {
303
- text: 'Setup credentials',
304
+ text: "Setup credentials",
304
305
  click: function () {
305
306
  persistentNotifications[notificationId].hideNotification();
306
307
  RED.projects.showFilesPrompt();
@@ -308,17 +309,17 @@ jQuery.propHooks.disabled = {
308
309
  },
309
310
  ];
310
311
  }
311
- } else if (msg.error === 'project_empty') {
312
- if (RED.user.hasPermission('projects.write')) {
312
+ } else if (msg.error === "project_empty") {
313
+ if (RED.user.hasPermission("projects.write")) {
313
314
  options.buttons = [
314
315
  {
315
- text: 'No thanks',
316
+ text: "No thanks",
316
317
  click: function () {
317
318
  persistentNotifications[notificationId].hideNotification();
318
319
  },
319
320
  },
320
321
  {
321
- text: 'Create default project files',
322
+ text: "Create default project files",
322
323
  click: function () {
323
324
  persistentNotifications[notificationId].hideNotification();
324
325
  RED.projects.createDefaultFileSet();
@@ -326,13 +327,13 @@ jQuery.propHooks.disabled = {
326
327
  },
327
328
  ];
328
329
  }
329
- } else if (msg.error === 'git_merge_conflict') {
330
+ } else if (msg.error === "git_merge_conflict") {
330
331
  RED.nodes.clear();
331
332
  RED.sidebar.versionControl.refresh(true);
332
- if (RED.user.hasPermission('projects.write')) {
333
+ if (RED.user.hasPermission("projects.write")) {
333
334
  options.buttons = [
334
335
  {
335
- text: 'Show merge conflicts',
336
+ text: "Show merge conflicts",
336
337
  click: function () {
337
338
  persistentNotifications[notificationId].hideNotification();
338
339
  RED.sidebar.versionControl.showLocalChanges();
@@ -352,11 +353,11 @@ jQuery.propHooks.disabled = {
352
353
  delete persistentNotifications[notificationId];
353
354
  }
354
355
  });
355
- RED.comms.subscribe('status/#', function (topic, msg) {
356
- var parts = topic.split('/');
356
+ RED.comms.subscribe("status/#", function (topic, msg) {
357
+ var parts = topic.split("/");
357
358
  var node = RED.nodes.node(parts[1]);
358
359
  if (node) {
359
- if (msg.hasOwnProperty('text') && /^[a-zA-Z]/.test(msg.text)) {
360
+ if (msg.hasOwnProperty("text") && /^[a-zA-Z]/.test(msg.text)) {
360
361
  msg.text = node._(msg.text.toString(), {
361
362
  defaultValue: msg.text.toString(),
362
363
  });
@@ -366,74 +367,77 @@ jQuery.propHooks.disabled = {
366
367
  RED.view.redraw();
367
368
  }
368
369
  });
369
- RED.comms.subscribe('notification/node/#', function (topic, msg) {
370
+ RED.comms.subscribe("notification/node/#", function (topic, msg) {
370
371
  var i, m;
371
372
  var typeList;
372
373
  var info;
373
- if (topic == 'notification/node/added') {
374
+ if (topic == "notification/node/added") {
374
375
  var addedTypes = [];
375
376
  msg.forEach(function (m) {
376
377
  var id = m.id;
377
378
  RED.nodes.addNodeSet(m);
378
379
  addedTypes = addedTypes.concat(m.types);
379
380
  RED.i18n.loadNodeCatalog(id, function () {
380
- $.get('nodes/' + id, function (data) {
381
+ $.get("nodes/" + id, function (data) {
381
382
  appendNodeConfig(data);
382
383
  });
383
384
  });
384
385
  });
385
386
  if (addedTypes.length) {
386
- typeList = '<ul><li>' + addedTypes.join('</li><li>') + '</li></ul>';
387
- RED.notify(`Node added to palette: ${addedTypes.length} ` + typeList,
388
- 'success'
387
+ typeList = "<ul><li>" + addedTypes.join("</li><li>") + "</li></ul>";
388
+ RED.notify(
389
+ `Node added to palette: ${addedTypes.length} ` + typeList,
390
+ "success"
389
391
  );
390
392
  }
391
393
  loadIconList();
392
- } else if (topic == 'notification/node/removed') {
394
+ } else if (topic == "notification/node/removed") {
393
395
  for (i = 0; i < msg.length; i++) {
394
396
  m = msg[i];
395
397
  info = RED.nodes.removeNodeSet(m.id);
396
398
  if (info.added) {
397
- typeList = '<ul><li>' + m.types.join('</li><li>') + '</li></ul>';
398
- RED.notify(`Node removed from palette: ${m.types.length}` + typeList,
399
- 'success'
399
+ typeList = "<ul><li>" + m.types.join("</li><li>") + "</li></ul>";
400
+ RED.notify(
401
+ `Node removed from palette: ${m.types.length}` + typeList,
402
+ "success"
400
403
  );
401
404
  }
402
405
  }
403
406
  loadIconList();
404
- } else if (topic == 'notification/node/enabled') {
407
+ } else if (topic == "notification/node/enabled") {
405
408
  if (msg.types) {
406
409
  info = RED.nodes.getNodeSet(msg.id);
407
410
  if (info.added) {
408
411
  RED.nodes.enableNodeSet(msg.id);
409
- typeList = '<ul><li>' + msg.types.join('</li><li>') + '</li></ul>';
412
+ typeList = "<ul><li>" + msg.types.join("</li><li>") + "</li></ul>";
410
413
  // RED.notify(
411
414
  // RED._('palette.event.nodeEnabled', { count: msg.types.length }) +
412
415
  // typeList,
413
416
  // 'success'
414
417
  // );
415
418
  } else {
416
- $.get('nodes/' + msg.id, function (data) {
419
+ $.get("nodes/" + msg.id, function (data) {
417
420
  appendNodeConfig(data);
418
421
  typeList =
419
- '<ul><li>' + msg.types.join('</li><li>') + '</li></ul>';
420
- RED.notify(`Node added to palette: ${msg.types.length} ` + typeList,
421
- 'success'
422
+ "<ul><li>" + msg.types.join("</li><li>") + "</li></ul>";
423
+ RED.notify(
424
+ `Node added to palette: ${msg.types.length} ` + typeList,
425
+ "success"
422
426
  );
423
427
  });
424
428
  }
425
429
  }
426
- } else if (topic == 'notification/node/disabled') {
430
+ } else if (topic == "notification/node/disabled") {
427
431
  if (msg.types) {
428
432
  RED.nodes.disableNodeSet(msg.id);
429
- typeList = '<ul><li>' + msg.types.join('</li><li>') + '</li></ul>';
433
+ typeList = "<ul><li>" + msg.types.join("</li><li>") + "</li></ul>";
430
434
  // RED.notify(
431
435
  // RED._('palette.event.nodeDisabled', { count: msg.types.length }) +
432
436
  // typeList,
433
437
  // 'success'
434
438
  // );
435
439
  }
436
- } else if (topic == 'notification/node/upgraded') {
440
+ } else if (topic == "notification/node/upgraded") {
437
441
  // RED.notify(
438
442
  // RED._('palette.event.nodeUpgraded', {
439
443
  // module: msg.module,
@@ -444,18 +448,18 @@ jQuery.propHooks.disabled = {
444
448
  RED.nodes.registry.setModulePendingUpdated(msg.module, msg.version);
445
449
  }
446
450
  });
447
- RED.comms.subscribe('event-log/#', function (topic, payload) {
451
+ RED.comms.subscribe("event-log/#", function (topic, payload) {
448
452
  var id = topic.substring(9);
449
453
  RED.eventLog.log(id, payload);
450
454
  });
451
455
  }
452
456
 
453
457
  function showAbout() {
454
- $.get('red/about', function (data) {
458
+ $.get("red/about", function (data) {
455
459
  var aboutHeader =
456
460
  '<div style="text-align:center;">' +
457
461
  '<img width="50px" src="red/images/kumologica-core-icon.svg" />' +
458
- '</div>';
462
+ "</div>";
459
463
 
460
464
  RED.sidebar.info.set(aboutHeader + marked(data));
461
465
  RED.sidebar.info.show();
@@ -464,180 +468,180 @@ jQuery.propHooks.disabled = {
464
468
 
465
469
  function loadEditor() {
466
470
  var menuOptions = [];
467
- if (RED.settings.theme('projects.enabled', false)) {
471
+ if (RED.settings.theme("projects.enabled", false)) {
468
472
  menuOptions.push({
469
- id: 'menu-item-projects-menu',
470
- label: 'Projects',
473
+ id: "menu-item-projects-menu",
474
+ label: "Projects",
471
475
  options: [
472
476
  {
473
- id: 'menu-item-projects-new',
474
- label: 'New',
477
+ id: "menu-item-projects-new",
478
+ label: "New",
475
479
  disabled: false,
476
- onselect: 'core:new-project',
480
+ onselect: "core:new-project",
477
481
  },
478
482
  {
479
- id: 'menu-item-projects-open',
480
- label: 'Open',
483
+ id: "menu-item-projects-open",
484
+ label: "Open",
481
485
  disabled: false,
482
- onselect: 'core:open-project',
486
+ onselect: "core:open-project",
483
487
  },
484
488
  {
485
- id: 'menu-item-projects-settings',
486
- label: 'Project Settings',
489
+ id: "menu-item-projects-settings",
490
+ label: "Project Settings",
487
491
  disabled: false,
488
- onselect: 'core:show-project-settings',
492
+ onselect: "core:show-project-settings",
489
493
  },
490
494
  ],
491
495
  });
492
496
  }
493
497
 
494
498
  menuOptions.push({
495
- id: 'menu-item-view-menu',
496
- label: 'View',
499
+ id: "menu-item-view-menu",
500
+ label: "View",
497
501
  options: [
498
502
  {
499
- id: 'menu-item-palette',
500
- label: 'Show palette',
503
+ id: "menu-item-palette",
504
+ label: "Show palette",
501
505
  toggle: true,
502
- onselect: 'core:toggle-palette',
506
+ onselect: "core:toggle-palette",
503
507
  selected: true,
504
508
  },
505
509
  {
506
- id: 'menu-item-sidebar',
507
- label: 'Show sidebar',
510
+ id: "menu-item-sidebar",
511
+ label: "Show sidebar",
508
512
  toggle: true,
509
- onselect: 'core:toggle-sidebar',
513
+ onselect: "core:toggle-sidebar",
510
514
  selected: false,
511
515
  },
512
516
  {
513
- id: 'menu-item-event-log',
514
- label: 'Event log',
515
- onselect: 'core:show-event-log',
517
+ id: "menu-item-event-log",
518
+ label: "Event log",
519
+ onselect: "core:show-event-log",
516
520
  },
517
521
  null,
518
522
  ],
519
523
  });
520
524
  menuOptions.push(null);
521
525
  menuOptions.push({
522
- id: 'menu-item-import',
523
- label: 'Import',
526
+ id: "menu-item-import",
527
+ label: "Import",
524
528
  options: [
525
529
  {
526
- id: 'menu-item-import-clipboard',
527
- label: 'Clipboard',
528
- onselect: 'core:show-import-dialog',
530
+ id: "menu-item-import-clipboard",
531
+ label: "Clipboard",
532
+ onselect: "core:show-import-dialog",
529
533
  },
530
534
  {
531
- id: 'menu-item-import-library',
532
- label: 'Library',
535
+ id: "menu-item-import-library",
536
+ label: "Library",
533
537
  options: [],
534
538
  },
535
539
  ],
536
540
  });
537
541
  menuOptions.push({
538
- id: 'menu-item-export',
539
- label: 'Export',
542
+ id: "menu-item-export",
543
+ label: "Export",
540
544
  options: [
541
545
  {
542
- id: 'menu-item-export-clipboard',
543
- label: 'Clipboard',
544
- onselect: 'core:show-export-dialog',
546
+ id: "menu-item-export-clipboard",
547
+ label: "Clipboard",
548
+ onselect: "core:show-export-dialog",
545
549
  },
546
550
  {
547
- id: 'menu-item-export-library',
548
- label: 'Library',
551
+ id: "menu-item-export-library",
552
+ label: "Library",
549
553
  disabled: true,
550
- onselect: 'core:library-export',
554
+ onselect: "core:library-export",
551
555
  },
552
556
  ],
553
557
  });
554
558
  menuOptions.push(null);
555
559
  menuOptions.push({
556
- id: 'menu-item-search',
557
- label: 'Search',
558
- onselect: 'core:search',
560
+ id: "menu-item-search",
561
+ label: "Search",
562
+ onselect: "core:search",
559
563
  });
560
564
  menuOptions.push(null);
561
565
  menuOptions.push({
562
- id: 'menu-item-config-nodes',
563
- label: 'Configuration nodes',
564
- onselect: 'core:show-config-tab',
566
+ id: "menu-item-config-nodes",
567
+ label: "Configuration nodes",
568
+ onselect: "core:show-config-tab",
565
569
  });
566
570
  menuOptions.push({
567
- id: 'menu-item-workspace',
568
- label: 'Flows',
571
+ id: "menu-item-workspace",
572
+ label: "Flows",
569
573
  options: [
570
574
  {
571
- id: 'menu-item-workspace-add',
572
- label: 'Add',
573
- onselect: 'core:add-flow',
575
+ id: "menu-item-workspace-add",
576
+ label: "Add",
577
+ onselect: "core:add-flow",
574
578
  },
575
579
  {
576
- id: 'menu-item-workspace-edit',
577
- label: 'Rename',
578
- onselect: 'core:edit-flow',
580
+ id: "menu-item-workspace-edit",
581
+ label: "Rename",
582
+ onselect: "core:edit-flow",
579
583
  },
580
584
  {
581
- id: 'menu-item-workspace-delete',
582
- label: 'Delete',
583
- onselect: 'core:remove-flow',
585
+ id: "menu-item-workspace-delete",
586
+ label: "Delete",
587
+ onselect: "core:remove-flow",
584
588
  },
585
589
  ],
586
590
  });
587
591
  menuOptions.push({
588
- id: 'menu-item-subflow',
589
- label: 'Subflows',
592
+ id: "menu-item-subflow",
593
+ label: "Subflows",
590
594
  options: [
591
595
  {
592
- id: 'menu-item-subflow-create',
593
- label: 'Create Subflow',
594
- onselect: 'core:create-subflow',
596
+ id: "menu-item-subflow-create",
597
+ label: "Create Subflow",
598
+ onselect: "core:create-subflow",
595
599
  },
596
600
  {
597
- id: 'menu-item-subflow-convert',
598
- label: 'Selection to Subflow',
601
+ id: "menu-item-subflow-convert",
602
+ label: "Selection to Subflow",
599
603
  disabled: true,
600
- onselect: 'core:convert-to-subflow',
604
+ onselect: "core:convert-to-subflow",
601
605
  },
602
606
  ],
603
607
  });
604
608
  menuOptions.push(null);
605
- if (RED.settings.theme('palette.editable') !== false) {
609
+ if (RED.settings.theme("palette.editable") !== false) {
606
610
  menuOptions.push({
607
- id: 'menu-item-edit-palette',
608
- label: 'Manage palette',
609
- onselect: 'core:manage-palette',
611
+ id: "menu-item-edit-palette",
612
+ label: "Manage palette",
613
+ onselect: "core:manage-palette",
610
614
  });
611
615
  menuOptions.push(null);
612
616
  }
613
617
 
614
618
  menuOptions.push({
615
- id: 'menu-item-user-settings',
616
- label: 'Settings',
617
- onselect: 'core:show-user-settings',
619
+ id: "menu-item-user-settings",
620
+ label: "Settings",
621
+ onselect: "core:show-user-settings",
618
622
  });
619
623
  menuOptions.push(null);
620
624
 
621
625
  menuOptions.push({
622
- id: 'menu-item-keyboard-shortcuts',
623
- label: 'Keyboard shortcuts',
624
- onselect: 'core:show-help',
626
+ id: "menu-item-keyboard-shortcuts",
627
+ label: "Keyboard shortcuts",
628
+ onselect: "core:show-help",
625
629
  });
626
630
  menuOptions.push({
627
- id: 'menu-item-help',
631
+ id: "menu-item-help",
628
632
  label: RED.settings.theme(
629
- 'menu.menu-item-help.label',
630
- 'Kumologica website'
633
+ "menu.menu-item-help.label",
634
+ "Kumologica website"
631
635
  ),
632
636
  href: RED.settings.theme(
633
- 'menu.menu-item-help.url',
634
- 'http://kumologica.com/docs'
637
+ "menu.menu-item-help.url",
638
+ "http://kumologica.com/docs"
635
639
  ),
636
640
  });
637
641
  menuOptions.push({
638
- id: 'menu-item-kumologica-core-version',
639
- label: 'v' + RED.settings.version,
640
- onselect: 'core:show-about',
642
+ id: "menu-item-kumologica-core-version",
643
+ label: "v" + RED.settings.version,
644
+ onselect: "core:show-about",
641
645
  });
642
646
 
643
647
  RED.view.init();
@@ -649,13 +653,13 @@ jQuery.propHooks.disabled = {
649
653
  RED.palette.explorer.init();
650
654
  RED.palette.nodes.init();
651
655
  RED.eventLog.init();
652
- if (RED.settings.theme('palette.editable') !== false) {
656
+ if (RED.settings.theme("palette.editable") !== false) {
653
657
  RED.palette.editor.init();
654
658
  }
655
659
 
656
660
  RED.sidebar.init();
657
661
 
658
- if (RED.settings.theme('projects.enabled', false)) {
662
+ if (RED.settings.theme("projects.enabled", false)) {
659
663
  RED.projects.init();
660
664
  }
661
665
 
@@ -666,16 +670,17 @@ jQuery.propHooks.disabled = {
666
670
  RED.search.init();
667
671
  RED.projectInfo.init();
668
672
  RED.uiSettings.init();
673
+ RED.modules.init();
669
674
 
670
675
  RED.editor.init();
671
676
  //RED.diff.init();
672
677
 
673
- RED.menu.init({ id: 'btn-sidemenu', options: menuOptions });
678
+ RED.menu.init({ id: "btn-sidemenu", options: menuOptions });
674
679
 
675
- RED.deploy.init(RED.settings.theme('deployButton', null));
680
+ RED.deploy.init(RED.settings.theme("deployButton", null));
676
681
  RED.notifications.init();
677
682
 
678
- RED.actions.add('core:show-about', showAbout);
683
+ RED.actions.add("core:show-about", showAbout);
679
684
  RED.nodes.init();
680
685
 
681
686
  if (!disableComms) {
@@ -693,8 +698,8 @@ jQuery.propHooks.disabled = {
693
698
 
694
699
  //RED.comms.connectWS();
695
700
 
696
- $('#main-container').show();
697
- $('.header-toolbar').show();
701
+ $("#main-container").show();
702
+ $(".header-toolbar").show();
698
703
 
699
704
  // Terminal must go before headers, as they reference the terminal in the shelves section
700
705
  //RED.terminal.init();
@@ -708,21 +713,20 @@ jQuery.propHooks.disabled = {
708
713
 
709
714
  function init(options) {
710
715
  if (initialised) {
711
- throw new Error('RED already initialised');
716
+ throw new Error("RED already initialised");
712
717
  }
713
718
  disableComms = options.disableComms || false;
714
719
  initialised = true;
715
- ace.require('ace/ext/language_tools');
720
+ ace.require("ace/ext/language_tools");
716
721
  options = options || {};
717
- options.apiRootUrl = options.apiRootUrl || '';
722
+ options.apiRootUrl = options.apiRootUrl || "";
718
723
  if (options.apiRootUrl && !/\/$/.test(options.apiRootUrl)) {
719
- options.apiRootUrl = options.apiRootUrl + '/';
724
+ options.apiRootUrl = options.apiRootUrl + "/";
720
725
  }
721
726
  RED.i18n.init(options, function () {
722
727
  RED.settings.init(options, loadEditor);
723
728
  });
724
729
  RED.footer.init();
725
-
726
730
  }
727
731
 
728
732
  return {
@@ -8627,103 +8631,211 @@ RED.panels = (function() {
8627
8631
  },
8628
8632
  };
8629
8633
  })();
8630
- ;
8631
- (function($) {
8634
+ ;(function ($) {
8635
+ /**
8636
+ * options:
8637
+ * - minimumLength : the minimum length of text before firing a change event
8638
+ * - delay : delay, in ms, after a keystroke before firing change event
8639
+ *
8640
+ * methods:
8641
+ * - value([val]) - gets the current value, or, if `val` is provided, sets the value
8642
+ * - count - sets or clears a sub-label on the input. This can be used to provide
8643
+ * a feedback on the number of matches, or number of available entries to search
8644
+ * - change - trigger a change event
8645
+ *
8646
+ */
8632
8647
 
8633
- /**
8634
- * options:
8635
- * - minimumLength : the minimum length of text before firing a change event
8636
- * - delay : delay, in ms, after a keystroke before firing change event
8637
- *
8638
- * methods:
8639
- * - value([val]) - gets the current value, or, if `val` is provided, sets the value
8640
- * - count - sets or clears a sub-label on the input. This can be used to provide
8641
- * a feedback on the number of matches, or number of available entries to search
8642
- * - change - trigger a change event
8643
- *
8644
- */
8648
+ $.widget("nodered.searchBox", {
8649
+ _create: function () {
8650
+ var that = this;
8645
8651
 
8646
- $.widget( "nodered.searchBox", {
8647
- _create: function() {
8648
- var that = this;
8652
+ this.currentTimeout = null;
8653
+ this.lastSent = "";
8654
+ this.element.val("");
8655
+ this.uiContainer = this.element.wrap("<div>").parent();
8656
+ this.uiContainer.addClass("red-ui-searchBox-container");
8657
+
8658
+ $('<i class="fa fa-search"></i>').prependTo(this.uiContainer);
8659
+ this.clearButton = $(
8660
+ '<a href="#"><i class="fa fa-times"></i></a>'
8661
+ ).appendTo(this.uiContainer);
8662
+ this.clearButton.on("click", function (e) {
8663
+ e.preventDefault();
8664
+ that.element.val("");
8665
+ that._change("", true);
8666
+ that.element.focus();
8667
+ });
8649
8668
 
8650
- this.currentTimeout = null;
8651
- this.lastSent = "";
8652
- this.element.val("");
8653
- this.uiContainer = this.element.wrap("<div>").parent();
8654
- this.uiContainer.addClass("red-ui-searchBox-container");
8669
+ this.resultCount = $("<span>", {
8670
+ class: "red-ui-searchBox-resultCount hide",
8671
+ }).appendTo(this.uiContainer);
8655
8672
 
8656
- $('<i class="fa fa-search"></i>').prependTo(this.uiContainer);
8657
- this.clearButton = $('<a href="#"><i class="fa fa-times"></i></a>').appendTo(this.uiContainer);
8658
- this.clearButton.on("click",function(e) {
8659
- e.preventDefault();
8660
- that.element.val("");
8661
- that._change("",true);
8662
- that.element.focus();
8663
- });
8673
+ this.element.val("");
8674
+ this.element.on("keydown", function (evt) {
8675
+ if (evt.keyCode === 27) {
8676
+ that.element.val("");
8677
+ }
8678
+ });
8679
+ this.element.on("keyup", function (evt) {
8680
+ that._change($(this).val());
8681
+ });
8664
8682
 
8665
- this.resultCount = $('<span>',{class:"red-ui-searchBox-resultCount hide"}).appendTo(this.uiContainer);
8683
+ this.element.on("focus", function () {
8684
+ $("body").one("mousedown", function () {
8685
+ that.element.blur();
8686
+ });
8687
+ });
8688
+ },
8689
+ _change: function (val, instant) {
8690
+ var fireEvent = false;
8691
+ if (val === "") {
8692
+ this.clearButton.hide();
8693
+ fireEvent = true;
8694
+ } else {
8695
+ this.clearButton.show();
8696
+ fireEvent = val.length >= (this.options.minimumLength || 0);
8697
+ }
8698
+ var current = this.element.val();
8699
+ fireEvent = fireEvent && current !== this.lastSent;
8700
+ if (fireEvent) {
8701
+ if (!instant && this.options.delay > 0) {
8702
+ clearTimeout(this.currentTimeout);
8703
+ var that = this;
8704
+ this.currentTimeout = setTimeout(function () {
8705
+ that.lastSent = that.element.val();
8706
+ that._trigger("change");
8707
+ }, this.options.delay);
8708
+ } else {
8709
+ this._trigger("change");
8710
+ }
8711
+ }
8712
+ },
8713
+ value: function (val) {
8714
+ if (val === undefined) {
8715
+ return this.element.val();
8716
+ } else {
8717
+ this.element.val(val);
8718
+ this._change(val);
8719
+ }
8720
+ },
8721
+ count: function (val) {
8722
+ if (val === undefined || val === null || val === "") {
8723
+ this.resultCount.text("").hide();
8724
+ } else {
8725
+ this.resultCount.text(val).show();
8726
+ }
8727
+ },
8728
+ change: function () {
8729
+ this._trigger("change");
8730
+ },
8731
+ });
8732
+ })(jQuery);
8733
+ ;(function ($) {
8734
+ /**
8735
+ * options:
8736
+ * - command : the command to run
8737
+ * - delay : delay, in ms, after a keystroke before firing change event
8738
+ *
8739
+ * methods:
8740
+ * - value([val]) - gets the current value, or, if `val` is provided, sets the value
8741
+ * - count - sets or clears a sub-label on the input. This can be used to provide
8742
+ * a feedback on the number of matches, or number of available entries to search
8743
+ * - change - trigger a change event
8744
+ *
8745
+ */
8666
8746
 
8667
- this.element.val("");
8668
- this.element.on("keydown",function(evt) {
8669
- if (evt.keyCode === 27) {
8670
- that.element.val("");
8671
- }
8672
- })
8673
- this.element.on("keyup",function(evt) {
8674
- that._change($(this).val());
8675
- });
8747
+ $.widget("kumologica.commandBox", {
8748
+ _create: function () {
8749
+ var that = this;
8676
8750
 
8677
- this.element.on("focus",function() {
8678
- $("body").one("mousedown",function() {
8679
- that.element.blur();
8680
- });
8681
- });
8751
+ this.currentTimeout = null;
8752
+ this.lastSent = "";
8753
+ let command = this.options.command || "";
8682
8754
 
8683
- },
8684
- _change: function(val,instant) {
8685
- var fireEvent = false;
8686
- if (val === "") {
8687
- this.clearButton.hide();
8688
- fireEvent = true;
8689
- } else {
8690
- this.clearButton.show();
8691
- fireEvent = (val.length >= (this.options.minimumLength||0));
8692
- }
8693
- var current = this.element.val();
8694
- fireEvent = fireEvent && current !== this.lastSent;
8695
- if (fireEvent) {
8696
- if (!instant && this.options.delay > 0) {
8697
- clearTimeout(this.currentTimeout);
8698
- var that = this;
8699
- this.currentTimeout = setTimeout(function() {
8700
- that.lastSent = that.element.val();
8701
- that._trigger("change");
8702
- },this.options.delay);
8703
- } else {
8704
- this._trigger("change");
8705
- }
8706
- }
8707
- },
8708
- value: function(val) {
8709
- if (val === undefined) {
8710
- return this.element.val();
8711
- } else {
8712
- this.element.val(val);
8713
- this._change(val);
8714
- }
8715
- },
8716
- count: function(val) {
8717
- if (val === undefined || val === null || val === "") {
8718
- this.resultCount.text("").hide();
8719
- } else {
8720
- this.resultCount.text(val).show();
8721
- }
8722
- },
8723
- change: function() {
8724
- this._trigger("change");
8755
+ this.element.val(command + " ");
8756
+ this.uiContainer = this.element.wrap("<div>").parent();
8757
+ this.uiContainer.addClass("red-ui-commandBox-container");
8758
+
8759
+ $(
8760
+ `<div class="red-ui-commandBox-command"><i class="fa fa-terminal"></i></div>`
8761
+ ).prependTo(this.uiContainer);
8762
+ this.enterButton = $(
8763
+ '<span class="enter-command pointer">run</span>'
8764
+ ).appendTo(this.uiContainer);
8765
+
8766
+ this.enterButton.on("click", function (e) {
8767
+ e.preventDefault();
8768
+ that.options.execute(that.element.val());
8769
+ });
8770
+
8771
+ this.resultCount = $("<span>", {
8772
+ class: "red-ui-searchBox-resultCount hide",
8773
+ }).appendTo(this.uiContainer);
8774
+
8775
+ this.element.on("keydown", function (evt) {
8776
+ if (evt.keyCode === 27) {
8777
+ // Escape key
8778
+ that.element.val("");
8779
+ } else if (evt.keyCode === 13) {
8780
+ // Enter key
8781
+ evt.preventDefault();
8782
+ let command = that.element.val();
8783
+ that.options.execute(command);
8725
8784
  }
8726
- });
8785
+ });
8786
+ this.element.on("keyup", function (evt) {
8787
+ that._change($(this).val());
8788
+ });
8789
+
8790
+ this.element.on("focus", function () {
8791
+ $("body").one("mousedown", function () {
8792
+ that.element.blur();
8793
+ });
8794
+ });
8795
+ },
8796
+ _change: function (val, instant) {
8797
+ var fireEvent = false;
8798
+ if (val === "") {
8799
+ // this.clearButton.hide();
8800
+ fireEvent = true;
8801
+ } else {
8802
+ // this.clearButton.show();
8803
+ fireEvent = val.length >= (this.options.minimumLength || 0);
8804
+ }
8805
+ var current = this.element.val();
8806
+ fireEvent = fireEvent && current !== this.lastSent;
8807
+ if (fireEvent) {
8808
+ if (!instant && this.options.delay > 0) {
8809
+ clearTimeout(this.currentTimeout);
8810
+ var that = this;
8811
+ this.currentTimeout = setTimeout(function () {
8812
+ that.lastSent = that.element.val();
8813
+ that._trigger("change");
8814
+ }, this.options.delay);
8815
+ } else {
8816
+ this._trigger("change");
8817
+ }
8818
+ }
8819
+ },
8820
+ value: function (val) {
8821
+ if (val === undefined) {
8822
+ return this.element.val();
8823
+ } else {
8824
+ this.element.val(val);
8825
+ this._change(val);
8826
+ }
8827
+ },
8828
+ count: function (val) {
8829
+ if (val === undefined || val === null || val === "") {
8830
+ this.resultCount.text("").hide();
8831
+ } else {
8832
+ this.resultCount.text(val).show();
8833
+ }
8834
+ },
8835
+ change: function () {
8836
+ this._trigger("change");
8837
+ },
8838
+ });
8727
8839
  })(jQuery);
8728
8840
  ;RED.tabs = (function () {
8729
8841
  var defaultTabIcon = 'fa fa-lemon-o';
@@ -36376,15 +36488,15 @@ RED.notifications = (function() {
36376
36488
  var results = [];
36377
36489
 
36378
36490
  function indexProperty(node, label, property) {
36379
- if (typeof property === 'string' || typeof property === 'number') {
36380
- property = ('' + property).toLowerCase();
36491
+ if (typeof property === "string" || typeof property === "number") {
36492
+ property = ("" + property).toLowerCase();
36381
36493
  index[property] = index[property] || {};
36382
36494
  index[property][node.id] = { node: node, label: label };
36383
36495
  } else if (Array.isArray(property)) {
36384
36496
  property.forEach(function (prop) {
36385
36497
  indexProperty(node, label, prop);
36386
36498
  });
36387
- } else if (typeof property === 'object') {
36499
+ } else if (typeof property === "object") {
36388
36500
  for (var prop in property) {
36389
36501
  if (property.hasOwnProperty(prop)) {
36390
36502
  indexProperty(node, label, property[prop]);
@@ -36395,13 +36507,13 @@ RED.notifications = (function() {
36395
36507
  function indexNode(n) {
36396
36508
  var l = RED.utils.getNodeLabel(n);
36397
36509
  if (l) {
36398
- l = ('' + l).toLowerCase();
36510
+ l = ("" + l).toLowerCase();
36399
36511
  index[l] = index[l] || {};
36400
36512
  index[l][n.id] = { node: n, label: l };
36401
36513
  }
36402
- l = l || n.label || n.name || n.id || '';
36514
+ l = l || n.label || n.name || n.id || "";
36403
36515
 
36404
- var properties = ['id', 'type', 'name', 'label', 'info'];
36516
+ var properties = ["id", "type", "name", "label", "info"];
36405
36517
  if (n._def && n._def.defaults) {
36406
36518
  properties = properties.concat(Object.keys(n._def.defaults));
36407
36519
  }
@@ -36429,14 +36541,14 @@ RED.notifications = (function() {
36429
36541
 
36430
36542
  /**
36431
36543
  * User search when typing it the search box...
36432
- * @param {string} val
36544
+ * @param {string} val
36433
36545
  */
36434
36546
  function search(val) {
36435
- searchResults.editableList('empty');
36547
+ searchResults.editableList("empty");
36436
36548
  var typeFilter;
36437
36549
  var m = /(?:^| )type:([^ ]+)/.exec(val);
36438
36550
  if (m) {
36439
- val = val.replace(/(?:^| )type:[^ ]+/, '');
36551
+ val = val.replace(/(?:^| )type:[^ ]+/, "");
36440
36552
  typeFilter = m[1];
36441
36553
  }
36442
36554
 
@@ -36448,27 +36560,25 @@ RED.notifications = (function() {
36448
36560
  // Excluding tabs
36449
36561
  // results = results.filter((r) => r.node.type !== 'tab');
36450
36562
  for (i = 0; i < Math.min(results.length, 25); i++) {
36451
- searchResults.editableList('addItem', results[i]);
36563
+ searchResults.editableList("addItem", results[i]);
36452
36564
  }
36453
36565
  } else {
36454
- searchResults.editableList('addItem', {});
36566
+ searchResults.editableList("addItem", {});
36455
36567
  }
36456
36568
  } else {
36457
36569
  let commands = searchCommands();
36458
- commands.forEach(c => {
36459
- searchResults.editableList('addItem', c);
36570
+ commands.forEach((c) => {
36571
+ searchResults.editableList("addItem", c);
36460
36572
  });
36461
36573
 
36462
- let results = $('#search-result-list');
36574
+ let results = $("#search-result-list");
36463
36575
  $('<div class="searchSeparator"></div>').appendTo(results);
36464
36576
 
36465
-
36466
36577
  let allNodes = searchNodes();
36467
36578
 
36468
- allNodes.forEach(n => {
36469
- searchResults.editableList('addItem', n);
36470
- })
36471
-
36579
+ allNodes.forEach((n) => {
36580
+ searchResults.editableList("addItem", n);
36581
+ });
36472
36582
  }
36473
36583
  }
36474
36584
 
@@ -36507,56 +36617,89 @@ RED.notifications = (function() {
36507
36617
  results.push(nodes[list[i]]);
36508
36618
  }
36509
36619
  } else {
36510
- let setResults = new Set()
36620
+ let setResults = new Set();
36511
36621
  for (const i in index) {
36512
- index[i].forEach(n => {
36622
+ index[i].forEach((n) => {
36513
36623
  if (setResults.has(n.node.id)) return;
36514
36624
  else {
36515
36625
  setResults.add(n.node.id);
36516
- if (n.node.type === 'tab') {
36626
+ if (n.node.type === "tab") {
36517
36627
  results.push({ label: n.node.label, node: n.node });
36518
36628
  } else {
36519
36629
  results.push({ label: n.node.name, node: n.node });
36520
36630
  }
36521
36631
  }
36522
- })
36632
+ });
36523
36633
  }
36524
-
36525
36634
  }
36526
36635
  return results;
36527
-
36528
36636
  }
36529
36637
  /**
36530
36638
  * Returns a list of commands that will be added to the search window when it is opened
36531
36639
  */
36532
36640
  function searchCommands() {
36533
-
36534
36641
  return [
36535
- { type: 'command', title: 'Open Settings', action: 'core:settings:open', shortcut: `${CtrlOrCmd()} /` },
36536
- { type: 'command', title: 'Show Project Info', action: 'core:project-info' },
36537
36642
  {
36538
- type: 'command', title: 'Run Test...', cb: () => {
36539
- if (!$('.sidebar-test').is(':visible')) {
36540
- $('#red-ui-tab-test-link-button').click();
36643
+ type: "command",
36644
+ title: "Open Settings",
36645
+ action: "core:settings:open",
36646
+ shortcut: `${CtrlOrCmd()} /`,
36647
+ },
36648
+ {
36649
+ type: "command",
36650
+ title: "Show Project Info",
36651
+ action: "core:project-info",
36652
+ },
36653
+ {
36654
+ type: "command",
36655
+ title: "Run Test...",
36656
+ cb: () => {
36657
+ if (!$(".sidebar-test").is(":visible")) {
36658
+ $("#red-ui-tab-test-link-button").click();
36541
36659
  }
36542
36660
 
36543
- $('#test-sidebar-run-btn').click();
36544
- }
36661
+ $("#test-sidebar-run-btn").click();
36662
+ },
36663
+ },
36664
+ {
36665
+ type: "command",
36666
+ title: "Open Log Viewer",
36667
+ cb: () => {
36668
+ $("#workspace-terminal").toggle();
36669
+ },
36670
+ shortcut: `${CtrlOrCmd()} T`,
36545
36671
  },
36546
36672
  {
36547
- type: 'command', title: 'Open Log Viewer', cb: () => {
36548
- $('#workspace-terminal').toggle()
36549
- }, shortcut: `${CtrlOrCmd()} T`
36673
+ type: "command",
36674
+ title: "Import Flow",
36675
+ action: "core:show-import-dialog",
36676
+ shortcut: `${CtrlOrCmd()} I`,
36677
+ },
36678
+ {
36679
+ type: "command",
36680
+ title: "Export Flow",
36681
+ action: "core:show-export-dialog",
36682
+ shortcut: `${CtrlOrCmd()} E`,
36550
36683
  },
36551
- { type: 'command', title: 'Import Flow', action: 'core:show-import-dialog', shortcut: `${CtrlOrCmd()} I` },
36552
- { type: 'command', title: 'Export Flow', action: 'core:show-export-dialog', shortcut: `${CtrlOrCmd()} E` },
36553
36684
  // { type: 'command', title: 'SignIn to Kumologica.dev', action: 'core:signup:show' },
36554
36685
  {
36555
- type: 'command', title: 'Help: Documentation', cb: () => {
36556
- window.__kumologica.electron.shell.openExternal('https://docs.kumologica.com/docs/guide/Intro.html');
36557
- }
36558
- }
36559
- ]
36686
+ type: "command",
36687
+ title: "Task: npm install",
36688
+ action: "npm:install",
36689
+ cb: () => {
36690
+ RED.actions.invoke("core:search:close");
36691
+ },
36692
+ },
36693
+ {
36694
+ type: "command",
36695
+ title: "Help: Documentation",
36696
+ cb: () => {
36697
+ window.__kumologica.electron.shell.openExternal(
36698
+ "https://docs.kumologica.com/docs/guide/Intro.html"
36699
+ );
36700
+ },
36701
+ },
36702
+ ];
36560
36703
  }
36561
36704
 
36562
36705
  function CtrlOrCmd() {
@@ -36564,7 +36707,7 @@ RED.notifications = (function() {
36564
36707
  }
36565
36708
 
36566
36709
  function ensureSelectedIsVisible() {
36567
- var selectedEntry = searchResults.find('li.selected');
36710
+ var selectedEntry = searchResults.find("li.selected");
36568
36711
  if (selectedEntry.length === 1) {
36569
36712
  var scrollWindow = searchResults.parent();
36570
36713
  var scrollHeight = scrollWindow.height();
@@ -36573,21 +36716,31 @@ RED.notifications = (function() {
36573
36716
  var h = selectedEntry.height();
36574
36717
  if (y + h > scrollHeight) {
36575
36718
  scrollWindow.animate(
36576
- { scrollTop: '-=' + (scrollHeight - (y + h) - 10) },
36719
+ { scrollTop: "-=" + (scrollHeight - (y + h) - 10) },
36577
36720
  50
36578
36721
  );
36579
36722
  } else if (y < 0) {
36580
- scrollWindow.animate({ scrollTop: '+=' + (y - 10) }, 50);
36723
+ scrollWindow.animate({ scrollTop: "+=" + (y - 10) }, 50);
36581
36724
  }
36582
36725
  }
36583
36726
  }
36584
36727
 
36728
+ function shouldInvokeCommand(value) {
36729
+ if (value.startsWith("npm install")) {
36730
+ RED.actions.invoke("core:search:close");
36731
+ RED.actions.invoke("npm:install", value);
36732
+ RED.modules.updateValue(value);
36733
+ return true;
36734
+ } else {
36735
+ return false;
36736
+ }
36737
+ }
36585
36738
  function createDialog() {
36586
- dialog = $('<div>', {
36587
- id: 'red-ui-search',
36588
- class: 'red-ui-search',
36589
- }).appendTo('#main-container');
36590
- var searchDiv = $('<div>', { class: 'red-ui-search-container' }).appendTo(
36739
+ dialog = $("<div>", {
36740
+ id: "red-ui-search",
36741
+ class: "red-ui-search",
36742
+ }).appendTo("#main-container");
36743
+ var searchDiv = $("<div>", { class: "red-ui-search-container" }).appendTo(
36591
36744
  dialog
36592
36745
  );
36593
36746
  searchInput = $(
@@ -36595,25 +36748,30 @@ RED.notifications = (function() {
36595
36748
  )
36596
36749
  .appendTo(searchDiv)
36597
36750
  .searchBox({
36598
- delay: 200,
36751
+ delay: 100,
36599
36752
  change: function () {
36600
- search($(this).val());
36753
+ let value = $(this).val();
36754
+ if (!shouldInvokeCommand(value)) {
36755
+ search($(this).val());
36756
+ }
36601
36757
  },
36602
36758
  });
36603
36759
 
36604
- searchInput.on('keydown', function (evt) {
36760
+ searchInput.on("keydown", function (evt) {
36605
36761
  var children;
36606
- if (results.length > 0) {
36762
+
36763
+ // Check for embedded commands
36764
+ if (!shouldInvokeCommand(evt.target.value) && results.length > 0) {
36607
36765
  if (evt.keyCode === 40) {
36608
36766
  // Down
36609
36767
  children = searchResults.children();
36610
36768
  if (selected < children.length - 1) {
36611
36769
  if (selected > -1) {
36612
- $(children[selected]).removeClass('selected');
36770
+ $(children[selected]).removeClass("selected");
36613
36771
  }
36614
36772
  selected++;
36615
36773
  }
36616
- $(children[selected]).addClass('selected');
36774
+ $(children[selected]).addClass("selected");
36617
36775
  ensureSelectedIsVisible();
36618
36776
  evt.preventDefault();
36619
36777
  } else if (evt.keyCode === 38) {
@@ -36621,11 +36779,11 @@ RED.notifications = (function() {
36621
36779
  children = searchResults.children();
36622
36780
  if (selected > 0) {
36623
36781
  if (selected < children.length) {
36624
- $(children[selected]).removeClass('selected');
36782
+ $(children[selected]).removeClass("selected");
36625
36783
  }
36626
36784
  selected--;
36627
36785
  }
36628
- $(children[selected]).addClass('selected');
36786
+ $(children[selected]).addClass("selected");
36629
36787
  ensureSelectedIsVisible();
36630
36788
  evt.preventDefault();
36631
36789
  } else if (evt.keyCode === 13) {
@@ -36638,13 +36796,13 @@ RED.notifications = (function() {
36638
36796
  });
36639
36797
  searchInput.i18n();
36640
36798
 
36641
- var searchResultsDiv = $('<div>', {
36642
- class: 'red-ui-search-results-container',
36799
+ var searchResultsDiv = $("<div>", {
36800
+ class: "red-ui-search-results-container",
36643
36801
  }).appendTo(dialog);
36644
36802
 
36645
- searchResults = $('<ol>', {
36646
- id: 'search-result-list',
36647
- style: 'position: absolute;top: 5px;bottom: 5px;left: 5px;right: 5px;',
36803
+ searchResults = $("<ol>", {
36804
+ id: "search-result-list",
36805
+ style: "position: absolute;top: 5px;bottom: 5px;left: 5px;right: 5px;",
36648
36806
  })
36649
36807
  .appendTo(searchResultsDiv)
36650
36808
  .editableList({
@@ -36652,36 +36810,38 @@ RED.notifications = (function() {
36652
36810
  addItem: function (container, i, object) {
36653
36811
  var node = object.node;
36654
36812
 
36655
- // If node === undefined and object is object => object is the command
36813
+ // If node === undefined and object is object => object is the command
36656
36814
  // If node === undefiend and object is empty => user search yield no results
36657
36815
  // otherwise is a normal search ...
36658
36816
 
36659
36817
  if (node === undefined && !object) {
36660
36818
  // case of user search yield no results
36661
- $('<div>', { class: 'red-ui-search-empty' })
36662
- .text('No matches found')
36819
+ $("<div>", { class: "red-ui-search-empty" })
36820
+ .text("No matches found")
36663
36821
  .appendTo(container);
36664
36822
  } else if (node === undefined && object) {
36665
36823
  // case of initial display of options (commands & tabs ) ... (object is a command)
36666
- if (object.type === 'command') {
36667
-
36824
+ if (object.type === "command") {
36668
36825
  // Main result container
36669
- var div = $('<a>', {
36670
- href: '#',
36671
- class: 'red-ui-search-result',
36826
+ var div = $("<a>", {
36827
+ href: "#",
36828
+ class: "red-ui-search-result",
36672
36829
  }).appendTo(container);
36673
36830
 
36674
36831
  // Command title here
36675
- var contentDescription = $('<div>', {
36676
- class: 'red-ui-search-result-description',
36832
+ var contentDescription = $("<div>", {
36833
+ class: "red-ui-search-result-description",
36677
36834
  }).appendTo(div);
36678
36835
 
36679
- $('<div>', { class: 'red-ui-search-result-command-label', style: 'width:95%' })
36836
+ $("<div>", {
36837
+ class: "red-ui-search-result-command-label",
36838
+ style: "width:95%",
36839
+ })
36680
36840
  .text(object.title)
36681
36841
  .appendTo(contentDescription);
36682
36842
 
36683
36843
  // Type of object (command)
36684
- $('<div>', { class: 'red-ui-search-result-command-shortcut' })
36844
+ $("<div>", { class: "red-ui-search-result-command-shortcut" })
36685
36845
  .text(object.shortcut)
36686
36846
  .appendTo(div);
36687
36847
 
@@ -36690,46 +36850,48 @@ RED.notifications = (function() {
36690
36850
  if (object.action) {
36691
36851
  hide();
36692
36852
  window.setTimeout(() => {
36693
- RED.actions.invoke(object.action)
36694
- }, 10)
36853
+ RED.actions.invoke(object.action);
36854
+ }, 10);
36695
36855
  } else {
36696
36856
  hide();
36697
36857
  window.setTimeout(() => {
36698
- object.cb()
36699
- }, 10)
36858
+ object.cb();
36859
+ }, 10);
36700
36860
  }
36701
-
36702
36861
  });
36703
36862
  }
36704
-
36705
36863
  } else {
36706
36864
  var def = node._def;
36707
- var div = $('<a>', {
36708
- href: '#',
36709
- class: 'red-ui-search-result',
36865
+ var div = $("<a>", {
36866
+ href: "#",
36867
+ class: "red-ui-search-result",
36710
36868
  }).appendTo(container);
36711
36869
 
36712
36870
  // ::: Part of the description
36713
- var contentDescription = $('<div>', {
36714
- class: 'red-ui-search-result-description',
36871
+ var contentDescription = $("<div>", {
36872
+ class: "red-ui-search-result-description",
36715
36873
  }).appendTo(div);
36716
36874
 
36717
- // ::: Part of the icon here...
36718
- var nodeDiv = $('<div>', {
36719
- class: 'ui-search-result-node',
36875
+ // ::: Part of the icon here...
36876
+ var nodeDiv = $("<div>", {
36877
+ class: "ui-search-result-node",
36720
36878
  }).appendTo(contentDescription);
36721
36879
 
36722
36880
  var colour = RED.utils.getNodeColor(node.type, def);
36723
36881
  var icon_url = RED.utils.getNodeIcon(def, node);
36724
36882
 
36725
- if (node.type === 'tab') {
36726
- var iconContainer = $('<div/>', {
36727
- class: 'palette_icon_container',
36883
+ if (node.type === "tab") {
36884
+ var iconContainer = $("<div/>", {
36885
+ class: "palette_icon_container",
36728
36886
  }).appendTo(nodeDiv);
36729
- RED.utils.createIconElement('icons/kumologica-core/kumologica-tab.png', iconContainer, true);
36887
+ RED.utils.createIconElement(
36888
+ "icons/kumologica-core/kumologica-tab.png",
36889
+ iconContainer,
36890
+ true
36891
+ );
36730
36892
  } else {
36731
- var iconContainer = $('<div/>', {
36732
- class: 'palette_icon_container',
36893
+ var iconContainer = $("<div/>", {
36894
+ class: "palette_icon_container",
36733
36895
  }).appendTo(nodeDiv);
36734
36896
  RED.utils.createIconElement(icon_url, iconContainer, true);
36735
36897
  }
@@ -36738,22 +36900,22 @@ RED.notifications = (function() {
36738
36900
  var workspace = RED.nodes.workspace(node.z);
36739
36901
  if (!workspace) {
36740
36902
  workspace = RED.nodes.subflow(node.z);
36741
- workspace = 'subflow:' + workspace.name;
36903
+ workspace = "subflow:" + workspace.name;
36742
36904
  } else {
36743
36905
  workspace = workspace.label; //'flow:' + workspace.label
36744
36906
  }
36745
- $('<div>', { class: 'red-ui-search-result-node-flow' })
36907
+ $("<div>", { class: "red-ui-search-result-node-flow" })
36746
36908
  .text(workspace)
36747
36909
  .appendTo(div);
36748
36910
  }
36749
36911
 
36750
- $('<div>', { class: 'red-ui-search-result-node-label' })
36912
+ $("<div>", { class: "red-ui-search-result-node-label" })
36751
36913
  .text(object.label || node.id)
36752
36914
  .appendTo(contentDescription);
36753
- $('<div>', { class: 'red-ui-search-result-node-type' })
36915
+ $("<div>", { class: "red-ui-search-result-node-type" })
36754
36916
  .text(node.type)
36755
36917
  .appendTo(contentDescription);
36756
- $('<div>', { class: 'red-ui-search-result-node-id' })
36918
+ $("<div>", { class: "red-ui-search-result-node-id" })
36757
36919
  .text(node.id)
36758
36920
  .appendTo(contentDescription);
36759
36921
 
@@ -36780,15 +36942,15 @@ RED.notifications = (function() {
36780
36942
 
36781
36943
  function show(v) {
36782
36944
  // Disable the project dialog
36783
- RED.actions.invoke('core:project-info:close');
36784
- RED.actions.invoke('core:settings:close');
36945
+ RED.actions.invoke("core:project-info:close");
36946
+ RED.actions.invoke("core:settings:close");
36785
36947
 
36786
36948
  if (!visible) {
36787
- RED.keyboard.add('*', 'escape', function () {
36949
+ RED.keyboard.add("*", "escape", function () {
36788
36950
  hide();
36789
36951
  });
36790
36952
 
36791
- $('#main-container').click(() => {
36953
+ $("#main-container").click(() => {
36792
36954
  hide();
36793
36955
  });
36794
36956
 
@@ -36798,24 +36960,22 @@ RED.notifications = (function() {
36798
36960
  createDialog();
36799
36961
  }
36800
36962
  dialog.slideDown(300);
36801
- searchInput.searchBox('value', v);
36802
- RED.events.emit('search:open');
36963
+ searchInput.searchBox("value", v);
36964
+ RED.events.emit("search:open");
36803
36965
  visible = true;
36804
36966
  window.setTimeout(() => {
36805
- searchInput.focus()
36967
+ searchInput.focus();
36806
36968
  }, 50);
36807
36969
 
36808
36970
  // Populate search results with commands and tabs at least
36809
36971
  search();
36810
36972
  }
36811
-
36812
-
36813
36973
  }
36814
36974
 
36815
36975
  function hide() {
36816
36976
  if (visible) {
36817
- $('#main-container').off('click');
36818
- RED.keyboard.remove('escape');
36977
+ $("#main-container").off("click");
36978
+ RED.keyboard.remove("escape");
36819
36979
  visible = false;
36820
36980
  // $('#header-shade').hide();
36821
36981
  // $('#editor-shade').hide();
@@ -36824,28 +36984,28 @@ RED.notifications = (function() {
36824
36984
  // $('#sidebar-separator').show();
36825
36985
  if (dialog !== null) {
36826
36986
  dialog.slideUp(200, function () {
36827
- searchInput.searchBox('value', '');
36987
+ searchInput.searchBox("value", "");
36828
36988
  });
36829
36989
  }
36830
- RED.events.emit('search:close');
36990
+ RED.events.emit("search:close");
36831
36991
  }
36832
36992
  }
36833
36993
 
36834
36994
  function init() {
36835
- RED.actions.add('core:search', show);
36836
- RED.actions.add('core:search:close', hide);
36995
+ RED.actions.add("core:search", show);
36996
+ RED.actions.add("core:search:close", hide);
36837
36997
 
36838
- RED.events.on('type-search:open', function () {
36998
+ RED.events.on("type-search:open", function () {
36839
36999
  disabled = true;
36840
37000
  });
36841
- RED.events.on('type-search:close', function () {
37001
+ RED.events.on("type-search:close", function () {
36842
37002
  disabled = false;
36843
37003
  });
36844
37004
 
36845
- $('#header-shade').on('mousedown', hide);
36846
- $('#editor-shade').on('mousedown', hide);
36847
- $('#palette-shade').on('mousedown', hide);
36848
- $('#sidebar-shade').on('mousedown', hide);
37005
+ $("#header-shade").on("mousedown", hide);
37006
+ $("#editor-shade").on("mousedown", hide);
37007
+ $("#palette-shade").on("mousedown", hide);
37008
+ $("#sidebar-shade").on("mousedown", hide);
36849
37009
  }
36850
37010
 
36851
37011
  return {
@@ -36853,7 +37013,171 @@ RED.notifications = (function() {
36853
37013
  show: show,
36854
37014
  hide: hide,
36855
37015
  reveal: reveal,
36856
- revealByNodeId: revealByNodeId
37016
+ revealByNodeId: revealByNodeId,
37017
+ };
37018
+ })();
37019
+ ;RED.modules = (function () {
37020
+ let dialog;
37021
+ let commandInputContainer;
37022
+ let visible = false;
37023
+
37024
+ const NPM_INSTALL_CMD = "npm install";
37025
+ function createDialog() {
37026
+ console.log("[RED.modules.createDialog] Invoked");
37027
+
37028
+ let $mainContainer = $("#main-container");
37029
+
37030
+ dialog = $(
37031
+ `<div id="modules-dialog-container" class="red-ui-search"></div>`
37032
+ ).appendTo($mainContainer);
37033
+
37034
+ dialog.on("click", function (e) {
37035
+ e.stopPropagation();
37036
+ });
37037
+
37038
+ console.log(
37039
+ "[RED.modules.createDialog] Looking for hook for main-container",
37040
+ $("#main-container")
37041
+ );
37042
+
37043
+ commandInputContainer = $("<div>", {
37044
+ class: "command-input-container",
37045
+ }).appendTo(dialog);
37046
+
37047
+ installInput = $(
37048
+ `<input type="text" placeholder="Type module to install...">`
37049
+ )
37050
+ .appendTo(commandInputContainer)
37051
+ .commandBox({
37052
+ command: NPM_INSTALL_CMD,
37053
+ delay: 100,
37054
+ change: function () {
37055
+ evaluateCommand($(this).val());
37056
+ },
37057
+ execute: function (command) {
37058
+ hide();
37059
+ $("#workspace-terminal").show();
37060
+ console.log("[modules] command received", command);
37061
+ executeCommand(command);
37062
+ },
37063
+ });
37064
+ console.log("[RED.modules.createDialog] 2");
37065
+
37066
+ installInput.on("keydown", function (evt) {
37067
+ if (evt.key === "Enter" || evt.keyCode === 13) {
37068
+ evt.preventDefault(); // Prevent default action if necessary
37069
+ evaluateCommand($(this).val());
37070
+ }
37071
+ });
37072
+
37073
+ installInput.on("paste", function (evt) {
37074
+ evt.preventDefault();
37075
+
37076
+ let clipboardData =
37077
+ evt.originalEvent.clipboardData || window.clipboardData;
37078
+ let pastedData = clipboardData.getData("Text");
37079
+ if (pastedData.startsWith(NPM_INSTALL_CMD)) {
37080
+ pastedData = pastedData.slice(NPM_INSTALL_CMD.length).trim();
37081
+ }
37082
+
37083
+ installInput.commandBox("value", `${NPM_INSTALL_CMD} ${pastedData}`);
37084
+ });
37085
+ }
37086
+
37087
+ function init() {
37088
+ RED.actions.add("npm:install", show);
37089
+ RED.actions.add("npm:install:close", hide);
37090
+ }
37091
+
37092
+ function show(v) {
37093
+ if (!visible) {
37094
+ RED.keyboard.add("*", "escape", function () {
37095
+ hide();
37096
+ });
37097
+
37098
+ $("#main-container").click(() => {
37099
+ hide();
37100
+ });
37101
+
37102
+ console.log("[modules.show] dialog?", dialog);
37103
+ if (!dialog) {
37104
+ createDialog();
37105
+ }
37106
+ // restore the value to the original
37107
+ installInput.commandBox("value", NPM_INSTALL_CMD + " ");
37108
+ visible = true;
37109
+ console.log("[modules.show] dialog created");
37110
+ dialog.slideDown(300);
37111
+
37112
+ RED.events.emit("modules:install");
37113
+ window.setTimeout(() => {
37114
+ installInput.focus();
37115
+ }, 50);
37116
+ }
37117
+ }
37118
+ function updateValue(value) {
37119
+ installInput.commandBox("value", value);
37120
+ }
37121
+ function hide() {
37122
+ if (visible) {
37123
+ $("#main-container").off("click");
37124
+ RED.keyboard.remove("escape");
37125
+ visible = false;
37126
+ if (dialog !== null) {
37127
+ dialog.slideUp(200, function () {
37128
+ installInput.commandBox("value", NPM_INSTALL_CMD);
37129
+ });
37130
+ }
37131
+ RED.events.emit("modules:close");
37132
+ }
37133
+ }
37134
+
37135
+ function evaluateCommand(module) {
37136
+ // check that module contains the prefix: NPM_INSTALL_CMD otherwise quit the app
37137
+ if (!module.startsWith(NPM_INSTALL_CMD)) {
37138
+ hide();
37139
+ RED.actions.invoke("core:search");
37140
+ } else {
37141
+ const moduleName = module.slice(NPM_INSTALL_CMD.length).trim();
37142
+ console.log(`npm install ${moduleName}`);
37143
+ }
37144
+ }
37145
+
37146
+ async function executeCommand(command) {
37147
+ try {
37148
+ await window.__kumologica.command.npmInstall(command);
37149
+ RED.notifications.notify(
37150
+ "<b>Task Completed Successfully</b></br>Please reload the designer to update the nodes palette.",
37151
+ {
37152
+ type: "success",
37153
+ buttons: [
37154
+ {
37155
+ text: "Reload",
37156
+ click: () => {
37157
+ window.__kumologica.main.dispatch("restart-requested");
37158
+ },
37159
+ },
37160
+ ],
37161
+ fixed: true,
37162
+ },
37163
+ true,
37164
+ undefined
37165
+ );
37166
+ } catch (err) {
37167
+ RED.notifications.notify(
37168
+ "<b>Error: Task Failed</b></br>The task could not be completed due to errors. Check the logs for details",
37169
+ "error",
37170
+ undefined,
37171
+ 5000
37172
+ );
37173
+ }
37174
+ }
37175
+
37176
+ return {
37177
+ init,
37178
+ show,
37179
+ hide,
37180
+ updateValue,
36857
37181
  };
36858
37182
  })();
36859
37183
  ;RED.projectInfo = (function () {
@@ -37092,62 +37416,67 @@ RED.notifications = (function() {
37092
37416
  getWorkspaceInfo
37093
37417
  };
37094
37418
  })();
37095
- ;RED.uiSettings = (function(){
37096
- let testConfigStore;
37097
- let cloudConfigStore = window.__kumologica.settings.cloudConfigStore;
37098
- let networkConfigStore = window.__kumologica.settings.networkConfigStore
37099
- let shell = window.__kumologica.electron.shell;
37100
- let dialog = null;
37101
- let visible = false;
37102
- let cmInstanceCloud = null;
37103
- let cmInstanceEnvvars = null;
37104
- let totalHeightAvailable;
37105
-
37106
- let screen;
37107
-
37108
- function getScreen() {
37109
- if (!screen){
37110
- // we get a reference here and not like the rest of the stores, as the testConfig relies on the project details set which are injected in the header.
37111
- testConfigStore = window.__kumologica.settings.testConfig;
37112
- // initialize the screen now
37113
- screen = [
37114
- { "selected": true,
37115
- "id": "ui-settings-creds",
37116
- "label": "Cloud Profiles",
37117
- "body": {
37118
- "title": "Cloud Profiles",
37119
- "subtitle": `
37419
+ ;RED.uiSettings = (function () {
37420
+ let testConfigStore;
37421
+ let cloudConfigStore = window.__kumologica.settings.cloudConfigStore;
37422
+ let networkConfigStore = window.__kumologica.settings.networkConfigStore;
37423
+ let shell = window.__kumologica.electron.shell;
37424
+ let dialog = null;
37425
+ let visible = false;
37426
+ let cmInstanceCloud = null;
37427
+ let cmInstanceEnvvars = null;
37428
+ let totalHeightAvailable;
37429
+
37430
+ let screen;
37431
+
37432
+ function getScreen() {
37433
+ if (!screen) {
37434
+ // we get a reference here and not like the rest of the stores, as the testConfig relies on the project details set which are injected in the header.
37435
+ testConfigStore = window.__kumologica.settings.testConfig;
37436
+ // initialize the screen now
37437
+ screen = [
37438
+ {
37439
+ selected: true,
37440
+ id: "ui-settings-creds",
37441
+ label: "Cloud Profiles",
37442
+ body: {
37443
+ title: "Cloud Profiles",
37444
+ subtitle: `
37120
37445
  Configure all of your cloud profile settings that can be used by this designer to support testing or deploying.
37121
37446
  <a href="https://docs.kumologica.com/docs/guide/Intro.html" target="_blank">Learn more</a>`,
37122
- "html": `
37447
+ html: `
37123
37448
  <div>
37124
37449
  <div id="fileLocationPath">
37125
37450
  <span id="settingFilePath">${cloudConfigStore.getCloudConfigFileFullPath()}</span>
37126
37451
  </div>
37127
37452
  <textarea id="cloud-settings-editor" rows="20">
37128
37453
  </textarea>
37129
- </div>`
37130
- },
37131
- "onInit": () => {
37132
- // load content of config credentials file: ~/.kumologica/credentials
37133
- let cloudConfigContent = cloudConfigStore.readCloudConfigFile();
37134
- cmInstanceCloud = initEditor('cloud-settings-editor', cloudConfigContent);
37135
- },
37136
- "onSelect": () => {
37137
- cmInstanceCloud.refresh();
37138
- },
37139
- "onSave": () => {
37140
- cloudConfigStore.writeCloudConfigFile(cmInstanceCloud.getValue());
37141
- RED.events.emit('settings:cloud-config-changed');
37142
- }
37454
+ </div>`,
37143
37455
  },
37144
- {
37145
- "id": "ui-settings-network",
37146
- "label": "Network",
37147
- "body": {
37148
- "title": "Proxy Server Settings",
37149
- "subtitle": "Configure the proxy settings used by the designer. Flows will use the proxy specified on the nodes instead.",
37150
- "html": `
37456
+ onInit: () => {
37457
+ // load content of config credentials file: ~/.kumologica/credentials
37458
+ let cloudConfigContent = cloudConfigStore.readCloudConfigFile();
37459
+ cmInstanceCloud = initEditor(
37460
+ "cloud-settings-editor",
37461
+ cloudConfigContent
37462
+ );
37463
+ },
37464
+ onSelect: () => {
37465
+ cmInstanceCloud.refresh();
37466
+ },
37467
+ onSave: () => {
37468
+ cloudConfigStore.writeCloudConfigFile(cmInstanceCloud.getValue());
37469
+ RED.events.emit("settings:cloud-config-changed");
37470
+ },
37471
+ },
37472
+ {
37473
+ id: "ui-settings-network",
37474
+ label: "Network",
37475
+ body: {
37476
+ title: "Proxy Server Settings",
37477
+ subtitle:
37478
+ "Configure the proxy settings used by the designer. Flows will use the proxy specified on the nodes instead.",
37479
+ html: `
37151
37480
  <div>
37152
37481
  <form id="proxy-options-div">
37153
37482
  <input type="radio" id="proxy-option-default" name="proxy-option" style="margin:0"> Use default operating system settings<br>
@@ -37158,45 +37487,45 @@ RED.notifications = (function() {
37158
37487
  <div class="option"><label>Port</label><input type="text" id="proxy-port" /></div>
37159
37488
  </div>
37160
37489
  <div id="proxy-auth">
37161
- <div id="proxyCredsRequiredBox" style="display: flex">
37162
- <input type="checkbox" id="proxyAuthRequired" style="margin-right: 3px">
37490
+ <div id="proxyCredsRequiredBox" style="display: flex; align-items: flex-start">
37491
+ <input type="checkbox" id="proxyAuthRequired" style="margin-top: 3px; margin-right: 3px">
37163
37492
  <label>Proxy server requires username and password</label>
37164
37493
  </div>
37165
- <div id="proxyCredsBox" style="padding-left: 40px">
37494
+ <div id="proxyCredsBox" style="padding-top: 10px;padding-left: 40px">
37166
37495
  <div class="option"><label>Username</label><input type="text" id="proxy-auth-username" style="width:50%" /></div>
37167
37496
  <div class="option"><label>Password</label><input type="password" id="proxy-auth-password" style="width:50%"/></div>
37168
37497
  </div>
37169
37498
  </div>
37170
37499
  </div>
37171
- `
37172
- },
37173
- "onInit": () => {
37174
- // load content of config credentials file: ~/.kumologica/settings
37175
- let proxySettings = networkConfigStore.getProxyDetails();
37176
- initProxySettings(proxySettings);
37177
- handleProxySettingsEvent();
37178
- },
37179
- "onSelect": () => {},
37180
- "onSave": () => {
37181
- // Save proxy details
37182
- networkConfigStore.saveProxyDetails(
37183
- $('#proxy-option-custom').is(':checked'), // custom clicked?
37184
- $('#proxy-server').val(), // host
37185
- $('#proxy-port').val(), // port
37186
- $('#proxyAuthRequired').is(':checked'), // authentication clicked?
37187
- $('#proxy-auth-username').val(), // username
37188
- $('#proxy-auth-password').val() // password
37189
- );
37190
- }
37500
+ `,
37191
37501
  },
37192
- {
37193
- "id": "ui-settings-envvars",
37194
- "label": "Environments",
37195
- "body": {
37196
- "title": "Environments",
37197
- "subtitle": `
37502
+ onInit: () => {
37503
+ // load content of config credentials file: ~/.kumologica/settings
37504
+ let proxySettings = networkConfigStore.getProxyDetails();
37505
+ initProxySettings(proxySettings);
37506
+ handleProxySettingsEvent();
37507
+ },
37508
+ onSelect: () => {},
37509
+ onSave: () => {
37510
+ // Save proxy details
37511
+ networkConfigStore.saveProxyDetails(
37512
+ $("#proxy-option-custom").is(":checked"), // custom clicked?
37513
+ $("#proxy-server").val(), // host
37514
+ $("#proxy-port").val(), // port
37515
+ $("#proxyAuthRequired").is(":checked"), // authentication clicked?
37516
+ $("#proxy-auth-username").val(), // username
37517
+ $("#proxy-auth-password").val() // password
37518
+ );
37519
+ },
37520
+ },
37521
+ {
37522
+ id: "ui-settings-envvars",
37523
+ label: "Environments",
37524
+ body: {
37525
+ title: "Environments",
37526
+ subtitle: `
37198
37527
  Environments are groups of key value pairs (variables) that allow you to quickly set a different context for each test executions`,
37199
- "html": `
37528
+ html: `
37200
37529
  <div>
37201
37530
  <!--
37202
37531
  <div id="fileLocationPath">
@@ -37204,393 +37533,398 @@ RED.notifications = (function() {
37204
37533
  </div> -->
37205
37534
  <textarea id="envvar-settings-editor" rows="20">
37206
37535
  </textarea>
37207
- </div>`
37208
- },
37209
- "onInit": () => {
37210
- let envvarConfigContent = testConfigStore.getEnvironmentSectionFromConfig();
37211
- cmInstanceEnvvars = initEditor('envvar-settings-editor', envvarConfigContent);
37212
- },
37213
- "onSelect": () => {
37214
- cmInstanceEnvvars.refresh();
37215
- },
37216
- "onSave": () => {
37217
- testConfigStore.saveEnvironmentSectionIntoConfig(cmInstanceEnvvars.getValue());
37218
- RED.events.emit('settings:environment-variables-changed');
37219
- }
37220
- }
37221
- ];
37222
- }
37223
- return screen;
37536
+ </div>`,
37537
+ },
37538
+ onInit: () => {
37539
+ let envvarConfigContent =
37540
+ testConfigStore.getEnvironmentSectionFromConfig();
37541
+ cmInstanceEnvvars = initEditor(
37542
+ "envvar-settings-editor",
37543
+ envvarConfigContent
37544
+ );
37545
+ },
37546
+ onSelect: () => {
37547
+ cmInstanceEnvvars.refresh();
37548
+ },
37549
+ onSave: () => {
37550
+ testConfigStore.saveEnvironmentSectionIntoConfig(
37551
+ cmInstanceEnvvars.getValue()
37552
+ );
37553
+ RED.events.emit("settings:environment-variables-changed");
37554
+ },
37555
+ },
37556
+ ];
37224
37557
  }
37558
+ return screen;
37559
+ }
37225
37560
 
37226
- function createDialog() {
37227
-
37228
-
37229
- // remove if previous dialog exist
37230
- $('#ui-settings').remove();
37561
+ function createDialog() {
37562
+ // remove if previous dialog exist
37563
+ $("#ui-settings").remove();
37231
37564
 
37232
- dialog = $('<div>', {
37233
- id: 'ui-settings',
37234
- class: 'ui-settings',
37235
- }).appendTo('#main-container');
37565
+ dialog = $("<div>", {
37566
+ id: "ui-settings",
37567
+ class: "ui-settings",
37568
+ }).appendTo("#main-container");
37236
37569
 
37237
- // Programmatically calculate the height of the ui-settings window
37238
- totalHeightAvailable = $('#main-container').height();
37239
- let offset = 74;
37240
- $('#ui-settings').height(totalHeightAvailable - offset);
37570
+ // Programmatically calculate the height of the ui-settings window
37571
+ totalHeightAvailable = $("#main-container").height();
37572
+ let offset = 74;
37573
+ $("#ui-settings").height(900);
37241
37574
 
37242
- let wrapperDiv = $('<div>', {
37243
- class: 'ui-settings-body'
37244
- }).appendTo(dialog);
37575
+ let wrapperDiv = $("<div>", {
37576
+ class: "ui-settings-body",
37577
+ }).appendTo(dialog);
37245
37578
 
37246
- // Left pannel of settings
37247
- let optionsDiv = $(`
37579
+ // Left pannel of settings
37580
+ let optionsDiv = $(`
37248
37581
  <div id="ui-settings-options">
37249
37582
  </div>
37250
37583
  `).appendTo(wrapperDiv);
37251
37584
 
37252
- // Left pannel of settings
37253
- getScreen().forEach(option => {
37254
- if (option.selected){
37255
- $(`
37585
+ // Left pannel of settings
37586
+ getScreen().forEach((option) => {
37587
+ if (option.selected) {
37588
+ $(`
37256
37589
  <div id="${option.id}" class="ui-settings-option ui-settings-option-selected">
37257
37590
  <span class="settingsOptionLabel">
37258
37591
  ${option.label}
37259
37592
  </span>
37260
37593
  </div>`).appendTo(optionsDiv);
37261
- } else {
37262
- $(`
37594
+ } else {
37595
+ $(`
37263
37596
  <div id="${option.id}" class="ui-settings-option ui-settings-option">
37264
37597
  <span class="settingsOptionLabel">
37265
37598
  ${option.label}
37266
37599
  </span>
37267
37600
  </div>`).appendTo(optionsDiv);
37268
- }
37269
-
37270
- });
37601
+ }
37602
+ });
37271
37603
 
37272
- // Right pannel of settings
37273
- let optionsBodyDiv = $(`
37604
+ // Right pannel of settings
37605
+ let optionsBodyDiv = $(`
37274
37606
  <div id="ui-settings-optionsbody">
37275
37607
  </div>
37276
- `).appendTo(wrapperDiv)
37608
+ `).appendTo(wrapperDiv);
37277
37609
 
37278
- getScreen().forEach(option => {
37279
- $(`
37610
+ getScreen().forEach((option) => {
37611
+ $(`
37280
37612
  <div id="${option.id}-body" class="ui-settings-general-body">
37281
- <div>
37613
+ <div style="display=flex; flex-direction: column; height:100%">
37282
37614
  <div class="settingsTitle">${option.body.title}</div>
37283
37615
  <div class="settingsSubtitle">${option.body.subtitle}</div>
37284
37616
  ${option.body.html}
37285
37617
  </div>
37286
37618
  </div>
37287
- `).appendTo(optionsBodyDiv)
37288
- });
37289
-
37290
- $(`
37291
- <div class="editor-tray-toolbar" style="top: 16px !important">
37619
+ `).appendTo(optionsBodyDiv);
37620
+ });
37621
+
37622
+ $(`
37623
+ <div class="editor-tray-toolbar">
37292
37624
  <button class="ui-button ui-widget ui-state-default ui-corner-all ui-buton-text-only secondary" role="button" aria-disabled="false" id="options-cancel">Cancel</button>
37293
37625
  <button class="ui-button ui-widget ui-state-default ui-corner-all ui-buton-text-only primary" role="button" aria-disabled="false" id="options-save">Save</button>
37294
37626
  </div>
37295
37627
  `).appendTo(optionsBodyDiv);
37296
37628
 
37297
- // Initialize the options body screen
37298
- getScreen().forEach(option => {
37299
- // Left click on option
37300
- $(`#${option.id}`).click ((e) => {
37301
- resetWindows();
37302
- $(`#${option.id}`).addClass('ui-settings-option-selected');
37303
- $(`#${option.id}-body`).show();
37304
- option.onSelect();
37305
- });
37306
- // Specific functionality
37307
- option.onInit()
37629
+ // Initialize the options body screen
37630
+ getScreen().forEach((option) => {
37631
+ // Left click on option
37632
+ $(`#${option.id}`).click((e) => {
37633
+ resetWindows();
37634
+ $(`#${option.id}`).addClass("ui-settings-option-selected");
37635
+ $(`#${option.id}-body`).show();
37636
+ option.onSelect();
37637
+ });
37638
+ // Specific functionality
37639
+ option.onInit();
37308
37640
 
37309
- // Hide screen if not default
37310
- if (option.hasOwnProperty("selected") && option.selected){
37311
- $(`#${option.id}-body`).show();
37312
- } else {
37313
- $(`#${option.id}-body`).hide();
37314
- }
37315
- });
37316
- // Initialize the toolbar
37317
- $('#options-save').click(e=> {
37318
- saveSettings();
37319
- });
37641
+ // Hide screen if not default
37642
+ if (option.hasOwnProperty("selected") && option.selected) {
37643
+ $(`#${option.id}-body`).show();
37644
+ } else {
37645
+ $(`#${option.id}-body`).hide();
37646
+ }
37647
+ });
37648
+ // Initialize the toolbar
37649
+ $("#options-save").click((e) => {
37650
+ saveSettings();
37651
+ });
37320
37652
 
37321
- $('#options-cancel').click(e => {
37322
- cancelSettings();
37323
- });
37653
+ $("#options-cancel").click((e) => {
37654
+ cancelSettings();
37655
+ });
37656
+ }
37324
37657
 
37325
- }
37658
+ function saveSettings() {
37659
+ getScreen().forEach((option) => {
37660
+ option.onSave();
37661
+ });
37662
+ hide();
37663
+ }
37326
37664
 
37327
- function saveSettings() {
37328
- getScreen().forEach(option => {
37329
- option.onSave();
37330
- })
37331
- hide();
37332
- }
37665
+ function cancelSettings() {
37666
+ hide();
37667
+ }
37333
37668
 
37334
- function cancelSettings() {
37335
- hide();
37336
- }
37669
+ function selectProxyCustom() {
37670
+ setTimeout(() => {
37671
+ $("#proxy-option-custom").prop("checked", true);
37672
+ $("#proxy-option-default").prop("checked", false);
37673
+ }, 50);
37337
37674
 
37338
- function selectProxyCustom() {
37339
- setTimeout(() => {
37340
- $('#proxy-option-custom').prop('checked', true);
37341
- $('#proxy-option-default').prop('checked', false);
37342
- }, 50);
37675
+ $("#proxy-server").prop("readonly", false);
37676
+ $("#proxy-port").prop("readonly", false);
37677
+ }
37343
37678
 
37344
- $('#proxy-server').prop('readonly', false);
37345
- $('#proxy-port').prop('readonly', false);
37346
- }
37679
+ function selectProxyDefault() {
37680
+ setTimeout(() => {
37681
+ $("#proxy-option-custom").prop("checked", false);
37682
+ $("#proxy-option-default").prop("checked", true);
37683
+ }, 50);
37347
37684
 
37348
- function selectProxyDefault(){
37349
- setTimeout(() => {
37350
- $('#proxy-option-custom').prop('checked', false);
37351
- $('#proxy-option-default').prop('checked', true);
37352
- }, 50);
37353
-
37354
- $('#proxy-server').prop('readonly', true);
37355
- $('#proxy-port').prop('readonly', true);
37356
- }
37685
+ $("#proxy-server").prop("readonly", true);
37686
+ $("#proxy-port").prop("readonly", true);
37687
+ }
37357
37688
 
37358
- function selectProxyAuth() {
37359
- setTimeout(() => {
37360
- let isChecked = $('#proxyAuthRequired').is(':checked');
37361
- if (isChecked){
37362
- $('#proxyAuthRequired').prop('checked', false);
37363
- $('#proxy-auth-username').prop('readonly', true);
37364
- $('#proxy-auth-password').prop('readonly', true);
37365
- } else {
37366
- $('#proxyAuthRequired').prop('checked', true);
37367
- $('#proxy-auth-username').prop('readonly', false);
37368
- $('#proxy-auth-password').prop('readonly', false);
37369
- }
37370
- }, 50);
37371
- }
37689
+ function selectProxyAuth() {
37690
+ setTimeout(() => {
37691
+ let isChecked = $("#proxyAuthRequired").is(":checked");
37692
+ if (isChecked) {
37693
+ $("#proxyAuthRequired").prop("checked", false);
37694
+ $("#proxy-auth-username").prop("readonly", true);
37695
+ $("#proxy-auth-password").prop("readonly", true);
37696
+ } else {
37697
+ $("#proxyAuthRequired").prop("checked", true);
37698
+ $("#proxy-auth-username").prop("readonly", false);
37699
+ $("#proxy-auth-password").prop("readonly", false);
37700
+ }
37701
+ }, 50);
37702
+ }
37372
37703
 
37373
- function handleProxySettingsEvent(){
37374
- $('#proxy-option-default').click( () => {
37375
- RED.events.emit('settings:select-proxy-default');
37376
- return false;
37377
- });
37704
+ function handleProxySettingsEvent() {
37705
+ $("#proxy-option-default").click(() => {
37706
+ RED.events.emit("settings:select-proxy-default");
37707
+ return false;
37708
+ });
37378
37709
 
37379
- $('#proxy-option-custom').click( () => {
37380
- RED.events.emit('settings:select-proxy-custom');
37381
- return false;
37382
- });
37710
+ $("#proxy-option-custom").click(() => {
37711
+ RED.events.emit("settings:select-proxy-custom");
37712
+ return false;
37713
+ });
37383
37714
 
37384
- $('#proxyAuthRequired').click( function(e){
37385
- RED.events.emit('settings:select-proxy-auth');
37386
- return false;
37387
- });
37715
+ $("#proxyAuthRequired").click(function (e) {
37716
+ RED.events.emit("settings:select-proxy-auth");
37717
+ return false;
37718
+ });
37719
+ }
37720
+
37721
+ function initProxySettings(proxySettings) {
37722
+ // console.log('[ui-settings] initProxySettings with settings:', proxySettings);
37723
+ // Proxy server
37724
+ if (proxySettings.custom) {
37725
+ $("#proxy-option-custom").prop("checked", true);
37726
+ $("#proxy-option-default").prop("checked", false);
37727
+ $("#proxy-server").val(proxySettings.host);
37728
+ $("#proxy-port").val(proxySettings.port || "8080");
37729
+ } else {
37730
+ $("#proxy-option-default").prop("checked", true);
37731
+ $("#proxy-option-custom").prop("checked", false);
37732
+ $("#proxy-server").prop("readonly", true);
37733
+ $("#proxy-port").prop("readonly", true);
37734
+ }
37735
+ // Proxy auth
37736
+ if (proxySettings.authentication) {
37737
+ $("#proxyAuthRequired").prop("checked", true);
37738
+ $("#proxy-auth-username").val(proxySettings.username);
37739
+ $("#proxy-auth-password").val(proxySettings.password);
37740
+ } else {
37741
+ $("#proxyAuthRequired").prop("checked", false);
37742
+ $("#proxy-auth-username").prop("readonly", true);
37743
+ $("#proxy-auth-password").prop("readonly", true);
37388
37744
  }
37389
37745
 
37390
- function initProxySettings(proxySettings){
37391
- // console.log('[ui-settings] initProxySettings with settings:', proxySettings);
37392
- // Proxy server
37393
- if (proxySettings.custom){
37394
- $('#proxy-option-custom').prop('checked', true);
37395
- $('#proxy-option-default').prop('checked', false);
37396
- $('#proxy-server').val(proxySettings.host);
37397
- $('#proxy-port').val(proxySettings.port || '8080');
37398
- } else {
37399
- $('#proxy-option-default').prop('checked', true);
37400
- $('#proxy-option-custom').prop('checked', false);
37401
- $('#proxy-server').prop('readonly', true);
37402
- $('#proxy-port').prop('readonly', true);
37403
- }
37404
- // Proxy auth
37405
- if (proxySettings.authentication){
37406
- $('#proxyAuthRequired').prop('checked', true);
37407
- $('#proxy-auth-username').val(proxySettings.username);
37408
- $('#proxy-auth-password').val(proxySettings.password);
37409
- } else {
37410
- $('#proxyAuthRequired').prop('checked', false);
37411
- $('#proxy-auth-username').prop('readonly', true);
37412
- $('#proxy-auth-password').prop('readonly', true);
37413
- }
37746
+ RED.events.on("settings:select-proxy-custom", selectProxyCustom);
37747
+ RED.events.on("settings:select-proxy-default", selectProxyDefault);
37748
+ RED.events.on("settings:select-proxy-auth", selectProxyAuth);
37749
+ }
37414
37750
 
37415
- RED.events.on('settings:select-proxy-custom', selectProxyCustom);
37416
- RED.events.on('settings:select-proxy-default', selectProxyDefault);
37417
- RED.events.on('settings:select-proxy-auth', selectProxyAuth);
37418
- }
37751
+ function initEditor(anchorId, contentBody) {
37752
+ CodeMirror.defineMode("properties", function () {
37753
+ return {
37754
+ token: function (stream, state) {
37755
+ var sol = stream.sol() || state.afterSection;
37756
+ var eol = stream.eol();
37419
37757
 
37420
- function initEditor(anchorId, contentBody) {
37421
- CodeMirror.defineMode("properties", function() {
37422
- return {
37423
- token: function(stream, state) {
37424
- var sol = stream.sol() || state.afterSection;
37425
- var eol = stream.eol();
37426
-
37427
- state.afterSection = false;
37428
-
37429
- if (sol) {
37430
- if (state.nextMultiline) {
37431
- state.inMultiline = true;
37432
- state.nextMultiline = false;
37433
- } else {
37434
- state.position = "def";
37435
- }
37436
- }
37437
-
37438
- if (eol && ! state.nextMultiline) {
37439
- state.inMultiline = false;
37440
- state.position = "def";
37441
- }
37442
-
37443
- if (sol) {
37444
- while(stream.eatSpace()) {}
37445
- }
37446
-
37447
- var ch = stream.next();
37448
-
37449
- if (sol && (ch === "#" || ch === "!" || ch === ";")) {
37450
- state.position = "comment";
37451
- stream.skipToEnd();
37452
- return "comment";
37453
- } else if (sol && ch === "[") {
37454
- state.afterSection = true;
37455
- stream.skipTo("]"); stream.eat("]");
37456
- return "header";
37457
- } else if (ch === "=") {
37458
- state.position = "quote";
37459
- return null;
37460
- } else if (ch === "\\" && state.position === "quote") {
37461
- if (stream.eol()) { // end of line?
37462
- // Multiline value
37463
- state.nextMultiline = true;
37464
- }
37465
- }
37466
-
37467
- return state.position;
37468
- },
37469
-
37470
- startState: function() {
37471
- return {
37472
- position : "def", // Current position, "def", "quote" or "comment"
37473
- nextMultiline : false, // Is the next line multiline value
37474
- inMultiline : false, // Is the current line a multiline value
37475
- afterSection : false // Did we just open a section
37476
- };
37477
- }
37478
-
37479
- };
37480
- });
37481
- let cmInstance = CodeMirror.fromTextArea(document.getElementById(anchorId), {
37482
- theme: "monokai",
37483
- lineWrapping: true,
37484
- mode: 'properties'
37485
- });
37758
+ state.afterSection = false;
37486
37759
 
37487
- // reset the listenere
37488
- cmInstance.off("change");
37760
+ if (sol) {
37761
+ if (state.nextMultiline) {
37762
+ state.inMultiline = true;
37763
+ state.nextMultiline = false;
37764
+ } else {
37765
+ state.position = "def";
37766
+ }
37767
+ }
37489
37768
 
37490
- cmInstance.getDoc().setValue(contentBody);
37491
- cmInstance.focus();
37492
- //console.log(`lineCount: ${cmInstance.lineCount()}`)
37493
- // Set the cursor at the end of existing content
37494
- cmInstance.setCursor(cmInstance.lineCount(), 0);
37495
- let codeMirrorHeight = totalHeightAvailable - 400;
37769
+ if (eol && !state.nextMultiline) {
37770
+ state.inMultiline = false;
37771
+ state.position = "def";
37772
+ }
37496
37773
 
37497
- cmInstance.setSize(null, codeMirrorHeight);
37498
- // cmInstance.refresh();
37499
- setTimeout(function() {
37500
- cmInstance.refresh();
37501
- }, 100);
37774
+ if (sol) {
37775
+ while (stream.eatSpace()) {}
37776
+ }
37502
37777
 
37503
- cmInstance.on("change", function(cm, change){
37504
- // enable the save button
37505
- $('#options-save').removeClass('disabled');
37506
- })
37778
+ var ch = stream.next();
37507
37779
 
37508
- return cmInstance;
37509
- }
37780
+ if (sol && (ch === "#" || ch === "!" || ch === ";")) {
37781
+ state.position = "comment";
37782
+ stream.skipToEnd();
37783
+ return "comment";
37784
+ } else if (sol && ch === "[") {
37785
+ state.afterSection = true;
37786
+ stream.skipTo("]");
37787
+ stream.eat("]");
37788
+ return "header";
37789
+ } else if (ch === "=") {
37790
+ state.position = "quote";
37791
+ return null;
37792
+ } else if (ch === "\\" && state.position === "quote") {
37793
+ if (stream.eol()) {
37794
+ // end of line?
37795
+ // Multiline value
37796
+ state.nextMultiline = true;
37797
+ }
37798
+ }
37510
37799
 
37511
- function show(){
37512
-
37513
- // Disable the search dialog if opened
37514
- RED.actions.invoke('core:search:close');
37515
- RED.actions.invoke('core:project-info:close');
37516
- if (!visible){
37517
- RED.keyboard.add('*', 'escape', () => hide() );
37800
+ return state.position;
37801
+ },
37518
37802
 
37519
- createDialog();
37520
- dialog.slideDown(300);
37521
- visible = true;
37803
+ startState: function () {
37804
+ return {
37805
+ position: "def", // Current position, "def", "quote" or "comment"
37806
+ nextMultiline: false, // Is the next line multiline value
37807
+ inMultiline: false, // Is the current line a multiline value
37808
+ afterSection: false, // Did we just open a section
37809
+ };
37810
+ },
37811
+ };
37812
+ });
37813
+ let cmInstance = CodeMirror.fromTextArea(
37814
+ document.getElementById(anchorId),
37815
+ {
37816
+ theme: "monokai",
37817
+ lineWrapping: true,
37818
+ mode: "properties",
37819
+ }
37820
+ );
37522
37821
 
37523
- // UI goodies
37524
- $('#ui-settings').click( e=> {
37525
- e.preventDefault();
37526
- if ($(e.target).is('a')){
37527
- shell.openExternal(e.target.href);
37528
- }
37529
- e.stopImmediatePropagation();
37530
- });
37531
-
37532
- $('#main-container').click((e)=> {
37533
- hide();
37534
- });
37535
- }
37822
+ // reset the listenere
37823
+ cmInstance.off("change");
37536
37824
 
37537
- }
37825
+ cmInstance.getDoc().setValue(contentBody);
37826
+ cmInstance.focus();
37827
+ //console.log(`lineCount: ${cmInstance.lineCount()}`)
37828
+ // Set the cursor at the end of existing content
37829
+ cmInstance.setCursor(cmInstance.lineCount(), 0);
37830
+ let codeMirrorHeight = 650; // totalHeightAvailable - 400;
37538
37831
 
37539
- function showEnvironments() {
37540
- show();
37541
- $('#ui-settings-envvars').click();
37542
- }
37832
+ cmInstance.setSize(null, codeMirrorHeight);
37833
+ // cmInstance.refresh();
37834
+ setTimeout(function () {
37835
+ cmInstance.refresh();
37836
+ }, 100);
37543
37837
 
37544
- function hide(){
37545
- if (visible){
37546
- $('#main-container').off('click');
37547
- RED.keyboard.remove('escape');
37548
- visible = false;
37549
- if (dialog !== null) {
37550
- dialog.slideUp(200, function () {
37551
- // searchInput.searchBox('value', '');
37552
- });
37553
- }
37838
+ cmInstance.on("change", function (cm, change) {
37839
+ // enable the save button
37840
+ $("#options-save").removeClass("disabled");
37841
+ });
37842
+
37843
+ return cmInstance;
37844
+ }
37845
+
37846
+ function show() {
37847
+ // Disable the search dialog if opened
37848
+ RED.actions.invoke("core:search:close");
37849
+ RED.actions.invoke("core:project-info:close");
37850
+ if (!visible) {
37851
+ RED.keyboard.add("*", "escape", () => hide());
37852
+
37853
+ createDialog();
37854
+ dialog.slideDown(300);
37855
+ visible = true;
37856
+
37857
+ // UI goodies
37858
+ $("#ui-settings").click((e) => {
37859
+ e.preventDefault();
37860
+ if ($(e.target).is("a")) {
37861
+ shell.openExternal(e.target.href);
37554
37862
  }
37555
- }
37863
+ e.stopImmediatePropagation();
37864
+ });
37556
37865
 
37557
- function resetWindows() {
37558
- getScreen().forEach(option => {
37559
- $(`#${option.id}-body`).hide();
37560
- $(`#${option.id}`).removeClass('ui-settings-option-selected');
37866
+ $("#main-container").click((e) => {
37867
+ hide();
37561
37868
  });
37562
37869
  }
37870
+ }
37563
37871
 
37564
- function getProxyHeader() {
37565
- // Read the proxy details
37566
- let proxyHeader = undefined;
37567
- let proxySettings = networkConfigStore.getProxyDetails();
37568
- let { custom, host, port, authentication, username, password } = proxySettings;
37569
- if (custom){
37570
- proxyHeader = `${host}:${port}`;
37571
- if (proxySettings.authentication){
37572
- proxyHeader = `${username}:${password}@${proxyHeader}`
37573
- }
37574
- proxyHeader = `http://${proxyHeader}`;
37575
- }
37872
+ function showEnvironments() {
37873
+ show();
37874
+ $("#ui-settings-envvars").click();
37875
+ }
37576
37876
 
37577
- return proxyHeader;
37877
+ function hide() {
37878
+ if (visible) {
37879
+ $("#main-container").off("click");
37880
+ RED.keyboard.remove("escape");
37881
+ visible = false;
37882
+ if (dialog !== null) {
37883
+ dialog.slideUp(200, function () {
37884
+ // searchInput.searchBox('value', '');
37885
+ });
37886
+ }
37578
37887
  }
37888
+ }
37579
37889
 
37580
- function init() {
37581
- RED.actions.add('core:settings:open', show);
37582
- RED.actions.add('core:settings:close', hide);
37583
- RED.actions.add('core:settings:select-environments', showEnvironments)
37890
+ function resetWindows() {
37891
+ getScreen().forEach((option) => {
37892
+ $(`#${option.id}-body`).hide();
37893
+ $(`#${option.id}`).removeClass("ui-settings-option-selected");
37894
+ });
37895
+ }
37896
+
37897
+ function getProxyHeader() {
37898
+ // Read the proxy details
37899
+ let proxyHeader = undefined;
37900
+ let proxySettings = networkConfigStore.getProxyDetails();
37901
+ let { custom, host, port, authentication, username, password } =
37902
+ proxySettings;
37903
+ if (custom) {
37904
+ proxyHeader = `${host}:${port}`;
37905
+ if (proxySettings.authentication) {
37906
+ proxyHeader = `${username}:${password}@${proxyHeader}`;
37907
+ }
37908
+ proxyHeader = `http://${proxyHeader}`;
37584
37909
  }
37585
37910
 
37911
+ return proxyHeader;
37912
+ }
37586
37913
 
37587
- return {
37588
- init: init,
37589
- show: show,
37590
- hide: hide,
37591
- getProxyHeader: getProxyHeader,
37592
- }
37593
- })();;RED.typeSearch = (function () {
37914
+ function init() {
37915
+ RED.actions.add("core:settings:open", show);
37916
+ RED.actions.add("core:settings:close", hide);
37917
+ RED.actions.add("core:settings:select-environments", showEnvironments);
37918
+ }
37919
+
37920
+ return {
37921
+ init: init,
37922
+ show: show,
37923
+ hide: hide,
37924
+ getProxyHeader: getProxyHeader,
37925
+ };
37926
+ })();
37927
+ ;RED.typeSearch = (function () {
37594
37928
  var shade;
37595
37929
 
37596
37930
  var disabled = false;