Skip to content

Commit

Permalink
Merge pull request #779 from rszwajko/typeAheadFilter
Browse files Browse the repository at this point in the history
Add type-ahead search to GroupedEnumFilter
  • Loading branch information
yaacov authored Nov 28, 2023
2 parents 6bc0dcd + d280b5e commit 00b6a69
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 11 deletions.
47 changes: 36 additions & 11 deletions packages/common/src/components/Filter/GroupedEnumFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {

import { EnumValue } from '../../utils';

import { FilterTypeProps } from './types';
import { FilterTypeProps, InlineFilter } from './types';

/**
* This Filter type enables selecting one or many enum values that are separated by groups.
Expand Down Expand Up @@ -40,7 +40,8 @@ export const GroupedEnumFilter = ({
supportedGroups = [],
placeholderLabel,
showFilter = true,
}: FilterTypeProps) => {
hasInlineFilter = false,
}: FilterTypeProps & InlineFilter) => {
const [isExpanded, setExpanded] = useState(false);

// simplify lookup
Expand Down Expand Up @@ -76,6 +77,36 @@ export const GroupedEnumFilter = ({
compareTo: (option) => option.id === id && option.groupId === groupId,
} as SelectOptionObject);

const options = supportedGroups.map(({ label, groupId }) => (
<SelectGroup key={groupId} label={label}>
{supportedEnumValues
.filter((item) => item.groupId === groupId)
.map(({ id, label }) => (
<SelectOption key={id} value={toSelectOption({ id, label, groupId })} />
))}
</SelectGroup>
));

const onFilter = (_, textInput) => {
if (textInput === '') {
return options;
}

const filteredGroups = options
.map((group) => {
const filteredGroup = React.cloneElement(group, {
children: group.props.children.filter((item) => {
// options are not plain strings but the our toString() method
// converts them in a meaningful way
return item.props.value.toString().toLowerCase().includes(textInput.toLowerCase());
}),
});
if (filteredGroup.props.children.length > 0) return filteredGroup;
})
.filter((newGroup) => newGroup);
return filteredGroups;
};

return (
<>
{/**
Expand Down Expand Up @@ -123,16 +154,10 @@ export const GroupedEnumFilter = ({
placeholderText={placeholderLabel}
isOpen={isExpanded}
onToggle={setExpanded}
hasInlineFilter={hasInlineFilter}
onFilter={onFilter}
>
{supportedGroups.map(({ label, groupId }) => (
<SelectGroup key={groupId} label={label}>
{supportedEnumValues
.filter((item) => item.groupId === groupId)
.map(({ id, label }) => (
<SelectOption key={id} value={toSelectOption({ id, label, groupId })} />
))}
</SelectGroup>
))}
{options}
</Select>,
)}
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';

import { GroupedEnumFilter } from './GroupedEnumFilter';
import { FilterTypeProps } from './types';

/**
* GroupedEnumFilter with inline search enabled.
*/
export const SearchableGroupedEnumFilter = (props: FilterTypeProps) => (
<GroupedEnumFilter {...props} hasInlineFilter={true} />
);
1 change: 1 addition & 0 deletions packages/common/src/components/Filter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export * from './DateRangeFilter';
export * from './EnumFilter';
export * from './FreetextFilter';
export * from './GroupedEnumFilter';
export * from './SearchableGroupedEnumFilter';
export * from './SwitchFilter';
export * from './types';
// @endindex
4 changes: 4 additions & 0 deletions packages/common/src/components/Filter/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,7 @@ export interface FilterTypeProps {
/** Text that explains how to use the filter. */
helperText?: string | React.ReactNode;
}

export interface InlineFilter {
hasInlineFilter?: boolean;
}
8 changes: 8 additions & 0 deletions packages/common/src/components/FilterGroup/matchers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
EnumFilter,
FreetextFilter,
GroupedEnumFilter,
SearchableGroupedEnumFilter,
SwitchFilter,
} from '../Filter';

Expand Down Expand Up @@ -103,6 +104,11 @@ const groupedEnumMatcher = {
matchValue: enumMatcher.matchValue,
};

const searchableGroupedEnumMatcher = {
filterType: 'searchableGroupedEnum',
matchValue: enumMatcher.matchValue,
};

const dateMatcher = {
filterType: 'date',
matchValue: (value: string) => (filter: string) => areSameDayInUTCZero(value, filter),
Expand All @@ -122,6 +128,7 @@ export const defaultValueMatchers: ValueMatcher[] = [
freetextMatcher,
enumMatcher,
groupedEnumMatcher,
searchableGroupedEnumMatcher,
sliderMatcher,
dateMatcher,
dateRangeMatcher,
Expand All @@ -134,6 +141,7 @@ export const defaultSupportedFilters: Record<string, FilterRenderer> = {
freetext: FreetextFilter,
groupedEnum: GroupedEnumFilter,
slider: SwitchFilter,
searchableGroupedEnum: SearchableGroupedEnumFilter,
};

/**
Expand Down

0 comments on commit 00b6a69

Please sign in to comment.