Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ui): supported stored procedure in database #13031

Merged
merged 13 commits into from
Sep 4, 2023
Merged
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { Database } from 'generated/entity/data/database';
import { DatabaseSchema } from 'generated/entity/data/databaseSchema';
import { Mlmodel } from 'generated/entity/data/mlmodel';
import { Pipeline } from 'generated/entity/data/pipeline';
import { StoredProcedure } from 'generated/entity/data/storedProcedure';
import { Table } from 'generated/entity/data/table';
import { Topic } from 'generated/entity/data/topic';
import { DashboardService } from 'generated/entity/services/dashboardService';
Expand All @@ -43,6 +44,7 @@ export type DataAssetsType =
| Container
| Database
| DashboardDataModel
| StoredProcedure
| DatabaseSchema
| DatabaseService
| MessagingService
Expand Down Expand Up @@ -90,6 +92,7 @@ export type DataAssetsHeaderProps = {
| DataAssetMlmodel
| DataAssetContainer
| DataAssetDashboardDataModel
| DataAssetStoredProcedure
| DataAssetDatabase
| DataAssetDatabaseSchema
| DataAssetDatabaseService
Expand Down Expand Up @@ -135,6 +138,11 @@ export interface DataAssetDashboardDataModel {
entityType: EntityType.DASHBOARD_DATA_MODEL;
}

export interface DataAssetStoredProcedure {
dataAsset: StoredProcedure;
entityType: EntityType.STORED_PROCEDURE;
}

export interface DataAssetDatabase {
dataAsset: Database;
entityType: EntityType.DATABASE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ import DashboardSummary from 'components/Explore/EntitySummaryPanel/DashboardSum
import DataModelSummary from 'components/Explore/EntitySummaryPanel/DataModelSummary/DataModelSummary.component';
import MlModelSummary from 'components/Explore/EntitySummaryPanel/MlModelSummary/MlModelSummary.component';
import PipelineSummary from 'components/Explore/EntitySummaryPanel/PipelineSummary/PipelineSummary.component';
import StoredProcedureSummary from 'components/Explore/EntitySummaryPanel/StoredProcedureSummary/StoredProcedureSummary.component';
import TableSummary from 'components/Explore/EntitySummaryPanel/TableSummary/TableSummary.component';
import TopicSummary from 'components/Explore/EntitySummaryPanel/TopicSummary/TopicSummary.component';
import { FQN_SEPARATOR_CHAR } from 'constants/char.constants';
import { Container } from 'generated/entity/data/container';
import { DashboardDataModel } from 'generated/entity/data/dashboardDataModel';
import { Mlmodel } from 'generated/entity/data/mlmodel';
import { StoredProcedure } from 'generated/entity/data/storedProcedure';
import { EntityDetailUnion } from 'Models';
import React, { useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
Expand All @@ -33,6 +35,7 @@ import { getDataModelsByName } from 'rest/dataModelsAPI';
import { getMlModelByFQN } from 'rest/mlModelAPI';
import { getPipelineByFqn } from 'rest/pipelineAPI';
import { getContainerByName } from 'rest/storageAPI';
import { getStoredProceduresByName } from 'rest/storedProceduresAPI';
import { getTableDetailsByFQN } from 'rest/tableAPI';
import { getTopicByFqn } from 'rest/topicsAPI';
import { EntityType } from '../../../enums/entity.enum';
Expand Down Expand Up @@ -130,6 +133,12 @@ const EntityInfoDrawer = ({

break;
}

case EntityType.STORED_PROCEDURE: {
response = await getStoredProceduresByName(encodedFqn, 'owner,tags');

break;
}
default:
break;
}
Expand Down Expand Up @@ -221,6 +230,16 @@ const EntityInfoDrawer = ({
/>
);

case EntityType.STORED_PROCEDURE:
return (
<StoredProcedureSummary
componentType={DRAWER_NAVIGATION_OPTIONS.lineage}
entityDetails={entityDetail as StoredProcedure}
isLoading={isLoading}
tags={tags}
/>
);

default:
return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
* Copyright 2023 Collate.
* 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 { Col, Divider, Row, Typography } from 'antd';
import { ReactComponent as IconExternalLink } from 'assets/svg/external-links.svg';
import classNames from 'classnames';
import SummaryTagsDescription from 'components/common/SummaryTagsDescription/SummaryTagsDescription.component';
import SchemaEditor from 'components/schema-editor/SchemaEditor';
import SummaryPanelSkeleton from 'components/Skeleton/SummaryPanelSkeleton/SummaryPanelSkeleton.component';
import { CSMode } from 'enums/codemirror.enum';
import { ExplorePageTabs } from 'enums/Explore.enum';
import {
StoredProcedure,
StoredProcedureCodeObject,
} from 'generated/entity/data/storedProcedure';
import { isEmpty, isObject } from 'lodash';
import React, { useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom';
import {
DRAWER_NAVIGATION_OPTIONS,
getEntityOverview,
} from 'utils/EntityUtils';
import { StoredProcedureSummaryProps } from './StoredProcedureSummary.interface';

const StoredProcedureSummary = ({
entityDetails,
componentType = DRAWER_NAVIGATION_OPTIONS.explore,
tags,
isLoading,
}: StoredProcedureSummaryProps) => {
const { t } = useTranslation();
const [storedProcedureDetails, setStoredProcedureDetails] =
Ashish8689 marked this conversation as resolved.
Show resolved Hide resolved
useState<StoredProcedure>(entityDetails);

const entityInfo = useMemo(
() =>
getEntityOverview(
ExplorePageTabs.STORED_PROCEDURE,
storedProcedureDetails
),
[storedProcedureDetails]
);

useEffect(() => {
if (!isEmpty(entityDetails)) {
setStoredProcedureDetails(entityDetails);
}
}, [entityDetails]);
Ashish8689 marked this conversation as resolved.
Show resolved Hide resolved

return (
<SummaryPanelSkeleton
loading={isLoading || isEmpty(storedProcedureDetails)}>
<>
<Row className="m-md" gutter={[0, 4]}>
<Col span={24}>
<Row gutter={[0, 4]}>
{entityInfo.map((info) => {
const isOwner = info.name === t('label.owner');

return info.visible?.includes(componentType) ? (
<Col key={info.name} span={24}>
<Row
className={classNames('', {
'p-b-md': isOwner,
})}
gutter={[16, 32]}>
{!isOwner ? (
<Col data-testid={`${info.name}-label`} span={8}>
<Typography.Text className="text-grey-muted">
{info.name}
</Typography.Text>
</Col>
) : null}
<Col data-testid={`${info.name}-value`} span={16}>
{info.isLink ? (
<Link
component={Typography.Link}
target={info.isExternal ? '_blank' : '_self'}
to={{ pathname: info.url }}>
{info.value}
{info.isExternal ? (
<IconExternalLink className="m-l-xs" width={12} />
) : null}
</Link>
) : (
<Typography.Text
className={classNames('text-grey-muted', {
'text-grey-body': !isOwner,
})}>
{info.value}
</Typography.Text>
)}
</Col>
</Row>
</Col>
) : null;
})}
</Row>
</Col>
</Row>

<Divider className="m-y-xs" />

<SummaryTagsDescription
entityDetail={entityDetails}
tags={tags ? tags : []}
/>
<Divider className="m-y-xs" />

{isObject(entityDetails.storedProcedureCode) && (
<Row className="m-md" gutter={[0, 8]}>
<Col span={24}>
<Typography.Text
className="text-base text-grey-muted"
data-testid="column-header">
{t('label.code')}
</Typography.Text>
</Col>
<Col span={24}>
<SchemaEditor
editorClass="custom-code-mirror-theme custom-query-editor"
mode={{ name: CSMode.SQL }}
options={{
styleActiveLine: false,
readOnly: 'nocursor',
}}
value={
(
entityDetails.storedProcedureCode as StoredProcedureCodeObject
).code ?? ''
}
/>
</Col>
</Row>
)}
</>
</SummaryPanelSkeleton>
);
};

export default StoredProcedureSummary;
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright 2023 Collate.
* 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 { StoredProcedure } from 'generated/entity/data/storedProcedure';
import { TagLabel } from 'generated/type/tagLabel';

export interface StoredProcedureSummaryProps {
entityDetails: StoredProcedure;
componentType?: string;
tags?: TagLabel[];
isLoading?: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { DashboardDataModel } from 'generated/entity/data/dashboardDataModel';
import { Database } from 'generated/entity/data/database';
import { DatabaseSchema } from 'generated/entity/data/databaseSchema';
import { Glossary } from 'generated/entity/data/glossary';
import { StoredProcedure } from 'generated/entity/data/storedProcedure';
import { QueryFilterInterface } from 'pages/explore/ExplorePage.interface';
import { SearchIndex } from '../../enums/search.enum';
import { Dashboard } from '../../generated/entity/data/dashboard';
Expand Down Expand Up @@ -120,7 +121,8 @@ export type EntityUnion =
| Database
| Glossary
| Tag
| DashboardDataModel;
| DashboardDataModel
| StoredProcedure;

export type EntityWithServices =
| Topic
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export enum ResourceEntity {
QUERY = 'query',
DASHBOARD_DATA_MODEL = 'dashboardDataModel',
EVENT_SUBSCRIPTION = 'eventsubscription',
STORED_PROCEDURE = 'storedProcedure',
}

export interface PermissionContextType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/

import { Container } from 'generated/entity/data/container';
import { StoredProcedure } from 'generated/entity/data/storedProcedure';
import { EntityType } from '../../../enums/entity.enum';
import { Dashboard } from '../../../generated/entity/data/dashboard';
import { Mlmodel } from '../../../generated/entity/data/mlmodel';
Expand All @@ -24,7 +25,8 @@ export type EntityDetails = Table &
Dashboard &
Pipeline &
Mlmodel &
Container;
Container &
StoredProcedure;

export interface CustomPropertyProps {
isVersionView?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ const DataModelDetailsPage = withSuspenseFallback(
React.lazy(() => import('pages/DataModelPage/DataModelPage.component'))
);

const StoredProcedureDetailsPage = withSuspenseFallback(
React.lazy(() => import('pages/StoredProcedure/StoredProcedurePage'))
);

const TableDetailsPageV1 = withSuspenseFallback(
React.lazy(() => import('pages/TableDetailsPageV1/TableDetailsPageV1'))
);
Expand Down Expand Up @@ -461,6 +465,23 @@ const AuthenticatedAppRouter: FunctionComponent = () => {
component={DataModelDetailsPage}
path={ROUTES.DATA_MODEL_DETAILS_WITH_SUB_TAB}
/>

<Route
exact
component={StoredProcedureDetailsPage}
path={ROUTES.STORED_PROCEDURE_DETAILS}
/>
<Route
exact
component={StoredProcedureDetailsPage}
path={ROUTES.STORED_PROCEDURE_DETAILS_WITH_TAB}
/>
<Route
exact
component={StoredProcedureDetailsPage}
path={ROUTES.STORED_PROCEDURE_DETAILS_WITH_SUB_TAB}
/>

<Route
exact
component={PipelineDetailsPage}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,12 @@ export const PAGE_HEADERS = {
entity: i18n.t('label.container-plural'),
}),
},
STORED_PROCEDURE_CUSTOM_ATTRIBUTES: {
header: i18n.t('label.stored-procedure'),
subHeader: i18n.t('message.define-custom-property-for-entity', {
entity: i18n.t('label.label.stored-procedure'),
}),
},
BOTS: {
header: i18n.t('label.bot-plural'),
subHeader: i18n.t('message.page-sub-header-for-bots'),
Expand Down
Loading