@finos/legend-extension-dsl-data-space 10.4.258 → 10.4.260

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 (49) hide show
  1. package/lib/components/DataSpaceDescription.d.ts +5 -0
  2. package/lib/components/DataSpaceDescription.d.ts.map +1 -1
  3. package/lib/components/DataSpaceDescription.js +39 -0
  4. package/lib/components/DataSpaceDescription.js.map +1 -1
  5. package/lib/components/DataSpaceExecutionContextViewer.d.ts +1 -6
  6. package/lib/components/DataSpaceExecutionContextViewer.d.ts.map +1 -1
  7. package/lib/components/DataSpaceExecutionContextViewer.js +12 -16
  8. package/lib/components/DataSpaceExecutionContextViewer.js.map +1 -1
  9. package/lib/components/DataSpaceLakehouseAccess.d.ts +22 -0
  10. package/lib/components/DataSpaceLakehouseAccess.d.ts.map +1 -0
  11. package/lib/components/DataSpaceLakehouseAccess.js +127 -0
  12. package/lib/components/DataSpaceLakehouseAccess.js.map +1 -0
  13. package/lib/components/DataSpaceQuickStart.d.ts.map +1 -1
  14. package/lib/components/DataSpaceQuickStart.js +3 -2
  15. package/lib/components/DataSpaceQuickStart.js.map +1 -1
  16. package/lib/components/DataSpaceViewer.d.ts.map +1 -1
  17. package/lib/components/DataSpaceViewer.js +7 -13
  18. package/lib/components/DataSpaceViewer.js.map +1 -1
  19. package/lib/components/DataSpaceWiki.d.ts.map +1 -1
  20. package/lib/components/DataSpaceWiki.js +3 -2
  21. package/lib/components/DataSpaceWiki.js.map +1 -1
  22. package/lib/graph-manager/protocol/pure/v1/V1_DSL_DataSpace_PureGraphManagerExtension.js +2 -2
  23. package/lib/graph-manager/protocol/pure/v1/V1_DSL_DataSpace_PureGraphManagerExtension.js.map +1 -1
  24. package/lib/index.css +2 -2
  25. package/lib/index.css.map +1 -1
  26. package/lib/package.json +1 -1
  27. package/lib/stores/DataSpaceLayoutState.d.ts.map +1 -1
  28. package/lib/stores/DataSpaceLayoutState.js +3 -3
  29. package/lib/stores/DataSpaceLayoutState.js.map +1 -1
  30. package/lib/stores/DataSpaceViewerNavigation.d.ts +1 -0
  31. package/lib/stores/DataSpaceViewerNavigation.d.ts.map +1 -1
  32. package/lib/stores/DataSpaceViewerNavigation.js +1 -0
  33. package/lib/stores/DataSpaceViewerNavigation.js.map +1 -1
  34. package/lib/stores/DataSpaceViewerState.d.ts +3 -0
  35. package/lib/stores/DataSpaceViewerState.d.ts.map +1 -1
  36. package/lib/stores/DataSpaceViewerState.js +28 -2
  37. package/lib/stores/DataSpaceViewerState.js.map +1 -1
  38. package/package.json +8 -8
  39. package/src/components/DataSpaceDescription.tsx +86 -0
  40. package/src/components/DataSpaceExecutionContextViewer.tsx +41 -44
  41. package/src/components/DataSpaceLakehouseAccess.tsx +449 -0
  42. package/src/components/DataSpaceQuickStart.tsx +22 -11
  43. package/src/components/DataSpaceViewer.tsx +2 -55
  44. package/src/components/DataSpaceWiki.tsx +7 -1
  45. package/src/graph-manager/protocol/pure/v1/V1_DSL_DataSpace_PureGraphManagerExtension.ts +2 -2
  46. package/src/stores/DataSpaceLayoutState.ts +5 -6
  47. package/src/stores/DataSpaceViewerNavigation.ts +1 -0
  48. package/src/stores/DataSpaceViewerState.ts +36 -2
  49. package/tsconfig.json +1 -0
@@ -0,0 +1,449 @@
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 { observer } from 'mobx-react-lite';
18
+ import { useEffect, useMemo, useRef, useState } from 'react';
19
+ import {
20
+ Button,
21
+ ButtonGroup,
22
+ IconButton,
23
+ Menu,
24
+ MenuItem,
25
+ Tooltip,
26
+ } from '@mui/material';
27
+ import {
28
+ CaretDownIcon,
29
+ ExpandMoreIcon,
30
+ RefreshIcon,
31
+ clsx,
32
+ } from '@finos/legend-art';
33
+ import {
34
+ extractElementNameFromPath,
35
+ type V1_AccessPointGroup,
36
+ } from '@finos/legend-graph';
37
+ import {
38
+ AccessPointGroupAccess,
39
+ CollapsibleWikiSection,
40
+ DataProductAPGAccessRequestControl,
41
+ EntitlementsDataContractCreator,
42
+ type DataProductAPGState,
43
+ } from '@finos/legend-extension-dsl-data-product';
44
+ import { type DataSpaceViewerState } from '../stores/DataSpaceViewerState.js';
45
+ import type { DataSpaceDataProductAccessState } from '../stores/DataSpaceDataProductAccessState.js';
46
+ import { DataSpaceMarkdownTextViewer } from './DataSpaceMarkdownTextViewer.js';
47
+ import { resolveOpenDataProductAction } from './DataSpaceExecutionContextViewer.js';
48
+ import {
49
+ DATA_SPACE_VIEWER_ACTIVITY_MODE,
50
+ generateAnchorForActivity,
51
+ } from '../stores/DataSpaceViewerNavigation.js';
52
+
53
+ const isEntitled = (access: AccessPointGroupAccess): boolean =>
54
+ access === AccessPointGroupAccess.APPROVED ||
55
+ access === AccessPointGroupAccess.ENTERPRISE;
56
+
57
+ const getBulkRequestTargetApgStates = (
58
+ accessState: DataSpaceDataProductAccessState,
59
+ ): DataProductAPGState[] => {
60
+ const apgStates = accessState.dataProductViewerState?.apgStates ?? [];
61
+ return apgStates.filter((state) => !isEntitled(state.access));
62
+ };
63
+
64
+ const getContractableApgStates = (
65
+ accessState: DataSpaceDataProductAccessState,
66
+ ): DataProductAPGState[] => {
67
+ const apgStates = accessState.dataProductViewerState?.apgStates ?? [];
68
+ return apgStates.filter(
69
+ (state) => state.access !== AccessPointGroupAccess.ENTERPRISE,
70
+ );
71
+ };
72
+
73
+ const DataSpaceLakehouseAccessRequestButton = observer(
74
+ (props: {
75
+ accessState: DataSpaceDataProductAccessState;
76
+ onRequestForSelf: () => void;
77
+ onRequestForOthers: () => void;
78
+ }) => {
79
+ const { accessState, onRequestForSelf, onRequestForOthers } = props;
80
+ const buttonGroupRef = useRef<HTMLDivElement>(null);
81
+ const [isMenuOpen, setIsMenuOpen] = useState<boolean>(false);
82
+ const apgStates = accessState.dataProductViewerState?.apgStates;
83
+ if (!apgStates || apgStates.length === 0) {
84
+ return null;
85
+ }
86
+ const total = apgStates.length;
87
+ const entitled = apgStates.filter((state) =>
88
+ isEntitled(state.access),
89
+ ).length;
90
+ const pending = apgStates.filter(
91
+ (state) =>
92
+ state.access === AccessPointGroupAccess.SUBMITTED_FOR_APPROVALS ||
93
+ state.access === AccessPointGroupAccess.PENDING_MANAGER_APPROVAL ||
94
+ state.access === AccessPointGroupAccess.PENDING_DATA_OWNER_APPROVAL,
95
+ ).length;
96
+ const hasAllAccess = entitled >= total;
97
+ const requestableTargets = getBulkRequestTargetApgStates(accessState);
98
+ const primaryDisabled = hasAllAccess || requestableTargets.length === 0;
99
+ const forOthersTargets = getContractableApgStates(accessState);
100
+ const showForOthers = forOthersTargets.length > 0;
101
+ const primaryTooltip = hasAllAccess
102
+ ? `You have access to all ${total} Access Point Group${total === 1 ? '' : 's'} under this Data Product required to access this DataSpace.`
103
+ : `Request access to the Access Point Groups under this Data Product required to access this DataSpace. ${entitled} of ${total} granted${pending > 0 ? `, ${pending} pending approval` : ''}.`;
104
+ return (
105
+ <>
106
+ <ButtonGroup
107
+ variant="contained"
108
+ color={hasAllAccess ? 'success' : 'primary'}
109
+ ref={buttonGroupRef}
110
+ className="data-space__viewer__lakehouse-access__group__request-btn"
111
+ >
112
+ <Tooltip title={primaryTooltip} arrow={true}>
113
+ <span>
114
+ <Button
115
+ disabled={!hasAllAccess && primaryDisabled}
116
+ onClick={hasAllAccess ? undefined : onRequestForSelf}
117
+ sx={{
118
+ height: '100%',
119
+ cursor: hasAllAccess ? 'default' : undefined,
120
+ borderTopRightRadius: showForOthers ? 0 : undefined,
121
+ borderBottomRightRadius: showForOthers ? 0 : undefined,
122
+ }}
123
+ >
124
+ {hasAllAccess
125
+ ? 'Access Granted'
126
+ : `Request Access (${entitled} / ${total})`}
127
+ </Button>
128
+ </span>
129
+ </Tooltip>
130
+ {showForOthers && (
131
+ <Button
132
+ size="small"
133
+ onClick={() => setIsMenuOpen((prev) => !prev)}
134
+ title="More options"
135
+ >
136
+ <CaretDownIcon />
137
+ </Button>
138
+ )}
139
+ </ButtonGroup>
140
+ {showForOthers && (
141
+ <Menu
142
+ anchorEl={buttonGroupRef.current}
143
+ open={isMenuOpen}
144
+ onClose={() => setIsMenuOpen(false)}
145
+ >
146
+ <MenuItem
147
+ onClick={() => {
148
+ onRequestForOthers();
149
+ setIsMenuOpen(false);
150
+ }}
151
+ >
152
+ Request Access for Others
153
+ </MenuItem>
154
+ </Menu>
155
+ )}
156
+ </>
157
+ );
158
+ },
159
+ );
160
+
161
+ const DataSpaceLakehouseAccessGroup = observer(
162
+ (props: {
163
+ viewerState: DataSpaceViewerState;
164
+ dataProductPath: string;
165
+ initiallyCollapsed: boolean;
166
+ }) => {
167
+ const { viewerState, dataProductPath, initiallyCollapsed } = props;
168
+ const [isCollapsed, setIsCollapsed] = useState<boolean>(initiallyCollapsed);
169
+ const [bulkRequestMode, setBulkRequestMode] = useState<
170
+ 'self' | 'others' | undefined
171
+ >(undefined);
172
+ const accessState = viewerState.getDataProductAccessState(dataProductPath);
173
+ const isReadOnly = accessState === undefined;
174
+ const readOnlyApgIds: string[] = useMemo(() => {
175
+ if (!isReadOnly) {
176
+ return [];
177
+ }
178
+ const dp =
179
+ viewerState.graphManagerState.graph.getOwnNullableDataProduct(
180
+ dataProductPath,
181
+ );
182
+ return dp?.accessPointGroups.map((group) => group.id) ?? [];
183
+ }, [dataProductPath, isReadOnly, viewerState.graphManagerState.graph]);
184
+ const tokenProvider =
185
+ viewerState.mappingProviderAccessConfig?.tokenProvider ??
186
+ ((): undefined => undefined);
187
+ const apgStates = accessState?.dataProductViewerState?.apgStates ?? [];
188
+ const isLoading = accessState?.initializingState.isInProgress ?? false;
189
+ const hasError =
190
+ accessState?.errorMessage !== undefined && apgStates.length === 0;
191
+ const displayedCount = isReadOnly
192
+ ? readOnlyApgIds.length
193
+ : apgStates.length;
194
+
195
+ const bulkTargetApgStates = accessState
196
+ ? bulkRequestMode === 'others'
197
+ ? getContractableApgStates(accessState)
198
+ : getBulkRequestTargetApgStates(accessState)
199
+ : [];
200
+ const bulkTargetApgs: V1_AccessPointGroup[] = bulkTargetApgStates.map(
201
+ (state) => state.apg,
202
+ );
203
+
204
+ const representativeApgState: DataProductAPGState | undefined =
205
+ bulkTargetApgStates[0];
206
+
207
+ const onOpenDataProduct = resolveOpenDataProductAction(
208
+ viewerState,
209
+ dataProductPath,
210
+ );
211
+
212
+ return (
213
+ <div className="data-space__viewer__lakehouse-access__group">
214
+ <div className="data-space__viewer__lakehouse-access__group__header-row">
215
+ <button
216
+ className="data-space__viewer__lakehouse-access__group__caret-btn"
217
+ tabIndex={-1}
218
+ onClick={(): void => setIsCollapsed((prev) => !prev)}
219
+ title={isCollapsed ? 'Expand' : 'Collapse'}
220
+ >
221
+ <ExpandMoreIcon
222
+ className={clsx(
223
+ 'data-space__viewer__lakehouse-access__group__caret',
224
+ {
225
+ 'data-space__viewer__lakehouse-access__group__caret--collapsed':
226
+ isCollapsed,
227
+ },
228
+ )}
229
+ />
230
+ </button>
231
+ <div className="data-space__viewer__lakehouse-access__group__header">
232
+ {onOpenDataProduct ? (
233
+ <button
234
+ type="button"
235
+ className="data-space__viewer__lakehouse-access__group__label data-space__viewer__lakehouse-access__group__label--clickable"
236
+ title={`Open Data Product: ${dataProductPath}`}
237
+ onClick={onOpenDataProduct}
238
+ >
239
+ {extractElementNameFromPath(dataProductPath)}
240
+ </button>
241
+ ) : (
242
+ <span
243
+ className="data-space__viewer__lakehouse-access__group__label"
244
+ title={dataProductPath}
245
+ >
246
+ {extractElementNameFromPath(dataProductPath)}
247
+ </span>
248
+ )}
249
+ <span className="data-space__viewer__lakehouse-access__group__count">
250
+ {displayedCount}
251
+ </span>
252
+ </div>
253
+ {!isReadOnly && (
254
+ <div className="data-space__viewer__lakehouse-access__group__actions">
255
+ {!hasError && (
256
+ <DataSpaceLakehouseAccessRequestButton
257
+ accessState={accessState}
258
+ onRequestForSelf={(): void => setBulkRequestMode('self')}
259
+ onRequestForOthers={(): void => setBulkRequestMode('others')}
260
+ />
261
+ )}
262
+ <IconButton
263
+ className="data-space__viewer__lakehouse-access__group__refresh-btn"
264
+ size="small"
265
+ color="primary"
266
+ title="Refresh Data Product access"
267
+ disabled={accessState.initializingState.isInProgress}
268
+ onClick={(): void =>
269
+ viewerState.refreshDataProductAccessState(dataProductPath)
270
+ }
271
+ >
272
+ <RefreshIcon />
273
+ </IconButton>
274
+ </div>
275
+ )}
276
+ </div>
277
+ {!isCollapsed && (
278
+ <div className="data-space__viewer__lakehouse-access__group__rows">
279
+ {isReadOnly ? (
280
+ readOnlyApgIds.length === 0 ? (
281
+ <div className="data-space__viewer__lakehouse-access__row">
282
+ <span className="data-space__viewer__lakehouse-access__row__unavailable">
283
+ Data Product is not available in the local project — Access
284
+ Point Groups cannot be listed in preview.
285
+ </span>
286
+ </div>
287
+ ) : (
288
+ readOnlyApgIds.map((apgId) => (
289
+ <div
290
+ key={apgId}
291
+ className="data-space__viewer__lakehouse-access__row"
292
+ >
293
+ <span
294
+ className="data-space__viewer__lakehouse-access__row__apg"
295
+ title={apgId}
296
+ >
297
+ {apgId}
298
+ </span>
299
+ </div>
300
+ ))
301
+ )
302
+ ) : hasError ? (
303
+ <div
304
+ className="data-space__viewer__lakehouse-access__row"
305
+ title={accessState.errorMessage}
306
+ >
307
+ <span className="data-space__viewer__lakehouse-access__row__unavailable">
308
+ Unavailable
309
+ </span>
310
+ </div>
311
+ ) : isLoading && apgStates.length === 0 ? (
312
+ <div className="data-space__viewer__lakehouse-access__row">
313
+ <span className="data-space__viewer__lakehouse-access__row__loading">
314
+ Loading...
315
+ </span>
316
+ </div>
317
+ ) : (
318
+ apgStates.map((apgState) => (
319
+ <div
320
+ key={apgState.apg.id}
321
+ className="data-space__viewer__lakehouse-access__row"
322
+ >
323
+ <span
324
+ className="data-space__viewer__lakehouse-access__row__apg"
325
+ title={apgState.apg.id}
326
+ >
327
+ {apgState.apg.id}
328
+ </span>
329
+ <div className="data-space__viewer__lakehouse-access__row__actions">
330
+ {accessState.dataAccessState && (
331
+ <DataProductAPGAccessRequestControl
332
+ apgState={apgState}
333
+ dataAccessState={accessState.dataAccessState}
334
+ tokenProvider={tokenProvider}
335
+ />
336
+ )}
337
+ </div>
338
+ </div>
339
+ ))
340
+ )}
341
+ </div>
342
+ )}
343
+ {bulkRequestMode !== undefined &&
344
+ accessState?.dataAccessState &&
345
+ representativeApgState &&
346
+ bulkTargetApgs.length > 0 && (
347
+ <EntitlementsDataContractCreator
348
+ open={true}
349
+ onClose={(): void => setBulkRequestMode(undefined)}
350
+ tokenProvider={tokenProvider}
351
+ apgState={representativeApgState}
352
+ dataAccessState={accessState.dataAccessState}
353
+ overrideTargetApgs={bulkTargetApgs}
354
+ headerContent={
355
+ <>
356
+ Submit access request for{' '}
357
+ <span className="marketplace-lakehouse-text__emphasis">
358
+ {bulkTargetApgs.length}
359
+ </span>{' '}
360
+ Access Point Group
361
+ {bulkTargetApgs.length === 1 ? '' : 's'} in{' '}
362
+ <span className="marketplace-lakehouse-text__emphasis">
363
+ {accessState.dataAccessState.dataProductViewerState.product
364
+ .title ?? extractElementNameFromPath(dataProductPath)}
365
+ </span>{' '}
366
+ Data Product
367
+ </>
368
+ }
369
+ />
370
+ )}
371
+ </div>
372
+ );
373
+ },
374
+ );
375
+
376
+ const DataSpaceLakehouseAccessPanel = observer(
377
+ (props: {
378
+ viewerState: DataSpaceViewerState;
379
+ dataProductPaths: string[];
380
+ }) => {
381
+ const { viewerState, dataProductPaths } = props;
382
+ return (
383
+ <>
384
+ <div className="data-space__viewer__lakehouse-access__description">
385
+ <DataSpaceMarkdownTextViewer
386
+ value={
387
+ "The following Data Products are required to access this DataSpace. Products you don't have access to can be requested below."
388
+ }
389
+ />
390
+ </div>
391
+ <div className="data-space__viewer__lakehouse-access">
392
+ <div className="data-space__viewer__lakehouse-access__header">
393
+ Data Product Access
394
+ </div>
395
+ {dataProductPaths.map((dataProductPath) => (
396
+ <DataSpaceLakehouseAccessGroup
397
+ key={dataProductPath}
398
+ viewerState={viewerState}
399
+ dataProductPath={dataProductPath}
400
+ initiallyCollapsed={true}
401
+ />
402
+ ))}
403
+ </div>
404
+ </>
405
+ );
406
+ },
407
+ );
408
+
409
+ export const DataSpaceLakehouseAccess = observer(
410
+ (props: { dataSpaceViewerState: DataSpaceViewerState }) => {
411
+ const { dataSpaceViewerState } = props;
412
+ const sectionRef = useRef<HTMLDivElement>(null);
413
+ const anchor = generateAnchorForActivity(
414
+ DATA_SPACE_VIEWER_ACTIVITY_MODE.DATASPACE_LAKEHOUSE_ACCESS,
415
+ );
416
+
417
+ useEffect(() => {
418
+ if (sectionRef.current) {
419
+ dataSpaceViewerState.layoutState.setWikiPageAnchor(
420
+ anchor,
421
+ sectionRef.current,
422
+ );
423
+ }
424
+ return () => dataSpaceViewerState.layoutState.unsetWikiPageAnchor(anchor);
425
+ }, [dataSpaceViewerState, anchor]);
426
+
427
+ const dataProductPaths = dataSpaceViewerState.referencedDataProductPaths;
428
+
429
+ if (dataProductPaths.length === 0) {
430
+ return null;
431
+ }
432
+
433
+ return (
434
+ <div ref={sectionRef} className="viewer__wiki__section">
435
+ <CollapsibleWikiSection
436
+ viewerState={dataSpaceViewerState}
437
+ section={DATA_SPACE_VIEWER_ACTIVITY_MODE.DATASPACE_LAKEHOUSE_ACCESS}
438
+ >
439
+ <div className="viewer__wiki__section__content">
440
+ <DataSpaceLakehouseAccessPanel
441
+ viewerState={dataSpaceViewerState}
442
+ dataProductPaths={dataProductPaths}
443
+ />
444
+ </div>
445
+ </CollapsibleWikiSection>
446
+ </div>
447
+ );
448
+ },
449
+ );
@@ -46,7 +46,7 @@ import {
46
46
  LakehouseDataProductExecutableAccessorInfo,
47
47
  } from '../graph-manager/action/analytics/DataSpaceAnalysis.js';
48
48
  import { DataSpaceMarkdownTextViewer } from './DataSpaceMarkdownTextViewer.js';
49
- import { DataSpaceOpenDataProductButton } from './DataSpaceExecutionContextViewer.js';
49
+ import { resolveOpenDataProductAction } from './DataSpaceExecutionContextViewer.js';
50
50
  import type { DSL_DataSpace_LegendApplicationPlugin_Extension } from '../stores/DSL_DataSpace_LegendApplicationPlugin_Extension.js';
51
51
  import { useEffect, useRef, useState } from 'react';
52
52
  import { DataSpaceWikiPlaceholder } from './DataSpacePlaceholder.js';
@@ -227,6 +227,10 @@ const DataSpaceDataProductAccessPanel = observer(
227
227
  const accessState = viewerState.getDataProductAccessState(
228
228
  group.dataProductPath,
229
229
  );
230
+ const onOpenDataProduct = resolveOpenDataProductAction(
231
+ viewerState,
232
+ group.dataProductPath,
233
+ );
230
234
  return (
231
235
  <div
232
236
  key={group.dataProductPath}
@@ -250,21 +254,28 @@ const DataSpaceDataProductAccessPanel = observer(
250
254
  />
251
255
  </button>
252
256
  <div className="data-space__viewer__quickstart__tds__apg-access__group__header">
253
- <span
254
- className="data-space__viewer__quickstart__tds__apg-access__group__label"
255
- title={group.dataProductPath}
256
- >
257
- {extractElementNameFromPath(group.dataProductPath)}
258
- </span>
257
+ {onOpenDataProduct ? (
258
+ <button
259
+ type="button"
260
+ className="data-space__viewer__quickstart__tds__apg-access__group__label data-space__viewer__quickstart__tds__apg-access__group__label--clickable"
261
+ title={`Open Data Product: ${group.dataProductPath}`}
262
+ onClick={onOpenDataProduct}
263
+ >
264
+ {extractElementNameFromPath(group.dataProductPath)}
265
+ </button>
266
+ ) : (
267
+ <span
268
+ className="data-space__viewer__quickstart__tds__apg-access__group__label"
269
+ title={group.dataProductPath}
270
+ >
271
+ {extractElementNameFromPath(group.dataProductPath)}
272
+ </span>
273
+ )}
259
274
  <span className="data-space__viewer__quickstart__tds__apg-access__group__count">
260
275
  {group.accessPointGroupIds.length}
261
276
  </span>
262
277
  </div>
263
278
  <div className="data-space__viewer__quickstart__tds__apg-access__group__actions">
264
- <DataSpaceOpenDataProductButton
265
- dataSpaceViewerState={viewerState}
266
- dataProductPath={group.dataProductPath}
267
- />
268
279
  {accessState && (
269
280
  <IconButton
270
281
  className="data-space__viewer__quickstart__tds__apg-access__group__refresh-btn"
@@ -20,7 +20,6 @@ import {
20
20
  CaretUpIcon,
21
21
  ControlledDropdownMenu,
22
22
  MenuContent,
23
- MenuContentDivider,
24
23
  MenuContentItem,
25
24
  MoreVerticalIcon,
26
25
  PlayIcon,
@@ -36,15 +35,11 @@ import { DataSpaceWiki } from './DataSpaceWiki.js';
36
35
  import { DataSpaceViewerActivityBar } from './DataSpaceViewerActivityBar.js';
37
36
  import { useCallback, useEffect, useRef, useState } from 'react';
38
37
  import { DATA_SPACE_WIKI_PAGE_SECTIONS } from '../stores/DataSpaceLayoutState.js';
39
- import {
40
- DATA_SPACE_VIEWER_ACTIVITY_MODE,
41
- generateAnchorForActivity,
42
- } from '../stores/DataSpaceViewerNavigation.js';
38
+ import { DATA_SPACE_VIEWER_ACTIVITY_MODE } from '../stores/DataSpaceViewerNavigation.js';
43
39
  import { DataSpacePlaceholderPanel } from './DataSpacePlaceholder.js';
44
40
  import { useApplicationStore } from '@finos/legend-application';
45
41
  import { DataSpaceLegendAIIntegration } from './DataSpaceLegendAIIntegration.js';
46
42
  import { DSL_DATASPACE_EVENT } from '../__lib__/DSL_DataSpace_Event.js';
47
- import { guaranteeNonNullable } from '@finos/legend-shared';
48
43
  import { DataSpaceQualityEmote } from './DataSpaceQualityEmote.js';
49
44
 
50
45
  const DataSpaceHeader = observer(
@@ -194,29 +189,6 @@ const DataSpaceHeader = observer(
194
189
  title="More Actions..."
195
190
  content={
196
191
  <MenuContent>
197
- {dataSpaceViewerState.currentExecutionContext && (
198
- <>
199
- <MenuContentItem
200
- onClick={() =>
201
- dataSpaceViewerState.queryDataSpace(
202
- guaranteeNonNullable(
203
- dataSpaceViewerState.currentExecutionContext,
204
- ).name,
205
- )
206
- }
207
- >
208
- Query Data Space
209
- </MenuContentItem>
210
- <MenuContentDivider />
211
- </>
212
- )}
213
- <MenuContentItem
214
- onClick={() =>
215
- dataSpaceViewerState.viewProject(analysisResult.path)
216
- }
217
- >
218
- View Project
219
- </MenuContentItem>
220
192
  <MenuContentItem
221
193
  onClick={() => {
222
194
  dataSpaceViewerState
@@ -224,32 +196,7 @@ const DataSpaceHeader = observer(
224
196
  .catch(applicationStore.alertUnhandledError);
225
197
  }}
226
198
  >
227
- View SDLC Project
228
- </MenuContentItem>
229
- <MenuContentDivider />
230
- <MenuContentItem
231
- onClick={() => {
232
- const documentationUrl =
233
- analysisResult.supportInfo?.documentationUrl;
234
- if (documentationUrl) {
235
- applicationStore.navigationService.navigator.visitAddress(
236
- documentationUrl,
237
- );
238
- }
239
- }}
240
- >
241
- Read Documentation
242
- </MenuContentItem>
243
- <MenuContentItem
244
- onClick={() =>
245
- dataSpaceViewerState.changeZone(
246
- generateAnchorForActivity(
247
- DATA_SPACE_VIEWER_ACTIVITY_MODE.SUPPORT,
248
- ),
249
- )
250
- }
251
- >
252
- Get Help
199
+ View Project
253
200
  </MenuContentItem>
254
201
  </MenuContent>
255
202
  }
@@ -18,7 +18,11 @@ import type { DataSpaceViewerState } from '../stores/DataSpaceViewerState.js';
18
18
  import { observer } from 'mobx-react-lite';
19
19
  import { DataSpaceQuickStart } from './DataSpaceQuickStart.js';
20
20
  import { DataSpaceDataAccess } from './DataSpaceDataAccess.js';
21
- import { DataSpaceDescription } from './DataSpaceDescription.js';
21
+ import {
22
+ DataSpaceDescription,
23
+ DataSpaceWikiBadges,
24
+ } from './DataSpaceDescription.js';
25
+ import { DataSpaceLakehouseAccess } from './DataSpaceLakehouseAccess.js';
22
26
  import { useEffect } from 'react';
23
27
  import { ModelsDocumentation } from '@finos/legend-lego/model-documentation';
24
28
  import { DiagramViewer } from '@finos/legend-extension-dsl-diagram';
@@ -57,7 +61,9 @@ export const DataSpaceWiki = observer(
57
61
 
58
62
  return (
59
63
  <div className="data-space__viewer__wiki">
64
+ <DataSpaceWikiBadges dataSpaceViewerState={dataSpaceViewerState} />
60
65
  <DataSpaceDescription dataSpaceViewerState={dataSpaceViewerState} />
66
+ <DataSpaceLakehouseAccess dataSpaceViewerState={dataSpaceViewerState} />
61
67
  <DiagramViewer
62
68
  diagramViewerState={dataSpaceViewerState.diagramViewerState}
63
69
  actions={{
@@ -50,7 +50,7 @@ import {
50
50
  V1_MappingModelCoveragePartition,
51
51
  V1_getGenericTypeFullPath,
52
52
  V1_buildFullPath,
53
- V1_LakehouseRuntime,
53
+ V1_LakehouseBaseRuntime,
54
54
  V1_packageableRuntimeModelSchema,
55
55
  V1_RelationType,
56
56
  GenericType,
@@ -514,7 +514,7 @@ export class V1_DSL_DataSpace_PureGraphManagerExtension extends DSL_DataSpace_Pu
514
514
  V1_packageableRuntimeModelSchema,
515
515
  runtimeEntity.content,
516
516
  );
517
- if (runtimeProtocol.runtimeValue instanceof V1_LakehouseRuntime) {
517
+ if (runtimeProtocol.runtimeValue instanceof V1_LakehouseBaseRuntime) {
518
518
  dataSpaceAnalysisResult.__INTERNAL__useRelationTDS = true;
519
519
  }
520
520
  }
@@ -28,16 +28,13 @@ import { BaseLayoutState } from '@finos/legend-extension-dsl-data-product';
28
28
 
29
29
  export const DATA_SPACE_WIKI_PAGE_SECTIONS = [
30
30
  DATA_SPACE_VIEWER_ACTIVITY_MODE.DESCRIPTION,
31
+ DATA_SPACE_VIEWER_ACTIVITY_MODE.DATASPACE_LAKEHOUSE_ACCESS,
31
32
  DATA_SPACE_VIEWER_ACTIVITY_MODE.DIAGRAM_VIEWER,
32
33
  DATA_SPACE_VIEWER_ACTIVITY_MODE.MODELS_DOCUMENTATION,
33
34
  DATA_SPACE_VIEWER_ACTIVITY_MODE.QUICK_START,
34
35
  DATA_SPACE_VIEWER_ACTIVITY_MODE.DATA_ACCESS,
35
36
  ];
36
37
 
37
- const DATA_SPACE_WIKI_PAGE_ANCHORS = DATA_SPACE_WIKI_PAGE_SECTIONS.map(
38
- (activity) => generateAnchorForActivity(activity),
39
- );
40
-
41
38
  export class DataSpaceLayoutState extends BaseLayoutState {
42
39
  private dataSpaceViewerState!: DataSpaceViewerState;
43
40
 
@@ -53,7 +50,9 @@ export class DataSpaceLayoutState extends BaseLayoutState {
53
50
  }
54
51
 
55
52
  protected getValidAnchors(): string[] {
56
- return DATA_SPACE_WIKI_PAGE_ANCHORS;
53
+ return this.dataSpaceViewerState.wikiPageSectionsToRender.map((activity) =>
54
+ generateAnchorForActivity(activity),
55
+ );
57
56
  }
58
57
 
59
58
  protected get expectedGridCount(): number {
@@ -63,7 +62,7 @@ export class DataSpaceLayoutState extends BaseLayoutState {
63
62
  override get isWikiPageFullyRendered(): boolean {
64
63
  return (
65
64
  super.isWikiPageFullyRendered &&
66
- DATA_SPACE_WIKI_PAGE_SECTIONS.includes(
65
+ this.dataSpaceViewerState.wikiPageSectionsToRender.includes(
67
66
  this.dataSpaceViewerState.currentActivity,
68
67
  )
69
68
  );
@@ -20,6 +20,7 @@ import type { DiagramAnalysisResult } from '@finos/legend-extension-dsl-diagram'
20
20
 
21
21
  export enum DATA_SPACE_VIEWER_ACTIVITY_MODE {
22
22
  DESCRIPTION = 'description',
23
+ DATASPACE_LAKEHOUSE_ACCESS = 'dataspace-lakehouse-access',
23
24
  DIAGRAM_VIEWER = 'diagram-viewer',
24
25
  MODELS_DOCUMENTATION = 'models-documentation',
25
26
  QUICK_START = 'quick-start',