@finos/legend-application-marketplace
Version:
Legend Marketplace application core
201 lines • 18.8 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
/**
* Copyright (c) 2020-present, Goldman Sachs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { observer } from 'mobx-react-lite';
import { Accordion, AccordionDetails, AccordionSummary, Box, Button, CircularProgress, Dialog, DialogContent, DialogTitle, IconButton, Link, } from '@mui/material';
import { Timeline, TimelineConnector, TimelineContent, TimelineDot, TimelineItem, TimelineOppositeContent, TimelineSeparator, } from '@mui/lab';
import { V1_AccessPointGroupReference, V1_AdhocTeam, V1_ApprovalType, V1_ContractState, V1_ContractUserEventDataProducerPayload, V1_ContractUserEventPrivilegeManagerPayload, V1_UserType, } from '@finos/legend-graph';
import React, { useEffect, useState } from 'react';
import { formatDate, guaranteeNonNullable, isNonNullable, LegendUser, } from '@finos/legend-shared';
import { getUserById, isContractInTerminalState, isContractStateComplete, stringifyOrganizationalScope, } from '../../../stores/lakehouse/LakehouseUtils.js';
import { useLegendMarketplaceBaseStore } from '../../../application/LegendMarketplaceFrameworkProvider.js';
import { flowResult } from 'mobx';
import { useAuth } from 'react-oidc-context';
import { CloseIcon, CopyIcon, CubesLoadingIndicator, CubesLoadingIndicatorIcon, ExpandMoreIcon, RefreshIcon, UserDisplay, } from '@finos/legend-art';
import { generateLakehouseTaskPath } from '../../../__lib__/LegendMarketplaceNavigation.js';
const AssigneesList = (props) => {
const { users, userProfileImageUrl, onUserClick } = props;
return users.length === 1 ? (_jsxs("span", { children: ["Assignee:", ' ', users[0] instanceof LegendUser ? (_jsx(UserDisplay, { user: users[0], imgSrc: userProfileImageUrl?.replace('{userId}', users[0].id), onClick: () => onUserClick?.(users[0].id) })) : (_jsx("div", { children: users[0] }))] })) : (_jsxs(Accordion, { className: "marketplace-lakehouse-entitlements__data-contract-viewer__user-list__container", elevation: 0, disableGutters: true, defaultExpanded: true, children: [_jsxs(AccordionSummary, { expandIcon: _jsx(ExpandMoreIcon, {}), children: ["Assignees (", users.length, "):"] }), _jsx(AccordionDetails, { className: "marketplace-lakehouse-entitlements__data-contract-viewer__user-list", children: users.map((user) => user instanceof LegendUser ? (_jsx(UserDisplay, { user: user, imgSrc: userProfileImageUrl?.replace('{userId}', user.id), onClick: () => onUserClick?.(user.id) }, user.id)) : (_jsx("div", { children: user }, user))) })] }));
};
const TaskApprovalView = (props) => {
const { contractState, task, userDataMap, userProfileImageUrl, onUserClick } = props;
const approverId = task?.rec.eventPayload instanceof
V1_ContractUserEventPrivilegeManagerPayload
? task.rec.eventPayload.managerIdentity
: task?.rec.eventPayload instanceof
V1_ContractUserEventDataProducerPayload
? task.rec.eventPayload.dataProducerIdentity
: undefined;
const legendUser = userDataMap.get(approverId ?? '');
if (contractState === V1_ContractState.PENDING_DATA_OWNER_APPROVAL ||
contractState === V1_ContractState.COMPLETED) {
if (task) {
return (_jsxs(Box, { className: "marketplace-lakehouse-entitlements__data-contract-viewer__task-approval-view", children: [_jsxs(Box, { children: ["Approved by", ' ', legendUser ? (_jsx(UserDisplay, { user: legendUser, imgSrc: userProfileImageUrl?.replace('{userId}', legendUser.id), onClick: () => onUserClick?.(legendUser.id) })) : (approverId)] }), _jsx(Box, { className: "marketplace-lakehouse-entitlements__data-contract-viewer__task-approval-view__timestamp", children: formatDate(new Date(task.rec.eventPayload.eventTimestamp), `MM/dd/yyyy HH:mm:ss`) })] }));
}
else {
return _jsx(Box, { children: "Approved" });
}
}
else if (contractState === V1_ContractState.REJECTED) {
if (task) {
return (_jsxs(Box, { className: "marketplace-lakehouse-entitlements__data-contract-viewer__task-approval-view", children: [_jsxs(Box, { children: ["Rejected by", ' ', legendUser ? (_jsx(UserDisplay, { user: legendUser, imgSrc: userProfileImageUrl?.replace('{userId}', legendUser.id), onClick: () => onUserClick?.(legendUser.id) })) : (approverId)] }), _jsx(Box, { className: "marketplace-lakehouse-entitlements__data-contract-viewer__task-approval-view__timestamp", children: formatDate(new Date(task.rec.eventPayload.eventTimestamp), `MM/dd/yyyy HH:mm:ss`) })] }));
}
else {
return _jsx(Box, { children: "Rejected" });
}
}
else {
return undefined;
}
};
export const EntitlementsDataContractViewer = observer((props) => {
const { open, currentViewer, dataProductGroupAccessState, dataProductViewerState, onClose, } = props;
const auth = useAuth();
const legendMarketplaceStore = useLegendMarketplaceBaseStore();
const [userDataMap, setUserDataMap] = useState(new Map());
const [isLoadingUserData, setIsLoadingUserData] = useState(false);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
if (!currentViewer.initializationState.hasCompleted) {
setIsLoading(true);
flowResult(currentViewer.init(auth.user?.access_token))
.catch(legendMarketplaceStore.applicationStore.alertUnhandledError)
.finally(() => setIsLoading(false));
}
}, [
currentViewer,
auth.user?.access_token,
legendMarketplaceStore.applicationStore.alertUnhandledError,
]);
useEffect(() => {
const fetchUserData = async (userIds) => {
const userSearchService = legendMarketplaceStore.userSearchService;
if (userSearchService) {
setIsLoadingUserData(true);
try {
const users = (await Promise.all(userIds.map(async (userId) => getUserById(userId, userSearchService)))).filter(isNonNullable);
const userMap = new Map();
users.forEach((user) => {
userMap.set(user.id, user);
});
setUserDataMap(userMap);
}
finally {
setIsLoadingUserData(false);
}
}
};
const userIds = [
currentViewer.value.createdBy,
...(currentViewer.value.consumer instanceof V1_AdhocTeam
? currentViewer.value.consumer.users
.map((user) => user.userType === V1_UserType.WORKFORCE_USER
? user.name
: undefined)
.filter(isNonNullable)
: []),
...(currentViewer.associatedTasks
?.map((task) => task.assignees)
.flat() ?? []),
];
// eslint-disable-next-line no-void
void fetchUserData(userIds);
}, [
legendMarketplaceStore.userSearchService,
currentViewer.associatedTasks,
currentViewer.value.consumer,
currentViewer.value.createdBy,
]);
const refresh = async () => {
setIsLoading(true);
await flowResult(dataProductViewerState?.fetchContracts(auth.user?.access_token));
if (dataProductGroupAccessState?.associatedContract) {
dataProductViewerState?.setDataContract(dataProductGroupAccessState.associatedContract);
}
await flowResult(currentViewer.init(auth.user?.access_token))
.catch(legendMarketplaceStore.applicationStore.alertUnhandledError)
.finally(() => setIsLoading(false));
};
if (!(currentViewer.value.resource instanceof V1_AccessPointGroupReference)) {
return (_jsxs(Dialog, { open: true, onClose: onClose, fullWidth: true, maxWidth: "md", children: [_jsx(DialogTitle, { children: "Data Contract Request" }), _jsx(IconButton, { onClick: onClose, className: "marketplace-dialog-close-btn", children: _jsx(CloseIcon, {}) }), _jsx(DialogContent, { className: "marketplace-lakehouse-entitlements__data-contract-viewer__content", children: "Unable to display data contract request details for this resource." })] }));
}
const dataProduct = currentViewer.value.resource.dataProduct;
const accessPointGroup = currentViewer.value.resource.accessPointGroup;
const currentState = currentViewer.value.state;
const privilegeManagerApprovalTask = currentViewer.associatedTasks?.find((task) => task.rec.type === V1_ApprovalType.CONSUMER_PRIVILEGE_MANAGER_APPROVAL);
const dataOwnerApprovalTask = currentViewer.associatedTasks?.find((task) => task.rec.type === V1_ApprovalType.DATA_OWNER_APPROVAL);
const currentTask = currentState === V1_ContractState.OPEN_FOR_PRIVILEGE_MANAGER_APPROVAL
? privilegeManagerApprovalTask
: currentState === V1_ContractState.PENDING_DATA_OWNER_APPROVAL
? dataOwnerApprovalTask
: undefined;
const copyTaskLink = (text) => {
legendMarketplaceStore.applicationStore.clipboardService
.copyTextToClipboard(text)
.then(() => legendMarketplaceStore.applicationStore.notificationService.notifySuccess('Task Link Copied to Clipboard', undefined, 2500))
.catch(legendMarketplaceStore.applicationStore.alertUnhandledError);
};
const openUserDirectoryLink = (userId) => legendMarketplaceStore.applicationStore.navigationService.navigator.visitAddress(`${legendMarketplaceStore.applicationStore.config.lakehouseEntitlementsConfig?.applicationDirectoryUrl}/${userId}`);
const steps = [
{ key: 'submitted', isCompleteOrActive: true, label: _jsx(_Fragment, { children: "Submitted" }) },
{
key: 'privilege-manager-approval',
label: currentState ===
V1_ContractState.OPEN_FOR_PRIVILEGE_MANAGER_APPROVAL &&
currentTask ? (_jsxs(_Fragment, { children: [_jsx(Link, { href: legendMarketplaceStore.applicationStore.navigationService.navigator.generateAddress(generateLakehouseTaskPath(currentTask.rec.taskId)), target: "_blank", rel: "noopener noreferrer", children: "Privilege Manager Approval" }), _jsx(IconButton, { onClick: () => copyTaskLink(legendMarketplaceStore.applicationStore.navigationService.navigator.generateAddress(generateLakehouseTaskPath(currentTask.rec.taskId))), children: _jsx(CopyIcon, {}) })] })) : (_jsx(_Fragment, { children: "Privilege Manager Approval" })),
isCompleteOrActive: currentState ===
V1_ContractState.OPEN_FOR_PRIVILEGE_MANAGER_APPROVAL ||
isContractStateComplete(currentState, V1_ContractState.OPEN_FOR_PRIVILEGE_MANAGER_APPROVAL),
description: currentState ===
V1_ContractState.OPEN_FOR_PRIVILEGE_MANAGER_APPROVAL ? (currentTask ? (_jsx(AssigneesList, { users: currentTask.assignees.map((asignee) => userDataMap.get(asignee) ?? asignee), userProfileImageUrl: legendMarketplaceStore.applicationStore.config
.marketplaceUserProfileImageUrl, onUserClick: openUserDirectoryLink })) : (_jsx("span", { children: "No tasks associated with contract" }))) : currentState === V1_ContractState.PENDING_DATA_OWNER_APPROVAL ||
currentState === V1_ContractState.COMPLETED ||
currentState === V1_ContractState.REJECTED ? (_jsx(TaskApprovalView, { contractState: currentState, task: privilegeManagerApprovalTask, userDataMap: userDataMap, userProfileImageUrl: legendMarketplaceStore.applicationStore.config
.marketplaceUserProfileImageUrl, onUserClick: openUserDirectoryLink })) : undefined,
},
{
key: 'data-producer-approval',
label: currentState === V1_ContractState.PENDING_DATA_OWNER_APPROVAL &&
currentTask ? (_jsxs(_Fragment, { children: [_jsx(Link, { href: legendMarketplaceStore.applicationStore.navigationService.navigator.generateAddress(generateLakehouseTaskPath(currentTask.rec.taskId)), target: "_blank", rel: "noopener noreferrer", children: "Data Producer Approval" }), _jsx(IconButton, { onClick: () => copyTaskLink(legendMarketplaceStore.applicationStore.navigationService.navigator.generateAddress(generateLakehouseTaskPath(currentTask.rec.taskId))), children: _jsx(CopyIcon, {}) })] })) : (_jsx(_Fragment, { children: "Data Producer Approval" })),
isCompleteOrActive: currentState === V1_ContractState.PENDING_DATA_OWNER_APPROVAL ||
isContractStateComplete(currentState, V1_ContractState.PENDING_DATA_OWNER_APPROVAL),
description: currentState === V1_ContractState.PENDING_DATA_OWNER_APPROVAL ? (currentTask ? (_jsx(AssigneesList, { users: currentTask.assignees.map((asignee) => userDataMap.get(asignee) ?? asignee), userProfileImageUrl: legendMarketplaceStore.applicationStore.config
.marketplaceUserProfileImageUrl, onUserClick: openUserDirectoryLink })) : (_jsx("span", { children: "No tasks associated with contract" }))) : currentState === V1_ContractState.COMPLETED ||
currentState === V1_ContractState.REJECTED ? (_jsx(TaskApprovalView, { contractState: currentState, task: dataOwnerApprovalTask, userDataMap: userDataMap, userProfileImageUrl: legendMarketplaceStore.applicationStore.config
.marketplaceUserProfileImageUrl, onUserClick: openUserDirectoryLink })) : undefined,
},
{
key: 'complete',
isCompleteOrActive: currentState === V1_ContractState.COMPLETED ||
isContractStateComplete(currentState, V1_ContractState.COMPLETED),
label: _jsx(_Fragment, { children: "Complete" }),
},
];
return (_jsxs(Dialog, { open: open, onClose: onClose, fullWidth: true, maxWidth: "md", children: [_jsxs(DialogTitle, { children: [isContractInTerminalState(currentViewer.value) ? '' : 'Pending ', "Data Contract Request"] }), _jsx(IconButton, { onClick: onClose, className: "marketplace-dialog-close-btn", children: _jsx(CloseIcon, {}) }), _jsxs(DialogContent, { className: "marketplace-lakehouse-entitlements__data-contract-viewer__content", children: [_jsx(CubesLoadingIndicator, { isLoading: isLoading, children: _jsx(CubesLoadingIndicatorIcon, {}) }), !isLoading && (_jsxs(_Fragment, { children: [_jsxs("div", { children: ["Access request for", ' ', _jsx("span", { className: "marketplace-lakehouse-text__emphasis", children: accessPointGroup }), ' ', "Access Point Group in", ' ', _jsx("span", { className: "marketplace-lakehouse-text__emphasis", children: dataProduct.name }), ' ', "Data Product"] }), _jsxs(Box, { className: "marketplace-lakehouse-entitlements__data-contract-viewer__metadata", children: [_jsxs("div", { className: "marketplace-lakehouse-entitlements__data-contract-viewer__metadata__ordered-by", children: [_jsx("b", { children: "Ordered By: " }), isLoadingUserData ? (_jsx(CircularProgress, { size: 20 })) : userDataMap.get(currentViewer.value.createdBy) ? (_jsx(UserDisplay, { user: guaranteeNonNullable(userDataMap.get(currentViewer.value.createdBy)), imgSrc: legendMarketplaceStore.applicationStore.config.marketplaceUserProfileImageUrl?.replace('{userId}', userDataMap.get(currentViewer.value.createdBy)?.id ??
''), onClick: () => openUserDirectoryLink(guaranteeNonNullable(userDataMap.get(currentViewer.value.createdBy)).id) })) : (currentViewer.value.createdBy)] }), _jsxs("div", { className: "marketplace-lakehouse-entitlements__data-contract-viewer__metadata__ordered-for", children: [_jsx("b", { children: "Ordered For: " }), isLoadingUserData ? (_jsx(CircularProgress, { size: 20 })) : currentViewer.value.consumer instanceof V1_AdhocTeam ? (currentViewer.value.consumer.users.map((user, index) => {
const userData = userDataMap.get(user.name);
if (userData) {
return (_jsx(UserDisplay, { user: userData, imgSrc: legendMarketplaceStore.applicationStore.config.marketplaceUserProfileImageUrl?.replace('{userId}', userDataMap.get(user.name)?.id ?? ''), onClick: () => openUserDirectoryLink(userData.id) }, user.name));
}
else {
return `${user.name}${index < currentViewer.value.consumer.users.length - 1 ? ', ' : ''}`;
}
})) : (stringifyOrganizationalScope(currentViewer.value.consumer))] }), _jsxs("div", { children: [_jsx("b", { children: "Business Justification: " }), currentViewer.value.description] })] }), !isContractInTerminalState(currentViewer.value) && (_jsx(Box, { className: "marketplace-lakehouse-entitlements__data-contract-viewer__refresh-btn", children: _jsx(Button, { size: "small", variant: "outlined", startIcon: _jsx(RefreshIcon, {}), onClick: () => {
// eslint-disable-next-line no-void
void refresh();
}, children: "Refresh" }) })), _jsx(Box, { className: "marketplace-lakehouse-entitlements__data-contract-viewer__timeline", children: _jsx(Timeline, { children: steps.map((step, index) => (_jsxs(TimelineItem, { children: [_jsx(TimelineOppositeContent, { className: "marketplace-lakehouse-entitlements__data-contract-viewer__timeline__content", children: step.label }), _jsxs(TimelineSeparator, { children: [_jsx(TimelineDot, { color: "primary", variant: step.isCompleteOrActive ? 'filled' : 'outlined' }), index < steps.length - 1 && _jsx(TimelineConnector, {})] }), _jsx(TimelineContent, { className: "marketplace-lakehouse-entitlements__data-contract-viewer__timeline__content", children: step.description })] }, step.key))) }) })] })), _jsxs(Box, { className: "marketplace-lakehouse-entitlements__data-contract-viewer__footer", children: ["Contract ID: ", currentViewer.value.guid] })] })] }));
});
//# sourceMappingURL=EntitlementsDataContractViewer.js.map