From ca7853c5a4d7bddb6c0bdbdedd0bc9092f491bca Mon Sep 17 00:00:00 2001
From: Anna Everhart <149417426+annadoesdesign@users.noreply.github.com>
Date: Mon, 5 May 2025 11:44:38 -0700
Subject: [PATCH] Update search results page (#13303)
---
.../components/Pills/utils.ts | 2 +-
.../src/app/searchV2/SearchPage.tsx | 13 +-
.../src/app/searchV2/SearchResults.tsx | 156 +++---------------
.../searchV2/filters/SearchFilterOptions.tsx | 24 ---
.../app/searchV2/filters/SearchFilters.tsx | 135 +++++++++++++--
.../searchV2/filters/SearchFiltersSection.tsx | 18 +-
.../searchV2/recommendation/FilterPill.tsx | 53 ++----
.../recommendation/RecommendedFilters.tsx | 5 -
.../app/sharedV2/search/DownloadButton.tsx | 18 +-
.../src/app/sharedV2/search/EditButton.tsx | 15 +-
.../lineageV2/v2_download_lineage_results.js | 2 +-
11 files changed, 207 insertions(+), 234 deletions(-)
diff --git a/datahub-web-react/src/alchemy-components/components/Pills/utils.ts b/datahub-web-react/src/alchemy-components/components/Pills/utils.ts
index abab592e1f..f1284559f0 100644
--- a/datahub-web-react/src/alchemy-components/components/Pills/utils.ts
+++ b/datahub-web-react/src/alchemy-components/components/Pills/utils.ts
@@ -45,7 +45,7 @@ const getPillVariantStyles = (variant: PillVariantOptions, colorStyles: ColorSty
},
outline: {
backgroundColor: 'transparent',
- border: `1px solid ${colorStyles.primaryColor}`,
+ border: `1px solid ${colorStyles.bgColor}`,
color: colorStyles.primaryColor,
'&:hover': {
backgroundColor: colorStyles.hoverColor,
diff --git a/datahub-web-react/src/app/searchV2/SearchPage.tsx b/datahub-web-react/src/app/searchV2/SearchPage.tsx
index 2ebf74de15..2cce0385b6 100644
--- a/datahub-web-react/src/app/searchV2/SearchPage.tsx
+++ b/datahub-web-react/src/app/searchV2/SearchPage.tsx
@@ -240,17 +240,18 @@ export const SearchPage = () => {
onChangeFilters={onChangeFilters}
onClearFilters={onClearFilters}
onChangeUnionType={onChangeUnionType}
- />
-
+ `
display: flex;
@@ -69,15 +60,12 @@ const ResultContainer = styled.div<{ v2Styles: boolean }>`
`;
const PaginationControlContainer = styled.div`
- padding-top: 16px;
- padding-bottom: 16px;
- text-align: center;
+ padding: 16px;
+ text-align: start;
`;
const PaginationInfoContainer = styled.div<{ v2Styles: boolean }>`
- padding: 12px 24px 14px 24px;
- min-height: 47px;
- border-color: ${(props) => props.theme.styles['border-color-base']};
+ padding: 4px 8px 4px 12px;
display: flex;
justify-content: space-between;
align-items: center;
@@ -97,7 +85,8 @@ const SearchResultsScrollContainer = styled.div<{ $isShowNavBarRedesign?: boolea
const LeftControlsContainer = styled.div`
display: flex;
- gap: 12px;
+ color: ${colors.gray[1700]};
+ gap: 4px;
`;
const StyledTabToolbar = styled.div`
@@ -111,11 +100,6 @@ const StyledTabToolbar = styled.div`
border: 1.5px solid ${ANTD_GRAY[4]};
`;
-const SearchMenuContainer = styled.div`
- display: flex;
- align-items: center;
-`;
-
const SearchResultListContainer = styled.div<{ v2Styles: boolean; $isShowNavBarRedesign?: boolean }>`
display: flex;
flex-direction: column;
@@ -130,41 +114,9 @@ const SearchResultListContainer = styled.div<{ v2Styles: boolean; $isShowNavBarR
margin: ${(props) => (props.$isShowNavBarRedesign ? '5px 4px 5px 0px' : '4px 12px 4px 0px')};
`;
-const CustomSwitch = styled.div`
- background: #F6F6F6;
- border: 1px solid #EBECF0;
- border-radius: 30px;
- display: flex;
- gap: 2px;
- align-items: center;
- padding: 2px;
- width: fit-content;
- justify-content: space-between;
- margin-left: 8px;
-}
-`;
-
-const IconContainer = styled.div<{ isActive?: boolean }>`
- cursor: pointer;
- align-items: center;
- display: flex;
- padding: 4px;
- transition: left 0.5s ease;
-
- ${(props) =>
- props.isActive &&
- `
- background: ${props.theme.styles['primary-color']};
- border-radius: 100%;
- color: white;
- `}
-`;
-
interface Props {
loading: boolean;
- unionType?: UnionType;
query: string;
- viewUrn?: string;
page: number;
searchResponse?: {
start: number;
@@ -175,12 +127,10 @@ interface Props {
matchedFields: MatchedField[];
}[];
} | null;
- availableFilters: Array | null;
selectedFilters: Array;
error: any;
onChangeFilters: (filters: Array) => void;
onChangePage: (page: number) => void;
- downloadSearchResults: (input: DownloadSearchResultsInput) => Promise;
numResultsPerPage: number;
setNumResultsPerPage: (numResults: number) => void;
isSelectMode: boolean;
@@ -198,26 +148,22 @@ interface Props {
export const SearchResults = ({
loading,
- unionType = UnionType.AND,
query,
- viewUrn,
page,
searchResponse,
- availableFilters,
selectedFilters,
error,
onChangeFilters,
onChangePage,
- downloadSearchResults,
numResultsPerPage,
setNumResultsPerPage,
isSelectMode,
selectedEntities,
+ suggestions,
+ setSelectedEntities,
areAllEntitiesSelected,
setAreAllEntitiesSelected,
- suggestions,
setIsSelectMode,
- setSelectedEntities,
onChangeSelectAll,
refetch,
previewType,
@@ -235,10 +181,8 @@ export const SearchResults = ({
showSeparateSiblings,
searchResponse?.searchResults,
);
- const { selectedSortOption, setSelectedSortOption } = useSearchContext();
// For vertical sidebar
const [highlightedIndex, setHighlightedIndex] = useState(0);
- const { isFullViewCard, setIsFullViewCard } = useSearchContext();
const searchResultUrns = combinedSiblingSearchResults.map((result) => result.entity.urn) || [];
const selectedEntityUrns = selectedEntities.map((entity) => entity.urn);
@@ -279,70 +223,8 @@ export const SearchResults = ({
v2Styles={showSearchFiltersV2}
$isShowNavBarRedesign={isShowNavBarRedesign}
>
-
-
-
- Showing{' '}
-
- {lastResultIndex > 0 ? (page - 1) * pageSize + 1 : 0} -{' '}
- {lastResultIndex}
- {' '}
- of{' '}
-
- {totalResults >= 10000
- ? `${formatNumberWithoutAbbreviation(10000)}+`
- : formatNumberWithoutAbbreviation(totalResults)}
- {' '}
- results
-
-
-
-
-
-
- setIsFullViewCard(true)}
- >
-
-
-
-
- setIsFullViewCard(false)}
- >
-
-
-
-
-
-
-
{totalResults > 0 && }
-
+
{isSelectMode && (
)}
+
+
+ Showing{' '}
+
+ {lastResultIndex > 0 ? (page - 1) * pageSize + 1 : 0} -{' '}
+ {lastResultIndex}
+ {' '}
+ of{' '}
+
+ {totalResults >= 10000
+ ? `${formatNumberWithoutAbbreviation(10000)}+`
+ : formatNumberWithoutAbbreviation(totalResults)}
+ {' '}
+ results
+
+
-
-
- Filters
-
-
{loading && !visibleFilters?.length && }
{visibleFilters?.map((filter) => {
return filterRendererRegistry.hasRenderer(filter.field) ? (
diff --git a/datahub-web-react/src/app/searchV2/filters/SearchFilters.tsx b/datahub-web-react/src/app/searchV2/filters/SearchFilters.tsx
index ce4e0e51f6..f5dad7b885 100644
--- a/datahub-web-react/src/app/searchV2/filters/SearchFilters.tsx
+++ b/datahub-web-react/src/app/searchV2/filters/SearchFilters.tsx
@@ -1,9 +1,14 @@
+import { Icon, Tooltip, colors } from '@components';
import React from 'react';
import styled from 'styled-components';
import { SEARCH_RESULTS_FILTERS_ID } from '@app/onboarding/config/SearchOnboardingConfig';
+import { useSearchContext } from '@app/search/context/SearchContext';
import SearchFilterOptions from '@app/searchV2/filters/SearchFilterOptions';
import SelectedSearchFilters from '@app/searchV2/filters/SelectedSearchFilters';
+import { RecommendedFilters } from '@app/searchV2/recommendation/RecommendedFilters';
+import { useGetRecommendedFilters } from '@app/searchV2/recommendation/useGetRecommendedFilters';
+import SearchSortSelect from '@app/searchV2/sorting/SearchSortSelect';
import {
BROWSE_PATH_V2_FILTER_NAME,
COMPLETED_FORMS_COMPLETED_PROMPT_IDS_FILTER_NAME,
@@ -20,22 +25,62 @@ import {
UnionType,
VERIFIED_FORMS_FILTER_NAME,
} from '@app/searchV2/utils/constants';
+import { generateOrFilters } from '@app/searchV2/utils/generateOrFilters';
+import { DownloadSearchResults, DownloadSearchResultsInput } from '@app/searchV2/utils/types';
+import SearchMenuItems from '@app/sharedV2/search/SearchMenuItems';
import { useShowNavBarRedesign } from '@src/app/useShowNavBarRedesign';
import { FacetFilterInput, FacetMetadata } from '@types';
const Container = styled.div<{ $isShowNavBarRedesign?: boolean }>`
- background-color: #ffffff;
+ background-color: ${colors.white};
border-radius: ${(props) =>
props.$isShowNavBarRedesign ? props.theme.styles['border-radius-navbar-redesign'] : '8px'};
- padding: 16px 24px 16px 32px;
- border: 1px solid #e8e8e8;
+ padding: 16px 0px 8px 0px;
+ border: 1px solid ${colors.gray[100]};
box-shadow: ${(props) =>
props.$isShowNavBarRedesign ? props.theme.styles['box-shadow-navbar-redesign'] : '0px 4px 10px 0px #a8a8a840'};
`;
-const FilterSpacer = styled.div`
- margin: 16px 0px;
+const FiltersContainerTop = styled.div`
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ padding-left: 16px;
+ padding-right: 16px;
+ padding-bottom: 8px;
+`;
+
+const CustomSwitch = styled.div`
+ border: 1px solid ${colors.gray[100]};
+ border-radius: 30px;
+ display: flex;
+ gap: 2px;
+ align-items: center;
+ padding: 2px;
+ width: fit-content;
+ justify-content: space-between;
+`;
+
+const IconContainer = styled.div<{ isActive?: boolean }>`
+ cursor: pointer;
+ align-items: center;
+ display: flex;
+ padding: 4px;
+ transition: left 0.5s ease;
+ color: ${colors.gray[1800]};
+
+ ${(props) =>
+ props.isActive &&
+ `
+ background: ${colors.gray[100]};
+ border-radius: 100%;
+ color: ${colors.gray[1700]};
+ `}
+`;
+
+const SelectedFiltersContainer = styled.div`
+ padding: 4px 16px 8px 16px;
`;
// remove legacy filter options as well as new _index and browsePathV2 filter from dropdowns
@@ -56,6 +101,18 @@ const FILTERS_TO_REMOVE = [
PROPOSED_SCHEMA_TAGS_FILTER_NAME,
];
+const ControlsContainer = styled.div`
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ align-self: start;
+`;
+
+const RecommendedFiltersContainer = styled.div`
+ border-top: 1px solid ${colors.gray[100]};
+ padding: 16px 16px 8px 16px;
+`;
+
interface Props {
loading: boolean;
availableFilters: FacetMetadata[];
@@ -65,6 +122,11 @@ interface Props {
onChangeFilters: (newFilters: FacetFilterInput[]) => void;
onChangeUnionType: (unionType: UnionType) => void;
onClearFilters: () => void;
+ query: string;
+ viewUrn?: string;
+ totalResults?: number;
+ setShowSelectMode?: (showSelectMode: boolean) => any;
+ downloadSearchResults: (input: DownloadSearchResultsInput) => Promise;
}
export default function SearchFilters({
@@ -76,24 +138,58 @@ export default function SearchFilters({
onChangeFilters,
onChangeUnionType,
onClearFilters,
+ query,
+ viewUrn,
+ totalResults,
+ setShowSelectMode,
+ downloadSearchResults,
}: Props) {
const isShowNavBarRedesign = useShowNavBarRedesign();
+ const { isFullViewCard, setIsFullViewCard, selectedSortOption, setSelectedSortOption } = useSearchContext();
// Filter out the available filters if `basicFilters` is true
const filteredFilters = (availableFilters || []).filter((f) => !FILTERS_TO_REMOVE.includes(f.field));
const filters = basicFilters ? filteredFilters : availableFilters;
+ const recommendedFilters = useGetRecommendedFilters(filters, activeFilters);
return (
-
+
+
+
+
+
+
+ setIsFullViewCard(true)}>
+
+
+
+
+ setIsFullViewCard(false)}>
+
+
+
+
+
+
+
{activeFilters.length > 0 && (
- <>
-
+
- >
+
+ )}
+ {(totalResults || 0) > 0 && recommendedFilters.length > 0 && (
+
+
+
)}
);
diff --git a/datahub-web-react/src/app/searchV2/filters/SearchFiltersSection.tsx b/datahub-web-react/src/app/searchV2/filters/SearchFiltersSection.tsx
index bc78b547d1..dba55202a4 100644
--- a/datahub-web-react/src/app/searchV2/filters/SearchFiltersSection.tsx
+++ b/datahub-web-react/src/app/searchV2/filters/SearchFiltersSection.tsx
@@ -4,6 +4,7 @@ import styled from 'styled-components';
import { SEARCH_RESULTS_FILTERS_V2_INTRO } from '@app/onboarding/config/SearchOnboardingConfig';
import SearchFilters from '@app/searchV2/filters/SearchFilters';
import { UnionType } from '@app/searchV2/utils/constants';
+import { DownloadSearchResults, DownloadSearchResultsInput } from '@app/searchV2/utils/types';
import { useShowNavBarRedesign } from '@src/app/useShowNavBarRedesign';
import { FacetFilterInput, FacetMetadata } from '@types';
@@ -26,6 +27,11 @@ interface Props {
onChangeFilters: (newFilters: FacetFilterInput[]) => void;
onClearFilters: () => void;
onChangeUnionType: (unionType: UnionType) => void;
+ query: string;
+ viewUrn?: string;
+ totalResults: number;
+ setShowSelectMode?: (showSelectMode: boolean) => any;
+ downloadSearchResults: (input: DownloadSearchResultsInput) => Promise;
}
export default function SearchFiltersSection({
@@ -36,6 +42,11 @@ export default function SearchFiltersSection({
onChangeFilters,
onClearFilters,
onChangeUnionType,
+ query,
+ viewUrn,
+ totalResults,
+ setShowSelectMode,
+ downloadSearchResults,
}: Props) {
const [finalAvailableFilters, setFinalAvailableFilters] = useState(availableFilters);
const isShowNavBarRedesign = useShowNavBarRedesign();
@@ -61,8 +72,13 @@ export default function SearchFiltersSection({
activeFilters={activeFilters}
unionType={unionType}
onChangeFilters={onChangeFilters}
- onChangeUnionType={onChangeUnionType}
onClearFilters={onClearFilters}
+ onChangeUnionType={onChangeUnionType}
+ query={query}
+ viewUrn={viewUrn}
+ totalResults={totalResults}
+ setShowSelectMode={setShowSelectMode}
+ downloadSearchResults={downloadSearchResults}
/>
);
diff --git a/datahub-web-react/src/app/searchV2/recommendation/FilterPill.tsx b/datahub-web-react/src/app/searchV2/recommendation/FilterPill.tsx
index b71ffb4d71..33fa1a18a3 100644
--- a/datahub-web-react/src/app/searchV2/recommendation/FilterPill.tsx
+++ b/datahub-web-react/src/app/searchV2/recommendation/FilterPill.tsx
@@ -1,40 +1,7 @@
-import { Tooltip } from '@components';
+import { Pill, Tooltip } from '@components';
import React from 'react';
-import styled from 'styled-components';
import { RecommendedFilter } from '@app/searchV2/recommendation/types';
-import { getFilterColor } from '@app/searchV2/recommendation/utils';
-
-const Pill = styled.div<{ color: string }>`
- border-radius: 20px;
- padding: 6px 10px;
- background-color: white;
- margin-right: 0px;
- border: 2px solid white;
- :hover {
- opacity: 1;
- cursor: pointer;
- border-color: ${(props) => props.color};
- }
- font-size: 14px;
- display: flex;
- align-items: center;
- box-shadow: ${(props) => props.theme.styles['box-shadow']};
-`;
-
-const Icon = styled.div`
- margin-right: 4px;
- &&&& {
- color: #ffffff;
- }
- display: flex;
-`;
-
-const Text = styled.div`
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
-`;
type Props = {
filter: RecommendedFilter;
@@ -42,7 +9,11 @@ type Props = {
};
export const FilterPill = ({ filter, onToggle }: Props) => {
- const color = getFilterColor(filter.field, filter.value);
+ // Convert the color to a valid ColorValues enum value, defaulting to gray if not found
+
+ // Convert ReactNode label to string
+ const labelString = typeof filter.label === 'string' ? filter.label : filter.label?.toString() || '';
+
return (
{
>
}
>
-
- {filter.icon && {filter.icon}}
- {filter.label}
-
+ filter.icon}
+ color="gray"
+ variant="outline"
+ clickable
+ onPillClick={onToggle}
+ />
);
};
diff --git a/datahub-web-react/src/app/searchV2/recommendation/RecommendedFilters.tsx b/datahub-web-react/src/app/searchV2/recommendation/RecommendedFilters.tsx
index 3f169e0378..60ab29893a 100644
--- a/datahub-web-react/src/app/searchV2/recommendation/RecommendedFilters.tsx
+++ b/datahub-web-react/src/app/searchV2/recommendation/RecommendedFilters.tsx
@@ -10,9 +10,6 @@ import { FacetFilterInput, FacetMetadata, FilterOperator } from '@types';
const FilterPills = styled.div`
display: flex;
flex-direction: row;
- margin-bottom: 8px;
- margin-left: 20px;
- padding-right: 20px;
gap: 8px;
flex-shrink: 0;
overflow-x: auto;
@@ -21,8 +18,6 @@ const FilterPills = styled.div`
&::-webkit-scrollbar {
display: none;
}
-
- mask-image: linear-gradient(to right, rgba(0, 0, 0, 1) 95%, rgba(255, 0, 0, 0.5) 100%, rgba(255, 0, 0, 0) 100%);
`;
type Props = {
diff --git a/datahub-web-react/src/app/sharedV2/search/DownloadButton.tsx b/datahub-web-react/src/app/sharedV2/search/DownloadButton.tsx
index 1ffcc53b85..d3bd16bd02 100644
--- a/datahub-web-react/src/app/sharedV2/search/DownloadButton.tsx
+++ b/datahub-web-react/src/app/sharedV2/search/DownloadButton.tsx
@@ -1,11 +1,9 @@
-import { DownloadOutlined } from '@ant-design/icons';
-import { Button, Tooltip } from '@components';
+import { Button, Tooltip, colors } from '@components';
import React from 'react';
import styled from 'styled-components';
const StyledButton = styled(Button)`
- height: 28px;
- margin: 0px 4px 0px 4px;
+ border: 1px solid ${colors.gray[100]};
`;
type Props = {
@@ -17,8 +15,16 @@ type Props = {
export default function DownloadButton({ setShowDownloadAsCsvModal, isDownloadingCsv, disabled }: Props) {
return (
- setShowDownloadAsCsvModal(true)} disabled={isDownloadingCsv || disabled}>
-
+ setShowDownloadAsCsvModal(true)}
+ disabled={isDownloadingCsv || disabled}
+ isCircle
+ icon={{ icon: 'DownloadSimple', source: 'phosphor' }}
+ variant="text"
+ color="gray"
+ size="sm"
+ data-testid="download-csv-button"
+ >
{isDownloadingCsv ? 'Downloading...' : null}
diff --git a/datahub-web-react/src/app/sharedV2/search/EditButton.tsx b/datahub-web-react/src/app/sharedV2/search/EditButton.tsx
index 22de955d2b..b4a5cc8e9b 100644
--- a/datahub-web-react/src/app/sharedV2/search/EditButton.tsx
+++ b/datahub-web-react/src/app/sharedV2/search/EditButton.tsx
@@ -1,11 +1,9 @@
-import { EditOutlined } from '@ant-design/icons';
-import { Button, Tooltip } from '@components';
+import { Button, Tooltip, colors } from '@components';
import React from 'react';
import styled from 'styled-components';
const StyledButton = styled(Button)`
- height: 28px;
- margin: 0px 4px 0px 4px;
+ border: 1px solid ${colors.gray[100]};
`;
type Props = {
@@ -20,9 +18,12 @@ export default function EditButton({ setShowSelectMode, disabled }: Props) {
onClick={() => setShowSelectMode(true)}
disabled={disabled}
data-testid="search-results-edit-button"
- >
-
-
+ isCircle
+ icon={{ icon: 'PencilSimple', source: 'phosphor' }}
+ variant="text"
+ color="gray"
+ size="sm"
+ />
);
}
diff --git a/smoke-test/tests/cypress/cypress/e2e/lineageV2/v2_download_lineage_results.js b/smoke-test/tests/cypress/cypress/e2e/lineageV2/v2_download_lineage_results.js
index 3b81c5abea..c79eba9b10 100644
--- a/smoke-test/tests/cypress/cypress/e2e/lineageV2/v2_download_lineage_results.js
+++ b/smoke-test/tests/cypress/cypress/e2e/lineageV2/v2_download_lineage_results.js
@@ -23,7 +23,7 @@ const third_degree_plus = [
];
const downloadCsvFile = (filename) => {
cy.get(".ant-list-items").should("be.visible");
- cy.get(".anticon-download").should("be.visible").click();
+ cy.get('[data-testid="download-csv-button"]').should("be.visible").click();
cy.get('[data-testid="download-as-csv-input"]').clear().type(filename);
cy.get('[data-testid="csv-modal-download-button"]').click().wait(5000);
cy.ensureTextNotPresent("Creating CSV");