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(React): Deprecation status in dataset header #2097

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions datahub-web-react/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
**/*.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Avatar, Badge, Popover, Space, Tooltip, Typography } from 'antd';
import React from 'react';
import { Link } from 'react-router-dom';
import { Dataset, EntityType } from '../../../../types.generated';
import { useEntityRegistry } from '../../../useEntityRegistry';
import defaultAvatar from '../../../../images/default_avatar.png';

export type Props = {
dataset: Dataset;
};

export default function DatasetHeader({ dataset: { description, ownership, deprecation } }: Props) {
const entityRegistry = useEntityRegistry();

return (
<>
<Typography.Paragraph>{description}</Typography.Paragraph>
<Space direction="vertical">
<Avatar.Group maxCount={6} size="large">
{ownership &&
ownership.owners &&
ownership.owners.map((owner: any) => (
<Tooltip title={owner.owner.info?.fullName}>
<Link to={`/${entityRegistry.getPathName(EntityType.CorpUser)}/${owner.owner.urn}`}>
<Avatar
style={{
color: '#f56a00',
backgroundColor: '#fde3cf',
}}
src={
(owner.owner.editableInfo && owner.owner.editableInfo.pictureLink) ||
defaultAvatar
}
/>
</Link>
</Tooltip>
))}
</Avatar.Group>
<div>
{deprecation?.deprecated && (
<Popover
placement="bottomLeft"
content={
<>
<Typography.Paragraph>By: {deprecation?.actor}</Typography.Paragraph>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Maybe not need for the ":" here. It would also be useful to add a link

{deprecation.decommissionTime && (
<Typography.Paragraph>
On: {new Date(deprecation?.decommissionTime).toUTCString()}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here with the ":"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great points- let's do those in followups.

</Typography.Paragraph>
)}
{deprecation?.note && (
<Typography.Paragraph>{deprecation.note}</Typography.Paragraph>
)}
</>
}
title="Deprecated"
>
<Badge count="Deprecated" />
</Popover>
)}
</div>
</Space>
</>
);
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
import React from 'react';
import { Avatar, Tooltip, Typography } from 'antd';
import { Link } from 'react-router-dom';
import { useGetDatasetQuery, useUpdateDatasetMutation } from '../../../../graphql/dataset.generated';
import defaultAvatar from '../../../../images/default_avatar.png';
import { Ownership as OwnershipView } from './Ownership';
import SchemaView from './schema/Schema';
import { EntityProfile } from '../../../shared/EntityProfile';
import { Dataset, EntityType } from '../../../../types.generated';
import { useEntityRegistry } from '../../../useEntityRegistry';
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 {
Ownership = 'Ownership',
Expand All @@ -28,37 +25,10 @@ const EMPTY_ARR: never[] = [];
* Responsible for display the Dataset Page
*/
export const Profile = ({ urn }: { urn: string }): JSX.Element => {
const entityRegistry = useEntityRegistry();

const { loading, error, data } = useGetDatasetQuery({ variables: { urn } });

const [updateDataset] = useUpdateDatasetMutation();

const getBody = (description: string, ownership: any) => (
<>
<Typography.Paragraph>{description}</Typography.Paragraph>
<Avatar.Group maxCount={6} size="large">
{ownership &&
ownership.owners &&
ownership.owners.map((owner: any) => (
<Tooltip title={owner.owner.info?.fullName}>
<Link to={`/${entityRegistry.getPathName(EntityType.CorpUser)}/${owner.owner.urn}`}>
<Avatar
style={{
color: '#f56a00',
backgroundColor: '#fde3cf',
}}
src={
(owner.owner.editableInfo && owner.owner.editableInfo.pictureLink) ||
defaultAvatar
}
/>
</Link>
</Tooltip>
))}
</Avatar.Group>
</>
);
const getHeader = (dataset: Dataset) => <DatasetHeader dataset={dataset} />;

const getTabs = ({ ownership, properties, institutionalMemory, schema }: Dataset) => {
return [
Expand Down Expand Up @@ -118,8 +88,8 @@ export const Profile = ({ urn }: { urn: string }): JSX.Element => {
<EntityProfile
title={data.dataset.name}
tags={data.dataset.tags}
body={getBody(data.dataset?.description || '', data.dataset?.ownership)}
tabs={getTabs(data.dataset as Dataset)}
header={getHeader(data.dataset as Dataset)}
/>
)}
{error && <p>Failed to load dataset with urn {urn}</p>}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import { Story, Meta } from '@storybook/react';

import TestPageContainer from '../../../../../utils/test-utils/TestPageContainer';
import DatasetHeader, { Props } from '../DatasetHeader';
import { sampleDataset, sampleDeprecatedDataset } from './sampleDataset';

export default {
title: 'Dataset Profile / DatasetHeader',
component: DatasetHeader,
} as Meta;

const Template: Story<Props> = (args) => <DatasetHeader {...args} />;

export const DescriptionAndOwner = Template.bind({});
DescriptionAndOwner.args = { dataset: sampleDataset };
DescriptionAndOwner.decorators = [
(InnerStory) => (
<>
<TestPageContainer>
<InnerStory />
</TestPageContainer>
</>
),
];

export const Deprecated = Template.bind({});
Deprecated.args = { dataset: sampleDeprecatedDataset };
Deprecated.decorators = [
(InnerStory) => (
<>
<TestPageContainer>
<InnerStory />
</TestPageContainer>
</>
),
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Dataset, EntityType, FabricType, OwnershipType } from '../../../../../types.generated';

export const sampleDataset: Dataset = {
__typename: 'Dataset',
urn: 'test:urn',
platform: {
type: EntityType.DataPlatform,
urn: 'test:hive:urn',
name: 'hive',
},
name: 'hive dataset',
origin: FabricType.Prod,
description: 'Some description',
type: EntityType.Dataset,
created: { time: 1 },
lastModified: { time: 1 },
tags: [],
ownership: {
owners: [
{ owner: { urn: 'user:urn', type: EntityType.CorpUser, username: 'UserA' }, type: OwnershipType.Dataowner },
],
lastModified: { time: 1 },
},
};

export const sampleDeprecatedDataset: Dataset = {
__typename: 'Dataset',
urn: 'test:urn',
platform: {
type: EntityType.DataPlatform,
urn: 'test:hive:urn',
name: 'hive',
},
name: 'hive dataset',
origin: FabricType.Prod,
description: 'Some deprecated description',
type: EntityType.Dataset,
created: { time: 1 },
lastModified: { time: 1 },
tags: [],
ownership: {
owners: [
{ owner: { urn: 'user:urn', type: EntityType.CorpUser, username: 'UserA' }, type: OwnershipType.Dataowner },
],
lastModified: { time: 1 },
},
deprecation: {
actor: 'UserB',
deprecated: true,
note: "Don't touch this dataset with a 10 foot pole",
decommissionTime: 1612565520292,
},
};
14 changes: 7 additions & 7 deletions datahub-web-react/src/components/shared/EntityProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { RoutedTabs } from './RoutedTabs';
export interface EntityProfileProps {
title: string;
tags?: Array<string>;
body: React.ReactNode;
header: React.ReactNode;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this rename!

tabs?: Array<{
name: string;
path: string;
Expand All @@ -21,27 +21,27 @@ const defaultProps = {
/**
* A default container view for presenting Entity details.
*/
export const EntityProfile = ({ title: _title, tags: _tags, body: _body, tabs: _tabs }: EntityProfileProps) => {
const defaultTabPath = _tabs && _tabs?.length > 0 ? _tabs[0].path : '';
export const EntityProfile = ({ title, tags, header, tabs }: EntityProfileProps) => {
const defaultTabPath = tabs && tabs?.length > 0 ? tabs[0].path : '';

/* eslint-disable spaced-comment */
return (
<Layout.Content style={{ backgroundColor: 'white', padding: '0px 100px' }}>
<Row style={{ padding: '20px 0px 10px 0px' }}>
<Col span={24}>
<div>
<h1 style={{ float: 'left' }}>{_title}</h1>
<h1 style={{ float: 'left' }}>{title}</h1>
<div style={{ float: 'left', margin: '5px 20px' }}>
{_tags && _tags.map((t) => <Tag color="blue">{t}</Tag>)}
{tags && tags.map((t) => <Tag color="blue">{t}</Tag>)}
</div>
</div>
</Col>
</Row>
{_body}
{header}
<Divider style={{ marginBottom: '0px' }} />
<Row style={{ padding: '0px 0px 10px 0px' }}>
<Col span={24}>
<RoutedTabs defaultPath={defaultTabPath} tabs={_tabs || []} />
<RoutedTabs defaultPath={defaultTabPath} tabs={tabs || []} />
</Col>
</Row>
</Layout.Content>
Expand Down
12 changes: 12 additions & 0 deletions datahub-web-react/src/graphql/dataset.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ query getDataset($urn: String!) {
}
primaryKeys
}
deprecation {
actor
deprecated
note
decommissionTime
}
}
}

Expand Down Expand Up @@ -146,5 +152,11 @@ mutation updateDataset($input: DatasetUpdateInput!) {
}
primaryKeys
}
deprecation {
actor
deprecated
note
decommissionTime
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default ({ children }: Props) => {

return (
<MemoryRouter>
<EntityRegistryContext.Provider value={entityRegistry}>{children}</EntityRegistryContext.Provider>;
<EntityRegistryContext.Provider value={entityRegistry}>{children}</EntityRegistryContext.Provider>
</MemoryRouter>
);
};