@kumologica/sdk 3.5.4 → 3.6.0-alpha7

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.
Files changed (36) hide show
  1. package/cli/cli.js +31 -8
  2. package/cli/commands/open.js +88 -15
  3. package/cli/commands/run.js +167 -0
  4. package/cli/commands/serve.js +139 -0
  5. package/package.json +5 -5
  6. package/src/app/main-process/main-window.js +1 -0
  7. package/src/app/main-process/modal-home.js +1 -0
  8. package/src/app/main-process/modal-newproject.js +1 -0
  9. package/src/app/main-process/modal-newtab.js +1 -0
  10. package/src/app/main-process/modal-nodelibrary.js +1 -0
  11. package/src/app/main-process/modal-renameTab.js +1 -0
  12. package/src/app/main-process/modal-welcome.js +1 -0
  13. package/src/app/main.js +179 -141
  14. package/src/app/preload.js +225 -139
  15. package/src/app/ui/editor-client/public/red/red.js +1943 -783
  16. package/src/app/ui/editor-client/public/red/red.min.js +2 -2
  17. package/src/app/ui/editor-client/public/red/style.min.css +1 -1
  18. package/src/app/ui/editor-client/public/vendor/ace-linters/javascript-service.js +10 -2
  19. package/src/app/ui/editor-client/src/js/red.js +183 -179
  20. package/src/app/ui/editor-client/src/js/ui/common/commandBox.js +107 -0
  21. package/src/app/ui/editor-client/src/js/ui/common/searchBox.js +91 -90
  22. package/src/app/ui/editor-client/src/js/ui/modules.js +164 -0
  23. package/src/app/ui/editor-client/src/js/ui/search.js +171 -123
  24. package/src/app/ui/editor-client/src/js/ui/sidebar.js +1 -1
  25. package/src/app/ui/editor-client/src/js/ui/ui-settings.js +419 -410
  26. package/src/app/ui/editor-client/src/sass/editor.scss +745 -746
  27. package/src/app/ui/editor-client/src/sass/forms.scss +1 -1
  28. package/src/app/ui/editor-client/src/sass/search.scss +16 -2
  29. package/src/app/ui/editor-client/src/sass/sidebar.scss +1 -1
  30. package/src/app/ui/editor-client/src/sass/style.scss +72 -69
  31. package/src/app/ui/editor-client/src/sass/ui/common/commandBox.scss +100 -0
  32. package/src/app/ui/editor-client/src/sass/ui/common/searchBox.scss +3 -2
  33. package/src/app/ui/editor-client/src/sass/ui-settings.scss +14 -14
  34. package/src/app/ui/editor-client/src/vendor/ace-linters/build/javascript-service.js +10 -2
  35. package/src/app/ui/editor-client/templates/index.mst +2 -2
  36. package/src/server/DesignerServer.js +152 -153
@@ -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
+ });
8682
+
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
+ */
8664
8746
 
8665
- this.resultCount = $('<span>',{class:"red-ui-searchBox-resultCount hide"}).appendTo(this.uiContainer);
8747
+ $.widget("kumologica.commandBox", {
8748
+ _create: function () {
8749
+ var that = this;
8666
8750
 
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
- });
8751
+ this.currentTimeout = null;
8752
+ this.lastSent = "";
8753
+ let command = this.options.command || "";
8676
8754
 
8677
- this.element.on("focus",function() {
8678
- $("body").one("mousedown",function() {
8679
- that.element.blur();
8680
- });
8681
- });
8755
+ this.element.val(command + " ");
8756
+ this.uiContainer = this.element.wrap("<div>").parent();
8757
+ this.uiContainer.addClass("red-ui-commandBox-container");
8682
8758
 
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");
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';
@@ -21208,7 +21320,7 @@ RED.view.tools = (function() {
21208
21320
  RED.sidebar.info.init();
21209
21321
  RED.sidebar.test.init();
21210
21322
  RED.sidebar.git.init();
21211
- //RED.sidebar.kumohub.init();
21323
+ RED.sidebar.kumohub.init();
21212
21324
  RED.sidebar.azure.init();
21213
21325
  RED.sidebar.awsDeploy.init();
21214
21326
 
@@ -26730,7 +26842,833 @@ RED.sidebar.azure = (function () {
26730
26842
  init: init,
26731
26843
  show: show,
26732
26844
  };
26733
- })();;RED.palette = (function () {
26845
+ })();;RED.sidebar.kumohub = (function () {
26846
+ marked.setOptions({
26847
+ renderer: new marked.Renderer(),
26848
+ gfm: true,
26849
+ tables: true,
26850
+ breaks: false,
26851
+ pedantic: false,
26852
+ sanitize: true,
26853
+ smartLists: true,
26854
+ smartypants: false,
26855
+ });
26856
+
26857
+ var content;
26858
+ var sections;
26859
+ var functionSection;
26860
+ var environmentSection;
26861
+ var initialised = false;
26862
+ var parameters;
26863
+ var SELECT_KUMOHUB_PROFILE = 'Select Kumohub profile...';
26864
+ var DEFINE_KUMOHUB_PROFILE = 'Define Kumohub profile';
26865
+ let workspaces; // workspaces from kumohub.io
26866
+ // store for workspace, storage, policy from profile before kumohub login
26867
+ let profileWorkspace;
26868
+ let profileStage;
26869
+ let profilePolicy;
26870
+
26871
+ const DEPLOYING = 'DEPLOYING';
26872
+ const NOTDEPLOYING = 'NOTDEPLOYING';
26873
+ let deployState = NOTDEPLOYING;
26874
+
26875
+ function initCss() {
26876
+ $('<style>')
26877
+ .text(
26878
+ `
26879
+ select {
26880
+ outline: 1.5px solid #ccc;
26881
+ }
26882
+ select:focus {
26883
+ outline: 1.5px solid #ccc;
26884
+ outline-offset: 0px;
26885
+ }
26886
+ .invalid {
26887
+ border: 1px solid red;
26888
+ }
26889
+
26890
+ .valid {
26891
+ border: 1px solid green;
26892
+ }
26893
+ datalist {
26894
+ max-height: 300px;
26895
+ overflow-y: auto !important;
26896
+ }
26897
+ .editor-button-xsmall {
26898
+ height: 16px;
26899
+ min-width: 16px;
26900
+ line-height: 14px;
26901
+ font-size: 10px;
26902
+ border-radius: 2px;
26903
+ padding: 0 2px;
26904
+ }
26905
+ `
26906
+ )
26907
+ .appendTo(document.head);
26908
+ }
26909
+
26910
+ function initHTML() {
26911
+ initCss();
26912
+ content = document.createElement('div');
26913
+ content.className = 'sidebar-kumohub';
26914
+
26915
+ RED.actions.add('core:show-kumohub-tab', show);
26916
+
26917
+ var stackContainer = $('<div>', {
26918
+ class: 'sidebar-node-info-stack',
26919
+ }).appendTo(content);
26920
+
26921
+ let headerContentHtml = `
26922
+ <div class="sidebar-title-wrapper">
26923
+ <span>Deploy: Kumohub</span>
26924
+ </div>
26925
+ <div id="kumohub-sidebar-header" class="sidebar-header">
26926
+ <div id="kumohub-instrumentation" class="node-info">
26927
+ <div id="kumohub-profiles-wrapper">
26928
+ <span style="padding-left: 3px">Profiles</span>
26929
+ <select id="kumohub-sidebar-profiles" class="palette-textinput" style="padding: 0px;">
26930
+ <option value="Select Kumohub profile..." style="color:#3988CB !important">Click to select one...</option>
26931
+ </select>
26932
+ </div>
26933
+
26934
+ <div id="kumohub-wrapper">
26935
+ <!-- connect btn -->
26936
+ <div>
26937
+ <a id="kumohub-sidebar-connect-btn" class="sidebar-header-button" href="#">
26938
+ <i id="kumohub-sidebar-connect-icon" class="fa fa-circle" style="color: red"></i>
26939
+ Connect
26940
+ </a>
26941
+ </div>
26942
+
26943
+ <!-- deploy btn -->
26944
+ <div style="margin-right: 4px;">
26945
+ <a id="kumohub-sidebar-deploy-btn" class="sidebar-header-button" href="#">
26946
+ <i id="kumohub-sidebar-deploy-icon" class="fa fa-cloud-upload"></i>
26947
+ Deploy
26948
+ </a>
26949
+ </div>
26950
+
26951
+ <!-- export btn -->
26952
+ <div id="kumohub-options-dropdown">
26953
+ <a id="kumohub-sidebar-export-btn" class="sidebar-header-button" href="#">
26954
+ <i class="fa fa-ellipsis-h"></i>
26955
+ </a>
26956
+ </div>
26957
+ <div id="kumohub-options-dropdown-content">
26958
+ <span id="kumohub-buildZipBtn" class="option">Export as Zip</span>
26959
+ <!--span id="kumohub-exportServerlessBtn" class="option">Serverless</span-->
26960
+ </div>
26961
+ </div>
26962
+ </div>
26963
+ <table hidden id="kumohub-sidebar-error" class="node-info" style="margin: 0px;">
26964
+ <tr>
26965
+ <td style="border: 0px solid white; padding: 3px; width: 100%;">
26966
+ <p style="font-size: 12px; margin: 0px; text-align: center; color:red;"><span>Kumohub profile has not been configured</span></p>
26967
+ </td>
26968
+
26969
+ <td style="border: 0px solid white; padding: 3px;">
26970
+ <a id="kumohub-sidebar-error-help-btn" class="editor-button editor-button-xsmall" href="https://docs.kumologica.com/docs/guide/GettingStarted.html#installation" target="_blank">
26971
+ <i class="fa fa-question"></i>
26972
+ </a>
26973
+ </td>
26974
+
26975
+ <td style="border: 0px solid white; padding: 3px 6px 3px 3px;">
26976
+ <a id="kumohub-sidebar-error-close-btn" class="editor-button editor-button-xsmall" href="#">
26977
+ <i class="fa fa-times"></i></a>
26978
+ </td>
26979
+ </tr>
26980
+ </table>
26981
+ </div>
26982
+ `;
26983
+
26984
+ $(headerContentHtml).appendTo(stackContainer);
26985
+
26986
+ let bodyContainer = $(`<div id="kumohub-sidebar-body" style="display:none"></div>`);
26987
+ bodyContainer.appendTo(stackContainer);
26988
+
26989
+ sections = RED.stack
26990
+ .create({
26991
+ container: bodyContainer,
26992
+ })
26993
+ .hide();
26994
+
26995
+ // function section
26996
+ functionSection = sections.add({
26997
+ title: 'function',
26998
+ collapsible: true,
26999
+ });
27000
+ functionSection.expand();
27001
+
27002
+ // environment section
27003
+ environmentSection = sections.add({
27004
+ title: 'environment',
27005
+ collapsible: true,
27006
+ });
27007
+ //environmentSection.expand();
27008
+
27009
+ RED.sidebar.addTab({
27010
+ id: 'kumohub',
27011
+ label: 'Kumohub',
27012
+ name: 'Kumohub Deployer',
27013
+ iconClass: 'fa fa-cloud',
27014
+ action: 'core:show-kumohub-tab',
27015
+ content: content,
27016
+ pinned: true,
27017
+ enableOnEdit: true,
27018
+ onchange: onchange,
27019
+ onsame: onsame
27020
+ });
27021
+
27022
+ // Function content init
27023
+ let functionSectionHtml = `
27024
+ <table class="node-info">
27025
+ <tr class="node-info-node-row">
27026
+ <td>Service Name</td>
27027
+ <td colspan="2" style="background: white"><input style="width:100%" id="kumohub-fn-name" class="palette-textinput" pattern="[a-zA-Z0-9-_]{1,64}" type="text"></td>
27028
+ </tr>
27029
+ <tr class="node-info-node-row">
27030
+ <td>Description</td>
27031
+ <td colspan="2" style="background: white"><input style="width:100%" id="kumohub-fn-description" class="palette-textinput" type="text"></td>
27032
+ </tr>
27033
+ <tr class="node-info-node-row">
27034
+ <td>Memory (MB)</td>
27035
+ <td colspan="2" style="background: white"><input id="kumohub-fn-memory" class="palette-textinput" type="number" min="128" max="1536"></td>
27036
+ </tr>
27037
+ <tr class="node-info-node-row">
27038
+ <td>Timeout (s)</td>
27039
+ <td colspan="2" style="background: white"><input id="kumohub-fn-timeout" class="palette-textinput" type="number" min="5" max="900"></td>
27040
+ </tr>
27041
+ <tr class="node-info-node-row">
27042
+ <td>Workspace</td>
27043
+ <td colspan="2" style="background: white">
27044
+ <select type="text" class="palette-textinput" id="kumohub-fn-workspace" style="float: left; width: 100%; padding: 0px; outline: 0px solid #ccc; ">
27045
+ <option value="UNDEFINED" selected="true">Undefined</option>
27046
+ </select>
27047
+ </td>
27048
+ </tr>
27049
+
27050
+ <tr class="node-info-node-row">
27051
+ <td>Stage</td>
27052
+ <td colspan="2" style="background: white">
27053
+ <select type="text" class="palette-textinput" id="kumohub-fn-stage" style="float: left; width: 100%; padding: 0px; outline: 0px solid #ccc; ">
27054
+ <option value="UNDEFINED" selected="true">Undefined</option>
27055
+ </select>
27056
+ </td>
27057
+ </tr>
27058
+
27059
+ <tr class="node-info-node-row">
27060
+ <td>Policy</td>
27061
+ <td colspan="2" style="background: white">
27062
+ <select type="text" class="palette-textinput" id="kumohub-fn-policy" style="float: left; width: 100%; padding: 0px; outline: 0px solid #ccc; ">
27063
+ <option value="Public" selected="true">Public</option>
27064
+ </select>
27065
+ </td>
27066
+ </tr>
27067
+ </table>
27068
+ `;
27069
+ $(functionSectionHtml).appendTo(functionSection.content);
27070
+ functionSection.container.show();
27071
+
27072
+ // Environment section init
27073
+ let environmentSectionHtml = `
27074
+ <div style="display:flex; flex-direction: column; justify-content: flex-start;">
27075
+ <div style="display:flex; justify-content: flex-end; padding:6px">
27076
+ <a id="kumohub-add-environment-variable" href="#" class="editor-button editor-button-small red-ui-editableList-addButton">
27077
+ <i class="fa fa-plus"></i> Add
27078
+ </a>
27079
+ </div>
27080
+ <div id="kumohub-fn-env" style="display:flex; flex-direction: column">
27081
+ <table id="kumohub-fn-env-table" class="node-info" style="table-layout: fixed">
27082
+
27083
+ </table>
27084
+ </div>
27085
+ </div>
27086
+ `;
27087
+ $(environmentSectionHtml).appendTo(environmentSection.content);
27088
+ environmentSection.container.show();
27089
+
27090
+ // Tooltips
27091
+ RED.popover.tooltip($('#kumohub-sidebar-deploy-btn'), 'Deploy to Kumohub');
27092
+ RED.popover.tooltip($('#kumohub-options-dropdown'), 'Other Kumohub Operations');
27093
+ RED.popover.tooltip($('#kumohub-sidebar-connect-btn'), 'Connect to Kumohub');
27094
+ }
27095
+
27096
+ function onchange(){
27097
+ RED.actions.invoke('core:show-sidebar');
27098
+ }
27099
+
27100
+ function onsame(){
27101
+ RED.actions.invoke('core:hide-sidebar');
27102
+ }
27103
+
27104
+ function sanitizeLambdaName(name) {
27105
+ return name
27106
+ .replace('.json', '')
27107
+ .trim()
27108
+ .replace(/^@/, '')
27109
+ .replace(/[^a-zA-Z0-9-_]/g, '_')
27110
+ .substr(0, 140);
27111
+ }
27112
+
27113
+ function setLambdaName(name) {
27114
+ $('#kumohub-fn-name').val(sanitizeLambdaName(name));
27115
+ }
27116
+
27117
+ function setValues(params) {
27118
+ // storing for setting it up after login to kumohub
27119
+ profileWorkspace = params.workspace || params.account;
27120
+ profileStage = params.stage;
27121
+ profilePolicy = params.policy;
27122
+ console.log(`profile stored: ${profileWorkspace} - ${profileStage} - ${profilePolicy}`);
27123
+
27124
+ if (!initialised) {
27125
+ parameters = params;
27126
+ return;
27127
+ }
27128
+
27129
+ if (params && (params.name || params.functionName)) {
27130
+ setLambdaName(params.name || params.functionName || params["service-name"]);
27131
+ } else {
27132
+ if (window.__kumologica.settings.projectFlowName) {
27133
+ setLambdaName(window.__kumologica.settings.projectFlowName);
27134
+ }
27135
+ }
27136
+ if (!params) {
27137
+ return;
27138
+ }
27139
+ if (params.profile) {
27140
+ setProfile(params.profile);
27141
+ }
27142
+ if (params.description) {
27143
+ $('#kumohub-fn-description').val(params.description);
27144
+ }
27145
+ if (params.memory) {
27146
+ $('#kumohub-fn-memory').val(params.memory);
27147
+ }
27148
+ if (params.timeout) {
27149
+ $('#kumohub-fn-timeout').val(params.timeout);
27150
+ }
27151
+ if (params.account) {
27152
+ $('#kumohub-fn-workspace').val(params.workspace || params.account);
27153
+ fillStages(params.workspace || params.account);
27154
+ }
27155
+ if (params.workspace) {
27156
+ $('#kumohub-fn-workspace').val(params.workspace);
27157
+ fillStages(params.workspace);
27158
+ }
27159
+
27160
+ if (params.stage) {
27161
+ $('#kumohub-fn-stage').val(params.stage);
27162
+ }
27163
+ if (params.policy) {
27164
+ $('#kumohub-fn-policy').val(params.policy);
27165
+ }
27166
+
27167
+ if (params.environment && params.environment.length > 0) {
27168
+ let environmentTable = $('#kumohub-fn-env-table');
27169
+
27170
+ params.environment.forEach(function (e, i) {
27171
+ $(`
27172
+ <tr class="node-info-node-row">
27173
+ <td style="background: white; width:46%"><input id="kumohub-fn-env-key" class="palette-textinput" type="text" placeholder="key" style="width:100%" value="${e.key}"></td>
27174
+ <td style="background: white; width:46%"><input id="kumohub-fn-env-val" class="palette-textinput" type="text" placeholder="value" style="width:100%" value="${e.value}"></td>
27175
+ <td id="kumohub-fn-env-row" style="text-align:center; width:8%" class="removeRow"><i class="fa fa-minus"></i></td>
27176
+ </tr>`).appendTo(environmentTable);
27177
+ });
27178
+ }
27179
+ }
27180
+
27181
+ function getValues() {
27182
+ // Basic information
27183
+ let fnProfile = getProfile();
27184
+ let fnName = $('#kumohub-fn-name').val();
27185
+ let fnDescription = $('#kumohub-fn-description').val();
27186
+ let fnMemory = $('#kumohub-fn-memory').val();
27187
+ let fnTimeout = $('#kumohub-fn-timeout').val();
27188
+ let fnStage = $('#kumohub-fn-stage').val();
27189
+ let fnAccount = $('#kumohub-fn-account').val();
27190
+ let fnWorkspace = $('#kumohub-fn-workspace').val();
27191
+ let fnPolicy = $('#kumohub-fn-policy').val();
27192
+
27193
+ // Environment variables
27194
+ let environment = [];
27195
+ let envvarRows = $('#kumohub-fn-env-table tr');
27196
+
27197
+ envvarRows.map((index, row) => {
27198
+ let envvar = $(row).find('td').find('input');
27199
+ let key = $(envvar[0]).val();
27200
+ let value = $(envvar[1]).val();
27201
+ environment.push({ key, value });
27202
+ });
27203
+
27204
+ return {
27205
+ profile: fnProfile,
27206
+ "service-name": fnName,
27207
+ description: fnDescription,
27208
+ memory: fnMemory,
27209
+ timeout: fnTimeout,
27210
+ workspace: fnWorkspace || fnAccount,
27211
+ stage: fnStage,
27212
+ environment: environment,
27213
+ policy: fnPolicy
27214
+ };
27215
+ }
27216
+
27217
+ function fillWorkspaces() {
27218
+ let dropdown = $('#kumohub-fn-workspace');
27219
+
27220
+ if (workspaces.length > 0) {
27221
+ dropdown.empty();
27222
+ }
27223
+ workspaces.forEach(function (w) {
27224
+ dropdown.append($('<option></option>').val(w.name).text(w.name));
27225
+ });
27226
+
27227
+ if (profileWorkspace) {
27228
+ $('#kumohub-fn-workspace').val(profileWorkspace);
27229
+ fillStages(profileWorkspace);
27230
+ }
27231
+ }
27232
+
27233
+ function fillStages(fnWorkspace) {
27234
+
27235
+ let dropdown = $('#kumohub-fn-stage');
27236
+ if (fnWorkspace == "UNDEFINED") {
27237
+ //dropdown.append($('<option></option>').val("UNDEFINED").text("Undefined"));
27238
+ return;
27239
+ }
27240
+ let ws;
27241
+
27242
+ if (workspaces) {
27243
+ ws = workspaces.find(w => w.name === fnWorkspace);
27244
+ }
27245
+
27246
+ if (ws) {
27247
+ dropdown.empty();
27248
+ if (ws.stages && ws.stages.length > 0) {
27249
+ ws.stages.forEach(function (s) {
27250
+ dropdown.append($('<option></option>').val(s.name).text(s.name));
27251
+ });
27252
+ if (profileStage) {
27253
+ $('#kumohub-fn-stage').val(profileStage);
27254
+ fillPolicies(fnWorkspace, profileStage);
27255
+ }
27256
+ } else {
27257
+ dropdown.append($('<option></option>').val("UNDEFINED").text("Undefined"));
27258
+ }
27259
+
27260
+ }
27261
+ }
27262
+
27263
+ function fillPolicies(workspace, stage) {
27264
+
27265
+ let dropdown = $('#kumohub-fn-policy');
27266
+ if (workspace == "UNDEFINED") {
27267
+ //dropdown.append($('<option></option>').val("UNDEFINED").text("Undefined"));
27268
+ return;
27269
+ }
27270
+ let ws;
27271
+
27272
+ if (workspaces) {
27273
+ ws = workspaces.find(w => w.name === workspace);
27274
+ }
27275
+
27276
+ if (ws) {
27277
+ let st = ws.stages.find(s => s.name === stage);
27278
+ if (st && st.policies) {
27279
+ dropdown.empty();
27280
+
27281
+ if (st.policies && st.policies.length > 0) {
27282
+ st.policies.forEach(function (p) {
27283
+ dropdown.append($('<option></option>').val(p.name).text(p.name));
27284
+ });
27285
+ if (profilePolicy) {
27286
+ $('#kumohub-fn-policy').val(profilePolicy);
27287
+ }
27288
+ } else {
27289
+ dropdown.append($('<option></option>').val("Public").text("Public"));
27290
+ }
27291
+ }
27292
+ }
27293
+ }
27294
+
27295
+ function fillProfiles() {
27296
+ try {
27297
+ const profiles = window.__kumologica.kumohub.listProfiles();
27298
+ let dropdown = $('#kumohub-sidebar-profiles');
27299
+
27300
+ if (profiles.length > 0) {
27301
+ dropdown.empty();
27302
+ dropdown.append($('<option disabled>Available Kumohub Profiles</option>'));
27303
+ }
27304
+ profiles.forEach(function (profile) {
27305
+ dropdown.append($('<option></option>').val(profile).text(profile));
27306
+ });
27307
+
27308
+ // in case kumohub-config.json was loaded already and
27309
+ // setValues could not select correct profile, doing it now
27310
+ if (window.__kumologica.kumohub.profile) {
27311
+ setProfile(window.__kumologica.kumohub.profile);
27312
+ }
27313
+ } catch (Error) {
27314
+ console.log(`error: ${Error}`);
27315
+ showProfileError();
27316
+ }
27317
+ }
27318
+
27319
+ function getProfile() {
27320
+ return $('#kumohub-sidebar-profiles').find(':selected').val();
27321
+ }
27322
+
27323
+ function setProfile(profile) {
27324
+ window.__kumologica.kumohub.profile = profile;
27325
+
27326
+ // Show the body if profile is set to existing profile
27327
+ if (profile != SELECT_KUMOHUB_PROFILE &&
27328
+ $('#kumohub-sidebar-profiles').find('option[value=' + profile + ']').length) {
27329
+
27330
+ $(`#kumohub-sidebar-profiles option[value='${SELECT_KUMOHUB_PROFILE}']`).remove();
27331
+ $('#kumohub-sidebar-profiles').val(profile);
27332
+ } else {
27333
+ $('#kumohub-sidebar-profiles').val(SELECT_KUMOHUB_PROFILE);
27334
+ }
27335
+ }
27336
+
27337
+
27338
+ function showProfileError() {
27339
+ $('#kumohub-sidebar-error').show();
27340
+ }
27341
+
27342
+ RED.events.on('settings:cloud-config-changed', function() {
27343
+ fillProfiles();
27344
+ });
27345
+
27346
+ // event triggered when kumohub-config.json file has been loaded
27347
+ RED.events.on('kumohub-config', function () {
27348
+ if (!$('#kumohub-fn-name').val() &&
27349
+ window.__kumologica.settings.projectFlowName
27350
+ ) {
27351
+ setLambdaName(window.__kumologica.settings.projectFlowName);
27352
+ }
27353
+
27354
+ if (window.__kumologica.settings.kumohubConfig ) {
27355
+ const params = window.__kumologica.settings.kumohubConfig.getKumohubConfig();
27356
+
27357
+ setValues(params);
27358
+
27359
+ } else {
27360
+ console.log('kumologica.settings.kumohubConfig not present');
27361
+ }
27362
+ });
27363
+
27364
+ function initJs() {
27365
+ fillProfiles();
27366
+
27367
+ // Initialize fields with default values
27368
+ if (window.__kumologica.settings.projectFlowName) {
27369
+ setLambdaName(window.__kumologica.settings.projectFlowName);
27370
+ }
27371
+
27372
+ $('#kumohub-fn-description').val('kumologica flow');
27373
+ $('#kumohub-fn-memory').val('512');
27374
+ $('#kumohub-fn-timeout').val('20');
27375
+
27376
+ $('#kumohub-fn-timeout, #kumohub-fn-workspace, #kumohub-fn-stage, #kumohub-fn-policy, #kumohub-fn-memory, #kumohub-fn-description, #kumohub-fn-name').change(function () {
27377
+ saveSettings();
27378
+ });
27379
+
27380
+ $('#kumohub-fn-name').change(function () {
27381
+ this.value = sanitizeLambdaName(this.value);
27382
+ });
27383
+
27384
+ $('#kumohub-fn-workspace').on('change', function() {
27385
+ fillStages( this.value );
27386
+ });
27387
+
27388
+ $('#kumohub-fn-stage').on('change', function() {
27389
+ fillPolicies($('#kumohub-fn-workspace').val(), this.value);
27390
+ });
27391
+
27392
+ $('#kumohub-sidebar-profiles').change(function () {
27393
+
27394
+ if (this.value) {
27395
+ $('#kumohub-sidebar-body').show();
27396
+ }
27397
+ saveSettings();
27398
+
27399
+ if (this.value != SELECT_KUMOHUB_PROFILE) {
27400
+ $(`#kumohub-sidebar-profiles option[value='${SELECT_KUMOHUB_PROFILE}']`).remove();
27401
+ window.__kumologica.kumohub.profile = this.value;
27402
+ disconnectFromKumohub();
27403
+ }
27404
+ });
27405
+
27406
+ // Attach the environment variables
27407
+ $('#kumohub-add-environment-variable').click((e) => {
27408
+ let environmentTable = $('#kumohub-fn-env-table');
27409
+ let environmentRowHtml = `
27410
+ <tr class="node-info-node-row">
27411
+ <td style="background: white; width:46%"><input id="kumohub-fn-env-key" class="palette-textinput" type="text" placeholder="key" style="width:100%"></td>
27412
+ <td style="background: white; width:46%"><input id="kumohub-fn-env-val" class="palette-textinput" type="text" placeholder="value" style="width:100%"></td>
27413
+ <td id="kumohub-fn-env-row" style="text-align:center; width:8%" class="removeRow"><i class="fa fa-minus"></i></td>
27414
+ </tr>`;
27415
+ $(environmentRowHtml).appendTo(environmentTable);
27416
+
27417
+ $('#kumohub-fn-env-table')
27418
+ .find('input')
27419
+ .each(function () {
27420
+ $(this).change(function () {
27421
+ saveSettings();
27422
+ });
27423
+ });
27424
+ });
27425
+
27426
+ $('#kumohub-fn-env-table')
27427
+ .find('input')
27428
+ .each(function () {
27429
+ $(this).change(function () {
27430
+ saveSettings();
27431
+ });
27432
+ });
27433
+
27434
+ $('#kumohub-fn-env-table').on('click', '.removeRow', function () {
27435
+ $(this).parent().remove();
27436
+ saveSettings();
27437
+ });
27438
+
27439
+ // Close export menu when click in the window
27440
+ $('.sidebar-kumohub').click(function (e) {
27441
+ $('#kumohub-options-dropdown-content').hide();
27442
+ });
27443
+
27444
+ // Connect to AWS button
27445
+ $('#kumohub-sidebar-connect-btn').click((e) => {
27446
+ e.preventDefault();
27447
+ connectToKumohub();
27448
+ });
27449
+
27450
+ // Deploy to kumohub button
27451
+ $('#kumohub-sidebar-deploy-btn').click((e) => {
27452
+ e.preventDefault();
27453
+ deploy();
27454
+ });
27455
+
27456
+ $('#kumohub-buildZipBtn').click((e) => {
27457
+ e.preventDefault();
27458
+ hideMenu();
27459
+ buildZip();
27460
+ });
27461
+
27462
+ // Export cloudformation script
27463
+ $('#kumohub-exportCloudFormationBtn').click((e) => {
27464
+ e.preventDefault();
27465
+ hideMenu();
27466
+ exportScript(window.__kumologica.cloud.provider.aws);
27467
+ });
27468
+
27469
+ // Export serverless script
27470
+ $('#kumohub-exportServerlessBtn').click((e) => {
27471
+ e.preventDefault();
27472
+ hideMenu();
27473
+ exportScript(window.__kumologica.cloud.provider.serverless);
27474
+ });
27475
+
27476
+ $('#kumohub-options-dropdown').click((e) => {
27477
+ e.stopPropagation();
27478
+
27479
+ $('#kumohub-sidebar-export-btn').toggleClass('dropdown-selected');
27480
+
27481
+ $('#kumohub-options-dropdown-content').toggle();
27482
+ });
27483
+
27484
+ initialised = true;
27485
+ if (parameters) {
27486
+ setValues(parameters);
27487
+ }
27488
+
27489
+ connectUIDisconnected();
27490
+ }
27491
+
27492
+ function hideMenu() {
27493
+ $('#kumohub-sidebar-export-btn').removeClass('dropdown-selected');
27494
+ $('#kumohub-options-dropdown-content').hide();
27495
+ }
27496
+
27497
+ async function exportScript(provider) {
27498
+
27499
+ $('#workspace-terminal').show();
27500
+ try {
27501
+ await window.__kumologica.cloud.generateScript(
27502
+ provider,
27503
+ RED.header.getCurrentProjectInfo(),
27504
+ getValues()
27505
+ );
27506
+ } catch (Error) {
27507
+ handleError(Error);
27508
+ }
27509
+ }
27510
+
27511
+ async function buildZip(provider) {
27512
+
27513
+ $('#workspace-terminal').show();
27514
+ try {
27515
+ await window.__kumologica.kumohub.build(RED.header.getCurrentProjectInfo());
27516
+ /*await window.__kumologica.cloud.generateScript(
27517
+ provider,
27518
+ RED.header.getCurrentProjectInfo(),
27519
+ getValues()
27520
+ );*/
27521
+ } catch (Error) {
27522
+ handleError(Error);
27523
+ }
27524
+ }
27525
+
27526
+ async function connectToKumohub() {
27527
+ profile = getProfile();
27528
+
27529
+ if (!profile || profile == SELECT_KUMOHUB_PROFILE) {
27530
+ RED.notify(`<strong>Error</strong>: Please select Kumohub profile before connecting to Kumohub account.`, 'error');
27531
+ return;
27532
+ }
27533
+
27534
+ if (window.__kumologica.kumohub.isLoggedIn(profile)) {
27535
+ RED.notify(`<strong>Information</strong>: Already connected to ${profile} Kumohub account.`, 'info');
27536
+ return;
27537
+ }
27538
+
27539
+ connectUIConnecting();
27540
+
27541
+ try {
27542
+ await window.__kumologica.kumohub.login(profile);
27543
+ workspaces = await window.__kumologica.kumohub.getWorkspaces(profile);
27544
+
27545
+ fillWorkspaces(profileWorkspace);
27546
+ } catch (err) {
27547
+ connectUIDisconnected();
27548
+
27549
+ RED.notify(`<strong>Error</strong>: ${err.stderr? err.stderr: err}`, 'error');
27550
+ return;
27551
+ }
27552
+ connectUIConnected();
27553
+ }
27554
+
27555
+ function disconnectFromKumohub() {
27556
+ window.__kumologica.kumohub.logout();
27557
+ connectUIDisconnected();
27558
+ }
27559
+
27560
+ function connectUIDisconnected() {
27561
+ // show connect button
27562
+ $('#kumohub-sidebar-connect-btn').show();
27563
+ if ($('#kumohub-sidebar-connect-btn') && $('#kumohub-sidebar-connect-btn').html()) {
27564
+ $('#kumohub-sidebar-connect-btn').html($('#kumohub-sidebar-connect-btn').html().replace('Connecting', 'Connect'));
27565
+ }
27566
+ $('#kumohub-sidebar-connect-icon').attr({'class': 'fa fa-circle'});
27567
+ $('#kumohub-sidebar-connect-icon').css({'color': 'red'});
27568
+ // hide deploy and export buttons
27569
+ $('#kumohub-sidebar-deploy-btn').hide();
27570
+ $('#kumohub-sidebar-export-btn').hide();
27571
+ $('#kumohub-sidebar-body').hide();
27572
+ }
27573
+
27574
+ function connectUIConnecting() {
27575
+ $('#kumohub-sidebar-connect-icon').attr({'class': 'fa fa-spinner fa-spin'});
27576
+ $('#kumohub-sidebar-connect-icon').css({'color': 'black'});
27577
+ }
27578
+
27579
+ function connectUIConnected() {
27580
+ // hide connect button
27581
+ $('#kumohub-sidebar-connect-btn').hide();
27582
+ //$('#kumohub-sidebar-connect-btn').html($('#kumohub-sidebar-connect-btn').html().replace('Connect', 'Connected'));
27583
+ //$('#kumohub-sidebar-connect-icon').attr({'class': 'fa fa-circle'});
27584
+ //$('#kumohub-sidebar-connect-icon').css({'color': 'green'});
27585
+
27586
+ // show deploy and options buttons
27587
+ $('#kumohub-sidebar-deploy-btn').show();
27588
+
27589
+ // dont show until functionality implemented
27590
+ $('#kumohub-sidebar-export-btn').show();
27591
+ $('#kumohub-sidebar-body').show();
27592
+ }
27593
+
27594
+ function deployingUIDeploying() {
27595
+ $('#kumohub-sidebar-deploy-icon').attr({'class': 'fa fa-spinner fa-spin'});
27596
+ }
27597
+ function deployingUINotDeploying() {
27598
+ $('#kumohub-sidebar-deploy-icon').attr({'class': 'fa fa-cloud-upload'});
27599
+ }
27600
+
27601
+ async function deploy() {
27602
+
27603
+ const profile = getProfile();
27604
+ if (!profile || profile == SELECT_KUMOHUB_PROFILE) {
27605
+ RED.notify(`Please select kumohub profile before deploying flows.`, 'error');
27606
+ return;
27607
+ }
27608
+
27609
+ if (deployState == DEPLOYING) {
27610
+ RED.notify(`<strong>Information</strong>: Already deploying to Kumohub.`, 'info');
27611
+ return;
27612
+ }
27613
+
27614
+ RED.deploy.save();
27615
+
27616
+ deployingUIDeploying();
27617
+ deployState = DEPLOYING;
27618
+
27619
+ $('#workspace-terminal').show();
27620
+
27621
+ let params = getValues();
27622
+
27623
+ let envs = params.environment;
27624
+
27625
+ if (envs) {
27626
+ let variables = {Variables: {}};
27627
+
27628
+ envs.forEach(function(e) {
27629
+ variables.Variables[e.key] = e.value;
27630
+ });
27631
+ params.environment = {};
27632
+ params.environment = JSON.stringify(variables);
27633
+ };
27634
+
27635
+ try {
27636
+ await window.__kumologica.kumohub.deploy(
27637
+ RED.header.getCurrentProjectInfo(),
27638
+ params
27639
+ );
27640
+
27641
+ } catch (Error) {
27642
+ handleError(Error);
27643
+ }
27644
+
27645
+ deployState = NOTDEPLOYING;
27646
+ deployingUINotDeploying();
27647
+ }
27648
+
27649
+ function handleError(error) {
27650
+ let msg = error.toString();
27651
+ RED.notify(msg, 'error');
27652
+ }
27653
+
27654
+ function saveSettings() {
27655
+ window.__kumologica.settings.kumohubConfig.setKumohubConfig(getValues());
27656
+ }
27657
+
27658
+ function show() {
27659
+ RED.sidebar.show('kumohub');
27660
+ }
27661
+
27662
+ function init() {
27663
+ initHTML();
27664
+ initJs();
27665
+ }
27666
+
27667
+ return {
27668
+ init: init,
27669
+ show: show,
27670
+ };
27671
+ })();;RED.palette = (function () {
26734
27672
  const options = {
26735
27673
  nodes: {
26736
27674
  header: 'palette-option-nodes-a',
@@ -35550,15 +36488,15 @@ RED.notifications = (function() {
35550
36488
  var results = [];
35551
36489
 
35552
36490
  function indexProperty(node, label, property) {
35553
- if (typeof property === 'string' || typeof property === 'number') {
35554
- property = ('' + property).toLowerCase();
36491
+ if (typeof property === "string" || typeof property === "number") {
36492
+ property = ("" + property).toLowerCase();
35555
36493
  index[property] = index[property] || {};
35556
36494
  index[property][node.id] = { node: node, label: label };
35557
36495
  } else if (Array.isArray(property)) {
35558
36496
  property.forEach(function (prop) {
35559
36497
  indexProperty(node, label, prop);
35560
36498
  });
35561
- } else if (typeof property === 'object') {
36499
+ } else if (typeof property === "object") {
35562
36500
  for (var prop in property) {
35563
36501
  if (property.hasOwnProperty(prop)) {
35564
36502
  indexProperty(node, label, property[prop]);
@@ -35569,13 +36507,13 @@ RED.notifications = (function() {
35569
36507
  function indexNode(n) {
35570
36508
  var l = RED.utils.getNodeLabel(n);
35571
36509
  if (l) {
35572
- l = ('' + l).toLowerCase();
36510
+ l = ("" + l).toLowerCase();
35573
36511
  index[l] = index[l] || {};
35574
36512
  index[l][n.id] = { node: n, label: l };
35575
36513
  }
35576
- l = l || n.label || n.name || n.id || '';
36514
+ l = l || n.label || n.name || n.id || "";
35577
36515
 
35578
- var properties = ['id', 'type', 'name', 'label', 'info'];
36516
+ var properties = ["id", "type", "name", "label", "info"];
35579
36517
  if (n._def && n._def.defaults) {
35580
36518
  properties = properties.concat(Object.keys(n._def.defaults));
35581
36519
  }
@@ -35603,14 +36541,14 @@ RED.notifications = (function() {
35603
36541
 
35604
36542
  /**
35605
36543
  * User search when typing it the search box...
35606
- * @param {string} val
36544
+ * @param {string} val
35607
36545
  */
35608
36546
  function search(val) {
35609
- searchResults.editableList('empty');
36547
+ searchResults.editableList("empty");
35610
36548
  var typeFilter;
35611
36549
  var m = /(?:^| )type:([^ ]+)/.exec(val);
35612
36550
  if (m) {
35613
- val = val.replace(/(?:^| )type:[^ ]+/, '');
36551
+ val = val.replace(/(?:^| )type:[^ ]+/, "");
35614
36552
  typeFilter = m[1];
35615
36553
  }
35616
36554
 
@@ -35622,27 +36560,25 @@ RED.notifications = (function() {
35622
36560
  // Excluding tabs
35623
36561
  // results = results.filter((r) => r.node.type !== 'tab');
35624
36562
  for (i = 0; i < Math.min(results.length, 25); i++) {
35625
- searchResults.editableList('addItem', results[i]);
36563
+ searchResults.editableList("addItem", results[i]);
35626
36564
  }
35627
36565
  } else {
35628
- searchResults.editableList('addItem', {});
36566
+ searchResults.editableList("addItem", {});
35629
36567
  }
35630
36568
  } else {
35631
36569
  let commands = searchCommands();
35632
- commands.forEach(c => {
35633
- searchResults.editableList('addItem', c);
36570
+ commands.forEach((c) => {
36571
+ searchResults.editableList("addItem", c);
35634
36572
  });
35635
36573
 
35636
- let results = $('#search-result-list');
36574
+ let results = $("#search-result-list");
35637
36575
  $('<div class="searchSeparator"></div>').appendTo(results);
35638
36576
 
35639
-
35640
36577
  let allNodes = searchNodes();
35641
36578
 
35642
- allNodes.forEach(n => {
35643
- searchResults.editableList('addItem', n);
35644
- })
35645
-
36579
+ allNodes.forEach((n) => {
36580
+ searchResults.editableList("addItem", n);
36581
+ });
35646
36582
  }
35647
36583
  }
35648
36584
 
@@ -35681,56 +36617,89 @@ RED.notifications = (function() {
35681
36617
  results.push(nodes[list[i]]);
35682
36618
  }
35683
36619
  } else {
35684
- let setResults = new Set()
36620
+ let setResults = new Set();
35685
36621
  for (const i in index) {
35686
- index[i].forEach(n => {
36622
+ index[i].forEach((n) => {
35687
36623
  if (setResults.has(n.node.id)) return;
35688
36624
  else {
35689
36625
  setResults.add(n.node.id);
35690
- if (n.node.type === 'tab') {
36626
+ if (n.node.type === "tab") {
35691
36627
  results.push({ label: n.node.label, node: n.node });
35692
36628
  } else {
35693
36629
  results.push({ label: n.node.name, node: n.node });
35694
36630
  }
35695
36631
  }
35696
- })
36632
+ });
35697
36633
  }
35698
-
35699
36634
  }
35700
36635
  return results;
35701
-
35702
36636
  }
35703
36637
  /**
35704
36638
  * Returns a list of commands that will be added to the search window when it is opened
35705
36639
  */
35706
36640
  function searchCommands() {
35707
-
35708
36641
  return [
35709
- { type: 'command', title: 'Open Settings', action: 'core:settings:open', shortcut: `${CtrlOrCmd()} /` },
35710
- { type: 'command', title: 'Show Project Info', action: 'core:project-info' },
35711
36642
  {
35712
- type: 'command', title: 'Run Test...', cb: () => {
35713
- if (!$('.sidebar-test').is(':visible')) {
35714
- $('#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();
35715
36659
  }
35716
36660
 
35717
- $('#test-sidebar-run-btn').click();
35718
- }
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`,
36671
+ },
36672
+ {
36673
+ type: "command",
36674
+ title: "Import Flow",
36675
+ action: "core:show-import-dialog",
36676
+ shortcut: `${CtrlOrCmd()} I`,
35719
36677
  },
35720
36678
  {
35721
- type: 'command', title: 'Open Log Viewer', cb: () => {
35722
- $('#workspace-terminal').toggle()
35723
- }, shortcut: `${CtrlOrCmd()} T`
36679
+ type: "command",
36680
+ title: "Export Flow",
36681
+ action: "core:show-export-dialog",
36682
+ shortcut: `${CtrlOrCmd()} E`,
35724
36683
  },
35725
- { type: 'command', title: 'Import Flow', action: 'core:show-import-dialog', shortcut: `${CtrlOrCmd()} I` },
35726
- { type: 'command', title: 'Export Flow', action: 'core:show-export-dialog', shortcut: `${CtrlOrCmd()} E` },
35727
36684
  // { type: 'command', title: 'SignIn to Kumologica.dev', action: 'core:signup:show' },
35728
36685
  {
35729
- type: 'command', title: 'Help: Documentation', cb: () => {
35730
- window.__kumologica.electron.shell.openExternal('https://docs.kumologica.com/docs/guide/Intro.html');
35731
- }
35732
- }
35733
- ]
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
+ ];
35734
36703
  }
35735
36704
 
35736
36705
  function CtrlOrCmd() {
@@ -35738,7 +36707,7 @@ RED.notifications = (function() {
35738
36707
  }
35739
36708
 
35740
36709
  function ensureSelectedIsVisible() {
35741
- var selectedEntry = searchResults.find('li.selected');
36710
+ var selectedEntry = searchResults.find("li.selected");
35742
36711
  if (selectedEntry.length === 1) {
35743
36712
  var scrollWindow = searchResults.parent();
35744
36713
  var scrollHeight = scrollWindow.height();
@@ -35747,21 +36716,31 @@ RED.notifications = (function() {
35747
36716
  var h = selectedEntry.height();
35748
36717
  if (y + h > scrollHeight) {
35749
36718
  scrollWindow.animate(
35750
- { scrollTop: '-=' + (scrollHeight - (y + h) - 10) },
36719
+ { scrollTop: "-=" + (scrollHeight - (y + h) - 10) },
35751
36720
  50
35752
36721
  );
35753
36722
  } else if (y < 0) {
35754
- scrollWindow.animate({ scrollTop: '+=' + (y - 10) }, 50);
36723
+ scrollWindow.animate({ scrollTop: "+=" + (y - 10) }, 50);
35755
36724
  }
35756
36725
  }
35757
36726
  }
35758
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
+ }
35759
36738
  function createDialog() {
35760
- dialog = $('<div>', {
35761
- id: 'red-ui-search',
35762
- class: 'red-ui-search',
35763
- }).appendTo('#main-container');
35764
- 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(
35765
36744
  dialog
35766
36745
  );
35767
36746
  searchInput = $(
@@ -35769,25 +36748,30 @@ RED.notifications = (function() {
35769
36748
  )
35770
36749
  .appendTo(searchDiv)
35771
36750
  .searchBox({
35772
- delay: 200,
36751
+ delay: 100,
35773
36752
  change: function () {
35774
- search($(this).val());
36753
+ let value = $(this).val();
36754
+ if (!shouldInvokeCommand(value)) {
36755
+ search($(this).val());
36756
+ }
35775
36757
  },
35776
36758
  });
35777
36759
 
35778
- searchInput.on('keydown', function (evt) {
36760
+ searchInput.on("keydown", function (evt) {
35779
36761
  var children;
35780
- if (results.length > 0) {
36762
+
36763
+ // Check for embedded commands
36764
+ if (!shouldInvokeCommand(evt.target.value) && results.length > 0) {
35781
36765
  if (evt.keyCode === 40) {
35782
36766
  // Down
35783
36767
  children = searchResults.children();
35784
36768
  if (selected < children.length - 1) {
35785
36769
  if (selected > -1) {
35786
- $(children[selected]).removeClass('selected');
36770
+ $(children[selected]).removeClass("selected");
35787
36771
  }
35788
36772
  selected++;
35789
36773
  }
35790
- $(children[selected]).addClass('selected');
36774
+ $(children[selected]).addClass("selected");
35791
36775
  ensureSelectedIsVisible();
35792
36776
  evt.preventDefault();
35793
36777
  } else if (evt.keyCode === 38) {
@@ -35795,11 +36779,11 @@ RED.notifications = (function() {
35795
36779
  children = searchResults.children();
35796
36780
  if (selected > 0) {
35797
36781
  if (selected < children.length) {
35798
- $(children[selected]).removeClass('selected');
36782
+ $(children[selected]).removeClass("selected");
35799
36783
  }
35800
36784
  selected--;
35801
36785
  }
35802
- $(children[selected]).addClass('selected');
36786
+ $(children[selected]).addClass("selected");
35803
36787
  ensureSelectedIsVisible();
35804
36788
  evt.preventDefault();
35805
36789
  } else if (evt.keyCode === 13) {
@@ -35812,13 +36796,13 @@ RED.notifications = (function() {
35812
36796
  });
35813
36797
  searchInput.i18n();
35814
36798
 
35815
- var searchResultsDiv = $('<div>', {
35816
- class: 'red-ui-search-results-container',
36799
+ var searchResultsDiv = $("<div>", {
36800
+ class: "red-ui-search-results-container",
35817
36801
  }).appendTo(dialog);
35818
36802
 
35819
- searchResults = $('<ol>', {
35820
- id: 'search-result-list',
35821
- 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;",
35822
36806
  })
35823
36807
  .appendTo(searchResultsDiv)
35824
36808
  .editableList({
@@ -35826,36 +36810,38 @@ RED.notifications = (function() {
35826
36810
  addItem: function (container, i, object) {
35827
36811
  var node = object.node;
35828
36812
 
35829
- // If node === undefined and object is object => object is the command
36813
+ // If node === undefined and object is object => object is the command
35830
36814
  // If node === undefiend and object is empty => user search yield no results
35831
36815
  // otherwise is a normal search ...
35832
36816
 
35833
36817
  if (node === undefined && !object) {
35834
36818
  // case of user search yield no results
35835
- $('<div>', { class: 'red-ui-search-empty' })
35836
- .text('No matches found')
36819
+ $("<div>", { class: "red-ui-search-empty" })
36820
+ .text("No matches found")
35837
36821
  .appendTo(container);
35838
36822
  } else if (node === undefined && object) {
35839
36823
  // case of initial display of options (commands & tabs ) ... (object is a command)
35840
- if (object.type === 'command') {
35841
-
36824
+ if (object.type === "command") {
35842
36825
  // Main result container
35843
- var div = $('<a>', {
35844
- href: '#',
35845
- class: 'red-ui-search-result',
36826
+ var div = $("<a>", {
36827
+ href: "#",
36828
+ class: "red-ui-search-result",
35846
36829
  }).appendTo(container);
35847
36830
 
35848
36831
  // Command title here
35849
- var contentDescription = $('<div>', {
35850
- class: 'red-ui-search-result-description',
36832
+ var contentDescription = $("<div>", {
36833
+ class: "red-ui-search-result-description",
35851
36834
  }).appendTo(div);
35852
36835
 
35853
- $('<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
+ })
35854
36840
  .text(object.title)
35855
36841
  .appendTo(contentDescription);
35856
36842
 
35857
36843
  // Type of object (command)
35858
- $('<div>', { class: 'red-ui-search-result-command-shortcut' })
36844
+ $("<div>", { class: "red-ui-search-result-command-shortcut" })
35859
36845
  .text(object.shortcut)
35860
36846
  .appendTo(div);
35861
36847
 
@@ -35864,46 +36850,48 @@ RED.notifications = (function() {
35864
36850
  if (object.action) {
35865
36851
  hide();
35866
36852
  window.setTimeout(() => {
35867
- RED.actions.invoke(object.action)
35868
- }, 10)
36853
+ RED.actions.invoke(object.action);
36854
+ }, 10);
35869
36855
  } else {
35870
36856
  hide();
35871
36857
  window.setTimeout(() => {
35872
- object.cb()
35873
- }, 10)
36858
+ object.cb();
36859
+ }, 10);
35874
36860
  }
35875
-
35876
36861
  });
35877
36862
  }
35878
-
35879
36863
  } else {
35880
36864
  var def = node._def;
35881
- var div = $('<a>', {
35882
- href: '#',
35883
- class: 'red-ui-search-result',
36865
+ var div = $("<a>", {
36866
+ href: "#",
36867
+ class: "red-ui-search-result",
35884
36868
  }).appendTo(container);
35885
36869
 
35886
36870
  // ::: Part of the description
35887
- var contentDescription = $('<div>', {
35888
- class: 'red-ui-search-result-description',
36871
+ var contentDescription = $("<div>", {
36872
+ class: "red-ui-search-result-description",
35889
36873
  }).appendTo(div);
35890
36874
 
35891
- // ::: Part of the icon here...
35892
- var nodeDiv = $('<div>', {
35893
- class: 'ui-search-result-node',
36875
+ // ::: Part of the icon here...
36876
+ var nodeDiv = $("<div>", {
36877
+ class: "ui-search-result-node",
35894
36878
  }).appendTo(contentDescription);
35895
36879
 
35896
36880
  var colour = RED.utils.getNodeColor(node.type, def);
35897
36881
  var icon_url = RED.utils.getNodeIcon(def, node);
35898
36882
 
35899
- if (node.type === 'tab') {
35900
- var iconContainer = $('<div/>', {
35901
- class: 'palette_icon_container',
36883
+ if (node.type === "tab") {
36884
+ var iconContainer = $("<div/>", {
36885
+ class: "palette_icon_container",
35902
36886
  }).appendTo(nodeDiv);
35903
- 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
+ );
35904
36892
  } else {
35905
- var iconContainer = $('<div/>', {
35906
- class: 'palette_icon_container',
36893
+ var iconContainer = $("<div/>", {
36894
+ class: "palette_icon_container",
35907
36895
  }).appendTo(nodeDiv);
35908
36896
  RED.utils.createIconElement(icon_url, iconContainer, true);
35909
36897
  }
@@ -35912,22 +36900,22 @@ RED.notifications = (function() {
35912
36900
  var workspace = RED.nodes.workspace(node.z);
35913
36901
  if (!workspace) {
35914
36902
  workspace = RED.nodes.subflow(node.z);
35915
- workspace = 'subflow:' + workspace.name;
36903
+ workspace = "subflow:" + workspace.name;
35916
36904
  } else {
35917
36905
  workspace = workspace.label; //'flow:' + workspace.label
35918
36906
  }
35919
- $('<div>', { class: 'red-ui-search-result-node-flow' })
36907
+ $("<div>", { class: "red-ui-search-result-node-flow" })
35920
36908
  .text(workspace)
35921
36909
  .appendTo(div);
35922
36910
  }
35923
36911
 
35924
- $('<div>', { class: 'red-ui-search-result-node-label' })
36912
+ $("<div>", { class: "red-ui-search-result-node-label" })
35925
36913
  .text(object.label || node.id)
35926
36914
  .appendTo(contentDescription);
35927
- $('<div>', { class: 'red-ui-search-result-node-type' })
36915
+ $("<div>", { class: "red-ui-search-result-node-type" })
35928
36916
  .text(node.type)
35929
36917
  .appendTo(contentDescription);
35930
- $('<div>', { class: 'red-ui-search-result-node-id' })
36918
+ $("<div>", { class: "red-ui-search-result-node-id" })
35931
36919
  .text(node.id)
35932
36920
  .appendTo(contentDescription);
35933
36921
 
@@ -35954,15 +36942,15 @@ RED.notifications = (function() {
35954
36942
 
35955
36943
  function show(v) {
35956
36944
  // Disable the project dialog
35957
- RED.actions.invoke('core:project-info:close');
35958
- RED.actions.invoke('core:settings:close');
36945
+ RED.actions.invoke("core:project-info:close");
36946
+ RED.actions.invoke("core:settings:close");
35959
36947
 
35960
36948
  if (!visible) {
35961
- RED.keyboard.add('*', 'escape', function () {
36949
+ RED.keyboard.add("*", "escape", function () {
35962
36950
  hide();
35963
36951
  });
35964
36952
 
35965
- $('#main-container').click(() => {
36953
+ $("#main-container").click(() => {
35966
36954
  hide();
35967
36955
  });
35968
36956
 
@@ -35972,24 +36960,22 @@ RED.notifications = (function() {
35972
36960
  createDialog();
35973
36961
  }
35974
36962
  dialog.slideDown(300);
35975
- searchInput.searchBox('value', v);
35976
- RED.events.emit('search:open');
36963
+ searchInput.searchBox("value", v);
36964
+ RED.events.emit("search:open");
35977
36965
  visible = true;
35978
36966
  window.setTimeout(() => {
35979
- searchInput.focus()
36967
+ searchInput.focus();
35980
36968
  }, 50);
35981
36969
 
35982
36970
  // Populate search results with commands and tabs at least
35983
36971
  search();
35984
36972
  }
35985
-
35986
-
35987
36973
  }
35988
36974
 
35989
36975
  function hide() {
35990
36976
  if (visible) {
35991
- $('#main-container').off('click');
35992
- RED.keyboard.remove('escape');
36977
+ $("#main-container").off("click");
36978
+ RED.keyboard.remove("escape");
35993
36979
  visible = false;
35994
36980
  // $('#header-shade').hide();
35995
36981
  // $('#editor-shade').hide();
@@ -35998,28 +36984,28 @@ RED.notifications = (function() {
35998
36984
  // $('#sidebar-separator').show();
35999
36985
  if (dialog !== null) {
36000
36986
  dialog.slideUp(200, function () {
36001
- searchInput.searchBox('value', '');
36987
+ searchInput.searchBox("value", "");
36002
36988
  });
36003
36989
  }
36004
- RED.events.emit('search:close');
36990
+ RED.events.emit("search:close");
36005
36991
  }
36006
36992
  }
36007
36993
 
36008
36994
  function init() {
36009
- RED.actions.add('core:search', show);
36010
- RED.actions.add('core:search:close', hide);
36995
+ RED.actions.add("core:search", show);
36996
+ RED.actions.add("core:search:close", hide);
36011
36997
 
36012
- RED.events.on('type-search:open', function () {
36998
+ RED.events.on("type-search:open", function () {
36013
36999
  disabled = true;
36014
37000
  });
36015
- RED.events.on('type-search:close', function () {
37001
+ RED.events.on("type-search:close", function () {
36016
37002
  disabled = false;
36017
37003
  });
36018
37004
 
36019
- $('#header-shade').on('mousedown', hide);
36020
- $('#editor-shade').on('mousedown', hide);
36021
- $('#palette-shade').on('mousedown', hide);
36022
- $('#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);
36023
37009
  }
36024
37010
 
36025
37011
  return {
@@ -36027,7 +37013,171 @@ RED.notifications = (function() {
36027
37013
  show: show,
36028
37014
  hide: hide,
36029
37015
  reveal: reveal,
36030
- 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,
36031
37181
  };
36032
37182
  })();
36033
37183
  ;RED.projectInfo = (function () {
@@ -36266,62 +37416,67 @@ RED.notifications = (function() {
36266
37416
  getWorkspaceInfo
36267
37417
  };
36268
37418
  })();
36269
- ;RED.uiSettings = (function(){
36270
- let testConfigStore;
36271
- let cloudConfigStore = window.__kumologica.settings.cloudConfigStore;
36272
- let networkConfigStore = window.__kumologica.settings.networkConfigStore
36273
- let shell = window.__kumologica.electron.shell;
36274
- let dialog = null;
36275
- let visible = false;
36276
- let cmInstanceCloud = null;
36277
- let cmInstanceEnvvars = null;
36278
- let totalHeightAvailable;
36279
-
36280
- let screen;
36281
-
36282
- function getScreen() {
36283
- if (!screen){
36284
- // 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.
36285
- testConfigStore = window.__kumologica.settings.testConfig;
36286
- // initialize the screen now
36287
- screen = [
36288
- { "selected": true,
36289
- "id": "ui-settings-creds",
36290
- "label": "Cloud Profiles",
36291
- "body": {
36292
- "title": "Cloud Profiles",
36293
- "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: `
36294
37445
  Configure all of your cloud profile settings that can be used by this designer to support testing or deploying.
36295
37446
  <a href="https://docs.kumologica.com/docs/guide/Intro.html" target="_blank">Learn more</a>`,
36296
- "html": `
37447
+ html: `
36297
37448
  <div>
36298
37449
  <div id="fileLocationPath">
36299
37450
  <span id="settingFilePath">${cloudConfigStore.getCloudConfigFileFullPath()}</span>
36300
37451
  </div>
36301
37452
  <textarea id="cloud-settings-editor" rows="20">
36302
37453
  </textarea>
36303
- </div>`
36304
- },
36305
- "onInit": () => {
36306
- // load content of config credentials file: ~/.kumologica/credentials
36307
- let cloudConfigContent = cloudConfigStore.readCloudConfigFile();
36308
- cmInstanceCloud = initEditor('cloud-settings-editor', cloudConfigContent);
36309
- },
36310
- "onSelect": () => {
36311
- cmInstanceCloud.refresh();
36312
- },
36313
- "onSave": () => {
36314
- cloudConfigStore.writeCloudConfigFile(cmInstanceCloud.getValue());
36315
- RED.events.emit('settings:cloud-config-changed');
36316
- }
37454
+ </div>`,
36317
37455
  },
36318
- {
36319
- "id": "ui-settings-network",
36320
- "label": "Network",
36321
- "body": {
36322
- "title": "Proxy Server Settings",
36323
- "subtitle": "Configure the proxy settings used by the designer. Flows will use the proxy specified on the nodes instead.",
36324
- "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: `
36325
37480
  <div>
36326
37481
  <form id="proxy-options-div">
36327
37482
  <input type="radio" id="proxy-option-default" name="proxy-option" style="margin:0"> Use default operating system settings<br>
@@ -36332,45 +37487,45 @@ RED.notifications = (function() {
36332
37487
  <div class="option"><label>Port</label><input type="text" id="proxy-port" /></div>
36333
37488
  </div>
36334
37489
  <div id="proxy-auth">
36335
- <div id="proxyCredsRequiredBox" style="display: flex">
36336
- <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">
36337
37492
  <label>Proxy server requires username and password</label>
36338
37493
  </div>
36339
- <div id="proxyCredsBox" style="padding-left: 40px">
37494
+ <div id="proxyCredsBox" style="padding-top: 10px;padding-left: 40px">
36340
37495
  <div class="option"><label>Username</label><input type="text" id="proxy-auth-username" style="width:50%" /></div>
36341
37496
  <div class="option"><label>Password</label><input type="password" id="proxy-auth-password" style="width:50%"/></div>
36342
37497
  </div>
36343
37498
  </div>
36344
37499
  </div>
36345
- `
36346
- },
36347
- "onInit": () => {
36348
- // load content of config credentials file: ~/.kumologica/settings
36349
- let proxySettings = networkConfigStore.getProxyDetails();
36350
- initProxySettings(proxySettings);
36351
- handleProxySettingsEvent();
36352
- },
36353
- "onSelect": () => {},
36354
- "onSave": () => {
36355
- // Save proxy details
36356
- networkConfigStore.saveProxyDetails(
36357
- $('#proxy-option-custom').is(':checked'), // custom clicked?
36358
- $('#proxy-server').val(), // host
36359
- $('#proxy-port').val(), // port
36360
- $('#proxyAuthRequired').is(':checked'), // authentication clicked?
36361
- $('#proxy-auth-username').val(), // username
36362
- $('#proxy-auth-password').val() // password
36363
- );
36364
- }
37500
+ `,
36365
37501
  },
36366
- {
36367
- "id": "ui-settings-envvars",
36368
- "label": "Environments",
36369
- "body": {
36370
- "title": "Environments",
36371
- "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: `
36372
37527
  Environments are groups of key value pairs (variables) that allow you to quickly set a different context for each test executions`,
36373
- "html": `
37528
+ html: `
36374
37529
  <div>
36375
37530
  <!--
36376
37531
  <div id="fileLocationPath">
@@ -36378,393 +37533,398 @@ RED.notifications = (function() {
36378
37533
  </div> -->
36379
37534
  <textarea id="envvar-settings-editor" rows="20">
36380
37535
  </textarea>
36381
- </div>`
36382
- },
36383
- "onInit": () => {
36384
- let envvarConfigContent = testConfigStore.getEnvironmentSectionFromConfig();
36385
- cmInstanceEnvvars = initEditor('envvar-settings-editor', envvarConfigContent);
36386
- },
36387
- "onSelect": () => {
36388
- cmInstanceEnvvars.refresh();
36389
- },
36390
- "onSave": () => {
36391
- testConfigStore.saveEnvironmentSectionIntoConfig(cmInstanceEnvvars.getValue());
36392
- RED.events.emit('settings:environment-variables-changed');
36393
- }
36394
- }
36395
- ];
36396
- }
36397
- 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
+ ];
36398
37557
  }
37558
+ return screen;
37559
+ }
36399
37560
 
36400
- function createDialog() {
36401
-
36402
-
36403
- // remove if previous dialog exist
36404
- $('#ui-settings').remove();
37561
+ function createDialog() {
37562
+ // remove if previous dialog exist
37563
+ $("#ui-settings").remove();
36405
37564
 
36406
- dialog = $('<div>', {
36407
- id: 'ui-settings',
36408
- class: 'ui-settings',
36409
- }).appendTo('#main-container');
37565
+ dialog = $("<div>", {
37566
+ id: "ui-settings",
37567
+ class: "ui-settings",
37568
+ }).appendTo("#main-container");
36410
37569
 
36411
- // Programmatically calculate the height of the ui-settings window
36412
- totalHeightAvailable = $('#main-container').height();
36413
- let offset = 74;
36414
- $('#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);
36415
37574
 
36416
- let wrapperDiv = $('<div>', {
36417
- class: 'ui-settings-body'
36418
- }).appendTo(dialog);
37575
+ let wrapperDiv = $("<div>", {
37576
+ class: "ui-settings-body",
37577
+ }).appendTo(dialog);
36419
37578
 
36420
- // Left pannel of settings
36421
- let optionsDiv = $(`
37579
+ // Left pannel of settings
37580
+ let optionsDiv = $(`
36422
37581
  <div id="ui-settings-options">
36423
37582
  </div>
36424
37583
  `).appendTo(wrapperDiv);
36425
37584
 
36426
- // Left pannel of settings
36427
- getScreen().forEach(option => {
36428
- if (option.selected){
36429
- $(`
37585
+ // Left pannel of settings
37586
+ getScreen().forEach((option) => {
37587
+ if (option.selected) {
37588
+ $(`
36430
37589
  <div id="${option.id}" class="ui-settings-option ui-settings-option-selected">
36431
37590
  <span class="settingsOptionLabel">
36432
37591
  ${option.label}
36433
37592
  </span>
36434
37593
  </div>`).appendTo(optionsDiv);
36435
- } else {
36436
- $(`
37594
+ } else {
37595
+ $(`
36437
37596
  <div id="${option.id}" class="ui-settings-option ui-settings-option">
36438
37597
  <span class="settingsOptionLabel">
36439
37598
  ${option.label}
36440
37599
  </span>
36441
37600
  </div>`).appendTo(optionsDiv);
36442
- }
36443
-
36444
- });
37601
+ }
37602
+ });
36445
37603
 
36446
- // Right pannel of settings
36447
- let optionsBodyDiv = $(`
37604
+ // Right pannel of settings
37605
+ let optionsBodyDiv = $(`
36448
37606
  <div id="ui-settings-optionsbody">
36449
37607
  </div>
36450
- `).appendTo(wrapperDiv)
37608
+ `).appendTo(wrapperDiv);
36451
37609
 
36452
- getScreen().forEach(option => {
36453
- $(`
37610
+ getScreen().forEach((option) => {
37611
+ $(`
36454
37612
  <div id="${option.id}-body" class="ui-settings-general-body">
36455
- <div>
37613
+ <div style="display=flex; flex-direction: column; height:100%">
36456
37614
  <div class="settingsTitle">${option.body.title}</div>
36457
37615
  <div class="settingsSubtitle">${option.body.subtitle}</div>
36458
37616
  ${option.body.html}
36459
37617
  </div>
36460
37618
  </div>
36461
- `).appendTo(optionsBodyDiv)
36462
- });
36463
-
36464
- $(`
36465
- <div class="editor-tray-toolbar" style="top: 16px !important">
37619
+ `).appendTo(optionsBodyDiv);
37620
+ });
37621
+
37622
+ $(`
37623
+ <div class="editor-tray-toolbar">
36466
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>
36467
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>
36468
37626
  </div>
36469
37627
  `).appendTo(optionsBodyDiv);
36470
37628
 
36471
- // Initialize the options body screen
36472
- getScreen().forEach(option => {
36473
- // Left click on option
36474
- $(`#${option.id}`).click ((e) => {
36475
- resetWindows();
36476
- $(`#${option.id}`).addClass('ui-settings-option-selected');
36477
- $(`#${option.id}-body`).show();
36478
- option.onSelect();
36479
- });
36480
- // Specific functionality
36481
- 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();
36482
37640
 
36483
- // Hide screen if not default
36484
- if (option.hasOwnProperty("selected") && option.selected){
36485
- $(`#${option.id}-body`).show();
36486
- } else {
36487
- $(`#${option.id}-body`).hide();
36488
- }
36489
- });
36490
- // Initialize the toolbar
36491
- $('#options-save').click(e=> {
36492
- saveSettings();
36493
- });
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
+ });
36494
37652
 
36495
- $('#options-cancel').click(e => {
36496
- cancelSettings();
36497
- });
37653
+ $("#options-cancel").click((e) => {
37654
+ cancelSettings();
37655
+ });
37656
+ }
36498
37657
 
36499
- }
37658
+ function saveSettings() {
37659
+ getScreen().forEach((option) => {
37660
+ option.onSave();
37661
+ });
37662
+ hide();
37663
+ }
36500
37664
 
36501
- function saveSettings() {
36502
- getScreen().forEach(option => {
36503
- option.onSave();
36504
- })
36505
- hide();
36506
- }
37665
+ function cancelSettings() {
37666
+ hide();
37667
+ }
36507
37668
 
36508
- function cancelSettings() {
36509
- hide();
36510
- }
37669
+ function selectProxyCustom() {
37670
+ setTimeout(() => {
37671
+ $("#proxy-option-custom").prop("checked", true);
37672
+ $("#proxy-option-default").prop("checked", false);
37673
+ }, 50);
36511
37674
 
36512
- function selectProxyCustom() {
36513
- setTimeout(() => {
36514
- $('#proxy-option-custom').prop('checked', true);
36515
- $('#proxy-option-default').prop('checked', false);
36516
- }, 50);
37675
+ $("#proxy-server").prop("readonly", false);
37676
+ $("#proxy-port").prop("readonly", false);
37677
+ }
36517
37678
 
36518
- $('#proxy-server').prop('readonly', false);
36519
- $('#proxy-port').prop('readonly', false);
36520
- }
37679
+ function selectProxyDefault() {
37680
+ setTimeout(() => {
37681
+ $("#proxy-option-custom").prop("checked", false);
37682
+ $("#proxy-option-default").prop("checked", true);
37683
+ }, 50);
36521
37684
 
36522
- function selectProxyDefault(){
36523
- setTimeout(() => {
36524
- $('#proxy-option-custom').prop('checked', false);
36525
- $('#proxy-option-default').prop('checked', true);
36526
- }, 50);
36527
-
36528
- $('#proxy-server').prop('readonly', true);
36529
- $('#proxy-port').prop('readonly', true);
36530
- }
37685
+ $("#proxy-server").prop("readonly", true);
37686
+ $("#proxy-port").prop("readonly", true);
37687
+ }
36531
37688
 
36532
- function selectProxyAuth() {
36533
- setTimeout(() => {
36534
- let isChecked = $('#proxyAuthRequired').is(':checked');
36535
- if (isChecked){
36536
- $('#proxyAuthRequired').prop('checked', false);
36537
- $('#proxy-auth-username').prop('readonly', true);
36538
- $('#proxy-auth-password').prop('readonly', true);
36539
- } else {
36540
- $('#proxyAuthRequired').prop('checked', true);
36541
- $('#proxy-auth-username').prop('readonly', false);
36542
- $('#proxy-auth-password').prop('readonly', false);
36543
- }
36544
- }, 50);
36545
- }
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
+ }
36546
37703
 
36547
- function handleProxySettingsEvent(){
36548
- $('#proxy-option-default').click( () => {
36549
- RED.events.emit('settings:select-proxy-default');
36550
- return false;
36551
- });
37704
+ function handleProxySettingsEvent() {
37705
+ $("#proxy-option-default").click(() => {
37706
+ RED.events.emit("settings:select-proxy-default");
37707
+ return false;
37708
+ });
36552
37709
 
36553
- $('#proxy-option-custom').click( () => {
36554
- RED.events.emit('settings:select-proxy-custom');
36555
- return false;
36556
- });
37710
+ $("#proxy-option-custom").click(() => {
37711
+ RED.events.emit("settings:select-proxy-custom");
37712
+ return false;
37713
+ });
36557
37714
 
36558
- $('#proxyAuthRequired').click( function(e){
36559
- RED.events.emit('settings:select-proxy-auth');
36560
- return false;
36561
- });
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);
36562
37744
  }
36563
37745
 
36564
- function initProxySettings(proxySettings){
36565
- // console.log('[ui-settings] initProxySettings with settings:', proxySettings);
36566
- // Proxy server
36567
- if (proxySettings.custom){
36568
- $('#proxy-option-custom').prop('checked', true);
36569
- $('#proxy-option-default').prop('checked', false);
36570
- $('#proxy-server').val(proxySettings.host);
36571
- $('#proxy-port').val(proxySettings.port || '8080');
36572
- } else {
36573
- $('#proxy-option-default').prop('checked', true);
36574
- $('#proxy-option-custom').prop('checked', false);
36575
- $('#proxy-server').prop('readonly', true);
36576
- $('#proxy-port').prop('readonly', true);
36577
- }
36578
- // Proxy auth
36579
- if (proxySettings.authentication){
36580
- $('#proxyAuthRequired').prop('checked', true);
36581
- $('#proxy-auth-username').val(proxySettings.username);
36582
- $('#proxy-auth-password').val(proxySettings.password);
36583
- } else {
36584
- $('#proxyAuthRequired').prop('checked', false);
36585
- $('#proxy-auth-username').prop('readonly', true);
36586
- $('#proxy-auth-password').prop('readonly', true);
36587
- }
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
+ }
36588
37750
 
36589
- RED.events.on('settings:select-proxy-custom', selectProxyCustom);
36590
- RED.events.on('settings:select-proxy-default', selectProxyDefault);
36591
- RED.events.on('settings:select-proxy-auth', selectProxyAuth);
36592
- }
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();
36593
37757
 
36594
- function initEditor(anchorId, contentBody) {
36595
- CodeMirror.defineMode("properties", function() {
36596
- return {
36597
- token: function(stream, state) {
36598
- var sol = stream.sol() || state.afterSection;
36599
- var eol = stream.eol();
36600
-
36601
- state.afterSection = false;
36602
-
36603
- if (sol) {
36604
- if (state.nextMultiline) {
36605
- state.inMultiline = true;
36606
- state.nextMultiline = false;
36607
- } else {
36608
- state.position = "def";
36609
- }
36610
- }
36611
-
36612
- if (eol && ! state.nextMultiline) {
36613
- state.inMultiline = false;
36614
- state.position = "def";
36615
- }
36616
-
36617
- if (sol) {
36618
- while(stream.eatSpace()) {}
36619
- }
36620
-
36621
- var ch = stream.next();
36622
-
36623
- if (sol && (ch === "#" || ch === "!" || ch === ";")) {
36624
- state.position = "comment";
36625
- stream.skipToEnd();
36626
- return "comment";
36627
- } else if (sol && ch === "[") {
36628
- state.afterSection = true;
36629
- stream.skipTo("]"); stream.eat("]");
36630
- return "header";
36631
- } else if (ch === "=") {
36632
- state.position = "quote";
36633
- return null;
36634
- } else if (ch === "\\" && state.position === "quote") {
36635
- if (stream.eol()) { // end of line?
36636
- // Multiline value
36637
- state.nextMultiline = true;
36638
- }
36639
- }
36640
-
36641
- return state.position;
36642
- },
36643
-
36644
- startState: function() {
36645
- return {
36646
- position : "def", // Current position, "def", "quote" or "comment"
36647
- nextMultiline : false, // Is the next line multiline value
36648
- inMultiline : false, // Is the current line a multiline value
36649
- afterSection : false // Did we just open a section
36650
- };
36651
- }
36652
-
36653
- };
36654
- });
36655
- let cmInstance = CodeMirror.fromTextArea(document.getElementById(anchorId), {
36656
- theme: "monokai",
36657
- lineWrapping: true,
36658
- mode: 'properties'
36659
- });
37758
+ state.afterSection = false;
36660
37759
 
36661
- // reset the listenere
36662
- 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
+ }
36663
37768
 
36664
- cmInstance.getDoc().setValue(contentBody);
36665
- cmInstance.focus();
36666
- //console.log(`lineCount: ${cmInstance.lineCount()}`)
36667
- // Set the cursor at the end of existing content
36668
- cmInstance.setCursor(cmInstance.lineCount(), 0);
36669
- let codeMirrorHeight = totalHeightAvailable - 400;
37769
+ if (eol && !state.nextMultiline) {
37770
+ state.inMultiline = false;
37771
+ state.position = "def";
37772
+ }
36670
37773
 
36671
- cmInstance.setSize(null, codeMirrorHeight);
36672
- // cmInstance.refresh();
36673
- setTimeout(function() {
36674
- cmInstance.refresh();
36675
- }, 100);
37774
+ if (sol) {
37775
+ while (stream.eatSpace()) {}
37776
+ }
36676
37777
 
36677
- cmInstance.on("change", function(cm, change){
36678
- // enable the save button
36679
- $('#options-save').removeClass('disabled');
36680
- })
37778
+ var ch = stream.next();
36681
37779
 
36682
- return cmInstance;
36683
- }
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
+ }
36684
37799
 
36685
- function show(){
36686
-
36687
- // Disable the search dialog if opened
36688
- RED.actions.invoke('core:search:close');
36689
- RED.actions.invoke('core:project-info:close');
36690
- if (!visible){
36691
- RED.keyboard.add('*', 'escape', () => hide() );
37800
+ return state.position;
37801
+ },
36692
37802
 
36693
- createDialog();
36694
- dialog.slideDown(300);
36695
- 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
+ );
36696
37821
 
36697
- // UI goodies
36698
- $('#ui-settings').click( e=> {
36699
- e.preventDefault();
36700
- if ($(e.target).is('a')){
36701
- shell.openExternal(e.target.href);
36702
- }
36703
- e.stopImmediatePropagation();
36704
- });
36705
-
36706
- $('#main-container').click((e)=> {
36707
- hide();
36708
- });
36709
- }
37822
+ // reset the listenere
37823
+ cmInstance.off("change");
36710
37824
 
36711
- }
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;
36712
37831
 
36713
- function showEnvironments() {
36714
- show();
36715
- $('#ui-settings-envvars').click();
36716
- }
37832
+ cmInstance.setSize(null, codeMirrorHeight);
37833
+ // cmInstance.refresh();
37834
+ setTimeout(function () {
37835
+ cmInstance.refresh();
37836
+ }, 100);
36717
37837
 
36718
- function hide(){
36719
- if (visible){
36720
- $('#main-container').off('click');
36721
- RED.keyboard.remove('escape');
36722
- visible = false;
36723
- if (dialog !== null) {
36724
- dialog.slideUp(200, function () {
36725
- // searchInput.searchBox('value', '');
36726
- });
36727
- }
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);
36728
37862
  }
36729
- }
37863
+ e.stopImmediatePropagation();
37864
+ });
36730
37865
 
36731
- function resetWindows() {
36732
- getScreen().forEach(option => {
36733
- $(`#${option.id}-body`).hide();
36734
- $(`#${option.id}`).removeClass('ui-settings-option-selected');
37866
+ $("#main-container").click((e) => {
37867
+ hide();
36735
37868
  });
36736
37869
  }
37870
+ }
36737
37871
 
36738
- function getProxyHeader() {
36739
- // Read the proxy details
36740
- let proxyHeader = undefined;
36741
- let proxySettings = networkConfigStore.getProxyDetails();
36742
- let { custom, host, port, authentication, username, password } = proxySettings;
36743
- if (custom){
36744
- proxyHeader = `${host}:${port}`;
36745
- if (proxySettings.authentication){
36746
- proxyHeader = `${username}:${password}@${proxyHeader}`
36747
- }
36748
- proxyHeader = `http://${proxyHeader}`;
36749
- }
37872
+ function showEnvironments() {
37873
+ show();
37874
+ $("#ui-settings-envvars").click();
37875
+ }
36750
37876
 
36751
- 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
+ }
36752
37887
  }
37888
+ }
36753
37889
 
36754
- function init() {
36755
- RED.actions.add('core:settings:open', show);
36756
- RED.actions.add('core:settings:close', hide);
36757
- 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}`;
36758
37909
  }
36759
37910
 
37911
+ return proxyHeader;
37912
+ }
36760
37913
 
36761
- return {
36762
- init: init,
36763
- show: show,
36764
- hide: hide,
36765
- getProxyHeader: getProxyHeader,
36766
- }
36767
- })();;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 () {
36768
37928
  var shade;
36769
37929
 
36770
37930
  var disabled = false;