mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Table panel: Fix filter not working for special characters and allow filter's case sensitivity control (#40458)
* Fix filter not working for special characters and allow case sansitive filter control * Memoize regex
This commit is contained in:
parent
80a7401cfb
commit
6201b5b1d9
@ -10,18 +10,26 @@ interface Props {
|
||||
values: SelectableValue[];
|
||||
options: SelectableValue[];
|
||||
onChange: (options: SelectableValue[]) => void;
|
||||
caseSensitive?: boolean;
|
||||
}
|
||||
|
||||
const ITEM_HEIGHT = 28;
|
||||
const MIN_HEIGHT = ITEM_HEIGHT * 5;
|
||||
|
||||
export const FilterList: FC<Props> = ({ options, values, onChange }) => {
|
||||
export const FilterList: FC<Props> = ({ options, values, caseSensitive, onChange }) => {
|
||||
const theme = useTheme2();
|
||||
const styles = getStyles(theme);
|
||||
const [searchFilter, setSearchFilter] = useState('');
|
||||
const regex = useMemo(() => new RegExp(searchFilter, caseSensitive ? undefined : 'i'), [searchFilter, caseSensitive]);
|
||||
const items = useMemo(
|
||||
() => options.filter((option) => option.label?.toLowerCase().includes(searchFilter.toLowerCase())),
|
||||
[options, searchFilter]
|
||||
() =>
|
||||
options.filter((option) => {
|
||||
if (option.label === undefined) {
|
||||
return false;
|
||||
}
|
||||
return regex.test(option.label);
|
||||
}),
|
||||
[options, regex]
|
||||
);
|
||||
const gutter = theme.spacing.gridSize;
|
||||
const height = useMemo(() => Math.min(items.length * ITEM_HEIGHT, MIN_HEIGHT) + gutter, [gutter, items.length]);
|
||||
|
@ -3,8 +3,8 @@ import { Field, GrafanaTheme, SelectableValue } from '@grafana/data';
|
||||
import { css, cx } from '@emotion/css';
|
||||
|
||||
import { TableStyles } from './styles';
|
||||
import { stylesFactory, useStyles } from '../../themes';
|
||||
import { Button, ClickOutsideWrapper, HorizontalGroup, Label, VerticalGroup } from '..';
|
||||
import { stylesFactory, useStyles, useTheme2 } from '../../themes';
|
||||
import { Button, ClickOutsideWrapper, HorizontalGroup, IconButton, Label, VerticalGroup } from '..';
|
||||
import { FilterList } from './FilterList';
|
||||
import { calculateUniqueFieldValues, getFilteredOptions, valuesToOptions } from './utils';
|
||||
|
||||
@ -16,10 +16,12 @@ interface Props {
|
||||
}
|
||||
|
||||
export const FilterPopup: FC<Props> = ({ column: { preFilteredRows, filterValue, setFilter }, onClose, field }) => {
|
||||
const theme = useTheme2();
|
||||
const uniqueValues = useMemo(() => calculateUniqueFieldValues(preFilteredRows, field), [preFilteredRows, field]);
|
||||
const options = useMemo(() => valuesToOptions(uniqueValues), [uniqueValues]);
|
||||
const filteredOptions = useMemo(() => getFilteredOptions(options, filterValue), [options, filterValue]);
|
||||
const [values, setValues] = useState<SelectableValue[]>(filteredOptions);
|
||||
const [matchCase, setMatchCase] = useState(false);
|
||||
|
||||
const onCancel = useCallback((event?: React.MouseEvent) => onClose(), [onClose]);
|
||||
|
||||
@ -49,9 +51,19 @@ export const FilterPopup: FC<Props> = ({ column: { preFilteredRows, filterValue,
|
||||
<div className={cx(styles.filterContainer)} onClick={stopPropagation}>
|
||||
<VerticalGroup spacing="lg">
|
||||
<VerticalGroup spacing="xs">
|
||||
<Label>Filter by values:</Label>
|
||||
<HorizontalGroup justify="space-between" align="center">
|
||||
<Label className={styles.label}>Filter by values:</Label>
|
||||
<IconButton
|
||||
name="text-fields"
|
||||
tooltip="Match case"
|
||||
style={{ color: matchCase ? theme.colors.text.link : theme.colors.text.disabled }}
|
||||
onClick={() => {
|
||||
setMatchCase((s) => !s);
|
||||
}}
|
||||
/>
|
||||
</HorizontalGroup>
|
||||
<div className={cx(styles.listDivider)} />
|
||||
<FilterList onChange={setValues} values={values} options={options} />
|
||||
<FilterList onChange={setValues} values={values} options={options} caseSensitive={matchCase} />
|
||||
</VerticalGroup>
|
||||
<HorizontalGroup spacing="lg">
|
||||
<HorizontalGroup>
|
||||
@ -96,6 +108,9 @@ const getStyles = stylesFactory((theme: GrafanaTheme) => ({
|
||||
border-top: ${theme.border.width.sm} solid ${theme.colors.border2};
|
||||
padding: ${theme.spacing.xs} ${theme.spacing.md};
|
||||
`,
|
||||
label: css`
|
||||
margin-bottom: 0;
|
||||
`,
|
||||
}));
|
||||
|
||||
const stopPropagation = (event: React.MouseEvent) => {
|
||||
|
@ -143,6 +143,7 @@ export const getAvailableIcons = () =>
|
||||
'sync',
|
||||
'table',
|
||||
'tag-alt',
|
||||
'text-fields',
|
||||
'times',
|
||||
'toggle-on',
|
||||
'trash-alt',
|
||||
|
Loading…
Reference in New Issue
Block a user