@finos/legend-application-studio 13.1.0 → 14.0.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 (115) hide show
  1. package/lib/components/EditorComponentTestUtils.d.ts +3 -13
  2. package/lib/components/EditorComponentTestUtils.d.ts.map +1 -1
  3. package/lib/components/EditorComponentTestUtils.js +3 -22
  4. package/lib/components/EditorComponentTestUtils.js.map +1 -1
  5. package/lib/components/editor/edit-panel/EditPanel.js +4 -4
  6. package/lib/components/editor/edit-panel/EditPanel.js.map +1 -1
  7. package/lib/components/editor/edit-panel/{ModelLoader.d.ts → ModelImporter.d.ts} +2 -2
  8. package/lib/components/editor/edit-panel/ModelImporter.d.ts.map +1 -0
  9. package/lib/components/editor/edit-panel/ModelImporter.js +132 -0
  10. package/lib/components/editor/edit-panel/ModelImporter.js.map +1 -0
  11. package/lib/components/editor/edit-panel/connection-editor/RelationalDatabaseConnectionEditor.d.ts.map +1 -1
  12. package/lib/components/editor/edit-panel/connection-editor/RelationalDatabaseConnectionEditor.js +10 -2
  13. package/lib/components/editor/edit-panel/connection-editor/RelationalDatabaseConnectionEditor.js.map +1 -1
  14. package/lib/components/editor/edit-panel/external-format-editor/SchemaSetElementEditor.d.ts +7 -0
  15. package/lib/components/editor/edit-panel/external-format-editor/SchemaSetElementEditor.d.ts.map +1 -1
  16. package/lib/components/editor/edit-panel/external-format-editor/SchemaSetElementEditor.js +18 -42
  17. package/lib/components/editor/edit-panel/external-format-editor/SchemaSetElementEditor.js.map +1 -1
  18. package/lib/components/editor/edit-panel/external-format-editor/SchemaSetModelGenerationEditor.d.ts +24 -0
  19. package/lib/components/editor/edit-panel/external-format-editor/SchemaSetModelGenerationEditor.d.ts.map +1 -0
  20. package/lib/components/editor/edit-panel/external-format-editor/SchemaSetModelGenerationEditor.js +75 -0
  21. package/lib/components/editor/edit-panel/external-format-editor/SchemaSetModelGenerationEditor.js.map +1 -0
  22. package/lib/components/editor/edit-panel/service-editor/testable/ServiceTestDataEditor.d.ts.map +1 -1
  23. package/lib/components/editor/edit-panel/service-editor/testable/ServiceTestDataEditor.js +6 -4
  24. package/lib/components/editor/edit-panel/service-editor/testable/ServiceTestDataEditor.js.map +1 -1
  25. package/lib/components/editor/edit-panel/uml-editor/AssociationEditor.d.ts.map +1 -1
  26. package/lib/components/editor/edit-panel/uml-editor/AssociationEditor.js +2 -4
  27. package/lib/components/editor/edit-panel/uml-editor/AssociationEditor.js.map +1 -1
  28. package/lib/components/editor/side-bar/Explorer.js +4 -4
  29. package/lib/components/editor/side-bar/Explorer.js.map +1 -1
  30. package/lib/index.css +2 -2
  31. package/lib/index.css.map +1 -1
  32. package/lib/package.json +1 -1
  33. package/lib/stores/EditorGraphState.d.ts +1 -1
  34. package/lib/stores/EditorGraphState.d.ts.map +1 -1
  35. package/lib/stores/EditorGraphState.js +10 -10
  36. package/lib/stores/EditorGraphState.js.map +1 -1
  37. package/lib/stores/EditorStore.d.ts +3 -3
  38. package/lib/stores/EditorStore.d.ts.map +1 -1
  39. package/lib/stores/EditorStore.js +6 -8
  40. package/lib/stores/EditorStore.js.map +1 -1
  41. package/lib/stores/LegendStudioApplicationPlugin.d.ts +3 -3
  42. package/lib/stores/LegendStudioApplicationPlugin.d.ts.map +1 -1
  43. package/lib/stores/editor/NewElementState.d.ts.map +1 -1
  44. package/lib/stores/editor/NewElementState.js +4 -3
  45. package/lib/stores/editor/NewElementState.js.map +1 -1
  46. package/lib/stores/editor-state/ExternalFormatState.d.ts +3 -2
  47. package/lib/stores/editor-state/ExternalFormatState.d.ts.map +1 -1
  48. package/lib/stores/editor-state/ExternalFormatState.js +11 -8
  49. package/lib/stores/editor-state/ExternalFormatState.js.map +1 -1
  50. package/lib/stores/editor-state/ModelImporterState.d.ts +95 -0
  51. package/lib/stores/editor-state/ModelImporterState.d.ts.map +1 -0
  52. package/lib/stores/editor-state/ModelImporterState.js +358 -0
  53. package/lib/stores/editor-state/ModelImporterState.js.map +1 -0
  54. package/lib/stores/editor-state/element-editor-state/connection/ConnectionEditorState.d.ts +2 -1
  55. package/lib/stores/editor-state/element-editor-state/connection/ConnectionEditorState.d.ts.map +1 -1
  56. package/lib/stores/editor-state/element-editor-state/connection/ConnectionEditorState.js +9 -1
  57. package/lib/stores/editor-state/element-editor-state/connection/ConnectionEditorState.js.map +1 -1
  58. package/lib/stores/editor-state/element-editor-state/external-format/SchemaSetEditorState.d.ts +35 -12
  59. package/lib/stores/editor-state/element-editor-state/external-format/SchemaSetEditorState.d.ts.map +1 -1
  60. package/lib/stores/editor-state/element-editor-state/external-format/SchemaSetEditorState.js +141 -34
  61. package/lib/stores/editor-state/element-editor-state/external-format/SchemaSetEditorState.js.map +1 -1
  62. package/lib/stores/editor-state/element-editor-state/service/ServiceExecutionState.d.ts.map +1 -1
  63. package/lib/stores/editor-state/element-editor-state/service/ServiceExecutionState.js +1 -1
  64. package/lib/stores/editor-state/element-editor-state/service/ServiceExecutionState.js.map +1 -1
  65. package/lib/stores/editor-state/element-editor-state/service/testable/ServiceTestDataState.d.ts.map +1 -1
  66. package/lib/stores/editor-state/element-editor-state/service/testable/ServiceTestDataState.js +2 -2
  67. package/lib/stores/editor-state/element-editor-state/service/testable/ServiceTestDataState.js.map +1 -1
  68. package/lib/stores/editor-state/element-editor-state/service/testable/ServiceTestEditorState.d.ts.map +1 -1
  69. package/lib/stores/editor-state/element-editor-state/service/testable/ServiceTestEditorState.js +3 -3
  70. package/lib/stores/editor-state/element-editor-state/service/testable/ServiceTestEditorState.js.map +1 -1
  71. package/lib/stores/graphModifier/DSLExternalFormat_GraphModifierHelper.d.ts +1 -0
  72. package/lib/stores/graphModifier/DSLExternalFormat_GraphModifierHelper.d.ts.map +1 -1
  73. package/lib/stores/graphModifier/DSLExternalFormat_GraphModifierHelper.js +3 -0
  74. package/lib/stores/graphModifier/DSLExternalFormat_GraphModifierHelper.js.map +1 -1
  75. package/lib/stores/graphModifier/StoreRelational_GraphModifierHelper.d.ts +2 -1
  76. package/lib/stores/graphModifier/StoreRelational_GraphModifierHelper.d.ts.map +1 -1
  77. package/lib/stores/graphModifier/StoreRelational_GraphModifierHelper.js +3 -0
  78. package/lib/stores/graphModifier/StoreRelational_GraphModifierHelper.js.map +1 -1
  79. package/lib/stores/shared/testable/TestableUtils.d.ts.map +1 -1
  80. package/lib/stores/shared/testable/TestableUtils.js +2 -3
  81. package/lib/stores/shared/testable/TestableUtils.js.map +1 -1
  82. package/package.json +9 -9
  83. package/src/components/EditorComponentTestUtils.tsx +2 -29
  84. package/src/components/editor/edit-panel/EditPanel.tsx +4 -4
  85. package/src/components/editor/edit-panel/ModelImporter.tsx +376 -0
  86. package/src/components/editor/edit-panel/connection-editor/RelationalDatabaseConnectionEditor.tsx +36 -0
  87. package/src/components/editor/edit-panel/external-format-editor/SchemaSetElementEditor.tsx +47 -163
  88. package/src/components/editor/edit-panel/external-format-editor/SchemaSetModelGenerationEditor.tsx +226 -0
  89. package/src/components/editor/edit-panel/service-editor/testable/ServiceTestDataEditor.tsx +63 -36
  90. package/src/components/editor/edit-panel/uml-editor/AssociationEditor.tsx +1 -7
  91. package/src/components/editor/side-bar/Explorer.tsx +8 -8
  92. package/src/stores/EditorGraphState.ts +13 -12
  93. package/src/stores/EditorStore.ts +7 -9
  94. package/src/stores/LegendStudioApplicationPlugin.ts +4 -4
  95. package/src/stores/editor/NewElementState.ts +4 -3
  96. package/src/stores/editor-state/ExternalFormatState.ts +15 -12
  97. package/src/stores/editor-state/ModelImporterState.ts +506 -0
  98. package/src/stores/editor-state/element-editor-state/connection/ConnectionEditorState.ts +10 -0
  99. package/src/stores/editor-state/element-editor-state/external-format/SchemaSetEditorState.ts +203 -46
  100. package/src/stores/editor-state/element-editor-state/service/ServiceExecutionState.ts +1 -0
  101. package/src/stores/editor-state/element-editor-state/service/testable/ServiceTestDataState.ts +2 -1
  102. package/src/stores/editor-state/element-editor-state/service/testable/ServiceTestEditorState.ts +12 -3
  103. package/src/stores/graphModifier/DSLExternalFormat_GraphModifierHelper.ts +5 -0
  104. package/src/stores/graphModifier/StoreRelational_GraphModifierHelper.ts +10 -0
  105. package/src/stores/shared/testable/TestableUtils.ts +4 -3
  106. package/tsconfig.json +3 -2
  107. package/lib/components/editor/edit-panel/ModelLoader.d.ts.map +0 -1
  108. package/lib/components/editor/edit-panel/ModelLoader.js +0 -95
  109. package/lib/components/editor/edit-panel/ModelLoader.js.map +0 -1
  110. package/lib/stores/editor-state/ModelLoaderState.d.ts +0 -52
  111. package/lib/stores/editor-state/ModelLoaderState.d.ts.map +0 -1
  112. package/lib/stores/editor-state/ModelLoaderState.js +0 -199
  113. package/lib/stores/editor-state/ModelLoaderState.js.map +0 -1
  114. package/src/components/editor/edit-panel/ModelLoader.tsx +0 -259
  115. package/src/stores/editor-state/ModelLoaderState.ts +0 -280
@@ -24,7 +24,6 @@ import {
24
24
  ResizablePanelSplitterLine,
25
25
  LockIcon,
26
26
  PlusIcon,
27
- RefreshIcon,
28
27
  PanelLoadingIndicator,
29
28
  UploadIcon,
30
29
  Dialog,
@@ -33,25 +32,17 @@ import {
33
32
  MenuContent,
34
33
  MenuContentItem,
35
34
  } from '@finos/legend-art';
36
- import {
37
- type GenerationProperty,
38
- ExternalFormatSchema as Schema,
39
- } from '@finos/legend-graph';
35
+ import { ExternalFormatSchema as Schema } from '@finos/legend-graph';
40
36
  import { flowResult } from 'mobx';
41
- import { useMemo } from 'react';
42
37
  import {
43
38
  SchemaSetEditorState,
39
+ type InnerSchemaSetEditorState,
44
40
  SCHEMA_SET_TAB_TYPE,
45
41
  } from '../../../../stores/editor-state/element-editor-state/external-format/SchemaSetEditorState.js';
46
42
  import { EDITOR_LANGUAGE } from '@finos/legend-application';
47
43
  import { StudioTextInputEditor } from '../../../shared/StudioTextInputEditor.js';
48
44
  import { getEditorLanguageFromFormat } from '../../../../stores/editor-state/FileGenerationViewerState.js';
49
- import {
50
- debounce,
51
- guaranteeNonNullable,
52
- prettyCONSTName,
53
- } from '@finos/legend-shared';
54
- import { GenerationPropertyEditor } from '../element-generation-editor/FileGenerationEditor.js';
45
+ import { guaranteeNonNullable, prettyCONSTName } from '@finos/legend-shared';
55
46
  import { useEditorStore } from '../../EditorStoreProvider.js';
56
47
  import {
57
48
  externalFormat_schemaSet_addSchema,
@@ -60,9 +51,12 @@ import {
60
51
  externalFormat_schema_setId,
61
52
  externalFormat_schema_setLocation,
62
53
  } from '../../../../stores/graphModifier/DSLExternalFormat_GraphModifierHelper.js';
54
+ import { SchemaSetModelGenerationEditor } from './SchemaSetModelGenerationEditor.js';
63
55
 
64
56
  const SchemaLoader = observer(
65
- (props: { schemaSetEditorState: SchemaSetEditorState }) => {
57
+ (props: {
58
+ schemaSetEditorState: InnerSchemaSetEditorState | SchemaSetEditorState;
59
+ }) => {
66
60
  const { schemaSetEditorState } = props;
67
61
  const importState = schemaSetEditorState.importSchemaContentState;
68
62
  const onClose = (): void => importState.closeModal();
@@ -199,19 +193,23 @@ const SchemaBasicEditor = observer(
199
193
  },
200
194
  );
201
195
 
202
- const SchemaSetGeneralEditor = observer(
203
- (props: { schemaSetEditorState: SchemaSetEditorState }) => {
204
- const { schemaSetEditorState } = props;
196
+ export const SchemaSetGeneralEditor = observer(
197
+ (props: {
198
+ schemaSetEditorState: InnerSchemaSetEditorState | SchemaSetEditorState;
199
+ isReadOnly: boolean;
200
+ }) => {
201
+ const { schemaSetEditorState, isReadOnly } = props;
205
202
  const schemaSet = schemaSetEditorState.schemaSet;
206
203
  const applicationStore = schemaSetEditorState.editorStore.applicationStore;
207
204
  const importSchemaContentState =
208
205
  schemaSetEditorState.importSchemaContentState;
209
206
  const currentSchema = schemaSetEditorState.currentSchema;
210
- const isReadOnly = schemaSetEditorState.isReadOnly;
211
207
  const description =
212
208
  schemaSetEditorState.schemaSetModelGenerationState.description;
213
209
  // TEMPROARY engine api should return `fileformat`.
214
- const language = getEditorLanguageFromFormat(description.name);
210
+ const language = description
211
+ ? getEditorLanguageFromFormat(description.name)
212
+ : EDITOR_LANGUAGE.TEXT;
215
213
  const changeState =
216
214
  (schema: Schema): (() => void) =>
217
215
  (): void => {
@@ -246,7 +244,10 @@ const SchemaSetGeneralEditor = observer(
246
244
  }
247
245
  };
248
246
  const validateSchema = (): void => {
249
- if (currentSchema) {
247
+ if (
248
+ currentSchema &&
249
+ schemaSetEditorState instanceof SchemaSetEditorState
250
+ ) {
250
251
  flowResult(schemaSetEditorState.validateSchema(currentSchema)).catch(
251
252
  applicationStore.alertUnhandledError,
252
253
  );
@@ -332,15 +333,17 @@ const SchemaSetGeneralEditor = observer(
332
333
  </div>
333
334
  </div>
334
335
  <div className="panel__header__actions">
335
- <button
336
- className="btn--dark model-loader__header__load-btn"
337
- onClick={validateSchema}
338
- disabled={!currentSchema}
339
- tabIndex={-1}
340
- title="Validate Schema"
341
- >
342
- Validate
343
- </button>
336
+ {schemaSetEditorState instanceof SchemaSetEditorState && (
337
+ <button
338
+ className="btn--dark model-loader__header__load-btn"
339
+ onClick={validateSchema}
340
+ disabled={!currentSchema}
341
+ tabIndex={-1}
342
+ title="Validate Schema"
343
+ >
344
+ Validate
345
+ </button>
346
+ )}
344
347
  </div>
345
348
  </div>
346
349
  <div className="schema-set-panel__content">
@@ -366,133 +369,6 @@ const SchemaSetGeneralEditor = observer(
366
369
  },
367
370
  );
368
371
 
369
- const SchemaSetModelGenerationEditor = observer(
370
- (props: { schemaSetEditorState: SchemaSetEditorState }) => {
371
- const { schemaSetEditorState } = props;
372
- const applicationStore = schemaSetEditorState.editorStore.applicationStore;
373
- const schemaSet = schemaSetEditorState.schemaSet;
374
- const modelGenerationState =
375
- schemaSetEditorState.schemaSetModelGenerationState;
376
- const description = modelGenerationState.description;
377
- const properties = description.modelGenerationProperties;
378
- const isReadOnly = schemaSetEditorState.isReadOnly;
379
- const debouncedRegenerate = useMemo(
380
- () =>
381
- debounce(() => flowResult(modelGenerationState.generateModel()), 500),
382
- [modelGenerationState],
383
- );
384
- const update = (
385
- generationProperty: GenerationProperty,
386
- newValue: object,
387
- ): void => {
388
- debouncedRegenerate.cancel();
389
- modelGenerationState.updateGenerationParameters(
390
- generationProperty,
391
- newValue,
392
- );
393
- debouncedRegenerate()?.catch(applicationStore.alertUnhandledError);
394
- };
395
- const regenerate = (): void => {
396
- modelGenerationState.generateModel();
397
- };
398
- const getConfigValue = (name: string): unknown | undefined =>
399
- modelGenerationState.getConfigValue(name);
400
-
401
- const importGeneratedElements = (): void => {
402
- modelGenerationState.importGrammar();
403
- };
404
- return (
405
- <div className="panel__content file-generation-editor__content">
406
- <ResizablePanelGroup orientation="vertical">
407
- <ResizablePanel size={250} minSize={50}>
408
- <div className="panel file-generation-editor__configuration">
409
- <div className="panel__header">
410
- <div className="panel__header__title">
411
- <div className="panel__header__title__label">{`${schemaSet.format} configuration`}</div>
412
- </div>
413
- <div className="panel__header__actions">
414
- <button
415
- className="panel__header__action file-generation-editor__configuration__reset-btn"
416
- tabIndex={-1}
417
- disabled={isReadOnly || !properties.length}
418
- onClick={regenerate}
419
- title={'Reset to default configuration'}
420
- >
421
- <RefreshIcon />
422
- </button>
423
- </div>
424
- </div>
425
- <div className="panel__content">
426
- <div className="file-generation-editor__configuration__content">
427
- {modelGenerationState.modelGenerationProperties.map(
428
- (abstractGenerationProperty) => (
429
- <GenerationPropertyEditor
430
- key={abstractGenerationProperty.name}
431
- update={update}
432
- isReadOnly={isReadOnly}
433
- getConfigValue={getConfigValue}
434
- property={abstractGenerationProperty}
435
- />
436
- ),
437
- )}
438
- </div>
439
- </div>
440
- </div>
441
- </ResizablePanel>
442
- <ResizablePanelSplitter>
443
- <ResizablePanelSplitterLine color="var(--color-dark-grey-200)" />
444
- </ResizablePanelSplitter>
445
- <ResizablePanel>
446
- <div className="panel generation-result-viewer__file">
447
- <div className="panel__header">
448
- <div className="panel__header__title">
449
- <div className="panel__header__title__label">result</div>
450
- </div>
451
- <div className="panel__header__actions">
452
- <button
453
- className={clsx(
454
- 'panel__header__action generation-result-viewer__regenerate-btn',
455
- {
456
- ' generation-result-viewer__regenerate-btn--loading':
457
- modelGenerationState.isGenerating,
458
- },
459
- )}
460
- tabIndex={-1}
461
- disabled={modelGenerationState.isGenerating}
462
- onClick={regenerate}
463
- title={'Re-generate'}
464
- >
465
- <RefreshIcon />
466
- </button>
467
- <button
468
- className="btn--dark model-loader__header__load-btn"
469
- onClick={importGeneratedElements}
470
- disabled={modelGenerationState.generationValue === ''}
471
- tabIndex={-1}
472
- title="Import generated elements"
473
- >
474
- Import
475
- </button>
476
- </div>
477
- </div>
478
- <div className="panel__content">
479
- <PanelLoadingIndicator
480
- isLoading={modelGenerationState.isGenerating}
481
- />
482
- <StudioTextInputEditor
483
- inputValue={modelGenerationState.generationValue}
484
- isReadOnly={true}
485
- language={EDITOR_LANGUAGE.PURE}
486
- />
487
- </div>
488
- </div>
489
- </ResizablePanel>
490
- </ResizablePanelGroup>
491
- </div>
492
- );
493
- },
494
- );
495
-
496
372
  export const SchemaSetEditor = observer(() => {
497
373
  const editorStore = useEditorStore();
498
374
  const schemaSetEditorState =
@@ -513,17 +389,23 @@ export const SchemaSetEditor = observer(() => {
513
389
  <BlankPanelContent>Fetching format descriptions</BlankPanelContent>
514
390
  );
515
391
  }
516
- if (currentTab === SCHEMA_SET_TAB_TYPE.GENERAL) {
392
+ if (currentTab === SCHEMA_SET_TAB_TYPE.SCHEMAS) {
517
393
  return (
518
- <SchemaSetGeneralEditor schemaSetEditorState={schemaSetEditorState} />
394
+ <SchemaSetGeneralEditor
395
+ schemaSetEditorState={schemaSetEditorState}
396
+ isReadOnly={isReadOnly}
397
+ />
519
398
  );
520
399
  }
521
400
  const supportsModelGeneraiton =
522
401
  schemaSetEditorState.schemaSetModelGenerationState.description
523
- .supportsModelGeneration;
402
+ ?.supportsModelGeneration;
524
403
  return supportsModelGeneraiton ? (
525
404
  <SchemaSetModelGenerationEditor
526
- schemaSetEditorState={schemaSetEditorState}
405
+ modelGenerationState={
406
+ schemaSetEditorState.schemaSetModelGenerationState
407
+ }
408
+ isReadOnly={isReadOnly}
527
409
  />
528
410
  ) : (
529
411
  <BlankPanelContent>
@@ -531,11 +413,12 @@ export const SchemaSetEditor = observer(() => {
531
413
  </BlankPanelContent>
532
414
  );
533
415
  };
416
+
534
417
  return (
535
418
  <div className="panel schema-set-panel">
536
419
  <div className="schema-set-panel__header">
537
420
  <div className="schema-set-panel__header__title">
538
- {isReadOnly && (
421
+ {schemaSetEditorState.isReadOnly && (
539
422
  <div className="schema-set-panel__header__lock">
540
423
  <LockIcon />
541
424
  </div>
@@ -544,7 +427,7 @@ export const SchemaSetEditor = observer(() => {
544
427
  Schema Set
545
428
  </div>
546
429
  <div className="schema-set-panel__header__title__content">
547
- {schemaSet.name}
430
+ {schemaSetEditorState.schemaSet.name}
548
431
  </div>
549
432
  </div>
550
433
  </div>
@@ -568,13 +451,14 @@ export const SchemaSetEditor = observer(() => {
568
451
  </div>
569
452
 
570
453
  <div className="panel__content file-generation-editor__content">
571
- {currentTab === SCHEMA_SET_TAB_TYPE.GENERAL && (
454
+ {currentTab === SCHEMA_SET_TAB_TYPE.SCHEMAS && (
572
455
  <SchemaSetGeneralEditor
573
456
  schemaSetEditorState={schemaSetEditorState}
457
+ isReadOnly={isReadOnly}
574
458
  />
575
459
  )}
576
460
 
577
- {currentTab === SCHEMA_SET_TAB_TYPE.MODEL_GENERATION &&
461
+ {currentTab === SCHEMA_SET_TAB_TYPE.GENERATE_MODEL &&
578
462
  renderMainEditPanel()}
579
463
  </div>
580
464
  </div>
@@ -0,0 +1,226 @@
1
+ /**
2
+ * Copyright (c) 2020-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import { type GenerationProperty, isValidFullPath } from '@finos/legend-graph';
18
+ import { flowResult } from 'mobx';
19
+ import { observer } from 'mobx-react-lite';
20
+ import { useMemo } from 'react';
21
+ import type { SchemaSetModelGenerationState } from '../../../../stores/editor-state/element-editor-state/external-format/SchemaSetEditorState.js';
22
+ import { debounce } from '@finos/legend-shared';
23
+ import {
24
+ clsx,
25
+ InputWithInlineValidation,
26
+ PanelLoadingIndicator,
27
+ RefreshIcon,
28
+ ResizablePanel,
29
+ ResizablePanelGroup,
30
+ ResizablePanelSplitter,
31
+ ResizablePanelSplitterLine,
32
+ } from '@finos/legend-art';
33
+ import { GenerationPropertyEditor } from '../element-generation-editor/FileGenerationEditor.js';
34
+ import { StudioTextInputEditor } from '../../../shared/StudioTextInputEditor.js';
35
+ import { EDITOR_LANGUAGE } from '@finos/legend-application';
36
+
37
+ enum HIDDEN_CONFIGURATION_PROPERTIES {
38
+ FORMAT = 'format',
39
+ }
40
+
41
+ export const SchemaSetModelGenerationEditor = observer(
42
+ (props: {
43
+ modelGenerationState: SchemaSetModelGenerationState;
44
+ isReadOnly: boolean;
45
+ }) => {
46
+ const { modelGenerationState, isReadOnly } = props;
47
+ const applicationStore = modelGenerationState.editorStore.applicationStore;
48
+ const format = modelGenerationState.schemaSet.format;
49
+ const description = modelGenerationState.description;
50
+ const properties = description?.modelGenerationProperties ?? [];
51
+ const debouncedRegenerate = useMemo(
52
+ () =>
53
+ debounce(() => flowResult(modelGenerationState.generateModel()), 500),
54
+ [modelGenerationState],
55
+ );
56
+ const update = (
57
+ generationProperty: GenerationProperty,
58
+ newValue: object,
59
+ ): void => {
60
+ debouncedRegenerate.cancel();
61
+ modelGenerationState.updateGenerationParameters(
62
+ generationProperty,
63
+ newValue,
64
+ );
65
+ debouncedRegenerate()?.catch(applicationStore.alertUnhandledError);
66
+ };
67
+ const regenerate = (): void => {
68
+ modelGenerationState.generateModel();
69
+ };
70
+ const getConfigValue = (name: string): unknown | undefined =>
71
+ modelGenerationState.getConfigValue(name);
72
+ const targetBindingPathValidationMessage =
73
+ Boolean(modelGenerationState.targetBinding) &&
74
+ !isValidFullPath(modelGenerationState.targetBinding)
75
+ ? 'Invalid target binding path'
76
+ : undefined;
77
+
78
+ const changeTargetBindingPath: React.ChangeEventHandler<
79
+ HTMLInputElement
80
+ > = (event) => {
81
+ modelGenerationState.setTargetBindingPath(event.target.value);
82
+ if (
83
+ !modelGenerationState.targetBinding ||
84
+ (modelGenerationState.targetBinding &&
85
+ isValidFullPath(modelGenerationState.targetBinding))
86
+ ) {
87
+ modelGenerationState.handleTargetBindingPathChange();
88
+ debouncedRegenerate()?.catch(applicationStore.alertUnhandledError);
89
+ }
90
+ };
91
+ const importGeneratedElements = (): void => {
92
+ modelGenerationState.importGeneratedModelsIntoGraph();
93
+ };
94
+
95
+ return (
96
+ <div className="panel__content file-generation-editor__content">
97
+ <ResizablePanelGroup orientation="vertical">
98
+ <ResizablePanel size={250} minSize={50}>
99
+ <div className="panel file-generation-editor__configuration">
100
+ <div className="panel__header">
101
+ <div className="panel__header__title">
102
+ <div className="panel__header__title__label">{`${format} configuration`}</div>
103
+ </div>
104
+ <div className="panel__header__actions">
105
+ <button
106
+ className="panel__header__action file-generation-editor__configuration__reset-btn"
107
+ tabIndex={-1}
108
+ disabled={isReadOnly || !properties.length}
109
+ onClick={regenerate}
110
+ title={'Reset to default configuration'}
111
+ >
112
+ <RefreshIcon />
113
+ </button>
114
+ </div>
115
+ </div>
116
+ <div className="panel__content">
117
+ <div className="file-generation-editor__configuration__content">
118
+ <div className="panel__content__form__section">
119
+ <div className="panel__content__form__section__header__label">
120
+ {'Target Binding Path'}
121
+ </div>
122
+ <div className="panel__content__form__section__header__prompt">
123
+ {
124
+ 'If path is provided, a binding will be generated alongside the models. The binding will ensure the schema and models are compatible through compile time validations.'
125
+ }
126
+ </div>
127
+ <InputWithInlineValidation
128
+ className="query-builder__parameters__parameter__name__input input-group__input"
129
+ spellCheck={false}
130
+ value={modelGenerationState.targetBinding}
131
+ onChange={changeTargetBindingPath}
132
+ placeholder={`Target binding path`}
133
+ validationErrorMessage={
134
+ targetBindingPathValidationMessage
135
+ }
136
+ />
137
+ </div>
138
+
139
+ {modelGenerationState.modelGenerationProperties
140
+ .filter(
141
+ (property) =>
142
+ !Object.values(
143
+ HIDDEN_CONFIGURATION_PROPERTIES,
144
+ ).includes(
145
+ property.name as HIDDEN_CONFIGURATION_PROPERTIES,
146
+ ),
147
+ )
148
+ .map((abstractGenerationProperty) => (
149
+ <GenerationPropertyEditor
150
+ key={abstractGenerationProperty.name}
151
+ update={update}
152
+ isReadOnly={isReadOnly}
153
+ getConfigValue={getConfigValue}
154
+ property={abstractGenerationProperty}
155
+ />
156
+ ))}
157
+ </div>
158
+ </div>
159
+ </div>
160
+ </ResizablePanel>
161
+ <ResizablePanelSplitter>
162
+ <ResizablePanelSplitterLine color="var(--color-dark-grey-200)" />
163
+ </ResizablePanelSplitter>
164
+ <ResizablePanel>
165
+ <div className="panel generation-result-viewer__file">
166
+ <div className="panel__header">
167
+ <div className="panel__header__title">
168
+ <div className="panel__header__title__label">result</div>
169
+ </div>
170
+ <div className="panel__header__actions">
171
+ <button
172
+ className={clsx(
173
+ 'panel__header__action generation-result-viewer__regenerate-btn',
174
+ {
175
+ ' generation-result-viewer__regenerate-btn--loading':
176
+ modelGenerationState.generatingModelsState
177
+ .isInProgress ||
178
+ modelGenerationState.importGeneratedElementsState
179
+ .isInProgress,
180
+ },
181
+ )}
182
+ tabIndex={-1}
183
+ disabled={
184
+ modelGenerationState.generatingModelsState.isInProgress ||
185
+ modelGenerationState.importGeneratedElementsState
186
+ .isInProgress
187
+ }
188
+ onClick={regenerate}
189
+ title={'Re-generate'}
190
+ >
191
+ <RefreshIcon />
192
+ </button>
193
+ {!modelGenerationState.isolatedGraph && (
194
+ <button
195
+ className="btn--dark model-loader__header__load-btn"
196
+ onClick={importGeneratedElements}
197
+ disabled={modelGenerationState.generationValue === ''}
198
+ tabIndex={-1}
199
+ title="Import generated elements"
200
+ >
201
+ Import
202
+ </button>
203
+ )}
204
+ </div>
205
+ </div>
206
+ <div className="panel__content">
207
+ <PanelLoadingIndicator
208
+ isLoading={
209
+ modelGenerationState.generatingModelsState.isInProgress ||
210
+ modelGenerationState.importGeneratedElementsState
211
+ .isInProgress
212
+ }
213
+ />
214
+ <StudioTextInputEditor
215
+ inputValue={modelGenerationState.generationValue}
216
+ isReadOnly={true}
217
+ language={EDITOR_LANGUAGE.PURE}
218
+ />
219
+ </div>
220
+ </div>
221
+ </ResizablePanel>
222
+ </ResizablePanelGroup>
223
+ </div>
224
+ );
225
+ },
226
+ );
@@ -212,12 +212,14 @@ export const NewConnectionDataModal = observer(
212
212
  const dataElementOptions = testDataState.editorStore.dataOptions;
213
213
  const newConnectionState = testDataState.newConnectionDataState;
214
214
  const dataElement = newConnectionState.dataElement;
215
- const selectedOption = dataElement ? buildElementOption(dataElement) : null;
215
+ const selectedDataElement = dataElement
216
+ ? buildElementOption(dataElement)
217
+ : null;
216
218
  const onDataElementChange = (val: {
217
219
  label: string;
218
220
  value?: DataElement;
219
221
  }): void => {
220
- if (val.value !== selectedOption?.value && val.value) {
222
+ if (val.value !== selectedDataElement?.value && val.value) {
221
223
  newConnectionState.setDataElement(val.value);
222
224
  }
223
225
  };
@@ -265,7 +267,7 @@ export const NewConnectionDataModal = observer(
265
267
  // external format
266
268
  const selectedEmbeddedType = newConnectionState.embeddedDataType
267
269
  ? {
268
- label: prettyCONSTName(newConnectionState.embeddedDataType.label),
270
+ label: prettyCONSTName(newConnectionState.embeddedDataType.value),
269
271
  value: newConnectionState.embeddedDataType.value,
270
272
  }
271
273
  : undefined;
@@ -301,42 +303,67 @@ export const NewConnectionDataModal = observer(
301
303
  >
302
304
  <form
303
305
  onSubmit={handleSubmit}
304
- className="modal modal--dark search-modal"
306
+ className="modal service-test-data-modal modal--dark"
305
307
  >
306
- <div className="modal__title">Create a connection test data</div>
307
- <div className="explorer__new-element-modal__driver">
308
- <CustomSelectorInput
309
- className="explorer__new-element-modal__driver__dropdown"
310
- options={connectionOptions}
311
- onChange={onConnectionSelectionChange}
312
- value={selectedConnection}
313
- isClearable={false}
314
- darkMode={true}
315
- />
308
+ <div className="modal__header">
309
+ <div className="modal__title">Create a connection test data</div>
316
310
  </div>
317
- <div className="explorer__new-element-modal__driver">
318
- <CustomSelectorInput
319
- className="explorer__new-element-modal__driver__dropdown"
320
- options={embeddedOptions}
321
- onChange={onEmbeddedTypeChange}
322
- value={selectedEmbeddedType}
323
- isClearable={false}
324
- darkMode={true}
325
- />
326
- </div>
327
- {selectedEmbeddedType?.value === EmbeddedDataType.DATA_ELEMENT && (
328
- <div className="explorer__new-element-modal__driver">
329
- <CustomSelectorInput
330
- className="panel__content__form__section__dropdown data-element-reference-editor__value__dropdown"
331
- disabled={isReadOnly}
332
- options={dataElementOptions}
333
- onChange={onDataElementChange}
334
- value={selectedOption}
335
- darkMode={true}
336
- />
311
+ <div className="modal__body">
312
+ <div className="panel__content__form__section">
313
+ <div className="panel__content__form__section__header__label">
314
+ Connection ID
315
+ </div>
316
+ <div className="panel__content__form__section__header__prompt">
317
+ Connection in runtime to povide test data for
318
+ </div>
319
+ <div className="explorer__new-element-modal__driver">
320
+ <CustomSelectorInput
321
+ className="explorer__new-element-modal__driver__dropdown"
322
+ options={connectionOptions}
323
+ onChange={onConnectionSelectionChange}
324
+ value={selectedConnection}
325
+ isClearable={false}
326
+ darkMode={true}
327
+ />
328
+ </div>
337
329
  </div>
338
- )}
339
- <div className="search-modal__actions">
330
+ <div className="panel__content__form__section">
331
+ <div className="panel__content__form__section__header__label">
332
+ Data Type
333
+ </div>
334
+ <div className="panel__content__form__section__header__prompt">
335
+ Test data type that will be loaded to your test connection
336
+ </div>
337
+ <div className="explorer__new-element-modal__driver">
338
+ <CustomSelectorInput
339
+ className="explorer__new-element-modal__driver__dropdown"
340
+ options={embeddedOptions}
341
+ onChange={onEmbeddedTypeChange}
342
+ value={selectedEmbeddedType}
343
+ isClearable={false}
344
+ darkMode={true}
345
+ />
346
+ </div>
347
+ </div>
348
+ {selectedEmbeddedType?.value === EmbeddedDataType.DATA_ELEMENT && (
349
+ <div className="panel__content__form__section">
350
+ <div className="panel__content__form__section__header__label">
351
+ Data Element
352
+ </div>
353
+ <div className="explorer__new-element-modal__driver">
354
+ <CustomSelectorInput
355
+ className="panel__content__form__section__dropdown data-element-reference-editor__value__dropdown"
356
+ disabled={isReadOnly}
357
+ options={dataElementOptions}
358
+ onChange={onDataElementChange}
359
+ value={selectedDataElement}
360
+ darkMode={true}
361
+ />
362
+ </div>
363
+ </div>
364
+ )}
365
+ </div>
366
+ <div className="modal__footer">
340
367
  <button
341
368
  type="button"
342
369
  className="btn btn--dark"