@finos/legend-application-marketplace
Version:
Legend Marketplace application core
273 lines • 21.2 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 { 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