mirror of
https://github.com/datahub-project/datahub.git
synced 2025-10-28 09:23:25 +00:00
feat(embed): embed lookup route (#8033)
This commit is contained in:
parent
72bcfc53af
commit
d3dc2f22a5
@ -7,6 +7,7 @@ import { PageRoutes } from '../conf/Global';
|
||||
import EmbeddedPage from './embed/EmbeddedPage';
|
||||
import { useEntityRegistry } from './useEntityRegistry';
|
||||
import AppProviders from './AppProviders';
|
||||
import EmbedLookup from './embed/lookup';
|
||||
|
||||
/**
|
||||
* Container for all views behind an authentication wall.
|
||||
@ -20,6 +21,7 @@ export const ProtectedRoutes = (): JSX.Element => {
|
||||
<Layout>
|
||||
<Switch>
|
||||
<Route exact path="/" render={() => <HomePage />} />
|
||||
<Route exact path={PageRoutes.EMBED_LOOKUP} render={() => <EmbedLookup />} />
|
||||
{entityRegistry.getEntities().map((entity) => (
|
||||
<Route
|
||||
key={`${entity.getPathName()}/${PageRoutes.EMBED}`}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { DataHubViewType, EntityType, RecommendationRenderType, ScenarioType } from '../../types.generated';
|
||||
import { EmbedLookupNotFoundReason } from '../embed/lookup/constants';
|
||||
import { Direction } from '../lineage/types';
|
||||
|
||||
/**
|
||||
@ -68,6 +69,7 @@ export enum EventType {
|
||||
DeselectQuickFilterEvent,
|
||||
EmbedProfileViewEvent,
|
||||
EmbedProfileViewInDataHubEvent,
|
||||
EmbedLookupNotFoundEvent,
|
||||
}
|
||||
|
||||
/**
|
||||
@ -519,6 +521,12 @@ export interface EmbedProfileViewInDataHubEvent extends BaseEvent {
|
||||
entityUrn: string;
|
||||
}
|
||||
|
||||
export interface EmbedLookupNotFoundEvent extends BaseEvent {
|
||||
type: EventType.EmbedLookupNotFoundEvent;
|
||||
url: string;
|
||||
reason: EmbedLookupNotFoundReason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event consisting of a union of specific event types.
|
||||
*/
|
||||
@ -585,4 +593,5 @@ export type Event =
|
||||
| SelectQuickFilterEvent
|
||||
| DeselectQuickFilterEvent
|
||||
| EmbedProfileViewEvent
|
||||
| EmbedProfileViewInDataHubEvent;
|
||||
| EmbedProfileViewInDataHubEvent
|
||||
| EmbedLookupNotFoundEvent;
|
||||
|
||||
38
datahub-web-react/src/app/embed/lookup/EmbedLookup.tsx
Normal file
38
datahub-web-react/src/app/embed/lookup/EmbedLookup.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
import React from 'react';
|
||||
import { useParams } from 'react-router';
|
||||
import styled from 'styled-components';
|
||||
import { ErrorSection } from '../../shared/error/ErrorSection';
|
||||
import useGetEntityByUrl from './useGetEntityByUrl';
|
||||
import LookupNotFound from './LookupNotFound';
|
||||
import LookupFoundMultiple from './LookupFoundMultiple';
|
||||
import LookupLoading from './LookupLoading';
|
||||
import GoToLookup from './GoToLookup';
|
||||
|
||||
type RouteParams = {
|
||||
url: string;
|
||||
};
|
||||
|
||||
const PageContainer = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 85vh;
|
||||
`;
|
||||
|
||||
const EmbedLookup = () => {
|
||||
const { url: encodedUrl } = useParams<RouteParams>();
|
||||
const decodedUrl = decodeURIComponent(encodedUrl);
|
||||
const { count, entity, error, loading } = useGetEntityByUrl(decodedUrl);
|
||||
|
||||
const getContent = () => {
|
||||
if (loading) return <LookupLoading />;
|
||||
if (error) return <ErrorSection />;
|
||||
if (count === 0 || !entity) return <LookupNotFound url={encodedUrl} />;
|
||||
if (count > 1) return <LookupFoundMultiple url={encodedUrl} />;
|
||||
return <GoToLookup entityType={entity.type} entityUrn={entity.urn} />;
|
||||
};
|
||||
|
||||
return <PageContainer>{getContent()}</PageContainer>;
|
||||
};
|
||||
|
||||
export default EmbedLookup;
|
||||
19
datahub-web-react/src/app/embed/lookup/GoToLookup.tsx
Normal file
19
datahub-web-react/src/app/embed/lookup/GoToLookup.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { useHistory } from 'react-router';
|
||||
import { EntityType } from '../../../types.generated';
|
||||
import { useEntityRegistry } from '../../useEntityRegistry';
|
||||
import { PageRoutes } from '../../../conf/Global';
|
||||
import { urlEncodeUrn } from '../../entity/shared/utils';
|
||||
import LookupLoading from './LookupLoading';
|
||||
|
||||
const GoToLookup = ({ entityType, entityUrn }: { entityType: EntityType; entityUrn: string }) => {
|
||||
const registry = useEntityRegistry();
|
||||
const history = useHistory();
|
||||
useEffect(() => {
|
||||
const entityUrl = `${PageRoutes.EMBED}/${registry.getPathName(entityType)}/${urlEncodeUrn(entityUrn)}`;
|
||||
history.push(entityUrl);
|
||||
}, [entityType, entityUrn, history, registry]);
|
||||
return <LookupLoading />;
|
||||
};
|
||||
|
||||
export default GoToLookup;
|
||||
@ -0,0 +1,13 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import useEmbedLookupAnalytics from './useEmbedAnalytics';
|
||||
import NonExistentEntityPage from '../../entity/shared/entity/NonExistentEntityPage';
|
||||
|
||||
const LookupFoundMultiple = ({ url }: { url: string }) => {
|
||||
const { trackLookupMultipleFoundEvent } = useEmbedLookupAnalytics();
|
||||
useEffect(() => {
|
||||
trackLookupMultipleFoundEvent(url);
|
||||
}, [trackLookupMultipleFoundEvent, url]);
|
||||
return <NonExistentEntityPage />;
|
||||
};
|
||||
|
||||
export default LookupFoundMultiple;
|
||||
8
datahub-web-react/src/app/embed/lookup/LookupLoading.tsx
Normal file
8
datahub-web-react/src/app/embed/lookup/LookupLoading.tsx
Normal file
@ -0,0 +1,8 @@
|
||||
import { LoadingOutlined } from '@ant-design/icons';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const LookupLoading = styled(LoadingOutlined)`
|
||||
font-size: 50px;
|
||||
`;
|
||||
|
||||
export default LookupLoading;
|
||||
13
datahub-web-react/src/app/embed/lookup/LookupNotFound.tsx
Normal file
13
datahub-web-react/src/app/embed/lookup/LookupNotFound.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import useEmbedLookupAnalytics from './useEmbedAnalytics';
|
||||
import NonExistentEntityPage from '../../entity/shared/entity/NonExistentEntityPage';
|
||||
|
||||
const LookupNotFound = ({ url }: { url: string }) => {
|
||||
const { trackLookupNotFoundEvent } = useEmbedLookupAnalytics();
|
||||
useEffect(() => {
|
||||
trackLookupNotFoundEvent(url);
|
||||
}, [trackLookupNotFoundEvent, url]);
|
||||
return <NonExistentEntityPage />;
|
||||
};
|
||||
|
||||
export default LookupNotFound;
|
||||
7
datahub-web-react/src/app/embed/lookup/constants.ts
Normal file
7
datahub-web-react/src/app/embed/lookup/constants.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export const EMBED_LOOKUP_NOT_FOUND_REASON = {
|
||||
NO_ENTITY_FOUND: 'NO_ENTITY_FOUND',
|
||||
MULTIPLE_ENTITIES_FOUND: 'MULTIPLE_ENTITIES_FOUND',
|
||||
} as const;
|
||||
|
||||
export type EmbedLookupNotFoundReason =
|
||||
typeof EMBED_LOOKUP_NOT_FOUND_REASON[keyof typeof EMBED_LOOKUP_NOT_FOUND_REASON];
|
||||
3
datahub-web-react/src/app/embed/lookup/index.tsx
Normal file
3
datahub-web-react/src/app/embed/lookup/index.tsx
Normal file
@ -0,0 +1,3 @@
|
||||
import EmbedLookup from './EmbedLookup';
|
||||
|
||||
export default EmbedLookup;
|
||||
26
datahub-web-react/src/app/embed/lookup/useEmbedAnalytics.ts
Normal file
26
datahub-web-react/src/app/embed/lookup/useEmbedAnalytics.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { useCallback } from 'react';
|
||||
import analytics from '../../analytics/analytics';
|
||||
import { EventType } from '../../analytics';
|
||||
import { EMBED_LOOKUP_NOT_FOUND_REASON } from './constants';
|
||||
|
||||
const useEmbedLookupAnalytics = () => {
|
||||
const trackLookupNotFoundEvent = useCallback((url: string) => {
|
||||
analytics.event({
|
||||
type: EventType.EmbedLookupNotFoundEvent,
|
||||
url,
|
||||
reason: EMBED_LOOKUP_NOT_FOUND_REASON.NO_ENTITY_FOUND,
|
||||
});
|
||||
}, []);
|
||||
|
||||
const trackLookupMultipleFoundEvent = useCallback((url: string) => {
|
||||
analytics.event({
|
||||
type: EventType.EmbedLookupNotFoundEvent,
|
||||
url,
|
||||
reason: EMBED_LOOKUP_NOT_FOUND_REASON.MULTIPLE_ENTITIES_FOUND,
|
||||
});
|
||||
}, []);
|
||||
|
||||
return { trackLookupNotFoundEvent, trackLookupMultipleFoundEvent } as const;
|
||||
};
|
||||
|
||||
export default useEmbedLookupAnalytics;
|
||||
44
datahub-web-react/src/app/embed/lookup/useGetEntityByUrl.ts
Normal file
44
datahub-web-react/src/app/embed/lookup/useGetEntityByUrl.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useGetSearchResultsForMultipleQuery } from '../../../graphql/search.generated';
|
||||
import { FilterOperator } from '../../../types.generated';
|
||||
import { UnionType } from '../../search/utils/constants';
|
||||
import { generateOrFilters } from '../../search/utils/generateOrFilters';
|
||||
|
||||
const URL_FIELDS = ['externalUrl', 'chartUrl', 'dashboardUrl'] as const;
|
||||
|
||||
const useGetEntityByUrl = (externalUrl: string) => {
|
||||
const { data, loading, error } = useGetSearchResultsForMultipleQuery({
|
||||
variables: {
|
||||
input: {
|
||||
query: '*',
|
||||
start: 0,
|
||||
count: 2,
|
||||
orFilters: generateOrFilters(
|
||||
UnionType.OR,
|
||||
URL_FIELDS.map((field) => ({
|
||||
field,
|
||||
values: [externalUrl],
|
||||
condition: FilterOperator.Equal,
|
||||
})),
|
||||
),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const entities = data?.searchAcrossEntities?.searchResults.map((result) => result.entity) ?? [];
|
||||
const count = entities.length;
|
||||
const entity = count === 1 ? entities[0] : null;
|
||||
|
||||
return useMemo(
|
||||
() =>
|
||||
({
|
||||
count,
|
||||
entity,
|
||||
loading,
|
||||
error,
|
||||
} as const),
|
||||
[count, entity, error, loading],
|
||||
);
|
||||
};
|
||||
|
||||
export default useGetEntityByUrl;
|
||||
@ -24,6 +24,7 @@ import { EmbedTab } from '../shared/tabs/Embed/EmbedTab';
|
||||
import { capitalizeFirstLetterOnly } from '../../shared/textUtil';
|
||||
import DataProductSection from '../shared/containers/profile/sidebar/DataProduct/DataProductSection';
|
||||
import { getDataProduct } from '../shared/utils';
|
||||
import EmbeddedProfile from '../shared/embed/EmbeddedProfile';
|
||||
|
||||
/**
|
||||
* Definition of the DataHub Chart entity.
|
||||
@ -237,4 +238,13 @@ export class ChartEntity implements Entity<Chart> {
|
||||
EntityCapabilityType.DATA_PRODUCTS,
|
||||
]);
|
||||
};
|
||||
|
||||
renderEmbeddedProfile = (urn: string) => (
|
||||
<EmbeddedProfile
|
||||
urn={urn}
|
||||
entityType={EntityType.Chart}
|
||||
useEntityQuery={useGetChartQuery}
|
||||
getOverrideProperties={this.getOverridePropertiesFromEntity}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@ import { SidebarDomainSection } from '../shared/containers/profile/sidebar/Domai
|
||||
import { capitalizeFirstLetterOnly } from '../../shared/textUtil';
|
||||
import DataProductSection from '../shared/containers/profile/sidebar/DataProduct/DataProductSection';
|
||||
import { getDataProduct } from '../shared/utils';
|
||||
import EmbeddedProfile from '../shared/embed/EmbeddedProfile';
|
||||
|
||||
/**
|
||||
* Definition of the DataHub Container entity.
|
||||
@ -186,4 +187,13 @@ export class ContainerEntity implements Entity<Container> {
|
||||
EntityCapabilityType.DATA_PRODUCTS,
|
||||
]);
|
||||
};
|
||||
|
||||
renderEmbeddedProfile = (urn: string) => (
|
||||
<EmbeddedProfile
|
||||
urn={urn}
|
||||
entityType={EntityType.Container}
|
||||
useEntityQuery={useGetContainerQuery}
|
||||
getOverrideProperties={this.getOverridePropertiesFromEntity}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -78,7 +78,7 @@ export const ErrorSection = (): JSX.Element => {
|
||||
</DetailParagraph>
|
||||
<ResourceList>
|
||||
{resources.map((resource) => (
|
||||
<ResourceListItem>
|
||||
<ResourceListItem key={resource.path}>
|
||||
<a href={resource.path}>{resource.label}</a>
|
||||
</ResourceListItem>
|
||||
))}
|
||||
|
||||
@ -27,6 +27,7 @@ export enum PageRoutes {
|
||||
GLOSSARY = '/glossary',
|
||||
SETTINGS_VIEWS = '/settings/views',
|
||||
EMBED = '/embed',
|
||||
EMBED_LOOKUP = '/embed/lookup/:url',
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -67,7 +67,8 @@ public enum DataHubUsageEventType {
|
||||
SELECT_QUICK_FILTER_EVENT("SelectQuickFilterEvent"),
|
||||
DESELECT_QUICK_FILTER_EVENT("DeselectQuickFilterEvent"),
|
||||
EMBED_PROFILE_VIEW_EVENT("EmbedProfileViewEvent"),
|
||||
EMBED_PROFILE_VIEW_IN_DATAHUB_EVENT("EmbedProfileViewInDataHubEvent");
|
||||
EMBED_PROFILE_VIEW_IN_DATAHUB_EVENT("EmbedProfileViewInDataHubEvent"),
|
||||
EMBED_LOOKUP_NOT_FOUND_EVENT("EmbedLookupNotFoundEvent");
|
||||
|
||||
private final String type;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user