mirror of
https://github.com/datahub-project/datahub.git
synced 2025-11-10 00:11:15 +00:00
fix(ui): add warning for view all modal (#14702)
This commit is contained in:
parent
9105241bfd
commit
3e1e9fcf34
@ -78,6 +78,8 @@ export enum EventType {
|
|||||||
IngestionTestConnectionEvent,
|
IngestionTestConnectionEvent,
|
||||||
IngestionExecutionResultViewedEvent,
|
IngestionExecutionResultViewedEvent,
|
||||||
IngestionSourceConfigurationImpressionEvent,
|
IngestionSourceConfigurationImpressionEvent,
|
||||||
|
IngestionViewAllClickEvent,
|
||||||
|
IngestionViewAllClickWarningEvent,
|
||||||
CreateIngestionSourceEvent,
|
CreateIngestionSourceEvent,
|
||||||
UpdateIngestionSourceEvent,
|
UpdateIngestionSourceEvent,
|
||||||
DeleteIngestionSourceEvent,
|
DeleteIngestionSourceEvent,
|
||||||
@ -620,6 +622,16 @@ export interface IngestionTestConnectionEvent extends BaseEvent {
|
|||||||
outcome?: string;
|
outcome?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IngestionViewAllClickEvent extends BaseEvent {
|
||||||
|
type: EventType.IngestionViewAllClickEvent;
|
||||||
|
executionUrn?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IngestionViewAllClickWarningEvent extends BaseEvent {
|
||||||
|
type: EventType.IngestionViewAllClickWarningEvent;
|
||||||
|
executionUrn?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IngestionExecutionResultViewedEvent extends BaseEvent {
|
export interface IngestionExecutionResultViewedEvent extends BaseEvent {
|
||||||
type: EventType.IngestionExecutionResultViewedEvent;
|
type: EventType.IngestionExecutionResultViewedEvent;
|
||||||
executionUrn: string;
|
executionUrn: string;
|
||||||
@ -1249,4 +1261,6 @@ export type Event =
|
|||||||
| ProductTourButtonClickEvent
|
| ProductTourButtonClickEvent
|
||||||
| IngestionTestConnectionEvent
|
| IngestionTestConnectionEvent
|
||||||
| IngestionExecutionResultViewedEvent
|
| IngestionExecutionResultViewedEvent
|
||||||
| IngestionSourceConfigurationImpressionEvent;
|
| IngestionSourceConfigurationImpressionEvent
|
||||||
|
| IngestionViewAllClickEvent
|
||||||
|
| IngestionViewAllClickWarningEvent;
|
||||||
|
|||||||
@ -109,6 +109,8 @@ type Props = {
|
|||||||
applyView?: boolean;
|
applyView?: boolean;
|
||||||
onLineageClick?: () => void;
|
onLineageClick?: () => void;
|
||||||
isLineageTab?: boolean;
|
isLineageTab?: boolean;
|
||||||
|
isViewAllMode?: boolean | false;
|
||||||
|
handleViewAllClickWarning?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EmbeddedListSearch = ({
|
export const EmbeddedListSearch = ({
|
||||||
@ -139,6 +141,8 @@ export const EmbeddedListSearch = ({
|
|||||||
applyView = false,
|
applyView = false,
|
||||||
onLineageClick,
|
onLineageClick,
|
||||||
isLineageTab = false,
|
isLineageTab = false,
|
||||||
|
isViewAllMode = false,
|
||||||
|
handleViewAllClickWarning,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const { shouldRefetchEmbeddedListSearch, setShouldRefetchEmbeddedListSearch } = useEntityContext();
|
const { shouldRefetchEmbeddedListSearch, setShouldRefetchEmbeddedListSearch } = useEntityContext();
|
||||||
// Adjust query based on props
|
// Adjust query based on props
|
||||||
@ -348,6 +352,8 @@ export const EmbeddedListSearch = ({
|
|||||||
setSelectedEntities={setSelectedEntities}
|
setSelectedEntities={setSelectedEntities}
|
||||||
entityAction={entityAction}
|
entityAction={entityAction}
|
||||||
applyView={applyView}
|
applyView={applyView}
|
||||||
|
isViewAllMode={isViewAllMode}
|
||||||
|
handleViewAllClickWarning={handleViewAllClickWarning}
|
||||||
/>
|
/>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -33,6 +33,8 @@ type Props = {
|
|||||||
searchBarInputStyle?: any;
|
searchBarInputStyle?: any;
|
||||||
entityAction?: React.FC<EntityActionProps>;
|
entityAction?: React.FC<EntityActionProps>;
|
||||||
applyView?: boolean;
|
applyView?: boolean;
|
||||||
|
isViewAllMode?: boolean | false;
|
||||||
|
handleViewAllClickWarning?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EmbeddedListSearchModal = ({
|
export const EmbeddedListSearchModal = ({
|
||||||
@ -48,6 +50,8 @@ export const EmbeddedListSearchModal = ({
|
|||||||
searchBarInputStyle,
|
searchBarInputStyle,
|
||||||
entityAction,
|
entityAction,
|
||||||
applyView,
|
applyView,
|
||||||
|
isViewAllMode,
|
||||||
|
handleViewAllClickWarning,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
// Component state
|
// Component state
|
||||||
const [query, setQuery] = useState<string>('');
|
const [query, setQuery] = useState<string>('');
|
||||||
@ -98,6 +102,8 @@ export const EmbeddedListSearchModal = ({
|
|||||||
searchBarInputStyle={searchBarInputStyle}
|
searchBarInputStyle={searchBarInputStyle}
|
||||||
entityAction={entityAction}
|
entityAction={entityAction}
|
||||||
applyView={applyView}
|
applyView={applyView}
|
||||||
|
isViewAllMode={isViewAllMode}
|
||||||
|
handleViewAllClickWarning={handleViewAllClickWarning}
|
||||||
/>
|
/>
|
||||||
</SearchContainer>
|
</SearchContainer>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import { LoadingOutlined } from '@ant-design/icons';
|
import { ExclamationCircleFilled, LoadingOutlined } from '@ant-design/icons';
|
||||||
|
import { Text, colors } from '@components';
|
||||||
import { Button, Pagination, Spin, Typography } from 'antd';
|
import { Button, Pagination, Spin, Typography } from 'antd';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { useHistory } from 'react-router';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -13,10 +15,11 @@ import { EntityAndType } from '@app/entity/shared/types';
|
|||||||
import { SearchFiltersSection } from '@app/search/SearchFiltersSection';
|
import { SearchFiltersSection } from '@app/search/SearchFiltersSection';
|
||||||
import { combineSiblingsInSearchResults } from '@app/search/utils/combineSiblingsInSearchResults';
|
import { combineSiblingsInSearchResults } from '@app/search/utils/combineSiblingsInSearchResults';
|
||||||
import { UnionType } from '@app/search/utils/constants';
|
import { UnionType } from '@app/search/utils/constants';
|
||||||
|
import { navigateToSearchUrl } from '@app/searchV2/utils/navigateToSearchUrl';
|
||||||
import { useIsShowSeparateSiblingsEnabled } from '@app/useAppConfig';
|
import { useIsShowSeparateSiblingsEnabled } from '@app/useAppConfig';
|
||||||
import { SearchCfg } from '@src/conf';
|
import { SearchCfg } from '@src/conf';
|
||||||
|
|
||||||
import { FacetFilterInput, FacetMetadata, SearchResults as SearchResultType } from '@types';
|
import { Dataset, FacetFilterInput, FacetMetadata, SearchResults as SearchResultType } from '@types';
|
||||||
|
|
||||||
const SearchBody = styled.div`
|
const SearchBody = styled.div`
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@ -82,6 +85,17 @@ const ErrorMessage = styled.div`
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const WarningMessage = styled.div`
|
||||||
|
gap: 8px;
|
||||||
|
padding: 8px;
|
||||||
|
display: flex;
|
||||||
|
margin: 8px 16px 0 16px
|
||||||
|
align-items: center;
|
||||||
|
color: ${colors.yellow[1000]};
|
||||||
|
background-color: ${colors.yellow[0]};
|
||||||
|
border-radius: 8px;
|
||||||
|
`;
|
||||||
|
|
||||||
const StyledLinkButton = styled(Button)`
|
const StyledLinkButton = styled(Button)`
|
||||||
margin: 0 -14px;
|
margin: 0 -14px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
@ -110,8 +124,14 @@ interface Props {
|
|||||||
onClickLessHops?: () => void;
|
onClickLessHops?: () => void;
|
||||||
onLineageClick?: () => void;
|
onLineageClick?: () => void;
|
||||||
isLineageTab?: boolean;
|
isLineageTab?: boolean;
|
||||||
|
isViewAllMode?: boolean | false;
|
||||||
|
handleViewAllClickWarning?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getPlatformUrnFromSearchResponse = (searchResponse: SearchResultType | null | undefined) => {
|
||||||
|
return searchResponse?.facets?.find((facet) => facet.field === 'platform')?.aggregations?.[0]?.value;
|
||||||
|
};
|
||||||
|
|
||||||
export const EmbeddedListSearchResults = ({
|
export const EmbeddedListSearchResults = ({
|
||||||
page,
|
page,
|
||||||
searchResponse,
|
searchResponse,
|
||||||
@ -135,7 +155,10 @@ export const EmbeddedListSearchResults = ({
|
|||||||
onClickLessHops,
|
onClickLessHops,
|
||||||
onLineageClick,
|
onLineageClick,
|
||||||
isLineageTab = false,
|
isLineageTab = false,
|
||||||
|
isViewAllMode = false,
|
||||||
|
handleViewAllClickWarning,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
|
const history = useHistory();
|
||||||
const showSeparateSiblings = useIsShowSeparateSiblingsEnabled();
|
const showSeparateSiblings = useIsShowSeparateSiblingsEnabled();
|
||||||
const combinedSiblingSearchResults = combineSiblingsInSearchResults(
|
const combinedSiblingSearchResults = combineSiblingsInSearchResults(
|
||||||
showSeparateSiblings,
|
showSeparateSiblings,
|
||||||
@ -147,6 +170,28 @@ export const EmbeddedListSearchResults = ({
|
|||||||
const totalResults = searchResponse?.total || 0;
|
const totalResults = searchResponse?.total || 0;
|
||||||
const lastResultIndex = pageStart + pageSize > totalResults ? totalResults : pageStart + pageSize;
|
const lastResultIndex = pageStart + pageSize > totalResults ? totalResults : pageStart + pageSize;
|
||||||
|
|
||||||
|
const platformUrn = getPlatformUrnFromSearchResponse(searchResponse);
|
||||||
|
let platform: string | null = null;
|
||||||
|
try {
|
||||||
|
platform = (combinedSiblingSearchResults?.[0]?.entity as Dataset).platform?.name;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error getting platform from search response', error);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSearchAllAssetsClick = () => {
|
||||||
|
handleViewAllClickWarning?.();
|
||||||
|
if (platformUrn) {
|
||||||
|
const platformFilter: FacetFilterInput = {
|
||||||
|
field: 'platform',
|
||||||
|
values: [platformUrn],
|
||||||
|
};
|
||||||
|
navigateToSearchUrl({
|
||||||
|
filters: [platformFilter],
|
||||||
|
history,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<SearchBody>
|
<SearchBody>
|
||||||
@ -180,6 +225,30 @@ export const EmbeddedListSearchResults = ({
|
|||||||
</StyledLinkButton>
|
</StyledLinkButton>
|
||||||
</ErrorMessage>
|
</ErrorMessage>
|
||||||
)}
|
)}
|
||||||
|
{isViewAllMode && (
|
||||||
|
<WarningMessage>
|
||||||
|
<ExclamationCircleFilled style={{ color: colors.yellow[1000], fontSize: 16 }} />
|
||||||
|
<Text weight="bold" style={{ lineHeight: 'normal' }}>
|
||||||
|
Results may be incomplete.{' '}
|
||||||
|
{platform && (
|
||||||
|
<span
|
||||||
|
onClick={handleSearchAllAssetsClick}
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
if (e.key === 'Enter' || e.key === ' ') {
|
||||||
|
e.preventDefault();
|
||||||
|
handleSearchAllAssetsClick();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
role="button"
|
||||||
|
tabIndex={0}
|
||||||
|
style={{ cursor: 'pointer', textDecoration: 'underline' }}
|
||||||
|
>
|
||||||
|
Search all ingested {platform} assets
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</Text>
|
||||||
|
</WarningMessage>
|
||||||
|
)}
|
||||||
{!loading && !isServerOverloadError && (
|
{!loading && !isServerOverloadError && (
|
||||||
<EntitySearchResults
|
<EntitySearchResults
|
||||||
searchResults={combinedSiblingSearchResults || []}
|
searchResults={combinedSiblingSearchResults || []}
|
||||||
|
|||||||
@ -100,7 +100,7 @@ export const SummaryTab = ({
|
|||||||
)}
|
)}
|
||||||
<IngestedAssetsSection>
|
<IngestedAssetsSection>
|
||||||
{data?.executionRequest?.id && (
|
{data?.executionRequest?.id && (
|
||||||
<IngestedAssets executionResult={result} id={data?.executionRequest?.id} />
|
<IngestedAssets executionResult={result} id={data?.executionRequest?.id} urn={urn} />
|
||||||
)}
|
)}
|
||||||
</IngestedAssetsSection>
|
</IngestedAssetsSection>
|
||||||
<SectionBase>
|
<SectionBase>
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import React, { useMemo, useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
import analytics from '@app/analytics';
|
||||||
|
import { EventType } from '@app/analytics/event';
|
||||||
import { EmbeddedListSearchModal } from '@app/entity/shared/components/styled/search/EmbeddedListSearchModal';
|
import { EmbeddedListSearchModal } from '@app/entity/shared/components/styled/search/EmbeddedListSearchModal';
|
||||||
import {
|
import {
|
||||||
extractEntityTypeCountsFromFacets,
|
extractEntityTypeCountsFromFacets,
|
||||||
@ -107,6 +109,7 @@ const IngestionRowCount = styled(Text)`
|
|||||||
type Props = {
|
type Props = {
|
||||||
id: string;
|
id: string;
|
||||||
executionResult?: Maybe<Partial<ExecutionRequestResult>>;
|
executionResult?: Maybe<Partial<ExecutionRequestResult>>;
|
||||||
|
urn: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ENTITY_FACET_NAME = 'entity';
|
const ENTITY_FACET_NAME = 'entity';
|
||||||
@ -153,12 +156,27 @@ const IngestionContents: React.FC<RenderIngestionContentsProps> = ({ items, getK
|
|||||||
</IngestionBoxesContainer>
|
</IngestionBoxesContainer>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default function IngestedAssets({ id, executionResult }: Props) {
|
export default function IngestedAssets({ id, executionResult, urn }: Props) {
|
||||||
const entityRegistry = useEntityRegistry();
|
const entityRegistry = useEntityRegistry();
|
||||||
|
|
||||||
// First thing to do is to search for all assets with the id as the run id!
|
// First thing to do is to search for all assets with the id as the run id!
|
||||||
const [showAssetSearch, setShowAssetSearch] = useState(false);
|
const [showAssetSearch, setShowAssetSearch] = useState(false);
|
||||||
|
|
||||||
|
const handleViewAllClick = () => {
|
||||||
|
analytics.event({
|
||||||
|
type: EventType.IngestionViewAllClickEvent,
|
||||||
|
executionUrn: urn,
|
||||||
|
});
|
||||||
|
setShowAssetSearch(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleViewAllClickWarning = () => {
|
||||||
|
analytics.event({
|
||||||
|
type: EventType.IngestionViewAllClickWarningEvent,
|
||||||
|
executionUrn: urn,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// Try getting the counts via the ingestion report.
|
// Try getting the counts via the ingestion report.
|
||||||
const totalEntitiesIngested = executionResult && getTotalEntitiesIngested(executionResult, entityRegistry);
|
const totalEntitiesIngested = executionResult && getTotalEntitiesIngested(executionResult, entityRegistry);
|
||||||
const entitiesIngestedByTypeFromReport =
|
const entitiesIngestedByTypeFromReport =
|
||||||
@ -245,11 +263,7 @@ export default function IngestedAssets({ id, executionResult }: Props) {
|
|||||||
<Card
|
<Card
|
||||||
title={formatNumber(total)}
|
title={formatNumber(total)}
|
||||||
button={
|
button={
|
||||||
<Button
|
<Button style={{ width: '110px' }} variant="text" onClick={handleViewAllClick}>
|
||||||
style={{ width: '110px' }}
|
|
||||||
variant="text"
|
|
||||||
onClick={() => setShowAssetSearch(true)}
|
|
||||||
>
|
|
||||||
View All
|
View All
|
||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
@ -323,6 +337,8 @@ export default function IngestedAssets({ id, executionResult }: Props) {
|
|||||||
unionType: UnionType.AND,
|
unionType: UnionType.AND,
|
||||||
filters: [{ field: 'runId', values: [id] }],
|
filters: [{ field: 'runId', values: [id] }],
|
||||||
}}
|
}}
|
||||||
|
isViewAllMode
|
||||||
|
handleViewAllClickWarning={handleViewAllClickWarning}
|
||||||
onClose={() => setShowAssetSearch(false)}
|
onClose={() => setShowAssetSearch(false)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -58,6 +58,8 @@ public enum DataHubUsageEventType {
|
|||||||
INGESTION_TEST_CONNECTION_EVENT("IngestionTestConnectionEvent"),
|
INGESTION_TEST_CONNECTION_EVENT("IngestionTestConnectionEvent"),
|
||||||
INGESTION_EXECUTION_RESULT_VIEWED_EVENT("IngestionExecutionResultViewedEvent"),
|
INGESTION_EXECUTION_RESULT_VIEWED_EVENT("IngestionExecutionResultViewedEvent"),
|
||||||
INGESTION_SOURCE_CONFIGURATION_IMPRESSION_EVENT("IngestionSourceConfigurationImpressionEvent"),
|
INGESTION_SOURCE_CONFIGURATION_IMPRESSION_EVENT("IngestionSourceConfigurationImpressionEvent"),
|
||||||
|
INGESTION_VIEW_ALL_CLICK_EVENT("IngestionViewAllClickEvent"),
|
||||||
|
INGESTION_VIEW_ALL_CLICK_WARNING_EVENT("IngestionViewAllClickWarningEvent"),
|
||||||
CREATE_INGESTION_SOURCE_EVENT("CreateIngestionSourceEvent"),
|
CREATE_INGESTION_SOURCE_EVENT("CreateIngestionSourceEvent"),
|
||||||
UPDATE_INGESTION_SOURCE_EVENT("UpdateIngestionSourceEvent"),
|
UPDATE_INGESTION_SOURCE_EVENT("UpdateIngestionSourceEvent"),
|
||||||
DELETE_INGESTION_SOURCE_EVENT("DeleteIngestionSourceEvent"),
|
DELETE_INGESTION_SOURCE_EVENT("DeleteIngestionSourceEvent"),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user