@kumologica/sdk 3.3.0-beta9 → 3.4.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 (60) hide show
  1. package/cli/commands/open.js +6 -7
  2. package/cli/commands/test-commands/TestSuiteRunner.js +75 -0
  3. package/cli/commands/test-commands/lib/TestCaseRunner.js +105 -0
  4. package/cli/commands/test-commands/lib/index.js +12 -0
  5. package/cli/commands/test-commands/lib/reporters/index.js +120 -0
  6. package/cli/commands/test.js +92 -120
  7. package/package.json +4 -5
  8. package/src/app/lib/stores/store.js +15 -1
  9. package/src/app/lib/stores/user-preference-store.js +2 -0
  10. package/src/app/lib/stores/workspace-preference-store.js +42 -0
  11. package/src/app/main-process/editor-manager.js +11 -51
  12. package/src/app/main-process/main-window.js +10 -0
  13. package/src/app/main-process/menu.js +4 -2
  14. package/src/app/main-process/modal-home.js +5 -7
  15. package/src/app/main-process/modal-newproject.js +4 -6
  16. package/src/app/main-process/modal-newtab.js +4 -6
  17. package/src/app/main-process/modal-nodelibrary.js +4 -6
  18. package/src/app/main-process/modal-welcome.js +5 -8
  19. package/src/app/main.js +3 -1
  20. package/src/app/preload.js +28 -4
  21. package/src/app/ui/editor-api/lib/index.js +6 -9
  22. package/src/app/ui/editor-client/public/red/red.js +434 -176
  23. package/src/app/ui/editor-client/public/red/red.min.js +3 -3
  24. package/src/app/ui/editor-client/public/red/style.min.css +1 -1
  25. package/src/app/ui/editor-client/public/vendor/vendor.css +21 -1
  26. package/src/app/ui/editor-client/src/js/red.js +1 -1
  27. package/src/app/ui/editor-client/src/js/ui/clipboard.js +8 -0
  28. package/src/app/ui/editor-client/src/js/ui/header.js +2 -40
  29. package/src/app/ui/editor-client/src/js/ui/palette-explorer.js +328 -0
  30. package/src/app/ui/editor-client/src/js/ui/palette.js +10 -8
  31. package/src/app/ui/editor-client/src/js/ui/project-info.js +10 -8
  32. package/src/app/ui/editor-client/src/js/ui/search.js +147 -44
  33. package/src/app/ui/editor-client/src/js/ui/ui-settings.js +1 -1
  34. package/src/app/ui/editor-client/src/js/ui/view.js +2 -5
  35. package/src/app/ui/editor-client/src/js/validators.js +2 -2
  36. package/src/app/ui/editor-client/src/sass/dropdownMenu.scss +1 -1
  37. package/src/app/ui/editor-client/src/sass/editor.scss +1 -0
  38. package/src/app/ui/editor-client/src/sass/header.scss +16 -7
  39. package/src/app/ui/editor-client/src/sass/palette.scss +46 -5
  40. package/src/app/ui/editor-client/src/sass/project-info.scss +4 -3
  41. package/src/app/ui/editor-client/src/sass/search.scss +49 -21
  42. package/src/app/ui/editor-client/src/sass/style.scss +1 -0
  43. package/src/app/ui/editor-client/src/sass/ui/common/editableList.scss +3 -3
  44. package/src/app/ui/editor-client/src/sass/ui/common/searchBox.scss +1 -2
  45. package/src/app/ui/editor-client/src/sass/ui-settings.scss +5 -3
  46. package/src/app/ui/editor-client/src/vendor/jqtree/jqtree.css +21 -1
  47. package/src/app/ui/editor-client/templates/index.mst +89 -79
  48. package/src/server/DesignerServer.js +161 -0
  49. package/src/server/certificate.pem +23 -0
  50. package/src/server/private-key.pem +28 -0
  51. package/cli/commands/test-utils/TestSuiteController.js +0 -363
  52. package/cli/commands/test-utils/TestSuiteController.test.js +0 -171
  53. package/cli/commands/test-utils/util/output.js +0 -14
  54. package/cli/commands/test-utils/util/updates/index.js +0 -17
  55. package/cli/commands/test-utils/util/updates/pkg.js +0 -13
  56. package/cli/commands/test-utils/util/updates/templates/default-settings.js +0 -209
  57. package/src/app/ui/editor-client/src/js/ui/palette-navigator.js +0 -144
  58. /package/cli/commands/{test-utils → test-commands/lib}/fixtures/example3-flow.json +0 -0
  59. /package/cli/commands/{test-utils → test-commands/lib}/fixtures/package.json +0 -0
  60. /package/cli/commands/{test-utils → test-commands/lib}/fixtures/s3-event.js +0 -0
@@ -646,7 +646,7 @@ jQuery.propHooks.disabled = {
646
646
  RED.library.init();
647
647
  RED.keyboard.init();
648
648
  RED.palette.init();
649
- RED.palette.navigator.init();
649
+ RED.palette.explorer.init();
650
650
  RED.palette.nodes.init();
651
651
  RED.eventLog.init();
652
652
  if (RED.settings.theme('palette.editable') !== false) {
@@ -5956,13 +5956,13 @@ RED.validators = {
5956
5956
  } else if (ptype === 'msg' || ptype === 'flow' || ptype === 'global' ) {
5957
5957
  return RED.utils.validatePropertyExpression(v);
5958
5958
  } else if (ptype === 'num') {
5959
- console.log('[validators] pType=num. v=', v);
5959
+ // console.log('[validators] pType=num. v=', v);
5960
5960
  return /^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$/.test(v);
5961
5961
  }
5962
5962
  return true;
5963
5963
  }},
5964
5964
  typedInputRules: function(ptypeName) { return function(v) {
5965
- console.log('[validators] TypedInput. v=', v);
5965
+ // console.log('[validators] TypedInput. v=', v);
5966
5966
  let valid = true;
5967
5967
  if (Array.isArray(v)){
5968
5968
  v.forEach( rule => {
@@ -17038,7 +17038,6 @@ RED.h = handlers;
17038
17038
  var lastSelection = null;
17039
17039
 
17040
17040
  function updateSelection(ignoreEdit) {
17041
- console.log(`[view::updateSelection] invoked - ignoreEdit=${ignoreEdit}`)
17042
17041
  var selection = {};
17043
17042
 
17044
17043
  var workspaceSelection = RED.workspaces.selection();
@@ -17164,13 +17163,11 @@ RED.h = handlers;
17164
17163
  }else{
17165
17164
  if (selectionJSON !== lastSelection) {
17166
17165
  lastSelection = selectionJSON;
17167
- console.log('[view::updateSelection] Selection has changed from lastSelection:\n', lastSelection);
17168
- console.log('[view::updateSelection] Selection has changed to selectionJSON:\n', selectionJSON);
17169
-
17170
17166
  RED.editor.edit(selection);
17171
17167
  }else{
17172
17168
  // User has clicked on the canvas or link
17173
- console.log('[view::updateSelection] Selection has not changed. Ignore');
17169
+ // console.log('[view::updateSelection] Selection has not changed. Ignore');
17170
+
17174
17171
  // Just close the sidebar
17175
17172
  RED.editor.resetEditor();
17176
17173
  }
@@ -26465,11 +26462,11 @@ RED.sidebar.azure = (function () {
26465
26462
  RED.palette.nodes.collapseAllPalette()
26466
26463
  }
26467
26464
  },
26468
- navigator: {
26469
- header: 'palette-option-projectnav-a',
26470
- panel: 'palette-projectnav',
26465
+ explorer: {
26466
+ header: 'palette-option-explorer-a',
26467
+ panel: 'palette-explorer',
26471
26468
  onSelect: () => {
26472
- RED.palette.navigator.refresh()
26469
+ RED.palette.explorer.refresh()
26473
26470
  }
26474
26471
  }
26475
26472
  }
@@ -26479,15 +26476,17 @@ RED.sidebar.azure = (function () {
26479
26476
  deselectAll();
26480
26477
  select(options.nodes);
26481
26478
  });
26482
- $(`#${options.navigator.header}`).click(e=> {
26479
+
26480
+ $(`#${options.explorer.header}`).click(e=> {
26483
26481
  deselectAll();
26484
- select(options.navigator);
26482
+ select(options.explorer);
26485
26483
  });
26486
26484
  }
26487
26485
 
26488
26486
  const deselectAll = () => {
26489
26487
  deselect(options.nodes);
26490
- deselect(options.navigator);
26488
+ deselect(options.explorer);
26489
+
26491
26490
  }
26492
26491
 
26493
26492
  const deselect = (option) => {
@@ -26506,7 +26505,7 @@ RED.sidebar.azure = (function () {
26506
26505
 
26507
26506
  const init = () => {
26508
26507
  // Preselection
26509
- deselect(options.navigator);
26508
+ deselect(options.explorer);
26510
26509
  select(options.nodes);
26511
26510
 
26512
26511
  // Handle the click events
@@ -26518,50 +26517,214 @@ RED.sidebar.azure = (function () {
26518
26517
  };
26519
26518
 
26520
26519
  })();
26521
- ;RED.palette.navigator = (function () {
26522
- const init = () => {
26523
- let addTabBtn = `<div id="createTab" class="header-btn2"><i class="icofont-plus"></i></div>`;
26524
- $(addTabBtn).appendTo($('#projectbtnnav'));
26520
+ ;RED.palette.explorer = (function () {
26521
+ let workspacePreferences = window.__kumologica.settings.workspacePreferenceStore;
26522
+ let path = window.__kumologica.libs.path;
26523
+
26524
+ const openProject = (projectLocation) => {
26525
+ window.__kumologica.main.dispatch('modal-home:open-project-in-editor', {
26526
+ payload: {
26527
+ projectLocation
26528
+ }
26529
+ });
26530
+ }
26531
+
26532
+ const initCurrentProject = () => {
26533
+ // Add Tab button
26534
+ let addTabBtn = `<div id="createTab" class="header-btn2"><i class="icofont-plus"></i></div>`;
26535
+ $(addTabBtn).appendTo($('#exp-open-project-createTab'));
26536
+ RED.popover.tooltip($('#exp-open-project-createTab'), 'Create Tab...');
26537
+
26538
+ $('#createTab').on('click', event => {
26539
+ event.stopPropagation();
26540
+ window.__kumologica.main.dispatch('navigator:open-new-tab-dialog', null);
26541
+ })
26542
+
26543
+ // Initialize the palette explorer with folder only
26544
+ let data = [
26545
+ { id: '__root__',
26546
+ name: 'OPEN PROJECT',
26547
+ children: []
26548
+ }
26549
+ ];
26550
+
26551
+ try{
26552
+ $('#exp-open-project').tree({
26553
+ data:data,
26554
+ autoOpen: true,
26555
+ selectable: true,
26556
+ onCanSelectNode: function(node) {
26557
+ if (node.id === '__root__'){
26558
+ $('#exp-open-project').tree('toggle', node);
26559
+ return false;
26560
+ } else {
26561
+ return true;
26562
+ }
26563
+
26564
+ },
26565
+ usecontextmenu: true,
26566
+ closedIcon: $('<i class="icofont-rounded-right"></i>'),
26567
+ openedIcon: $('<i class="icofont-rounded-down"></i>'),
26568
+ onCreateLi: function(node, $li) { }
26569
+ });
26570
+
26571
+ // Add the context menu
26572
+ $('#exp-open-project').jqTreeContextMenu({
26573
+ menu: '#palette-explorer-context-menu',
26574
+ onContextMenuItem: function(e, node, $el){
26575
+ let operation = $el.data("item");
26576
+ switch(operation) {
26577
+ case "open":
26578
+ RED.workspaces.showSafe(node.id);
26579
+ break;
26580
+ case "delete": {
26581
+ RED.actions.invoke('core:deploy');
26582
+ RED.workspaces.remove(node.id);
26583
+ RED.actions.invoke('core:deploy'); // save it so we can persist the tab straight away.
26584
+ refresh();
26585
+ break;
26586
+ }
26587
+ default: {}
26588
+ }
26589
+
26590
+ }
26591
+ });
26592
+ }catch(err) {
26593
+ // HACK: case where a modal is using this module, which it has no biz on tree
26594
+ }
26595
+
26596
+ let ipcRenderer = window.__kumologica.electron.ipcRenderer;
26597
+ ipcRenderer.on('create-new-tab', (event, payload)=> {
26598
+ let tabName = payload.tabName;
26599
+ if (tabName){
26600
+ createTabFn(tabName.toLowerCase());
26601
+ }
26602
+
26603
+ });
26604
+
26605
+ // On select tab option
26606
+ $('#exp-open-project').on(
26607
+ 'tree.select',
26608
+ function(event) {
26609
+ event.stopImmediatePropagation();
26610
+ if (event.node) {
26611
+ // console.log(`[palette-navigator] Select Tab=(${event.node.id})`);
26612
+ // node was selected
26613
+ var node = event.node;
26614
+ if (node.id){
26615
+ RED.workspaces.showSafe(node.id);
26616
+ }
26617
+ }
26618
+ else {
26619
+ var prevNode = event.previous_node
26620
+ if (prevNode.id){
26621
+ RED.workspaces.showSafe(prevNode.id);
26622
+ selectTab(prevNode.id);
26623
+ }
26624
+ }
26625
+ }
26626
+ );
26627
+
26628
+ refresh();
26629
+ }
26525
26630
 
26526
- // Initialize the palette navigator with folder only
26527
- let data = [
26528
- {
26529
- name: 'Project',
26631
+ const initWorkspaceProjects = () => {
26632
+ // Add Tab button
26633
+ let addProjectToWorkspaceBtn = `<div id="addProjectToWorkspace" class="header-btn2"><i class="icofont-plus"></i></div>`;
26634
+ $(addProjectToWorkspaceBtn).appendTo($('#exp-workspace-addFolder'));
26635
+ RED.popover.tooltip($('#exp-workspace-addFolder'), 'Add Project to Workspace...');
26636
+
26637
+ // Add action to the add button
26638
+ $('#addProjectToWorkspace').click((event) => {
26639
+ console.log('[palette-explorer] addProjectToWorkspaceBtn clicked');
26640
+
26641
+ let currentWindow = window.__kumologica.electron.remote.getCurrentWindow()
26642
+ let dialog = window.__kumologica.electron.remote.dialog;
26643
+ let options = {
26644
+ title: 'Select Projects to add to Workspace...',
26645
+ properties: ['openDirectory', 'multiSelections'],
26646
+ };
26647
+ dialog.showOpenDialog(currentWindow, options).then((result) => {
26648
+ if (!result.canceled){
26649
+ let projects = result.filePaths;
26650
+ console.log('[palette-explorer] projects=', projects);
26651
+ projects.forEach(project => {
26652
+ let valid = window.__kumologica.libs.findKumologicaFlowInDir(project);
26653
+ if (valid) {
26654
+ workspacePreferences.addProjectToWorkspace(project);
26655
+ } else {
26656
+ RED.notifications.notify(`<b>Invalid Kumologica project directory:</b> ${project}`, 'error', undefined, 3000);
26657
+ }
26658
+ });
26659
+ refreshWorkspaceProjects();
26660
+ }
26661
+ console.log('[palette-explorer] result=', result);
26662
+ });
26663
+ });
26664
+
26665
+ // Initialize the projects in workspace
26666
+ let data = [
26667
+ { id: '__root__',
26668
+ name: 'WORKSPACE PROJECTS',
26530
26669
  children: []
26531
26670
  }
26532
26671
  ];
26533
26672
 
26534
26673
  try{
26535
- $('#projectnav').tree({
26674
+ $('#exp-workspace').tree({
26536
26675
  data:data,
26537
26676
  autoOpen: true,
26538
26677
  selectable: true,
26678
+ onCanSelectNode: function(node) {
26679
+ if (node.id === '__root__'){
26680
+ $('#exp-workspace').tree('toggle', node);
26681
+ return false;
26682
+ } else {
26683
+ const el = $(node.element);
26684
+ const selectionRequired = !el.hasClass('jqtree-selected');
26685
+ // Deselect all nodes
26686
+ $('#exp-workspace').find('.jqtree-selected').removeClass('jqtree-selected');
26687
+
26688
+ if (selectionRequired) {
26689
+ el.addClass('jqtree-selected');
26690
+ }
26691
+
26692
+ return false;
26693
+ }
26694
+
26695
+ },
26539
26696
  usecontextmenu: true,
26540
26697
  closedIcon: $('<i class="icofont-rounded-right"></i>'),
26541
26698
  openedIcon: $('<i class="icofont-rounded-down"></i>'),
26542
26699
  onCreateLi: function(node, $li) {
26543
- // if (node.name === 'Project'){
26544
- // $li.find('.jqtree-element').append(``);
26545
- // } else {
26546
- // $li.find('.jqtree-element').addClass(selector);
26547
- // $li.find('.jqtree-element').attr('id', selector);
26548
- //}
26700
+ if (node.id !== '__root__'){
26701
+ RED.popover.tooltip(
26702
+ $li.find('.jqtree-title'),
26703
+ node.path
26704
+ );
26705
+ $li.find('.jqtree-title').before('<span class="icon" style="position: relative; left: 14px; font-size: 13px; color: #8b3ff8"><i class="fa fa-folder"></i></span>');
26706
+ }
26549
26707
  }
26550
26708
  });
26709
+
26551
26710
  // Add the context menu
26552
- $('#projectnav').jqTreeContextMenu({
26553
- menu: '#palette-context-menu',
26711
+ $('#exp-workspace').jqTreeContextMenu({
26712
+ menu: '#palette-workspace-context-menu',
26554
26713
  onContextMenuItem: function(e, node, $el){
26714
+
26555
26715
  let operation = $el.data("item");
26716
+ let projectLocation = node.path;
26717
+
26556
26718
  switch(operation) {
26557
26719
  case "open":
26558
- RED.workspaces.showSafe(node.id);
26720
+ openProject(projectLocation);
26559
26721
  break;
26560
- case "delete": {
26561
- RED.actions.invoke('core:deploy');
26562
- RED.workspaces.remove(node.id);
26563
- RED.actions.invoke('core:deploy'); // save it so we can persist the tab straight away.
26564
- refresh();
26722
+ case "openLocation":
26723
+ window.__kumologica.libs.openFolder(projectLocation);
26724
+ break;
26725
+ case "removeFromWorkspace": {
26726
+ workspacePreferences.removeProjectFromWorkspace(projectLocation);
26727
+ refreshWorkspaceProjects();
26565
26728
  break;
26566
26729
  }
26567
26730
  default: {}
@@ -26573,50 +26736,25 @@ RED.sidebar.azure = (function () {
26573
26736
  // HACK: case where a modal is using this module, which it has no biz on tree
26574
26737
  }
26575
26738
 
26576
- // Add tab button
26577
- $('#createTab').on('click', event => {
26578
- event.stopPropagation();
26579
- window.__kumologica.main.dispatch('navigator:open-new-tab-dialog', null);
26580
- })
26581
-
26582
- let ipcRenderer = window.__kumologica.electron.ipcRenderer;
26583
- ipcRenderer.on('create-new-tab', (event, payload)=> {
26584
- let tabName = payload.tabName;
26585
- if (tabName){
26586
- createTabFn(tabName.toLowerCase());
26587
- }
26588
-
26589
- });
26590
-
26739
+ // On double click project ...
26591
26740
  // On select tab option
26592
- $('#projectnav').on(
26593
- 'tree.select',
26741
+ $('#exp-workspace').on(
26742
+ 'tree.dblclick',
26594
26743
  function(event) {
26595
26744
  event.stopImmediatePropagation();
26596
- if (event.node) {
26597
- // console.log(`[palette-navigator] Select Tab=(${event.node.id})`);
26598
- // node was selected
26599
- var node = event.node;
26600
- if (node.id){
26601
- RED.workspaces.showSafe(node.id);
26602
- // selectTab(node.id);
26603
- }
26604
- // let ws = RED.nodes.workspace(node.id);
26605
- // RED.workspaces.add(ws);
26606
- // RED.workspaces.show(ws.id);
26607
-
26608
- }
26609
- else {
26610
- var prevNode = event.previous_node
26611
- if (prevNode.id){
26612
- RED.workspaces.showSafe(prevNode.id);
26613
- selectTab(prevNode.id);
26614
- }
26745
+ if (event.node && event.node.path) {
26746
+ openProject(event.node.path)
26615
26747
  }
26616
26748
  }
26617
26749
  );
26618
-
26619
- refresh();
26750
+
26751
+ }
26752
+
26753
+
26754
+
26755
+ const init = () => {
26756
+ initCurrentProject();
26757
+ initWorkspaceProjects();
26620
26758
  }
26621
26759
 
26622
26760
  const createTabFn = (newTabName) => {
@@ -26632,18 +26770,21 @@ RED.sidebar.azure = (function () {
26632
26770
  }
26633
26771
 
26634
26772
  const selectTab = (nodeId) => {
26635
- const tnode = $('#projectnav').tree('getNodeById', nodeId);
26636
- $('#projectnav').tree('selectNode', tnode);
26773
+ const tnode = $('#exp-open-project').tree('getNodeById', nodeId);
26774
+ $('#exp-open-project').tree('selectNode', tnode);
26637
26775
  // Hack to maintain the focus on the selected tab
26638
26776
  $('#workspace-tabs').addClass('workspace-focussed');
26639
26777
  }
26640
- const refresh = () => {
26778
+
26779
+ const refreshTabs = () => {
26641
26780
  if (!RED.workspaces.tabs() || RED.workspaces.tabs().length === 0) return;
26642
- // console.log('[palette-navigator#refresh] RED.workspaces.tabs()=',RED.workspaces.tabs());
26781
+
26643
26782
  const tabs = RED.nodes.listWorkspaces();
26783
+ const currentProjectName = RED.projectInfo.getWorkspaceInfo()[0].name;
26644
26784
  let data = [
26645
26785
  {
26646
- name: 'Project',
26786
+ id: '__root__',
26787
+ name: currentProjectName,
26647
26788
  children: []
26648
26789
  }
26649
26790
  ];
@@ -26652,7 +26793,49 @@ RED.sidebar.azure = (function () {
26652
26793
  data[0].children.push({ id: tabs[key].id, name: tabs[key].label })
26653
26794
  }
26654
26795
 
26655
- $('#projectnav').tree('loadData', data);
26796
+ $('#exp-open-project').tree('loadData', data);
26797
+ }
26798
+
26799
+ const refreshWorkspaceProjects = () => {
26800
+ let projects = workspacePreferences.getWorkspaceProjects();
26801
+
26802
+ // Initialize the tree with empty data
26803
+ let data = [
26804
+ {
26805
+ id: '__root__',
26806
+ name: 'WORKSPACE PROJECTS',
26807
+ children: []
26808
+ }
26809
+ ];
26810
+
26811
+
26812
+ // Update the data with info from workspace preferences
26813
+ if (projects){
26814
+ projects.forEach((project, index) => {
26815
+ let projectName = path.basename(project);
26816
+ data[0].children.push({ id: name, name: projectName, path: project });
26817
+ })
26818
+ }
26819
+
26820
+ // Render the tree
26821
+ $('#exp-workspace').tree('loadData', data);
26822
+
26823
+ // Hack to add style to the title if no projects are added. As this element is not considered a folder
26824
+ if (!projects || projects.length === 0){
26825
+ const elements = $('.jqtree-title-button-left');
26826
+ const maxElements = elements.length;
26827
+ for(let i = 0; i < maxElements; i++){
26828
+ if ($(elements[i]).text() === 'WORKSPACE PROJECTS'){
26829
+ $(elements[i]).addClass('jqtree-title-emptyfolder');
26830
+ break;
26831
+ }
26832
+ }
26833
+ }
26834
+ }
26835
+
26836
+ const refresh = () => {
26837
+ refreshTabs();
26838
+ refreshWorkspaceProjects();
26656
26839
  }
26657
26840
 
26658
26841
  return {
@@ -33515,9 +33698,15 @@ RED.eventLog = (function() {
33515
33698
  },
33516
33699
  close: function(e) {
33517
33700
  if (popover) {
33701
+ console.log(popover);
33518
33702
  popover.close(true);
33519
33703
  currentPopoverError = null;
33520
33704
  }
33705
+ // Otherwise for some fucking reason the screen gets moved to the top...
33706
+ $('#main-container').hide();
33707
+ window.setTimeout(()=> {
33708
+ $('#main-container').show()
33709
+ }, 10);
33521
33710
  }
33522
33711
  });
33523
33712
 
@@ -33659,6 +33848,8 @@ RED.eventLog = (function() {
33659
33848
  if (disabled) {
33660
33849
  return;
33661
33850
  }
33851
+ RED.actions.invoke('core:search:close');
33852
+
33662
33853
  dialogContainer.empty();
33663
33854
  dialogContainer.append($(importNodesDialog));
33664
33855
  dialogContainer.i18n();
@@ -34865,6 +35056,10 @@ RED.notifications = (function() {
34865
35056
  });
34866
35057
  }
34867
35058
 
35059
+ /**
35060
+ * User search when typing it the search box...
35061
+ * @param {string} val
35062
+ */
34868
35063
  function search(val) {
34869
35064
  searchResults.editableList('empty');
34870
35065
  var typeFilter;
@@ -34874,11 +35069,42 @@ RED.notifications = (function() {
34874
35069
  typeFilter = m[1];
34875
35070
  }
34876
35071
 
34877
- val = val.trim();
34878
-
34879
35072
  selected = -1;
35073
+
35074
+ if (val && (val.length > 0 || typeFilter)) {
35075
+ let results = searchNodes(val, typeFilter);
35076
+ if (results.length > 0) {
35077
+ // Excluding tabs
35078
+ // results = results.filter((r) => r.node.type !== 'tab');
35079
+ for (i = 0; i < Math.min(results.length, 25); i++) {
35080
+ searchResults.editableList('addItem', results[i]);
35081
+ }
35082
+ } else {
35083
+ searchResults.editableList('addItem', {});
35084
+ }
35085
+ } else {
35086
+ let commands = searchCommands();
35087
+ commands.forEach(c=> {
35088
+ searchResults.editableList('addItem', c);
35089
+ });
35090
+
35091
+ let results = $('#search-result-list');
35092
+ $('<div class="searchSeparator"></div>').appendTo(results);
35093
+
35094
+
35095
+ let allNodes = searchNodes();
35096
+
35097
+ allNodes.forEach(n => {
35098
+ searchResults.editableList('addItem', n);
35099
+ })
35100
+
35101
+ }
35102
+ }
35103
+
35104
+ function searchNodes(val, typeFilter){
34880
35105
  results = [];
34881
- if (val.length > 0 || typeFilter) {
35106
+ if (val) {
35107
+ val = val.trim();
34882
35108
  val = val.toLowerCase();
34883
35109
  var i;
34884
35110
  var j;
@@ -34909,16 +35135,47 @@ RED.notifications = (function() {
34909
35135
  for (i = 0; i < list.length; i++) {
34910
35136
  results.push(nodes[list[i]]);
34911
35137
  }
34912
- if (results.length > 0) {
34913
- // Excluding tabs
34914
- // results = results.filter((r) => r.node.type !== 'tab');
34915
- for (i = 0; i < Math.min(results.length, 25); i++) {
34916
- searchResults.editableList('addItem', results[i]);
34917
- }
34918
- } else {
34919
- searchResults.editableList('addItem', {});
35138
+ } else {
35139
+ let setResults = new Set()
35140
+ for (const i in index) {
35141
+ index[i].forEach(n => {
35142
+ if (setResults.has(n.node.id)) return;
35143
+ else {
35144
+ setResults.add(n.node.id);
35145
+ if (n.node.type === 'tab'){
35146
+ results.push({ label:n.node.label, node: n.node});
35147
+ }else {
35148
+ results.push({ label:n.node.name, node: n.node});
35149
+ }
35150
+ }
35151
+ })
34920
35152
  }
35153
+
34921
35154
  }
35155
+ return results;
35156
+
35157
+ }
35158
+ /**
35159
+ * Returns a list of commands that will be added to the search window when it is opened
35160
+ */
35161
+ function searchCommands() {
35162
+ return [
35163
+ { type: 'command', title: 'Open Settings', action: 'core:settings:open', shortcut: `${CtrlOrCmd()} ,` },
35164
+ { type: 'command', title: 'Show Project Info', action: 'core:project-info' },
35165
+ { type: 'command', title: 'Run Test...', cb: () => {
35166
+ if (!$('.sidebar-test').is(':visible')){
35167
+ $('#red-ui-tab-test-link-button').click();
35168
+ }
35169
+
35170
+ $('#test-sidebar-run-btn').click();
35171
+ } },
35172
+ { type: 'command', title: 'Import Flow', action: 'core:show-import-dialog', shortcut: `${CtrlOrCmd()} I` },
35173
+ { type: 'command', title: 'Export Flow', action: 'core:show-export-dialog', shortcut: `${CtrlOrCmd()} E` },
35174
+ ]
35175
+ }
35176
+
35177
+ function CtrlOrCmd() {
35178
+ return window.__kumologica.settings.platform.isMac? "⌘": "Ctrl";
34922
35179
  }
34923
35180
 
34924
35181
  function ensureSelectedIsVisible() {
@@ -34949,7 +35206,7 @@ RED.notifications = (function() {
34949
35206
  dialog
34950
35207
  );
34951
35208
  searchInput = $(
34952
- '<input type="text" placeholder="Find (Nodes and Tabs)">'
35209
+ '<input type="text" placeholder="Search nodes and tabs by name or type">'
34953
35210
  )
34954
35211
  .appendTo(searchDiv)
34955
35212
  .searchBox({
@@ -35009,14 +35266,55 @@ RED.notifications = (function() {
35009
35266
  addButton: false,
35010
35267
  addItem: function (container, i, object) {
35011
35268
  var node = object.node;
35012
- console.log(`[search] node = `, node);
35013
35269
 
35014
- if (node === undefined) {
35270
+ // If node === undefined and object is object => object is the command
35271
+ // If node === undefiend and object is empty => user search yield no results
35272
+ // otherwise is a normal search ...
35273
+
35274
+ if (node === undefined && !object ) {
35275
+ // case of user search yield no results
35015
35276
  $('<div>', { class: 'red-ui-search-empty' })
35016
35277
  .text('No matches found')
35017
35278
  .appendTo(container);
35018
- // } else if (node.type === 'tab') {
35019
- // }
35279
+ } else if (node === undefined && object) {
35280
+ // case of initial display of options (commands & tabs ) ... (object is a command)
35281
+ if (object.type === 'command') {
35282
+
35283
+ // Main result container
35284
+ var div = $('<a>', {
35285
+ href: '#',
35286
+ class: 'red-ui-search-result',
35287
+ }).appendTo(container);
35288
+
35289
+ // Command title here
35290
+ var contentDescription = $('<div>', {
35291
+ class: 'red-ui-search-result-description',
35292
+ }).appendTo(div);
35293
+
35294
+ $('<div>', { class: 'red-ui-search-result-command-label', style: 'width:95%' })
35295
+ .text(object.title)
35296
+ .appendTo(contentDescription);
35297
+
35298
+ // Type of object (command)
35299
+ $('<div>', { class: 'red-ui-search-result-command-shortcut' })
35300
+ .text(object.shortcut)
35301
+ .appendTo(div);
35302
+
35303
+ div.click(function (evt) {
35304
+ evt.preventDefault();
35305
+ if (object.action){
35306
+ hide();
35307
+ window.setTimeout( ()=> {
35308
+ RED.actions.invoke(object.action)}, 10)
35309
+ } else {
35310
+ hide();
35311
+ window.setTimeout( ()=> {
35312
+ object.cb() }, 10)
35313
+ }
35314
+
35315
+ });
35316
+ }
35317
+
35020
35318
  } else {
35021
35319
  var def = node._def;
35022
35320
  var div = $('<a>', {
@@ -35024,54 +35322,53 @@ RED.notifications = (function() {
35024
35322
  class: 'red-ui-search-result',
35025
35323
  }).appendTo(container);
35026
35324
 
35027
- var nodeDiv = $('<div>', {
35028
- class: 'red-ui-search-result-node',
35325
+ // ::: Part of the description
35326
+ var contentDescription = $('<div>', {
35327
+ class: 'red-ui-search-result-description',
35029
35328
  }).appendTo(div);
35329
+
35330
+ // ::: Part of the icon here...
35331
+ var nodeDiv = $('<div>', {
35332
+ class: 'ui-search-result-node',
35333
+ }).appendTo(contentDescription);
35334
+
35030
35335
  var colour = RED.utils.getNodeColor(node.type, def);
35031
35336
  var icon_url = RED.utils.getNodeIcon(def, node);
35337
+
35032
35338
  if (node.type === 'tab') {
35033
- // colour = '#C0DEED';
35034
35339
  var iconContainer = $('<div/>', {
35035
35340
  class: 'palette_icon_container',
35036
35341
  }).appendTo(nodeDiv);
35037
35342
  RED.utils.createIconElement('icons/kumologica-core/kumologica-tab.png', iconContainer, true);
35038
- }else{
35039
- // Disable the background color, we want it transparent now
35040
- //nodeDiv.css('backgroundColor', colour);
35343
+ } else {
35041
35344
  var iconContainer = $('<div/>', {
35042
35345
  class: 'palette_icon_container',
35043
35346
  }).appendTo(nodeDiv);
35044
35347
  RED.utils.createIconElement(icon_url, iconContainer, true);
35045
35348
  }
35046
-
35047
-
35048
-
35049
35349
 
35050
- var contentDiv = $('<div>', {
35051
- class: 'red-ui-search-result-description',
35052
- }).appendTo(div);
35053
35350
  if (node.z) {
35054
35351
  var workspace = RED.nodes.workspace(node.z);
35055
35352
  if (!workspace) {
35056
35353
  workspace = RED.nodes.subflow(node.z);
35057
35354
  workspace = 'subflow:' + workspace.name;
35058
35355
  } else {
35059
- workspace = 'tab:' + workspace.label; //'flow:' + workspace.label
35356
+ workspace = workspace.label; //'flow:' + workspace.label
35060
35357
  }
35061
35358
  $('<div>', { class: 'red-ui-search-result-node-flow' })
35062
35359
  .text(workspace)
35063
- .appendTo(contentDiv);
35360
+ .appendTo(div);
35064
35361
  }
35065
35362
 
35066
35363
  $('<div>', { class: 'red-ui-search-result-node-label' })
35067
35364
  .text(object.label || node.id)
35068
- .appendTo(contentDiv);
35365
+ .appendTo(contentDescription);
35069
35366
  $('<div>', { class: 'red-ui-search-result-node-type' })
35070
35367
  .text(node.type)
35071
- .appendTo(contentDiv);
35368
+ .appendTo(contentDescription);
35072
35369
  $('<div>', { class: 'red-ui-search-result-node-id' })
35073
35370
  .text(node.id)
35074
- .appendTo(contentDiv);
35371
+ .appendTo(contentDescription);
35075
35372
 
35076
35373
  div.click(function (evt) {
35077
35374
  evt.preventDefault();
@@ -35081,11 +35378,6 @@ RED.notifications = (function() {
35081
35378
  },
35082
35379
  scrollOnAdd: false,
35083
35380
  });
35084
-
35085
- // Hint to how to close the search panel
35086
- $(`
35087
- <div style="text-align:center; padding: 3px 0 5px 0">Press <span class="escape-key">Esc</span> to close</div>
35088
- `).appendTo(dialog);
35089
35381
  }
35090
35382
 
35091
35383
  function reveal(node) {
@@ -35104,11 +35396,6 @@ RED.notifications = (function() {
35104
35396
  RED.actions.invoke('core:project-info:close');
35105
35397
  RED.actions.invoke('core:settings:close');
35106
35398
 
35107
- console.log('[search] disabled=', disabled);
35108
- if (disabled) {
35109
- return;
35110
- }
35111
- console.log('[search] visible=', visible);
35112
35399
  if (!visible) {
35113
35400
  RED.keyboard.add('*', 'escape', function () {
35114
35401
  hide();
@@ -35127,8 +35414,15 @@ RED.notifications = (function() {
35127
35414
  searchInput.searchBox('value', v);
35128
35415
  RED.events.emit('search:open');
35129
35416
  visible = true;
35417
+ window.setTimeout(()=> {
35418
+ searchInput.focus()
35419
+ }, 50);
35420
+
35421
+ // Populate search results with commands and tabs at least
35422
+ search();
35130
35423
  }
35131
- searchInput.focus();
35424
+
35425
+
35132
35426
  }
35133
35427
 
35134
35428
  function hide() {
@@ -35309,11 +35603,6 @@ RED.notifications = (function() {
35309
35603
  hide();
35310
35604
  });
35311
35605
 
35312
- // Hint to how to close the search panel
35313
- $(`
35314
- <div style="text-align:center; padding: 11px 0 11px 0">Press <span class="escape-key">Esc</span> to close</div>
35315
- `).appendTo(dialog);
35316
-
35317
35606
  if (config) {
35318
35607
  setValues(config);
35319
35608
  }
@@ -35355,6 +35644,12 @@ RED.notifications = (function() {
35355
35644
  RED.view.reveal(node.id);
35356
35645
  }
35357
35646
 
35647
+ function getWorkspaceInfo() {
35648
+ return [
35649
+ { name: projectName, path: projectDir }
35650
+ ]
35651
+ }
35652
+
35358
35653
  function show(v) {
35359
35654
  // Disable the search dialog if opened
35360
35655
  RED.actions.invoke('core:search:close');
@@ -35404,9 +35699,10 @@ RED.notifications = (function() {
35404
35699
  }
35405
35700
 
35406
35701
  return {
35407
- init: init,
35408
- show: show,
35409
- hide: hide,
35702
+ init,
35703
+ show,
35704
+ hide,
35705
+ getWorkspaceInfo
35410
35706
  };
35411
35707
  })();
35412
35708
  ;RED.uiSettings = (function(){
@@ -35809,7 +36105,7 @@ RED.notifications = (function() {
35809
36105
  //console.log(`lineCount: ${cmInstance.lineCount()}`)
35810
36106
  // Set the cursor at the end of existing content
35811
36107
  cmInstance.setCursor(cmInstance.lineCount(), 0);
35812
- let codeMirrorHeight = totalHeightAvailable - 300;
36108
+ let codeMirrorHeight = totalHeightAvailable - 400;
35813
36109
 
35814
36110
  cmInstance.setSize(null, codeMirrorHeight);
35815
36111
  // cmInstance.refresh();
@@ -43869,65 +44165,27 @@ RED.touch.radialMenu = (function() {
43869
44165
  initImportExport();
43870
44166
  initShelvesFromHeader();
43871
44167
  initSettingsButtonFromHeader();
43872
- initSearchBtn();
43873
44168
  initDeployBtn();
43874
44169
  initProjectIndicator();
43875
44170
  }
43876
44171
 
43877
44172
  function initProjectIndicator() {
43878
44173
  $('#projectIndicator').click((e) => {
43879
- e.preventDefault();
43880
- if ($('#red-ui-project-info').is(':visible')) {
43881
- RED.actions.invoke('core:project-info:close');
43882
- } else {
43883
- RED.actions.invoke('core:project-info');
43884
- }
43885
- });
43886
- $('#projectInfoExpand').click((e) => {
43887
- e.preventDefault();
43888
- if ($('#red-ui-project-info').is(':visible')) {
43889
- RED.actions.invoke('core:project-info:close');
43890
- } else {
43891
- RED.actions.invoke('core:project-info');
43892
- }
43893
- });
43894
- $('#projectIndicator').hover(
43895
- () => {
43896
- $('#projectInfoExpand').css('color', '#999');
43897
- },
43898
- () => {
43899
- $('#projectInfoExpand').css('color', '#ecebeb');
43900
- }
43901
- );
43902
- $('#projectInfoExpand').hover(
43903
- () => {
43904
- $('#projectInfoExpand').css('color', '#999');
43905
- },
43906
- () => {
43907
- $('#projectInfoExpand').css('color', '#ecebeb');
43908
- }
43909
- );
43910
- }
43911
-
43912
- function initSearchBtn() {
43913
- $('#btn-search').click((e) => {
43914
44174
  e.preventDefault();
43915
44175
  if ($('#red-ui-search').is(':visible')) {
43916
- console.log('[header] closing search panel')
43917
44176
  RED.actions.invoke('core:search:close');
43918
44177
  } else {
43919
- console.log('[header] opening search panel')
43920
44178
  RED.actions.invoke('core:search');
43921
44179
  }
43922
44180
  });
43923
44181
  }
43924
44182
 
43925
-
43926
44183
  function initDeployBtn() {
43927
44184
  RED.actions.add('core:deploy', deployFlow);
43928
44185
 
43929
44186
  $('#btn-deploy').click((e) => {
43930
- RED.actions.invoke('core:deploy');
44187
+ e.stopPropagation();
44188
+ RED.actions.invoke('core:deploy');
43931
44189
  });
43932
44190
 
43933
44191
  // RED.popover.tooltip($('#btn-deploy'), 'Save & Deploy');