Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Table: Add select/unselect all column values to table filter #79290

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -191,6 +191,8 @@ To filter column values, click the filter (funnel) icon next to a column title.

Click the check box next to the values that you want to display. Enter text in the search field at the top to show those values in the display so that you can select them rather than scroll to find them.

Click the check box next to the Ok/Cancel buttons to add or remove all displayed values to/from the filter.
ahuarte47 marked this conversation as resolved.
Show resolved Hide resolved

### Clear column filters

Columns with filters applied have a blue funnel displayed next to the title.
Expand Down
48 changes: 47 additions & 1 deletion packages/grafana-ui/src/components/Table/FilterList.tsx
@@ -1,4 +1,4 @@
import { css } from '@emotion/css';
import { css, cx } from '@emotion/css';
import React, { useCallback, useMemo, useState } from 'react';
import { FixedSizeList as List } from 'react-window';

Expand Down Expand Up @@ -30,6 +30,24 @@ export const FilterList = ({ options, values, caseSensitive, onChange }: Props)
}),
[options, regex]
);
const selectedItems = useMemo(() => items.filter((item) => values.includes(item)), [items, values]);

const selectCheckValue = useMemo(() => items.length === selectedItems.length, [items, selectedItems]);
const selectCheckIndeterminate = useMemo(
() => selectedItems.length > 0 && items.length > selectedItems.length,
[items, selectedItems]
);
const selectCheckLabel = useMemo(
() => (selectedItems.length ? `${selectedItems.length} selected` : `Select all`),
[selectedItems]
);
const selectCheckDescription = useMemo(
() =>
items.length !== selectedItems.length
? 'Click to add all displayed values to the filter'
: 'Click to remove all displayed values from the filter',
[items, selectedItems]
);

const styles = useStyles2(getStyles);
const theme = useTheme2();
Expand All @@ -47,6 +65,16 @@ export const FilterList = ({ options, values, caseSensitive, onChange }: Props)
[onChange, values]
);

const onSelectChanged = useCallback(() => {
if (items.length === selectedItems.length) {
const newValues = values.filter((item) => !items.includes(item));
onChange(newValues);
} else {
const newValues = [...new Set([...values, ...items])];
onChange(newValues);
}
}, [onChange, values, items, selectedItems]);

return (
<VerticalGroup spacing="md">
<FilterInput placeholder="Filter values" onChange={setSearchFilter} value={searchFilter} />
Expand All @@ -72,6 +100,18 @@ export const FilterList = ({ options, values, caseSensitive, onChange }: Props)
}}
</List>
)}
{items.length && (
<VerticalGroup spacing="xs">
<div className={cx(styles.selectDivider)} />
<Checkbox
value={selectCheckValue}
indeterminate={selectCheckIndeterminate}
label={selectCheckLabel}
description={selectCheckDescription}
onChange={onSelectChanged}
/>
</VerticalGroup>
)}
</VerticalGroup>
);
};
Expand All @@ -92,4 +132,10 @@ const getStyles = (theme: GrafanaTheme2) => ({
backgroundColor: theme.colors.action.hover,
},
}),
selectDivider: css({
label: 'selectDivider',
width: '100%',
borderTop: `1px solid ${theme.colors.border.medium}`,
padding: theme.spacing(0.5, 2),
}),
});