-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(advanced search): Add component to show all advanced search filt…
…ers & add new filter (#6058) * adding select value modal * expanding gql model and adding advanced search filter component * adding advanced search filters component * removing console logs * improve readability * responding to comments
- Loading branch information
1 parent
4792ac5
commit 7359d92
Showing
3 changed files
with
219 additions
and
0 deletions.
There are no files selected for viewing
51 changes: 51 additions & 0 deletions
51
datahub-web-react/src/app/search/AdvancedSearchAddFilterSelect.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { Select } from 'antd'; | ||
import * as React from 'react'; | ||
import styled from 'styled-components'; | ||
import { PlusOutlined } from '@ant-design/icons'; | ||
|
||
import { FacetFilterInput } from '../../types.generated'; | ||
import { FIELD_TO_LABEL } from './utils/constants'; | ||
|
||
const StyledPlus = styled(PlusOutlined)` | ||
margin-right: 6px; | ||
`; | ||
|
||
interface Props { | ||
selectedFilters: Array<FacetFilterInput>; | ||
onFilterFieldSelect: (value) => void; | ||
} | ||
|
||
const { Option } = Select; | ||
|
||
export const AdvancedSearchAddFilterSelect = ({ selectedFilters, onFilterFieldSelect }: Props) => { | ||
return ( | ||
<Select | ||
value={{ | ||
value: 'value', | ||
label: ( | ||
<div> | ||
<StyledPlus /> | ||
Add Filter | ||
</div> | ||
), | ||
}} | ||
labelInValue | ||
style={{ padding: 6, fontWeight: 500 }} | ||
onChange={onFilterFieldSelect} | ||
dropdownMatchSelectWidth={false} | ||
filterOption={(_, option) => option?.value === 'null'} | ||
> | ||
{Object.keys(FIELD_TO_LABEL) | ||
.sort((a, b) => FIELD_TO_LABEL[a].localeCompare(FIELD_TO_LABEL[b])) | ||
.map((key) => ( | ||
<Option | ||
// disable the `entity` option if they already have an entity filter selected | ||
disabled={key === 'entity' && !!selectedFilters.find((filter) => filter.field === 'entity')} | ||
value={key} | ||
> | ||
{FIELD_TO_LABEL[key]} | ||
</Option> | ||
))} | ||
</Select> | ||
); | ||
}; |
44 changes: 44 additions & 0 deletions
44
datahub-web-react/src/app/search/AdvancedSearchFilterOverallUnionTypeSelect.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { Select } from 'antd'; | ||
import React from 'react'; | ||
import styled from 'styled-components/macro'; | ||
|
||
import { ANTD_GRAY } from '../entity/shared/constants'; | ||
import { UnionType } from './utils/constants'; | ||
|
||
type Props = { | ||
unionType: UnionType; | ||
onUpdate: (newValue: UnionType) => void; | ||
}; | ||
|
||
const { Option } = Select; | ||
|
||
const StyledSelect = styled(Select)` | ||
border-radius: 5px; | ||
background: ${ANTD_GRAY[4]}; | ||
:hover { | ||
background: ${ANTD_GRAY[4.5]}; | ||
} | ||
`; | ||
|
||
export const AdvancedSearchFilterOverallUnionTypeSelect = ({ unionType, onUpdate }: Props) => { | ||
return ( | ||
<> | ||
<StyledSelect | ||
showArrow={false} | ||
bordered={false} | ||
// these values are just for display purposes- the actual value is the unionType prop | ||
value={unionType === UnionType.AND ? 'all filters' : 'any filter'} | ||
onChange={(newValue) => { | ||
if ((newValue as any) !== unionType) { | ||
onUpdate(newValue as any); | ||
} | ||
}} | ||
size="small" | ||
dropdownMatchSelectWidth={false} | ||
> | ||
<Option value={UnionType.AND}>all filters</Option> | ||
<Option value={UnionType.OR}>any filter</Option> | ||
</StyledSelect> | ||
</> | ||
); | ||
}; |
124 changes: 124 additions & 0 deletions
124
datahub-web-react/src/app/search/AdvancedSearchFilters.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
import * as React from 'react'; | ||
import { useState } from 'react'; | ||
import styled from 'styled-components'; | ||
|
||
import { FacetFilterInput, FacetMetadata, SearchCondition } from '../../types.generated'; | ||
import { ANTD_GRAY } from '../entity/shared/constants'; | ||
import { AdvancedSearchFilter } from './AdvancedSearchFilter'; | ||
import { AdvancedSearchFilterOverallUnionTypeSelect } from './AdvancedSearchFilterOverallUnionTypeSelect'; | ||
import { AdvancedFilterSelectValueModal } from './AdvancedFilterSelectValueModal'; | ||
import { FIELDS_THAT_USE_CONTAINS_OPERATOR, UnionType } from './utils/constants'; | ||
import { AdvancedSearchAddFilterSelect } from './AdvancedSearchAddFilterSelect'; | ||
|
||
export const SearchFilterWrapper = styled.div` | ||
min-height: 100%; | ||
overflow: auto; | ||
margin-top: 6px; | ||
margin-left: 12px; | ||
margin-right: 12px; | ||
&::-webkit-scrollbar { | ||
height: 12px; | ||
width: 1px; | ||
background: #f2f2f2; | ||
} | ||
&::-webkit-scrollbar-thumb { | ||
background: #cccccc; | ||
-webkit-border-radius: 1ex; | ||
-webkit-box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.75); | ||
} | ||
`; | ||
|
||
const AnyAllSection = styled.div` | ||
padding: 6px; | ||
color: ${ANTD_GRAY[8]}; | ||
`; | ||
|
||
const EmptyStateSection = styled.div` | ||
border-radius: 5px; | ||
background-color: ${ANTD_GRAY[2]}; | ||
padding: 22px; | ||
margin-top: 10px; | ||
`; | ||
|
||
interface Props { | ||
selectedFilters: Array<FacetFilterInput>; | ||
facets: Array<FacetMetadata>; | ||
onFilterSelect: (newFilters: Array<FacetFilterInput>) => void; | ||
onChangeUnionType: (unionType: UnionType) => void; | ||
unionType?: UnionType; | ||
} | ||
|
||
export const AdvancedSearchFilters = ({ | ||
unionType = UnionType.AND, | ||
facets, | ||
selectedFilters, | ||
onFilterSelect, | ||
onChangeUnionType, | ||
}: Props) => { | ||
const [filterField, setFilterField] = useState<null | string>(null); | ||
|
||
const onFilterFieldSelect = (value) => { | ||
setFilterField(value.value); | ||
}; | ||
|
||
const onSelectValueFromModal = (values) => { | ||
if (!filterField) return; | ||
|
||
const newFilter: FacetFilterInput = { | ||
field: filterField, | ||
values: values as string[], | ||
value: '', // TODO(Gabe): remove once we refactor the model | ||
condition: FIELDS_THAT_USE_CONTAINS_OPERATOR.includes(filterField) | ||
? SearchCondition.Contain | ||
: SearchCondition.Equal, | ||
}; | ||
onFilterSelect([...selectedFilters, newFilter]); | ||
}; | ||
|
||
return ( | ||
<SearchFilterWrapper> | ||
<AdvancedSearchAddFilterSelect | ||
selectedFilters={selectedFilters} | ||
onFilterFieldSelect={onFilterFieldSelect} | ||
/> | ||
{selectedFilters?.length >= 2 && ( | ||
<AnyAllSection> | ||
Show results that match{' '} | ||
<AdvancedSearchFilterOverallUnionTypeSelect | ||
unionType={unionType} | ||
onUpdate={(newValue) => onChangeUnionType(newValue)} | ||
/> | ||
</AnyAllSection> | ||
)} | ||
{selectedFilters.map((filter) => ( | ||
<AdvancedSearchFilter | ||
facet={facets.find((facet) => facet.field === filter.field) || facets[0]} | ||
filter={filter} | ||
onClose={() => { | ||
onFilterSelect(selectedFilters.filter((f) => f !== filter)); | ||
}} | ||
onUpdate={(newValue) => { | ||
onFilterSelect( | ||
selectedFilters.map((f) => { | ||
if (f === filter) { | ||
return newValue; | ||
} | ||
return f; | ||
}), | ||
); | ||
}} | ||
/> | ||
))} | ||
{filterField && ( | ||
<AdvancedFilterSelectValueModal | ||
facet={facets.find((facet) => facet.field === filterField) || null} | ||
onCloseModal={() => setFilterField(null)} | ||
filterField={filterField} | ||
onSelect={onSelectValueFromModal} | ||
/> | ||
)} | ||
{selectedFilters?.length === 0 && <EmptyStateSection>No filters applied, add one above.</EmptyStateSection>} | ||
</SearchFilterWrapper> | ||
); | ||
}; |