@finos/legend-extension-dsl-data-product 0.0.20 → 0.0.21

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 (22) hide show
  1. package/lib/components/DataProduct/DataContract/EntitlementsDataContractViewer.d.ts +1 -2
  2. package/lib/components/DataProduct/DataContract/EntitlementsDataContractViewer.d.ts.map +1 -1
  3. package/lib/components/DataProduct/DataContract/EntitlementsDataContractViewer.js +64 -18
  4. package/lib/components/DataProduct/DataContract/EntitlementsDataContractViewer.js.map +1 -1
  5. package/lib/components/DataProduct/DataProductDataAccess.d.ts.map +1 -1
  6. package/lib/components/DataProduct/DataProductDataAccess.js +14 -4
  7. package/lib/components/DataProduct/DataProductDataAccess.js.map +1 -1
  8. package/lib/components/__test-utils__/TEST_DATA__LakehouseContractData.d.ts +4 -2
  9. package/lib/components/__test-utils__/TEST_DATA__LakehouseContractData.d.ts.map +1 -1
  10. package/lib/components/__test-utils__/TEST_DATA__LakehouseContractData.js +130 -1
  11. package/lib/components/__test-utils__/TEST_DATA__LakehouseContractData.js.map +1 -1
  12. package/lib/index.css +1 -1
  13. package/lib/package.json +1 -1
  14. package/lib/stores/DataProduct/EntitlementsDataContractViewerState.d.ts +10 -3
  15. package/lib/stores/DataProduct/EntitlementsDataContractViewerState.d.ts.map +1 -1
  16. package/lib/stores/DataProduct/EntitlementsDataContractViewerState.js +38 -9
  17. package/lib/stores/DataProduct/EntitlementsDataContractViewerState.js.map +1 -1
  18. package/package.json +9 -9
  19. package/src/components/DataProduct/DataContract/EntitlementsDataContractViewer.tsx +289 -150
  20. package/src/components/DataProduct/DataProductDataAccess.tsx +18 -2
  21. package/src/components/__test-utils__/TEST_DATA__LakehouseContractData.ts +137 -2
  22. package/src/stores/DataProduct/EntitlementsDataContractViewerState.ts +64 -13
@@ -22,6 +22,7 @@ import {
22
22
  Box,
23
23
  Button,
24
24
  Dialog,
25
+ DialogActions,
25
26
  DialogContent,
26
27
  DialogTitle,
27
28
  IconButton,
@@ -47,17 +48,20 @@ import {
47
48
  V1_ContractUserEventPrivilegeManagerPayload,
48
49
  V1_ResourceType,
49
50
  V1_UserApprovalStatus,
51
+ V1_UserType,
50
52
  } from '@finos/legend-graph';
51
53
  import React, { useCallback, useEffect, useMemo, useState } from 'react';
52
54
  import {
53
55
  type UserSearchService,
54
56
  ActionState,
57
+ assertErrorThrown,
55
58
  formatDate,
56
59
  lodashCapitalize,
57
60
  } from '@finos/legend-shared';
58
61
  import { flowResult } from 'mobx';
59
62
  import { useAuth } from 'react-oidc-context';
60
63
  import {
64
+ ArrowUpFromBracketIcon,
61
65
  CloseIcon,
62
66
  CopyIcon,
63
67
  CubesLoadingIndicator,
@@ -75,7 +79,6 @@ import {
75
79
  import { UserRenderer } from '../../UserRenderer/UserRenderer.js';
76
80
  import { isContractInTerminalState } from '../../../utils/DataContractUtils.js';
77
81
  import type { GenericLegendApplicationStore } from '@finos/legend-application';
78
- import type { DataProductAPGState } from '../../../stores/DataProduct/DataProductAPGState.js';
79
82
 
80
83
  const AssigneesList = (props: {
81
84
  userIds: string[];
@@ -167,6 +170,91 @@ const TaskApprovalView = (props: {
167
170
  }
168
171
  };
169
172
 
173
+ const ContractEscalationModal = (props: {
174
+ open: boolean;
175
+ onClose: () => void;
176
+ currentViewer: EntitlementsDataContractViewerState;
177
+ selectedUser: string | undefined;
178
+ refresh: () => Promise<void>;
179
+ }) => {
180
+ const { open, onClose, currentViewer, selectedUser, refresh } = props;
181
+
182
+ const auth = useAuth();
183
+ const [isLoading, setIsLoading] = useState(false);
184
+
185
+ if (!selectedUser) {
186
+ return (
187
+ <Dialog open={open} onClose={onClose} fullWidth={true} maxWidth="sm">
188
+ <DialogContent className="marketplace-lakehouse-entitlements__data-contract-viewer__escalation__content">
189
+ <div>
190
+ Can&apos;t escalate privilege manager approval request. No user
191
+ selected.
192
+ </div>
193
+ </DialogContent>
194
+ <DialogActions>
195
+ <Button onClick={onClose} variant="outlined" disabled={isLoading}>
196
+ Close
197
+ </Button>
198
+ </DialogActions>
199
+ </Dialog>
200
+ );
201
+ }
202
+
203
+ const handleEscalate = async () => {
204
+ setIsLoading(true);
205
+ try {
206
+ await currentViewer.lakehouseContractServerClient.escalateUserOnContract(
207
+ currentViewer.liteContract.guid,
208
+ selectedUser,
209
+ false,
210
+ auth.user?.access_token,
211
+ );
212
+ currentViewer.applicationStore.notificationService.notifySuccess(
213
+ 'Successfully escalated contract request',
214
+ );
215
+ // eslint-disable-next-line no-void
216
+ void refresh();
217
+ onClose();
218
+ } catch (error) {
219
+ assertErrorThrown(error);
220
+ currentViewer.applicationStore.alertUnhandledError(error);
221
+ } finally {
222
+ setIsLoading(false);
223
+ }
224
+ };
225
+
226
+ return (
227
+ <Dialog open={open} onClose={onClose} fullWidth={true} maxWidth="sm">
228
+ <DialogContent className="marketplace-lakehouse-entitlements__data-contract-viewer__escalation__content">
229
+ <CubesLoadingIndicator isLoading={isLoading}>
230
+ <CubesLoadingIndicatorIcon />
231
+ </CubesLoadingIndicator>
232
+ {!isLoading && (
233
+ <div>
234
+ Are you sure you want to escalate the privilege manager approval
235
+ request?
236
+ </div>
237
+ )}
238
+ </DialogContent>
239
+ <DialogActions>
240
+ <Button
241
+ onClick={() => {
242
+ // eslint-disable-next-line no-void
243
+ void handleEscalate();
244
+ }}
245
+ variant="contained"
246
+ disabled={isLoading}
247
+ >
248
+ Escalate
249
+ </Button>
250
+ <Button onClick={onClose} variant="outlined" disabled={isLoading}>
251
+ Cancel
252
+ </Button>
253
+ </DialogActions>
254
+ </Dialog>
255
+ );
256
+ };
257
+
170
258
  export const EntitlementsDataContractViewer = observer(
171
259
  (props: {
172
260
  open: boolean;
@@ -174,20 +262,20 @@ export const EntitlementsDataContractViewer = observer(
174
262
  currentViewer: EntitlementsDataContractViewerState;
175
263
  getContractTaskUrl: (taskId: string) => string;
176
264
  getDataProductUrl: (dataProductId: string, deploymentId: number) => string;
177
- apgState?: DataProductAPGState | undefined;
178
265
  initialSelectedUser?: string | undefined;
266
+ onRefresh?: (() => void) | (() => Promise<void>);
179
267
  }) => {
180
268
  const {
181
269
  open,
182
270
  currentViewer,
183
271
  getContractTaskUrl,
184
272
  getDataProductUrl,
185
- apgState,
186
273
  onClose,
187
274
  initialSelectedUser,
275
+ onRefresh,
188
276
  } = props;
189
277
  const auth = useAuth();
190
- const consumer = currentViewer.value.consumer;
278
+ const consumer = currentViewer.liteContract.consumer;
191
279
 
192
280
  // We try to get the target users from the associated tasks first, since the
193
281
  // tasks are what drive the timeline view. If there are no associated tasks,
@@ -244,6 +332,7 @@ export const EntitlementsDataContractViewer = observer(
244
332
  string | undefined
245
333
  >(initialSelectedUser ?? targetUsers?.[0]);
246
334
  const [isLoading, setIsLoading] = useState(false);
335
+ const [showEscalationModal, setShowEscalationModal] = useState(false);
247
336
 
248
337
  useEffect(() => {
249
338
  if (!currentViewer.initializationState.hasCompleted) {
@@ -267,18 +356,13 @@ export const EntitlementsDataContractViewer = observer(
267
356
 
268
357
  const refresh = async (): Promise<void> => {
269
358
  setIsLoading(true);
270
- if (apgState?.associatedUserContract) {
271
- apgState.fetchUserAccessStatus(
272
- apgState.associatedUserContract.guid,
273
- currentViewer.lakehouseContractServerClient,
274
- auth.user?.access_token,
275
- );
276
- }
277
359
  currentViewer.initializationState = ActionState.create();
360
+ await onRefresh?.();
278
361
  };
279
362
 
280
363
  if (
281
- currentViewer.value.resourceType !== V1_ResourceType.ACCESS_POINT_GROUP
364
+ currentViewer.liteContract.resourceType !==
365
+ V1_ResourceType.ACCESS_POINT_GROUP
282
366
  ) {
283
367
  return (
284
368
  <Dialog open={true} onClose={onClose} fullWidth={true} maxWidth="md">
@@ -291,15 +375,15 @@ export const EntitlementsDataContractViewer = observer(
291
375
  </IconButton>
292
376
  <DialogContent className="marketplace-lakehouse-entitlements__data-contract-viewer__content">
293
377
  Unable to display data contract request details for resource of type{' '}
294
- {currentViewer.value.resourceType} on data product{' '}
295
- {currentViewer.value.resourceId}.
378
+ {currentViewer.liteContract.resourceType} on data product{' '}
379
+ {currentViewer.liteContract.resourceId}.
296
380
  </DialogContent>
297
381
  </Dialog>
298
382
  );
299
383
  }
300
384
 
301
- const dataProduct = currentViewer.value.resourceId;
302
- const accessPointGroup = currentViewer.value.accessPointGroup;
385
+ const dataProduct = currentViewer.liteContract.resourceId;
386
+ const accessPointGroup = currentViewer.liteContract.accessPointGroup;
303
387
  const privilegeManagerApprovalTask = currentViewer.associatedTasks?.find(
304
388
  (task) =>
305
389
  task.rec.consumer === selectedTargetUser &&
@@ -314,6 +398,28 @@ export const EntitlementsDataContractViewer = observer(
314
398
  privilegeManagerApprovalTask?.rec.status ===
315
399
  V1_UserApprovalStatus.PENDING ||
316
400
  dataOwnerApprovalTask?.rec.status === V1_UserApprovalStatus.PENDING;
401
+ const showEscalationButton =
402
+ selectedTargetUser ===
403
+ currentViewer.applicationStore.identityService.currentUser ||
404
+ (selectedTargetUser !== undefined &&
405
+ currentViewer.getContractUserType(selectedTargetUser) ===
406
+ V1_UserType.SYSTEM_ACCOUNT);
407
+ const isContractEscalated =
408
+ privilegeManagerApprovalTask?.rec.isEscalated === true;
409
+ const canEscalateContract = showEscalationButton && !isContractEscalated;
410
+
411
+ const copyContractId = (): void => {
412
+ currentViewer.applicationStore.clipboardService
413
+ .copyTextToClipboard(currentViewer.liteContract.guid)
414
+ .then(() =>
415
+ currentViewer.applicationStore.notificationService.notifySuccess(
416
+ 'Contract ID Copied to Clipboard',
417
+ undefined,
418
+ 2500,
419
+ ),
420
+ )
421
+ .catch(currentViewer.applicationStore.alertUnhandledError);
422
+ };
317
423
 
318
424
  const copyTaskLink = (text: string): void => {
319
425
  currentViewer.applicationStore.clipboardService
@@ -360,6 +466,24 @@ export const EntitlementsDataContractViewer = observer(
360
466
  >
361
467
  <CopyIcon />
362
468
  </IconButton>
469
+ {showEscalationButton && (
470
+ <span
471
+ title={
472
+ canEscalateContract
473
+ ? 'Escalate request'
474
+ : isContractEscalated
475
+ ? 'Request has already been escalated'
476
+ : 'Cannot escalate request'
477
+ }
478
+ >
479
+ <IconButton
480
+ onClick={() => setShowEscalationModal(true)}
481
+ disabled={!canEscalateContract}
482
+ >
483
+ <ArrowUpFromBracketIcon />
484
+ </IconButton>
485
+ </span>
486
+ )}
363
487
  </>
364
488
  ) : (
365
489
  <>Privilege Manager Approval</>
@@ -443,144 +567,159 @@ export const EntitlementsDataContractViewer = observer(
443
567
  ];
444
568
 
445
569
  return (
446
- <Dialog open={open} onClose={onClose} fullWidth={true} maxWidth="md">
447
- <DialogTitle>
448
- {isContractInProgressForUser ? 'Pending ' : ''}Data Contract Request
449
- </DialogTitle>
450
- <IconButton onClick={onClose} className="marketplace-dialog-close-btn">
451
- <CloseIcon />
452
- </IconButton>
453
- <DialogContent className="marketplace-lakehouse-entitlements__data-contract-viewer__content">
454
- <CubesLoadingIndicator isLoading={isLoading}>
455
- <CubesLoadingIndicatorIcon />
456
- </CubesLoadingIndicator>
457
- {!isLoading && (
458
- <>
459
- <div>
460
- Access request for{' '}
461
- <span className="marketplace-lakehouse-text__emphasis">
462
- {accessPointGroup}
463
- </span>{' '}
464
- Access Point Group in{' '}
465
- <Link
466
- className="marketplace-lakehouse-text__emphasis"
467
- href={getDataProductUrl(
468
- dataProduct,
469
- currentViewer.value.deploymentId,
470
- )}
471
- target="_blank"
472
- rel="noopener noreferrer"
473
- >
474
- {dataProduct}
475
- </Link>{' '}
476
- Data Product
477
- </div>
478
- <Box className="marketplace-lakehouse-entitlements__data-contract-viewer__metadata">
479
- <div className="marketplace-lakehouse-entitlements__data-contract-viewer__metadata__ordered-by">
480
- <b>Ordered By: </b>
481
- <UserRenderer
482
- userId={currentViewer.value.createdBy}
483
- applicationStore={currentViewer.applicationStore}
484
- userSearchService={currentViewer.userSearchService}
485
- />
570
+ <>
571
+ <Dialog open={open} onClose={onClose} fullWidth={true} maxWidth="md">
572
+ <DialogTitle>
573
+ {isContractInProgressForUser ? 'Pending ' : ''}Data Contract Request
574
+ </DialogTitle>
575
+ <IconButton
576
+ onClick={onClose}
577
+ className="marketplace-dialog-close-btn"
578
+ >
579
+ <CloseIcon />
580
+ </IconButton>
581
+ <DialogContent className="marketplace-lakehouse-entitlements__data-contract-viewer__content">
582
+ <CubesLoadingIndicator isLoading={isLoading}>
583
+ <CubesLoadingIndicatorIcon />
584
+ </CubesLoadingIndicator>
585
+ {!isLoading && (
586
+ <>
587
+ <div>
588
+ Access request for{' '}
589
+ <span className="marketplace-lakehouse-text__emphasis">
590
+ {accessPointGroup}
591
+ </span>{' '}
592
+ Access Point Group in{' '}
593
+ <Link
594
+ className="marketplace-lakehouse-text__emphasis"
595
+ href={getDataProductUrl(
596
+ dataProduct,
597
+ currentViewer.liteContract.deploymentId,
598
+ )}
599
+ target="_blank"
600
+ rel="noopener noreferrer"
601
+ >
602
+ {dataProduct}
603
+ </Link>{' '}
604
+ Data Product
486
605
  </div>
487
- <div className="marketplace-lakehouse-entitlements__data-contract-viewer__metadata__ordered-for">
488
- <b>
489
- Ordered For
490
- <Tooltip
491
- className="marketplace-lakehouse-entitlements__data-contract-viewer__metadata__ordered-for__tooltip__icon"
492
- title={
493
- <>
494
- Contract consumer type:{' '}
495
- {getOrganizationalScopeTypeName(
496
- consumer,
497
- currentViewer.applicationStore.pluginManager.getApplicationPlugins(),
498
- )}
499
- {getOrganizationalScopeTypeDetails(
500
- consumer,
501
- currentViewer.applicationStore.pluginManager.getApplicationPlugins(),
502
- )}
503
- </>
504
- }
505
- >
506
- <InfoCircleIcon />
507
- </Tooltip>
508
- :{' '}
509
- </b>
510
- {targetUsers !== undefined ? (
511
- targetUsers.length === 1 ? (
512
- <UserRenderer
513
- key={targetUsers[0]}
514
- userId={targetUsers[0]}
515
- applicationStore={currentViewer.applicationStore}
516
- userSearchService={currentViewer.userSearchService}
517
- />
518
- ) : (
519
- <Select
520
- value={selectedTargetUser}
521
- onChange={(event) =>
522
- setSelectedTargetUser(event.target.value)
606
+ <Box className="marketplace-lakehouse-entitlements__data-contract-viewer__metadata">
607
+ <div className="marketplace-lakehouse-entitlements__data-contract-viewer__metadata__ordered-by">
608
+ <b>Ordered By: </b>
609
+ <UserRenderer
610
+ userId={currentViewer.liteContract.createdBy}
611
+ applicationStore={currentViewer.applicationStore}
612
+ userSearchService={currentViewer.userSearchService}
613
+ />
614
+ </div>
615
+ <div className="marketplace-lakehouse-entitlements__data-contract-viewer__metadata__ordered-for">
616
+ <b>
617
+ Ordered For
618
+ <Tooltip
619
+ className="marketplace-lakehouse-entitlements__data-contract-viewer__metadata__ordered-for__tooltip__icon"
620
+ title={
621
+ <>
622
+ Contract consumer type:{' '}
623
+ {getOrganizationalScopeTypeName(
624
+ consumer,
625
+ currentViewer.applicationStore.pluginManager.getApplicationPlugins(),
626
+ )}
627
+ {getOrganizationalScopeTypeDetails(
628
+ consumer,
629
+ currentViewer.applicationStore.pluginManager.getApplicationPlugins(),
630
+ )}
631
+ </>
523
632
  }
524
- size="small"
525
- className="marketplace-lakehouse-entitlements__data-contract-viewer__metadata__ordered-for__select"
526
633
  >
527
- {targetUserSelectItems}
528
- </Select>
529
- )
530
- ) : (
531
- stringifyOrganizationalScope(consumer)
532
- )}
533
- </div>
534
- <div>
535
- <b>Business Justification: </b>
536
- {currentViewer.value.description}
537
- </div>
538
- </Box>
539
- {!isContractInTerminalState(currentViewer.value) && (
540
- <Box className="marketplace-lakehouse-entitlements__data-contract-viewer__refresh-btn">
541
- <Button
542
- size="small"
543
- variant="outlined"
544
- startIcon={<RefreshIcon />}
545
- onClick={() => {
546
- // eslint-disable-next-line no-void
547
- void refresh();
548
- }}
549
- >
550
- Refresh
551
- </Button>
552
- </Box>
553
- )}
554
- <Box className="marketplace-lakehouse-entitlements__data-contract-viewer__timeline">
555
- <Timeline>
556
- {steps.map((step, index) => (
557
- <TimelineItem key={step.key}>
558
- <TimelineOppositeContent className="marketplace-lakehouse-entitlements__data-contract-viewer__timeline__content">
559
- {step.label}
560
- </TimelineOppositeContent>
561
- <TimelineSeparator>
562
- <TimelineDot
563
- color={step.isDeniedStep ? 'error' : 'primary'}
564
- variant={
565
- step.isCompleteOrActive ? 'filled' : 'outlined'
566
- }
634
+ <InfoCircleIcon />
635
+ </Tooltip>
636
+ :{' '}
637
+ </b>
638
+ {targetUsers !== undefined ? (
639
+ targetUsers.length === 1 ? (
640
+ <UserRenderer
641
+ key={targetUsers[0]}
642
+ userId={targetUsers[0]}
643
+ applicationStore={currentViewer.applicationStore}
644
+ userSearchService={currentViewer.userSearchService}
567
645
  />
568
- {index < steps.length - 1 && <TimelineConnector />}
569
- </TimelineSeparator>
570
- <TimelineContent className="marketplace-lakehouse-entitlements__data-contract-viewer__timeline__content">
571
- {step.description}
572
- </TimelineContent>
573
- </TimelineItem>
574
- ))}
575
- </Timeline>
576
- </Box>
577
- </>
578
- )}
579
- <Box className="marketplace-lakehouse-entitlements__data-contract-viewer__footer">
580
- Contract ID: {currentViewer.value.guid}
581
- </Box>
582
- </DialogContent>
583
- </Dialog>
646
+ ) : (
647
+ <Select
648
+ value={selectedTargetUser}
649
+ onChange={(event) =>
650
+ setSelectedTargetUser(event.target.value)
651
+ }
652
+ size="small"
653
+ className="marketplace-lakehouse-entitlements__data-contract-viewer__metadata__ordered-for__select"
654
+ >
655
+ {targetUserSelectItems}
656
+ </Select>
657
+ )
658
+ ) : (
659
+ stringifyOrganizationalScope(consumer)
660
+ )}
661
+ </div>
662
+ <div>
663
+ <b>Business Justification: </b>
664
+ {currentViewer.liteContract.description}
665
+ </div>
666
+ </Box>
667
+ {!isContractInTerminalState(currentViewer.liteContract) && (
668
+ <Box className="marketplace-lakehouse-entitlements__data-contract-viewer__refresh-btn">
669
+ <Button
670
+ size="small"
671
+ variant="outlined"
672
+ startIcon={<RefreshIcon />}
673
+ onClick={() => {
674
+ // eslint-disable-next-line no-void
675
+ void refresh();
676
+ }}
677
+ >
678
+ Refresh
679
+ </Button>
680
+ </Box>
681
+ )}
682
+ <Box className="marketplace-lakehouse-entitlements__data-contract-viewer__timeline">
683
+ <Timeline>
684
+ {steps.map((step, index) => (
685
+ <TimelineItem key={step.key}>
686
+ <TimelineOppositeContent className="marketplace-lakehouse-entitlements__data-contract-viewer__timeline__content">
687
+ {step.label}
688
+ </TimelineOppositeContent>
689
+ <TimelineSeparator>
690
+ <TimelineDot
691
+ color={step.isDeniedStep ? 'error' : 'primary'}
692
+ variant={
693
+ step.isCompleteOrActive ? 'filled' : 'outlined'
694
+ }
695
+ />
696
+ {index < steps.length - 1 && <TimelineConnector />}
697
+ </TimelineSeparator>
698
+ <TimelineContent className="marketplace-lakehouse-entitlements__data-contract-viewer__timeline__content">
699
+ {step.description}
700
+ </TimelineContent>
701
+ </TimelineItem>
702
+ ))}
703
+ </Timeline>
704
+ </Box>
705
+ </>
706
+ )}
707
+ <Box className="marketplace-lakehouse-entitlements__data-contract-viewer__footer">
708
+ Contract ID: {currentViewer.liteContract.guid}
709
+ <IconButton onClick={() => copyContractId()}>
710
+ <CopyIcon />
711
+ </IconButton>
712
+ </Box>
713
+ </DialogContent>
714
+ </Dialog>
715
+ <ContractEscalationModal
716
+ open={showEscalationModal && canEscalateContract}
717
+ onClose={() => setShowEscalationModal(false)}
718
+ currentViewer={currentViewer}
719
+ selectedUser={selectedTargetUser}
720
+ refresh={refresh}
721
+ />
722
+ </>
584
723
  );
585
724
  },
586
725
  );
@@ -38,6 +38,7 @@ import {
38
38
  import {
39
39
  type V1_RelationTypeColumn,
40
40
  extractElementNameFromPath,
41
+ V1_AccessPointGroupReference,
41
42
  V1_AdHocDeploymentDataProductOrigin,
42
43
  V1_AppliedFunction,
43
44
  V1_AppliedProperty,
@@ -590,18 +591,25 @@ export const DataProductAccessPointGroupViewer = observer(
590
591
  const requestAccessButtonGroupRef = useRef<HTMLDivElement | null>(null);
591
592
 
592
593
  const entitlementsDataContractViewerState = useMemo(() => {
593
- return dataAccessState?.dataContract
594
+ return dataAccessState?.dataContract &&
595
+ dataAccessState.dataContract.resource instanceof
596
+ V1_AccessPointGroupReference &&
597
+ dataAccessState.dataContract.resource.accessPointGroup ===
598
+ apgState.apg.id
594
599
  ? new EntitlementsDataContractViewerState(
595
600
  V1_transformDataContractToLiteDatacontract(
596
601
  dataAccessState.dataContract,
597
602
  ),
598
603
  apgState.applicationStore,
599
604
  dataAccessState.lakehouseContractServerClient,
605
+ apgState.dataProductViewerState.graphManagerState,
600
606
  apgState.dataProductViewerState.userSearchService,
601
607
  )
602
608
  : undefined;
603
609
  }, [
610
+ apgState.apg.id,
604
611
  apgState.applicationStore,
612
+ apgState.dataProductViewerState.graphManagerState,
605
613
  apgState.dataProductViewerState.userSearchService,
606
614
  dataAccessState?.dataContract,
607
615
  dataAccessState?.lakehouseContractServerClient,
@@ -844,7 +852,15 @@ export const DataProductAccessPointGroupViewer = observer(
844
852
  open={true}
845
853
  onClose={() => dataAccessState.setDataContract(undefined)}
846
854
  currentViewer={entitlementsDataContractViewerState}
847
- apgState={apgState}
855
+ onRefresh={() => {
856
+ if (apgState.associatedUserContract) {
857
+ apgState.fetchUserAccessStatus(
858
+ apgState.associatedUserContract.guid,
859
+ dataAccessState.lakehouseContractServerClient,
860
+ auth.user?.access_token,
861
+ );
862
+ }
863
+ }}
848
864
  getContractTaskUrl={dataAccessState.getContractTaskUrl}
849
865
  getDataProductUrl={dataAccessState.getDataProductUrl}
850
866
  />