mirror of
https://github.com/datahub-project/datahub.git
synced 2025-08-17 13:45:54 +00:00
feat(propagation): Add Documentation Propagation Settings (#11038)
This commit is contained in:
parent
6f09b96b1d
commit
d6be56f9d9
@ -8,6 +8,7 @@ import {
|
||||
FilterOutlined,
|
||||
TeamOutlined,
|
||||
PushpinOutlined,
|
||||
ControlOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { Redirect, Route, useHistory, useLocation, useRouteMatch, Switch } from 'react-router';
|
||||
import styled from 'styled-components';
|
||||
@ -17,11 +18,17 @@ import { ManagePermissions } from '../permissions/ManagePermissions';
|
||||
import { useAppConfig } from '../useAppConfig';
|
||||
import { AccessTokens } from './AccessTokens';
|
||||
import { Preferences } from './Preferences';
|
||||
import { Features } from './features/Features';
|
||||
import { ManageViews } from '../entity/view/ManageViews';
|
||||
import { useUserContext } from '../context/useUserContext';
|
||||
import { ManageOwnership } from '../entity/ownership/ManageOwnership';
|
||||
import ManagePosts from './posts/ManagePosts';
|
||||
|
||||
const MenuItem = styled(Menu.Item)`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const PageContainer = styled.div`
|
||||
display: flex;
|
||||
overflow: auto;
|
||||
@ -59,6 +66,17 @@ const ItemTitle = styled.span`
|
||||
|
||||
const menuStyle = { width: 256, 'margin-top': 8, overflow: 'hidden auto' };
|
||||
|
||||
const NewTag = styled.span`
|
||||
padding: 4px 8px;
|
||||
margin-left: 8px;
|
||||
|
||||
border-radius: 24px;
|
||||
background: #f1fbfe;
|
||||
|
||||
color: #09739a;
|
||||
font-size: 12px;
|
||||
`;
|
||||
|
||||
/**
|
||||
* URL Paths for each settings page.
|
||||
*/
|
||||
@ -70,6 +88,7 @@ const PATHS = [
|
||||
{ path: 'views', content: <ManageViews /> },
|
||||
{ path: 'ownership', content: <ManageOwnership /> },
|
||||
{ path: 'posts', content: <ManagePosts /> },
|
||||
{ path: 'features', content: <Features /> },
|
||||
];
|
||||
|
||||
/**
|
||||
@ -80,6 +99,7 @@ const DEFAULT_PATH = PATHS[0];
|
||||
export const SettingsPage = () => {
|
||||
const { path, url } = useRouteMatch();
|
||||
const { pathname } = useLocation();
|
||||
|
||||
const history = useHistory();
|
||||
const subRoutes = PATHS.map((p) => p.path.replace('/', ''));
|
||||
const currPathName = pathname.replace(path, '');
|
||||
@ -101,6 +121,7 @@ export const SettingsPage = () => {
|
||||
const showViews = isViewsEnabled || false;
|
||||
const showOwnershipTypes = me && me?.platformPrivileges?.manageOwnershipTypes;
|
||||
const showHomePagePosts = me && me?.platformPrivileges?.manageGlobalAnnouncements && !readOnlyModeEnabled;
|
||||
const showFeatures = true; // TODO: Add feature flag for this
|
||||
|
||||
return (
|
||||
<PageContainer>
|
||||
@ -143,6 +164,13 @@ export const SettingsPage = () => {
|
||||
)}
|
||||
{(showViews || showOwnershipTypes || showHomePagePosts) && (
|
||||
<Menu.ItemGroup title="Manage">
|
||||
{showFeatures && (
|
||||
<MenuItem key="features">
|
||||
<ControlOutlined />
|
||||
<ItemTitle>Features</ItemTitle>
|
||||
<NewTag>New!</NewTag>
|
||||
</MenuItem>
|
||||
)}
|
||||
{showViews && (
|
||||
<Menu.Item key="views">
|
||||
<FilterOutlined /> <ItemTitle>My Views</ItemTitle>
|
||||
|
179
datahub-web-react/src/app/settings/features/Feature.tsx
Normal file
179
datahub-web-react/src/app/settings/features/Feature.tsx
Normal file
@ -0,0 +1,179 @@
|
||||
import React from 'react';
|
||||
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { Divider, Typography, Switch, Card, Button, Tooltip } from 'antd';
|
||||
import { ArrowRightOutlined } from '@ant-design/icons';
|
||||
import { ANTD_GRAY } from '../../entity/shared/constants';
|
||||
|
||||
const Title = styled(Typography.Title)`
|
||||
&& {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
`;
|
||||
|
||||
const FeatureRow = styled.div`
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
`;
|
||||
|
||||
const FeatureOptionRow = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
`;
|
||||
|
||||
const SettingsOptionRow = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 16px;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
`;
|
||||
|
||||
const DescriptionText = styled(Typography.Text)`
|
||||
color: ${ANTD_GRAY[7]};
|
||||
font-size: 11px;
|
||||
`;
|
||||
|
||||
const SettingTitle = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 14px;
|
||||
margin-bottom: 4px;
|
||||
`;
|
||||
|
||||
const OptionTitle = styled(Typography.Text)`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 12px;
|
||||
`;
|
||||
|
||||
const learnMoreLinkStyle = {
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '8px',
|
||||
color: '#1890FF',
|
||||
fontSize: '12px',
|
||||
cursor: 'pointer',
|
||||
};
|
||||
|
||||
const NewTag = styled.div`
|
||||
padding: 4px 8px;
|
||||
|
||||
border-radius: 24px;
|
||||
background: #f1fbfe;
|
||||
|
||||
color: #09739a;
|
||||
font-size: 12px;
|
||||
`;
|
||||
|
||||
const DataHubOnlyTag = styled.div`
|
||||
padding: 2px 8px;
|
||||
|
||||
border-radius: 24px;
|
||||
background: #c9fff2;
|
||||
|
||||
color: #50a494;
|
||||
font-size: 12px;
|
||||
`;
|
||||
|
||||
export interface FeatureType {
|
||||
key: string;
|
||||
title: string;
|
||||
description: string;
|
||||
settings: Array<{
|
||||
key: string;
|
||||
title: string;
|
||||
isAvailable: boolean;
|
||||
buttonText: string;
|
||||
onClick?: () => void;
|
||||
}>;
|
||||
options: Array<{
|
||||
key: string;
|
||||
title: string;
|
||||
description: string;
|
||||
isAvailable: boolean;
|
||||
checked: boolean;
|
||||
onChange?: (checked: boolean) => void;
|
||||
}>;
|
||||
isNew: boolean;
|
||||
learnMoreLink?: string;
|
||||
}
|
||||
|
||||
export const Feature = ({ key, title, description, settings, options, isNew, learnMoreLink }: FeatureType) => (
|
||||
<Card style={{ marginBottom: '1rem' }} key={key}>
|
||||
<FeatureRow>
|
||||
<div style={{ flex: 1 }}>
|
||||
<SettingTitle>
|
||||
<Title level={5} style={{ marginBottom: 0 }}>
|
||||
{title}
|
||||
</Title>
|
||||
{isNew && <NewTag>New!</NewTag>}
|
||||
</SettingTitle>
|
||||
<div>
|
||||
<Typography.Paragraph type="secondary">{description}</Typography.Paragraph>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
{learnMoreLink && (
|
||||
<a href={learnMoreLink} target="_blank" style={learnMoreLinkStyle} rel="noreferrer">
|
||||
Learn more <ArrowRightOutlined />
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</FeatureRow>
|
||||
<Divider style={{ margin: `8px 0 24px 0` }} />
|
||||
{settings.map((option) => (
|
||||
<>
|
||||
<SettingsOptionRow key={option.key}>
|
||||
<span>
|
||||
<OptionTitle>
|
||||
<span>{option.title}</span>
|
||||
</OptionTitle>
|
||||
</span>
|
||||
<Tooltip title={option.isAvailable ? '' : 'Only available on DataHub Cloud'}>
|
||||
<Button onClick={option.onClick} disabled={!option.isAvailable}>
|
||||
{option.buttonText}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</SettingsOptionRow>
|
||||
</>
|
||||
))}
|
||||
<Card style={{ margin: `16px auto` }}>
|
||||
{options.map((option, index) => (
|
||||
<>
|
||||
<FeatureOptionRow key={option.key}>
|
||||
<span>
|
||||
<OptionTitle>
|
||||
<span>{option.title}</span>
|
||||
{!option.isAvailable && (
|
||||
<DataHubOnlyTag>Only available on DataHub Cloud</DataHubOnlyTag>
|
||||
)}
|
||||
</OptionTitle>
|
||||
<div>
|
||||
<DescriptionText>{option.description}</DescriptionText>
|
||||
</div>
|
||||
</span>
|
||||
<Switch
|
||||
checked={option.checked}
|
||||
onChange={(checked) => (option.onChange ? option.onChange(checked) : null)}
|
||||
disabled={!option.isAvailable}
|
||||
/>
|
||||
</FeatureOptionRow>
|
||||
{index !== options.length - 1 && <Divider />}
|
||||
</>
|
||||
))}
|
||||
</Card>
|
||||
</Card>
|
||||
);
|
110
datahub-web-react/src/app/settings/features/Features.tsx
Normal file
110
datahub-web-react/src/app/settings/features/Features.tsx
Normal file
@ -0,0 +1,110 @@
|
||||
import React from 'react';
|
||||
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { Divider, Typography } from 'antd';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
import { Feature, FeatureType } from './Feature';
|
||||
|
||||
import { useGetDocPropagationSettings, useUpdateDocPropagationSettings } from './useDocPropagationSettings';
|
||||
|
||||
const Page = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
const SourceContainer = styled.div`
|
||||
width: 80%;
|
||||
padding-top: 20px;
|
||||
padding-right: 40px;
|
||||
padding-left: 40px;
|
||||
`;
|
||||
const Container = styled.div`
|
||||
padding-top: 0px;
|
||||
`;
|
||||
|
||||
const Title = styled(Typography.Title)`
|
||||
&& {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
`;
|
||||
|
||||
export const Features = () => {
|
||||
/*
|
||||
* Note: When adding new features, make sure to update the features array below
|
||||
* and create a hook file for the new feature in the same directory
|
||||
*/
|
||||
|
||||
// Hooks to get and update the document propagation settings
|
||||
const { isColPropagateChecked, setIsColPropagateChecked } = useGetDocPropagationSettings();
|
||||
const { updateDocPropagation } = useUpdateDocPropagationSettings();
|
||||
|
||||
// Features to display
|
||||
const features: FeatureType[] = [
|
||||
{
|
||||
key: uuidv4(),
|
||||
title: 'Documentation Propagation',
|
||||
description: 'Automatically propagate documentation from upstream to downstream columns and assets.',
|
||||
settings: [
|
||||
{
|
||||
key: uuidv4(),
|
||||
title: 'Rollback Propagation Changes',
|
||||
isAvailable: false,
|
||||
buttonText: 'Rollback',
|
||||
},
|
||||
{
|
||||
key: uuidv4(),
|
||||
title: 'Backfill existing documentation from upstream to downstream columns/assets',
|
||||
isAvailable: false,
|
||||
buttonText: 'Initialize',
|
||||
},
|
||||
],
|
||||
options: [
|
||||
{
|
||||
key: uuidv4(),
|
||||
title: 'Column Level Propagation',
|
||||
description:
|
||||
'Propagate new documentation from upstream to downstream columns based on column-level lineage relationships.',
|
||||
isAvailable: true,
|
||||
checked: isColPropagateChecked,
|
||||
onChange: (checked: boolean) => {
|
||||
setIsColPropagateChecked(checked);
|
||||
updateDocPropagation(checked);
|
||||
},
|
||||
},
|
||||
{
|
||||
key: uuidv4(),
|
||||
title: 'Asset Level Propagation',
|
||||
description:
|
||||
'Propagate new documentation from upstream to downstream assets based on data lineage relationships.',
|
||||
isAvailable: false,
|
||||
checked: false,
|
||||
},
|
||||
],
|
||||
isNew: true,
|
||||
learnMoreLink: 'https://datahubproject.io/docs/automations/doc-propagation',
|
||||
},
|
||||
];
|
||||
|
||||
// Render
|
||||
return (
|
||||
<Page>
|
||||
<SourceContainer>
|
||||
<Container>
|
||||
<div>
|
||||
<Title level={2}>Features</Title>
|
||||
<Typography.Paragraph type="secondary">
|
||||
Explore and configure specific features
|
||||
</Typography.Paragraph>
|
||||
</div>
|
||||
</Container>
|
||||
<Divider />
|
||||
{features.map((feature) => (
|
||||
<Feature {...feature} />
|
||||
))}
|
||||
</SourceContainer>
|
||||
</Page>
|
||||
);
|
||||
};
|
@ -0,0 +1,50 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { message } from 'antd';
|
||||
|
||||
import {
|
||||
useGetDocPropagationSettingsQuery,
|
||||
useUpdateDocPropagationSettingsMutation,
|
||||
} from '../../../graphql/app.generated';
|
||||
|
||||
// Hook to get the document propagation settings & manage state
|
||||
export const useGetDocPropagationSettings = () => {
|
||||
const { data, refetch } = useGetDocPropagationSettingsQuery();
|
||||
const [isColPropagateChecked, setIsColPropagateChecked] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
const docPropSetting = data?.docPropagationSettings?.docColumnPropagation;
|
||||
if (docPropSetting !== undefined) setIsColPropagateChecked(!!docPropSetting);
|
||||
}, [data]);
|
||||
|
||||
return {
|
||||
isColPropagateChecked,
|
||||
setIsColPropagateChecked,
|
||||
refetch,
|
||||
};
|
||||
};
|
||||
|
||||
// Hook to update the document propagation settings
|
||||
export const useUpdateDocPropagationSettings = () => {
|
||||
const [updateDocPropagationSettings] = useUpdateDocPropagationSettingsMutation();
|
||||
const { refetch } = useGetDocPropagationSettingsQuery();
|
||||
|
||||
const updateDocPropagation = async (checked: boolean) => {
|
||||
try {
|
||||
await updateDocPropagationSettings({
|
||||
variables: {
|
||||
input: {
|
||||
docColumnPropagation: checked,
|
||||
},
|
||||
},
|
||||
});
|
||||
refetch();
|
||||
message.success('Successfully updated documentation propagation settings');
|
||||
} catch (e) {
|
||||
message.error('Failed to update documentation propagation settings');
|
||||
refetch();
|
||||
}
|
||||
};
|
||||
|
||||
return { updateDocPropagation };
|
||||
};
|
@ -89,6 +89,16 @@ query getGlobalViewsSettings {
|
||||
}
|
||||
}
|
||||
|
||||
query getDocPropagationSettings {
|
||||
docPropagationSettings {
|
||||
docColumnPropagation
|
||||
}
|
||||
}
|
||||
|
||||
mutation updateGlobalViewsSettings($input: UpdateGlobalViewsSettingsInput!) {
|
||||
updateGlobalViewsSettings(input: $input)
|
||||
}
|
||||
|
||||
mutation updateDocPropagationSettings($input: UpdateDocPropagationSettingsInput!) {
|
||||
updateDocPropagationSettings(input: $input)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user