@finos/legend-application-studio 26.1.11 → 27.1.0

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 (136) hide show
  1. package/lib/__lib__/LegendStudioApplicationNavigationContext.d.ts +9 -1
  2. package/lib/__lib__/LegendStudioApplicationNavigationContext.d.ts.map +1 -1
  3. package/lib/__lib__/LegendStudioApplicationNavigationContext.js +11 -1
  4. package/lib/__lib__/LegendStudioApplicationNavigationContext.js.map +1 -1
  5. package/lib/application/LegendStudioApplicationConfig.d.ts +6 -0
  6. package/lib/application/LegendStudioApplicationConfig.d.ts.map +1 -1
  7. package/lib/application/LegendStudioApplicationConfig.js +7 -0
  8. package/lib/application/LegendStudioApplicationConfig.js.map +1 -1
  9. package/lib/components/ElementIconUtils.d.ts.map +1 -1
  10. package/lib/components/ElementIconUtils.js +3 -1
  11. package/lib/components/ElementIconUtils.js.map +1 -1
  12. package/lib/components/editor/editor-group/ModelImporter.d.ts.map +1 -1
  13. package/lib/components/editor/editor-group/ModelImporter.js +1 -0
  14. package/lib/components/editor/editor-group/ModelImporter.js.map +1 -1
  15. package/lib/components/editor/editor-group/connection-editor/DatabaseBuilder.d.ts.map +1 -1
  16. package/lib/components/editor/editor-group/connection-editor/DatabaseBuilder.js +8 -10
  17. package/lib/components/editor/editor-group/connection-editor/DatabaseBuilder.js.map +1 -1
  18. package/lib/components/editor/editor-group/data-editor/EmbeddedDataEditor.d.ts.map +1 -1
  19. package/lib/components/editor/editor-group/data-editor/EmbeddedDataEditor.js +5 -0
  20. package/lib/components/editor/editor-group/data-editor/EmbeddedDataEditor.js.map +1 -1
  21. package/lib/components/editor/editor-group/data-editor/RelationalCSVDataEditor.d.ts.map +1 -1
  22. package/lib/components/editor/editor-group/data-editor/RelationalCSVDataEditor.js +3 -0
  23. package/lib/components/editor/editor-group/data-editor/RelationalCSVDataEditor.js.map +1 -1
  24. package/lib/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_BindingElementEditor.d.ts.map +1 -1
  25. package/lib/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_BindingElementEditor.js +3 -0
  26. package/lib/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_BindingElementEditor.js.map +1 -1
  27. package/lib/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_SchemaSetElementEditor.d.ts.map +1 -1
  28. package/lib/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_SchemaSetElementEditor.js +3 -0
  29. package/lib/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_SchemaSetElementEditor.js.map +1 -1
  30. package/lib/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_SchemaSetModelGenerationEditor.d.ts.map +1 -1
  31. package/lib/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_SchemaSetModelGenerationEditor.js +3 -0
  32. package/lib/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_SchemaSetModelGenerationEditor.js.map +1 -1
  33. package/lib/components/editor/editor-group/mapping-editor/NewMappingElementModal.js +1 -2
  34. package/lib/components/editor/editor-group/mapping-editor/NewMappingElementModal.js.map +1 -1
  35. package/lib/components/editor/editor-group/project-configuration-editor/ProjectDependencyEditor.d.ts.map +1 -1
  36. package/lib/components/editor/editor-group/project-configuration-editor/ProjectDependencyEditor.js +6 -6
  37. package/lib/components/editor/editor-group/project-configuration-editor/ProjectDependencyEditor.js.map +1 -1
  38. package/lib/components/editor/editor-group/service-editor/testable/ServiceTestsEditor.d.ts.map +1 -1
  39. package/lib/components/editor/editor-group/service-editor/testable/ServiceTestsEditor.js +16 -5
  40. package/lib/components/editor/editor-group/service-editor/testable/ServiceTestsEditor.js.map +1 -1
  41. package/lib/components/editor/panel-group/SQLPlaygroundPanel.d.ts.map +1 -1
  42. package/lib/components/editor/panel-group/SQLPlaygroundPanel.js +38 -6
  43. package/lib/components/editor/panel-group/SQLPlaygroundPanel.js.map +1 -1
  44. package/lib/components/editor/side-bar/CreateNewElementModal.d.ts +3 -0
  45. package/lib/components/editor/side-bar/CreateNewElementModal.d.ts.map +1 -1
  46. package/lib/components/editor/side-bar/CreateNewElementModal.js +43 -1
  47. package/lib/components/editor/side-bar/CreateNewElementModal.js.map +1 -1
  48. package/lib/components/editor/side-bar/testable/GlobalTestRunner.d.ts.map +1 -1
  49. package/lib/components/editor/side-bar/testable/GlobalTestRunner.js +15 -14
  50. package/lib/components/editor/side-bar/testable/GlobalTestRunner.js.map +1 -1
  51. package/lib/components/extensions/Core_LegendStudioApplicationPlugin.d.ts.map +1 -1
  52. package/lib/components/extensions/Core_LegendStudioApplicationPlugin.js +10 -0
  53. package/lib/components/extensions/Core_LegendStudioApplicationPlugin.js.map +1 -1
  54. package/lib/index.css +2 -2
  55. package/lib/index.css.map +1 -1
  56. package/lib/package.json +4 -4
  57. package/lib/stores/LegendStudioApplicationPlugin.d.ts +7 -7
  58. package/lib/stores/LegendStudioApplicationPlugin.d.ts.map +1 -1
  59. package/lib/stores/LegendStudioApplicationPlugin.js.map +1 -1
  60. package/lib/stores/editor/EditorGraphState.js +1 -1
  61. package/lib/stores/editor/EditorGraphState.js.map +1 -1
  62. package/lib/stores/editor/EditorStore.d.ts.map +1 -1
  63. package/lib/stores/editor/EditorStore.js +10 -2
  64. package/lib/stores/editor/EditorStore.js.map +1 -1
  65. package/lib/stores/editor/GraphEditFormModeState.d.ts.map +1 -1
  66. package/lib/stores/editor/GraphEditFormModeState.js +0 -1
  67. package/lib/stores/editor/GraphEditFormModeState.js.map +1 -1
  68. package/lib/stores/editor/NewElementState.d.ts +0 -1
  69. package/lib/stores/editor/NewElementState.d.ts.map +1 -1
  70. package/lib/stores/editor/NewElementState.js +47 -12
  71. package/lib/stores/editor/NewElementState.js.map +1 -1
  72. package/lib/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.d.ts +0 -1
  73. package/lib/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.d.ts.map +1 -1
  74. package/lib/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.js +26 -30
  75. package/lib/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.js.map +1 -1
  76. package/lib/stores/editor/editor-state/element-editor-state/mapping/MappingEditorState.d.ts +4 -1
  77. package/lib/stores/editor/editor-state/element-editor-state/mapping/MappingEditorState.d.ts.map +1 -1
  78. package/lib/stores/editor/editor-state/element-editor-state/mapping/MappingEditorState.js +5 -1
  79. package/lib/stores/editor/editor-state/element-editor-state/mapping/MappingEditorState.js.map +1 -1
  80. package/lib/stores/editor/editor-state/element-editor-state/service/ServicePostValidationState.js +1 -1
  81. package/lib/stores/editor/editor-state/element-editor-state/service/ServicePostValidationState.js.map +1 -1
  82. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestEditorState.d.ts.map +1 -1
  83. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestEditorState.js +3 -1
  84. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestEditorState.js.map +1 -1
  85. package/lib/stores/editor/editor-state/project-configuration-editor-state/ProjectDependencyEditorState.d.ts +1 -1
  86. package/lib/stores/editor/editor-state/project-configuration-editor-state/ProjectDependencyEditorState.d.ts.map +1 -1
  87. package/lib/stores/editor/editor-state/project-configuration-editor-state/ProjectDependencyEditorState.js +2 -2
  88. package/lib/stores/editor/editor-state/project-configuration-editor-state/ProjectDependencyEditorState.js.map +1 -1
  89. package/lib/stores/editor/panel-group/SQLPlaygroundPanelState.d.ts +9 -0
  90. package/lib/stores/editor/panel-group/SQLPlaygroundPanelState.d.ts.map +1 -1
  91. package/lib/stores/editor/panel-group/SQLPlaygroundPanelState.js +149 -3
  92. package/lib/stores/editor/panel-group/SQLPlaygroundPanelState.js.map +1 -1
  93. package/lib/stores/editor/sidebar-state/BulkServiceRegistrationState.js +1 -1
  94. package/lib/stores/editor/sidebar-state/BulkServiceRegistrationState.js.map +1 -1
  95. package/lib/stores/editor/utils/MockDataUtils.d.ts +1 -1
  96. package/lib/stores/editor/utils/MockDataUtils.d.ts.map +1 -1
  97. package/lib/stores/editor/utils/MockDataUtils.js.map +1 -1
  98. package/lib/stores/editor/utils/ModelClassifierUtils.d.ts +2 -5
  99. package/lib/stores/editor/utils/ModelClassifierUtils.d.ts.map +1 -1
  100. package/lib/stores/editor/utils/ModelClassifierUtils.js +2 -6
  101. package/lib/stores/editor/utils/ModelClassifierUtils.js.map +1 -1
  102. package/lib/stores/editor/utils/PackageTreeUtils.js +3 -3
  103. package/lib/stores/editor/utils/PackageTreeUtils.js.map +1 -1
  104. package/package.json +14 -14
  105. package/src/__lib__/LegendStudioApplicationNavigationContext.ts +12 -1
  106. package/src/application/LegendStudioApplicationConfig.ts +8 -0
  107. package/src/components/ElementIconUtils.tsx +3 -0
  108. package/src/components/editor/editor-group/ModelImporter.tsx +4 -0
  109. package/src/components/editor/editor-group/connection-editor/DatabaseBuilder.tsx +12 -13
  110. package/src/components/editor/editor-group/data-editor/EmbeddedDataEditor.tsx +11 -1
  111. package/src/components/editor/editor-group/data-editor/RelationalCSVDataEditor.tsx +6 -0
  112. package/src/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_BindingElementEditor.tsx +7 -0
  113. package/src/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_SchemaSetElementEditor.tsx +6 -0
  114. package/src/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_SchemaSetModelGenerationEditor.tsx +6 -0
  115. package/src/components/editor/editor-group/mapping-editor/NewMappingElementModal.tsx +1 -1
  116. package/src/components/editor/editor-group/project-configuration-editor/ProjectDependencyEditor.tsx +6 -10
  117. package/src/components/editor/editor-group/service-editor/testable/ServiceTestsEditor.tsx +22 -9
  118. package/src/components/editor/panel-group/SQLPlaygroundPanel.tsx +104 -18
  119. package/src/components/editor/side-bar/CreateNewElementModal.tsx +111 -1
  120. package/src/components/editor/side-bar/testable/GlobalTestRunner.tsx +21 -23
  121. package/src/components/extensions/Core_LegendStudioApplicationPlugin.tsx +10 -0
  122. package/src/stores/LegendStudioApplicationPlugin.ts +7 -11
  123. package/src/stores/editor/EditorGraphState.ts +1 -1
  124. package/src/stores/editor/EditorStore.ts +29 -17
  125. package/src/stores/editor/GraphEditFormModeState.ts +0 -1
  126. package/src/stores/editor/NewElementState.ts +115 -23
  127. package/src/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.ts +33 -40
  128. package/src/stores/editor/editor-state/element-editor-state/mapping/MappingEditorState.ts +5 -1
  129. package/src/stores/editor/editor-state/element-editor-state/service/ServicePostValidationState.ts +1 -1
  130. package/src/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestEditorState.ts +12 -2
  131. package/src/stores/editor/editor-state/project-configuration-editor-state/ProjectDependencyEditorState.ts +2 -2
  132. package/src/stores/editor/panel-group/SQLPlaygroundPanelState.ts +224 -1
  133. package/src/stores/editor/sidebar-state/BulkServiceRegistrationState.ts +1 -1
  134. package/src/stores/editor/utils/MockDataUtils.ts +1 -1
  135. package/src/stores/editor/utils/ModelClassifierUtils.ts +2 -6
  136. package/src/stores/editor/utils/PackageTreeUtils.ts +3 -3
@@ -81,6 +81,8 @@ export const getElementTypeLabel = (
81
81
  return 'generation specification';
82
82
  case PACKAGEABLE_ELEMENT_TYPE.DATA:
83
83
  return 'data';
84
+ case PACKAGEABLE_ELEMENT_TYPE.TEMPORARY__LOCAL_CONNECTION:
85
+ return 'local connection';
84
86
  default: {
85
87
  if (type) {
86
88
  const extraElementTypeLabelGetters = editorStore.pluginManager
@@ -436,7 +438,115 @@ const renderNewElementDriver = (
436
438
  }
437
439
  };
438
440
 
439
- // TODO: investigate the potential approach of VSCode to have inline input in the tree to create element quickly
441
+ export const CreateNewLocalConnectionModal = observer(() => {
442
+ const editorStore = useEditorStore();
443
+ const applicationStore = useApplicationStore();
444
+ const newElementState = editorStore.newElementState;
445
+ const selectedPackage = newElementState.selectedPackage;
446
+ // Name
447
+ const name = newElementState.name;
448
+ const handleNameChange: React.ChangeEventHandler<HTMLInputElement> = (
449
+ event,
450
+ ) => newElementState.setName(event.target.value);
451
+ const elementNameInputRef = useRef<HTMLInputElement>(null);
452
+ // Type
453
+ const typeOptions = ([PACKAGEABLE_ELEMENT_TYPE.PACKAGE] as string[])
454
+ .concat(editorStore.getSupportedElementTypes())
455
+ .filter(
456
+ // NOTE: we can only create package in root
457
+ (type) =>
458
+ selectedPackage !== editorStore.graphManagerState.graph.root ||
459
+ type === PACKAGEABLE_ELEMENT_TYPE.PACKAGE,
460
+ )
461
+ .map(buildElementTypeOption);
462
+
463
+ const selectedTypeOption = buildElementTypeOption(newElementState.type);
464
+ const handleTypeChange = (val: ElementTypeSelectOption): void =>
465
+ newElementState.setElementType(val.value);
466
+ // Submit button
467
+ const closeModal = (): void => newElementState.closeModal();
468
+ const [packagePath, elementName] = resolvePackageAndElementName(
469
+ selectedPackage,
470
+ selectedPackage === editorStore.graphManagerState.graph.root,
471
+ name,
472
+ );
473
+ const resolvedPackage =
474
+ editorStore.graphManagerState.graph.getNullablePackage(packagePath);
475
+ const needsToOverride = Boolean(
476
+ resolvedPackage?.children.find((child) => child.name === elementName),
477
+ );
478
+ const isDisabled = !name || needsToOverride || !newElementState.isValid;
479
+ const save = applicationStore.guardUnhandledError(() =>
480
+ flowResult(newElementState.save()),
481
+ );
482
+ const handleEnter = (): void => {
483
+ newElementState.setName('');
484
+ elementNameInputRef.current?.focus();
485
+ };
486
+
487
+ if (!newElementState.showModal) {
488
+ return null;
489
+ }
490
+ return (
491
+ <Dialog
492
+ open={newElementState.showModal}
493
+ onClose={closeModal}
494
+ TransitionProps={{
495
+ onEnter: handleEnter,
496
+ }}
497
+ classes={{ container: 'search-modal__container' }}
498
+ PaperProps={{ classes: { root: 'search-modal__inner-container' } }}
499
+ >
500
+ <form
501
+ data-testid={LEGEND_STUDIO_TEST_ID.NEW_ELEMENT_MODAL}
502
+ onSubmit={(event) => {
503
+ event.preventDefault();
504
+ save();
505
+ }}
506
+ className="modal modal--dark search-modal"
507
+ >
508
+ <div className="modal__title">
509
+ {`Create a New ${
510
+ getElementTypeLabel(editorStore, newElementState.type) ?? 'element'
511
+ }`}
512
+ </div>
513
+ <div>
514
+ {newElementState.showType && (
515
+ <CustomSelectorInput
516
+ options={typeOptions}
517
+ disabled={typeOptions.length === 1}
518
+ onChange={handleTypeChange}
519
+ value={selectedTypeOption}
520
+ isClearable={false}
521
+ darkMode={true}
522
+ />
523
+ )}
524
+ <input
525
+ className="input--dark explorer__new-element-modal__name-input"
526
+ ref={elementNameInputRef}
527
+ spellCheck={false}
528
+ value={name}
529
+ onChange={handleNameChange}
530
+ placeholder={`Enter a name, use ${ELEMENT_PATH_DELIMITER} to create new package(s) for the ${
531
+ getElementTypeLabel(editorStore, newElementState.type) ??
532
+ 'element'
533
+ }`}
534
+ />
535
+ {renderNewElementDriver(newElementState.type, editorStore)}
536
+ </div>
537
+ <div className="search-modal__actions">
538
+ <button type="button" className="btn btn--dark" onClick={closeModal}>
539
+ Cancel
540
+ </button>
541
+ <button className="btn btn--dark" disabled={isDisabled}>
542
+ Create
543
+ </button>
544
+ </div>
545
+ </form>
546
+ </Dialog>
547
+ );
548
+ });
549
+
440
550
  export const CreateNewElementModal = observer(() => {
441
551
  const editorStore = useEditorStore();
442
552
  const applicationStore = useApplicationStore();
@@ -54,7 +54,6 @@ import {
54
54
  type GeneratorFn,
55
55
  isNonNullable,
56
56
  prettyCONSTName,
57
- toTitleCase,
58
57
  } from '@finos/legend-shared';
59
58
  import { observer } from 'mobx-react-lite';
60
59
  import { forwardRef, useEffect, useState } from 'react';
@@ -429,23 +428,28 @@ export const GlobalTestRunner = observer(
429
428
  const editorStore = useEditorStore();
430
429
  const globalTestRunnerState = props.globalTestRunnerState;
431
430
  const isDispatchingAction = globalTestRunnerState.isDispatchingAction;
432
- const testRunnerTabs = (Object.values(TEST_RUNNER_TABS) as string[])
433
- .concat(
434
- editorStore.pluginManager
435
- .getApplicationPlugins()
436
- .flatMap(
437
- (plugin) => plugin.getExtraTestRunnerTabClassifiers?.() ?? [],
438
- ),
439
- )
440
- .map((e) => ({
441
- value: e,
442
- label: prettyCONSTName(e),
443
- }));
444
431
 
445
432
  const [selectedTab, setSelectedTab] = useState(
446
433
  TEST_RUNNER_TABS.TEST_RUNNER.valueOf(),
447
434
  );
448
435
 
436
+ const extractTestRunnerTabConfigurations = editorStore.pluginManager
437
+ .getApplicationPlugins()
438
+ .flatMap((plugin) => plugin.getExtraTestRunnerTabConfigurations?.() ?? [])
439
+ .filter((configuration) => configuration.renderer(editorStore));
440
+
441
+ const testRunnerTabs = (Object.values(TEST_RUNNER_TABS) as string[])
442
+ .map((e) => ({
443
+ value: e,
444
+ label: prettyCONSTName(e),
445
+ }))
446
+ .concat(
447
+ extractTestRunnerTabConfigurations.map((config) => ({
448
+ value: config.key,
449
+ label: config.title,
450
+ })),
451
+ );
452
+
449
453
  const changeTab = (tab: string): void => {
450
454
  setSelectedTab(tab);
451
455
  };
@@ -544,7 +548,7 @@ export const GlobalTestRunner = observer(
544
548
  ['panel__header__tab--active']: tab.value === selectedTab,
545
549
  })}
546
550
  >
547
- {toTitleCase(prettyCONSTName(tab.value))}
551
+ {tab.label}
548
552
  </div>
549
553
  ))}
550
554
  </div>
@@ -578,15 +582,9 @@ export const GlobalTestRunner = observer(
578
582
  </div>
579
583
  );
580
584
  } else {
581
- const extraTestRunnerTabEditorRenderers = editorStore.pluginManager
582
- .getApplicationPlugins()
583
- .flatMap(
584
- (plugin) => plugin.getExtraTestRunnerTabEditorRenderers?.() ?? [],
585
- );
586
- for (const editorRenderer of extraTestRunnerTabEditorRenderers) {
587
- const editor = editorRenderer(selectedTab, editorStore);
588
- if (editor) {
589
- return editor;
585
+ for (const testRunnerTabConfiguration of extractTestRunnerTabConfigurations) {
586
+ if (testRunnerTabConfiguration.key === selectedTab) {
587
+ return testRunnerTabConfiguration.renderer(editorStore);
590
588
  }
591
589
  }
592
590
  return (
@@ -133,6 +133,16 @@ export class Core_LegendStudioApplicationPlugin extends LegendStudioApplicationP
133
133
  LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.CONNECTION_EDITOR,
134
134
  LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.DATABASE_BUILDER,
135
135
  LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.SERVICE_EDITOR,
136
+ LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.DATA_ELEMENT_EDITOR,
137
+ LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.MAPPING_EDITOR,
138
+ LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.RUNTIME_EDITOR,
139
+ LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.BINDING_EDITOR,
140
+ LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.SCHEMA_SET_EDITOR,
141
+ LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.SCHEMA_SET_MODEL_GENERATION,
142
+ LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.EMBEDDED_DATA_RELATIONAL_EDITOR,
143
+ LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.EMBEDDED_DATA_EXTERNAL_FORMAT_EDITOR,
144
+ LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.EMBEDDED_DATA_DATA_ELEMENT_REFERENCE_EDITOR,
145
+ LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.EMBEDDED_DATA_MODEL_STORE_EDITOR,
136
146
  ];
137
147
  }
138
148
 
@@ -77,10 +77,11 @@ export type TestableMetadataGetter = (
77
77
  editorStore: EditorStore,
78
78
  ) => TestableMetadata | undefined;
79
79
 
80
- export type TestRunnerTabRenderer = (
81
- selectedTab: string,
82
- editorStore: EditorStore,
83
- ) => React.ReactNode | undefined;
80
+ export type TestRunnerTabConfiguration = {
81
+ key: string;
82
+ title: string;
83
+ renderer: (editorStore: EditorStore) => React.ReactNode | undefined;
84
+ };
84
85
 
85
86
  export abstract class LegendStudioApplicationPlugin extends LegendApplicationPlugin {
86
87
  /**
@@ -126,14 +127,9 @@ export abstract class LegendStudioApplicationPlugin extends LegendApplicationPlu
126
127
  getExtraTestableMetadata?(): TestableMetadataGetter[];
127
128
 
128
129
  /**
129
- * Get the list of the supported classifers for test runner tabs.
130
- */
131
- getExtraTestRunnerTabClassifiers?(): string[];
132
-
133
- /**
134
- * Get the list of renderers for the editor for a test runner tab.
130
+ * Get the list of configurations for the editor for a test runner tab.
135
131
  */
136
- getExtraTestRunnerTabEditorRenderers?(): TestRunnerTabRenderer[];
132
+ getExtraTestRunnerTabConfigurations?(): TestRunnerTabConfiguration[];
137
133
  }
138
134
 
139
135
  export type PureGrammarElementLabeler = (
@@ -860,6 +860,6 @@ export class EditorGraphState {
860
860
  return label;
861
861
  }
862
862
  }
863
- return PACKAGEABLE_ELEMENT_TYPE.UNKNOWN;
863
+ return PACKAGEABLE_ELEMENT_TYPE.INTERNAL__UNKNOWN;
864
864
  }
865
865
  }
@@ -929,25 +929,37 @@ export class EditorStore implements CommandRegistrar {
929
929
  PACKAGEABLE_ELEMENT_TYPE.ASSOCIATION,
930
930
  PACKAGEABLE_ELEMENT_TYPE.FUNCTION,
931
931
  PACKAGEABLE_ELEMENT_TYPE.MEASURE,
932
- PACKAGEABLE_ELEMENT_TYPE.MAPPING,
933
- PACKAGEABLE_ELEMENT_TYPE.RUNTIME,
934
- PACKAGEABLE_ELEMENT_TYPE.CONNECTION,
935
- PACKAGEABLE_ELEMENT_TYPE.SERVICE,
936
- PACKAGEABLE_ELEMENT_TYPE.GENERATION_SPECIFICATION,
937
- PACKAGEABLE_ELEMENT_TYPE.FILE_GENERATION,
938
- PACKAGEABLE_ELEMENT_TYPE.FLAT_DATA_STORE,
939
- PACKAGEABLE_ELEMENT_TYPE.DATABASE,
940
- PACKAGEABLE_ELEMENT_TYPE.DATA,
941
932
  ] as string[]
942
933
  ).concat(
943
- this.pluginManager
944
- .getApplicationPlugins()
945
- .flatMap(
946
- (plugin) =>
947
- (
948
- plugin as DSL_LegendStudioApplicationPlugin_Extension
949
- ).getExtraSupportedElementTypes?.() ?? [],
950
- ),
934
+ (
935
+ [
936
+ PACKAGEABLE_ELEMENT_TYPE.MAPPING,
937
+ PACKAGEABLE_ELEMENT_TYPE.RUNTIME,
938
+ PACKAGEABLE_ELEMENT_TYPE.CONNECTION,
939
+ PACKAGEABLE_ELEMENT_TYPE.SERVICE,
940
+ PACKAGEABLE_ELEMENT_TYPE.GENERATION_SPECIFICATION,
941
+ PACKAGEABLE_ELEMENT_TYPE.FILE_GENERATION,
942
+ PACKAGEABLE_ELEMENT_TYPE.FLAT_DATA_STORE,
943
+ PACKAGEABLE_ELEMENT_TYPE.DATABASE,
944
+ PACKAGEABLE_ELEMENT_TYPE.DATA,
945
+ this.applicationStore.config.options
946
+ .TEMPORARY__enableLocalConnectionBuilder
947
+ ? PACKAGEABLE_ELEMENT_TYPE.TEMPORARY__LOCAL_CONNECTION
948
+ : undefined,
949
+ ] as (string | undefined)[]
950
+ )
951
+ .filter(isNonNullable)
952
+ .concat(
953
+ this.pluginManager
954
+ .getApplicationPlugins()
955
+ .flatMap(
956
+ (plugin) =>
957
+ (
958
+ plugin as DSL_LegendStudioApplicationPlugin_Extension
959
+ ).getExtraSupportedElementTypes?.() ?? [],
960
+ ),
961
+ )
962
+ .sort((a, b) => a.localeCompare(b)),
951
963
  );
952
964
  }
953
965
 
@@ -578,7 +578,6 @@ export class GraphEditFormModeState extends GraphEditorMode {
578
578
 
579
579
  *onLeave(): GeneratorFn<void> {
580
580
  this.editorStore.sqlPlaygroundState.setConnection(undefined);
581
- return;
582
581
  }
583
582
 
584
583
  *cleanupBeforeEntering(fallbackOptions?: {
@@ -66,7 +66,6 @@ import {
66
66
  PackageableElementExplicitReference,
67
67
  RelationalDatabaseConnection,
68
68
  DatabaseType,
69
- StaticDatasourceSpecification,
70
69
  DefaultH2AuthenticationStrategy,
71
70
  ModelGenerationSpecification,
72
71
  DataElement,
@@ -74,6 +73,13 @@ import {
74
73
  Measure,
75
74
  Multiplicity,
76
75
  PrimitiveType,
76
+ LocalH2DatasourceSpecification,
77
+ SnowflakeDatasourceSpecification,
78
+ SnowflakePublicAuthenticationStrategy,
79
+ StoreConnections,
80
+ ConnectionPointer,
81
+ IdentifiedConnection,
82
+ generateIdentifiedConnectionId,
77
83
  } from '@finos/legend-graph';
78
84
  import type { DSL_Mapping_LegendStudioApplicationPlugin_Extension } from '../extensions/DSL_Mapping_LegendStudioApplicationPlugin_Extension.js';
79
85
  import {
@@ -302,6 +308,8 @@ export class NewFlatDataConnectionDriver extends NewConnectionValueDriver<FlatDa
302
308
  }
303
309
  }
304
310
 
311
+ const DEFAULT_H2_SQL =
312
+ '-- loads sample data for getting started. See https://github.com/pthom/northwind_psql for more info\n call loadNorthwindData()';
305
313
  export class NewRelationalDatabaseConnectionDriver extends NewConnectionValueDriver<RelationalDatabaseConnection> {
306
314
  constructor(editorStore: EditorStore) {
307
315
  super(editorStore);
@@ -327,10 +335,12 @@ export class NewRelationalDatabaseConnectionDriver extends NewConnectionValueDri
327
335
  const dbs = this.editorStore.graphManagerState.usableDatabases;
328
336
  selectedStore = dbs.length ? (dbs[0] as Database) : stub_Database();
329
337
  }
338
+ const spec = new LocalH2DatasourceSpecification();
339
+ spec.testDataSetupSqls = [DEFAULT_H2_SQL];
330
340
  return new RelationalDatabaseConnection(
331
341
  PackageableElementExplicitReference.create(selectedStore),
332
342
  DatabaseType.H2,
333
- new StaticDatasourceSpecification('dummyHost', 80, 'myDb'),
343
+ spec,
334
344
  new DefaultH2AuthenticationStrategy(),
335
345
  );
336
346
  }
@@ -440,7 +450,6 @@ export class NewPackageableConnectionDriver extends NewElementDriver<Packageable
440
450
  this.store = store;
441
451
  this.newConnectionValueDriver = newDriver;
442
452
  }
443
- return;
444
453
  }
445
454
 
446
455
  get isValid(): boolean {
@@ -643,7 +652,6 @@ export class NewElementState {
643
652
  _package: observable,
644
653
  name: observable,
645
654
  newElementDriver: observable,
646
- elementAndPackageName: computed,
647
655
  selectedPackage: computed,
648
656
  isValid: computed,
649
657
  setShowModal: action,
@@ -662,14 +670,6 @@ export class NewElementState {
662
670
  this.type = PACKAGEABLE_ELEMENT_TYPE.PACKAGE;
663
671
  }
664
672
 
665
- get elementAndPackageName(): [string, string] {
666
- return resolvePackageAndElementName(
667
- this.selectedPackage,
668
- this._package === this.editorStore.graphManagerState.graph.root,
669
- this.name,
670
- );
671
- }
672
-
673
673
  get selectedPackage(): Package {
674
674
  return this._package
675
675
  ? this._package
@@ -775,7 +775,11 @@ export class NewElementState {
775
775
 
776
776
  *save(): GeneratorFn<void> {
777
777
  if (this.name && this.isValid) {
778
- const [packagePath, elementName] = this.elementAndPackageName;
778
+ const [packagePath, elementName] = resolvePackageAndElementName(
779
+ this.selectedPackage,
780
+ this._package === this.editorStore.graphManagerState.graph.root,
781
+ this.name,
782
+ );
779
783
  if (
780
784
  this.editorStore.graphManagerState.graph.getNullablePackage(
781
785
  packagePath,
@@ -786,17 +790,105 @@ export class NewElementState {
786
790
  `Can't create elements for type other than 'package' in root package`,
787
791
  );
788
792
  } else {
789
- const element = this.createElement(elementName);
790
- yield flowResult(
791
- this.editorStore.graphEditorMode.addElement(
792
- element,
793
- packagePath,
794
- true,
795
- ),
796
- );
793
+ if (
794
+ this.editorStore.applicationStore.config.options
795
+ .TEMPORARY__enableLocalConnectionBuilder &&
796
+ this.type === PACKAGEABLE_ELEMENT_TYPE.TEMPORARY__LOCAL_CONNECTION
797
+ ) {
798
+ // NOTE: this is temporary until we have proper support for local connection
799
+ // For now, we aim to fulfill the PoC for SnowflakeApp use case and will generate
800
+ // everything: mapping, store, connection, runtime, etc.
801
+ const store = new Database(`${this.name}_Database`);
802
+ const mapping = new Mapping(`${this.name}_Mapping`);
803
+ // connection
804
+ const connection = new PackageableConnection(
805
+ `${this.name}_LocalConnection`,
806
+ );
807
+ const _suffix = `${packagePath.replaceAll(
808
+ ELEMENT_PATH_DELIMITER,
809
+ '-',
810
+ )}-${connection.name}`;
811
+ const datasourceSpecification = new SnowflakeDatasourceSpecification(
812
+ `legend-local-snowflake-accountName-${_suffix}`,
813
+ `legend-local-snowflake-region-${_suffix}`,
814
+ `legend-local-snowflake-warehouseName-${_suffix}`,
815
+ `legend-local-snowflake-databaseName-${_suffix}`,
816
+ );
817
+ datasourceSpecification.cloudType = `legend-local-snowflake-cloudType-${_suffix}`;
818
+ datasourceSpecification.role = `legend-local-snowflake-role-${_suffix}`;
819
+ const connectionValue = new RelationalDatabaseConnection(
820
+ PackageableElementExplicitReference.create(store),
821
+ DatabaseType.Snowflake,
822
+ datasourceSpecification,
823
+ new SnowflakePublicAuthenticationStrategy(
824
+ `legend-local-snowflake-privateKeyVaultReference-${_suffix}`,
825
+ `legend-local-snowflake-passphraseVaultReference-${_suffix}`,
826
+ `legend-local-snowflake-publicuserName-${_suffix}`,
827
+ ),
828
+ );
829
+ connectionValue.localMode = true;
830
+ connection.connectionValue = connectionValue;
831
+ // runtime
832
+ const runtime = new PackageableRuntime(`${this.name}_Runtime`);
833
+ const engineRuntime = new EngineRuntime();
834
+ engineRuntime.mappings = [
835
+ PackageableElementExplicitReference.create(mapping),
836
+ ];
837
+ const storeConnections = new StoreConnections(
838
+ PackageableElementExplicitReference.create(store),
839
+ );
840
+ storeConnections.storeConnections = [
841
+ new IdentifiedConnection(
842
+ generateIdentifiedConnectionId(engineRuntime),
843
+ new ConnectionPointer(
844
+ PackageableElementExplicitReference.create(connection),
845
+ ),
846
+ ),
847
+ ];
848
+ engineRuntime.connections = [storeConnections];
849
+ runtime.runtimeValue = engineRuntime;
850
+ // add the elements
851
+ yield flowResult(
852
+ this.editorStore.graphEditorMode.addElement(
853
+ store,
854
+ packagePath,
855
+ false,
856
+ ),
857
+ );
858
+ yield flowResult(
859
+ this.editorStore.graphEditorMode.addElement(
860
+ connection,
861
+ packagePath,
862
+ false,
863
+ ),
864
+ );
865
+ yield flowResult(
866
+ this.editorStore.graphEditorMode.addElement(
867
+ mapping,
868
+ packagePath,
869
+ false,
870
+ ),
871
+ );
872
+ yield flowResult(
873
+ this.editorStore.graphEditorMode.addElement(
874
+ runtime,
875
+ packagePath,
876
+ false,
877
+ ),
878
+ );
879
+ } else {
880
+ const element = this.createElement(elementName);
881
+ yield flowResult(
882
+ this.editorStore.graphEditorMode.addElement(
883
+ element,
884
+ packagePath,
885
+ true,
886
+ ),
887
+ );
797
888
 
798
- // post creation handling
799
- yield handlePostCreateAction(element, this.editorStore);
889
+ // post creation handling
890
+ yield handlePostCreateAction(element, this.editorStore);
891
+ }
800
892
  }
801
893
  }
802
894
  this.closeModal();
@@ -146,8 +146,8 @@ export class DatabaseBuilderState {
146
146
  makeObservable<DatabaseBuilderState>(this, {
147
147
  showModal: observable,
148
148
  targetDatabasePath: observable,
149
- isBuildingDatabase: observable,
150
149
  databaseGrammarCode: observable,
150
+ isBuildingDatabase: observable,
151
151
  isSavingDatabase: observable,
152
152
  currentDatabase: computed,
153
153
  setTargetDatabasePath: action,
@@ -219,7 +219,7 @@ export class DatabaseBuilderState {
219
219
  treeData: DatabaseBuilderTreeData,
220
220
  ): DatabaseBuilderTreeNodeData[] | undefined {
221
221
  return node.childrenIds
222
- ?.map((n) => treeData.nodes.get(n))
222
+ ?.map((childNode) => treeData.nodes.get(childNode))
223
223
  .filter(isNonNullable);
224
224
  }
225
225
 
@@ -245,7 +245,8 @@ export class DatabaseBuilderState {
245
245
  }
246
246
  }
247
247
  }
248
- // TODO: handle ColumnDatabaseBuilderTreeNodeData
248
+
249
+ // TODO: support toggling check for columns
249
250
  this.setTreeData({ ...treeData });
250
251
  }
251
252
 
@@ -279,6 +280,7 @@ export class DatabaseBuilderState {
279
280
  schemaId,
280
281
  schema,
281
282
  );
283
+ nodes.set(schemaId, schemaNode);
282
284
 
283
285
  schemaNode.setChecked(
284
286
  Boolean(
@@ -287,7 +289,6 @@ export class DatabaseBuilderState {
287
289
  ),
288
290
  ),
289
291
  );
290
- nodes.set(schemaId, schemaNode);
291
292
  });
292
293
  const treeData = { rootIds, nodes, database };
293
294
  this.setTreeData(treeData);
@@ -341,6 +342,8 @@ export class DatabaseBuilderState {
341
342
  schema,
342
343
  table,
343
344
  );
345
+ treeData.nodes.set(tableId, tableNode);
346
+ addUniqueEntry(childrenIds, tableId);
344
347
 
345
348
  if (this.currentDatabase) {
346
349
  const matchingSchema = getNullableSchema(
@@ -357,9 +360,6 @@ export class DatabaseBuilderState {
357
360
  } else {
358
361
  tableNode.setChecked(false);
359
362
  }
360
-
361
- treeData.nodes.set(tableId, tableNode);
362
- addUniqueEntry(childrenIds, tableId);
363
363
  });
364
364
  schemaNode.childrenIds = childrenIds;
365
365
  this.setTreeData({ ...treeData });
@@ -605,6 +605,8 @@ export class DatabaseBuilderState {
605
605
  } else {
606
606
  currentDatabase = this.currentDatabase;
607
607
  }
608
+
609
+ // remove undefined schemas
608
610
  const schemas = Array.from(this.treeData.nodes.values())
609
611
  .map((schemaNode) => {
610
612
  if (schemaNode instanceof SchemaDatabaseBuilderTreeNodeData) {
@@ -613,11 +615,32 @@ export class DatabaseBuilderState {
613
615
  return undefined;
614
616
  })
615
617
  .filter(isNonNullable);
616
- this.updateDatabase(currentDatabase, database, schemas);
618
+ currentDatabase.schemas = currentDatabase.schemas.filter((schema) => {
619
+ if (
620
+ schemas.find((item) => item.name === schema.name) &&
621
+ !database.schemas.find((s) => s.name === schema.name)
622
+ ) {
623
+ return false;
624
+ }
625
+ return true;
626
+ });
627
+
628
+ // update existing schemas
629
+ database.schemas.forEach((schema) => {
630
+ (schema as Writable<Schema>)._OWNER = currentDatabase;
631
+ const currentSchemaIndex = currentDatabase.schemas.findIndex(
632
+ (item) => item.name === schema.name,
633
+ );
634
+ if (currentSchemaIndex !== -1) {
635
+ currentDatabase.schemas[currentSchemaIndex] = schema;
636
+ } else {
637
+ currentDatabase.schemas.push(schema);
638
+ }
639
+ });
640
+
617
641
  this.editorStore.applicationStore.notificationService.notifySuccess(
618
- `Database successfully '${isUpdating ? 'updated' : 'created'}.`,
642
+ `Database successfully '${isUpdating ? 'updated' : 'created'}`,
619
643
  );
620
- this.fetchDatabaseMetadata();
621
644
  if (isUpdating) {
622
645
  yield flowResult(
623
646
  this.editorStore
@@ -639,34 +662,4 @@ export class DatabaseBuilderState {
639
662
  this.isSavingDatabase = false;
640
663
  }
641
664
  }
642
-
643
- updateDatabase(
644
- current: Database,
645
- generatedDatabase: Database,
646
- allSchemas: Schema[],
647
- ): void {
648
- // remove undefined schemas
649
- current.schemas = current.schemas.filter((schema) => {
650
- if (
651
- allSchemas.find((item) => item.name === schema.name) &&
652
- !generatedDatabase.schemas.find((c) => c.name === schema.name)
653
- ) {
654
- return false;
655
- }
656
- return true;
657
- });
658
-
659
- // update existing schemas
660
- generatedDatabase.schemas.forEach((schema) => {
661
- (schema as Writable<Schema>)._OWNER = current;
662
- const currentSchemaIndex = current.schemas.findIndex(
663
- (item) => item.name === schema.name,
664
- );
665
- if (currentSchemaIndex !== -1) {
666
- current.schemas[currentSchemaIndex] = schema;
667
- } else {
668
- current.schemas.push(schema);
669
- }
670
- });
671
- }
672
665
  }
@@ -121,7 +121,6 @@ import {
121
121
  setImpl_updateRootOnCreate,
122
122
  setImpl_updateRootOnDelete,
123
123
  } from '../../../../graph-modifier/DSL_Mapping_GraphModifierHelper.js';
124
- import { BASIC_SET_IMPLEMENTATION_TYPE } from '../../../utils/ModelClassifierUtils.js';
125
124
  import { rootRelationalSetImp_setMainTableAlias } from '../../../../graph-modifier/STO_Relational_GraphModifierHelper.js';
126
125
  import { LambdaEditorState } from '@finos/legend-query-builder';
127
126
  import type { MappingEditorTabState } from './MappingTabManagerState.js';
@@ -163,6 +162,11 @@ export enum MAPPING_ELEMENT_TYPE {
163
162
  ASSOCIATION = 'ASSOCIATION',
164
163
  }
165
164
 
165
+ export enum BASIC_SET_IMPLEMENTATION_TYPE {
166
+ OPERATION = 'operation',
167
+ INSTANCE = 'instance',
168
+ }
169
+
166
170
  export type MappingElement =
167
171
  | EnumerationMapping
168
172
  | SetImplementation