UNPKG

@finos/legend-application-marketplace

Version:
273 lines 21.2 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 { AnchorLinkIcon, CaretDownIcon, clsx, CubesLoadingIndicator, CubesLoadingIndicatorIcon, MarkdownTextViewer, QuestionCircleIcon, } from '@finos/legend-art'; import { observer } from 'mobx-react-lite'; import { DATA_PRODUCT_VIEWER_ACTIVITY_MODE, generateAnchorForActivity, } from '../../../stores/lakehouse/DataProductViewerNavigation.js'; import { useEffect, useRef, useState } from 'react'; import { useApplicationStore } from '@finos/legend-application'; import { DataProductGroupAccess, } from '../../../stores/lakehouse/DataProductDataAccessState.js'; import { DataGrid, } from '@finos/legend-lego/data-grid'; import { extractElementNameFromPath, PureClientVersion, V1_AppliedFunction, V1_AppliedProperty, V1_CBoolean, V1_CByteArray, V1_CDateTime, V1_CDecimal, V1_CFloat, V1_CInteger, V1_CStrictDate, V1_CStrictTime, V1_CString, V1_EnumValue, V1_getGenericTypeFullPath, V1_LambdaReturnTypeInput, V1_LegendSDLC, V1_Protocol, V1_PureGraphManager, V1_PureModelContextPointer, V1_relationTypeModelSchema, V1_RenderStyle, V1_serializeRawValueSpecification, } from '@finos/legend-graph'; import { CodeEditor } from '@finos/legend-lego/code-editor'; import { CODE_EDITOR_LANGUAGE, CODE_EDITOR_THEME, } from '@finos/legend-code-editor'; import { Box, Button, ButtonGroup, Menu, MenuItem, Tab, Tabs, } from '@mui/material'; import { useLegendMarketplaceBaseStore } from '../../../application/LegendMarketplaceFrameworkProvider.js'; import { EntitlementsDataContractCreator } from '../entitlements/EntitlementsDataContractCreator.js'; import { EntitlementsDataContractViewer } from '../entitlements/EntitlementsDataContractViewer.js'; import { EntitlementsDataContractViewerState } from '../../../stores/lakehouse/entitlements/EntitlementsDataContractViewerState.js'; import { useAuth } from 'react-oidc-context'; import { DataProductSubscriptionViewer } from '../subscriptions/DataProductSubscriptionsViewer.js'; import { assertErrorThrown, guaranteeType } from '@finos/legend-shared'; import { resolveVersion } from '@finos/legend-server-depot'; import { deserialize } from 'serializr'; const MAX_GRID_AUTO_HEIGHT_ROWS = 10; // Maximum number of rows to show before switching to normal height (scrollable grid) export const DataProductMarkdownTextViewer = (props) => (_jsx(MarkdownTextViewer, { className: "data-space__viewer__markdown-text-viewer", value: { value: props.value, }, components: { h1: 'h2', h2: 'h3', h3: 'h4', } })); const TDSColumnDocumentationCellRenderer = (params) => { const data = params.data; if (!data) { return null; } return data.description?.trim() ? (data.description) : (_jsx("div", { className: "data-space__viewer__grid__empty-cell", children: "No description to provide" })); }; const TDSColumnMoreInfoCellRenderer = (props) => { const { params, accessGroupState } = props; const data = params.data; const store = useLegendMarketplaceBaseStore(); let MoreInfoTabs; (function (MoreInfoTabs) { MoreInfoTabs["COLUMNS"] = "Columns"; MoreInfoTabs["GRAMMAR"] = "Grammar"; })(MoreInfoTabs || (MoreInfoTabs = {})); const [selectedTab, setSelectedTab] = useState(MoreInfoTabs.COLUMNS); const handleTabChange = (event, newValue) => { setSelectedTab(newValue); }; const [accessPointGrammar, setAccessPointGrammar] = useState('Loading ...'); const [accessPointRelationType, setAccessPointRelationType] = useState(); const [loadingAccessPointDetails, setLoadingAccessPointDetails] = useState(false); useEffect(() => { if (!data) { return; } const fetchAccessPointGrammar = async () => { try { const grammar = await store.engineServerClient.JSONToGrammar_lambda(V1_serializeRawValueSpecification(data.func), V1_RenderStyle.PRETTY); setAccessPointGrammar(grammar); } catch { throw new Error('Error fetching access point grammar'); } }; const fetchAccessPointRelationType = async () => { try { const model = accessGroupState.accessState.viewerState.isSandboxProduct ? guaranteeType(accessGroupState.accessState.viewerState.graphManagerState .graphManager, V1_PureGraphManager).getFullGraphModelData(accessGroupState.accessState.viewerState.graphManagerState.graph) : new V1_PureModelContextPointer( // TODO: remove as backend should handle undefined protocol input new V1_Protocol(V1_PureGraphManager.PURE_PROTOCOL_NAME, PureClientVersion.VX_X_X), new V1_LegendSDLC(accessGroupState.accessState.viewerState.project.groupId, accessGroupState.accessState.viewerState.project.artifactId, resolveVersion(accessGroupState.accessState.viewerState.project.versionId))); const relationTypeInput = new V1_LambdaReturnTypeInput(model, data.func); const relationType = deserialize(V1_relationTypeModelSchema, await store.engineServerClient.lambdaRelationType(V1_LambdaReturnTypeInput.serialization.toJson(relationTypeInput))); setAccessPointRelationType(relationType); } catch { throw new Error('Error fetching access point relation type'); } }; const fetchAccessPointDetails = async () => { return Promise.all([ fetchAccessPointGrammar(), fetchAccessPointRelationType(), ]); }; setLoadingAccessPointDetails(true); fetchAccessPointDetails() .catch((error) => { assertErrorThrown(error); accessGroupState.accessState.viewerState.applicationStore.notificationService.notifyError(error); }) .finally(() => { setLoadingAccessPointDetails(false); }); }, [data, store, accessGroupState]); if (!data) { return null; } const relationColumnDefs = [ { headerName: 'Column Name', field: 'name', flex: 1, }, { headerName: 'Column Type', flex: 1, valueGetter: (_params) => _params.data ? `${extractElementNameFromPath(V1_getGenericTypeFullPath(_params.data.genericType))}${_params.data.genericType.typeVariableValues.length > 0 ? `(${_params.data.genericType.typeVariableValues .map((valueSpec) => { // TODO: Move V1_stringifyValueSpecification out of // @finos/legend-query-builder so it can be used in other packages if (valueSpec instanceof V1_CDateTime || valueSpec instanceof V1_CStrictDate || valueSpec instanceof V1_CStrictTime || valueSpec instanceof V1_CString || valueSpec instanceof V1_CBoolean || valueSpec instanceof V1_CByteArray || valueSpec instanceof V1_CDecimal || valueSpec instanceof V1_CFloat || valueSpec instanceof V1_CFloat || valueSpec instanceof V1_CInteger || valueSpec instanceof V1_EnumValue) { return valueSpec.value.toString(); } else if (valueSpec instanceof V1_AppliedProperty) { return valueSpec.property; } else if (valueSpec instanceof V1_AppliedFunction) { return valueSpec.function; } else { return ''; } }) .join(',')})` : ''}` : '', }, ]; return (_jsxs("div", { children: [_jsxs(Tabs, { value: selectedTab, onChange: handleTabChange, children: [_jsx(Tab, { label: MoreInfoTabs.COLUMNS, value: MoreInfoTabs.COLUMNS }), _jsx(Tab, { label: MoreInfoTabs.GRAMMAR, value: MoreInfoTabs.GRAMMAR })] }), _jsxs(Box, { className: "data-space__viewer__more-info__container", children: [loadingAccessPointDetails && (_jsx(Box, { className: "data-space__viewer__more-info__loading-indicator", children: _jsx(CubesLoadingIndicator, { isLoading: true, children: _jsx(CubesLoadingIndicatorIcon, {}) }) })), !loadingAccessPointDetails && (_jsxs(_Fragment, { children: [selectedTab === MoreInfoTabs.COLUMNS && (_jsx(Box, { className: clsx('data-space__viewer__more-info__columns-grid', { 'data-space__viewer__more-info__columns-grid--auto-height': (accessPointRelationType?.columns.length ?? 0) <= MAX_GRID_AUTO_HEIGHT_ROWS, 'data-space__viewer__more-info__columns-grid--auto-height--empty': (accessPointRelationType?.columns.length ?? 0) === 0, 'data-space__viewer__more-info__columns-grid--auto-height--non-empty': (accessPointRelationType?.columns.length ?? 0) > 0 && (accessPointRelationType?.columns.length ?? 0) <= MAX_GRID_AUTO_HEIGHT_ROWS, }), children: _jsx(DataGrid, { rowData: accessPointRelationType?.columns ?? [], columnDefs: relationColumnDefs, domLayout: (accessPointRelationType?.columns.length ?? 0) > MAX_GRID_AUTO_HEIGHT_ROWS ? 'normal' : 'autoHeight' }) })), selectedTab === MoreInfoTabs.GRAMMAR && (_jsx(Box, { className: "data-space__viewer__more-info__grammar", children: _jsx(CodeEditor, { inputValue: accessPointGrammar, isReadOnly: true, language: CODE_EDITOR_LANGUAGE.TEXT, hideMinimap: true, hideGutter: true, hideActionBar: true, lightTheme: CODE_EDITOR_THEME.GITHUB_LIGHT, extraEditorOptions: { scrollBeyondLastLine: false, wordWrap: 'on', } }) }))] }))] })] })); }; export const DataProductAccessPointGroupViewer = observer((props) => { const { accessGroupState } = props; const accessPoints = accessGroupState.group.accessPoints; const auth = useAuth(); const [showSubscriptionsModal, setShowSubscriptionsModal] = useState(false); const [isEntitledButtonGroupMenuOpen, setIsEntitledButtonGroupMenuOpen] = useState(false); const entitledButtonGroupRef = useRef(null); useEffect(() => { if (accessGroupState.access === DataProductGroupAccess.COMPLETED && accessGroupState.associatedContract && accessGroupState.fetchingSubscriptionsState.isInInitialState) { accessGroupState.fetchSubscriptions(accessGroupState.associatedContract.guid, auth.user?.access_token); } }); const handleContractsClick = () => { accessGroupState.handleContractClick(); }; const handleSubscriptionsClick = () => { setShowSubscriptionsModal(true); }; const renderAccess = (val) => { switch (val) { case DataProductGroupAccess.UNKNOWN: return (_jsx(Button, { variant: "contained", color: "info", loading: accessGroupState.fetchingAccessState.isInProgress, children: "UNKNOWN" })); case DataProductGroupAccess.NO_ACCESS: return (_jsx(Button, { variant: "contained", color: "error", onClick: handleContractsClick, loading: accessGroupState.fetchingAccessState.isInProgress, children: "REQUEST ACCESS" })); case DataProductGroupAccess.PENDING_MANAGER_APPROVAL: case DataProductGroupAccess.PENDING_DATA_OWNER_APPROVAL: return (_jsx(Button, { variant: "contained", color: "primary", onClick: handleContractsClick, loading: accessGroupState.fetchingAccessState.isInProgress, children: _jsx("div", { children: val === DataProductGroupAccess.PENDING_MANAGER_APPROVAL ? 'PENDING MANAGER APPROVAL' : 'PENDING DATA OWNER APPROVAL' }) })); case DataProductGroupAccess.COMPLETED: return (_jsxs(_Fragment, { children: [_jsxs(ButtonGroup, { variant: "contained", color: "success", ref: entitledButtonGroupRef, children: [_jsx(Button, { onClick: handleContractsClick, loading: accessGroupState.fetchingAccessState.isInProgress, children: "ENTITLED" }), _jsx(Button, { size: "small", onClick: () => setIsEntitledButtonGroupMenuOpen((prev) => !prev), children: _jsx(CaretDownIcon, {}) })] }), _jsx(Menu, { anchorEl: entitledButtonGroupRef.current, open: isEntitledButtonGroupMenuOpen, onClose: () => setIsEntitledButtonGroupMenuOpen(false), children: _jsx(MenuItem, { onClick: () => { accessGroupState.accessState.viewerState.setDataContractAccessPointGroup(accessGroupState.group); setIsEntitledButtonGroupMenuOpen(false); }, children: "Request Access for Others" }) })] })); default: return null; } }; return (_jsxs("div", { className: "data-space__viewer__access-group__item", children: [_jsxs("div", { className: "data-space__viewer__access-group__item__header", children: [_jsxs("div", { className: "data-space__viewer__access-group__item__header-main", children: [_jsx("div", { className: "data-space__viewer__access-group__item__header__title", children: accessGroupState.group.id }), _jsx("div", { className: "data-space__viewer__access-group__item__header__type", children: "LAKEHOUSE" }), _jsx("button", { className: "data-space__viewer__access-group__item__header__anchor", tabIndex: -1, children: _jsx(AnchorLinkIcon, {}) })] }), _jsxs(Box, { className: "data-space__viewer__access-group__item__header__actions", children: [_jsx(Box, { className: "data-space__viewer__access-group__item__header__data-contract", children: renderAccess(accessGroupState.access) }), accessGroupState.access === DataProductGroupAccess.COMPLETED && (_jsx(Box, { className: "data-space__viewer__access-group__item__header__subscription", children: _jsx(Button, { variant: "outlined", color: "info", loading: accessGroupState.fetchingAccessState.isInProgress, onClick: handleSubscriptionsClick, children: "SUBSCRIPTIONS" }) }))] })] }), _jsx("div", { className: "data-space__viewer__access-group__item__description", children: _jsx(DataProductMarkdownTextViewer, { value: accessGroupState.group.description ?? '' }) }), _jsx("div", { className: "data-space__viewer__access-group__item__content", children: _jsx("div", { className: "data-space__viewer__access-group__item__content__tab__content", children: _jsx("div", { className: clsx('data-space__viewer__access-group__tds__column-specs', 'data-space__viewer__grid', 'ag-theme-balham', { 'data-space__viewer__grid--auto-height': accessPoints.length <= MAX_GRID_AUTO_HEIGHT_ROWS, 'data-space__viewer__grid--auto-height--non-empty': accessPoints.length > 0 && accessPoints.length <= MAX_GRID_AUTO_HEIGHT_ROWS, }), children: _jsx(DataGrid, { rowData: accessPoints, gridOptions: { suppressScrollOnNewData: true, getRowId: (rowData) => rowData.data.id, }, suppressFieldDotNotation: true, domLayout: accessPoints.length > MAX_GRID_AUTO_HEIGHT_ROWS ? 'normal' : 'autoHeight', columnDefs: [ { minWidth: 50, sortable: true, resizable: true, field: 'id', headerValueGetter: () => `Access Points`, flex: 1, }, { minWidth: 50, sortable: false, resizable: true, cellRenderer: TDSColumnDocumentationCellRenderer, headerName: 'Description', flex: 1, wrapText: true, autoHeight: true, }, { minWidth: 50, sortable: false, resizable: false, headerClass: 'data-space__viewer__grid__last-column-header', cellRenderer: 'agGroupCellRenderer', headerName: 'More Info', flex: 1, }, ], onRowDataUpdated: (params) => { params.api.refreshCells({ force: true }); }, masterDetail: true, detailCellRenderer: (params) => (_jsx(TDSColumnMoreInfoCellRenderer, { params: params, accessGroupState: accessGroupState })), detailRowAutoHeight: true }) }) }) }), accessGroupState.accessState.viewerState .dataContractAccessPointGroup === accessGroupState.group && (_jsx(EntitlementsDataContractCreator, { open: true, onClose: () => accessGroupState.accessState.viewerState.setDataContractAccessPointGroup(undefined), accessGroupState: accessGroupState })), accessGroupState.accessState.viewerState.dataContract && (_jsx(EntitlementsDataContractViewer, { open: true, currentViewer: new EntitlementsDataContractViewerState(accessGroupState.accessState.viewerState.dataContract, accessGroupState.accessState.viewerState.lakeServerClient), dataProductGroupAccessState: accessGroupState, dataProductViewerState: accessGroupState.accessState.viewerState, onClose: () => accessGroupState.accessState.viewerState.setDataContract(undefined) })), _jsx(DataProductSubscriptionViewer, { open: showSubscriptionsModal, accessGroupState: accessGroupState, onClose: () => setShowSubscriptionsModal(false) })] })); }); export const DataProducteDataAccess = observer((props) => { const { dataProductViewerState } = props; const applicationStore = useApplicationStore(); const documentationUrl = 'todo.com'; const sectionRef = useRef(null); const anchor = generateAnchorForActivity(DATA_PRODUCT_VIEWER_ACTIVITY_MODE.DATA_ACCESS); useEffect(() => { if (sectionRef.current) { dataProductViewerState.layoutState.setWikiPageAnchor(anchor, sectionRef.current); } return () => dataProductViewerState.layoutState.unsetWikiPageAnchor(anchor); }, [dataProductViewerState, anchor]); const seeDocumentation = () => { applicationStore.navigationService.navigator.visitAddress(documentationUrl); }; return (_jsxs("div", { ref: sectionRef, className: "data-space__viewer__wiki__section", children: [_jsxs("div", { className: "data-space__viewer__wiki__section__header", children: [_jsxs("div", { className: "data-space__viewer__wiki__section__header__label", children: ["Data Access", _jsx("button", { className: "data-space__viewer__wiki__section__header__anchor", tabIndex: -1, onClick: () => dataProductViewerState.changeZone(anchor, true), children: _jsx(AnchorLinkIcon, {}) })] }), Boolean(documentationUrl) && (_jsx("button", { className: "data-space__viewer__wiki__section__header__documentation", tabIndex: -1, onClick: seeDocumentation, title: "See Documentation", children: _jsx(QuestionCircleIcon, {}) }))] }), _jsx("div", { className: "data-space__viewer__wiki__section__content", children: _jsx("div", { className: "data-space__viewer__data-access", children: dataProductViewerState.accessState.accessGroupStates.map((groupState) => (_jsx(DataProductAccessPointGroupViewer, { accessGroupState: groupState }, groupState.id))) }) })] })); }); //# sourceMappingURL=DataProductDataAccess.js.map