@finos/legend-application-studio 27.0.0 → 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 (98) 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/service-editor/testable/ServiceTestsEditor.d.ts.map +1 -1
  36. package/lib/components/editor/editor-group/service-editor/testable/ServiceTestsEditor.js +9 -4
  37. package/lib/components/editor/editor-group/service-editor/testable/ServiceTestsEditor.js.map +1 -1
  38. package/lib/components/editor/panel-group/SQLPlaygroundPanel.d.ts.map +1 -1
  39. package/lib/components/editor/panel-group/SQLPlaygroundPanel.js +38 -6
  40. package/lib/components/editor/panel-group/SQLPlaygroundPanel.js.map +1 -1
  41. package/lib/components/editor/side-bar/CreateNewElementModal.d.ts +3 -0
  42. package/lib/components/editor/side-bar/CreateNewElementModal.d.ts.map +1 -1
  43. package/lib/components/editor/side-bar/CreateNewElementModal.js +43 -1
  44. package/lib/components/editor/side-bar/CreateNewElementModal.js.map +1 -1
  45. package/lib/components/extensions/Core_LegendStudioApplicationPlugin.d.ts.map +1 -1
  46. package/lib/components/extensions/Core_LegendStudioApplicationPlugin.js +10 -0
  47. package/lib/components/extensions/Core_LegendStudioApplicationPlugin.js.map +1 -1
  48. package/lib/index.css +2 -2
  49. package/lib/index.css.map +1 -1
  50. package/lib/package.json +1 -1
  51. package/lib/stores/editor/EditorGraphState.js +1 -1
  52. package/lib/stores/editor/EditorGraphState.js.map +1 -1
  53. package/lib/stores/editor/EditorStore.d.ts.map +1 -1
  54. package/lib/stores/editor/EditorStore.js +10 -2
  55. package/lib/stores/editor/EditorStore.js.map +1 -1
  56. package/lib/stores/editor/NewElementState.d.ts +0 -1
  57. package/lib/stores/editor/NewElementState.d.ts.map +1 -1
  58. package/lib/stores/editor/NewElementState.js +43 -10
  59. package/lib/stores/editor/NewElementState.js.map +1 -1
  60. package/lib/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.d.ts +0 -1
  61. package/lib/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.d.ts.map +1 -1
  62. package/lib/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.js +26 -30
  63. package/lib/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.js.map +1 -1
  64. package/lib/stores/editor/editor-state/element-editor-state/mapping/MappingEditorState.d.ts +4 -1
  65. package/lib/stores/editor/editor-state/element-editor-state/mapping/MappingEditorState.d.ts.map +1 -1
  66. package/lib/stores/editor/editor-state/element-editor-state/mapping/MappingEditorState.js +5 -1
  67. package/lib/stores/editor/editor-state/element-editor-state/mapping/MappingEditorState.js.map +1 -1
  68. package/lib/stores/editor/panel-group/SQLPlaygroundPanelState.d.ts +9 -0
  69. package/lib/stores/editor/panel-group/SQLPlaygroundPanelState.d.ts.map +1 -1
  70. package/lib/stores/editor/panel-group/SQLPlaygroundPanelState.js +149 -3
  71. package/lib/stores/editor/panel-group/SQLPlaygroundPanelState.js.map +1 -1
  72. package/lib/stores/editor/utils/ModelClassifierUtils.d.ts +2 -5
  73. package/lib/stores/editor/utils/ModelClassifierUtils.d.ts.map +1 -1
  74. package/lib/stores/editor/utils/ModelClassifierUtils.js +2 -6
  75. package/lib/stores/editor/utils/ModelClassifierUtils.js.map +1 -1
  76. package/package.json +3 -3
  77. package/src/__lib__/LegendStudioApplicationNavigationContext.ts +12 -1
  78. package/src/application/LegendStudioApplicationConfig.ts +8 -0
  79. package/src/components/ElementIconUtils.tsx +3 -0
  80. package/src/components/editor/editor-group/ModelImporter.tsx +4 -0
  81. package/src/components/editor/editor-group/connection-editor/DatabaseBuilder.tsx +12 -13
  82. package/src/components/editor/editor-group/data-editor/EmbeddedDataEditor.tsx +11 -1
  83. package/src/components/editor/editor-group/data-editor/RelationalCSVDataEditor.tsx +6 -0
  84. package/src/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_BindingElementEditor.tsx +7 -0
  85. package/src/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_SchemaSetElementEditor.tsx +6 -0
  86. package/src/components/editor/editor-group/external-format-editor/DSL_ExternalFormat_SchemaSetModelGenerationEditor.tsx +6 -0
  87. package/src/components/editor/editor-group/mapping-editor/NewMappingElementModal.tsx +1 -1
  88. package/src/components/editor/editor-group/service-editor/testable/ServiceTestsEditor.tsx +12 -7
  89. package/src/components/editor/panel-group/SQLPlaygroundPanel.tsx +104 -18
  90. package/src/components/editor/side-bar/CreateNewElementModal.tsx +111 -1
  91. package/src/components/extensions/Core_LegendStudioApplicationPlugin.tsx +10 -0
  92. package/src/stores/editor/EditorGraphState.ts +1 -1
  93. package/src/stores/editor/EditorStore.ts +29 -17
  94. package/src/stores/editor/NewElementState.ts +109 -20
  95. package/src/stores/editor/editor-state/element-editor-state/connection/DatabaseBuilderState.ts +33 -40
  96. package/src/stores/editor/editor-state/element-editor-state/mapping/MappingEditorState.ts +5 -1
  97. package/src/stores/editor/panel-group/SQLPlaygroundPanelState.ts +224 -1
  98. package/src/stores/editor/utils/ModelClassifierUtils.ts +2 -6
@@ -23,6 +23,7 @@ export enum LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY {
23
23
  EDITOR = 'studio.editor',
24
24
 
25
25
  MODEL_LOADER = 'studio.editor.model-loader',
26
+ MODEL_LOADER_EXTERNAL_FORMAT_IMPORTER = 'studio.editor.model-loader-external-format-importer',
26
27
  TEXT_MODE_EDITOR = 'studio.editor.text-mode-editor',
27
28
  EMBEDDED_QUERY_BUILDER = 'studio.editor.embedded-query-builder',
28
29
 
@@ -56,7 +57,17 @@ export enum LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY {
56
57
  SERVICE_EDITOR_EXECUTION = 'studio.editor.service-editor.execution',
57
58
  SERVICE_EDITOR_TEST = 'studio.editor.service-editor.test',
58
59
 
60
+ SQL_PLAYGROUND = 'studio.editor.panel-group.sql-playground',
61
+
62
+ // DataElement/Embedded data
59
63
  DATA_ELEMENT_EDITOR = 'studio.editor.data-element-editor',
64
+ EMBEDDED_DATA_RELATIONAL_EDITOR = 'studio.editor.embedded-data-relational-editor',
65
+ EMBEDDED_DATA_EXTERNAL_FORMAT_EDITOR = 'studio.editor.embedded-data-external-format-editor',
66
+ EMBEDDED_DATA_DATA_ELEMENT_REFERENCE_EDITOR = 'studio.editor.embedded-data-data-element-reference-editor',
67
+ EMBEDDED_DATA_MODEL_STORE_EDITOR = 'studio.editor.embedded-data-model-store-editor',
60
68
 
61
- SQL_PLAYGROUND = 'studio.editor.panel-group.sql-playground',
69
+ // external format
70
+ SCHEMA_SET_EDITOR = 'dsl-external-format.studio.editor.schema-set-editor',
71
+ SCHEMA_SET_MODEL_GENERATION = 'dsl-external-format.studio.editor.schema-set-model-generation',
72
+ BINDING_EDITOR = 'dsl-external-format.studio.editor.binding-editor',
62
73
  }
@@ -74,6 +74,13 @@ class LegendStudioApplicationCoreOptions {
74
74
  */
75
75
  TEMPORARY__enableFunctionActivatorSupport = false;
76
76
 
77
+ /**
78
+ * This flag can be removed when the support for local connection is official
79
+ * Right now it's done to support the SnowflakeApp creation demo
80
+ * See https://github.com/finos/legend-engine/pull/1819
81
+ */
82
+ TEMPORARY__enableLocalConnectionBuilder = false;
83
+
77
84
  /**
78
85
  * This flag can be removed when the support for raw SQL execution is official
79
86
  * See https://github.com/finos/legend-engine/pull/1841
@@ -110,6 +117,7 @@ class LegendStudioApplicationCoreOptions {
110
117
  TEMPORARY__preserveSectionIndex: optional(primitive()),
111
118
  TEMPORARY__enableFunctionActivatorSupport: optional(primitive()),
112
119
  TEMPORARY__enableRawSQLExecutor: optional(primitive()),
120
+ TEMPORARY__enableLocalConnectionBuilder: optional(primitive()),
113
121
  TEMPORARY__enableMappingTestableEditor: optional(primitive()),
114
122
  TEMPORARY__serviceRegistrationConfig: list(
115
123
  object(ServiceRegistrationEnvironmentConfig),
@@ -42,6 +42,7 @@ import {
42
42
  PURE_PackageIcon,
43
43
  PURE_DataIcon,
44
44
  LaunchIcon,
45
+ LinkIcon,
45
46
  } from '@finos/legend-art';
46
47
  import { PACKAGEABLE_ELEMENT_TYPE } from '../stores/editor/utils/ModelClassifierUtils.js';
47
48
 
@@ -88,6 +89,8 @@ export const getElementTypeIcon = (
88
89
  return <PURE_ServiceIcon />;
89
90
  case PACKAGEABLE_ELEMENT_TYPE.CONNECTION:
90
91
  return <PURE_ConnectionIcon />;
92
+ case PACKAGEABLE_ELEMENT_TYPE.TEMPORARY__LOCAL_CONNECTION:
93
+ return <LinkIcon />;
91
94
  case PACKAGEABLE_ELEMENT_TYPE.RUNTIME:
92
95
  return <PURE_RuntimeIcon />;
93
96
  case PACKAGEABLE_ELEMENT_TYPE.FILE_GENERATION:
@@ -100,6 +100,10 @@ const ExternalFormatModelImporterEditor = observer(
100
100
  </BlankPanelContent>
101
101
  );
102
102
  };
103
+
104
+ useApplicationNavigationContext(
105
+ LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.MODEL_LOADER_EXTERNAL_FORMAT_IMPORTER,
106
+ );
103
107
  return (
104
108
  <Panel className="schema-set-panel">
105
109
  <PanelContent className="model-loader">
@@ -22,7 +22,6 @@ import {
22
22
  ResizablePanel,
23
23
  ResizablePanelSplitter,
24
24
  PanelLoadingIndicator,
25
- clsx,
26
25
  TreeView,
27
26
  PURE_DatabaseSchemaIcon,
28
27
  PURE_DatabaseTableIcon,
@@ -139,7 +138,7 @@ const DatabaseBuilderTreeNodeContainer = observer(
139
138
 
140
139
  return (
141
140
  <div
142
- className={clsx('tree-view__node__container')}
141
+ className="tree-view__node__container"
143
142
  style={{
144
143
  paddingLeft: `${level * (stepPaddingInRem ?? 1)}rem`,
145
144
  display: 'flex',
@@ -151,7 +150,7 @@ const DatabaseBuilderTreeNodeContainer = observer(
151
150
  {nodeExpandIcon}
152
151
  </div>
153
152
  <div
154
- className={clsx('database-builder-tree__checker-icon')}
153
+ className="database-builder-tree__checker-icon"
155
154
  onClick={(event) => {
156
155
  event.stopPropagation();
157
156
  toggleCheckedNode(node);
@@ -198,6 +197,13 @@ export const DatabaseBuilderExplorer = observer(
198
197
  );
199
198
  };
200
199
 
200
+ const getChildNodes = (
201
+ node: DatabaseBuilderTreeNodeData,
202
+ ): DatabaseBuilderTreeNodeData[] =>
203
+ databaseBuilderState
204
+ .getChildNodes(node, treeData)
205
+ ?.sort((a, b) => a.label.localeCompare(b.label)) ?? [];
206
+
201
207
  const isPartiallySelected = (
202
208
  node: DatabaseBuilderTreeNodeData,
203
209
  ): boolean => {
@@ -208,22 +214,15 @@ export const DatabaseBuilderExplorer = observer(
208
214
  return Boolean(
209
215
  databaseBuilderState
210
216
  .getChildNodes(node, treeData)
211
- ?.find((s) => s.isChecked === true),
217
+ ?.find((childNode) => childNode.isChecked === true),
212
218
  );
213
219
  }
214
220
  return false;
215
221
  };
216
222
 
217
- const getChildNodes = (
218
- node: DatabaseBuilderTreeNodeData,
219
- ): DatabaseBuilderTreeNodeData[] =>
220
- databaseBuilderState
221
- .getChildNodes(node, treeData)
222
- ?.sort((a, b) => a.label.localeCompare(b.label)) ?? [];
223
-
224
- const toggleCheckedNode = (node: DatabaseBuilderTreeNodeData): void => {
223
+ const toggleCheckedNode = (node: DatabaseBuilderTreeNodeData): void =>
225
224
  databaseBuilderState.toggleCheckedNode(node, treeData);
226
- };
225
+
227
226
  return (
228
227
  <TreeView
229
228
  className="database-builder-tree"
@@ -62,6 +62,8 @@ import {
62
62
  import { RelationalCSVDataEditor } from './RelationalCSVDataEditor.js';
63
63
  import { CodeEditor } from '@finos/legend-lego/code-editor';
64
64
  import { getEditorLanguageForFormat } from '../../../../stores/editor/editor-state/ArtifactGenerationViewerState.js';
65
+ import { useApplicationNavigationContext } from '@finos/legend-application';
66
+ import { LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY } from '../../../../__lib__/LegendStudioApplicationNavigationContext.js';
65
67
 
66
68
  export const ExternalFormatDataEditor = observer(
67
69
  (props: {
@@ -92,6 +94,9 @@ export const ExternalFormatDataEditor = observer(
92
94
  ),
93
95
  );
94
96
  const format = (): void => externalFormatDataState.format();
97
+ useApplicationNavigationContext(
98
+ LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.EMBEDDED_DATA_EXTERNAL_FORMAT_EDITOR,
99
+ );
95
100
  return (
96
101
  <div className="panel external-format-data-editor">
97
102
  <div className="external-format-data-editor__header">
@@ -184,6 +189,9 @@ export const DataElementReferenceDataEditor = observer(
184
189
  };
185
190
  const visitData = (): void =>
186
191
  editorStore.graphEditorMode.openElement(dataElement);
192
+ useApplicationNavigationContext(
193
+ LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.EMBEDDED_DATA_DATA_ELEMENT_REFERENCE_EDITOR,
194
+ );
187
195
  return (
188
196
  <div className="panel data-element-reference-editor">
189
197
  <div className="data-element-reference-editor__header">
@@ -309,7 +317,9 @@ export const ModelStoreDataEditor = observer(
309
317
  isReadOnly: boolean;
310
318
  }) => {
311
319
  const { isReadOnly, modelStoreDataState } = props;
312
-
320
+ useApplicationNavigationContext(
321
+ LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.EMBEDDED_DATA_MODEL_STORE_EDITOR,
322
+ );
313
323
  return (
314
324
  <div className="panel connection-editor">
315
325
  {modelStoreDataState.modelDataStates.map((_modelDataState) => {
@@ -41,6 +41,8 @@ import {
41
41
  CODE_EDITOR_LANGUAGE,
42
42
  CodeEditor,
43
43
  } from '@finos/legend-lego/code-editor';
44
+ import { LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY } from '../../../../__lib__/LegendStudioApplicationNavigationContext.js';
45
+ import { useApplicationNavigationContext } from '@finos/legend-application';
44
46
 
45
47
  const RelationalTableIdentifierModal = observer(
46
48
  (props: { dataState: RelationalCSVDataState; isReadOnly: boolean }) => {
@@ -199,6 +201,10 @@ export const RelationalCSVDataEditor = observer(
199
201
  const isTableActive = (table: RelationalCSVDataTable): boolean =>
200
202
  currentTableState?.table === table;
201
203
  const showCSVModal = (): void => dataState.setShowImportCsvModal(true);
204
+
205
+ useApplicationNavigationContext(
206
+ LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.EMBEDDED_DATA_RELATIONAL_EDITOR,
207
+ );
202
208
  return (
203
209
  <ResizablePanelGroup orientation="vertical">
204
210
  <ResizablePanel minSize={30} size={300}>
@@ -59,6 +59,8 @@ import {
59
59
  externalFormat_modelUnit_deletePackageableElementExcludes,
60
60
  externalFormat_modelUnit_deletePackageableElementIncludes,
61
61
  } from '../../../../stores/graph-modifier/DSL_ExternalFormat_GraphModifierHelper.js';
62
+ import { useApplicationNavigationContext } from '@finos/legend-application';
63
+ import { LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY } from '../../../../__lib__/LegendStudioApplicationNavigationContext.js';
62
64
 
63
65
  const ModelUnitPackagableElementEntryEditor = observer(
64
66
  (props: {
@@ -424,6 +426,11 @@ export const BindingEditor = observer(() => {
424
426
  (tab: BINDING_TAB_TYPE): (() => void) =>
425
427
  (): void =>
426
428
  editorState.setSelectedTab(tab);
429
+
430
+ useApplicationNavigationContext(
431
+ LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.BINDING_EDITOR,
432
+ );
433
+
427
434
  return (
428
435
  <div className="binding-editor">
429
436
  <div className="binding-editor__header">
@@ -59,6 +59,8 @@ import {
59
59
  CodeEditor,
60
60
  } from '@finos/legend-lego/code-editor';
61
61
  import { getEditorLanguageForFormat } from '../../../../stores/editor/editor-state/ArtifactGenerationViewerState.js';
62
+ import { LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY } from '../../../../__lib__/LegendStudioApplicationNavigationContext.js';
63
+ import { useApplicationNavigationContext } from '@finos/legend-application';
62
64
 
63
65
  const SchemaLoader = observer(
64
66
  (props: {
@@ -415,6 +417,10 @@ export const SchemaSetEditor = observer(() => {
415
417
  );
416
418
  };
417
419
 
420
+ useApplicationNavigationContext(
421
+ LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.SCHEMA_SET_EDITOR,
422
+ );
423
+
418
424
  return (
419
425
  <div className="panel schema-set-panel">
420
426
  <div className="schema-set-panel__header">
@@ -39,6 +39,8 @@ import {
39
39
  CODE_EDITOR_LANGUAGE,
40
40
  CodeEditor,
41
41
  } from '@finos/legend-lego/code-editor';
42
+ import { useApplicationNavigationContext } from '@finos/legend-application';
43
+ import { LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY } from '../../../../__lib__/LegendStudioApplicationNavigationContext.js';
42
44
 
43
45
  enum HIDDEN_CONFIGURATION_PROPERTIES {
44
46
  FORMAT = 'format',
@@ -100,6 +102,10 @@ export const SchemaSetModelGenerationEditor = observer(
100
102
  modelGenerationState.importGeneratedModelsIntoGraph();
101
103
  };
102
104
 
105
+ useApplicationNavigationContext(
106
+ LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.SCHEMA_SET_MODEL_GENERATION,
107
+ );
108
+
103
109
  return (
104
110
  <PanelContent className="file-generation-editor__content">
105
111
  <ResizablePanelGroup orientation="vertical">
@@ -31,6 +31,7 @@ import {
31
31
  createEnumerationMapping,
32
32
  getAllMappingElements,
33
33
  MappingEditorState,
34
+ BASIC_SET_IMPLEMENTATION_TYPE,
34
35
  } from '../../../../stores/editor/editor-state/element-editor-state/mapping/MappingEditorState.js';
35
36
  import {
36
37
  guaranteeNonNullable,
@@ -45,7 +46,6 @@ import {
45
46
  Association,
46
47
  PrimitiveType,
47
48
  } from '@finos/legend-graph';
48
- import { BASIC_SET_IMPLEMENTATION_TYPE } from '../../../../stores/editor/utils/ModelClassifierUtils.js';
49
49
  import {
50
50
  buildElementOption,
51
51
  getPackageableElementOptionFormatter,
@@ -158,6 +158,14 @@ export const ExternalFormatParameterEditorModal = observer(
158
158
  updateParamValue,
159
159
  bindingParamPair,
160
160
  } = props;
161
+ const paramValue =
162
+ paramState.varExpression.genericType?.value.rawType === PrimitiveType.BYTE
163
+ ? atob(
164
+ (paramState.valueSpec as PrimitiveInstanceValue)
165
+ .values[0] as string,
166
+ )
167
+ : ((paramState.valueSpec as PrimitiveInstanceValue)
168
+ .values[0] as string);
161
169
  return (
162
170
  <Dialog
163
171
  open={true}
@@ -177,10 +185,7 @@ export const ExternalFormatParameterEditorModal = observer(
177
185
  <div className="service-test-editor__setup__parameter__code-editor__container__content">
178
186
  <CodeEditor
179
187
  key={paramState.uuid}
180
- inputValue={
181
- (paramState.valueSpec as PrimitiveInstanceValue)
182
- .values[0] as string
183
- }
188
+ inputValue={paramValue}
184
189
  updateInput={updateParamValue}
185
190
  isReadOnly={isReadOnly}
186
191
  language={
@@ -225,14 +230,14 @@ const ServiceTestParameterEditor = observer(
225
230
  const type = bindingParamPair
226
231
  ? bindingParamPair.binding.contentType
227
232
  : paramState.varExpression.genericType?.value.rawType.name ?? 'unknown';
228
- const paramValue = (
233
+ const paramValue =
229
234
  paramState.varExpression.genericType?.value.rawType === PrimitiveType.BYTE
230
235
  ? atob(
231
236
  (paramState.valueSpec as PrimitiveInstanceValue)
232
237
  .values[0] as string,
233
238
  )
234
- : (paramState.valueSpec as PrimitiveInstanceValue).values[0]
235
- ) as string;
239
+ : ((paramState.valueSpec as PrimitiveInstanceValue)
240
+ .values[0] as string);
236
241
 
237
242
  const openInPopUp = (): void => setShowPopUp(!showPopUp);
238
243
  const closePopUp = (): void => setShowPopUp(false);
@@ -20,7 +20,6 @@ import {
20
20
  ResizablePanelGroup,
21
21
  ResizablePanel,
22
22
  ResizablePanelSplitter,
23
- clsx,
24
23
  TreeView,
25
24
  PURE_DatabaseSchemaIcon,
26
25
  PURE_DatabaseTableIcon,
@@ -38,6 +37,11 @@ import {
38
37
  PanelLoadingIndicator,
39
38
  BlankPanelContent,
40
39
  TrashIcon,
40
+ CircleIcon,
41
+ CheckCircleIcon,
42
+ EmptyCircleIcon,
43
+ PURE_DatabaseIcon,
44
+ SyncIcon,
41
45
  } from '@finos/legend-art';
42
46
  import React, { useCallback, useEffect, useRef, useState } from 'react';
43
47
  import {
@@ -119,11 +123,15 @@ const DatabaseSchemaExplorerTreeNodeContainer: React.FC<
119
123
  TreeNodeContainerProps<
120
124
  DatabaseSchemaExplorerTreeNodeData,
121
125
  {
122
- // empty
126
+ toggleCheckedNode: (node: DatabaseSchemaExplorerTreeNodeData) => void;
127
+ isPartiallySelected: (
128
+ node: DatabaseSchemaExplorerTreeNodeData,
129
+ ) => boolean;
123
130
  }
124
131
  >
125
132
  > = (props) => {
126
- const { node, level, stepPaddingInRem, onNodeSelect } = props;
133
+ const { node, level, stepPaddingInRem, onNodeSelect, innerProps } = props;
134
+ const { toggleCheckedNode, isPartiallySelected } = innerProps;
127
135
  const isExpandable =
128
136
  Boolean(!node.childrenIds || node.childrenIds.length) &&
129
137
  !(node instanceof DatabaseSchemaExplorerTreeColumnNodeData);
@@ -154,9 +162,22 @@ const DatabaseSchemaExplorerTreeNodeContainer: React.FC<
154
162
  node instanceof DatabaseSchemaExplorerTreeColumnNodeData &&
155
163
  node.owner.primaryKey.includes(node.column);
156
164
 
165
+ const renderCheckedIcon = (
166
+ _node: DatabaseSchemaExplorerTreeNodeData,
167
+ ): React.ReactNode => {
168
+ if (_node instanceof DatabaseSchemaExplorerTreeColumnNodeData) {
169
+ return null;
170
+ } else if (isPartiallySelected(_node)) {
171
+ return <CircleIcon />;
172
+ } else if (_node.isChecked) {
173
+ return <CheckCircleIcon />;
174
+ }
175
+ return <EmptyCircleIcon />;
176
+ };
177
+
157
178
  return (
158
179
  <div
159
- className={clsx('tree-view__node__container')}
180
+ className="tree-view__node__container"
160
181
  style={{
161
182
  paddingLeft: `${level * (stepPaddingInRem ?? 1)}rem`,
162
183
  display: 'flex',
@@ -168,6 +189,15 @@ const DatabaseSchemaExplorerTreeNodeContainer: React.FC<
168
189
  <div className="sql-playground__database-schema-explorer-tree__expand-icon">
169
190
  {nodeExpandIcon}
170
191
  </div>
192
+ <div
193
+ className="sql-playground__database-schema-explorer-tree__toggle-icon"
194
+ onClick={(event) => {
195
+ event.stopPropagation();
196
+ toggleCheckedNode(node);
197
+ }}
198
+ >
199
+ {renderCheckedIcon(node)}
200
+ </div>
171
201
  <div className="sql-playground__database-schema-explorer-tree__type-icon">
172
202
  {nodeTypeIcon}
173
203
  </div>
@@ -215,13 +245,36 @@ export const DatabaseSchemaExplorer = observer(
215
245
  .getChildNodes(node, treeData)
216
246
  ?.sort((a, b) => a.label.localeCompare(b.label)) ?? [];
217
247
 
248
+ const isPartiallySelected = (
249
+ node: DatabaseSchemaExplorerTreeNodeData,
250
+ ): boolean => {
251
+ if (
252
+ node instanceof DatabaseSchemaExplorerTreeSchemaNodeData &&
253
+ !node.isChecked
254
+ ) {
255
+ return Boolean(
256
+ playgroundState
257
+ .getChildNodes(node, treeData)
258
+ ?.find((childNode) => childNode.isChecked === true),
259
+ );
260
+ }
261
+ return false;
262
+ };
263
+
264
+ const toggleCheckedNode = (
265
+ node: DatabaseSchemaExplorerTreeNodeData,
266
+ ): void => playgroundState.toggleCheckedNode(node, treeData);
267
+
218
268
  return (
219
269
  <TreeView
220
270
  className="sql-playground__database-schema-explorer-tree"
221
271
  components={{
222
272
  TreeNodeContainer: DatabaseSchemaExplorerTreeNodeContainer,
223
273
  }}
224
- innerProps={{}}
274
+ innerProps={{
275
+ toggleCheckedNode,
276
+ isPartiallySelected,
277
+ }}
225
278
  treeData={treeData}
226
279
  onNodeSelect={onNodeSelect}
227
280
  getChildNodes={getChildNodes}
@@ -647,6 +700,10 @@ export const SQLPlaygroundPanel = observer(() => {
647
700
  [handleConnectionDrop],
648
701
  );
649
702
 
703
+ const updateDatabase = applicationStore.guardUnhandledError(() =>
704
+ flowResult(playgroundState.updateDatabase()),
705
+ );
706
+
650
707
  useEffect(() => {
651
708
  flowResult(playgroundState.fetchDatabaseMetadata()).catch(
652
709
  applicationStore.alertUnhandledError,
@@ -668,20 +725,49 @@ export const SQLPlaygroundPanel = observer(() => {
668
725
  <ResizablePanelGroup orientation="vertical">
669
726
  <ResizablePanel size={300}>
670
727
  <div className="sql-playground__config">
671
- <div className="sql-playground__config__connection-selector">
672
- <div className="sql-playground__config__connection-selector__icon">
673
- <PURE_ConnectionIcon />
728
+ <div className="sql-playground__config__setup">
729
+ <div className="sql-playground__config__connection-selector">
730
+ <div className="sql-playground__config__connection-selector__icon">
731
+ <PURE_ConnectionIcon />
732
+ </div>
733
+ <CustomSelectorInput
734
+ ref={connectionSelectorRef}
735
+ className="sql-playground__config__connection-selector__input"
736
+ options={connectionOptions}
737
+ onChange={changeConnection}
738
+ value={selectedConnectionOption}
739
+ darkMode={true}
740
+ placeholder="Choose a connection..."
741
+ filterOption={connectionFilterOption}
742
+ />
743
+ </div>
744
+ <div className="sql-playground__config__database-selector">
745
+ <div className="sql-playground__config__database-selector__icon">
746
+ <PURE_DatabaseIcon />
747
+ </div>
748
+ <CustomSelectorInput
749
+ ref={connectionSelectorRef}
750
+ className="sql-playground__config__database-selector__input"
751
+ options={connectionOptions}
752
+ onChange={changeConnection}
753
+ value={selectedConnectionOption}
754
+ darkMode={true}
755
+ placeholder="Choose a connection..."
756
+ filterOption={connectionFilterOption}
757
+ />
758
+ <button
759
+ className="sql-playground__config__database-selector__update-btn btn--sm btn--dark"
760
+ disabled={
761
+ !playgroundState.database ||
762
+ playgroundState.isBuildingDatabase ||
763
+ playgroundState.isUpdatingDatabase
764
+ }
765
+ onClick={updateDatabase}
766
+ title="Update database"
767
+ >
768
+ <SyncIcon />
769
+ </button>
674
770
  </div>
675
- <CustomSelectorInput
676
- ref={connectionSelectorRef}
677
- className="sql-playground__config__connection-selector__input"
678
- options={connectionOptions}
679
- onChange={changeConnection}
680
- value={selectedConnectionOption}
681
- darkMode={true}
682
- placeholder="Choose a connection..."
683
- filterOption={connectionFilterOption}
684
- />
685
771
  </div>
686
772
  <div className="sql-playground__config__schema-explorer">
687
773
  {playgroundState.treeData && (
@@ -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();
@@ -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
 
@@ -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
  }