UNPKG

@finos/legend-application-marketplace

Version:
201 lines 18.8 kB
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