diff --git a/packages/grafana-ui/src/components/Table/Filter.tsx b/packages/grafana-ui/src/components/Table/Filter.tsx index 5f4474782cf..dd5b4ca8ba6 100644 --- a/packages/grafana-ui/src/components/Table/Filter.tsx +++ b/packages/grafana-ui/src/components/Table/Filter.tsx @@ -1,12 +1,13 @@ import { css, cx } from '@emotion/css'; import React, { useCallback, useMemo, useRef, useState } from 'react'; -import { Field, GrafanaTheme2 } from '@grafana/data'; +import { Field, GrafanaTheme2, SelectableValue } from '@grafana/data'; import { Popover } from '..'; import { useStyles2 } from '../../themes'; import { Icon } from '../Icon/Icon'; +import { REGEX_OPERATOR } from './FilterList'; import { FilterPopup } from './FilterPopup'; import { TableStyles } from './styles'; @@ -23,6 +24,8 @@ export const Filter = ({ column, field, tableStyles }: Props) => { const filterEnabled = useMemo(() => Boolean(column.filterValue), [column.filterValue]); const onShowPopover = useCallback(() => setPopoverVisible(true), [setPopoverVisible]); const onClosePopover = useCallback(() => setPopoverVisible(false), [setPopoverVisible]); + const [searchFilter, setSearchFilter] = useState(''); + const [operator, setOperator] = useState>(REGEX_OPERATOR); if (!field || !field.config.custom?.filterable) { return null; @@ -37,7 +40,18 @@ export const Filter = ({ column, field, tableStyles }: Props) => { {isPopoverVisible && ref.current && ( } + content={ + + } placement="bottom-start" referenceElement={ref.current} show diff --git a/packages/grafana-ui/src/components/Table/FilterList.tsx b/packages/grafana-ui/src/components/Table/FilterList.tsx index 7d24c3847d1..9a65476e6f4 100644 --- a/packages/grafana-ui/src/components/Table/FilterList.tsx +++ b/packages/grafana-ui/src/components/Table/FilterList.tsx @@ -1,5 +1,5 @@ import { css, cx } from '@emotion/css'; -import React, { useCallback, useMemo, useState } from 'react'; +import React, { useCallback, useMemo } from 'react'; import { FixedSizeList as List } from 'react-window'; import { GrafanaTheme2, formattedValueToString, getValueFormat, SelectableValue } from '@grafana/data'; @@ -13,6 +13,10 @@ interface Props { onChange: (options: SelectableValue[]) => void; caseSensitive?: boolean; showOperators?: boolean; + searchFilter: string; + setSearchFilter: (value: string) => void; + operator: SelectableValue; + setOperator: (item: SelectableValue) => void; } const ITEM_HEIGHT = 28; @@ -33,7 +37,7 @@ const operatorSelectableValues: { [key: string]: SelectableValue } = { }, }; const OPERATORS = Object.values(operatorSelectableValues); -const REGEX_OPERATOR = operatorSelectableValues['Contains']; +export const REGEX_OPERATOR = operatorSelectableValues['Contains']; const XPR_OPERATOR = operatorSelectableValues['Expression']; const comparableValue = (value: string): string | number | Date | boolean => { @@ -61,9 +65,17 @@ const comparableValue = (value: string): string | number | Date | boolean => { return value; }; -export const FilterList = ({ options, values, caseSensitive, showOperators, onChange }: Props) => { - const [operator, setOperator] = useState>(REGEX_OPERATOR); - const [searchFilter, setSearchFilter] = useState(''); +export const FilterList = ({ + options, + values, + caseSensitive, + showOperators, + onChange, + searchFilter, + setSearchFilter, + operator, + setOperator, +}: Props) => { const regex = useMemo(() => new RegExp(searchFilter, caseSensitive ? undefined : 'i'), [searchFilter, caseSensitive]); const items = useMemo( () => diff --git a/packages/grafana-ui/src/components/Table/FilterPopup.tsx b/packages/grafana-ui/src/components/Table/FilterPopup.tsx index 422dfe7a4f5..fcb4803f9bc 100644 --- a/packages/grafana-ui/src/components/Table/FilterPopup.tsx +++ b/packages/grafana-ui/src/components/Table/FilterPopup.tsx @@ -15,9 +15,21 @@ interface Props { tableStyles: TableStyles; onClose: () => void; field?: Field; + searchFilter: string; + setSearchFilter: (value: string) => void; + operator: SelectableValue; + setOperator: (item: SelectableValue) => void; } -export const FilterPopup = ({ column: { preFilteredRows, filterValue, setFilter }, onClose, field }: Props) => { +export const FilterPopup = ({ + column: { preFilteredRows, filterValue, setFilter }, + onClose, + field, + searchFilter, + setSearchFilter, + operator, + setOperator, +}: Props) => { const theme = useTheme2(); const uniqueValues = useMemo(() => calculateUniqueFieldValues(preFilteredRows, field), [preFilteredRows, field]); const options = useMemo(() => valuesToOptions(uniqueValues), [uniqueValues]); @@ -73,6 +85,10 @@ export const FilterPopup = ({ column: { preFilteredRows, filterValue, setFilter options={options} caseSensitive={matchCase} showOperators={true} + searchFilter={searchFilter} + setSearchFilter={setSearchFilter} + operator={operator} + setOperator={setOperator} />