@finos/legend-application-studio 28.21.3 → 28.21.4

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 (42) hide show
  1. package/lib/components/editor/editor-group/data-editor/RelationElementsDataEditor.d.ts.map +1 -1
  2. package/lib/components/editor/editor-group/data-editor/RelationElementsDataEditor.js +63 -20
  3. package/lib/components/editor/editor-group/data-editor/RelationElementsDataEditor.js.map +1 -1
  4. package/lib/components/editor/editor-group/dataProduct/DataProductEditor.d.ts.map +1 -1
  5. package/lib/components/editor/editor-group/dataProduct/DataProductEditor.js +9 -1
  6. package/lib/components/editor/editor-group/dataProduct/DataProductEditor.js.map +1 -1
  7. package/lib/components/editor/editor-group/dataProduct/testable/DataProductTestableEditor.d.ts +23 -0
  8. package/lib/components/editor/editor-group/dataProduct/testable/DataProductTestableEditor.d.ts.map +1 -0
  9. package/lib/components/editor/editor-group/dataProduct/testable/DataProductTestableEditor.js +230 -0
  10. package/lib/components/editor/editor-group/dataProduct/testable/DataProductTestableEditor.js.map +1 -0
  11. package/lib/components/editor/editor-group/testable/TestableSharedComponents.d.ts.map +1 -1
  12. package/lib/components/editor/editor-group/testable/TestableSharedComponents.js +39 -5
  13. package/lib/components/editor/editor-group/testable/TestableSharedComponents.js.map +1 -1
  14. package/lib/index.css +2 -2
  15. package/lib/index.css.map +1 -1
  16. package/lib/package.json +1 -1
  17. package/lib/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.d.ts +16 -1
  18. package/lib/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.d.ts.map +1 -1
  19. package/lib/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.js +36 -1
  20. package/lib/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.js.map +1 -1
  21. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.d.ts +4 -1
  22. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.d.ts.map +1 -1
  23. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js +4 -0
  24. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js.map +1 -1
  25. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.d.ts +118 -0
  26. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.d.ts.map +1 -0
  27. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.js +600 -0
  28. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.js.map +1 -0
  29. package/lib/stores/editor/editor-state/element-editor-state/testable/TestAssertionState.d.ts +17 -1
  30. package/lib/stores/editor/editor-state/element-editor-state/testable/TestAssertionState.d.ts.map +1 -1
  31. package/lib/stores/editor/editor-state/element-editor-state/testable/TestAssertionState.js +46 -1
  32. package/lib/stores/editor/editor-state/element-editor-state/testable/TestAssertionState.js.map +1 -1
  33. package/package.json +9 -9
  34. package/src/components/editor/editor-group/data-editor/RelationElementsDataEditor.tsx +135 -49
  35. package/src/components/editor/editor-group/dataProduct/DataProductEditor.tsx +14 -0
  36. package/src/components/editor/editor-group/dataProduct/testable/DataProductTestableEditor.tsx +872 -0
  37. package/src/components/editor/editor-group/testable/TestableSharedComponents.tsx +169 -15
  38. package/src/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.ts +54 -1
  39. package/src/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.ts +4 -0
  40. package/src/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.ts +863 -0
  41. package/src/stores/editor/editor-state/element-editor-state/testable/TestAssertionState.ts +66 -0
  42. package/tsconfig.json +2 -0
@@ -15,6 +15,7 @@
15
15
  */
16
16
 
17
17
  import {
18
+ BlankPanelPlaceholder,
18
19
  clsx,
19
20
  CompareIcon,
20
21
  ContextMenu,
@@ -38,6 +39,7 @@ import {
38
39
  } from '@finos/legend-art';
39
40
  import {
40
41
  type DataElement,
42
+ DataProduct,
41
43
  type ValueSpecification,
42
44
  type VariableExpression,
43
45
  type PrimitiveInstanceValue,
@@ -61,6 +63,8 @@ import {
61
63
  type TestAssertionState,
62
64
  EqualToAssertionState,
63
65
  EqualToAssertFailState,
66
+ EqualToRelationAssertionState,
67
+ EqualToRelationAssertFailState,
64
68
  } from '../../../../stores/editor/editor-state/element-editor-state/testable/TestAssertionState.js';
65
69
  import { externalFormatData_setData } from '../../../../stores/graph-modifier/DSL_Data_GraphModifierHelper.js';
66
70
  import { TESTABLE_RESULT } from '../../../../stores/editor/sidebar-state/testable/GlobalTestRunnerState.js';
@@ -76,11 +80,13 @@ import {
76
80
  getPackageableElementOptionFormatter,
77
81
  } from '@finos/legend-lego/graph-editor';
78
82
  import type { TestParamContentType } from '../../../../stores/editor/utils/TestableUtils.js';
83
+ import { RelationElementEditor } from '../data-editor/RelationElementsDataEditor.js';
79
84
  import {
80
85
  BasicValueSpecificationEditor,
81
86
  buildDefaultInstanceValue,
82
87
  } from '@finos/legend-query-builder';
83
88
  import { useApplicationStore } from '@finos/legend-application';
89
+ import type { DataProductTestState } from '../../../../stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.js';
84
90
 
85
91
  export const SharedDataElementModal = observer(
86
92
  (props: {
@@ -575,6 +581,132 @@ const TestErrorViewer = observer((props: { testError: TestError }) => {
575
581
  );
576
582
  });
577
583
 
584
+ const EqualToRelationAsssertionEditor = observer(
585
+ (props: {
586
+ testAssertionEditorState: TestAssertionEditorState;
587
+ equalToRelationAssertionState: EqualToRelationAssertionState;
588
+ }) => {
589
+ const { equalToRelationAssertionState, testAssertionEditorState } = props;
590
+ const isReadOnly = testAssertionEditorState.testState.isReadOnly;
591
+
592
+ return (
593
+ <RelationElementEditor
594
+ relationElementState={
595
+ equalToRelationAssertionState.expectedRelationElementState
596
+ }
597
+ isReadOnly={isReadOnly}
598
+ />
599
+ );
600
+ },
601
+ );
602
+
603
+ const DataProductEqualToRelationAssertionEditor = observer(
604
+ (props: { testAssertionEditorState: TestAssertionEditorState }) => {
605
+ const { testAssertionEditorState } = props;
606
+ const testState =
607
+ testAssertionEditorState.testState as DataProductTestState;
608
+ const isReadOnly = testAssertionEditorState.testState.isReadOnly;
609
+ const relationElementState = testState.testDataRelationState;
610
+
611
+ return (
612
+ <div className="service-test-data-editor panel">
613
+ <div className="function-testable-editor__header">
614
+ <div className="function-testable-editor__header__title">
615
+ <div className="function-testable-editor__header__title__label">
616
+ expected
617
+ </div>
618
+ </div>
619
+ </div>
620
+ <div className="panel__content__form__section">
621
+ <div className="panel__content__form__section__header__label">
622
+ Access Point
623
+ </div>
624
+ <div className="panel__content__form__section__header__prompt">
625
+ {testState.accessPointLabel}
626
+ </div>
627
+ </div>
628
+ {relationElementState ? (
629
+ <RelationElementEditor
630
+ relationElementState={relationElementState}
631
+ isReadOnly={isReadOnly}
632
+ />
633
+ ) : (
634
+ <BlankPanelPlaceholder
635
+ text="No expected columns"
636
+ tooltipText="No expected columns configured for this test"
637
+ />
638
+ )}
639
+ </div>
640
+ );
641
+ },
642
+ );
643
+
644
+ const EqualToRelationAssertFailViewer = observer(
645
+ (props: {
646
+ equalToRelationAssertFailState: EqualToRelationAssertFailState;
647
+ }) => {
648
+ const { equalToRelationAssertFailState } = props;
649
+ const applicationStore =
650
+ equalToRelationAssertFailState.resultState.editorStore.applicationStore;
651
+ const open = (): void => equalToRelationAssertFailState.setDiffModal(true);
652
+ const close = (): void =>
653
+ equalToRelationAssertFailState.setDiffModal(false);
654
+ const expected = equalToRelationAssertFailState.status.expected;
655
+ const actual = equalToRelationAssertFailState.status.actual;
656
+
657
+ return (
658
+ <>
659
+ <div className="equal-to-json-editor__message" onClick={open}>
660
+ {`<Click to see difference>`}
661
+ </div>
662
+ {equalToRelationAssertFailState.diffModal && (
663
+ <Dialog
664
+ open={Boolean(equalToRelationAssertFailState.diffModal)}
665
+ onClose={close}
666
+ classes={{
667
+ root: 'editor-modal__root-container',
668
+ container: 'editor-modal__container',
669
+ paper: 'editor-modal__content',
670
+ }}
671
+ >
672
+ <Modal
673
+ darkMode={
674
+ !applicationStore.layoutService
675
+ .TEMPORARY__isLightColorThemeEnabled
676
+ }
677
+ className="editor-modal"
678
+ >
679
+ <ModalHeader>
680
+ <div className="equal-to-json-result__diff__summary">
681
+ <div className="equal-to-json-result__diff__header__label">
682
+ expected
683
+ </div>
684
+ <div className="equal-to-json-result__diff__icon">
685
+ <CompareIcon />
686
+ </div>
687
+ <div className="equal-to-json-result__diff__header__label">
688
+ actual
689
+ </div>
690
+ </div>
691
+ </ModalHeader>
692
+ <ModalBody>
693
+ <JSONDiffView from={expected} to={actual} lossless={false} />
694
+ </ModalBody>
695
+ <ModalFooter>
696
+ <ModalFooterButton
697
+ text="Close"
698
+ onClick={close}
699
+ type="secondary"
700
+ />
701
+ </ModalFooter>
702
+ </Modal>
703
+ </Dialog>
704
+ )}
705
+ </>
706
+ );
707
+ },
708
+ );
709
+
578
710
  const AssertFailViewer = observer(
579
711
  (props: { assertFailState: AssertFailState }) => {
580
712
  const { assertFailState } = props;
@@ -606,6 +738,10 @@ const AssertFailViewer = observer(
606
738
  <EqualToJsonAssertFailViewer
607
739
  equalToJsonAssertFailState={assertFailState}
608
740
  />
741
+ ) : assertFailState instanceof EqualToRelationAssertFailState ? (
742
+ <EqualToRelationAssertFailViewer
743
+ equalToRelationAssertFailState={assertFailState}
744
+ />
609
745
  ) : assertFailState instanceof EqualToAssertFailState ? (
610
746
  <EqualToAssertFailViewer equalToAssertFailState={assertFailState} />
611
747
  ) : isGenericEqualToFail ? (
@@ -849,6 +985,8 @@ export const TestAssertionEditor = observer(
849
985
  const { testAssertionState } = props;
850
986
  const selectedTab = testAssertionState.selectedTab;
851
987
  const isReadOnly = testAssertionState.testState.isReadOnly;
988
+ const isDataProductTest =
989
+ testAssertionState.testState.testable instanceof DataProduct;
852
990
  const isDisabled =
853
991
  isReadOnly ||
854
992
  !testAssertionState.assertionState.supportsGeneratingAssertion ||
@@ -870,6 +1008,20 @@ export const TestAssertionEditor = observer(
870
1008
  testAssertionEditorState={testAssertionState}
871
1009
  />
872
1010
  );
1011
+ } else if (state instanceof EqualToRelationAssertionState) {
1012
+ if (isDataProductTest) {
1013
+ return (
1014
+ <DataProductEqualToRelationAssertionEditor
1015
+ testAssertionEditorState={testAssertionState}
1016
+ />
1017
+ );
1018
+ }
1019
+ return (
1020
+ <EqualToRelationAsssertionEditor
1021
+ equalToRelationAssertionState={state}
1022
+ testAssertionEditorState={testAssertionState}
1023
+ />
1024
+ );
873
1025
  }
874
1026
  return (
875
1027
  <UnsupportedEditorPanel
@@ -901,22 +1053,24 @@ export const TestAssertionEditor = observer(
901
1053
  </div>
902
1054
  ))}
903
1055
  </div>
904
- <div className="testable-test-assertion-editor__header__actions">
905
- <button
906
- className="panel__header__action service-execution-editor__test-data__generate-btn"
907
- onClick={generate}
908
- title="Generate expected result if possible"
909
- disabled={isDisabled}
910
- tabIndex={-1}
911
- >
912
- <div className="service-execution-editor__test-data__generate-btn__label">
913
- <RefreshIcon className="service-execution-editor__test-data__generate-btn__label__icon" />
914
- <div className="service-execution-editor__test-data__generate-btn__label__title">
915
- Generate
1056
+ {!isDataProductTest && (
1057
+ <div className="testable-test-assertion-editor__header__actions">
1058
+ <button
1059
+ className="panel__header__action service-execution-editor__test-data__generate-btn"
1060
+ onClick={generate}
1061
+ title="Generate expected result if possible"
1062
+ disabled={isDisabled}
1063
+ tabIndex={-1}
1064
+ >
1065
+ <div className="service-execution-editor__test-data__generate-btn__label">
1066
+ <RefreshIcon className="service-execution-editor__test-data__generate-btn__label__icon" />
1067
+ <div className="service-execution-editor__test-data__generate-btn__label__title">
1068
+ Generate
1069
+ </div>
916
1070
  </div>
917
- </div>
918
- </button>
919
- </div>
1071
+ </button>
1072
+ </div>
1073
+ )}
920
1074
  </div>
921
1075
  <div className="testable-test-assertion-editor__content">
922
1076
  {selectedTab === TEST_ASSERTION_TAB.EXPECTED && (
@@ -211,8 +211,12 @@ export class ModelStoreDataState extends EmbeddedDataState {
211
211
 
212
212
  export class RelationElementState {
213
213
  relationElement: RelationElement;
214
+ supportsColumnEditing: boolean;
214
215
 
215
- constructor(relationElement: RelationElement) {
216
+ constructor(
217
+ relationElement: RelationElement,
218
+ options?: { supportsColumnEditing?: boolean },
219
+ ) {
216
220
  makeObservable(this, {
217
221
  relationElement: observable,
218
222
  addColumn: action,
@@ -224,6 +228,7 @@ export class RelationElementState {
224
228
  clearAllData: action,
225
229
  importCSV: action,
226
230
  });
231
+ this.supportsColumnEditing = options?.supportsColumnEditing ?? true;
227
232
  this.relationElement = relationElement;
228
233
  this.relationElement = observe_RelationElement(relationElement);
229
234
  }
@@ -382,12 +387,21 @@ export class RelationElementState {
382
387
  }
383
388
  }
384
389
 
390
+ export interface RelationElementAccessorOption {
391
+ label: string;
392
+ value: string;
393
+ columns: string[];
394
+ }
395
+
385
396
  export class RelationElementsDataState extends EmbeddedDataState {
386
397
  override embeddedData: RelationElementsData;
387
398
  showImportCSVModal = false;
388
399
  showNewRelationElementModal = false;
389
400
  activeRelationElement: RelationElementState | undefined;
390
401
  relationElementStates: RelationElementState[];
402
+ accessorOptions: RelationElementAccessorOption[] | undefined;
403
+ accessorTypeLabel: string | undefined;
404
+ refreshAccessorOptions: (() => Promise<void>) | undefined;
391
405
 
392
406
  constructor(editorStore: EditorStore, embeddedData: RelationElementsData) {
393
407
  super(editorStore, embeddedData);
@@ -396,10 +410,15 @@ export class RelationElementsDataState extends EmbeddedDataState {
396
410
  showImportCSVModal: observable,
397
411
  showNewRelationElementModal: observable,
398
412
  activeRelationElement: observable,
413
+ relationElementStates: observable,
414
+ accessorOptions: observable,
415
+ accessorTypeLabel: observable,
399
416
  setActiveRelationElement: action,
400
417
  setShowImportCSVModal: action,
401
418
  setShowNewRelationElementModal: action,
402
419
  addRelationElement: action,
420
+ deleteRelationElement: action,
421
+ setAccessorOptions: action,
403
422
  });
404
423
  this.embeddedData = embeddedData;
405
424
  this.relationElementStates = embeddedData.relationElements.map(
@@ -423,6 +442,18 @@ export class RelationElementsDataState extends EmbeddedDataState {
423
442
  this.setActiveRelationElement(newElementState);
424
443
  }
425
444
 
445
+ deleteRelationElement(relationElementState: RelationElementState): void {
446
+ const idx = this.relationElementStates.indexOf(relationElementState);
447
+ if (idx === -1) {
448
+ return;
449
+ }
450
+ this.relationElementStates.splice(idx, 1);
451
+ this.embeddedData.relationElements.splice(idx, 1);
452
+ if (this.activeRelationElement === relationElementState) {
453
+ this.setActiveRelationElement(this.relationElementStates[0]);
454
+ }
455
+ }
456
+
426
457
  setShowImportCSVModal(show: boolean): void {
427
458
  this.showImportCSVModal = show;
428
459
  }
@@ -430,6 +461,28 @@ export class RelationElementsDataState extends EmbeddedDataState {
430
461
  setShowNewRelationElementModal(show: boolean): void {
431
462
  this.showNewRelationElementModal = show;
432
463
  }
464
+
465
+ setAccessorOptions(
466
+ options: RelationElementAccessorOption[] | undefined,
467
+ typeLabel: string | undefined,
468
+ ): void {
469
+ this.accessorOptions = options;
470
+ this.accessorTypeLabel = typeLabel;
471
+ }
472
+
473
+ setRefreshAccessorOptions(fn: (() => Promise<void>) | undefined): void {
474
+ this.refreshAccessorOptions = fn;
475
+ }
476
+
477
+ get availableAccessorOptions(): RelationElementAccessorOption[] {
478
+ if (!this.accessorOptions) {
479
+ return [];
480
+ }
481
+ const existingPaths = new Set(
482
+ this.relationElementStates.map((s) => s.relationElement.paths.join('.')),
483
+ );
484
+ return this.accessorOptions.filter((opt) => !existingPaths.has(opt.value));
485
+ }
433
486
  }
434
487
 
435
488
  export class RelationalCSVDataTableState {
@@ -109,6 +109,7 @@ import {
109
109
  modelAccessPointGroup_setMapping,
110
110
  dataProduct_setSupportInfoIfAbsent,
111
111
  } from '../../../../graph-modifier/DSL_DataProduct_GraphModifierHelper.js';
112
+ import { DataProductTestableState } from './testable/DataProductTestableState.js';
112
113
  import { LambdaEditorState, LineageState } from '@finos/legend-query-builder';
113
114
  import {
114
115
  DataProductElementEditorInitialConfiguration,
@@ -129,6 +130,7 @@ export enum DATA_PRODUCT_TAB {
129
130
  SUPPORT = 'Support',
130
131
  APG = 'APG',
131
132
  OPERATIONAL = 'Operational',
133
+ TESTING = 'Testing',
132
134
  }
133
135
 
134
136
  export enum DATA_PRODUCT_TYPE {
@@ -966,6 +968,7 @@ export class DataProductEditorState extends ElementEditorState {
966
968
  selectedGroupState: AccessPointGroupState | undefined;
967
969
  selectedTab: DATA_PRODUCT_TAB;
968
970
  modelledDataProduct = false;
971
+ testableState: DataProductTestableState;
969
972
 
970
973
  constructor(
971
974
  editorStore: EditorStore,
@@ -1015,6 +1018,7 @@ export class DataProductEditorState extends ElementEditorState {
1015
1018
  this.deployOnOpen = elementConfig.deployOnOpen ?? false;
1016
1019
  }
1017
1020
  this.selectedTab = DATA_PRODUCT_TAB.HOME;
1021
+ this.testableState = new DataProductTestableState(this);
1018
1022
  }
1019
1023
 
1020
1024
  setDeployOnOpen(value: boolean): void {