@kumologica/sdk 3.4.0 → 3.5.0-beta2

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 (51) hide show
  1. package/cli/commands/create-commands/openapi.js +42 -0
  2. package/cli/commands/create.js +17 -8
  3. package/cli/commands/login.js +87 -0
  4. package/package.json +18 -7
  5. package/src/app/lib/ai/layout.js +75 -0
  6. package/src/app/lib/ai/openai.js +108 -0
  7. package/src/app/lib/ai/prompt.txt +583 -0
  8. package/src/app/lib/aws/ca-cloudwatch-api.js +2 -10
  9. package/src/app/lib/aws/ca-dynamodb-api.js +6 -10
  10. package/src/app/lib/aws/ca-elb-api.js +4 -24
  11. package/src/app/lib/aws/ca-events-api.js +5 -12
  12. package/src/app/lib/aws/ca-iot-api.js +3 -87
  13. package/src/app/lib/aws/ca-s3-api.js +17 -62
  14. package/src/app/lib/aws/ca-sns-api.js +6 -15
  15. package/src/app/lib/aws/ca-sqs-api.js +9 -6
  16. package/src/app/lib/aws/index.js +70 -86
  17. package/src/app/lib/aws/kl-apigw-api.js +40 -0
  18. package/src/app/lib/aws/kl-iam-api.js +5 -5
  19. package/src/app/lib/github/index.js +0 -17
  20. package/src/app/lib/serverless/index.js +1 -1
  21. package/src/app/lib/stores/settings-cloud-store.js +35 -2
  22. package/src/app/main.js +34 -32
  23. package/src/app/preload.js +36 -28
  24. package/src/app/ui/editor-client/public/red/red.js +924 -458
  25. package/src/app/ui/editor-client/public/red/red.min.js +2 -2
  26. package/src/app/ui/editor-client/public/red/style.min.css +1 -1
  27. package/src/app/ui/editor-client/src/js/nodes.js +19 -18
  28. package/src/app/ui/editor-client/src/js/red.js +6 -3
  29. package/src/app/ui/editor-client/src/js/ui/editor.js +70 -70
  30. package/src/app/ui/editor-client/src/js/ui/footer.js +143 -0
  31. package/src/app/ui/editor-client/src/js/ui/search.js +43 -34
  32. package/src/app/ui/editor-client/src/js/ui/sidebar.js +26 -24
  33. package/src/app/ui/editor-client/src/js/ui/signup.js +56 -0
  34. package/src/app/ui/editor-client/src/js/ui/tab-ai.js +210 -0
  35. package/src/app/ui/editor-client/src/js/ui/tab-awsDeploy.js +30 -5
  36. package/src/app/ui/editor-client/src/js/ui/tab-test.js +120 -99
  37. package/src/app/ui/editor-client/src/js/ui/update-panel.js +0 -1
  38. package/src/app/ui/editor-client/src/js/ui/view.js +201 -202
  39. package/src/app/ui/editor-client/src/sass/editor.scss +715 -645
  40. package/src/app/ui/editor-client/src/sass/sidebar.scss +21 -12
  41. package/src/app/ui/editor-client/src/sass/style.scss +101 -0
  42. package/src/app/ui/editor-client/src/sass/tab-ai.scss +68 -0
  43. package/src/app/ui/editor-client/src/sass/workspace.scss +12 -2
  44. package/src/app/ui/editor-client/templates/index.mst +41 -7
  45. package/src/server/DesignerServer.js +2 -1
  46. package/cli/.DS_Store +0 -0
  47. package/fixtures/.DS_Store +0 -0
  48. package/src/app/lib/aws/ca-apigw-api.js +0 -216
  49. package/src/app/lib/aws/ca-codecommit-api.js +0 -63
  50. package/src/app/lib/aws/kl-rekognition-api.js +0 -66
  51. package/src/app/lib/aws/kl-ssm-api.js +0 -24
@@ -23,7 +23,7 @@ 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) {
@@ -93,7 +93,7 @@ jQuery.propHooks.disabled = {
93
93
  success: function (data) {
94
94
  RED.nodes.setNodeList(data);
95
95
  // RED.i18n.loadNodeCatalogs(function () {
96
- loadIconList(loadNodes);
96
+ loadIconList(loadNodes);
97
97
  // });
98
98
  },
99
99
  });
@@ -417,7 +417,7 @@ jQuery.propHooks.disabled = {
417
417
  appendNodeConfig(data);
418
418
  typeList =
419
419
  '<ul><li>' + msg.types.join('</li><li>') + '</li></ul>';
420
- RED.notify(`Node added to palette: ${msg.types.length} `+ typeList,
420
+ RED.notify(`Node added to palette: ${msg.types.length} ` + typeList,
421
421
  'success'
422
422
  );
423
423
  });
@@ -662,6 +662,7 @@ jQuery.propHooks.disabled = {
662
662
  RED.subflow.init();
663
663
  RED.workspaces.init();
664
664
  RED.clipboard.init();
665
+ RED.signup.init();
665
666
  RED.search.init();
666
667
  RED.projectInfo.init();
667
668
  RED.uiSettings.init();
@@ -720,6 +721,8 @@ jQuery.propHooks.disabled = {
720
721
  RED.i18n.init(options, function () {
721
722
  RED.settings.init(options, loadEditor);
722
723
  });
724
+ RED.footer.init();
725
+
723
726
  }
724
727
 
725
728
  return {
@@ -3171,9 +3174,9 @@ RED.state = {
3171
3174
 
3172
3175
  // TODO: too tightly coupled into palette UI
3173
3176
  }
3174
-
3177
+
3175
3178
  RED.events.emit('registry:node-type-added', nt);
3176
-
3179
+
3177
3180
  },
3178
3181
  removeNodeType: function (nt) {
3179
3182
  if (nt.substring(0, 8) != 'subflow:') {
@@ -3528,7 +3531,7 @@ RED.state = {
3528
3531
  if (
3529
3532
  !n.credentials._ ||
3530
3533
  n.credentials['has_' + cred] !=
3531
- n.credentials._['has_' + cred] ||
3534
+ n.credentials._['has_' + cred] ||
3532
3535
  (n.credentials['has_' + cred] && n.credentials[cred])
3533
3536
  ) {
3534
3537
  credentialSet[cred] = n.credentials[cred];
@@ -3613,7 +3616,7 @@ RED.state = {
3613
3616
  node.caname = '_error_unknown';
3614
3617
  node.category = '_error_unknown'
3615
3618
  }
3616
-
3619
+
3617
3620
  return node;
3618
3621
  }
3619
3622
 
@@ -3753,7 +3756,7 @@ RED.state = {
3753
3756
  }
3754
3757
  var nns = [];
3755
3758
  var i;
3756
-
3759
+
3757
3760
  for (i = 0; i < workspacesOrder.length; i++) {
3758
3761
  if (workspaces[workspacesOrder[i]].type == 'tab') {
3759
3762
  nns.push(convertWorkspace(workspaces[workspacesOrder[i]]));
@@ -3771,12 +3774,12 @@ RED.state = {
3771
3774
  }
3772
3775
  for (i = 0; i < nodes.length; i++) {
3773
3776
  var node = nodes[i];
3774
- let n = convertNode(node, exportCredentials);
3775
- // check if we need to report an error with node convertion
3776
- if (n.caname === '_error_unknown' && n.category === '_error_unknown'){
3777
- RED.notify(`<strong>Error</strong>: Invalid flow due to node type unknown [${n.type}]`, 'error');
3778
- }
3779
- nns.push(n);
3777
+ let n = convertNode(node, exportCredentials);
3778
+ // check if we need to report an error with node convertion
3779
+ if (n.caname === '_error_unknown' && n.category === '_error_unknown') {
3780
+ RED.notify(`<strong>Error</strong>: Invalid flow due to node type unknown [${n.type}]`, 'error');
3781
+ }
3782
+ nns.push(n);
3780
3783
  }
3781
3784
  return nns;
3782
3785
  }
@@ -3921,9 +3924,9 @@ RED.state = {
3921
3924
  var typeList = '<ul><li>' + unknownTypes.join('</li><li>') + '</li></ul>';
3922
3925
  RED.notify(
3923
3926
  '<p>' +
3924
- 'Imported unrecognised type:' +
3925
- '</p>' +
3926
- typeList,
3927
+ 'Imported unrecognised type:' +
3928
+ '</p>' +
3929
+ typeList,
3927
3930
  'error',
3928
3931
  false,
3929
3932
  10000
@@ -3931,6 +3934,7 @@ RED.state = {
3931
3934
  }
3932
3935
 
3933
3936
  var activeWorkspace = RED.workspaces.active();
3937
+ console.log('[nodes] ImportNodes --> activeWorkspace=', activeWorkspace)
3934
3938
  //TODO: check the z of the subflow instance and check _that_ if it exists
3935
3939
  var activeSubflow = getSubflow(activeWorkspace);
3936
3940
  for (i = 0; i < newNodes.length; i++) {
@@ -3948,7 +3952,7 @@ RED.state = {
3948
3952
  }
3949
3953
  if (err) {
3950
3954
  // TODO: standardise error codes
3951
- err.code = 'NODE_RED';
3955
+ err.code = 'KUMOLOGICA';
3952
3956
  throw err;
3953
3957
  }
3954
3958
  }
@@ -4468,9 +4472,9 @@ RED.state = {
4468
4472
  ];
4469
4473
  }
4470
4474
 
4471
- function getTabLabel(id){
4475
+ function getTabLabel(id) {
4472
4476
  let tabs = listWorkspaces();
4473
- for (tab in tabs){
4477
+ for (tab in tabs) {
4474
4478
  if (tabs[tab].id === id) {
4475
4479
  return tabs[tab].label;
4476
4480
  }
@@ -4753,7 +4757,7 @@ RED.state = {
4753
4757
  }
4754
4758
  },
4755
4759
  eachWorkspace: eachWorkspace,
4756
-
4760
+
4757
4761
  listWorkspaces: listWorkspaces,
4758
4762
 
4759
4763
  node: getNode,
@@ -6004,7 +6008,6 @@ RED.validators = {
6004
6008
  ipcRenderer.on('core:show-import-dialog', ()=> {
6005
6009
  RED.actions.invoke('core:show-import-dialog');
6006
6010
  });
6007
-
6008
6011
  ipcRenderer.on('core:show-export-dialog', ()=> {
6009
6012
  RED.actions.invoke('core:show-export-dialog');
6010
6013
  });
@@ -15270,14 +15273,14 @@ RED.h = handlers;
15270
15273
  {
15271
15274
  title: 'Paste',
15272
15275
  shortcut: 'Ctrl+V',
15273
- action: async function(elm, d, i) {
15276
+ action: async function (elm, d, i) {
15274
15277
  RED.actions.invoke('core:paste-from-internal-clipboard');
15275
15278
  }
15276
15279
  },
15277
15280
  {
15278
15281
  title: 'Search Node...',
15279
15282
  shortcut: 'Ctrl+F',
15280
- action: async function(elm, d, i) {
15283
+ action: async function (elm, d, i) {
15281
15284
  $('#btn-search').click();
15282
15285
  d3.event.stopPropagation();
15283
15286
  }
@@ -15285,7 +15288,7 @@ RED.h = handlers;
15285
15288
  { separator: true },
15286
15289
  {
15287
15290
  title: 'Clear All Breakpoints',
15288
- action: async function(elm, d, i) {
15291
+ action: async function (elm, d, i) {
15289
15292
  await window.__kumologica.debugger.removeAllBreakpoints();
15290
15293
  await redrawBreakpoints();
15291
15294
  redraw();
@@ -15295,7 +15298,7 @@ RED.h = handlers;
15295
15298
  {
15296
15299
  title: 'Run TestCase',
15297
15300
  shortcut: '',
15298
- action: async function(elm, d, i) {
15301
+ action: async function (elm, d, i) {
15299
15302
  $('#red-ui-tab-test-link-button').click();
15300
15303
  $('#test-sidebar-run-btn').click();
15301
15304
  }
@@ -15303,7 +15306,7 @@ RED.h = handlers;
15303
15306
  {
15304
15307
  title: 'Debug TestCase',
15305
15308
  shortcut: '',
15306
- action: async function(elm, d, i) {
15309
+ action: async function (elm, d, i) {
15307
15310
  $('#red-ui-tab-test-link-button').click();
15308
15311
  $('#test-sidebar-debug-btn').click();
15309
15312
  }
@@ -15312,14 +15315,14 @@ RED.h = handlers;
15312
15315
  {
15313
15316
  title: 'Toggle Navigator',
15314
15317
  shortcut: '',
15315
- action: async function(elm, d, i) {
15318
+ action: async function (elm, d, i) {
15316
15319
  RED.view.navigator.toggle();
15317
15320
  }
15318
- },
15321
+ },
15319
15322
  {
15320
15323
  title: 'Automatic Layout',
15321
15324
  shortcut: '',
15322
- action: async function(elm, d, i) {
15325
+ action: async function (elm, d, i) {
15323
15326
  applyLayout();
15324
15327
  }
15325
15328
  },
@@ -15327,25 +15330,25 @@ RED.h = handlers;
15327
15330
  {
15328
15331
  title: 'Open Node Library',
15329
15332
  shortcut: '',
15330
- action: async function(elm, d, i) {
15333
+ action: async function (elm, d, i) {
15331
15334
  $('#launch-node-library').click()
15332
15335
  }
15333
15336
  },
15334
15337
  {
15335
15338
  title: 'Add Node...',
15336
15339
  shortcut: 'Ctrl+Click',
15337
- action: async function(elm, d, i) {
15340
+ action: async function (elm, d, i) {
15338
15341
  d3.event.stopPropagation();
15339
15342
 
15340
15343
  let eventProps = {
15341
- ctrlKey: true,
15344
+ ctrlKey: true,
15342
15345
  metaKey: true,
15343
15346
  screenX: d3.event.screenX,
15344
15347
  screenY: d3.event.screenY,
15345
15348
  clientX: d3.event.clientX,
15346
15349
  clientY: d3.event.clientY,
15347
15350
  offsetX: d3.event.offsetX,
15348
- offsetY: d3.event.offsetY
15351
+ offsetY: d3.event.offsetY
15349
15352
  }
15350
15353
  mouse_mode = RED.state.DEFAULT;
15351
15354
 
@@ -15465,8 +15468,8 @@ RED.h = handlers;
15465
15468
  Math.max(
15466
15469
  0.3,
15467
15470
  scaleFactor +
15468
- Math.floor(moveTouchDistance * 100 - startTouchDistance * 100) /
15469
- 10000
15471
+ Math.floor(moveTouchDistance * 100 - startTouchDistance * 100) /
15472
+ 10000
15470
15473
  )
15471
15474
  );
15472
15475
 
@@ -15485,7 +15488,7 @@ RED.h = handlers;
15485
15488
  }
15486
15489
  }
15487
15490
  })
15488
-
15491
+
15489
15492
  vis.on('contextmenu', d3.contextMenu('canvas', menuCanvas, () => { zoomZero() }));
15490
15493
 
15491
15494
  var outer_background = vis
@@ -15554,13 +15557,13 @@ RED.h = handlers;
15554
15557
  var contextMenuLayer = vis.append('g');
15555
15558
  // add the context menu placeholder for the canvas
15556
15559
  contextMenuLayer
15557
- .append('foreignObject')
15558
- .attr('id', `d3-context-menu-canvas`)
15559
- .attr('class', `d3-context-menu-canvas d3-context-menu`)
15560
- .attr('width', 350)
15561
- .attr('height', 100)
15562
- .attr('x', 100)
15563
- .attr('y', 100)
15560
+ .append('foreignObject')
15561
+ .attr('id', `d3-context-menu-canvas`)
15562
+ .attr('class', `d3-context-menu-canvas d3-context-menu`)
15563
+ .attr('width', 350)
15564
+ .attr('height', 100)
15565
+ .attr('x', 100)
15566
+ .attr('y', 100)
15564
15567
 
15565
15568
  var drag_lines = [];
15566
15569
 
@@ -15685,7 +15688,7 @@ RED.h = handlers;
15685
15688
  zoomIn();
15686
15689
  });
15687
15690
 
15688
- $('#btn-minimize-restore').click( ()=> {
15691
+ $('#btn-minimize-restore').click(() => {
15689
15692
  if (scaleFactor === 1) {
15690
15693
  scaleFactor = 0.6;
15691
15694
  } else {
@@ -15694,7 +15697,7 @@ RED.h = handlers;
15694
15697
  zoomView(scaleFactor);
15695
15698
  });
15696
15699
 
15697
- $('#btn-layouter').click(function(){
15700
+ $('#btn-layouter').click(function () {
15698
15701
  applyLayout();
15699
15702
  });
15700
15703
 
@@ -15722,28 +15725,28 @@ RED.h = handlers;
15722
15725
 
15723
15726
  // Handle dragging the workspace
15724
15727
  $('#chart')
15725
- .keydown(function(e){
15726
- if(e.keyCode == 32) {
15728
+ .keydown(function (e) {
15729
+ if (e.keyCode == 32) {
15727
15730
  e.preventDefault();
15728
15731
  if (!drag) {
15729
15732
  drag = true;
15730
- $('#chart').attr('style','cursor: grab !important')
15733
+ $('#chart').attr('style', 'cursor: grab !important')
15731
15734
  }
15732
15735
  }
15733
15736
  })
15734
- .keyup(function(e){
15735
- if(e.keyCode == 32 && drag){
15736
- e.preventDefault();
15737
- drag = false;
15738
- dragging = false;
15739
- $('#chart').attr('style','cursor: default !important')
15740
- }
15737
+ .keyup(function (e) {
15738
+ if (e.keyCode == 32 && drag) {
15739
+ e.preventDefault();
15740
+ drag = false;
15741
+ dragging = false;
15742
+ $('#chart').attr('style', 'cursor: default !important')
15743
+ }
15741
15744
  })
15742
- .on("mousedown", function(e) {
15745
+ .on("mousedown", function (e) {
15743
15746
  if (drag && !dragging) {
15744
15747
  e.preventDefault();
15745
-
15746
- $('#chart').attr('style','cursor: grabbing !important')
15748
+
15749
+ $('#chart').attr('style', 'cursor: grabbing !important')
15747
15750
  dragging = true;
15748
15751
  draggingPos = {
15749
15752
  // The current scroll
@@ -15755,27 +15758,27 @@ RED.h = handlers;
15755
15758
  }
15756
15759
  })
15757
15760
 
15758
- .on("mouseup", function(e) {
15759
- if (drag && dragging){
15761
+ .on("mouseup", function (e) {
15762
+ if (drag && dragging) {
15760
15763
  e.preventDefault();
15761
15764
  dragging = false;
15762
15765
  // console.log('Dragging off')
15763
- $('#chart').attr('style','cursor: grab !important')
15766
+ $('#chart').attr('style', 'cursor: grab !important')
15764
15767
  }
15765
-
15768
+
15766
15769
  })
15767
15770
 
15768
- .on("mousemove", function(e) {
15769
- if (drag && dragging){
15770
- e.preventDefault();
15771
-
15772
- // How far the mouse has been moved
15773
- const dx = e.clientX - draggingPos.x;
15774
- const dy = e.clientY - draggingPos.y;
15775
-
15776
- $("#chart").scrollLeft(draggingPos.left - dx);
15777
- $("#chart").scrollTop(draggingPos.top - dy);
15778
- }
15771
+ .on("mousemove", function (e) {
15772
+ if (drag && dragging) {
15773
+ e.preventDefault();
15774
+
15775
+ // How far the mouse has been moved
15776
+ const dx = e.clientX - draggingPos.x;
15777
+ const dy = e.clientY - draggingPos.y;
15778
+
15779
+ $("#chart").scrollLeft(draggingPos.left - dx);
15780
+ $("#chart").scrollTop(draggingPos.top - dy);
15781
+ }
15779
15782
  });
15780
15783
 
15781
15784
 
@@ -15925,10 +15928,10 @@ RED.h = handlers;
15925
15928
  scale =
15926
15929
  0.4 -
15927
15930
  0.2 *
15928
- Math.max(
15929
- 0,
15930
- (node_width - Math.min(Math.abs(dx), Math.abs(dy))) / node_width
15931
- );
15931
+ Math.max(
15932
+ 0,
15933
+ (node_width - Math.min(Math.abs(dx), Math.abs(dy))) / node_width
15934
+ );
15932
15935
  }
15933
15936
  if (dx * sc > 0) {
15934
15937
  return (
@@ -16188,10 +16191,10 @@ RED.h = handlers;
16188
16191
  .attr(
16189
16192
  'transform',
16190
16193
  'translate(' +
16191
- (point[0] - node_width / 2) +
16192
- ',' +
16193
- (point[1] - node_height / 2) +
16194
- ')'
16194
+ (point[0] - node_width / 2) +
16195
+ ',' +
16196
+ (point[1] - node_height / 2) +
16197
+ ')'
16195
16198
  );
16196
16199
  ghostNode
16197
16200
  .append('rect')
@@ -16481,10 +16484,10 @@ RED.h = handlers;
16481
16484
  ghostNode.attr(
16482
16485
  'transform',
16483
16486
  'translate(' +
16484
- (point[0] - node_width / 2) +
16485
- ',' +
16486
- (point[1] - node_height / 2) +
16487
- ')'
16487
+ (point[0] - node_width / 2) +
16488
+ ',' +
16489
+ (point[1] - node_height / 2) +
16490
+ ')'
16488
16491
  );
16489
16492
  rebuildQuickAddLink();
16490
16493
  } else {
@@ -16499,7 +16502,7 @@ RED.h = handlers;
16499
16502
  redraw();
16500
16503
  }
16501
16504
  }
16502
-
16505
+
16503
16506
  // console.log('[view] Create a lasso.... mouse_mode = ', mouse_mode);
16504
16507
  // console.log('[view] Create a lasso....d3.event.ctrlKey = ', d3.event.ctrlKey);
16505
16508
 
@@ -17172,27 +17175,27 @@ RED.h = handlers;
17172
17175
  }
17173
17176
  return value;
17174
17177
  });
17175
-
17176
-
17177
- if (ignoreEdit){
17178
+
17179
+
17180
+ if (ignoreEdit) {
17178
17181
  // This is used during the hovering over the debug traces
17179
17182
  lastSelection = selectionJSON;
17180
17183
  // console.log('[view] the selection should not be edited');
17181
- }else{
17184
+ } else {
17182
17185
  if (selectionJSON !== lastSelection) {
17183
17186
  lastSelection = selectionJSON;
17184
17187
  RED.editor.edit(selection);
17185
- }else{
17188
+ } else {
17186
17189
  // User has clicked on the canvas or link
17187
17190
  // console.log('[view::updateSelection] Selection has not changed. Ignore');
17188
-
17191
+
17189
17192
  // Just close the sidebar
17190
17193
  RED.editor.resetEditor();
17191
17194
  }
17192
17195
  }
17193
17196
  }
17194
17197
 
17195
-
17198
+
17196
17199
  function editSelection() {
17197
17200
  // console.log('[view] editSelection invoked')
17198
17201
  if (moving_set.length > 0) {
@@ -17755,9 +17758,9 @@ RED.h = handlers;
17755
17758
  } catch (err) {
17756
17759
  console.log(
17757
17760
  'Definition error: ' +
17758
- node.type +
17759
- '.' +
17760
- (portType === PORT_TYPE_INPUT ? 'inputLabels' : 'outputLabels'),
17761
+ node.type +
17762
+ '.' +
17763
+ (portType === PORT_TYPE_INPUT ? 'inputLabels' : 'outputLabels'),
17761
17764
  err
17762
17765
  );
17763
17766
  result = null;
@@ -17768,7 +17771,7 @@ RED.h = handlers;
17768
17771
  return result;
17769
17772
  }
17770
17773
  function showTooltip(x, y, content, direction) {
17771
- if (!content){
17774
+ if (!content) {
17772
17775
  return;
17773
17776
  }
17774
17777
 
@@ -17870,7 +17873,7 @@ RED.h = handlers;
17870
17873
  (mouse_mode != RED.state.JOINING &&
17871
17874
  mouse_mode != RED.state.QUICK_JOINING) || // Not currently joining - all ports active
17872
17875
  (drag_lines.length > 0 && // Currently joining
17873
- drag_lines[0].portType !== portType && // INPUT->OUTPUT OUTPUT->INPUT
17876
+ drag_lines[0].portType !== portType && // INPUT->OUTPUT OUTPUT->INPUT
17874
17877
  (!drag_lines[0].virtualLink || // Not a link wire
17875
17878
  (drag_lines[0].node.type === 'link in' && d.type === 'link out') ||
17876
17879
  (drag_lines[0].node.type === 'link out' && d.type === 'link in')));
@@ -17930,8 +17933,8 @@ RED.h = handlers;
17930
17933
  ? 1
17931
17934
  : 0
17932
17935
  : d.direction == 'in'
17933
- ? 0
17934
- : 1;
17936
+ ? 0
17937
+ : 1;
17935
17938
  var wasJoining = false;
17936
17939
  if (
17937
17940
  mouse_mode === RED.state.JOINING ||
@@ -18241,7 +18244,7 @@ RED.h = handlers;
18241
18244
  }
18242
18245
  }
18243
18246
 
18244
- async function redrawBreakpoint(node){
18247
+ async function redrawBreakpoint(node) {
18245
18248
  let resp = await window.__kumologica.debugger.isBreakpointFound(node.id);
18246
18249
  let breakpointFound = resp.body;
18247
18250
  if (breakpointFound) {
@@ -18257,15 +18260,15 @@ RED.h = handlers;
18257
18260
  let bpids = resp.body;
18258
18261
 
18259
18262
  activeNodes
18260
- .filter(node => node.z === 'main.flow')
18261
- .forEach(node => {
18262
- node.dirty = true;
18263
- if (bpids.includes(node.id)) {
18264
- node.status = { fill: "red", shape: "dot" };
18265
- } else {
18266
- node.status = {};
18267
- }
18268
- });
18263
+ .filter(node => node.z === 'main.flow')
18264
+ .forEach(node => {
18265
+ node.dirty = true;
18266
+ if (bpids.includes(node.id)) {
18267
+ node.status = { fill: "red", shape: "dot" };
18268
+ } else {
18269
+ node.status = {};
18270
+ }
18271
+ });
18269
18272
  }
18270
18273
 
18271
18274
  function redraw(focusActivated) {
@@ -18617,7 +18620,7 @@ RED.h = handlers;
18617
18620
 
18618
18621
  return d.id;
18619
18622
  });
18620
-
18623
+
18621
18624
  node.exit().remove();
18622
18625
 
18623
18626
  var nodeEnter = node
@@ -18631,7 +18634,7 @@ RED.h = handlers;
18631
18634
  return d.type === 'link in' || d.type === 'link out';
18632
18635
  })
18633
18636
 
18634
-
18637
+
18635
18638
  nodeEnter.each(function (d, i) {
18636
18639
  var node = d3.select(this);
18637
18640
  var isLink = d.type === 'link in' || d.type === 'link out';
@@ -18778,23 +18781,23 @@ RED.h = handlers;
18778
18781
  let infoTooltipTimeout;
18779
18782
  let infoTooltipHover;
18780
18783
  node
18781
- .on('mouseover', function(d){
18782
- infoTooltipTimeout = setTimeout(
18783
- ()=> {
18784
- var pos = getElementPosition(node.node());
18785
- infoTooltipHover = showTooltip(pos[0] + 46, pos[1] + 10, d.info, 'right')
18786
- }, 200
18787
- )
18788
- })
18789
- .on('mouseout', function (d) {
18790
- clearTimeout(infoTooltipTimeout);
18791
- if (infoTooltipHover) {
18792
- infoTooltipHover.remove();
18793
- infoTooltipHover = null;
18794
- }
18795
- let tooltipEl = d3.select(this);
18796
- tooltipEl.classed('port_hovered', false);
18797
- })
18784
+ .on('mouseover', function (d) {
18785
+ infoTooltipTimeout = setTimeout(
18786
+ () => {
18787
+ var pos = getElementPosition(node.node());
18788
+ infoTooltipHover = showTooltip(pos[0] + 46, pos[1] + 10, d.info, 'right')
18789
+ }, 200
18790
+ )
18791
+ })
18792
+ .on('mouseout', function (d) {
18793
+ clearTimeout(infoTooltipTimeout);
18794
+ if (infoTooltipHover) {
18795
+ infoTooltipHover.remove();
18796
+ infoTooltipHover = null;
18797
+ }
18798
+ let tooltipEl = d3.select(this);
18799
+ tooltipEl.classed('port_hovered', false);
18800
+ })
18798
18801
 
18799
18802
 
18800
18803
  var selectionRect = node
@@ -18804,7 +18807,7 @@ RED.h = handlers;
18804
18807
  .attr('height', 100)
18805
18808
  .attr('height', 100)
18806
18809
  .attr('stroke', '#1890ff')
18807
- .attr('fill', '#e6f7ff')
18810
+ .attr('fill', '#e6f7ff')
18808
18811
  .attr('stroke-width', 2)
18809
18812
  .attr('opacity', 0.4)
18810
18813
  .attr('rx', 2)
@@ -19039,9 +19042,9 @@ RED.h = handlers;
19039
19042
  {
19040
19043
  title: 'Toggle Breakpoint',
19041
19044
  disabled: d._def.hasOwnProperty('disableToggleBreakpoint'),
19042
- action: async function(elm, d, i) {
19043
- let disabledFlagOn = d._def.hasOwnProperty('disableToggleBreakpoint');
19044
- if (!disabledFlagOn || (disabledFlagOn && d._def.disableToggleBreakpoint === false)){
19045
+ action: async function (elm, d, i) {
19046
+ let disabledFlagOn = d._def.hasOwnProperty('disableToggleBreakpoint');
19047
+ if (!disabledFlagOn || (disabledFlagOn && d._def.disableToggleBreakpoint === false)) {
19045
19048
  await window.__kumologica.debugger.toggleBreakpoint(d.id);
19046
19049
  await redrawBreakpoint(d);
19047
19050
  redraw();
@@ -19052,13 +19055,13 @@ RED.h = handlers;
19052
19055
  {
19053
19056
  title: 'Cut',
19054
19057
  shortcut: 'Ctrl+X',
19055
- action: async function(elm, d, i, ctx) {
19058
+ action: async function (elm, d, i, ctx) {
19056
19059
  if (ctx && ctx.nodes) {
19057
19060
  RED.view.select(ctx.nodes.map(n => n.id));
19058
19061
  } else {
19059
19062
  RED.view.select(d.id);
19060
19063
  }
19061
-
19064
+
19062
19065
  copySelection();
19063
19066
  deleteSelection();
19064
19067
  }
@@ -19066,7 +19069,7 @@ RED.h = handlers;
19066
19069
  {
19067
19070
  title: 'Copy',
19068
19071
  shortcut: 'Ctrl+C',
19069
- action: async function(elm, d, i, ctx) {
19072
+ action: async function (elm, d, i, ctx) {
19070
19073
  if (ctx && ctx.nodes) {
19071
19074
  RED.view.select(ctx.nodes.map(n => n.id));
19072
19075
  } else {
@@ -19085,7 +19088,7 @@ RED.h = handlers;
19085
19088
  {
19086
19089
  title: 'Delete',
19087
19090
  shortcut: 'Del',
19088
- action: async function(elm, d, i, ctx) {
19091
+ action: async function (elm, d, i, ctx) {
19089
19092
  if (ctx && ctx.nodes) {
19090
19093
  RED.view.select(ctx.nodes.map(n => n.id));
19091
19094
  } else {
@@ -19098,20 +19101,20 @@ RED.h = handlers;
19098
19101
  { separator: true },
19099
19102
  {
19100
19103
  title: 'Copy Node ID',
19101
- action: async function(elm, d, i, ctx) {
19102
- if (ctx.nodes.length > 1){
19104
+ action: async function (elm, d, i, ctx) {
19105
+ if (ctx.nodes.length > 1) {
19103
19106
  RED.notify('<strong>Error:</strong> This option requires selecing a single node', 'error');
19104
19107
  return;
19105
19108
  } else {
19106
19109
  RED.clipboard.copyText(d.id);
19107
- RED.notify(`Node ID [ <b>${d.id}</b> ] copied to clipboard`)
19110
+ RED.notify(`Node ID [ <b>${d.id}</b> ] copied to clipboard`)
19108
19111
  }
19109
19112
  }
19110
19113
  },
19111
19114
  {
19112
19115
  title: 'Settings...',
19113
- action: async function(elm, d, i, ctx) {
19114
- if (ctx.nodes.length > 1){
19116
+ action: async function (elm, d, i, ctx) {
19117
+ if (ctx.nodes.length > 1) {
19115
19118
  RED.notify('<strong>Error:</strong> This options requires selecting a single node', 'error');
19116
19119
  return;
19117
19120
  } else {
@@ -19124,15 +19127,15 @@ RED.h = handlers;
19124
19127
  // TODO Javier - prototype to support context menu extensions...
19125
19128
  // =============================================================
19126
19129
  // if there is special context menu for the element, attach it
19127
- if (d._def.hasOwnProperty('oncontextmenu')){
19130
+ if (d._def.hasOwnProperty('oncontextmenu')) {
19128
19131
  let nodeContextMenu = d._def.oncontextmenu.call(this, window) || [];
19129
19132
  menu = [...nodeContextMenu, { separator: true }, ...menu];
19130
19133
  }
19131
19134
 
19132
-
19135
+
19133
19136
 
19134
19137
  let nodeId = d.id.replace('.', '_');
19135
- node.on('contextmenu', d3.contextMenu(nodeId, menu, ()=> {
19138
+ node.on('contextmenu', d3.contextMenu(nodeId, menu, () => {
19136
19139
  console.log('[view] before context menu');
19137
19140
  console.log('[view] selection of nodes:', RED.view.selection());
19138
19141
  zoomZero()
@@ -19166,7 +19169,7 @@ RED.h = handlers;
19166
19169
  .attr('rx', 8)
19167
19170
  .attr('ry', 8)
19168
19171
  .attr('stroke-width', '2');
19169
-
19172
+
19170
19173
  statusLabel = status
19171
19174
  .append('svg:text')
19172
19175
  .attr('class', 'node_status_label')
@@ -19240,17 +19243,17 @@ RED.h = handlers;
19240
19243
  const MEDIUM_HEIGHT = 100;
19241
19244
  const LARGE_HEIGHT = 110;
19242
19245
 
19243
- if (numberOfLinesDesc <= 1){
19246
+ if (numberOfLinesDesc <= 1) {
19244
19247
  selectionHeight = SMALL_HEIGHT;
19245
19248
  } else if (numberOfLinesDesc === 2) {
19246
19249
  selectionHeight = MEDIUM_HEIGHT;
19247
19250
  } else {
19248
19251
  selectionHeight = LARGE_HEIGHT;
19249
19252
  }
19250
-
19251
- thisNode
19253
+
19254
+ thisNode
19252
19255
  .selectAll('.selectionRect')
19253
- .classed('selection_shown', function (d){
19256
+ .classed('selection_shown', function (d) {
19254
19257
  return d.selected;
19255
19258
  })
19256
19259
  .attr('height', selectionHeight);
@@ -19608,7 +19611,7 @@ RED.h = handlers;
19608
19611
  return (
19609
19612
  'M ' +
19610
19613
  ((!d._def.align && d.inputs !== 0 && d.outputs === 0) ||
19611
- 'right' === d._def.align
19614
+ 'right' === d._def.align
19612
19615
  ? 0
19613
19616
  : 30) +
19614
19617
  ' 1 l 0 ' +
@@ -19714,7 +19717,7 @@ RED.h = handlers;
19714
19717
  if (d && d.status && d.status.text) {
19715
19718
  if (typeof d.status.text == 'object') {
19716
19719
  const err = d.status.text;
19717
- errTxt = err.message || err.error || err.errorMessage || JSON.stringify(d.status.text);
19720
+ errTxt = err.message || err.error || err.errorMessage || JSON.stringify(d.status.text);
19718
19721
  } else {
19719
19722
  errTxt = d.status.text;
19720
19723
  }
@@ -19908,21 +19911,21 @@ RED.h = handlers;
19908
19911
  .attr(
19909
19912
  'd',
19910
19913
  'M ' +
19911
- stemLength +
19912
- ' 0 ' +
19913
- 'C ' +
19914
- (stemLength + 1.7 * branchLength) +
19915
- ' ' +
19916
- 0 +
19917
- ' ' +
19918
- (stemLength + 0.1 * branchLength) +
19919
- ' ' +
19920
- y +
19921
- ' ' +
19922
- (stemLength + branchLength * 1.5) +
19923
- ' ' +
19924
- y +
19925
- ' '
19914
+ stemLength +
19915
+ ' 0 ' +
19916
+ 'C ' +
19917
+ (stemLength + 1.7 * branchLength) +
19918
+ ' ' +
19919
+ 0 +
19920
+ ' ' +
19921
+ (stemLength + 0.1 * branchLength) +
19922
+ ' ' +
19923
+ y +
19924
+ ' ' +
19925
+ (stemLength + branchLength * 1.5) +
19926
+ ' ' +
19927
+ y +
19928
+ ' '
19926
19929
  );
19927
19930
  linkG
19928
19931
  .append('svg:path')
@@ -19930,26 +19933,26 @@ RED.h = handlers;
19930
19933
  .attr(
19931
19934
  'd',
19932
19935
  'M ' +
19933
- (stemLength + branchLength * 1.5 + s * (linkWidth + 7)) +
19934
- ' ' +
19935
- (y - 12) +
19936
- ' ' +
19937
- 'h ' +
19938
- -s * linkWidth +
19939
- ' ' +
19940
- 'a 3 3 45 0 ' +
19941
- (s === 1 ? '0' : '1') +
19942
- ' ' +
19943
- s * -3 +
19944
- ' 3 ' +
19945
- 'v 18 ' +
19946
- 'a 3 3 45 0 ' +
19947
- (s === 1 ? '0' : '1') +
19948
- ' ' +
19949
- s * 3 +
19950
- ' 3 ' +
19951
- 'h ' +
19952
- s * linkWidth
19936
+ (stemLength + branchLength * 1.5 + s * (linkWidth + 7)) +
19937
+ ' ' +
19938
+ (y - 12) +
19939
+ ' ' +
19940
+ 'h ' +
19941
+ -s * linkWidth +
19942
+ ' ' +
19943
+ 'a 3 3 45 0 ' +
19944
+ (s === 1 ? '0' : '1') +
19945
+ ' ' +
19946
+ s * -3 +
19947
+ ' 3 ' +
19948
+ 'v 18 ' +
19949
+ 'a 3 3 45 0 ' +
19950
+ (s === 1 ? '0' : '1') +
19951
+ ' ' +
19952
+ s * 3 +
19953
+ ' 3 ' +
19954
+ 'h ' +
19955
+ s * linkWidth
19953
19956
  );
19954
19957
  linkG
19955
19958
  .append('svg:path')
@@ -19957,20 +19960,20 @@ RED.h = handlers;
19957
19960
  .attr(
19958
19961
  'd',
19959
19962
  'M ' +
19960
- (stemLength + branchLength * 1.5 + s * (linkWidth + 10)) +
19961
- ' ' +
19962
- (y - 12) +
19963
- ' ' +
19964
- 'h ' +
19965
- s * (linkWidth * 3) +
19966
- ' ' +
19967
- 'M ' +
19968
- (stemLength + branchLength * 1.5 + s * (linkWidth + 10)) +
19969
- ' ' +
19970
- (y + 12) +
19971
- ' ' +
19972
- 'h ' +
19973
- s * (linkWidth * 3)
19963
+ (stemLength + branchLength * 1.5 + s * (linkWidth + 10)) +
19964
+ ' ' +
19965
+ (y - 12) +
19966
+ ' ' +
19967
+ 'h ' +
19968
+ s * (linkWidth * 3) +
19969
+ ' ' +
19970
+ 'M ' +
19971
+ (stemLength + branchLength * 1.5 + s * (linkWidth + 10)) +
19972
+ ' ' +
19973
+ (y + 12) +
19974
+ ' ' +
19975
+ 'h ' +
19976
+ s * (linkWidth * 3)
19974
19977
  )
19975
19978
  .style('stroke-dasharray', '12 3 8 4 3');
19976
19979
  linkG
@@ -20069,11 +20072,11 @@ RED.h = handlers;
20069
20072
  }
20070
20073
  }
20071
20074
 
20072
- function filterWorkspaces(newNodesStr){
20075
+ function filterWorkspaces(newNodesStr) {
20073
20076
  try {
20074
20077
  let newNodes = JSON.parse(newNodesStr);
20075
- if (newNodes && Array.isArray(newNodes)){
20076
- return newNodes.filter( e => (e.hasOwnProperty('type') && (e.type !== 'tab')) );
20078
+ if (newNodes && Array.isArray(newNodes)) {
20079
+ return newNodes.filter(e => (e.hasOwnProperty('type') && (e.type !== 'tab')));
20077
20080
  } else {
20078
20081
  return newNodes;
20079
20082
  }
@@ -20091,7 +20094,6 @@ RED.h = handlers;
20091
20094
  * - attached to mouse for placing - "IMPORT_DRAGGING"
20092
20095
  */
20093
20096
  function importNodes(newNodesStr, addNewFlow, touchImport) {
20094
- // Kumologica only has two flows: main and test, so never create a new flow
20095
20097
  addNewFlow = false;
20096
20098
  try {
20097
20099
  // Strip the newNodesStr from workspaces elements
@@ -20355,7 +20357,7 @@ RED.h = handlers;
20355
20357
 
20356
20358
  function applyLayout() {
20357
20359
  const NODE_SIZE = 45;
20358
- let ns = [];
20360
+ let ns = [];
20359
20361
 
20360
20362
  const dagre = window.__kumologica.libs.dagre;
20361
20363
  // Get all active nodes
@@ -20365,14 +20367,14 @@ RED.h = handlers;
20365
20367
  let g = new dagre.graphlib.Graph();
20366
20368
 
20367
20369
  // Set an object for the graph label
20368
- g.setGraph({rankdir: "LR", nodesep: 50, marginx: 50, marginy: 50 });
20370
+ g.setGraph({ rankdir: "LR", nodesep: 50, marginx: 50, marginy: 50 });
20369
20371
 
20370
20372
  // Default to assigning a new object as a label for each new edge.
20371
- g.setDefaultEdgeLabel(function() { return {}; });
20373
+ g.setDefaultEdgeLabel(function () { return {}; });
20372
20374
 
20373
20375
  // Create nodes for the graph
20374
20376
  nodes.forEach(n => {
20375
- g.setNode(n.id, {label: n.name, width: NODE_SIZE, height: NODE_SIZE })
20377
+ g.setNode(n.id, { label: n.name, width: NODE_SIZE, height: NODE_SIZE })
20376
20378
  });
20377
20379
 
20378
20380
  // Create the edges
@@ -20384,7 +20386,7 @@ RED.h = handlers;
20384
20386
  dagre.layout(g);
20385
20387
 
20386
20388
  // Apply the coordinates
20387
- g.nodes().forEach(nid=> {
20389
+ g.nodes().forEach(nid => {
20388
20390
  if (nid) {
20389
20391
  let node = nodes.find(n => n.id === nid);
20390
20392
  if (node) {
@@ -20435,7 +20437,7 @@ RED.h = handlers;
20435
20437
  if (node._def.category !== 'config' && node.z) {
20436
20438
  node.dirty = true;
20437
20439
  RED.workspaces.show(node.z);
20438
-
20440
+
20439
20441
  var screenSize = [
20440
20442
  chart.width() / scaleFactor,
20441
20443
  chart.height() / scaleFactor,
@@ -20444,7 +20446,7 @@ RED.h = handlers;
20444
20446
  chart.scrollLeft() / scaleFactor,
20445
20447
  chart.scrollTop() / scaleFactor,
20446
20448
  ];
20447
-
20449
+
20448
20450
  if (
20449
20451
  node.x < scrollPos[0] ||
20450
20452
  node.y < scrollPos[1] ||
@@ -20465,7 +20467,7 @@ RED.h = handlers;
20465
20467
  }
20466
20468
  }
20467
20469
  }
20468
- // ----
20470
+ // ----
20469
20471
 
20470
20472
  if (selectedNode) {
20471
20473
  selectedNode.selected = true;
@@ -20475,21 +20477,21 @@ RED.h = handlers;
20475
20477
  }
20476
20478
  if (Array.isArray(selection)) {
20477
20479
  console.log('[view] selection pre=', selection);
20478
- let selectionNodes =
20479
- (selection.length === 0)?
20480
- RED.nodes.filterNodes({ z: 'main.flow'}): RED.nodes.filterNodes({ id: selection });
20480
+ let selectionNodes =
20481
+ (selection.length === 0) ?
20482
+ RED.nodes.filterNodes({ z: 'main.flow' }) : RED.nodes.filterNodes({ id: selection });
20481
20483
 
20482
20484
  console.log('[view] selection nodes=', selectionNodes);
20483
- if (selectionNodes && Array.isArray(selectionNodes)){
20485
+ if (selectionNodes && Array.isArray(selectionNodes)) {
20484
20486
  moving_set = [];
20485
20487
  selectionNodes.forEach(sn => {
20486
20488
  sn.selected = true;
20487
20489
  sn.dirty = true;
20488
- moving_set.push({n: sn})
20490
+ moving_set.push({ n: sn })
20489
20491
  })
20490
20492
  }
20491
-
20492
-
20493
+
20494
+
20493
20495
  }
20494
20496
  } else {
20495
20497
  clearSelection();
@@ -20566,7 +20568,7 @@ RED.h = handlers;
20566
20568
  200
20567
20569
  );
20568
20570
  }
20569
-
20571
+
20570
20572
  if (!node._flashing) {
20571
20573
  node._flashing = true;
20572
20574
  var flash = 22;
@@ -20600,11 +20602,11 @@ RED.h = handlers;
20600
20602
  getActiveNodes: function () {
20601
20603
  return activeNodes;
20602
20604
  },
20603
- getActiveLinks: function() {
20605
+ getActiveLinks: function () {
20604
20606
  return activeLinks;
20605
20607
  },
20606
20608
  showTooltip: showTooltip,
20607
- applyLayout:applyLayout
20609
+ applyLayout: applyLayout
20608
20610
  };
20609
20611
  })();
20610
20612
  ;/**
@@ -20920,9 +20922,9 @@ RED.view.tools = (function() {
20920
20922
  $(tab.toolbar).show();
20921
20923
  }
20922
20924
  }
20923
-
20925
+
20924
20926
  },
20925
- onsame: function (tab){
20927
+ onsame: function (tab) {
20926
20928
  if (tab.onsame) {
20927
20929
  tab.onsame.call(tab);
20928
20930
  }
@@ -21027,16 +21029,16 @@ RED.view.tools = (function() {
21027
21029
  let d = ui.position.left;
21028
21030
  delta = sidebarWidthP0 - d;
21029
21031
  $('#sidebar').width(delta);
21030
- if ($('#sidebar').width() > maxWidthSidebar()){
21032
+ if ($('#sidebar').width() > maxWidthSidebar()) {
21031
21033
  $('#sidebar').width(maxWidthSidebar());
21032
21034
  }
21033
21035
  event.stopImmediatePropagation();
21034
21036
  RED.events.emit('sidebar:resize');
21035
21037
  },
21036
21038
  stop: function (event, ui) {
21037
- setTimeout(function() {
21039
+ setTimeout(function () {
21038
21040
  sidebarDragging = false;
21039
- },1000);
21041
+ }, 1000);
21040
21042
  RED.events.emit('sidebar:resize');
21041
21043
  },
21042
21044
  });
@@ -21060,10 +21062,10 @@ RED.view.tools = (function() {
21060
21062
  return totalWidth - shortcutsWidth - paletteWidth - sidebarSeparatorWidth;
21061
21063
  }
21062
21064
 
21063
- function maximizeSidebar(){
21065
+ function maximizeSidebar() {
21064
21066
  const targetWidth = maxWidthSidebar();
21065
21067
  $('#sidebar').width(targetWidth);
21066
-
21068
+
21067
21069
  // Hack: Make sure the workspace if reset before maximizing the sidebar. This is because when dragging the sidebar the workspace width is also modified
21068
21070
  $('#workspace').css('right', 485);
21069
21071
  RED.events.emit('sidebar:resize');
@@ -21078,7 +21080,7 @@ RED.view.tools = (function() {
21078
21080
  }
21079
21081
 
21080
21082
  function isSidebarVisible() {
21081
- return ! $('#main-container').hasClass('sidebar-closed');
21083
+ return !$('#main-container').hasClass('sidebar-closed');
21082
21084
  }
21083
21085
 
21084
21086
  function toggleSidebar(state) {
@@ -21089,7 +21091,7 @@ RED.view.tools = (function() {
21089
21091
  $('#main-container').addClass('sidebar-closed');
21090
21092
  $('#shelve-right').removeClass('shelf-selected');
21091
21093
  } else {
21092
- if (!$('#shelve-right').hasClass('shelf-selected')){
21094
+ if (!$('#shelve-right').hasClass('shelf-selected')) {
21093
21095
  checkIfscrollWorkspaceRequired = true;
21094
21096
  }
21095
21097
  // Show the sidebar and sidebar-separator
@@ -21099,7 +21101,7 @@ RED.view.tools = (function() {
21099
21101
  sidebar_tabs.resize();
21100
21102
  }
21101
21103
  RED.events.emit('sidebar:resize');
21102
- if (checkIfscrollWorkspaceRequired && RED.editor.getLatestNodeSelected()){
21104
+ if (checkIfscrollWorkspaceRequired && RED.editor.getLatestNodeSelected()) {
21103
21105
  // Reposition the workspace if the node may be left hidden behind the sidebar
21104
21106
  const safeDistNodeSidebar = 300;
21105
21107
  let nodeSelectedPosX = RED.editor.getLatestNodeSelected().x;
@@ -21111,9 +21113,9 @@ RED.view.tools = (function() {
21111
21113
  // - sidebarPosLeftX: ${sidebarPosLeftX}
21112
21114
  // ----------------------------------------
21113
21115
  // `);
21114
- if (nodeSelectedPosX - initialScrollLeft + safeDistNodeSidebar > sidebarPosLeftX ){
21115
- let targetScrollLeft = nodeSelectedPosX - sidebarPosLeftX + safeDistNodeSidebar;
21116
- $('#chart').animate( { scrollLeft: targetScrollLeft})
21116
+ if (nodeSelectedPosX - initialScrollLeft + safeDistNodeSidebar > sidebarPosLeftX) {
21117
+ let targetScrollLeft = nodeSelectedPosX - sidebarPosLeftX + safeDistNodeSidebar;
21118
+ $('#chart').animate({ scrollLeft: targetScrollLeft })
21117
21119
  }
21118
21120
  }
21119
21121
  }
@@ -21135,7 +21137,7 @@ RED.view.tools = (function() {
21135
21137
  return sidebar_tabs.contains(id);
21136
21138
  }
21137
21139
 
21138
- function deselectAll(){
21140
+ function deselectAll() {
21139
21141
  // Deselect the shortcut icon
21140
21142
  let selectedTab = $('.sidebar-shortcuts-icons').find('a.active');
21141
21143
  selectedTab.each(function () {
@@ -21153,11 +21155,11 @@ RED.view.tools = (function() {
21153
21155
 
21154
21156
  }
21155
21157
 
21156
- function selectTab(index){
21158
+ function selectTab(index) {
21157
21159
  let selectedTab = $('#sidebar-shortcuts').find('.sidebar-shortcuts-icons').children()[index];
21158
21160
  // Click only if has not been selected
21159
21161
  // console.log('[sidebar] selectedTab.hasClass(selected)=', selectedTab.hasClass('selected'));
21160
- if (!$(selectedTab).hasClass('selected')){
21162
+ if (!$(selectedTab).hasClass('selected')) {
21161
21163
  $(selectedTab).click();
21162
21164
  }
21163
21165
  }
@@ -21171,29 +21173,29 @@ RED.view.tools = (function() {
21171
21173
  }
21172
21174
  });
21173
21175
 
21174
- RED.actions.add('core:show-sidebar', function(e){
21176
+ RED.actions.add('core:show-sidebar', function (e) {
21175
21177
  //show the sidebar
21176
21178
  toggleSidebar(true);
21177
21179
 
21178
21180
  //show the sidebar-separator
21179
21181
  // let sidebarSeparator = $('#sidebar-separator');
21180
21182
  // sidebarSeparator.show();
21181
-
21183
+
21182
21184
  // Select internally the tab
21183
- if (e && e.hasOwnProperty('selectIndex')){
21184
- selectTab(e.selectIndex);
21185
+ if (e && e.hasOwnProperty('selectIndex')) {
21186
+ selectTab(e.selectIndex);
21185
21187
  }
21186
21188
  });
21187
21189
 
21188
- RED.actions.add('core:hide-sidebar', function(){
21189
- if (!sidebarDragging){
21190
+ RED.actions.add('core:hide-sidebar', function () {
21191
+ if (!sidebarDragging) {
21190
21192
  toggleSidebar(false);
21191
21193
  deselectAll();
21192
- }else {
21194
+ } else {
21193
21195
  console.log('[sidebar] Ignoring hide-sidebar as dragging is still enabled')
21194
21196
  }
21195
21197
  });
21196
-
21198
+
21197
21199
  // RED.popover.tooltip(
21198
21200
  // $('#sidebar-separator').find('.sidebar-control-right'),
21199
21201
  // RED._('keyboard.toggleSidebar'),
@@ -21210,6 +21212,8 @@ RED.view.tools = (function() {
21210
21212
  RED.sidebar.azure.init();
21211
21213
  RED.sidebar.awsDeploy.init();
21212
21214
 
21215
+ // RED.sidebar.ai.init();
21216
+
21213
21217
 
21214
21218
 
21215
21219
  // hide info bar at start if screen rather narrow...
@@ -22477,6 +22481,8 @@ RED.view.tools = (function() {
22477
22481
  return;
22478
22482
  }
22479
22483
 
22484
+ console.log(`attaching data list for ${serviceType} ${itemId} ${dataListId}`);
22485
+
22480
22486
  $(`#${dataListId}`).empty();
22481
22487
  try {
22482
22488
  let services = await window.__kumologica.cloud.listServices(serviceType);
@@ -22493,6 +22499,7 @@ RED.view.tools = (function() {
22493
22499
  $('<option>').attr('value', item.id).text(item.name)
22494
22500
  );
22495
22501
  });
22502
+
22496
22503
  $(`#${itemId}`).attr('list', dataListId);
22497
22504
 
22498
22505
  $(itemId).change(function () {
@@ -22528,6 +22535,27 @@ RED.view.tools = (function() {
22528
22535
  $(itemId).change(function () {
22529
22536
  saveSettings();
22530
22537
  });
22538
+
22539
+ // api got 2 levels dependency lists
22540
+ if (serviceType === "api") {
22541
+
22542
+ $(itemId).on('input', function() {
22543
+ let id = $(this).val(); // api id
22544
+ alert("Make Ajax call here.2");
22545
+
22546
+ $(`#${dataListId}`).find("option").each(function() {
22547
+ console.log($(this).val() + "<>" + id);
22548
+ if ($(this).val() === id) {
22549
+ // api id has been selected, populate stages and parentIds
22550
+ // find itemId of stage
22551
+ const stageItemId = itemId.replace("-api", "-stage");
22552
+ const parentItemId = itemId.replace("-api", "-parentId");
22553
+ // console.log("stage " + stageItemId + " parnet " + parentItemId);
22554
+ //alert("Make Ajax call here.2");
22555
+ }
22556
+ })
22557
+ })
22558
+ }
22531
22559
  }
22532
22560
  }
22533
22561
 
@@ -22546,6 +22574,7 @@ RED.view.tools = (function() {
22546
22574
  return msg;
22547
22575
  }
22548
22576
 
22577
+ // functions adds trigger definition to the list
22549
22578
  function eventTableHtml(eventSource, values, itemId, dataListId) {
22550
22579
  html = `
22551
22580
  <table id="cloud-fn-event-table" class="node-info" style="table-layout: fixed; padding: 0px; margin: 0px;">
@@ -22557,7 +22586,7 @@ RED.view.tools = (function() {
22557
22586
  </tr>
22558
22587
  </thead>
22559
22588
  <tbody>`;
22560
-
22589
+
22561
22590
  // add parameters
22562
22591
  parameterSets[eventSource].forEach(function (p, i) {
22563
22592
  let placeholder = 'optional';
@@ -22576,7 +22605,7 @@ RED.view.tools = (function() {
22576
22605
  if (p.list) {
22577
22606
  html += `
22578
22607
  <td style="background: white; width:46%">
22579
- <select type="text" class="palette-textinput" id="${itemId}-${i}" style="float: left; width: 100%; padding: 0px; outline: 0px solid #ccc; ">
22608
+ <select type="text" class="palette-textinput" id="${itemId}-${p.key}" style="float: left; width: 100%; padding: 0px; outline: 0px solid #ccc; ">
22580
22609
  `;
22581
22610
  $.each(p.list, function () {
22582
22611
  if (values && this.v == values[p.key]) {
@@ -22591,7 +22620,7 @@ RED.view.tools = (function() {
22591
22620
  } else if (p.function) {
22592
22621
  html += `
22593
22622
  <td style="background: white; width:46%">
22594
- <input id="${itemId}-${i}"
22623
+ <input id="${itemId}-${p.key}"
22595
22624
  class="palette-textinput" type="text"
22596
22625
  list="${dataListId}"
22597
22626
  placeholder="required" style="width:100%"
@@ -22606,7 +22635,7 @@ RED.view.tools = (function() {
22606
22635
  } else {
22607
22636
  html += `
22608
22637
  <td style="background: white; width:46%">
22609
- <input id="${itemId}-${i}" class="palette-textinput" type="text" placeholder="${placeholder}" style="width:100%" value="${
22638
+ <input id="${itemId}-${p.key}" class="palette-textinput" type="text" placeholder="${placeholder}" style="width:100%" value="${
22610
22639
  values == undefined || values[p.key] == undefined ? '' : values[p.key]
22611
22640
  }" ${requiredAttribute}>
22612
22641
  </td>
@@ -23290,7 +23319,7 @@ RED.view.tools = (function() {
23290
23319
  ];
23291
23320
  parameterSets['websocket'] = [
23292
23321
  {
23293
- label: 'ApiId',
23322
+ label: 'Api Id',
23294
23323
  key: 'apiId',
23295
23324
  value: '',
23296
23325
  required: true,
@@ -24314,7 +24343,7 @@ RED.sidebar.nodeinfo = (function(){
24314
24343
  init,
24315
24344
  emptyTab
24316
24345
  }
24317
- })();;RED.sidebar.test = (function() {
24346
+ })();;RED.sidebar.test = (function () {
24318
24347
  let editors = {};
24319
24348
 
24320
24349
  // html anchors
@@ -24324,7 +24353,7 @@ RED.sidebar.nodeinfo = (function(){
24324
24353
  let stackContainer;
24325
24354
  let testNodes;
24326
24355
  let triggeredTest; // Flag to indicate when launch a test. As we dont want to launch test for every deployment
24327
-
24356
+
24328
24357
  // control variables
24329
24358
  let testCaseIdSelected; // nodeID | __runall | undefined
24330
24359
  let environmentSelected;
@@ -24339,7 +24368,7 @@ RED.sidebar.nodeinfo = (function(){
24339
24368
 
24340
24369
  function updateTestCaseInit(event, msg) {
24341
24370
  let { testCaseID, testCaseDescription } = msg.payload.testCase;
24342
-
24371
+
24343
24372
  // sanitize the testCaseId, i.e. removing dots as jquery selector does not like it
24344
24373
  let testCaseId = testCaseID.replace(/\./g, '_');
24345
24374
 
@@ -24390,8 +24419,8 @@ RED.sidebar.nodeinfo = (function(){
24390
24419
  })
24391
24420
  .appendTo(testcaseTabs);
24392
24421
 
24393
- // This is the dropzone for content that will be selected in the tabs
24394
- $(`<div class="testcase-info-container">
24422
+ // This is the dropzone for content that will be selected in the tabs
24423
+ $(`<div class="testcase-info-container">
24395
24424
  <div id="testcase-info-response-${testCaseId}" class="testcase-info selected">
24396
24425
  <div style="display: flex; justify-content: flex-end; margin-right: 10px"><span class="testcase-resp-status">Status: </span><span id="testcase-status-${testCaseId}" style="font-size: 12px; color:#2979ff; margin-right: 4px"></span></div>
24397
24426
  <div id="testcase-info-response-header">
@@ -24442,11 +24471,11 @@ RED.sidebar.nodeinfo = (function(){
24442
24471
  });
24443
24472
 
24444
24473
  // Create an editor the the response body
24445
- editors[testCaseId] = RED.editor.createEditor({
24474
+ editors[testCaseId] = RED.editor.createEditor({
24446
24475
  id: `testcase-resp-body-${testCaseId}`,
24447
24476
  lineNumbers: true,
24448
24477
  showFoldWidgets: true,
24449
- mode:"ace/mode/text",
24478
+ mode: "ace/mode/text",
24450
24479
  options: {
24451
24480
  wrap: true
24452
24481
  }
@@ -24456,24 +24485,24 @@ RED.sidebar.nodeinfo = (function(){
24456
24485
  $(`#testcase-info-response-bodyformat-${testCaseId}`).on('change', function (e) {
24457
24486
  var valueSelected = this.value;
24458
24487
  switch (valueSelected) {
24459
- case 'json':
24488
+ case 'json':
24460
24489
  let rjson = editors[testCaseId].getSession().getValue();
24461
24490
  let prjson = JSON.parse(rjson);
24462
24491
  editors[testCaseId].getSession().setValue(JSON.stringify(prjson, null, 2));
24463
- editors[testCaseId].getSession().setMode('ace/mode/json');
24492
+ editors[testCaseId].getSession().setMode('ace/mode/json');
24464
24493
  break;
24465
- case 'xml':
24466
- editors[testCaseId].getSession().setMode('ace/mode/xml');
24494
+ case 'xml':
24495
+ editors[testCaseId].getSession().setMode('ace/mode/xml');
24467
24496
  let vxml = editors[testCaseId].getSession().getValue();
24468
24497
  editors[testCaseId].getSession().setValue(formatXml(vxml));
24469
24498
  break;
24470
- case 'html':
24471
- editors[testCaseId].getSession().setMode('ace/mode/html');
24499
+ case 'html':
24500
+ editors[testCaseId].getSession().setMode('ace/mode/html');
24472
24501
  let vhtml = editors[testCaseId].getSession().getValue();
24473
24502
  editors[testCaseId].getSession().setValue(formatXml(vhtml));
24474
24503
  break;
24475
- default:
24476
- editors[testCaseId].getSession().setMode('ace/mode/text');
24504
+ default:
24505
+ editors[testCaseId].getSession().setMode('ace/mode/text');
24477
24506
  break
24478
24507
  }
24479
24508
  });
@@ -24485,10 +24514,10 @@ RED.sidebar.nodeinfo = (function(){
24485
24514
  })
24486
24515
  });
24487
24516
 
24488
- $(`#testcase-info-copypaste-container-${testCaseId}`).click(e=> {
24517
+ $(`#testcase-info-copypaste-container-${testCaseId}`).click(e => {
24489
24518
  RED.clipboard.copyText(
24490
- editors[testCaseId].getSession().getValue(),
24491
- $(`#testcase-info-copypaste-container-${testCaseId}`),
24519
+ editors[testCaseId].getSession().getValue(),
24520
+ $(`#testcase-info-copypaste-container-${testCaseId}`),
24492
24521
  'Response Copied to Clipboard');
24493
24522
  });
24494
24523
 
@@ -24496,14 +24525,14 @@ RED.sidebar.nodeinfo = (function(){
24496
24525
  }
24497
24526
 
24498
24527
  function formatXml(xml, tab) { // tab = optional indent value, default is tab (\t)
24499
- var formatted = '', indent= '';
24528
+ var formatted = '', indent = '';
24500
24529
  tab = tab || '\t';
24501
- xml.split(/>\s*</).forEach(function(node) {
24502
- if (node.match( /^\/\w/ )) indent = indent.substring(tab.length); // decrease indent by one 'tab'
24503
- formatted += indent + '<' + node + '>\r\n';
24504
- if (node.match( /^<?\w[^>]*[^\/]$/ )) indent += tab; // increase indent
24530
+ xml.split(/>\s*</).forEach(function (node) {
24531
+ if (node.match(/^\/\w/)) indent = indent.substring(tab.length); // decrease indent by one 'tab'
24532
+ formatted += indent + '<' + node + '>\r\n';
24533
+ if (node.match(/^<?\w[^>]*[^\/]$/)) indent += tab; // increase indent
24505
24534
  });
24506
- return formatted.substring(1, formatted.length-3);
24535
+ return formatted.substring(1, formatted.length - 3);
24507
24536
  }
24508
24537
 
24509
24538
  function updateTestCaseStart(event, msg) {
@@ -24525,21 +24554,21 @@ RED.sidebar.nodeinfo = (function(){
24525
24554
 
24526
24555
  }
24527
24556
 
24528
- function convertBodyToString(body){
24557
+ function convertBodyToString(body) {
24529
24558
  let typeBody = typeof body;
24530
24559
 
24531
- if (typeBody === 'object'){
24560
+ if (typeBody === 'object') {
24532
24561
  return JSON.stringify(body, null, 2);
24533
- }else if (typeBody === 'string') {
24562
+ } else if (typeBody === 'string') {
24534
24563
  //return body.replace(/['"]+/g, '');;
24535
24564
  return body;
24536
24565
  } else {
24537
24566
  return ""
24538
24567
  }
24539
-
24568
+
24540
24569
  }
24541
24570
 
24542
- function attachHeaders(headers, testCaseId){
24571
+ function attachHeaders(headers, testCaseId) {
24543
24572
  let headersContainerEl = $(`#testcase-resp-headers-${testCaseId}`);
24544
24573
  for (let header in headers) {
24545
24574
  $(`
@@ -24554,7 +24583,7 @@ RED.sidebar.nodeinfo = (function(){
24554
24583
  }
24555
24584
  }
24556
24585
 
24557
- function changeTabSelection(key, testCaseId){
24586
+ function changeTabSelection(key, testCaseId) {
24558
24587
  // if headers selected, then disable the output format and wrap line option
24559
24588
  if (key === 'headers') {
24560
24589
  $(`#testcase-info-response-bodyformat-container-${testCaseId}`).hide();
@@ -24580,7 +24609,7 @@ RED.sidebar.nodeinfo = (function(){
24580
24609
  $(`#testcase-resp-${key}-${testCaseId}`).addClass('selected');
24581
24610
  }
24582
24611
 
24583
- function selectTestcaseTab(key, testCaseID){
24612
+ function selectTestcaseTab(key, testCaseID) {
24584
24613
  // Reset the tabs
24585
24614
  $(`#testcase-tab-assertion-${testCaseID}`).removeClass('selected');
24586
24615
  $(`#testcase-tab-response-${testCaseID}`).removeClass('selected');
@@ -24605,14 +24634,14 @@ RED.sidebar.nodeinfo = (function(){
24605
24634
  let status = 'passed';
24606
24635
 
24607
24636
  // Check whether the testcase is failed or not ...
24608
- for (let i=0; i < assertionResults.length; i++){
24637
+ for (let i = 0; i < assertionResults.length; i++) {
24609
24638
  if (assertionResults[i].status === 'failed') {
24610
24639
  status = 'failed';
24611
24640
  break;
24612
24641
  }
24613
24642
  }
24614
24643
  // Find the testcase section
24615
- if (status === 'failed'){
24644
+ if (status === 'failed') {
24616
24645
  $(`#section-${testCaseId}`).parent().parent().addClass('failed');
24617
24646
  } else {
24618
24647
  $(`#section-${testCaseId}`).parent().parent().addClass('passed');
@@ -24625,7 +24654,7 @@ RED.sidebar.nodeinfo = (function(){
24625
24654
  let testCaseId = testCaseID.replace(/\./g, '_')
24626
24655
 
24627
24656
  let assertionSectionHtml
24628
- if (status === 'failed'){
24657
+ if (status === 'failed') {
24629
24658
  assertionSectionHtml = `
24630
24659
  <div class="assertion assertion-failed" style="display: flex; flex-direction: column;">
24631
24660
  <div style="display:flex; align-items: center;">
@@ -24643,34 +24672,35 @@ RED.sidebar.nodeinfo = (function(){
24643
24672
  </div>
24644
24673
  `;
24645
24674
  }
24646
-
24675
+
24647
24676
  let testCaseAssertionsContainer = $(`#testcase-info-assertion-${testCaseId}`)
24648
24677
 
24649
24678
  $(assertionSectionHtml).appendTo(testCaseAssertionsContainer);
24650
24679
  testCaseSection.container.show();
24651
24680
  }
24652
24681
 
24653
- function onsame(){
24682
+ function onsame() {
24654
24683
  RED.actions.invoke('core:hide-sidebar');
24655
24684
  }
24656
24685
 
24657
24686
  // Refresh the test tab
24658
24687
  // silently - if true, we will update the nodes if required, but do not show the sidebar. Used primarily for the save button
24659
24688
  function refreshTab(silently) {
24660
- if (!silently){
24689
+ console.log('[tab-test] refreshTab, silently=', silently);
24690
+ if (!silently) {
24661
24691
  RED.actions.invoke('core:show-sidebar');
24662
24692
  }
24663
24693
 
24664
24694
  // Append to the selector all testcases found in the project
24665
24695
  let $testSidebarTestcases = $('#test-sidebar-testcases');
24666
-
24696
+
24667
24697
  // Searching for all testcases in the test.flow node.
24668
24698
  let testcasenodes = App.nodes.filterNodes({ type: 'TestCase' });
24669
24699
  // Searching for all HTTP testcases in the test.flow node.
24670
24700
  let httptestcasenodes = App.nodes.filterNodes({ type: 'HTTPTestCase' });
24671
24701
 
24672
24702
  testNodes = testcasenodes.concat(httptestcasenodes);
24673
-
24703
+
24674
24704
 
24675
24705
  if (testNodes && Array.isArray(testNodes) && testNodes.length > 0) {
24676
24706
  $('#test-sidebar-notestfound-explainer').hide();
@@ -24687,7 +24717,7 @@ RED.sidebar.nodeinfo = (function(){
24687
24717
  );
24688
24718
  $testSidebarTestcases.append(
24689
24719
  `<option value="${RUN_ALL_TEST_CASES}"> Run all TestCases</option>`
24690
- );
24720
+ );
24691
24721
  // Check which option will be selected
24692
24722
  // a) If nothing was selected, select the empty
24693
24723
  if (testCaseIdSelected === undefined || testCaseIdSelected === null) {
@@ -24708,6 +24738,10 @@ RED.sidebar.nodeinfo = (function(){
24708
24738
  $('#test-sidebar-notestfound-explainer').show();
24709
24739
  }
24710
24740
 
24741
+ // Notify the footer about the changes in the testCase dropdown
24742
+ refreshTestCases();
24743
+
24744
+ // Refresh the values of the environments in case there was a change in the config
24711
24745
  refreshEnvironments();
24712
24746
  }
24713
24747
 
@@ -24716,23 +24750,33 @@ RED.sidebar.nodeinfo = (function(){
24716
24750
  if (config) {
24717
24751
  // Preselect the last testCase selected
24718
24752
  testCaseIdSelected = config.getLatestSelectedTestCase();
24719
-
24753
+
24720
24754
  $(`#test-sidebar-testcases option[value="${testCaseIdSelected}"]`).attr(
24721
24755
  'selected',
24722
24756
  true
24723
24757
  );
24758
+
24759
+ let testCaseSelectedName = $('#test-sidebar-testcases option:selected').text()
24760
+ console.log(`[tab-test] refreshTestCases invoked with id=${testCaseIdSelected}`);
24761
+ console.log(`[tab-test] refreshTestCases invoked with name=${testCaseSelectedName}`);
24762
+
24763
+ RED.actions.invoke('test:change-testcase-selected',
24764
+ {
24765
+ id: testCaseIdSelected,
24766
+ name: testCaseSelectedName
24767
+ });
24724
24768
  }
24725
-
24769
+
24726
24770
  }
24727
24771
 
24728
24772
  function refreshEnvironments() {
24729
- let config = window.__kumologica.settings.testConfig;
24773
+ let config = window.__kumologica.settings.testConfig;
24730
24774
  if (config) {
24731
- let environmentsList =config.listEnvironments();
24775
+ let environmentsList = config.listEnvironments();
24732
24776
 
24733
24777
  let $testSidebarEnvironments = $('#test-sidebar-environments');
24734
24778
  $testSidebarEnvironments.empty();
24735
-
24779
+
24736
24780
  // Attach the "no environments" option
24737
24781
  $testSidebarEnvironments.append(
24738
24782
  `<option value="__no_environment__">No Environment</option>`
@@ -24742,7 +24786,7 @@ RED.sidebar.nodeinfo = (function(){
24742
24786
  `<option value=${e}>${e}</option>`
24743
24787
  );
24744
24788
  });
24745
-
24789
+
24746
24790
  // Select the latest environment
24747
24791
  environmentSelected = window.__kumologica.settings.testConfig.getLatestSelectedEnvironment();
24748
24792
  $(`#test-sidebar-environments option[value="${environmentSelected}"]`).attr('selected', true);
@@ -24756,16 +24800,16 @@ RED.sidebar.nodeinfo = (function(){
24756
24800
  * this to keep fake new row at the bottom.
24757
24801
  */
24758
24802
  function refreshProperties() {
24759
- if (window.__kumologica.settings.testConfig){
24803
+ if (window.__kumologica.settings.testConfig) {
24760
24804
  let envvars = window.__kumologica.settings.testConfig.listVariablesByEnvironment();
24761
24805
  // Clean up the table before starting injecting the new variables.
24762
24806
  $('#table-test-properties').empty();
24763
-
24807
+
24764
24808
  envvars.forEach(ev => {
24765
24809
  attachPropertyRow(ev.key, ev.value);
24766
24810
  })
24767
24811
  }
24768
-
24812
+
24769
24813
  }
24770
24814
 
24771
24815
  function init() {
@@ -24782,7 +24826,7 @@ RED.sidebar.nodeinfo = (function(){
24782
24826
  ipcRenderer.on('test:assertion-report', updateTestCaseAssertion);
24783
24827
 
24784
24828
  ipcRenderer.on('debugger:stopped', debuggerStoppedOnBreakpoint);
24785
-
24829
+
24786
24830
 
24787
24831
  // Prepare the html wrappers
24788
24832
  initHtml();
@@ -24799,6 +24843,14 @@ RED.sidebar.nodeinfo = (function(){
24799
24843
  // Attach the change event to the "testcase" select
24800
24844
  $('#test-sidebar-testcases').change(e => {
24801
24845
  testCaseIdSelected = e.target.value;
24846
+ let testCaseSelectedName = $('#test-sidebar-testcases option:selected').text();
24847
+
24848
+ RED.actions.invoke('test:change-testcase-selected',
24849
+ {
24850
+ id: testCaseIdSelected,
24851
+ name: testCaseSelectedName
24852
+ });
24853
+
24802
24854
  saveSettings();
24803
24855
  });
24804
24856
  $('#test-sidebar-environments').change(e => {
@@ -24814,40 +24866,38 @@ RED.sidebar.nodeinfo = (function(){
24814
24866
  });
24815
24867
 
24816
24868
  // Attach debugger events
24817
- $('#test-sidebar-debug-continue').click( async (e)=> {
24869
+ $('#test-sidebar-debug-continue').click(async (e) => {
24818
24870
  await window.__kumologica.debugger.continue()
24819
24871
  });
24820
24872
 
24821
- $('#test-sidebar-debug-terminate').click( async (e)=> {
24873
+ $('#test-sidebar-debug-terminate').click(async (e) => {
24822
24874
  await window.__kumologica.debugger.terminate();
24823
24875
  });
24824
24876
 
24825
- $('#test-sidebar-debug-next').click( async (e)=> {
24877
+ $('#test-sidebar-debug-next').click(async (e) => {
24826
24878
  await window.__kumologica.debugger.next();
24827
24879
  });
24828
24880
 
24829
24881
 
24830
- $('#test-sidebar-debug-restart').click( async (e)=> {
24882
+ $('#test-sidebar-debug-restart').click(async (e) => {
24831
24883
  await window.__kumologica.debugger.terminate();
24832
24884
  // give 1 sec to clean up the tab
24833
- setTimeout(async()=> {
24885
+ setTimeout(async () => {
24834
24886
  await triggerDebugTestSuite();
24835
24887
  }, 500);
24836
24888
  });
24837
24889
 
24838
- RED.events.on('deploy:finished', async()=> {
24839
- if (triggeredTest){
24890
+ RED.events.on('deploy:finished', async () => {
24891
+ if (triggeredTest) {
24840
24892
  await executeTestSuite();
24841
24893
  triggeredTest = false;
24842
24894
  }
24843
24895
  });
24844
24896
 
24845
24897
  // Case where the environment variables config has change
24846
- RED.events.on('settings:environment-variables-changed', ()=> {
24898
+ RED.events.on('settings:environment-variables-changed', () => {
24847
24899
  refreshEnvironments();
24848
24900
  })
24849
-
24850
-
24851
24901
  }
24852
24902
 
24853
24903
  function show() {
@@ -24858,7 +24908,7 @@ RED.sidebar.nodeinfo = (function(){
24858
24908
  $('#test-results-wrapper').empty();
24859
24909
  }
24860
24910
 
24861
- async function triggerExecuteTestSuite(opts){
24911
+ async function triggerExecuteTestSuite(opts) {
24862
24912
  // Clean up the test results from the secion
24863
24913
  if (sections) {
24864
24914
  sections.removeAll();
@@ -24881,10 +24931,10 @@ RED.sidebar.nodeinfo = (function(){
24881
24931
 
24882
24932
  // Clean up the previous test results
24883
24933
  $('#test-results-wrapper').empty();
24884
-
24934
+
24885
24935
  // Show the terminal if close
24886
24936
  let terminalOpen = $('#workspace-terminal').is(":visible");
24887
- if (!terminalOpen){
24937
+ if (!terminalOpen) {
24888
24938
  $('#shelve-middle').click();
24889
24939
  }
24890
24940
 
@@ -24903,20 +24953,20 @@ RED.sidebar.nodeinfo = (function(){
24903
24953
 
24904
24954
  // Trigger the testcases
24905
24955
  if (RUN_ALL_TEST_CASES === testCaseIdSelected) {
24906
- for (let i=0; i < testNodes.length; i++) {
24956
+ for (let i = 0; i < testNodes.length; i++) {
24907
24957
  createDebugMessageCache(testNodes[i].id);
24908
- try{
24958
+ try {
24909
24959
  // console.log(`[tab-test] Running testcase: ${testNodes[i].id} ...`, )
24910
24960
  await window.__kumologica.libs.testFlow('{}', testNodes[i].id, environment);
24911
- }catch(err){
24961
+ } catch (err) {
24912
24962
  console.log('[tab-test] error found: ', err);
24913
24963
  }
24914
- }
24964
+ }
24915
24965
  } else {
24916
24966
  try {
24917
24967
  createDebugMessageCache(testCaseIdSelected);
24918
24968
  await window.__kumologica.libs.testFlow('{}', testCaseIdSelected, environment);
24919
- } catch(err) {
24969
+ } catch (err) {
24920
24970
  console.log('[tab-test] error found: ', err);
24921
24971
  //App.notify(`Error found: ${JSON.stringify(err)}`, { type: 'error'});
24922
24972
  }
@@ -24926,7 +24976,7 @@ RED.sidebar.nodeinfo = (function(){
24926
24976
  }
24927
24977
  }
24928
24978
 
24929
- function createDebugMessageCache(testCaseID){
24979
+ function createDebugMessageCache(testCaseID) {
24930
24980
  let sanitizeTestCaseID = testCaseID.replace(/\./g, '_')
24931
24981
  $(`<div id="test-debug-message-cache-${sanitizeTestCaseID}" style="margin-right: 2px"></div>`).appendTo($('#test-debug-messages-caches'));
24932
24982
  }
@@ -25080,11 +25130,11 @@ RED.sidebar.nodeinfo = (function(){
25080
25130
  });
25081
25131
 
25082
25132
  // ==> Load initial data to the screen
25083
- refreshScreen();
25133
+ refreshScreen();
25084
25134
 
25085
25135
  // Append to the list of properties a fake record to append a new property
25086
25136
  // attachAppendPropertyRow(); // TODO: Javier review
25087
-
25137
+
25088
25138
  // Load the tooltips
25089
25139
  RED.popover.tooltip($('#test-sidebar-header-wrapper-left'), 'Select Test Case to Run');
25090
25140
  RED.popover.tooltip(
@@ -25113,8 +25163,8 @@ RED.sidebar.nodeinfo = (function(){
25113
25163
  attachAppendPropertyRow();
25114
25164
  });
25115
25165
 
25116
- function toggleProperties(){
25117
- if (propertiesOpened){
25166
+ function toggleProperties() {
25167
+ if (propertiesOpened) {
25118
25168
  // close the properties window
25119
25169
  $('#propertiesSection').hide();
25120
25170
  } else {
@@ -25135,9 +25185,9 @@ RED.sidebar.nodeinfo = (function(){
25135
25185
  refreshProperties();
25136
25186
  }
25137
25187
 
25138
-
25139
25188
 
25140
- function attachPropertyRow(key, value){
25189
+
25190
+ function attachPropertyRow(key, value) {
25141
25191
  const s = key;
25142
25192
  const keyid = s.replace(/[^a-zA-Z0-9-]/g, '_');
25143
25193
  let propertyRow = `
@@ -25167,30 +25217,30 @@ RED.sidebar.nodeinfo = (function(){
25167
25217
  });
25168
25218
  }
25169
25219
 
25170
- function deleteProperty(key){
25220
+ function deleteProperty(key) {
25171
25221
  // detach the DOM element
25172
25222
  $(`#row-${key}`).remove();
25173
25223
  saveSettings();
25174
25224
  }
25175
25225
 
25176
- function addProperty(key, value){
25226
+ function addProperty(key, value) {
25177
25227
  // reset the errors have happened in the past,... pity we cannot do the same in real life
25178
25228
  $('#new-prop-key').removeClass('wrong-value');
25179
25229
  $('#new-prop-value').removeClass('wrong-value');
25180
25230
 
25181
25231
  let errorsFound = false;
25182
25232
 
25183
- if (!key){
25233
+ if (!key) {
25184
25234
  errorsFound = true;
25185
25235
  $('#new-prop-key').addClass('wrong-value');
25186
25236
  }
25187
25237
 
25188
- if (!value){
25238
+ if (!value) {
25189
25239
  errorsFound = true;
25190
25240
  $('#new-prop-value').addClass('wrong-value');
25191
25241
  }
25192
25242
 
25193
- if (!errorsFound){
25243
+ if (!errorsFound) {
25194
25244
  // remove the addPropertyRow...
25195
25245
  $('#table-row-append').remove();
25196
25246
  // Sanitize the key. As this will be used as a valid `id` property of the html element
@@ -25234,37 +25284,37 @@ RED.sidebar.nodeinfo = (function(){
25234
25284
  <div id="addSaveProperty" class="table-cell-btn"><i class="icofont-save"></i></div>
25235
25285
  </div>
25236
25286
  `;
25237
- $(addPropertyRow).appendTo($('#table-test-properties'));
25287
+ $(addPropertyRow).appendTo($('#table-test-properties'));
25238
25288
 
25239
- // Attach the save event
25240
- $('#addSaveProperty').click(e => {
25241
- let key = $('#new-prop-key').val();
25242
- let value = $('#new-prop-value').val();
25243
- addProperty(key, value);
25244
- });
25245
- // Do not allow spaces on the key - replace if for dashes
25246
- $('#new-prop-key').on('input', () => {
25247
- let old = $('#new-prop-key').val();
25248
- $('#new-prop-key').val(old.replace(/\s+/g, '-') );
25249
- });
25289
+ // Attach the save event
25290
+ $('#addSaveProperty').click(e => {
25291
+ let key = $('#new-prop-key').val();
25292
+ let value = $('#new-prop-value').val();
25293
+ addProperty(key, value);
25294
+ });
25295
+ // Do not allow spaces on the key - replace if for dashes
25296
+ $('#new-prop-key').on('input', () => {
25297
+ let old = $('#new-prop-key').val();
25298
+ $('#new-prop-key').val(old.replace(/\s+/g, '-'));
25299
+ });
25250
25300
  }
25251
25301
 
25252
25302
  // Debugger operations
25253
25303
  async function triggerDebugTestSuite() {
25254
25304
  // console.log('[tab-test] Debugger started ...');
25255
- let { body} = await window.__kumologica.debugger.listBreakpoints();
25305
+ let { body } = await window.__kumologica.debugger.listBreakpoints();
25256
25306
  // console.log('[tab-test] Breakpoints =', body);
25257
- if ( body.length === 0 ) {
25307
+ if (body.length === 0) {
25258
25308
  // case of no breakpoints found in the flow
25259
25309
  await triggerExecuteTestSuite({ debug: false });
25260
25310
  RED.notifications.notify('No breakpoints found in the flow', 'warning', undefined, 2000);
25261
- } else{
25311
+ } else {
25262
25312
  $('#test-info-wrapper').hide();
25263
25313
  $('#properties-wrapper').hide();
25264
25314
  $('#debugger-wrapper').show();
25265
25315
  await triggerExecuteTestSuite({ debug: true });
25266
25316
  }
25267
-
25317
+
25268
25318
  }
25269
25319
 
25270
25320
  async function hideDebuggerControls() {
@@ -25281,17 +25331,17 @@ RED.sidebar.nodeinfo = (function(){
25281
25331
  $('#debugger-wrapper').show();
25282
25332
  }
25283
25333
 
25284
- function debuggerStoppedOnBreakpoint(e,msg) {
25334
+ function debuggerStoppedOnBreakpoint(e, msg) {
25285
25335
  // console.log('[tab-test] Debugger stopped on breakpoint ...e=', e);
25286
25336
  // console.log('[tab-test] Debugger stopped on breakpoint ...msg=', msg);
25287
25337
 
25288
25338
  showDebuggerControls();
25289
25339
 
25290
- let universalNodeId = msg.payload.nodeId;
25340
+ let universalNodeId = msg.payload.nodeId;
25291
25341
  let testCaseID = universalNodeId.split('::')[0];
25292
25342
  // sanitize the testCaseId, i.e. removing dots as jquery selector does not like it
25293
25343
  testCaseId = testCaseID.replace(/\./g, '_');
25294
-
25344
+
25295
25345
  sections.expandLastEntry();
25296
25346
  selectTestcaseTab('traces', testCaseId);
25297
25347
  }
@@ -25301,7 +25351,216 @@ RED.sidebar.nodeinfo = (function(){
25301
25351
  refreshTab,
25302
25352
  };
25303
25353
  })();
25304
- ;RED.sidebar.git = (function(){
25354
+ ;RED.sidebar.ai = (function () {
25355
+ let tabContent;
25356
+ let sections;
25357
+ let stackContainer;
25358
+ let latestCodeGenerated = '[]';
25359
+
25360
+ const INITIAL_MESSAGE = `Generate flow or node that ... (ctrl+enter to generate)`;
25361
+
25362
+ const openAIClient = window.__kumologica.libs.openAIClient; // TODO: javier
25363
+
25364
+ function initHTML() {
25365
+ tabContent = document.createElement('div');
25366
+ tabContent.className = 'sidebar-ai';
25367
+ tabContent.style = "height: 100%";
25368
+
25369
+ RED.actions.add('core:show-ai-tab', show);
25370
+
25371
+ stackContainer = $('<div>', {
25372
+ class: 'sidebar-node-info-stack',
25373
+ style: 'height: 100%'
25374
+ }).appendTo(tabContent);
25375
+
25376
+ // Append the header
25377
+ let headerContentHtml = `
25378
+ <div class="sidebar-ai-title-wrapper">
25379
+ <div style="display:flex;flex-direction:column;padding-right:10px; width:100%; height: 100%">
25380
+ <div id="sidebar-title-wrapper" style="display:flex">
25381
+ <span>Generative AI</span>
25382
+ </div>
25383
+
25384
+ <div id="sidebar-ai-body">
25385
+ <div id="sidebar-ai-error-wrapper" style="display:none">
25386
+ <span><b>An error occurred during processing your request</b>
25387
+ <span>Please check the logs for additional details or contact support for assistance</span>
25388
+ </div>
25389
+ <div id="sidebar-ai-response-wrapper" style="display:none">
25390
+ <div class="pt-0.5">
25391
+ <div class="gizmo-shadow-stroke flex h-6 w-6 items-center justify-center overflow-hidden rounded-full">
25392
+ <div class="relative p-1 rounded-sm h-9 w-9 text-white flex items-center justify-center" style="background-color: rgb(25, 195, 125); width: 24px; height: 24px; border-radius: 9999px; justify-content: center; align-items: center; color: white; margin-bottom: 7px">
25393
+ <svg width="41" height="41" viewBox="0 0 41 41" fill="none" xmlns="http://www.w3.org/2000/svg" class="icon-sm" role="img"><text x="-9999" y="-9999">ChatGPT</text><path d="M37.5324 16.8707C37.9808 15.5241 38.1363 14.0974 37.9886 12.6859C37.8409 11.2744 37.3934 9.91076 36.676 8.68622C35.6126 6.83404 33.9882 5.3676 32.0373 4.4985C30.0864 3.62941 27.9098 3.40259 25.8215 3.85078C24.8796 2.7893 23.7219 1.94125 22.4257 1.36341C21.1295 0.785575 19.7249 0.491269 18.3058 0.500197C16.1708 0.495044 14.0893 1.16803 12.3614 2.42214C10.6335 3.67624 9.34853 5.44666 8.6917 7.47815C7.30085 7.76286 5.98686 8.3414 4.8377 9.17505C3.68854 10.0087 2.73073 11.0782 2.02839 12.312C0.956464 14.1591 0.498905 16.2988 0.721698 18.4228C0.944492 20.5467 1.83612 22.5449 3.268 24.1293C2.81966 25.4759 2.66413 26.9026 2.81182 28.3141C2.95951 29.7256 3.40701 31.0892 4.12437 32.3138C5.18791 34.1659 6.8123 35.6322 8.76321 36.5013C10.7141 37.3704 12.8907 37.5973 14.9789 37.1492C15.9208 38.2107 17.0786 39.0587 18.3747 39.6366C19.6709 40.2144 21.0755 40.5087 22.4946 40.4998C24.6307 40.5054 26.7133 39.8321 28.4418 38.5772C30.1704 37.3223 31.4556 35.5506 32.1119 33.5179C33.5027 33.2332 34.8167 32.6547 35.9659 31.821C37.115 30.9874 38.0728 29.9178 38.7752 28.684C39.8458 26.8371 40.3023 24.6979 40.0789 22.5748C39.8556 20.4517 38.9639 18.4544 37.5324 16.8707ZM22.4978 37.8849C20.7443 37.8874 19.0459 37.2733 17.6994 36.1501C17.7601 36.117 17.8666 36.0586 17.936 36.0161L25.9004 31.4156C26.1003 31.3019 26.2663 31.137 26.3813 30.9378C26.4964 30.7386 26.5563 30.5124 26.5549 30.2825V19.0542L29.9213 20.998C29.9389 21.0068 29.9541 21.0198 29.9656 21.0359C29.977 21.052 29.9842 21.0707 29.9867 21.0902V30.3889C29.9842 32.375 29.1946 34.2791 27.7909 35.6841C26.3872 37.0892 24.4838 37.8806 22.4978 37.8849ZM6.39227 31.0064C5.51397 29.4888 5.19742 27.7107 5.49804 25.9832C5.55718 26.0187 5.66048 26.0818 5.73461 26.1244L13.699 30.7248C13.8975 30.8408 14.1233 30.902 14.3532 30.902C14.583 30.902 14.8088 30.8408 15.0073 30.7248L24.731 25.1103V28.9979C24.7321 29.0177 24.7283 29.0376 24.7199 29.0556C24.7115 29.0736 24.6988 29.0893 24.6829 29.1012L16.6317 33.7497C14.9096 34.7416 12.8643 35.0097 10.9447 34.4954C9.02506 33.9811 7.38785 32.7263 6.39227 31.0064ZM4.29707 13.6194C5.17156 12.0998 6.55279 10.9364 8.19885 10.3327C8.19885 10.4013 8.19491 10.5228 8.19491 10.6071V19.808C8.19351 20.0378 8.25334 20.2638 8.36823 20.4629C8.48312 20.6619 8.64893 20.8267 8.84863 20.9404L18.5723 26.5542L15.206 28.4979C15.1894 28.5089 15.1703 28.5155 15.1505 28.5173C15.1307 28.5191 15.1107 28.516 15.0924 28.5082L7.04046 23.8557C5.32135 22.8601 4.06716 21.2235 3.55289 19.3046C3.03862 17.3858 3.30624 15.3413 4.29707 13.6194ZM31.955 20.0556L22.2312 14.4411L25.5976 12.4981C25.6142 12.4872 25.6333 12.4805 25.6531 12.4787C25.6729 12.4769 25.6928 12.4801 25.7111 12.4879L33.7631 17.1364C34.9967 17.849 36.0017 18.8982 36.6606 20.1613C37.3194 21.4244 37.6047 22.849 37.4832 24.2684C37.3617 25.6878 36.8382 27.0432 35.9743 28.1759C35.1103 29.3086 33.9415 30.1717 32.6047 30.6641C32.6047 30.5947 32.6047 30.4733 32.6047 30.3889V21.188C32.6066 20.9586 32.5474 20.7328 32.4332 20.5338C32.319 20.3348 32.154 20.1698 31.955 20.0556ZM35.3055 15.0128C35.2464 14.9765 35.1431 14.9142 35.069 14.8717L27.1045 10.2712C26.906 10.1554 26.6803 10.0943 26.4504 10.0943C26.2206 10.0943 25.9948 10.1554 25.7963 10.2712L16.0726 15.8858V11.9982C16.0715 11.9783 16.0753 11.9585 16.0837 11.9405C16.0921 11.9225 16.1048 11.9068 16.1207 11.8949L24.1719 7.25025C25.4053 6.53903 26.8158 6.19376 28.2383 6.25482C29.6608 6.31589 31.0364 6.78077 32.2044 7.59508C33.3723 8.40939 34.2842 9.53945 34.8334 10.8531C35.3826 12.1667 35.5464 13.6095 35.3055 15.0128ZM14.2424 21.9419L10.8752 19.9981C10.8576 19.9893 10.8423 19.9763 10.8309 19.9602C10.8195 19.9441 10.8122 19.9254 10.8098 19.9058V10.6071C10.8107 9.18295 11.2173 7.78848 11.9819 6.58696C12.7466 5.38544 13.8377 4.42659 15.1275 3.82264C16.4173 3.21869 17.8524 2.99464 19.2649 3.1767C20.6775 3.35876 22.0089 3.93941 23.1034 4.85067C23.0427 4.88379 22.937 4.94215 22.8668 4.98473L14.9024 9.58517C14.7025 9.69878 14.5366 9.86356 14.4215 10.0626C14.3065 10.2616 14.2466 10.4877 14.2479 10.7175L14.2424 21.9419ZM16.071 17.9991L20.4018 15.4978L24.7325 17.9975V22.9985L20.4018 25.4983L16.071 22.9985V17.9991Z" fill="currentColor"></path>
25394
+ </svg>
25395
+ </div>
25396
+ </div>
25397
+ </div>
25398
+ <div id="sidebar-ai-response-message">
25399
+ <div id="sidebar-ai-response-action-wrapper">
25400
+ <a id="sidebar-ai-import-flow" class="sidebar-header-button" href="#" style="margin-right:5px">
25401
+ Import Flow
25402
+ </a>
25403
+ </div>
25404
+ <span id="sidebar-ai-response-flow-value"></span>
25405
+ </div>
25406
+
25407
+ </div>
25408
+ </div>
25409
+
25410
+ <div id="sidebar-ai-prompt">
25411
+ <div id="sidebar-ai-prompt-message-wrapper">
25412
+ <textarea id="sidebar-ai-prompt-message" rows="4" placeholder="${INITIAL_MESSAGE}" style="min-height:130px"></textarea>
25413
+ </div>
25414
+ <div id="sidebar-ai-prompt-actions">
25415
+ <a id="sidebar-ai-clear-btn" class="sidebar-header-button" href="#" style="margin-right:5px">
25416
+ Clear
25417
+ </a>
25418
+ <a id="sidebar-ai-generate-btn" class="sidebar-header-button" href="#" style="color: white !important; background: #2979ff;">
25419
+ Generate
25420
+ </a>
25421
+ </div>
25422
+ <div id="sidebar-ai-prompt-noactions" style="display:none">
25423
+ <a id="sidebar-ai-generating" class="sidebar-header-button" href="#" style="color: white !important; height: 24px;">
25424
+ <img src="red/images/spin.svg" class="palette-spinner" style="height: 16px; width: 57px" />
25425
+ </a>
25426
+ </div>
25427
+ </div>
25428
+
25429
+ <div id="ai-not-initialized" style="display:none">
25430
+ <div style="display:flex; flex-direction: column; align-items: center; margin-top: 150px">
25431
+ <div><i class="fa fa-magic" style="font-size: 56px; color: lightgrey;"></i></div>
25432
+ <div style="font-weight: bold; font-size: 22px; margin-top: 15px;color: grey;">OpenAI API Key not found</div>
25433
+ <div style="margin-top: 5px; color: grey;font-weight: 400; font-size: 13px;">To use this feature, you need to add your OpenAI key. </div>
25434
+ <div style="margin-top: 10px"><span id="add-ai-key" style="font-weight: 500;font-size: 12px; color: #2979ff">Add key</span></div>
25435
+ </div>
25436
+ </div>
25437
+ </div>
25438
+ </div>
25439
+ `;
25440
+
25441
+ $(headerContentHtml).appendTo(stackContainer);
25442
+
25443
+ RED.sidebar.addTab({
25444
+ id: 'ai',
25445
+ label: 'Gen AI',
25446
+ name: 'Generative AI',
25447
+ iconClass: 'fa fa-magic',
25448
+ action: 'core:show-git-tab',
25449
+ content: tabContent,
25450
+ pinned: true,
25451
+ enableOnEdit: true,
25452
+ onchange: refreshTab,
25453
+ onsame: onsame
25454
+ })
25455
+ }
25456
+ function displayGeneratedCode(code) {
25457
+ // update the latest code generated
25458
+ latestCodeGenerated = JSON.stringify(code, null, 2);
25459
+
25460
+ $('#sidebar-ai-response-wrapper').show();
25461
+ let $response = $('#sidebar-ai-response-flow-value');
25462
+
25463
+ RED.utils
25464
+ .createObjectElement({ "code": code }, {
25465
+ key: /*true*/ null,
25466
+ typeHint: 'object',
25467
+ hideKey: false,
25468
+ path: '',
25469
+ sourceId: 0,
25470
+ rootPath: '',
25471
+ })
25472
+ .appendTo($response);
25473
+ }
25474
+
25475
+ function changeStateToGenerating() {
25476
+ latestCodeGenerated = '[]';
25477
+ // Clear the previous response if required
25478
+ $('#sidebar-ai-response-wrapper').hide();
25479
+ $('#sidebar-ai-response-flow-value').empty();
25480
+
25481
+ // Control buttons
25482
+ $('#sidebar-ai-prompt-actions').hide();
25483
+ $('#sidebar-ai-prompt-noactions').show();
25484
+ }
25485
+
25486
+ function changeStateToGenerated() {
25487
+ $('#sidebar-ai-prompt-actions').show();
25488
+ $('#sidebar-ai-prompt-noactions').hide();
25489
+
25490
+ }
25491
+
25492
+ function initJS() {
25493
+ // Generate action
25494
+ $('#sidebar-ai-generate-btn').click(async e => {
25495
+ console.log('Asking AI to generate code...');
25496
+ // Change the icon to loading
25497
+ changeStateToGenerating();
25498
+
25499
+ let userPrompt = $('#sidebar-ai-prompt-message').val();
25500
+ if (userPrompt) {
25501
+ let response = await openAIClient.t2c(userPrompt);
25502
+ displayGeneratedCode(response);
25503
+ changeStateToGenerated();
25504
+ } else {
25505
+ changeStateToGenerated();
25506
+ }
25507
+
25508
+
25509
+ })
25510
+ // Trigger generate action from ctrl+click
25511
+ $('#sidebar-ai-prompt-message').keydown(e => {
25512
+ if ((e.ctrlKey || e.metaKey) && (e.keyCode == 13 || e.keyCode == 10)) {
25513
+ $('#sidebar-ai-generate-btn').click();
25514
+ }
25515
+ })
25516
+
25517
+ // Clear button
25518
+ $('#sidebar-ai-clear-btn').click(async e => {
25519
+ // Clear all messages
25520
+ $('#sidebar-ai-response-wrapper').hide();
25521
+ $('#sidebar-ai-response-flow-value').empty();
25522
+
25523
+ // Clear user prompt
25524
+ $('#sidebar-ai-prompt-message').val('');
25525
+ });
25526
+
25527
+ $('#sidebar-ai-import-flow').click(e => {
25528
+ // Copy code to clipboard
25529
+ const { clipboard } = window.__kumologica.electron;
25530
+ clipboard.writeText(latestCodeGenerated);
25531
+
25532
+ // Open the import flow dialog
25533
+ RED.actions.invoke('core:show-import-dialog')
25534
+
25535
+ // automatically trigger the import-from-clipboard option
25536
+ setTimeout(() => { $('#import-from-clipboard').click() }, 100);
25537
+ })
25538
+ }
25539
+
25540
+ function init() {
25541
+ initHTML();
25542
+ initJS();
25543
+ }
25544
+
25545
+ function show() {
25546
+ RED.sidebar.show('ai');
25547
+ }
25548
+
25549
+ function refreshTab(silently) {
25550
+ if (!silently) {
25551
+ RED.actions.invoke('core:show-sidebar');
25552
+ }
25553
+ }
25554
+
25555
+ function onsame() {
25556
+ RED.actions.invoke('core:hide-sidebar');
25557
+ }
25558
+
25559
+ return {
25560
+ init: init,
25561
+ show: show,
25562
+ }
25563
+ })();;RED.sidebar.git = (function(){
25305
25564
 
25306
25565
  let tabContent;
25307
25566
  let sections;
@@ -26535,7 +26794,149 @@ RED.sidebar.azure = (function () {
26535
26794
  };
26536
26795
 
26537
26796
  })();
26538
- ;RED.palette.explorer = (function () {
26797
+ ;RED.footer = (function () {
26798
+ // AI Section
26799
+ const askConfigureAI = () => {
26800
+ console.log(`[footer] showing "askConfigureAi"`)
26801
+
26802
+ $('#generate-code-ai').hide();
26803
+ $('#explain-code-ai').hide();
26804
+ $('#fix-code-ai').hide();
26805
+
26806
+ $('#ask-configure-ai').show();
26807
+ }
26808
+
26809
+ const showTasksAI = () => {
26810
+ console.log(`[footer] showing all AI tasks`)
26811
+
26812
+ $('#generate-code-ai').show();
26813
+ $('#explain-code-ai').show();
26814
+ $('#fix-code-ai').show();
26815
+
26816
+ $('#ask-configure-ai').hide();
26817
+ }
26818
+
26819
+ const isEnabledAI = () => {
26820
+ return false;
26821
+ }
26822
+
26823
+
26824
+ const handleChangeTestCase = (tcSelected) => {
26825
+ console.log('[footer] callback with tcSelected', tcSelected);
26826
+ let testcaseName = tcSelected.name || 'No TestCase selected'; // 'getTestCaseName(tcSelected.id);
26827
+ console.log('[footer] Resolved testcase name=', testcaseName);
26828
+
26829
+ if (testcaseName) {
26830
+ $('#footer-test').show();
26831
+ $('#footer-test-value').text(testcaseName);
26832
+ } else {
26833
+ $('#footer-test').hide();
26834
+ }
26835
+ }
26836
+
26837
+ const getTestCaseName = (testcaseId) => {
26838
+ if (!testcaseId) return "No TestCase selected";
26839
+
26840
+ if (testcaseId === '__runAll') {
26841
+ return "Run all TestCases";
26842
+ } else {
26843
+ let nodeSelected = RED.nodes.filterNodes({ id: testcaseId });
26844
+ console.log('[footer] Node Selected: ', nodeSelected)
26845
+ if (nodeSelected && Array.isArray(nodeSelected) && nodeSelected.length > 0) {
26846
+ let name = nodeSelected[0].name;
26847
+ return name;
26848
+ }
26849
+ }
26850
+ }
26851
+
26852
+ const initNodeLibraryWidget = () => {
26853
+ let $nodeLibrary = $('#launch-node-library');
26854
+ RED.popover.tooltip($nodeLibrary, 'Open node library...');
26855
+ }
26856
+
26857
+ const initRuntimeVerWidget = () => {
26858
+ let $runtimeVer = $('#footer-runtime-ver');
26859
+ RED.popover.create({
26860
+ target: $runtimeVer,
26861
+ trigger: 'hover',
26862
+ size: 'small',
26863
+ direction: 'top',
26864
+ content: 'Kumologica runtime installed',
26865
+ delay: { show: 750, hide: 50 },
26866
+ })
26867
+ }
26868
+
26869
+ const initServerWidget = () => {
26870
+ let $footerServer = $('#footer-server');
26871
+ RED.popover.tooltip($footerServer, 'Local server listening address')
26872
+ }
26873
+ const initTestWidget = () => {
26874
+ window.__kumologica.settings.loadConfigs();
26875
+ console.log('[footer] testConfig=', window.__kumologica.settings.testConfig);
26876
+
26877
+ let testcaseId = window.__kumologica.settings.testConfig.getLatestSelectedTestCase();
26878
+ let tcSelectedName = getTestCaseName(testcaseId);
26879
+
26880
+ handleChangeTestCase({
26881
+ id: testcaseId,
26882
+ name: tcSelectedName
26883
+ });
26884
+
26885
+ // Add action
26886
+ let $footerTest = $('#footer-test');
26887
+ $footerTest.click(e => {
26888
+ if (!$('.sidebar-test').is(':visible')) {
26889
+ $('#red-ui-tab-test-link-button').click();
26890
+ }
26891
+
26892
+ $('#test-sidebar-run-btn').click();
26893
+ });
26894
+ // Add popover
26895
+ RED.popover.tooltip($footerTest, "Run TestCase");
26896
+
26897
+ // Attach listener
26898
+ RED.actions.add('test:change-testcase-selected', handleChangeTestCase);
26899
+ }
26900
+
26901
+ const initAIWidget = () => {
26902
+ // check whether AI settings are configured or not
26903
+ let aiEnabled = isEnabledAI();
26904
+ if (aiEnabled) {
26905
+ showTasksAI();
26906
+ } else {
26907
+ askConfigureAI();
26908
+ }
26909
+ }
26910
+
26911
+ const initTerminalWidget = () => {
26912
+ let $footerTerminal = $('#footer-terminal');
26913
+
26914
+ $footerTerminal.click(e => {
26915
+ $('#workspace-terminal').toggle();
26916
+ });
26917
+ RED.popover.create({
26918
+ target: $footerTerminal,
26919
+ trigger: 'hover',
26920
+ size: 'small',
26921
+ direction: 'left',
26922
+ content: "Log Viewer",
26923
+ delay: { show: 750, hide: 50 }
26924
+ });
26925
+ }
26926
+
26927
+ const init = () => {
26928
+ initNodeLibraryWidget();
26929
+ initRuntimeVerWidget();
26930
+ initServerWidget();
26931
+ setTimeout(() => initTestWidget(), 2000);
26932
+ initAIWidget();
26933
+ initTerminalWidget();
26934
+ }
26935
+
26936
+ return {
26937
+ init: init
26938
+ }
26939
+ })();;RED.palette.explorer = (function () {
26539
26940
  let workspacePreferences = window.__kumologica.settings.workspacePreferenceStore;
26540
26941
  let path = window.__kumologica.libs.path;
26541
26942
 
@@ -28793,7 +29194,7 @@ RED.editor = (function () {
28793
29194
  return latestNodeSelected;
28794
29195
  }
28795
29196
 
28796
- function setLatestNodeSelected(newLatestNodeSelected){
29197
+ function setLatestNodeSelected(newLatestNodeSelected) {
28797
29198
  // console.log('[editor] setLatestNodeSelected=', newLatestNodeSelected);
28798
29199
  latestNodeSelected = newLatestNodeSelected;
28799
29200
  }
@@ -29069,10 +29470,10 @@ RED.editor = (function () {
29069
29470
  updateConfigNodeSelect(property, type, node[property], prefix);
29070
29471
  $(
29071
29472
  '<a id="' +
29072
- prefix +
29073
- '-lookup-' +
29074
- property +
29075
- '" class="editor-button"><i class="fa fa-pencil"></i></a>'
29473
+ prefix +
29474
+ '-lookup-' +
29475
+ property +
29476
+ '" class="editor-button"><i class="fa fa-pencil"></i></a>'
29076
29477
  )
29077
29478
  .css({ position: 'absolute', right: 0, top: 0 })
29078
29479
  .appendTo(outerWrap);
@@ -29194,10 +29595,10 @@ RED.editor = (function () {
29194
29595
  // Add the icon of dynamic expression
29195
29596
 
29196
29597
  //input
29197
- //.parent()
29198
- // .append(
29199
- // '<span style="display:none;float:right;position:relative;top:-23px;right:5px;color:#9c27b0;font-size:14px" class="fa fa-bolt icon-templatable"></span>'
29200
- // );
29598
+ //.parent()
29599
+ // .append(
29600
+ // '<span style="display:none;float:right;position:relative;top:-23px;right:5px;color:#9c27b0;font-size:14px" class="fa fa-bolt icon-templatable"></span>'
29601
+ // );
29201
29602
 
29202
29603
  RED.popover.tooltip(
29203
29604
  input.parent().find($('span.icon-templatable')),
@@ -29649,8 +30050,8 @@ RED.editor = (function () {
29649
30050
  function buildEditForm(container, formId, type, ns, node) {
29650
30051
  var dialogForm = $(
29651
30052
  '<form id="' +
29652
- formId +
29653
- '" class="form-horizontal" autocomplete="off"></form>'
30053
+ formId +
30054
+ '" class="form-horizontal" autocomplete="off"></form>'
29654
30055
  ).appendTo(container);
29655
30056
  dialogForm.html($("script[data-template-name='" + type + "']").html());
29656
30057
  ns = ns || 'kumologica-core';
@@ -29896,8 +30297,8 @@ RED.editor = (function () {
29896
30297
  var summary = $('<span>').appendTo(metaRow);
29897
30298
  var resetButton = $(
29898
30299
  '<button type="button" class="editor-button editor-button-small">' +
29899
- 'use default' +
29900
- '</button>'
30300
+ 'use default' +
30301
+ '</button>'
29901
30302
  )
29902
30303
  .appendTo(metaRow)
29903
30304
  .click(function (e) {
@@ -29960,10 +30361,10 @@ RED.editor = (function () {
29960
30361
 
29961
30362
  $(
29962
30363
  '<div class="form-row">' +
29963
- '<label for="node-input-show-label-btn" data-i18n="editor.label"></label>' +
29964
- '<button type="button" id="node-input-show-label-btn" class="editor-button" style="min-width: 80px; text-align: left;" type="button"><i id="node-input-show-label-btn-i" class="fa fa-toggle-on"></i> <span id="node-input-show-label-label"></span></button> ' +
29965
- '<input type="checkbox" id="node-input-show-label" style="display: none;"/>' +
29966
- '</div>'
30364
+ '<label for="node-input-show-label-btn" data-i18n="editor.label"></label>' +
30365
+ '<button type="button" id="node-input-show-label-btn" class="editor-button" style="min-width: 80px; text-align: left;" type="button"><i id="node-input-show-label-btn-i" class="fa fa-toggle-on"></i> <span id="node-input-show-label-label"></span></button> ' +
30366
+ '<input type="checkbox" id="node-input-show-label" style="display: none;"/>' +
30367
+ '</div>'
29967
30368
  ).appendTo(dialogForm);
29968
30369
 
29969
30370
  var setToggleState = function (state) {
@@ -30153,7 +30554,7 @@ RED.editor = (function () {
30153
30554
  value: node.info || '',
30154
30555
  lineNumbers: false,
30155
30556
  toolbar: false,
30156
- onChange: function(delta) {
30557
+ onChange: function (delta) {
30157
30558
  // console.log('[editor] InfoTab changed. Delta=', delta);
30158
30559
  notifyChanges(getLatestNodeSelected());
30159
30560
  }
@@ -30162,7 +30563,7 @@ RED.editor = (function () {
30162
30563
  return nodeInfoEditor;
30163
30564
  }
30164
30565
 
30165
- function resetEditor(){
30566
+ function resetEditor() {
30166
30567
  editStack.pop();
30167
30568
  RED.sidebar.nodeinfo.emptyTab();
30168
30569
  RED.actions.invoke('core:hide-sidebar');
@@ -30172,7 +30573,7 @@ RED.editor = (function () {
30172
30573
  notifyChanges(getLatestNodeSelected());
30173
30574
  }
30174
30575
 
30175
- function notifyChanges(nodeSelected){
30576
+ function notifyChanges(nodeSelected) {
30176
30577
  // console.log('[editor] notifyChanges with nodeSelected: ', nodeSelected);
30177
30578
  let editing_node = nodeSelected;
30178
30579
  let node = nodeSelected;
@@ -30336,11 +30737,11 @@ RED.editor = (function () {
30336
30737
  changed = changed || credsChanged;
30337
30738
  }
30338
30739
  if (editing_node.hasOwnProperty("_outputs")) {
30339
- outputMap = editing_node._outputs;
30340
- delete editing_node._outputs;
30341
- if (Object.keys(outputMap).length > 0) {
30342
- changed = true;
30343
- }
30740
+ outputMap = editing_node._outputs;
30741
+ delete editing_node._outputs;
30742
+ if (Object.keys(outputMap).length > 0) {
30743
+ changed = true;
30744
+ }
30344
30745
  }
30345
30746
  var removedLinks = updateNodeProperties(editing_node, outputMap);
30346
30747
 
@@ -30379,7 +30780,7 @@ RED.editor = (function () {
30379
30780
  }
30380
30781
  }
30381
30782
 
30382
-
30783
+
30383
30784
  if (changed) {
30384
30785
  // console.log('[editor] Editing node detected a change. Saving required.');
30385
30786
  var wasChanged = editing_node.changed;
@@ -30424,7 +30825,7 @@ RED.editor = (function () {
30424
30825
  setLatestNodeSelected(editing_node);
30425
30826
  // console.log('[editor] Node changed. Required to be saved', editing_node);
30426
30827
  RED.events.emit('editor:save', editing_node);
30427
- }else{
30828
+ } else {
30428
30829
  // console.log('[editor] Editing node is same as current node. No saving required');
30429
30830
  return;
30430
30831
  }
@@ -30435,7 +30836,7 @@ RED.editor = (function () {
30435
30836
  // console.log('[editor] Node properties changed. Event: keyup change');
30436
30837
  notifyChanges(getLatestNodeSelected());
30437
30838
  // Wait until the DOM has been modified as part of the click event, to set the new listener to the new elements
30438
- setTimeout(()=> {
30839
+ setTimeout(() => {
30439
30840
  listenEditorChanges();
30440
30841
  }, 300);
30441
30842
  }
@@ -30444,13 +30845,13 @@ RED.editor = (function () {
30444
30845
  // console.log('[editor] Node properties changed. Event: a click');
30445
30846
 
30446
30847
  // Wait until the DOM has been modified as part of the click event, to set the new listener to the new elements
30447
- setTimeout(()=> {
30848
+ setTimeout(() => {
30448
30849
  notifyChanges(getLatestNodeSelected());
30449
30850
  listenEditorChanges();
30450
30851
  }, 300);
30451
30852
  }
30452
30853
 
30453
- function listenEditorChanges(){
30854
+ function listenEditorChanges() {
30454
30855
  // console.log('[editor] Setting new listeners...')
30455
30856
  $('#editor-stack :input').off('keyup change', attachListenerToFieldsChange);
30456
30857
  $('#editor-stack :input').on('keyup change', attachListenerToFieldsChange);
@@ -30460,31 +30861,31 @@ RED.editor = (function () {
30460
30861
  }
30461
30862
 
30462
30863
  function showEditDialog(node) {
30463
- if (RED.sidebar.isDragging()){
30864
+ if (RED.sidebar.isDragging()) {
30464
30865
  return;
30465
30866
  }
30466
30867
 
30467
30868
  let editing_node;
30468
- if (Object.keys(node).length === 0 && node.constructor === Object){
30869
+ if (Object.keys(node).length === 0 && node.constructor === Object) {
30469
30870
  resetEditor();
30470
30871
  return;
30471
30872
  }
30472
30873
  // Case selection is about a `link`
30473
- if (node && node.hasOwnProperty('link')){
30874
+ if (node && node.hasOwnProperty('link')) {
30474
30875
  return;
30475
30876
  }
30476
30877
 
30477
30878
  // Case selection is about a `node`
30478
30879
  if (node && node.hasOwnProperty('nodes') && node.nodes.length === 1) { // Single node selection
30479
30880
  // Ignore if sidebar is not visible - only double click will pull initially the sidebar
30480
- if (RED.sidebar.isSidebarVisible()){
30881
+ if (RED.sidebar.isSidebarVisible()) {
30481
30882
  editing_node = node.nodes[0];
30482
30883
  } else {
30483
30884
  setLatestNodeSelected(node.nodes[0]);
30484
30885
  return;
30485
30886
  }
30486
-
30487
- } else if (node && node.hasOwnProperty('nodes') && Array.isArray(node.nodes)){ // Multinode selection
30887
+
30888
+ } else if (node && node.hasOwnProperty('nodes') && Array.isArray(node.nodes)) { // Multinode selection
30488
30889
  return;
30489
30890
  } else { // Double click on node
30490
30891
  editing_node = node;
@@ -30497,7 +30898,7 @@ RED.editor = (function () {
30497
30898
  // console.log('[editor] Before editStack.push() =', editStack);
30498
30899
  editStack.pop();
30499
30900
  editStack.push(node);
30500
-
30901
+
30501
30902
  //RED.view.state(RED.state.EDITING);
30502
30903
  var type = node.type;
30503
30904
 
@@ -30513,9 +30914,9 @@ RED.editor = (function () {
30513
30914
  ],
30514
30915
  resize: function (dimensions) {
30515
30916
  editTrayWidthCache[type] = dimensions.width;
30516
- $('.editor-tray-content').height(dimensions.height - 50);
30917
+ // $('.editor-tray-content').height(dimensions.height - 50);
30517
30918
  var form = $('.editor-tray-content form');
30518
-
30919
+
30519
30920
  // var form = $('.editor-tray-content form').height(
30520
30921
  // dimensions.height - 50 - 40
30521
30922
  // );
@@ -30610,10 +31011,10 @@ RED.editor = (function () {
30610
31011
  let editorTabContent = $('#help-tab');
30611
31012
 
30612
31013
  let helpText =
30613
- $("script[data-help-name='" + node.type + "']").html() ||
30614
- '<span class="node-info-none">' +
30615
- 'None' +
30616
- '</span>';
31014
+ $("script[data-help-name='" + node.type + "']").html() ||
31015
+ '<span class="node-info-none">' +
31016
+ 'None' +
31017
+ '</span>';
30617
31018
 
30618
31019
  $(`<div class="node-help">${helpText}</div>`).appendTo(editorTabContent);
30619
31020
 
@@ -30683,8 +31084,8 @@ RED.editor = (function () {
30683
31084
  if (editing_node) {
30684
31085
  // console.log('[editor] Showing editor ...')
30685
31086
  RED.sidebar.info.refresh(editing_node);
30686
- // activate the save button when node properties have changed
30687
- setTimeout( ()=> {
31087
+ // activate the save button when node properties have changed
31088
+ setTimeout(() => {
30688
31089
  listenEditorChanges();
30689
31090
  }, 300);
30690
31091
  }
@@ -30746,7 +31147,7 @@ RED.editor = (function () {
30746
31147
 
30747
31148
  RED.view.state(RED.state.EDITING);
30748
31149
  var trayOptions = {
30749
- title: getEditStackTitle(),
31150
+ title: getEditStackTitle(),
30750
31151
  nodeIconPath: getNodeIconPath(),
30751
31152
  resize: function (dimensions) {
30752
31153
  $('.editor-tray-content').height(dimensions.height - 50);
@@ -30859,8 +31260,8 @@ RED.editor = (function () {
30859
31260
  tabSelect.off('change');
30860
31261
  tabSelect.append(
30861
31262
  '<option value=""' +
30862
- (!editing_config_node.z ? ' selected' : '') +
30863
- ' data-i18n="sidebar.config.global"></option>'
31263
+ (!editing_config_node.z ? ' selected' : '') +
31264
+ ' data-i18n="sidebar.config.global"></option>'
30864
31265
  );
30865
31266
  tabSelect.append(
30866
31267
  '<option disabled data-i18n="sidebar.config.flows"></option>'
@@ -30872,10 +31273,10 @@ RED.editor = (function () {
30872
31273
  }
30873
31274
  $(
30874
31275
  '<option value="' +
30875
- ws.id +
30876
- '"' +
30877
- (ws.id == editing_config_node.z ? ' selected' : '') +
30878
- '></option>'
31276
+ ws.id +
31277
+ '"' +
31278
+ (ws.id == editing_config_node.z ? ' selected' : '') +
31279
+ '></option>'
30879
31280
  )
30880
31281
  .text(workspaceLabel)
30881
31282
  .appendTo(tabSelect);
@@ -30890,10 +31291,10 @@ RED.editor = (function () {
30890
31291
  }
30891
31292
  $(
30892
31293
  '<option value="' +
30893
- ws.id +
30894
- '"' +
30895
- (ws.id == editing_config_node.z ? ' selected' : '') +
30896
- '></option>'
31294
+ ws.id +
31295
+ '"' +
31296
+ (ws.id == editing_config_node.z ? ' selected' : '') +
31297
+ '></option>'
30897
31298
  )
30898
31299
  .text(workspaceLabel)
30899
31300
  .appendTo(tabSelect);
@@ -31261,10 +31662,10 @@ RED.editor = (function () {
31261
31662
  configNodes.forEach(function (cn) {
31262
31663
  $(
31263
31664
  '<option value="' +
31264
- cn.id +
31265
- '"' +
31266
- (value == cn.id ? ' selected' : '') +
31267
- '></option>'
31665
+ cn.id +
31666
+ '"' +
31667
+ (value == cn.id ? ' selected' : '') +
31668
+ '></option>'
31268
31669
  )
31269
31670
  .text(RED.text.bidi.enforceTextDirectionWithUCC(cn.__label__))
31270
31671
  .appendTo(select);
@@ -31273,9 +31674,9 @@ RED.editor = (function () {
31273
31674
 
31274
31675
  select.append(
31275
31676
  '<option value="_ADD_"' +
31276
- (value === '' ? ' selected' : '') +
31277
- '>' + `Add new ${type}...` +
31278
- '</option>'
31677
+ (value === '' ? ' selected' : '') +
31678
+ '>' + `Add new ${type}...` +
31679
+ '</option>'
31279
31680
  );
31280
31681
  window.setTimeout(function () {
31281
31682
  select.change();
@@ -31554,7 +31955,7 @@ RED.editor = (function () {
31554
31955
  editStack.pop();
31555
31956
  editing_node = null;
31556
31957
  },
31557
- show: function () {},
31958
+ show: function () { },
31558
31959
  };
31559
31960
  RED.tray.show(trayOptions);
31560
31961
  }
@@ -31645,7 +32046,7 @@ RED.editor = (function () {
31645
32046
  }
31646
32047
  if (options.mode === 'ace/mode/markdown') {
31647
32048
  $(el).addClass('node-text-editor-container-toolbar');
31648
- if (options.toolbar === false ){
32049
+ if (options.toolbar === false) {
31649
32050
  // do not show the toolbar
31650
32051
  } else {
31651
32052
  editor.toolbar = customEditTypes['_markdown'].buildToolbar(
@@ -31653,7 +32054,7 @@ RED.editor = (function () {
31653
32054
  editor
31654
32055
  );
31655
32056
  }
31656
-
32057
+
31657
32058
 
31658
32059
  if (options.expandable !== false) {
31659
32060
  // var previewButton = $(
@@ -31679,9 +32080,9 @@ RED.editor = (function () {
31679
32080
  // autoClose: 50,
31680
32081
  // });
31681
32082
  }
31682
- if (options.onChange){
31683
- session.on("change", function(delta){
31684
- options.onChange(delta);
32083
+ if (options.onChange) {
32084
+ session.on("change", function (delta) {
32085
+ options.onChange(delta);
31685
32086
  })
31686
32087
  }
31687
32088
  return editor;
@@ -31749,7 +32150,7 @@ RED.editor = (function () {
31749
32150
  editBuffer: function (options) {
31750
32151
  showTypeEditor('_buffer', options);
31751
32152
  },
31752
- editText: function(options){
32153
+ editText: function (options) {
31753
32154
  showTypeEditor('_string', options);
31754
32155
  },
31755
32156
  buildEditForm: buildEditForm,
@@ -34226,6 +34627,62 @@ RED.eventLog = (function() {
34226
34627
  copyText: copyText
34227
34628
  }
34228
34629
  })();
34630
+ ; RED.signup = (function() {
34631
+ // const {clipboard} = window.__kumologica.electron;
34632
+
34633
+ let signupWindow;
34634
+ const url = "https://api.dev.kumologica.dev/signup/ui?x-api-key=MLTh1kkXBLaBefMHEFR3d6Svub0otStnaTjjsN5R";
34635
+ //const url = "https://h5201rj4f8.execute-api.ap-southeast-2.amazonaws.com/default/signup/ui?x-api-key=MLTh1kkXBLaBefMHEFR3d6Svub0otStnaTjjsN5R";
34636
+ function signupCompleted(details) {
34637
+ const tokens = processCallback(details.url);
34638
+ saveTokens(tokens);
34639
+ signupWindow.destroy();
34640
+ }
34641
+
34642
+ function processCallback(url) {
34643
+ const u = url.replace("http://localhost:3000/#", "");
34644
+ const t = u.split("&");
34645
+ return t;
34646
+ }
34647
+
34648
+ function saveTokens(tokens) {
34649
+ const cfg = window.__kumologica.settings.settingsConfig;
34650
+ cfg.saveKumologicaDevAlias(tokens);
34651
+ }
34652
+
34653
+ function showSignup() {
34654
+ const {BrowserWindow} = window.__kumologica.electron.remote;
34655
+
34656
+ signupWindow = new BrowserWindow({width:700, height:470});
34657
+ signupWindow.loadURL(url);
34658
+
34659
+ const defaultSession = window.__kumologica.electron.remote.session.defaultSession;
34660
+
34661
+ defaultSession.webRequest.onBeforeRequest(
34662
+ { urls: ["http://localhost:3000/*"] },
34663
+ (details,
34664
+ callback) => {
34665
+ RED.events.emit('core:signup:completed', details);
34666
+ });
34667
+
34668
+ signupWindow.on('authenticated', (a) => {
34669
+ console.log("auth");
34670
+ console.log(a);
34671
+ });
34672
+
34673
+ signupWindow.on('closed', (a) => {
34674
+ console.log("closed");
34675
+ });
34676
+ }
34677
+
34678
+ return {
34679
+ init: function() {
34680
+ RED.actions.add("core:signup:show", showSignup);
34681
+ RED.events.on("core:signup:completed", (details) => signupCompleted(details));
34682
+ },
34683
+ // show: showSignup
34684
+ }
34685
+ })();
34229
34686
  ;RED.library = (function() {
34230
34687
  var exportToLibraryDialog;
34231
34688
  var elementPrefix = 'node-input-';
@@ -35170,16 +35627,16 @@ RED.notifications = (function() {
35170
35627
  }
35171
35628
  } else {
35172
35629
  let commands = searchCommands();
35173
- commands.forEach(c=> {
35630
+ commands.forEach(c => {
35174
35631
  searchResults.editableList('addItem', c);
35175
35632
  });
35176
35633
 
35177
35634
  let results = $('#search-result-list');
35178
35635
  $('<div class="searchSeparator"></div>').appendTo(results);
35179
35636
 
35180
-
35637
+
35181
35638
  let allNodes = searchNodes();
35182
-
35639
+
35183
35640
  allNodes.forEach(n => {
35184
35641
  searchResults.editableList('addItem', n);
35185
35642
  })
@@ -35187,7 +35644,7 @@ RED.notifications = (function() {
35187
35644
  }
35188
35645
  }
35189
35646
 
35190
- function searchNodes(val, typeFilter){
35647
+ function searchNodes(val, typeFilter) {
35191
35648
  results = [];
35192
35649
  if (val) {
35193
35650
  val = val.trim();
@@ -35228,10 +35685,10 @@ RED.notifications = (function() {
35228
35685
  if (setResults.has(n.node.id)) return;
35229
35686
  else {
35230
35687
  setResults.add(n.node.id);
35231
- if (n.node.type === 'tab'){
35232
- results.push({ label:n.node.label, node: n.node});
35233
- }else {
35234
- results.push({ label:n.node.name, node: n.node});
35688
+ if (n.node.type === 'tab') {
35689
+ results.push({ label: n.node.label, node: n.node });
35690
+ } else {
35691
+ results.push({ label: n.node.name, node: n.node });
35235
35692
  }
35236
35693
  }
35237
35694
  })
@@ -35245,30 +35702,37 @@ RED.notifications = (function() {
35245
35702
  * Returns a list of commands that will be added to the search window when it is opened
35246
35703
  */
35247
35704
  function searchCommands() {
35705
+
35248
35706
  return [
35249
35707
  { type: 'command', title: 'Open Settings', action: 'core:settings:open', shortcut: `${CtrlOrCmd()} /` },
35250
35708
  { type: 'command', title: 'Show Project Info', action: 'core:project-info' },
35251
- { type: 'command', title: 'Run Test...', cb: () => {
35252
- if (!$('.sidebar-test').is(':visible')){
35253
- $('#red-ui-tab-test-link-button').click();
35709
+ {
35710
+ type: 'command', title: 'Run Test...', cb: () => {
35711
+ if (!$('.sidebar-test').is(':visible')) {
35712
+ $('#red-ui-tab-test-link-button').click();
35713
+ }
35714
+
35715
+ $('#test-sidebar-run-btn').click();
35254
35716
  }
35255
-
35256
- $('#test-sidebar-run-btn').click();
35257
- } },
35258
- { type: 'command', title: 'Open Log Viewer', cb: ()=> {
35259
- $('#workspace-terminal').toggle()
35260
- }, shortcut: `${CtrlOrCmd()} T` },
35717
+ },
35718
+ {
35719
+ type: 'command', title: 'Open Log Viewer', cb: () => {
35720
+ $('#workspace-terminal').toggle()
35721
+ }, shortcut: `${CtrlOrCmd()} T`
35722
+ },
35261
35723
  { type: 'command', title: 'Import Flow', action: 'core:show-import-dialog', shortcut: `${CtrlOrCmd()} I` },
35262
35724
  { type: 'command', title: 'Export Flow', action: 'core:show-export-dialog', shortcut: `${CtrlOrCmd()} E` },
35263
- { type: 'command', title: 'Help: Documentation', cb: ()=> {
35725
+ // { type: 'command', title: 'SignIn to Kumologica.dev', action: 'core:signup:show' },
35726
+ {
35727
+ type: 'command', title: 'Help: Documentation', cb: () => {
35264
35728
  window.__kumologica.electron.shell.openExternal('https://docs.kumologica.com/docs/guide/Intro.html');
35265
- },
35729
+ }
35266
35730
  }
35267
35731
  ]
35268
35732
  }
35269
35733
 
35270
35734
  function CtrlOrCmd() {
35271
- return window.__kumologica.settings.platform.isMac? "⌘": "Ctrl";
35735
+ return window.__kumologica.settings.platform.isMac ? "⌘" : "Ctrl";
35272
35736
  }
35273
35737
 
35274
35738
  function ensureSelectedIsVisible() {
@@ -35364,7 +35828,7 @@ RED.notifications = (function() {
35364
35828
  // If node === undefiend and object is empty => user search yield no results
35365
35829
  // otherwise is a normal search ...
35366
35830
 
35367
- if (node === undefined && !object ) {
35831
+ if (node === undefined && !object) {
35368
35832
  // case of user search yield no results
35369
35833
  $('<div>', { class: 'red-ui-search-empty' })
35370
35834
  .text('No matches found')
@@ -35385,8 +35849,8 @@ RED.notifications = (function() {
35385
35849
  }).appendTo(div);
35386
35850
 
35387
35851
  $('<div>', { class: 'red-ui-search-result-command-label', style: 'width:95%' })
35388
- .text(object.title)
35389
- .appendTo(contentDescription);
35852
+ .text(object.title)
35853
+ .appendTo(contentDescription);
35390
35854
 
35391
35855
  // Type of object (command)
35392
35856
  $('<div>', { class: 'red-ui-search-result-command-shortcut' })
@@ -35395,16 +35859,18 @@ RED.notifications = (function() {
35395
35859
 
35396
35860
  div.click(function (evt) {
35397
35861
  evt.preventDefault();
35398
- if (object.action){
35862
+ if (object.action) {
35399
35863
  hide();
35400
- window.setTimeout( ()=> {
35401
- RED.actions.invoke(object.action)}, 10)
35864
+ window.setTimeout(() => {
35865
+ RED.actions.invoke(object.action)
35866
+ }, 10)
35402
35867
  } else {
35403
35868
  hide();
35404
- window.setTimeout( ()=> {
35405
- object.cb() }, 10)
35869
+ window.setTimeout(() => {
35870
+ object.cb()
35871
+ }, 10)
35406
35872
  }
35407
-
35873
+
35408
35874
  });
35409
35875
  }
35410
35876
 
@@ -35427,7 +35893,7 @@ RED.notifications = (function() {
35427
35893
 
35428
35894
  var colour = RED.utils.getNodeColor(node.type, def);
35429
35895
  var icon_url = RED.utils.getNodeIcon(def, node);
35430
-
35896
+
35431
35897
  if (node.type === 'tab') {
35432
35898
  var iconContainer = $('<div/>', {
35433
35899
  class: 'palette_icon_container',
@@ -35479,7 +35945,7 @@ RED.notifications = (function() {
35479
35945
  RED.view.reveal(node.id);
35480
35946
  }
35481
35947
 
35482
- function revealByNodeId(nodeId){
35948
+ function revealByNodeId(nodeId) {
35483
35949
  var selectedNode = RED.nodes.node(nodeId);
35484
35950
  reveal(selectedNode);
35485
35951
  }
@@ -35507,15 +35973,15 @@ RED.notifications = (function() {
35507
35973
  searchInput.searchBox('value', v);
35508
35974
  RED.events.emit('search:open');
35509
35975
  visible = true;
35510
- window.setTimeout(()=> {
35511
- searchInput.focus()
35976
+ window.setTimeout(() => {
35977
+ searchInput.focus()
35512
35978
  }, 50);
35513
35979
 
35514
35980
  // Populate search results with commands and tabs at least
35515
35981
  search();
35516
35982
  }
35517
35983
 
35518
-
35984
+
35519
35985
  }
35520
35986
 
35521
35987
  function hide() {