mirror of
https://github.com/datahub-project/datahub.git
synced 2025-12-25 17:08:29 +00:00
feat(React): Powering lineage page through graphql endpoint (#2099)
This commit is contained in:
parent
2e8ebcf109
commit
a9069d4d94
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Col, Pagination, Row } from 'antd';
|
||||
import { Col, Divider, Pagination, Row } from 'antd';
|
||||
import { Content } from 'antd/lib/layout/layout';
|
||||
import { BrowseResultGroup, EntityType, Entity } from '../../types.generated';
|
||||
import BrowseResultCard from './BrowseResultCard';
|
||||
@ -43,7 +43,10 @@ export const BrowseResults = ({
|
||||
</Col>
|
||||
))}
|
||||
{entities.map((entity) => (
|
||||
<Col span={24}>{entityRegistry.renderBrowse(type, entity)}</Col>
|
||||
<Col span={24}>
|
||||
{entityRegistry.renderBrowse(type, entity)}
|
||||
<Divider />
|
||||
</Col>
|
||||
))}
|
||||
<Col span={24}>
|
||||
<Pagination
|
||||
|
||||
@ -1,33 +1,36 @@
|
||||
import { List, Space, Typography } from 'antd';
|
||||
import React from 'react';
|
||||
import { Dataset, EntityType } from '../../../../types.generated';
|
||||
import { DownstreamLineage, EntityType, UpstreamLineage } from '../../../../types.generated';
|
||||
import { useEntityRegistry } from '../../../useEntityRegistry';
|
||||
import { PreviewType } from '../../Entity';
|
||||
|
||||
export type Props = {
|
||||
upstreamEntities: Dataset[];
|
||||
downstreamEntities: Dataset[];
|
||||
upstreamLineage?: UpstreamLineage | null;
|
||||
downstreamLineage?: DownstreamLineage | null;
|
||||
};
|
||||
|
||||
export default function Lineage({ upstreamEntities, downstreamEntities }: Props) {
|
||||
export default function Lineage({ upstreamLineage, downstreamLineage }: Props) {
|
||||
const entityRegistry = useEntityRegistry();
|
||||
const upstreamEntities = upstreamLineage?.upstreams.map((upstream) => upstream.dataset);
|
||||
const downstreamEntities = downstreamLineage?.downstreams.map((downstream) => downstream.dataset);
|
||||
|
||||
return (
|
||||
<Space direction="vertical" style={{ width: '100%' }} size="large">
|
||||
<List
|
||||
bordered
|
||||
dataSource={upstreamEntities}
|
||||
header={<Typography.Title level={3}>Upstream</Typography.Title>}
|
||||
renderItem={(item) => {
|
||||
return entityRegistry.renderPreview(EntityType.Dataset, PreviewType.PREVIEW, item);
|
||||
}}
|
||||
renderItem={(item) => (
|
||||
<List.Item>{entityRegistry.renderPreview(EntityType.Dataset, PreviewType.PREVIEW, item)}</List.Item>
|
||||
)}
|
||||
/>
|
||||
<List
|
||||
bordered
|
||||
dataSource={downstreamEntities}
|
||||
header={<Typography.Title level={3}>Downstream</Typography.Title>}
|
||||
renderItem={(item) => {
|
||||
return entityRegistry.renderPreview(EntityType.Dataset, PreviewType.PREVIEW, item);
|
||||
}}
|
||||
renderItem={(item) => (
|
||||
<List.Item>{entityRegistry.renderPreview(EntityType.Dataset, PreviewType.PREVIEW, item)}</List.Item>
|
||||
)}
|
||||
/>
|
||||
</Space>
|
||||
);
|
||||
|
||||
@ -7,7 +7,6 @@ import { Dataset } from '../../../../types.generated';
|
||||
import LineageView from './Lineage';
|
||||
import PropertiesView from './Properties';
|
||||
import DocumentsView from './Documentation';
|
||||
import { sampleDownstreamEntities, sampleUpstreamEntities } from './stories/lineageEntities';
|
||||
import DatasetHeader from './DatasetHeader';
|
||||
|
||||
export enum TabType {
|
||||
@ -30,7 +29,14 @@ export const Profile = ({ urn }: { urn: string }): JSX.Element => {
|
||||
|
||||
const getHeader = (dataset: Dataset) => <DatasetHeader dataset={dataset} />;
|
||||
|
||||
const getTabs = ({ ownership, properties, institutionalMemory, schema }: Dataset) => {
|
||||
const getTabs = ({
|
||||
ownership,
|
||||
upstreamLineage,
|
||||
downstreamLineage,
|
||||
properties,
|
||||
institutionalMemory,
|
||||
schema,
|
||||
}: Dataset) => {
|
||||
return [
|
||||
{
|
||||
name: TabType.Ownership,
|
||||
@ -53,12 +59,7 @@ export const Profile = ({ urn }: { urn: string }): JSX.Element => {
|
||||
{
|
||||
name: TabType.Lineage,
|
||||
path: TabType.Lineage.toLowerCase(),
|
||||
content: (
|
||||
<LineageView
|
||||
upstreamEntities={sampleUpstreamEntities}
|
||||
downstreamEntities={sampleDownstreamEntities}
|
||||
/>
|
||||
),
|
||||
content: <LineageView upstreamLineage={upstreamLineage} downstreamLineage={downstreamLineage} />,
|
||||
},
|
||||
{
|
||||
name: TabType.Properties,
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import Lineage from '../Lineage';
|
||||
import { sampleUpstreamEntities, sampleDownstreamEntities } from '../stories/lineageEntities';
|
||||
import { sampleDownstreamLineage, sampleUpstreamLineage } from '../stories/lineageEntities';
|
||||
import TestPageContainer from '../../../../../utils/test-utils/TestPageContainer';
|
||||
|
||||
describe('Lineage', () => {
|
||||
it('renders', () => {
|
||||
const { getByText } = render(
|
||||
<TestPageContainer>
|
||||
<Lineage upstreamEntities={sampleUpstreamEntities} downstreamEntities={sampleDownstreamEntities} />,
|
||||
<Lineage upstreamLineage={sampleUpstreamLineage} downstreamLineage={sampleDownstreamLineage} />,
|
||||
</TestPageContainer>,
|
||||
);
|
||||
expect(getByText('Upstream HiveDataset')).toBeInTheDocument();
|
||||
|
||||
@ -3,7 +3,7 @@ import { Story, Meta } from '@storybook/react';
|
||||
|
||||
import TestPageContainer from '../../../../../utils/test-utils/TestPageContainer';
|
||||
import Lineage, { Props } from '../Lineage';
|
||||
import { sampleUpstreamEntities, sampleDownstreamEntities } from './lineageEntities';
|
||||
import { sampleDownstreamLineage, sampleUpstreamLineage } from './lineageEntities';
|
||||
|
||||
export default {
|
||||
title: 'Dataset Profile / Lineage',
|
||||
@ -13,7 +13,7 @@ export default {
|
||||
const Template: Story<Props> = (args) => <Lineage {...args} />;
|
||||
|
||||
export const UpstreamAndDownstream = Template.bind({});
|
||||
UpstreamAndDownstream.args = { upstreamEntities: sampleUpstreamEntities, downstreamEntities: sampleDownstreamEntities };
|
||||
UpstreamAndDownstream.args = { upstreamLineage: sampleUpstreamLineage, downstreamLineage: sampleDownstreamLineage };
|
||||
UpstreamAndDownstream.decorators = [
|
||||
(InnerStory) => (
|
||||
<TestPageContainer>
|
||||
|
||||
@ -1,4 +1,11 @@
|
||||
import { EntityType, FabricType, PlatformNativeType } from '../../../../../types.generated';
|
||||
import {
|
||||
DatasetLineageType,
|
||||
DownstreamLineage,
|
||||
EntityType,
|
||||
FabricType,
|
||||
PlatformNativeType,
|
||||
UpstreamLineage,
|
||||
} from '../../../../../types.generated';
|
||||
|
||||
export const sampleUpstreamEntities = [
|
||||
{
|
||||
@ -85,3 +92,19 @@ export const sampleDownstreamEntities = [
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export const sampleUpstreamLineage = {
|
||||
upstreams: sampleUpstreamEntities.map((entity) => ({
|
||||
dataset: entity,
|
||||
type: DatasetLineageType.Transformed,
|
||||
created: { time: 0 },
|
||||
})),
|
||||
} as UpstreamLineage;
|
||||
|
||||
export const sampleDownstreamLineage = {
|
||||
downstreams: sampleDownstreamEntities.map((entity) => ({
|
||||
dataset: entity,
|
||||
type: DatasetLineageType.Transformed,
|
||||
created: { time: 0 },
|
||||
})),
|
||||
} as DownstreamLineage;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Divider, Space } from 'antd';
|
||||
import { Space } from 'antd';
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
@ -10,13 +10,12 @@ interface Props extends React.PropsWithChildren<any> {
|
||||
export default function DefaultPreviewCard({ title, url, children }: Props) {
|
||||
return (
|
||||
<Space direction="vertical" style={{ width: '100%' }}>
|
||||
<div style={{ padding: '0% 5%' }}>
|
||||
<div style={{ padding: '8px' }}>
|
||||
<Link to={url} style={{ color: '#0073b1' }} type="link">
|
||||
{title}
|
||||
</Link>
|
||||
{children}
|
||||
</div>
|
||||
<Divider />
|
||||
</Space>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import React from 'react';
|
||||
import * as QueryString from 'query-string';
|
||||
import { useHistory, useLocation, useParams } from 'react-router';
|
||||
import { Affix, Col, Row, Tabs, Layout } from 'antd';
|
||||
import { Affix, Col, Row, Tabs, Layout, List } from 'antd';
|
||||
|
||||
import { SearchablePage } from './SearchablePage';
|
||||
import { useGetSearchResultsQuery } from '../../graphql/search.generated';
|
||||
import { SearchResults } from './SearchResults';
|
||||
@ -67,9 +68,13 @@ export const SearchPage = () => {
|
||||
navigateToSearchUrl({ type: activeType, query, page: newPage, filters, history, entityRegistry });
|
||||
};
|
||||
|
||||
const toSearchResults = (elements: any) => {
|
||||
return elements.map((element: any) => entityRegistry.renderSearchResult(activeType, element));
|
||||
};
|
||||
const toSearchResults = (elements: any) => (
|
||||
<List
|
||||
dataSource={elements}
|
||||
renderItem={(item) => <List.Item>{entityRegistry.renderSearchResult(activeType, item)}</List.Item>}
|
||||
bordered
|
||||
/>
|
||||
);
|
||||
|
||||
const searchResults = toSearchResults(data?.search?.entities || []);
|
||||
|
||||
|
||||
@ -6,16 +6,14 @@ interface Props {
|
||||
pageStart: number;
|
||||
pageSize: number;
|
||||
totalResults: number;
|
||||
results: Array<JSX.Element>;
|
||||
results: React.ReactNode;
|
||||
onChangePage: (page: number) => void;
|
||||
}
|
||||
|
||||
export const SearchResults = ({ typeName, pageStart, pageSize, totalResults, results, onChangePage }: Props) => {
|
||||
return (
|
||||
<Card
|
||||
style={{ border: '1px solid #d2d2d2' }}
|
||||
title={<h1 style={{ marginBottom: '0px' }}>{typeName}</h1>}
|
||||
bodyStyle={{ padding: '24px 0px' }}
|
||||
extra={
|
||||
<div style={{ color: 'grey' }}>
|
||||
Showing {pageStart * pageSize} - {pageStart * pageSize + pageSize} of {totalResults} results
|
||||
|
||||
@ -1,162 +1,122 @@
|
||||
query getDataset($urn: String!) {
|
||||
dataset(urn: $urn) {
|
||||
urn
|
||||
name
|
||||
type
|
||||
origin
|
||||
description
|
||||
uri
|
||||
platformNativeType
|
||||
tags
|
||||
properties {
|
||||
key
|
||||
value
|
||||
}
|
||||
created {
|
||||
time
|
||||
fragment nonRecursiveDatasetFields on Dataset {
|
||||
urn
|
||||
name
|
||||
type
|
||||
origin
|
||||
description
|
||||
uri
|
||||
platformNativeType
|
||||
tags
|
||||
properties {
|
||||
key
|
||||
value
|
||||
}
|
||||
created {
|
||||
time
|
||||
}
|
||||
lastModified {
|
||||
time
|
||||
}
|
||||
ownership {
|
||||
owners {
|
||||
owner {
|
||||
urn
|
||||
type
|
||||
username
|
||||
info {
|
||||
active
|
||||
displayName
|
||||
title
|
||||
email
|
||||
firstName
|
||||
lastName
|
||||
fullName
|
||||
}
|
||||
editableInfo {
|
||||
pictureLink
|
||||
}
|
||||
}
|
||||
type
|
||||
}
|
||||
lastModified {
|
||||
time
|
||||
}
|
||||
ownership {
|
||||
owners {
|
||||
owner {
|
||||
urn
|
||||
type
|
||||
username
|
||||
info {
|
||||
active
|
||||
displayName
|
||||
title
|
||||
firstName
|
||||
lastName
|
||||
}
|
||||
editableInfo {
|
||||
pictureLink
|
||||
}
|
||||
}
|
||||
type
|
||||
}
|
||||
lastModified {
|
||||
}
|
||||
institutionalMemory {
|
||||
elements {
|
||||
url
|
||||
author
|
||||
description
|
||||
created {
|
||||
actor
|
||||
time
|
||||
}
|
||||
}
|
||||
institutionalMemory {
|
||||
elements {
|
||||
url
|
||||
author
|
||||
description
|
||||
created {
|
||||
actor
|
||||
time
|
||||
}
|
||||
}
|
||||
schema {
|
||||
datasetUrn
|
||||
name
|
||||
platformUrn
|
||||
version
|
||||
hash
|
||||
platformSchema {
|
||||
... on TableSchema {
|
||||
schema
|
||||
}
|
||||
... on KeyValueSchema {
|
||||
keySchema
|
||||
valueSchema
|
||||
}
|
||||
}
|
||||
schema {
|
||||
datasetUrn
|
||||
name
|
||||
platformUrn
|
||||
version
|
||||
hash
|
||||
platformSchema {
|
||||
... on TableSchema {
|
||||
schema
|
||||
}
|
||||
... on KeyValueSchema {
|
||||
keySchema
|
||||
valueSchema
|
||||
}
|
||||
}
|
||||
fields {
|
||||
fieldPath
|
||||
jsonPath
|
||||
nullable
|
||||
description
|
||||
type
|
||||
nativeDataType
|
||||
recursive
|
||||
}
|
||||
primaryKeys
|
||||
}
|
||||
deprecation {
|
||||
actor
|
||||
deprecated
|
||||
note
|
||||
decommissionTime
|
||||
fields {
|
||||
fieldPath
|
||||
jsonPath
|
||||
nullable
|
||||
description
|
||||
type
|
||||
nativeDataType
|
||||
recursive
|
||||
}
|
||||
primaryKeys
|
||||
}
|
||||
deprecation {
|
||||
actor
|
||||
deprecated
|
||||
note
|
||||
decommissionTime
|
||||
}
|
||||
}
|
||||
|
||||
mutation updateDataset($input: DatasetUpdateInput!) {
|
||||
updateDataset(input: $input) {
|
||||
urn
|
||||
ownership {
|
||||
owners {
|
||||
owner {
|
||||
urn
|
||||
type
|
||||
username
|
||||
info {
|
||||
active
|
||||
displayName
|
||||
title
|
||||
email
|
||||
firstName
|
||||
lastName
|
||||
fullName
|
||||
}
|
||||
editableInfo {
|
||||
pictureLink
|
||||
}
|
||||
...nonRecursiveDatasetFields
|
||||
}
|
||||
}
|
||||
|
||||
query getDataset($urn: String!) {
|
||||
dataset(urn: $urn) {
|
||||
...nonRecursiveDatasetFields
|
||||
upstreamLineage {
|
||||
upstreams {
|
||||
dataset {
|
||||
...nonRecursiveDatasetFields
|
||||
}
|
||||
type
|
||||
}
|
||||
lastModified {
|
||||
time
|
||||
}
|
||||
}
|
||||
institutionalMemory {
|
||||
elements {
|
||||
url
|
||||
author
|
||||
description
|
||||
created {
|
||||
actor
|
||||
time
|
||||
}
|
||||
}
|
||||
}
|
||||
schema {
|
||||
datasetUrn
|
||||
name
|
||||
platformUrn
|
||||
version
|
||||
hash
|
||||
platformSchema {
|
||||
... on TableSchema {
|
||||
schema
|
||||
downstreamLineage {
|
||||
downstreams {
|
||||
dataset {
|
||||
...nonRecursiveDatasetFields
|
||||
}
|
||||
... on KeyValueSchema {
|
||||
keySchema
|
||||
valueSchema
|
||||
}
|
||||
}
|
||||
fields {
|
||||
fieldPath
|
||||
jsonPath
|
||||
nullable
|
||||
description
|
||||
type
|
||||
nativeDataType
|
||||
recursive
|
||||
created {
|
||||
time
|
||||
}
|
||||
}
|
||||
primaryKeys
|
||||
}
|
||||
deprecation {
|
||||
actor
|
||||
deprecated
|
||||
note
|
||||
decommissionTime
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user