Skip to content

Commit d761f6c

Browse files
committed
add dataprocessinstance to buildentityregistry
1 parent 1c21ed2 commit d761f6c

File tree

4 files changed

+544
-0
lines changed

4 files changed

+544
-0
lines changed

datahub-web-react/src/app/buildEntityRegistry.ts

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { RestrictedEntity } from './entity/restricted/RestrictedEntity';
2525
import { BusinessAttributeEntity } from './entity/businessAttribute/BusinessAttributeEntity';
2626
import { SchemaFieldPropertiesEntity } from './entity/schemaField/SchemaFieldPropertiesEntity';
2727
import { StructuredPropertyEntity } from './entity/structuredProperty/StructuredPropertyEntity';
28+
import { DataProcessInstanceEntity } from './entity/dataProcessInstance/DataProcessInstanceEntity';
2829

2930
export default function buildEntityRegistry() {
3031
const registry = new EntityRegistry();
@@ -54,5 +55,6 @@ export default function buildEntityRegistry() {
5455
registry.register(new BusinessAttributeEntity());
5556
registry.register(new SchemaFieldPropertiesEntity());
5657
registry.register(new StructuredPropertyEntity());
58+
registry.register(new DataProcessInstanceEntity());
5759
return registry;
5860
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
import { ApiOutlined } from '@ant-design/icons';
2+
import { DataJob, DataProcessInstance, EntityType, OwnershipType, SearchResult } from '../../../types.generated';
3+
import { Preview } from './preview/Preview';
4+
import { Entity, EntityCapabilityType, IconStyleType, PreviewType } from '../Entity';
5+
import { EntityProfile } from '../shared/containers/profile/EntityProfile';
6+
import { useGetDataProcessInstanceQuery } from '../../../graphql/dataProcessInstance.generated';
7+
import { PropertiesTab } from '../shared/tabs/Properties/PropertiesTab';
8+
import { LineageTab } from '../shared/tabs/Lineage/LineageTab';
9+
import { SidebarAboutSection } from '../shared/containers/profile/sidebar/AboutSection/SidebarAboutSection';
10+
import { SidebarTagsSection } from '../shared/containers/profile/sidebar/SidebarTagsSection';
11+
import { SidebarOwnerSection } from '../shared/containers/profile/sidebar/Ownership/sidebar/SidebarOwnerSection';
12+
import { GenericEntityProperties } from '../shared/types';
13+
import { getDataForEntityType } from '../shared/containers/profile/utils';
14+
import { SidebarDomainSection } from '../shared/containers/profile/sidebar/Domain/SidebarDomainSection';
15+
import { EntityMenuItems } from '../shared/EntityDropdown/EntityDropdown';
16+
import { capitalizeFirstLetterOnly } from '../../shared/textUtil';
17+
import DataProductSection from '../shared/containers/profile/sidebar/DataProduct/DataProductSection';
18+
import { getDataProduct } from '../shared/utils';
19+
// import SummaryTab from './profile/DataProcessInstaceSummary';
20+
21+
const getProcessPlatformName = (data?: DataProcessInstance): string => {
22+
return (
23+
data?.dataPlatformInstance?.platform?.properties?.displayName ||
24+
capitalizeFirstLetterOnly(data?.dataPlatformInstance?.platform?.name) ||
25+
''
26+
);
27+
};
28+
29+
const getParentEntities = (data: DataProcessInstance): Entity<DataJob>[] => {
30+
const parentEntity = data?.relationships?.relationships?.find(
31+
(rel) => rel.type === 'InstanceOf' && rel.entity?.type === EntityType.DataJob,
32+
);
33+
34+
const containerEntity = data?.container?.entity;
35+
36+
return parentEntity ? [parentEntity.entity as Entity<DataJob>] : []; // TODO: HACK
37+
};
38+
39+
/**
40+
* Definition of the DataHub DataProcessInstance entity.
41+
*/
42+
export class DataProcessInstanceEntity implements Entity<DataProcessInstance> {
43+
type: EntityType = EntityType.DataProcessInstance;
44+
45+
icon = (fontSize: number, styleType: IconStyleType, color?: string) => {
46+
if (styleType === IconStyleType.TAB_VIEW) {
47+
return <ApiOutlined style={{ fontSize, color }} />;
48+
}
49+
50+
if (styleType === IconStyleType.HIGHLIGHT) {
51+
return <ApiOutlined style={{ fontSize, color: color || '#B37FEB' }} />;
52+
}
53+
54+
return (
55+
<ApiOutlined
56+
style={{
57+
fontSize,
58+
color: color || '#BFBFBF',
59+
}}
60+
/>
61+
);
62+
};
63+
64+
isSearchEnabled = () => true;
65+
66+
isBrowseEnabled = () => true;
67+
68+
isLineageEnabled = () => true;
69+
70+
getAutoCompleteFieldName = () => 'name';
71+
72+
getPathName = () => 'dataProcessInstance';
73+
74+
getEntityName = () => 'Process Instance';
75+
76+
getGraphName = () => 'dataProcessInstance';
77+
78+
getCollectionName = () => 'Process Instances';
79+
80+
useEntityQuery = useGetDataProcessInstanceQuery;
81+
82+
renderProfile = (urn: string) => (
83+
<EntityProfile
84+
urn={urn}
85+
entityType={EntityType.DataProcessInstance}
86+
useEntityQuery={this.useEntityQuery}
87+
// useUpdateQuery={useUpdateDataProcessInstanceMutation}
88+
getOverrideProperties={this.getOverridePropertiesFromEntity}
89+
headerDropdownItems={new Set([EntityMenuItems.UPDATE_DEPRECATION, EntityMenuItems.RAISE_INCIDENT])}
90+
tabs={[
91+
// {
92+
// name: 'Documentation',
93+
// component: DocumentationTab,
94+
// },
95+
// {
96+
// name: 'Summary',
97+
// component: SummaryTab,
98+
// },
99+
{
100+
name: 'Lineage',
101+
component: LineageTab,
102+
},
103+
{
104+
name: 'Properties',
105+
component: PropertiesTab,
106+
},
107+
// {
108+
// name: 'Incidents',
109+
// component: IncidentTab,
110+
// getDynamicName: (_, processInstance) => {
111+
// const activeIncidentCount = processInstance?.dataProcessInstance?.activeIncidents.total;
112+
// return `Incidents${(activeIncidentCount && ` (${activeIncidentCount})`) || ''}`;
113+
// },
114+
// },
115+
]}
116+
sidebarSections={this.getSidebarSections()}
117+
/>
118+
);
119+
120+
getSidebarSections = () => [
121+
{
122+
component: SidebarAboutSection,
123+
},
124+
{
125+
component: SidebarOwnerSection,
126+
properties: {
127+
defaultOwnerType: OwnershipType.TechnicalOwner,
128+
},
129+
},
130+
{
131+
component: SidebarTagsSection,
132+
properties: {
133+
hasTags: true,
134+
hasTerms: true,
135+
},
136+
},
137+
{
138+
component: SidebarDomainSection,
139+
},
140+
{
141+
component: DataProductSection,
142+
},
143+
];
144+
145+
getOverridePropertiesFromEntity = (processInstance?: DataProcessInstance | null): GenericEntityProperties => {
146+
const name = processInstance?.name;
147+
const externalUrl = processInstance?.externalUrl;
148+
return {
149+
name,
150+
externalUrl,
151+
};
152+
};
153+
154+
renderPreview = (_: PreviewType, data: DataProcessInstance) => {
155+
const genericProperties = this.getGenericEntityProperties(data);
156+
const parentEntities = getParentEntities(data);
157+
return (
158+
<Preview
159+
urn={data.urn}
160+
name={data.properties?.name || data.name || ''}
161+
subType={data.subTypes?.typeNames?.[0]}
162+
description=""
163+
platformName={
164+
data?.platform?.properties?.displayName || capitalizeFirstLetterOnly(data?.platform?.name)
165+
}
166+
platformLogo={data.platform.properties?.logoUrl}
167+
owners={null}
168+
globalTags={null}
169+
// domain={data.domain?.domain}
170+
dataProduct={getDataProduct(genericProperties?.dataProduct)}
171+
externalUrl={data.properties?.externalUrl}
172+
parentContainers={data.parentContainers}
173+
parentEntities={parentEntities}
174+
container={data.container || undefined}
175+
// health={data.health}
176+
/>
177+
);
178+
};
179+
180+
renderSearch = (result: SearchResult) => {
181+
const data = result.entity as DataProcessInstance;
182+
const genericProperties = this.getGenericEntityProperties(data);
183+
const parentEntities = getParentEntities(data);
184+
return (
185+
<Preview
186+
urn={data.urn}
187+
name={data.properties?.name || data.name || ''}
188+
subType={data.subTypes?.typeNames?.[0]}
189+
description=""
190+
platformName={
191+
data?.platform?.properties?.displayName || capitalizeFirstLetterOnly(data?.platform?.name)
192+
}
193+
platformLogo={data.platform.properties?.logoUrl}
194+
platformInstanceId={data.dataPlatformInstance?.instanceId}
195+
owners={null}
196+
globalTags={null}
197+
// domain={data.domain?.domain}
198+
dataProduct={getDataProduct(genericProperties?.dataProduct)}
199+
// deprecation={data.deprecation}
200+
insights={result.insights}
201+
externalUrl={data.properties?.externalUrl}
202+
degree={(result as any).degree}
203+
paths={(result as any).paths}
204+
parentContainers={data.parentContainers}
205+
parentEntities={parentEntities}
206+
container={data.container || undefined}
207+
duration={data?.state[0]?.durationMillis}
208+
status={data?.state[0]?.result?.resultType}
209+
startTime={data?.state[0]?.timestampMillis}
210+
// health={data.health}
211+
/>
212+
);
213+
};
214+
215+
getLineageVizConfig = (entity: DataProcessInstance) => {
216+
return {
217+
urn: entity?.urn,
218+
name: this.displayName(entity),
219+
type: EntityType.DataProcessInstance,
220+
subtype: entity?.subTypes?.typeNames?.[0],
221+
icon: entity?.platform?.properties?.logoUrl || undefined,
222+
platform: entity?.platform,
223+
container: entity?.container,
224+
// health: entity?.health || undefined,
225+
};
226+
};
227+
228+
displayName = (data: DataProcessInstance) => {
229+
return data.properties?.name || data.urn;
230+
};
231+
232+
getGenericEntityProperties = (data: DataProcessInstance) => {
233+
return getDataForEntityType({
234+
data,
235+
entityType: this.type,
236+
getOverrideProperties: this.getOverridePropertiesFromEntity,
237+
});
238+
};
239+
240+
supportedCapabilities = () => {
241+
return new Set([
242+
EntityCapabilityType.OWNERS,
243+
EntityCapabilityType.GLOSSARY_TERMS,
244+
EntityCapabilityType.TAGS,
245+
EntityCapabilityType.DOMAINS,
246+
EntityCapabilityType.DEPRECATION,
247+
EntityCapabilityType.SOFT_DELETE,
248+
EntityCapabilityType.DATA_PRODUCTS,
249+
]);
250+
};
251+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import React from 'react';
2+
import styled from 'styled-components';
3+
import { Typography } from 'antd';
4+
import {
5+
DataProduct,
6+
Deprecation,
7+
Domain,
8+
Entity,
9+
EntityPath,
10+
EntityType,
11+
GlobalTags,
12+
Health,
13+
Owner,
14+
SearchInsight,
15+
Container,
16+
ParentContainersResult,
17+
} from '../../../../types.generated';
18+
import DefaultPreviewCard from '../../../preview/DefaultPreviewCard';
19+
import { useEntityRegistry } from '../../../useEntityRegistry';
20+
import { IconStyleType } from '../../Entity';
21+
import { ANTD_GRAY } from '../../shared/constants';
22+
23+
const StatText = styled(Typography.Text)`
24+
color: ${ANTD_GRAY[8]};
25+
`;
26+
27+
export const Preview = ({
28+
urn,
29+
name,
30+
subType,
31+
description,
32+
platformName,
33+
platformLogo,
34+
platformInstanceId,
35+
container,
36+
owners,
37+
domain,
38+
dataProduct,
39+
deprecation,
40+
globalTags,
41+
snippet,
42+
insights,
43+
externalUrl,
44+
degree,
45+
paths,
46+
health,
47+
parentEntities,
48+
parentContainers,
49+
duration,
50+
status,
51+
startTime,
52+
}: {
53+
urn: string;
54+
name: string;
55+
subType?: string | null;
56+
description?: string | null;
57+
platformName?: string;
58+
platformLogo?: string | null;
59+
platformInstanceId?: string;
60+
container?: Container | null;
61+
owners?: Array<Owner> | null;
62+
domain?: Domain | null;
63+
dataProduct?: DataProduct | null;
64+
deprecation?: Deprecation | null;
65+
globalTags?: GlobalTags | null;
66+
snippet?: React.ReactNode | null;
67+
insights?: Array<SearchInsight> | null;
68+
externalUrl?: string | null;
69+
degree?: number;
70+
paths?: EntityPath[];
71+
health?: Health[] | null;
72+
parentEntities?: Entity[] | null;
73+
parentContainers?: ParentContainersResult | null;
74+
duration?: number | null;
75+
status?: string | null;
76+
startTime?: number | null;
77+
}): JSX.Element => {
78+
const entityRegistry = useEntityRegistry();
79+
return (
80+
<DefaultPreviewCard
81+
url={entityRegistry.getEntityUrl(EntityType.DataProcessInstance, urn)}
82+
name={name}
83+
urn={urn}
84+
description={description || ''}
85+
type={subType || 'Process Instance'}
86+
typeIcon={entityRegistry.getIcon(EntityType.DataProcessInstance, 14, IconStyleType.ACCENT)}
87+
platform={platformName || undefined}
88+
logoUrl={platformLogo || undefined}
89+
platformInstanceId={platformInstanceId}
90+
container={container}
91+
parentContainers={parentContainers}
92+
owners={owners}
93+
tags={globalTags || undefined}
94+
domain={domain}
95+
dataProduct={dataProduct}
96+
snippet={snippet}
97+
deprecation={deprecation}
98+
dataTestID="process-instance-item-preview"
99+
insights={insights}
100+
externalUrl={externalUrl}
101+
degree={degree}
102+
paths={paths}
103+
health={health || undefined}
104+
parentEntities={parentEntities}
105+
duration={duration}
106+
status={status}
107+
startTime={startTime}
108+
/>
109+
);
110+
};

0 commit comments

Comments
 (0)