@finos/legend-application-studio 28.21.42 → 28.21.44

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 (164) hide show
  1. package/lib/__lib__/LegendStudioEvent.d.ts +18 -4
  2. package/lib/__lib__/LegendStudioEvent.d.ts.map +1 -1
  3. package/lib/__lib__/LegendStudioEvent.js +20 -5
  4. package/lib/__lib__/LegendStudioEvent.js.map +1 -1
  5. package/lib/__lib__/LegendStudioTelemetryHelper.d.ts +177 -31
  6. package/lib/__lib__/LegendStudioTelemetryHelper.d.ts.map +1 -1
  7. package/lib/__lib__/LegendStudioTelemetryHelper.js +229 -72
  8. package/lib/__lib__/LegendStudioTelemetryHelper.js.map +1 -1
  9. package/lib/__lib__/LegendStudioUserDataHelper.d.ts +18 -1
  10. package/lib/__lib__/LegendStudioUserDataHelper.d.ts.map +1 -1
  11. package/lib/__lib__/LegendStudioUserDataHelper.js +71 -0
  12. package/lib/__lib__/LegendStudioUserDataHelper.js.map +1 -1
  13. package/lib/application/LegendStudioApplicationConfig.d.ts +12 -0
  14. package/lib/application/LegendStudioApplicationConfig.d.ts.map +1 -1
  15. package/lib/application/LegendStudioApplicationConfig.js +6 -0
  16. package/lib/application/LegendStudioApplicationConfig.js.map +1 -1
  17. package/lib/components/LegendStudioWebApplication.d.ts.map +1 -1
  18. package/lib/components/LegendStudioWebApplication.js +5 -2
  19. package/lib/components/LegendStudioWebApplication.js.map +1 -1
  20. package/lib/components/ShowcaseManager.d.ts.map +1 -1
  21. package/lib/components/ShowcaseManager.js +6 -4
  22. package/lib/components/ShowcaseManager.js.map +1 -1
  23. package/lib/components/editor/ActivityBar.d.ts.map +1 -1
  24. package/lib/components/editor/ActivityBar.js +2 -1
  25. package/lib/components/editor/ActivityBar.js.map +1 -1
  26. package/lib/components/editor/editor-group/GrammarTextEditor.d.ts.map +1 -1
  27. package/lib/components/editor/editor-group/GrammarTextEditor.js +7 -1
  28. package/lib/components/editor/editor-group/GrammarTextEditor.js.map +1 -1
  29. package/lib/components/editor/editor-group/data-editor/RelationElementSampleValuesEditor.d.ts +37 -0
  30. package/lib/components/editor/editor-group/data-editor/RelationElementSampleValuesEditor.d.ts.map +1 -0
  31. package/lib/components/editor/editor-group/data-editor/RelationElementSampleValuesEditor.js +126 -0
  32. package/lib/components/editor/editor-group/data-editor/RelationElementSampleValuesEditor.js.map +1 -0
  33. package/lib/components/editor/editor-group/dataProduct/DataProductEditor.d.ts.map +1 -1
  34. package/lib/components/editor/editor-group/dataProduct/DataProductEditor.js +22 -127
  35. package/lib/components/editor/editor-group/dataProduct/DataProductEditor.js.map +1 -1
  36. package/lib/components/editor/editor-group/service-editor/ServiceEditor.d.ts.map +1 -1
  37. package/lib/components/editor/editor-group/service-editor/ServiceEditor.js +4 -4
  38. package/lib/components/editor/editor-group/service-editor/ServiceEditor.js.map +1 -1
  39. package/lib/components/showcase/ShowcaseFeedback.d.ts +36 -0
  40. package/lib/components/showcase/ShowcaseFeedback.d.ts.map +1 -0
  41. package/lib/components/showcase/ShowcaseFeedback.js +70 -0
  42. package/lib/components/showcase/ShowcaseFeedback.js.map +1 -0
  43. package/lib/components/showcase/ShowcaseViewer.d.ts.map +1 -1
  44. package/lib/components/showcase/ShowcaseViewer.js +3 -1
  45. package/lib/components/showcase/ShowcaseViewer.js.map +1 -1
  46. package/lib/components/workspace-setup/WorkspaceSetup.d.ts.map +1 -1
  47. package/lib/components/workspace-setup/WorkspaceSetup.js +2 -1
  48. package/lib/components/workspace-setup/WorkspaceSetup.js.map +1 -1
  49. package/lib/index.css +2 -2
  50. package/lib/index.css.map +1 -1
  51. package/lib/index.d.ts +2 -1
  52. package/lib/index.d.ts.map +1 -1
  53. package/lib/index.js +2 -1
  54. package/lib/index.js.map +1 -1
  55. package/lib/package.json +1 -1
  56. package/lib/stores/LegendStudioBaseStore.d.ts.map +1 -1
  57. package/lib/stores/LegendStudioBaseStore.js +1 -0
  58. package/lib/stores/LegendStudioBaseStore.js.map +1 -1
  59. package/lib/stores/ShowcaseManagerState.d.ts +5 -3
  60. package/lib/stores/ShowcaseManagerState.d.ts.map +1 -1
  61. package/lib/stores/ShowcaseManagerState.js +44 -11
  62. package/lib/stores/ShowcaseManagerState.js.map +1 -1
  63. package/lib/stores/editor/EditorGraphState.d.ts.map +1 -1
  64. package/lib/stores/editor/EditorGraphState.js +1 -1
  65. package/lib/stores/editor/EditorGraphState.js.map +1 -1
  66. package/lib/stores/editor/EditorStore.d.ts +2 -1
  67. package/lib/stores/editor/EditorStore.d.ts.map +1 -1
  68. package/lib/stores/editor/EditorStore.js +8 -2
  69. package/lib/stores/editor/EditorStore.js.map +1 -1
  70. package/lib/stores/editor/GraphEditFormModeState.d.ts.map +1 -1
  71. package/lib/stores/editor/GraphEditFormModeState.js +2 -2
  72. package/lib/stores/editor/GraphEditFormModeState.js.map +1 -1
  73. package/lib/stores/editor/GraphEditGrammarModeState.d.ts +19 -0
  74. package/lib/stores/editor/GraphEditGrammarModeState.d.ts.map +1 -1
  75. package/lib/stores/editor/GraphEditGrammarModeState.js +92 -4
  76. package/lib/stores/editor/GraphEditGrammarModeState.js.map +1 -1
  77. package/lib/stores/editor/GraphEditorMode.d.ts +1 -0
  78. package/lib/stores/editor/GraphEditorMode.d.ts.map +1 -1
  79. package/lib/stores/editor/GraphEditorMode.js.map +1 -1
  80. package/lib/stores/editor/StandardEditorMode.d.ts +16 -5
  81. package/lib/stores/editor/StandardEditorMode.d.ts.map +1 -1
  82. package/lib/stores/editor/StandardEditorMode.js +4 -2
  83. package/lib/stores/editor/StandardEditorMode.js.map +1 -1
  84. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.d.ts +2 -14
  85. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.d.ts.map +1 -1
  86. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js +5 -75
  87. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js.map +1 -1
  88. package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.d.ts +0 -11
  89. package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.d.ts.map +1 -1
  90. package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.js +2 -77
  91. package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.js.map +1 -1
  92. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.d.ts.map +1 -1
  93. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.js +4 -4
  94. package/lib/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.js.map +1 -1
  95. package/lib/stores/editor/sidebar-state/LocalChangesState.d.ts +1 -0
  96. package/lib/stores/editor/sidebar-state/LocalChangesState.d.ts.map +1 -1
  97. package/lib/stores/editor/sidebar-state/LocalChangesState.js +27 -0
  98. package/lib/stores/editor/sidebar-state/LocalChangesState.js.map +1 -1
  99. package/lib/stores/editor/sidebar-state/WorkspaceUpdaterState.d.ts.map +1 -1
  100. package/lib/stores/editor/sidebar-state/WorkspaceUpdaterState.js +7 -0
  101. package/lib/stores/editor/sidebar-state/WorkspaceUpdaterState.js.map +1 -1
  102. package/lib/stores/editor/sidebar-state/dev-metadata/DevMetadataState.d.ts.map +1 -1
  103. package/lib/stores/editor/sidebar-state/dev-metadata/DevMetadataState.js +7 -2
  104. package/lib/stores/editor/sidebar-state/dev-metadata/DevMetadataState.js.map +1 -1
  105. package/lib/stores/lazy-text-editor/LazyTextEditorStore.d.ts +1 -0
  106. package/lib/stores/lazy-text-editor/LazyTextEditorStore.d.ts.map +1 -1
  107. package/lib/stores/lazy-text-editor/LazyTextEditorStore.js +3 -0
  108. package/lib/stores/lazy-text-editor/LazyTextEditorStore.js.map +1 -1
  109. package/lib/stores/project-reviewer/ProjectReviewerStore.d.ts.map +1 -1
  110. package/lib/stores/project-reviewer/ProjectReviewerStore.js +2 -0
  111. package/lib/stores/project-reviewer/ProjectReviewerStore.js.map +1 -1
  112. package/lib/stores/project-view/ProjectViewerEditorMode.d.ts +2 -2
  113. package/lib/stores/project-view/ProjectViewerEditorMode.d.ts.map +1 -1
  114. package/lib/stores/project-view/ProjectViewerEditorMode.js +12 -0
  115. package/lib/stores/project-view/ProjectViewerEditorMode.js.map +1 -1
  116. package/lib/stores/project-view/ProjectViewerStore.d.ts.map +1 -1
  117. package/lib/stores/project-view/ProjectViewerStore.js +3 -1
  118. package/lib/stores/project-view/ProjectViewerStore.js.map +1 -1
  119. package/lib/stores/showcase/ShowcaseViewerEditorMode.d.ts.map +1 -1
  120. package/lib/stores/showcase/ShowcaseViewerEditorMode.js.map +1 -1
  121. package/lib/stores/showcase/ShowcaseViewerStore.d.ts.map +1 -1
  122. package/lib/stores/showcase/ShowcaseViewerStore.js +7 -3
  123. package/lib/stores/showcase/ShowcaseViewerStore.js.map +1 -1
  124. package/lib/stores/workspace-setup/WorkspaceSetupStore.d.ts.map +1 -1
  125. package/lib/stores/workspace-setup/WorkspaceSetupStore.js +1 -0
  126. package/lib/stores/workspace-setup/WorkspaceSetupStore.js.map +1 -1
  127. package/package.json +16 -16
  128. package/src/__lib__/LegendStudioEvent.ts +22 -6
  129. package/src/__lib__/LegendStudioTelemetryHelper.ts +425 -104
  130. package/src/__lib__/LegendStudioUserDataHelper.ts +115 -0
  131. package/src/application/LegendStudioApplicationConfig.ts +19 -0
  132. package/src/components/LegendStudioWebApplication.tsx +18 -2
  133. package/src/components/ShowcaseManager.tsx +24 -4
  134. package/src/components/editor/ActivityBar.tsx +5 -1
  135. package/src/components/editor/editor-group/GrammarTextEditor.tsx +18 -1
  136. package/src/components/editor/editor-group/data-editor/RelationElementSampleValuesEditor.tsx +285 -0
  137. package/src/components/editor/editor-group/dataProduct/DataProductEditor.tsx +38 -323
  138. package/src/components/editor/editor-group/service-editor/ServiceEditor.tsx +4 -0
  139. package/src/components/showcase/ShowcaseFeedback.tsx +136 -0
  140. package/src/components/showcase/ShowcaseViewer.tsx +10 -0
  141. package/src/components/workspace-setup/WorkspaceSetup.tsx +6 -1
  142. package/src/index.ts +2 -0
  143. package/src/stores/LegendStudioBaseStore.ts +1 -0
  144. package/src/stores/ShowcaseManagerState.ts +67 -8
  145. package/src/stores/editor/EditorGraphState.ts +1 -0
  146. package/src/stores/editor/EditorStore.ts +26 -4
  147. package/src/stores/editor/GraphEditFormModeState.ts +2 -0
  148. package/src/stores/editor/GraphEditGrammarModeState.ts +139 -1
  149. package/src/stores/editor/GraphEditorMode.ts +1 -0
  150. package/src/stores/editor/StandardEditorMode.ts +21 -7
  151. package/src/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.ts +3 -119
  152. package/src/stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.ts +1 -136
  153. package/src/stores/editor/editor-state/element-editor-state/service/testable/ServiceTestDataState.ts +4 -0
  154. package/src/stores/editor/sidebar-state/LocalChangesState.ts +47 -0
  155. package/src/stores/editor/sidebar-state/WorkspaceUpdaterState.ts +18 -0
  156. package/src/stores/editor/sidebar-state/dev-metadata/DevMetadataState.ts +7 -0
  157. package/src/stores/lazy-text-editor/LazyTextEditorStore.ts +4 -0
  158. package/src/stores/project-reviewer/ProjectReviewerStore.ts +4 -0
  159. package/src/stores/project-view/ProjectViewerEditorMode.ts +17 -4
  160. package/src/stores/project-view/ProjectViewerStore.ts +5 -0
  161. package/src/stores/showcase/ShowcaseViewerEditorMode.ts +4 -5
  162. package/src/stores/showcase/ShowcaseViewerStore.ts +12 -2
  163. package/src/stores/workspace-setup/WorkspaceSetupStore.ts +2 -0
  164. package/tsconfig.json +2 -0
@@ -53,7 +53,6 @@ import {
53
53
  ModalFooter,
54
54
  ModalFooterButton,
55
55
  ModalHeader,
56
- ModalTitle,
57
56
  PanelContent,
58
57
  PanelDnDEntry,
59
58
  PanelEntryDragHandle,
@@ -198,7 +197,7 @@ import {
198
197
  } from '@finos/legend-extension-dsl-data-product';
199
198
  import type { LegendStudioApplicationStore } from '../../../../stores/LegendStudioBaseStore.js';
200
199
  import type { DepotServerClient } from '@finos/legend-server-depot';
201
- import { RelationElementEditor } from '../data-editor/RelationElementsDataEditor.js';
200
+ import { RelationElementSampleValuesEditor } from '../data-editor/RelationElementSampleValuesEditor.js';
202
201
  import type {
203
202
  AccessPointMeta,
204
203
  DataProductDocResponse,
@@ -492,216 +491,6 @@ const AccessPointGenerationViewer = observer(
492
491
  },
493
492
  );
494
493
 
495
- const SampleValuesEditorModal = observer(
496
- (props: {
497
- accessPointState: LakehouseAccessPointState;
498
- isReadOnly: boolean;
499
- }) => {
500
- const { accessPointState, isReadOnly } = props;
501
- const editorStore = accessPointState.state.state.editorStore;
502
- const dataElementPath =
503
- accessPointState.relationElementExistsinDataElementReference();
504
- const closeModal = (): void => {
505
- accessPointState.setShowSampleValuesModal(false);
506
- };
507
-
508
- const handleDeleteSampleValues = (): void => {
509
- editorStore.applicationStore.alertService.setActionAlertInfo({
510
- message: `Are you sure you want to delete sample values for Access Point ${accessPointState.accessPoint.id}?`,
511
- type: ActionAlertType.CAUTION,
512
- actions: [
513
- {
514
- label: 'Confirm',
515
- type: ActionAlertActionType.PROCEED_WITH_CAUTION,
516
- handler: (): void => {
517
- accessPointState.deleteRelationElement();
518
- closeModal();
519
- },
520
- },
521
- {
522
- label: 'Cancel',
523
- type: ActionAlertActionType.PROCEED,
524
- default: true,
525
- },
526
- ],
527
- });
528
- };
529
-
530
- const handleNavigateToDataElement = (): void => {
531
- if (dataElementPath) {
532
- const dataElement =
533
- editorStore.graphManagerState.graph.getNullableElement(
534
- dataElementPath,
535
- );
536
- if (dataElement) {
537
- editorStore.graphEditorMode.openElement(dataElement);
538
- closeModal();
539
- }
540
- }
541
- };
542
-
543
- return (
544
- <Dialog
545
- open={accessPointState.showSampleValuesModal}
546
- onClose={closeModal}
547
- classes={{
548
- root: 'editor-modal__root-container',
549
- container: 'editor-modal__container',
550
- paper: 'editor-modal__content',
551
- }}
552
- >
553
- <Modal
554
- className="editor-modal"
555
- darkMode={
556
- !editorStore.applicationStore.layoutService
557
- .TEMPORARY__isLightColorThemeEnabled
558
- }
559
- >
560
- <ModalHeader
561
- title={`${accessPointState.accessPoint.title ?? accessPointState.accessPoint.id} Sample Values`}
562
- />
563
- <ModalBody>
564
- <div
565
- style={{
566
- padding: 0,
567
- height: '100%',
568
- flex: 1,
569
- overflowY: 'auto',
570
- overflowX: 'hidden',
571
- }}
572
- >
573
- {dataElementPath !== undefined ? (
574
- <div
575
- style={{
576
- padding: '1.5rem',
577
- display: 'flex',
578
- alignItems: 'center',
579
- justifyContent: 'center',
580
- gap: '1rem',
581
- }}
582
- >
583
- <span
584
- style={{
585
- color: 'var(--color-light-grey-200)',
586
- whiteSpace: 'nowrap',
587
- fontSize: '1.3rem',
588
- fontWeight: 600,
589
- }}
590
- >
591
- Sample Values already in Data Element
592
- </span>
593
- <div
594
- style={{
595
- display: 'flex',
596
- alignItems: 'center',
597
- gap: '0.5rem',
598
- padding: '0.5rem 1rem',
599
- background: 'var(--color-dark-grey-100)',
600
- border: '1px solid var(--color-dark-grey-300)',
601
- borderRadius: '0.2rem',
602
- }}
603
- >
604
- <span
605
- style={{
606
- fontSize: '1.3rem',
607
- fontWeight: 600,
608
- color: 'var(--color-light-grey-200)',
609
- }}
610
- >
611
- {dataElementPath}
612
- </span>
613
- <button
614
- className="btn--sm btn--dark"
615
- onClick={handleNavigateToDataElement}
616
- tabIndex={-1}
617
- title="Navigate to data element"
618
- style={{
619
- padding: '0.3rem 0.5rem',
620
- display: 'flex',
621
- alignItems: 'center',
622
- }}
623
- >
624
- <LongArrowRightIcon />
625
- </button>
626
- </div>
627
- </div>
628
- ) : (
629
- <>
630
- <div
631
- style={{
632
- color: 'var(--color-orange-200)',
633
- fontWeight: 'bold',
634
- fontSize: '14px',
635
- padding: '0.5rem',
636
- marginBottom: '1rem',
637
- textAlign: 'center',
638
- backgroundColor: 'var(--color-orange-50)',
639
- border: '2px solid var(--color-orange-200)',
640
- borderRadius: '4px',
641
- }}
642
- >
643
- DO NOT ADD SENSITIVE DATA
644
- </div>
645
- {accessPointState.relationElementState && (
646
- <Tooltip
647
- title={
648
- accessPointState.getRelationElementMismatchMessage() ??
649
- ''
650
- }
651
- arrow={true}
652
- placement="top"
653
- disableHoverListener={
654
- !accessPointState.hasRelationElementMismatch
655
- }
656
- >
657
- <div
658
- style={{
659
- border: accessPointState.hasRelationElementMismatch
660
- ? '2px solid var(--color-red-300)'
661
- : 'none',
662
- borderRadius: '4px',
663
- padding: accessPointState.hasRelationElementMismatch
664
- ? '0.5rem'
665
- : '0',
666
- }}
667
- >
668
- <RelationElementEditor
669
- relationElementState={
670
- accessPointState.relationElementState
671
- }
672
- isReadOnly={isReadOnly}
673
- hideColumnDefinitions={true}
674
- />
675
- </div>
676
- </Tooltip>
677
- )}
678
- </>
679
- )}
680
- </div>
681
- </ModalBody>
682
- <ModalFooter>
683
- {dataElementPath === undefined && (
684
- <ModalFooterButton
685
- title="Delete sample values"
686
- onClick={handleDeleteSampleValues}
687
- text="Delete"
688
- type="secondary"
689
- disabled={isReadOnly}
690
- />
691
- )}
692
- <ModalFooterButton
693
- title="Close sample values editor"
694
- onClick={closeModal}
695
- text="Close"
696
- type="secondary"
697
- />
698
- </ModalFooter>
699
- </Modal>
700
- </Dialog>
701
- );
702
- },
703
- );
704
-
705
494
  export const LakehouseDataProductAccessPointEditor = observer(
706
495
  (props: {
707
496
  accessPointState: LakehouseAccessPointState;
@@ -971,58 +760,39 @@ export const LakehouseDataProductAccessPointEditor = observer(
971
760
  <div>Reproducible</div>
972
761
  </Tooltip>
973
762
  </div>
974
- {accessPointState.relationElementExistsinDataElementReference() !==
975
- undefined ? (
976
- <button
977
- className="access-point-editor__sample-values-btn"
978
- onClick={() =>
979
- accessPointState.setShowSampleValuesModal(true)
980
- }
981
- disabled={props.isReadOnly}
982
- title="Edit sample values"
983
- style={{
984
- cursor: props.isReadOnly ? 'not-allowed' : 'pointer',
985
- }}
986
- >
987
- <PencilEditIcon />
988
- <span>Sample Values</span>
989
- </button>
990
- ) : accessPointState.relationElementState !== undefined ? (
991
- <button
992
- className="access-point-editor__sample-values-btn"
993
- onClick={() =>
994
- accessPointState.setShowSampleValuesModal(true)
995
- }
996
- disabled={props.isReadOnly}
997
- title="Edit sample values"
998
- style={{
999
- border: accessPointState.hasRelationElementMismatch
1000
- ? '2px solid var(--color-red-300)'
1001
- : '1px solid var(--color-blue-200)',
1002
- cursor: props.isReadOnly ? 'not-allowed' : 'pointer',
1003
- }}
1004
- >
1005
- <PencilEditIcon />
1006
- <span>Sample Values</span>
1007
- </button>
1008
- ) : (
1009
- <button
1010
- className="access-point-editor__sample-values-btn"
1011
- onClick={() => {
1012
- flowResult(
1013
- accessPointState.createAndaddRelationElement(),
1014
- ).catch(editorStore.applicationStore.alertUnhandledError);
1015
- }}
1016
- disabled={props.isReadOnly}
1017
- title="Add sample values"
1018
- style={{
1019
- cursor: props.isReadOnly ? 'not-allowed' : 'pointer',
1020
- }}
1021
- >
1022
- <PlusIcon />
1023
- <span>Sample Values</span>
1024
- </button>
1025
- )}
763
+ <RelationElementSampleValuesEditor
764
+ title={`${accessPointState.accessPoint.title ?? accessPointState.accessPoint.id} Sample Values`}
765
+ relationElementState={accessPointState.relationElementState}
766
+ isReadOnly={props.isReadOnly}
767
+ hideColumnDefinitions={true}
768
+ hasMismatch={accessPointState.hasRelationElementMismatch}
769
+ mismatchMessage={accessPointState.getRelationElementMismatchMessage()}
770
+ readOnlySource={(() => {
771
+ const dataElementPath =
772
+ accessPointState.relationElementExistsinDataElementReference();
773
+ return dataElementPath !== undefined
774
+ ? {
775
+ label: dataElementPath,
776
+ onNavigate: () => {
777
+ const dataElement =
778
+ editorStore.graphManagerState.graph.getNullableElement(
779
+ dataElementPath,
780
+ );
781
+ if (dataElement) {
782
+ editorStore.graphEditorMode.openElement(
783
+ dataElement,
784
+ );
785
+ }
786
+ },
787
+ }
788
+ : undefined;
789
+ })()}
790
+ deleteConfirmMessage={`Are you sure you want to delete sample values for Access Point ${accessPointState.accessPoint.id}?`}
791
+ onAdd={() =>
792
+ flowResult(accessPointState.createAndaddRelationElement())
793
+ }
794
+ onDelete={() => accessPointState.deleteRelationElement()}
795
+ />
1026
796
  {editorStore.applicationStore.config.options
1027
797
  .dataProductConfig && (
1028
798
  <AccessPointClassification
@@ -1277,68 +1047,12 @@ export const LakehouseDataProductAccessPointEditor = observer(
1277
1047
  generationOutput={accessPointState.artifactGenerationContent}
1278
1048
  />
1279
1049
  )}
1280
- {accessPointState.showSampleValuesModal && (
1281
- <SampleValuesEditorModal
1282
- accessPointState={accessPointState}
1283
- isReadOnly={props.isReadOnly}
1284
- />
1285
- )}
1286
1050
  </div>
1287
1051
  </PanelDnDEntry>
1288
1052
  );
1289
1053
  },
1290
1054
  );
1291
1055
 
1292
- const DataProductDeploymentResponseModal = observer(
1293
- (props: { state: DataProductEditorState }) => {
1294
- const { state } = props;
1295
- const applicationStore = state.editorStore.applicationStore;
1296
- const closeModal = (): void => state.setDeployResponse(undefined);
1297
- return (
1298
- <Dialog
1299
- open={Boolean(state.deployResponse)}
1300
- classes={{
1301
- root: 'editor-modal__root-container',
1302
- container: 'editor-modal__container',
1303
- paper: 'editor-modal__content',
1304
- }}
1305
- onClose={closeModal}
1306
- >
1307
- <Modal
1308
- darkMode={
1309
- !applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled
1310
- }
1311
- className="editor-modal"
1312
- >
1313
- <ModalHeader>
1314
- <ModalTitle title="Data Product Deployment Response" />
1315
- </ModalHeader>
1316
- <ModalBody>
1317
- <PanelContent>
1318
- <CodeEditor
1319
- inputValue={JSON.stringify(
1320
- state.deployResponse?.content ?? {},
1321
- null,
1322
- 2,
1323
- )}
1324
- isReadOnly={true}
1325
- language={CODE_EDITOR_LANGUAGE.JSON}
1326
- />
1327
- </PanelContent>
1328
- </ModalBody>
1329
- <ModalFooter>
1330
- <ModalFooterButton
1331
- onClick={closeModal}
1332
- text="Close"
1333
- type="secondary"
1334
- />
1335
- </ModalFooter>
1336
- </Modal>
1337
- </Dialog>
1338
- );
1339
- },
1340
- );
1341
-
1342
1056
  const AccessPointGroupPublicToggle = observer(
1343
1057
  (props: { groupState: AccessPointGroupState }) => {
1344
1058
  const { groupState } = props;
@@ -1580,6 +1294,7 @@ const AccessPointGroupEditor = observer(
1580
1294
  LegendStudioTelemetryHelper.logEvent_DataProductLegendAISuggestLaunched(
1581
1295
  editorStore.applicationStore.telemetryService,
1582
1296
  productEditorState.product.path,
1297
+ editorStore.editorMode.getSourceInfo(),
1583
1298
  );
1584
1299
  setIsSuggestingWithAI(true);
1585
1300
  setAISuggestion(undefined);
@@ -1602,6 +1317,7 @@ const AccessPointGroupEditor = observer(
1602
1317
  editorStore.applicationStore.telemetryService,
1603
1318
  productEditorState.product.path,
1604
1319
  error.message,
1320
+ editorStore.editorMode.getSourceInfo(),
1605
1321
  );
1606
1322
  if (
1607
1323
  error instanceof NetworkClientError &&
@@ -1630,6 +1346,7 @@ const AccessPointGroupEditor = observer(
1630
1346
  LegendStudioTelemetryHelper.logEvent_DataProductLegendAISuggestApplied(
1631
1347
  editorStore.applicationStore.telemetryService,
1632
1348
  productEditorState.product.path,
1349
+ editorStore.editorMode.getSourceInfo(),
1633
1350
  );
1634
1351
  // Find matching group in the response
1635
1352
  const gIdx =
@@ -1672,6 +1389,7 @@ const AccessPointGroupEditor = observer(
1672
1389
  LegendStudioTelemetryHelper.logEvent_DataProductLegendAISuggestDiscarded(
1673
1390
  editorStore.applicationStore.telemetryService,
1674
1391
  productEditorState.product.path,
1392
+ editorStore.editorMode.getSourceInfo(),
1675
1393
  );
1676
1394
  setAISuggestion(undefined);
1677
1395
  };
@@ -2198,9 +1916,6 @@ const AccessPointGroupTab = observer(
2198
1916
  />
2199
1917
  )}
2200
1918
  </PanelContent>
2201
- {dataProductEditorState.deployResponse && (
2202
- <DataProductDeploymentResponseModal state={dataProductEditorState} />
2203
- )}
2204
1919
  </div>
2205
1920
  );
2206
1921
  },
@@ -274,6 +274,7 @@ const ServiceGeneralEditor = observer(() => {
274
274
  LegendStudioTelemetryHelper.logEvent_ServiceLegendAISuggestLaunched(
275
275
  applicationStore.telemetryService,
276
276
  service.path,
277
+ editorStore.editorMode.getSourceInfo(),
277
278
  );
278
279
  setIsSuggestingWithAI(true);
279
280
  setAIDocSuggestion(undefined);
@@ -290,6 +291,7 @@ const ServiceGeneralEditor = observer(() => {
290
291
  applicationStore.telemetryService,
291
292
  service.path,
292
293
  error.message,
294
+ editorStore.editorMode.getSourceInfo(),
293
295
  );
294
296
  if (
295
297
  error instanceof NetworkClientError &&
@@ -315,6 +317,7 @@ const ServiceGeneralEditor = observer(() => {
315
317
  LegendStudioTelemetryHelper.logEvent_ServiceLegendAISuggestApplied(
316
318
  applicationStore.telemetryService,
317
319
  service.path,
320
+ editorStore.editorMode.getSourceInfo(),
318
321
  );
319
322
  service_setDocumentation(service, aiDocSuggestion);
320
323
  setAIDocSuggestion(undefined);
@@ -323,6 +326,7 @@ const ServiceGeneralEditor = observer(() => {
323
326
  LegendStudioTelemetryHelper.logEvent_ServiceLegendAISuggestDiscarded(
324
327
  applicationStore.telemetryService,
325
328
  service.path,
329
+ editorStore.editorMode.getSourceInfo(),
326
330
  );
327
331
  setAIDocSuggestion(undefined);
328
332
  };
@@ -0,0 +1,136 @@
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 { useEffect, useRef, useState } from 'react';
18
+ import { clsx, ThumbsUpIcon, ThumbsDownIcon } from '@finos/legend-art';
19
+ import { useApplicationStore } from '@finos/legend-application';
20
+ import { LegendStudioUserDataHelper } from '../../__lib__/LegendStudioUserDataHelper.js';
21
+ import {
22
+ LegendStudioTelemetryHelper,
23
+ SHOWCASE_FEEDBACK_VOTE,
24
+ type SHOWCASE_FEEDBACK_SURFACE,
25
+ } from '../../__lib__/LegendStudioTelemetryHelper.js';
26
+
27
+ const THANKS_DISPLAY_DURATION_MS = 2500;
28
+
29
+ /**
30
+ * "Was this showcase helpful?" widget.
31
+ *
32
+ * v1 storage strategy: telemetry is the source of truth for aggregate
33
+ * analysis (`showcase.viewer.feedback.submit`). The user's vote per
34
+ * showcase is cached in browser `UserDataService` (localStorage) purely
35
+ * so we can suppress re-prompting on revisit — there is no backend today.
36
+ *
37
+ * UX: once a user votes, the buttons are replaced with a brief
38
+ * "Thanks for the feedback!" message and then the whole widget unmounts.
39
+ * On subsequent visits to the same showcase, the widget renders nothing.
40
+ */
41
+ export const ShowcaseFeedback = (props: {
42
+ showcasePath: string;
43
+ title?: string | undefined;
44
+ surface: SHOWCASE_FEEDBACK_SURFACE;
45
+ /** Optional CSS class hook so the two mount points can size / align. */
46
+ className?: string | undefined;
47
+ }) => {
48
+ const { showcasePath, title, surface, className } = props;
49
+ const applicationStore = useApplicationStore();
50
+ const alreadyVoted = Boolean(
51
+ LegendStudioUserDataHelper.showcaseFeedback_getVote(
52
+ applicationStore.userDataService,
53
+ showcasePath,
54
+ ),
55
+ );
56
+ const [phase, setPhase] = useState<'prompt' | 'thanks' | 'done'>(
57
+ alreadyVoted ? 'done' : 'prompt',
58
+ );
59
+ const timeoutRef = useRef<ReturnType<typeof setTimeout> | undefined>(
60
+ undefined,
61
+ );
62
+
63
+ useEffect(
64
+ () => (): void => {
65
+ if (timeoutRef.current !== undefined) {
66
+ clearTimeout(timeoutRef.current);
67
+ }
68
+ },
69
+ [],
70
+ );
71
+
72
+ const submit = (vote: SHOWCASE_FEEDBACK_VOTE): void => {
73
+ LegendStudioUserDataHelper.showcaseFeedback_recordVote(
74
+ applicationStore.userDataService,
75
+ {
76
+ showcasePath,
77
+ vote: vote === SHOWCASE_FEEDBACK_VOTE.UP ? 'up' : 'down',
78
+ },
79
+ );
80
+ LegendStudioTelemetryHelper.logEvent_ShowcaseFeedbackSubmit(
81
+ applicationStore.telemetryService,
82
+ {
83
+ showcasePath,
84
+ title,
85
+ vote,
86
+ surface,
87
+ },
88
+ );
89
+ setPhase('thanks');
90
+ timeoutRef.current = setTimeout(() => {
91
+ setPhase('done');
92
+ }, THANKS_DISPLAY_DURATION_MS);
93
+ };
94
+
95
+ if (phase === 'done') {
96
+ return null;
97
+ }
98
+
99
+ if (phase === 'thanks') {
100
+ return (
101
+ <div
102
+ className={clsx('showcase-feedback', className)}
103
+ role="status"
104
+ aria-live="polite"
105
+ >
106
+ <div className="showcase-feedback__prompt">
107
+ Thanks for the feedback!
108
+ </div>
109
+ </div>
110
+ );
111
+ }
112
+
113
+ return (
114
+ <div className={clsx('showcase-feedback', className)}>
115
+ <div className="showcase-feedback__prompt">Was this helpful?</div>
116
+ <button
117
+ type="button"
118
+ className="showcase-feedback__btn"
119
+ tabIndex={-1}
120
+ title="Thumbs up"
121
+ onClick={() => submit(SHOWCASE_FEEDBACK_VOTE.UP)}
122
+ >
123
+ <ThumbsUpIcon />
124
+ </button>
125
+ <button
126
+ type="button"
127
+ className="showcase-feedback__btn"
128
+ tabIndex={-1}
129
+ title="Thumbs down"
130
+ onClick={() => submit(SHOWCASE_FEEDBACK_VOTE.DOWN)}
131
+ >
132
+ <ThumbsDownIcon />
133
+ </button>
134
+ </div>
135
+ );
136
+ };
@@ -62,6 +62,8 @@ import { LEGEND_STUDIO_TEST_ID } from '../../__lib__/LegendStudioTesting.js';
62
62
  import { Explorer } from '../editor/side-bar/Explorer.js';
63
63
  import { PanelGroup } from '../editor/panel-group/PanelGroup.js';
64
64
  import { QueryDataCubeViewer } from '@finos/legend-query-builder';
65
+ import { ShowcaseFeedback } from './ShowcaseFeedback.js';
66
+ import { SHOWCASE_FEEDBACK_SURFACE } from '../../__lib__/LegendStudioTelemetryHelper.js';
65
67
 
66
68
  const ShowcaseViewerStatusBar = observer(() => {
67
69
  const editorStore = useEditorStore();
@@ -109,6 +111,14 @@ const ShowcaseViewerStatusBar = observer(() => {
109
111
  </div>
110
112
  </div>
111
113
  )}
114
+ {showcase && (
115
+ <ShowcaseFeedback
116
+ className="showcase-feedback--status-bar"
117
+ showcasePath={showcaseStore.showcase.path}
118
+ title={showcase.title}
119
+ surface={SHOWCASE_FEEDBACK_SURFACE.DEEP_LINK_VIEWER}
120
+ />
121
+ )}
112
122
  </div>
113
123
  <div className="editor__status-bar__right">
114
124
  <button
@@ -80,6 +80,7 @@ import {
80
80
  import { Project } from '@finos/legend-server-sdlc';
81
81
  import { WorkspaceSetupStore } from '../../stores/workspace-setup/WorkspaceSetupStore.js';
82
82
  import { openShowcaseManager } from '../../stores/ShowcaseManagerState.js';
83
+ import { SHOWCASE_MANAGER_ENTRY_POINT } from '../../__lib__/LegendStudioTelemetryHelper.js';
83
84
 
84
85
  const WorkspaceSetupStoreContext = createContext<
85
86
  WorkspaceSetupStore | undefined
@@ -151,7 +152,11 @@ export const ShowcaseCard: React.FC<{ hideDocumentation?: boolean }> = (
151
152
  <OpenIcon />
152
153
  </div>
153
154
  ),
154
- action: () => openShowcaseManager(applicationStore),
155
+ action: () =>
156
+ openShowcaseManager(
157
+ applicationStore,
158
+ SHOWCASE_MANAGER_ENTRY_POINT.WORKSPACE_SETUP,
159
+ ),
155
160
  },
156
161
  ]}
157
162
  isStable={true}
package/src/index.ts CHANGED
@@ -118,9 +118,11 @@ export {
118
118
  externalFormatData_setContentType,
119
119
  } from './stores/graph-modifier/DSL_Data_GraphModifierHelper.js';
120
120
  export { ExternalFormatDataEditor } from './components/editor/editor-group/data-editor/DataElementEditor.js';
121
+ export { RelationElementSampleValuesEditor } from './components/editor/editor-group/data-editor/RelationElementSampleValuesEditor.js';
121
122
  export {
122
123
  ExternalFormatDataState,
123
124
  EmbeddedDataState,
125
+ RelationElementState,
124
126
  } from './stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.js';
125
127
  export type { EmbeddedDataTypeOption } from './stores/editor/editor-state/element-editor-state/data/DataEditorState.js';
126
128
 
@@ -159,6 +159,7 @@ export class LegendStudioBaseStore {
159
159
  serverUrl: this.applicationStore.config.sdlcServerUrl,
160
160
  baseHeaders: this.applicationStore.config.sdlcServerBaseHeaders,
161
161
  client: this.applicationStore.config.sdlcServerClient,
162
+ useCookieAuthOnly: this.applicationStore.config.sdlcUseCookieAuthOnly,
162
163
  // On a mid-session 401, auto-launch the popup re-auth flow. The
163
164
  // handler enforces a one-attempt-per-episode guard to prevent endless
164
165
  // retry loops; when it gives up, the StatusBar manual button remains