@finos/legend-application-studio 28.21.31 → 28.21.33

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 (86) hide show
  1. package/lib/__lib__/LegendStudioApplicationNavigationContext.d.ts +2 -1
  2. package/lib/__lib__/LegendStudioApplicationNavigationContext.d.ts.map +1 -1
  3. package/lib/__lib__/LegendStudioApplicationNavigationContext.js +1 -0
  4. package/lib/__lib__/LegendStudioApplicationNavigationContext.js.map +1 -1
  5. package/lib/components/ElementIconUtils.d.ts.map +1 -1
  6. package/lib/components/ElementIconUtils.js +2 -0
  7. package/lib/components/ElementIconUtils.js.map +1 -1
  8. package/lib/components/editor/availability-editor.css +1 -0
  9. package/lib/components/editor/availability-editor.css.map +1 -0
  10. package/lib/components/editor/editor-group/EditorGroup.d.ts.map +1 -1
  11. package/lib/components/editor/editor-group/EditorGroup.js +5 -0
  12. package/lib/components/editor/editor-group/EditorGroup.js.map +1 -1
  13. package/lib/components/editor/editor-group/availability/AvailabilityEditor.d.ts +19 -0
  14. package/lib/components/editor/editor-group/availability/AvailabilityEditor.d.ts.map +1 -0
  15. package/lib/components/editor/editor-group/availability/AvailabilityEditor.js +50 -0
  16. package/lib/components/editor/editor-group/availability/AvailabilityEditor.js.map +1 -0
  17. package/lib/components/editor/editor-group/availability/testable/AvailabilityTestableEditor.d.ts +22 -0
  18. package/lib/components/editor/editor-group/availability/testable/AvailabilityTestableEditor.d.ts.map +1 -0
  19. package/lib/components/editor/editor-group/availability/testable/AvailabilityTestableEditor.js +205 -0
  20. package/lib/components/editor/editor-group/availability/testable/AvailabilityTestableEditor.js.map +1 -0
  21. package/lib/components/editor/editor-group/dataProduct/DataProductEditor.d.ts +1 -12
  22. package/lib/components/editor/editor-group/dataProduct/DataProductEditor.d.ts.map +1 -1
  23. package/lib/components/editor/editor-group/dataProduct/DataProductEditor.js +3 -86
  24. package/lib/components/editor/editor-group/dataProduct/DataProductEditor.js.map +1 -1
  25. package/lib/components/editor/editor-group/testable/TestableSharedComponents.d.ts +5 -0
  26. package/lib/components/editor/editor-group/testable/TestableSharedComponents.d.ts.map +1 -1
  27. package/lib/components/editor/editor-group/testable/TestableSharedComponents.js +1 -1
  28. package/lib/components/editor/editor-group/testable/TestableSharedComponents.js.map +1 -1
  29. package/lib/components/editor/panel-group/DevToolPanel.d.ts.map +1 -1
  30. package/lib/components/editor/panel-group/DevToolPanel.js +27 -24
  31. package/lib/components/editor/panel-group/DevToolPanel.js.map +1 -1
  32. package/lib/components/extensions/Core_LegendStudioApplicationPlugin.d.ts.map +1 -1
  33. package/lib/components/extensions/Core_LegendStudioApplicationPlugin.js +1 -0
  34. package/lib/components/extensions/Core_LegendStudioApplicationPlugin.js.map +1 -1
  35. package/lib/index.css +2 -2
  36. package/lib/index.css.map +1 -1
  37. package/lib/package.json +1 -1
  38. package/lib/stores/editor/EditorGraphState.d.ts.map +1 -1
  39. package/lib/stores/editor/EditorGraphState.js +4 -1
  40. package/lib/stores/editor/EditorGraphState.js.map +1 -1
  41. package/lib/stores/editor/EditorTabManagerState.d.ts.map +1 -1
  42. package/lib/stores/editor/EditorTabManagerState.js +5 -1
  43. package/lib/stores/editor/EditorTabManagerState.js.map +1 -1
  44. package/lib/stores/editor/editor-state/element-editor-state/availability/AvailabilityEditorState.d.ts +32 -0
  45. package/lib/stores/editor/editor-state/element-editor-state/availability/AvailabilityEditorState.d.ts.map +1 -0
  46. package/lib/stores/editor/editor-state/element-editor-state/availability/AvailabilityEditorState.js +46 -0
  47. package/lib/stores/editor/editor-state/element-editor-state/availability/AvailabilityEditorState.js.map +1 -0
  48. package/lib/stores/editor/editor-state/element-editor-state/availability/testable/AvailabilityTestableState.d.ts +111 -0
  49. package/lib/stores/editor/editor-state/element-editor-state/availability/testable/AvailabilityTestableState.d.ts.map +1 -0
  50. package/lib/stores/editor/editor-state/element-editor-state/availability/testable/AvailabilityTestableState.js +425 -0
  51. package/lib/stores/editor/editor-state/element-editor-state/availability/testable/AvailabilityTestableState.js.map +1 -0
  52. package/lib/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.d.ts +3 -0
  53. package/lib/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.d.ts.map +1 -1
  54. package/lib/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.js +8 -2
  55. package/lib/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.js.map +1 -1
  56. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.d.ts +1 -22
  57. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.d.ts.map +1 -1
  58. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js +3 -109
  59. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js.map +1 -1
  60. package/lib/stores/editor/utils/ModelClassifierUtils.d.ts +2 -1
  61. package/lib/stores/editor/utils/ModelClassifierUtils.d.ts.map +1 -1
  62. package/lib/stores/editor/utils/ModelClassifierUtils.js +1 -0
  63. package/lib/stores/editor/utils/ModelClassifierUtils.js.map +1 -1
  64. package/lib/stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.d.ts +1 -8
  65. package/lib/stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.d.ts.map +1 -1
  66. package/lib/stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.js +0 -21
  67. package/lib/stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.js.map +1 -1
  68. package/package.json +12 -12
  69. package/src/__lib__/LegendStudioApplicationNavigationContext.ts +1 -0
  70. package/src/components/ElementIconUtils.tsx +2 -0
  71. package/src/components/editor/editor-group/EditorGroup.tsx +4 -0
  72. package/src/components/editor/editor-group/availability/AvailabilityEditor.tsx +114 -0
  73. package/src/components/editor/editor-group/availability/testable/AvailabilityTestableEditor.tsx +829 -0
  74. package/src/components/editor/editor-group/dataProduct/DataProductEditor.tsx +0 -282
  75. package/src/components/editor/editor-group/testable/TestableSharedComponents.tsx +1 -1
  76. package/src/components/editor/panel-group/DevToolPanel.tsx +61 -60
  77. package/src/components/extensions/Core_LegendStudioApplicationPlugin.tsx +1 -0
  78. package/src/stores/editor/EditorGraphState.ts +3 -0
  79. package/src/stores/editor/EditorTabManagerState.ts +4 -0
  80. package/src/stores/editor/editor-state/element-editor-state/availability/AvailabilityEditorState.ts +56 -0
  81. package/src/stores/editor/editor-state/element-editor-state/availability/testable/AvailabilityTestableState.ts +631 -0
  82. package/src/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.ts +13 -3
  83. package/src/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.ts +1 -162
  84. package/src/stores/editor/utils/ModelClassifierUtils.ts +1 -0
  85. package/src/stores/graph-modifier/DSL_DataProduct_GraphModifierHelper.ts +0 -44
  86. package/tsconfig.json +4 -0
@@ -86,7 +86,6 @@ import {
86
86
  type ChangeEventHandler,
87
87
  useCallback,
88
88
  useEffect,
89
- useLayoutEffect,
90
89
  useMemo,
91
90
  useRef,
92
91
  useState,
@@ -114,15 +113,12 @@ import { DataProductTestableEditor } from './testable/DataProductTestableEditor.
114
113
  import { CODE_EDITOR_LANGUAGE } from '@finos/legend-code-editor';
115
114
  import { CodeEditor } from '@finos/legend-lego/code-editor';
116
115
  import {
117
- type DataProductElement,
118
- type DataProductElementScope,
119
116
  type Expertise,
120
117
  type GraphManagerState,
121
118
  type LakehouseAccessPoint,
122
119
  type Mapping,
123
120
  type PackageableElement,
124
121
  type DataProduct,
125
- type DataProductDiagram,
126
122
  DataProductEmbeddedImageIcon,
127
123
  DataProductLibraryIcon,
128
124
  Email,
@@ -174,8 +170,6 @@ import {
174
170
  dataProduct_setOperationalMetadataIfAbsent,
175
171
  operationalMetadata_deleteCoverageRegion,
176
172
  operationalMetadata_addCoverageRegion,
177
- dataProductDiagram_setTitle,
178
- dataProductDiagram_setDescription,
179
173
  operationalMetadata_setUpdateFrequency,
180
174
  dataProduct_setOwner,
181
175
  appDirOwner_setProduction,
@@ -1383,277 +1377,6 @@ const AccessPointGroupPublicToggle = observer(
1383
1377
  },
1384
1378
  );
1385
1379
 
1386
- export const CompatibleDiagramsEditor = observer(
1387
- (props: { groupState: ModelAccessPointGroupState }) => {
1388
- const { groupState } = props;
1389
- const group = groupState.value;
1390
-
1391
- const handleDiagramTitleChange = (
1392
- diagram: DataProductDiagram,
1393
- value: string | undefined,
1394
- ): void => {
1395
- dataProductDiagram_setTitle(diagram, value ?? '');
1396
- };
1397
-
1398
- const handleDiagramDescriptionChange = (
1399
- diagram: DataProductDiagram,
1400
- value: string | undefined,
1401
- ): void => {
1402
- dataProductDiagram_setDescription(diagram, value);
1403
- };
1404
-
1405
- const handleAddDiagram = (option: {
1406
- label: string;
1407
- value: PackageableElement;
1408
- }): void => {
1409
- groupState.addDiagram(option);
1410
- };
1411
-
1412
- const handleRemoveDiagram = (diagram: DataProductDiagram): void => {
1413
- groupState.handleRemoveDiagram(diagram);
1414
- };
1415
-
1416
- // ListEditor component renderers
1417
- const DiagramComponent = observer(
1418
- (diagramComponentProps: {
1419
- item: DataProductDiagram;
1420
- }): React.ReactElement => {
1421
- const { item } = diagramComponentProps;
1422
-
1423
- return (
1424
- <>
1425
- <div className="panel__content__form__section__list__item__content">
1426
- <div className="panel__content__form__section__header__label">
1427
- Diagram
1428
- </div>
1429
- <div className="panel__content__form__section__list__item__content__title">
1430
- {item.diagram.name}
1431
- </div>
1432
- </div>
1433
- <div className="panel__content__form__section__list__item__form">
1434
- <PanelFormTextField
1435
- name="Title"
1436
- value={item.title}
1437
- update={(value) => handleDiagramTitleChange(item, value)}
1438
- placeholder="Enter title"
1439
- className="dataSpace-editor__general__diagrams__title"
1440
- />
1441
- <PanelFormTextField
1442
- name="Description"
1443
- value={item.description ?? ''}
1444
- update={(value) => handleDiagramDescriptionChange(item, value)}
1445
- placeholder="Enter description"
1446
- className="dataSpace-editor__general__diagrams__description"
1447
- />
1448
- </div>
1449
- </>
1450
- );
1451
- },
1452
- );
1453
-
1454
- const hasMappingSet = group.mapping.value.path !== '';
1455
- const noDiagramsInProject =
1456
- groupState.getCompatibleDiagramOptions().length === 0 &&
1457
- group.diagrams.length === 0;
1458
- const [isGenerating, setIsGenerating] = useState(false);
1459
- const [isAddingDiagram, setIsAddingDiagram] = useState(false);
1460
-
1461
- const handleGenerateFromMapping = (): void => {
1462
- setIsGenerating(true);
1463
- flowResult(groupState.generateDiagramFromMapping())
1464
- .catch(
1465
- groupState.state.editorStore.applicationStore.alertUnhandledError,
1466
- )
1467
- .finally(() => setIsGenerating(false));
1468
- };
1469
-
1470
- const NewDiagramComponent = observer(
1471
- (newDiagramProps: {
1472
- onFinishEditing: () => void;
1473
- }): React.ReactElement => {
1474
- const { onFinishEditing } = newDiagramProps;
1475
-
1476
- useLayoutEffect(() => {
1477
- setIsAddingDiagram(true);
1478
- return () => setIsAddingDiagram(false);
1479
- }, []);
1480
-
1481
- return (
1482
- <>
1483
- <div className="panel__content__form__section__list__new-item__input">
1484
- <CustomSelectorInput
1485
- options={groupState.getCompatibleDiagramOptions()}
1486
- onChange={(event: {
1487
- label: string;
1488
- value: PackageableElement;
1489
- }) => {
1490
- onFinishEditing();
1491
- handleAddDiagram(event);
1492
- }}
1493
- placeholder="Select a diagram to add..."
1494
- darkMode={
1495
- !groupState.state.editorStore.applicationStore.layoutService
1496
- .TEMPORARY__isLightColorThemeEnabled
1497
- }
1498
- />
1499
- </div>
1500
- {noDiagramsInProject &&
1501
- hasMappingSet &&
1502
- !groupState.state.isReadOnly && (
1503
- <button
1504
- className="panel__content__form__section__list__new-item__cancel-btn btn btn--dark"
1505
- disabled={isGenerating}
1506
- onClick={() => {
1507
- onFinishEditing();
1508
- handleGenerateFromMapping();
1509
- }}
1510
- title="Auto-generate a diagram from the mapping"
1511
- tabIndex={-1}
1512
- >
1513
- {isGenerating ? 'Generating...' : 'Generate from Mapping'}
1514
- </button>
1515
- )}
1516
- </>
1517
- );
1518
- },
1519
- );
1520
-
1521
- return (
1522
- <div className="data-product-editor__diagrams-section">
1523
- <ListEditor
1524
- title="Diagrams"
1525
- prompt="Add diagrams to include in this Data Product. Diagrams are required to showcase and explain your curated data models"
1526
- items={group.diagrams}
1527
- keySelector={(element: DataProductDiagram) => element.diagram.name}
1528
- ItemComponent={DiagramComponent}
1529
- NewItemComponent={NewDiagramComponent}
1530
- handleRemoveItem={handleRemoveDiagram}
1531
- isReadOnly={groupState.state.isReadOnly}
1532
- emptyMessage="⚠ No Diagrams specified. Add at least one diagram to this Data Product."
1533
- emptyClassName="data-product-editor__empty-diagram"
1534
- />
1535
- {noDiagramsInProject &&
1536
- !isAddingDiagram &&
1537
- hasMappingSet &&
1538
- !groupState.state.isReadOnly && (
1539
- <div className="data-product-editor__generate-diagram-btn">
1540
- <button
1541
- className="panel__content__form__section__list__new-item__add-btn btn btn--dark"
1542
- disabled={isGenerating}
1543
- onClick={handleGenerateFromMapping}
1544
- title="Generate a Diagram from the Mapping"
1545
- tabIndex={-1}
1546
- >
1547
- {isGenerating ? 'Generating...' : 'Generate from Mapping'}
1548
- </button>
1549
- </div>
1550
- )}
1551
- </div>
1552
- );
1553
- },
1554
- );
1555
-
1556
- export const FeaturedElementsEditor = observer(
1557
- (props: { groupState: ModelAccessPointGroupState; isReadOnly: boolean }) => {
1558
- const { groupState, isReadOnly } = props;
1559
- const group = groupState.value;
1560
-
1561
- // Event handlers
1562
- const handleAddElement = (option: {
1563
- label: string;
1564
- value: DataProductElement;
1565
- }): void => {
1566
- if (typeof option.value === 'object') {
1567
- groupState.addFeaturedElement(option.value);
1568
- }
1569
- };
1570
-
1571
- const handleRemoveElement = (element: DataProductElementScope): void => {
1572
- groupState.removeFeaturedElement(element);
1573
- };
1574
-
1575
- const handleElementExcludeChange = (
1576
- element: DataProductElementScope,
1577
- event: React.ChangeEvent<HTMLInputElement>,
1578
- ): void => {
1579
- groupState.excludeFeaturedElement(element, event.target.checked);
1580
- };
1581
-
1582
- // ListEditor component renderers
1583
- const ElementComponent = observer(
1584
- (elementComponentProps: {
1585
- item: DataProductElementScope;
1586
- }): React.ReactElement => {
1587
- const { item } = elementComponentProps;
1588
-
1589
- return (
1590
- <div className="data-product-editor__element-item">
1591
- <div className="panel__content__form__section__list__item__content__label">
1592
- {item.element.value.path}
1593
- </div>
1594
- <div className="panel__content__form__section__list__item__content__actions">
1595
- <div className="panel__content__form__section__list__item__content__actions-exclude">
1596
- <Checkbox
1597
- disabled={isReadOnly}
1598
- checked={item.exclude ?? false}
1599
- onChange={(event) => handleElementExcludeChange(item, event)}
1600
- size="small"
1601
- className="panel__content__form__section__list__item__content__actions-exclude__btn"
1602
- />
1603
- <span className="panel__content__form__section__list__item__content__actions__label">
1604
- Exclude
1605
- </span>
1606
- </div>
1607
- </div>
1608
- </div>
1609
- );
1610
- },
1611
- );
1612
-
1613
- const NewElementComponent = observer(
1614
- (newElementProps: { onFinishEditing: () => void }) => {
1615
- const { onFinishEditing } = newElementProps;
1616
-
1617
- return (
1618
- <div className="panel__content__form__section__list__new-item__input">
1619
- <CustomSelectorInput
1620
- options={groupState.getFeaturedElementOptions()}
1621
- onChange={(event: {
1622
- label: string;
1623
- value: DataProductElement;
1624
- }) => {
1625
- onFinishEditing();
1626
- handleAddElement(event);
1627
- }}
1628
- placeholder="Select an element to add..."
1629
- darkMode={
1630
- !groupState.state.editorStore.applicationStore.layoutService
1631
- .TEMPORARY__isLightColorThemeEnabled
1632
- }
1633
- />
1634
- </div>
1635
- );
1636
- },
1637
- );
1638
-
1639
- return (
1640
- <ListEditor
1641
- title="Featured Elements"
1642
- prompt="Add classes and associations to display under Models Documentation. Use the exclude checkbox to exclude certain elements from this Data Product entirely."
1643
- items={group.featuredElements}
1644
- keySelector={(element: DataProductElementScope) =>
1645
- element.element.value.path
1646
- }
1647
- ItemComponent={ElementComponent}
1648
- NewItemComponent={NewElementComponent}
1649
- handleRemoveItem={handleRemoveElement}
1650
- isReadOnly={isReadOnly}
1651
- emptyMessage="No elements specified"
1652
- />
1653
- );
1654
- },
1655
- );
1656
-
1657
1380
  const ModelAccessPointGroupEditor = observer(
1658
1381
  (props: { groupState: ModelAccessPointGroupState; isReadOnly: boolean }) => {
1659
1382
  const { groupState, isReadOnly } = props;
@@ -1718,11 +1441,6 @@ const ModelAccessPointGroupEditor = observer(
1718
1441
  <LongArrowRightIcon />
1719
1442
  </button>
1720
1443
  </div>
1721
- <FeaturedElementsEditor
1722
- groupState={groupState}
1723
- isReadOnly={isReadOnly}
1724
- />
1725
- <CompatibleDiagramsEditor groupState={groupState} />
1726
1444
  </div>
1727
1445
  );
1728
1446
  },
@@ -795,7 +795,7 @@ const AssertFailViewer = observer(
795
795
  },
796
796
  );
797
797
 
798
- const TestAssertionResultViewer = observer(
798
+ export const TestAssertionResultViewer = observer(
799
799
  (props: { testAssertionEditorState: TestAssertionEditorState }) => {
800
800
  const { testAssertionEditorState } = props;
801
801
  const parentAssertionResultState =
@@ -31,12 +31,8 @@ import {
31
31
  } from '@finos/legend-shared';
32
32
  import { useEditorStore } from '../EditorStoreProvider.js';
33
33
  import { LEGEND_STUDIO_SETTING_KEY } from '../../../__lib__/LegendStudioSetting.js';
34
- import { flowResult } from 'mobx';
35
- import {
36
- PARSER_SECTION_MARKER,
37
- PURE_PARSER,
38
- type PureModel,
39
- } from '@finos/legend-graph';
34
+ import { PARSER_SECTION_MARKER, PURE_PARSER } from '@finos/legend-graph';
35
+ import { ProjectDependencyCoordinates } from '@finos/legend-server-depot';
40
36
 
41
37
  export const DevToolPanel = observer(() => {
42
38
  const editorStore = useEditorStore();
@@ -75,53 +71,50 @@ export const DevToolPanel = observer(() => {
75
71
  );
76
72
  };
77
73
 
78
- const downloadDependencyProjectGrammars = async (): Promise<string[]> => {
79
- const grammars = await Promise.all(
80
- Array.from(
81
- editorStore.graphManagerState.graph.dependencyManager
82
- .projectDependencyModelsIndex,
83
- ).map(
84
- (graph) =>
85
- flowResult(
86
- editorStore.graphManagerState.graphManager.graphToPureCode(
87
- graph[1] as PureModel,
88
- {
89
- pretty: true,
90
- },
91
- ),
92
- ) as string,
93
- ),
94
- );
95
- return grammars;
96
- };
97
-
98
74
  const downloadProjectGrammar = async (
99
75
  withDependency: boolean,
100
76
  ): Promise<void> => {
101
- const graphGrammar = (await Promise.all([
102
- flowResult(
103
- editorStore.graphManagerState.graphManager.graphToPureCode(
104
- editorStore.graphManagerState.graph,
105
- { pretty: true },
106
- ),
107
- ),
108
- ])) as unknown as string;
109
- const dependencyGrammars = withDependency
110
- ? ((await Promise.all([
111
- flowResult(downloadDependencyProjectGrammars()),
112
- ])) as unknown as string[])
113
- : [];
114
- const fullGrammar = [graphGrammar, ...dependencyGrammars].join(
115
- `\n${PARSER_SECTION_MARKER}${PURE_PARSER.PURE}\n`,
77
+ const graphManager = editorStore.graphManagerState.graphManager;
78
+ const graphGrammar = await graphManager.graphToPureCode(
79
+ editorStore.graphManagerState.graph,
80
+ { pretty: true },
116
81
  );
82
+ let dependencyGrammar: string | undefined;
83
+ if (withDependency) {
84
+ // Fetch the dependency graph directly from Depot as a
85
+ // `V1_PureModelContextData` payload and hand it straight to the engine
86
+ // grammar transform. This skips building a `PureModel` for dependencies
87
+ // and collapses the whole dependency graph into a single engine call.
88
+ const projectDependencies =
89
+ editorStore.projectConfigurationEditorState.currentProjectConfiguration
90
+ .projectDependencies;
91
+ if (projectDependencies.length) {
92
+ const dependencyCoordinates =
93
+ await editorStore.graphState.buildProjectDependencyCoordinates(
94
+ projectDependencies,
95
+ );
96
+ const dependencyProtocolGraph =
97
+ await editorStore.depotServerClient.collectDependencyEntitiesAsPureModelContextData(
98
+ dependencyCoordinates.map((e) =>
99
+ ProjectDependencyCoordinates.serialization.toJson(e),
100
+ ),
101
+ true,
102
+ true,
103
+ );
104
+ dependencyGrammar = await graphManager.protocolToPureCode(
105
+ dependencyProtocolGraph,
106
+ { pretty: true },
107
+ );
108
+ }
109
+ }
110
+ const fullGrammar =
111
+ dependencyGrammar === undefined
112
+ ? graphGrammar
113
+ : `${graphGrammar}\n${PARSER_SECTION_MARKER}${PURE_PARSER.PURE}\n// ------------------------------------------------------------\n// Dependency grammar starts here\n// ------------------------------------------------------------\n${dependencyGrammar}`;
117
114
  const fileName = `grammar.${getContentTypeFileExtension(
118
115
  ContentType.TEXT_PLAIN,
119
116
  )}`;
120
- downloadFileUsingDataURI(
121
- fileName,
122
- `${fullGrammar}`,
123
- ContentType.TEXT_PLAIN,
124
- );
117
+ downloadFileUsingDataURI(fileName, fullGrammar, ContentType.TEXT_PLAIN);
125
118
  };
126
119
 
127
120
  return (
@@ -205,16 +198,20 @@ export const DevToolPanel = observer(() => {
205
198
  />
206
199
  <PanelFormListItems title="Download Project Grammar">
207
200
  <div className="developer-tools__action-groups">
208
- <div className="developer-tools__action-group">
201
+ <div
202
+ className="developer-tools__action-group"
203
+ onClick={() => {
204
+ downloadProjectGrammar(false).catch(
205
+ editorStore.applicationStore.alertUnhandledError,
206
+ );
207
+ }}
208
+ role="button"
209
+ tabIndex={-1}
210
+ title="Download Project Grammar"
211
+ >
209
212
  <button
210
213
  className="developer-tools__action-group__btn"
211
- onClick={() => {
212
- downloadProjectGrammar(false).catch(
213
- editorStore.applicationStore.alertUnhandledError,
214
- );
215
- }}
216
214
  tabIndex={-1}
217
- title="Download Project Grammar"
218
215
  >
219
216
  <CloudDownloadIcon />
220
217
  </button>
@@ -222,16 +219,20 @@ export const DevToolPanel = observer(() => {
222
219
  download grammar without dependency
223
220
  </div>
224
221
  </div>
225
- <div className="developer-tools__action-group">
222
+ <div
223
+ className="developer-tools__action-group"
224
+ onClick={() => {
225
+ downloadProjectGrammar(true).catch(
226
+ editorStore.applicationStore.alertUnhandledError,
227
+ );
228
+ }}
229
+ role="button"
230
+ tabIndex={-1}
231
+ title="Download Project Grammar with Dependency"
232
+ >
226
233
  <button
227
234
  className="developer-tools__action-group__btn"
228
- onClick={() => {
229
- downloadProjectGrammar(true).catch(
230
- editorStore.applicationStore.alertUnhandledError,
231
- );
232
- }}
233
235
  tabIndex={-1}
234
- title="Download Project Grammar with Dependency"
235
236
  >
236
237
  <CloudDownloadIcon />
237
238
  </button>
@@ -190,6 +190,7 @@ export class Core_LegendStudioApplicationPlugin extends LegendStudioApplicationP
190
190
  LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.EMBEDDED_DATA_MODEL_STORE_EDITOR,
191
191
  LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.INGEST_DEFINITION_EDITOR,
192
192
  LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.DATA_PRODUCT_EDITOR,
193
+ LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.AVAILABILITY_EDITOR,
193
194
  ];
194
195
  }
195
196
 
@@ -95,6 +95,7 @@ import {
95
95
  DataProduct,
96
96
  IngestDefinition,
97
97
  MemSQLFunction,
98
+ Availability,
98
99
  } from '@finos/legend-graph';
99
100
  import { CONFIGURATION_EDITOR_TAB } from './editor-state/project-configuration-editor-state/ProjectConfigurationEditorState.js';
100
101
  import { PACKAGEABLE_ELEMENT_TYPE } from './utils/ModelClassifierUtils.js';
@@ -881,6 +882,8 @@ export class EditorGraphState {
881
882
  return PACKAGEABLE_ELEMENT_TYPE._COMPUTE;
882
883
  } else if (element instanceof IngestDefinition) {
883
884
  return PACKAGEABLE_ELEMENT_TYPE.INGEST_DEFINITION;
885
+ } else if (element instanceof Availability) {
886
+ return PACKAGEABLE_ELEMENT_TYPE.AVAILABILITY;
884
887
  } else if (element instanceof MemSQLFunction) {
885
888
  return PACKAGEABLE_ELEMENT_TYPE.MEM_SQL_FUNCTION;
886
889
  }
@@ -39,6 +39,7 @@ import {
39
39
  DataProduct,
40
40
  IngestDefinition,
41
41
  MemSQLFunction,
42
+ Availability,
42
43
  } from '@finos/legend-graph';
43
44
  import {
44
45
  type Clazz,
@@ -73,6 +74,7 @@ import { MemSQLFunctionActivatorEditorState } from './editor-state/element-edito
73
74
  import { ArtifactGenerationViewerState } from './editor-state/ArtifactGenerationViewerState.js';
74
75
  import { DataProductEditorState } from './editor-state/element-editor-state/dataProduct/DataProductEditorState.js';
75
76
  import { IngestDefinitionEditorState } from './editor-state/element-editor-state/ingest/IngestDefinitionEditorState.js';
77
+ import { AvailabilityEditorState } from './editor-state/element-editor-state/availability/AvailabilityEditorState.js';
76
78
  import type { EditorInitialConfiguration } from './editor-state/element-editor-state/ElementEditorInitialConfiguration.js';
77
79
 
78
80
  export class EditorTabManagerState extends TabManagerState {
@@ -186,6 +188,8 @@ export class EditorTabManagerState extends TabManagerState {
186
188
  return new ServiceEditorState(this.editorStore, element);
187
189
  } else if (element instanceof DataProduct) {
188
190
  return new DataProductEditorState(this.editorStore, element, config);
191
+ } else if (element instanceof Availability) {
192
+ return new AvailabilityEditorState(this.editorStore, element);
189
193
  } else if (element instanceof GenerationSpecification) {
190
194
  return new GenerationSpecificationEditorState(this.editorStore, element);
191
195
  } else if (element instanceof FileGenerationSpecification) {
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Copyright (c) 2026-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 PackageableElement, Availability } from '@finos/legend-graph';
18
+ import { guaranteeType } from '@finos/legend-shared';
19
+ import { action, makeObservable, observable } from 'mobx';
20
+ import type { EditorStore } from '../../../EditorStore.js';
21
+ import { ElementEditorState } from '../ElementEditorState.js';
22
+ import { AvailabilityTestableState } from './testable/AvailabilityTestableState.js';
23
+
24
+ export enum AVAILABILITY_TAB {
25
+ DEFINITION = 'Definition',
26
+ TESTING = 'Testing',
27
+ }
28
+
29
+ export class AvailabilityEditorState extends ElementEditorState {
30
+ activeTab = AVAILABILITY_TAB.DEFINITION;
31
+ readonly testableState = new AvailabilityTestableState(this);
32
+
33
+ constructor(editorStore: EditorStore, element: PackageableElement) {
34
+ super(editorStore, element);
35
+
36
+ makeObservable(this, {
37
+ activeTab: observable,
38
+ setActiveTab: action,
39
+ });
40
+ }
41
+
42
+ get availability(): Availability {
43
+ return guaranteeType(this.element, Availability);
44
+ }
45
+
46
+ setActiveTab(tab: AVAILABILITY_TAB): void {
47
+ this.activeTab = tab;
48
+ }
49
+
50
+ override reprocess(
51
+ newElement: PackageableElement,
52
+ editorStore: EditorStore,
53
+ ): ElementEditorState {
54
+ return new AvailabilityEditorState(editorStore, newElement);
55
+ }
56
+ }