Skip to content

Commit

Permalink
Merge branch 'master' into pluginv2
Browse files Browse the repository at this point in the history
  • Loading branch information
vishalkSimplify authored Jul 26, 2023
2 parents 9e45dfb + 2495b50 commit 58a63c6
Show file tree
Hide file tree
Showing 19 changed files with 447 additions and 81 deletions.
31 changes: 22 additions & 9 deletions datahub-web-react/src/app/search/SimpleSearchFilters.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import * as React from 'react';
import { useEffect, useState } from 'react';
import { FacetFilterInput, FacetMetadata } from '../../types.generated';
import { FilterScenarioType } from './filters/render/types';
import { useFilterRendererRegistry } from './filters/render/useFilterRenderer';
import { SimpleSearchFilter } from './SimpleSearchFilter';
import { ENTITY_FILTER_NAME, ENTITY_INDEX_FILTER_NAME, LEGACY_ENTITY_FILTER_NAME } from './utils/constants';

Expand Down Expand Up @@ -53,17 +55,28 @@ export const SimpleSearchFilters = ({ facets, selectedFilters, onFilterSelect, l
return TOP_FILTERS.indexOf(facetA.field) - TOP_FILTERS.indexOf(facetB.field);
});

const filterRendererRegistry = useFilterRendererRegistry();

return (
<>
{sortedFacets.map((facet) => (
<SimpleSearchFilter
key={`${facet.displayName}-${facet.field}`}
facet={facet}
selectedFilters={cachedProps.selectedFilters}
onFilterSelect={onFilterSelectAndSetCache}
defaultDisplayFilters={TOP_FILTERS.includes(facet.field)}
/>
))}
{sortedFacets.map((facet) => {
return filterRendererRegistry.hasRenderer(facet.field) ? (
filterRendererRegistry.render(facet.field, {
scenario: FilterScenarioType.SEARCH_V1,
filter: facet,
activeFilters: selectedFilters,
onChangeFilters: onFilterSelect,
})
) : (
<SimpleSearchFilter
key={`${facet.displayName}-${facet.field}`}
facet={facet}
selectedFilters={cachedProps.selectedFilters}
onFilterSelect={onFilterSelectAndSetCache}
defaultDisplayFilters={TOP_FILTERS.includes(facet.field)}
/>
);
})}
</>
);
};
28 changes: 20 additions & 8 deletions datahub-web-react/src/app/search/filters/BasicFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import {
SEARCH_RESULTS_ADVANCED_SEARCH_ID,
SEARCH_RESULTS_FILTERS_ID,
} from '../../onboarding/config/SearchOnboardingConfig';
import { useFilterRendererRegistry } from './render/useFilterRenderer';
import { FilterScenarioType } from './render/types';

const NUM_VISIBLE_FILTER_DROPDOWNS = 5;

Expand Down Expand Up @@ -80,19 +82,29 @@ export default function BasicFilters({
const shouldShowMoreDropdown = filters && filters.length > NUM_VISIBLE_FILTER_DROPDOWNS + 1;
const visibleFilters = shouldShowMoreDropdown ? filters?.slice(0, NUM_VISIBLE_FILTER_DROPDOWNS) : filters;
const hiddenFilters = shouldShowMoreDropdown ? filters?.slice(NUM_VISIBLE_FILTER_DROPDOWNS) : [];
const filterRendererRegistry = useFilterRendererRegistry();

return (
<span id={SEARCH_RESULTS_FILTERS_ID}>
<FlexSpacer>
<FlexWrapper>
{visibleFilters?.map((filter) => (
<SearchFilter
key={filter.field}
filter={filter}
activeFilters={activeFilters}
onChangeFilters={onChangeFilters}
/>
))}
{visibleFilters?.map((filter) => {
return filterRendererRegistry.hasRenderer(filter.field) ? (
filterRendererRegistry.render(filter.field, {
scenario: FilterScenarioType.SEARCH_V2_PRIMARY,
filter,
activeFilters,
onChangeFilters,
})
) : (
<SearchFilter
key={filter.field}
filter={filter}
activeFilters={activeFilters}
onChangeFilters={onChangeFilters}
/>
);
})}
{hiddenFilters && hiddenFilters.length > 0 && (
<MoreFilters
filters={hiddenFilters}
Expand Down
22 changes: 3 additions & 19 deletions datahub-web-react/src/app/search/filters/MoreFilterOption.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,10 @@ import React from 'react';
import { FacetFilterInput, FacetMetadata } from '../../../types.generated';
import { capitalizeFirstLetterOnly } from '../../shared/textUtil';
import OptionsDropdownMenu from './OptionsDropdownMenu';
import { ANTD_GRAY } from '../../entity/shared/constants';
import useSearchFilterDropdown from './useSearchFilterDropdown';
import { IconWrapper } from './SearchFilterView';
import { getFilterDropdownIcon } from './utils';

const OptionWrapper = styled.div<{ isActive: boolean; isOpen: boolean }>`
padding: 5px 12px;
font-size: 14px;
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
&:hover {
background-color: ${ANTD_GRAY[3]};
}
${(props) => props.isActive && `color: ${props.theme.styles['primary-color']};`}
${(props) => props.isOpen && `background-color: ${ANTD_GRAY[3]};`}
`;
import { MoreFilterOptionLabel } from './styledComponents';

const IconNameWrapper = styled.span`
display: flex;
Expand Down Expand Up @@ -72,7 +56,7 @@ export default function MoreFilterOption({ filter, activeFilters, onChangeFilter
/>
)}
>
<OptionWrapper
<MoreFilterOptionLabel
onClick={() => updateIsMenuOpen(!isMenuOpen)}
isActive={!!numActiveFilters}
isOpen={isMenuOpen}
Expand All @@ -83,7 +67,7 @@ export default function MoreFilterOption({ filter, activeFilters, onChangeFilter
{capitalizeFirstLetterOnly(filter.displayName)} {numActiveFilters ? `(${numActiveFilters}) ` : ''}
</IconNameWrapper>
<RightOutlined style={{ fontSize: '12px', height: '12px' }} />
</OptionWrapper>
</MoreFilterOptionLabel>
</Dropdown>
);
}
34 changes: 23 additions & 11 deletions datahub-web-react/src/app/search/filters/MoreFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import styled from 'styled-components';
import { FacetFilterInput, FacetMetadata } from '../../../types.generated';
import MoreFilterOption from './MoreFilterOption';
import { getNumActiveFiltersForGroupOfFilters } from './utils';
import { DropdownLabel } from './SearchFilterView';
import { SearchFilterLabel } from './styledComponents';
import useSearchFilterAnalytics from './useSearchFilterAnalytics';
import { useFilterRendererRegistry } from './render/useFilterRenderer';
import { FilterScenarioType } from './render/types';

const StyledPlus = styled(PlusOutlined)`
svg {
Expand Down Expand Up @@ -36,6 +38,7 @@ export default function MoreFilters({ filters, activeFilters, onChangeFilters }:
const { trackShowMoreEvent } = useSearchFilterAnalytics();
const [isMenuOpen, setIsMenuOpen] = useState(false);
const numActiveFilters = getNumActiveFiltersForGroupOfFilters(activeFilters, filters);
const filterRendererRegistry = useFilterRendererRegistry();

function updateFiltersAndClose(newFilters: FacetFilterInput[]) {
onChangeFilters(newFilters);
Expand All @@ -52,23 +55,32 @@ export default function MoreFilters({ filters, activeFilters, onChangeFilters }:
trigger={['click']}
dropdownRender={() => (
<DropdownMenu padding="4px 0px">
{filters.map((filter) => (
<MoreFilterOption
key={filter.field}
filter={filter}
activeFilters={activeFilters}
onChangeFilters={updateFiltersAndClose}
/>
))}
{filters.map((filter) => {
return filterRendererRegistry.hasRenderer(filter.field) ? (
filterRendererRegistry.render(filter.field, {
scenario: FilterScenarioType.SEARCH_V2_SECONDARY,
filter,
activeFilters,
onChangeFilters: updateFiltersAndClose,
})
) : (
<MoreFilterOption
key={filter.field}
filter={filter}
activeFilters={activeFilters}
onChangeFilters={updateFiltersAndClose}
/>
);
})}
</DropdownMenu>
)}
open={isMenuOpen}
onOpenChange={onOpenChange}
>
<DropdownLabel data-testid="more-filters-dropdown" isActive={!!numActiveFilters}>
<SearchFilterLabel data-testid="more-filters-dropdown" isActive={!!numActiveFilters}>
<StyledPlus />
More Filters {numActiveFilters ? `(${numActiveFilters}) ` : ''}
</DropdownLabel>
</SearchFilterLabel>
</Dropdown>
);
}
26 changes: 4 additions & 22 deletions datahub-web-react/src/app/search/filters/SearchFilterView.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,11 @@
import { CaretDownFilled } from '@ant-design/icons';
import { Button, Dropdown } from 'antd';
import { Dropdown } from 'antd';
import React from 'react';
import styled from 'styled-components';
import OptionsDropdownMenu from './OptionsDropdownMenu';
import { capitalizeFirstLetterOnly } from '../../shared/textUtil';
import { DisplayedFilterOption } from './mapFilterOption';
import { ANTD_GRAY } from '../../entity/shared/constants';

export const DropdownLabel = styled(Button)<{ isActive: boolean }>`
font-size: 14px;
font-weight: 700;
margin-right: 12px;
border: 1px solid ${ANTD_GRAY[5]};
border-radius: 8px;
display: flex;
align-items: center;
box-shadow: none;
${(props) =>
props.isActive &&
`
background-color: ${props.theme.styles['primary-color']};
border: 1px solid ${props.theme.styles['primary-color']};
color: white;
`}
`;
import { SearchFilterLabel } from './styledComponents';

export const IconWrapper = styled.div`
margin-right: 8px;
Expand Down Expand Up @@ -76,15 +58,15 @@ export default function SearchFilterView({
/>
)}
>
<DropdownLabel
<SearchFilterLabel
onClick={() => updateIsMenuOpen(!isMenuOpen)}
isActive={!!numActiveFilters}
data-testid={`filter-dropdown-${capitalizeFirstLetterOnly(displayName)}`}
>
{filterIcon && <IconWrapper>{filterIcon}</IconWrapper>}
{capitalizeFirstLetterOnly(displayName)} {numActiveFilters ? `(${numActiveFilters}) ` : ''}
<CaretDownFilled style={{ fontSize: '12px', height: '12px' }} />
</DropdownLabel>
</SearchFilterLabel>
</Dropdown>
);
}
29 changes: 29 additions & 0 deletions datahub-web-react/src/app/search/filters/render/FilterRenderer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { FilterRenderProps } from './types';

/**
* Base interface used for custom search filter renderers
*
*/
export interface FilterRenderer {
/**
* The filter field that is rendered by this renderer
*/
field: string;

/**
* Renders the filter
*/
render: (props: FilterRenderProps) => JSX.Element;

/**
* Ant-design icon associated with the Entity. For a list of all candidate icons, see
* https://ant.design/components/icon/
*/
icon: () => JSX.Element;

/**
* Returns a label for rendering the value of a particular field, e.g. for rendering the selected set of filters.
* Currently only for rendering the selected value set below Search V2 top-bar.
*/
valueLabel: (value: string) => JSX.Element;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { FilterRenderer } from './FilterRenderer';
import { FilterRenderProps } from './types';

function validatedGet<K, V>(key: K, map: Map<K, V>): V {
if (map.has(key)) {
return map.get(key) as V;
}
throw new Error(`Unrecognized key ${key} provided in map ${JSON.stringify(map)}`);
}

/**
* Serves as a singleton registry for custom filter renderers.
*/
export default class FilterRendererRegistry {
renderers: Array<FilterRenderer> = new Array<FilterRenderer>();

fieldNameToRenderer: Map<string, FilterRenderer> = new Map<string, FilterRenderer>();

register(renderer: FilterRenderer) {
this.renderers.push(renderer);
this.fieldNameToRenderer.set(renderer.field, renderer);
}

hasRenderer(field: string): boolean {
return this.fieldNameToRenderer.has(field);
}

render(field: string, props: FilterRenderProps): React.ReactNode {
const renderer = validatedGet(field, this.fieldNameToRenderer);
return renderer.render(props);
}

getValueLabel(field: string, value: string): React.ReactNode {
const renderer = validatedGet(field, this.fieldNameToRenderer);
return renderer.valueLabel(value);
}

getIcon(field: string): React.ReactNode {
const renderer = validatedGet(field, this.fieldNameToRenderer);
return renderer.icon();
}
}
Loading

0 comments on commit 58a63c6

Please sign in to comment.