diff --git a/datahub-web-react/src/app/search/AdvancedSearchAddFilterSelect.tsx b/datahub-web-react/src/app/search/AdvancedSearchAddFilterSelect.tsx new file mode 100644 index 00000000000000..5130ecc3b628b0 --- /dev/null +++ b/datahub-web-react/src/app/search/AdvancedSearchAddFilterSelect.tsx @@ -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; + onFilterFieldSelect: (value) => void; +} + +const { Option } = Select; + +export const AdvancedSearchAddFilterSelect = ({ selectedFilters, onFilterFieldSelect }: Props) => { + return ( + + ); +}; diff --git a/datahub-web-react/src/app/search/AdvancedSearchFilterOverallUnionTypeSelect.tsx b/datahub-web-react/src/app/search/AdvancedSearchFilterOverallUnionTypeSelect.tsx new file mode 100644 index 00000000000000..d74a4c2bc3229b --- /dev/null +++ b/datahub-web-react/src/app/search/AdvancedSearchFilterOverallUnionTypeSelect.tsx @@ -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 ( + <> + { + if ((newValue as any) !== unionType) { + onUpdate(newValue as any); + } + }} + size="small" + dropdownMatchSelectWidth={false} + > + + + + + ); +}; diff --git a/datahub-web-react/src/app/search/AdvancedSearchFilters.tsx b/datahub-web-react/src/app/search/AdvancedSearchFilters.tsx new file mode 100644 index 00000000000000..dedbec352ffc0d --- /dev/null +++ b/datahub-web-react/src/app/search/AdvancedSearchFilters.tsx @@ -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; + facets: Array; + onFilterSelect: (newFilters: Array) => void; + onChangeUnionType: (unionType: UnionType) => void; + unionType?: UnionType; +} + +export const AdvancedSearchFilters = ({ + unionType = UnionType.AND, + facets, + selectedFilters, + onFilterSelect, + onChangeUnionType, +}: Props) => { + const [filterField, setFilterField] = useState(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 ( + + + {selectedFilters?.length >= 2 && ( + + Show results that match{' '} + onChangeUnionType(newValue)} + /> + + )} + {selectedFilters.map((filter) => ( + 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 && ( + facet.field === filterField) || null} + onCloseModal={() => setFilterField(null)} + filterField={filterField} + onSelect={onSelectValueFromModal} + /> + )} + {selectedFilters?.length === 0 && No filters applied, add one above.} + + ); +};