fix(search): compile possible filter options from available entities (#3370)

* load filters from entities

* fix(search): compile possible filter options from available entities

* rename filter state and add text in case no filter can be applied
This commit is contained in:
Askar
2020-11-25 11:06:39 +01:00
committed by GitHub
parent 3aa7efb3ff
commit 76ff21c2d5
2 changed files with 97 additions and 64 deletions
@@ -49,8 +49,14 @@ export type FiltersState = {
checked: Array<string>;
};
export type FilterOptions = {
kind: Array<string>;
lifecycle: Array<string>;
};
type FiltersProps = {
filters: FiltersState;
filterOptions: FilterOptions;
resetFilters: () => void;
updateSelected: (filter: string) => void;
updateChecked: (filter: string) => void;
@@ -58,16 +64,13 @@ type FiltersProps = {
export const Filters = ({
filters,
filterOptions,
resetFilters,
updateSelected,
updateChecked,
}: FiltersProps) => {
const classes = useStyles();
// TODO: move mocked filters out of filters component to make it more generic
const filter1 = ['All', 'API', 'Component', 'Location', 'Template'];
const filter2 = ['deprecated', 'recommended', 'experimental', 'production'];
return (
<Card className={classes.filters}>
<CardHeader
@@ -79,54 +82,65 @@ export const Filters = ({
}
/>
<Divider />
<CardContent>
<Typography variant="subtitle2">Kind</Typography>
<Select
id="outlined-select"
onChange={(e: React.ChangeEvent<any>) =>
updateSelected(e?.target?.value)
}
variant="outlined"
className={classes.dropdown}
value={filters.selected}
>
{filter1.map(filter => (
<MenuItem
selected={filter === 'All'}
dense
key={filter}
value={filter}
>
{filter}
</MenuItem>
))}
</Select>
</CardContent>
<CardContent>
<Typography variant="subtitle2">Lifecycle</Typography>
<List disablePadding dense>
{filter2.map(filter => (
<ListItem
key={filter}
dense
button
onClick={() => updateChecked(filter)}
>
<Checkbox
edge="start"
disableRipple
className={classes.checkbox}
color="primary"
checked={filters.checked.includes(filter)}
tabIndex={-1}
{filterOptions.kind.length === 0 && filterOptions.lifecycle.length === 0 && (
<CardContent>
<Typography variant="subtitle2">
Filters cannot be applied to available results
</Typography>
</CardContent>
)}
{filterOptions.kind.length > 0 && (
<CardContent>
<Typography variant="subtitle2">Kind</Typography>
<Select
id="outlined-select"
onChange={(e: React.ChangeEvent<any>) =>
updateSelected(e?.target?.value)
}
variant="outlined"
className={classes.dropdown}
value={filters.selected}
>
{filterOptions.kind.map(filter => (
<MenuItem
selected={filter === 'All'}
dense
key={filter}
value={filter}
name={filter}
/>
<ListItemText id={filter} primary={filter} />
</ListItem>
))}
</List>
</CardContent>
>
{filter}
</MenuItem>
))}
</Select>
</CardContent>
)}
{filterOptions.lifecycle.length > 0 && (
<CardContent>
<Typography variant="subtitle2">Lifecycle</Typography>
<List disablePadding dense>
{filterOptions.lifecycle.map(filter => (
<ListItem
key={filter}
dense
button
onClick={() => updateChecked(filter)}
>
<Checkbox
edge="start"
disableRipple
className={classes.checkbox}
color="primary"
checked={filters.checked.includes(filter)}
tabIndex={-1}
value={filter}
name={filter}
/>
<ListItemText id={filter} primary={filter} />
</ListItem>
))}
</List>
</CardContent>
)}
</Card>
);
};
@@ -126,7 +126,7 @@ export const SearchResult = ({ searchQuery }: SearchResultProps) => {
const catalogApi = useApi(catalogApiRef);
const [showFilters, toggleFilters] = useState(false);
const [filters, setFilters] = useState<FiltersState>({
const [selectedFilters, setSelectedFilters] = useState<FiltersState>({
selected: 'All',
checked: [],
});
@@ -146,17 +146,18 @@ export const SearchResult = ({ searchQuery }: SearchResultProps) => {
// apply filters
// filter on selected
if (filters.selected !== 'All') {
if (selectedFilters.selected !== 'All') {
withFilters = results.filter((result: Result) =>
filters.selected.includes(result.kind),
selectedFilters.selected.includes(result.kind),
);
}
// filter on checked
if (filters.checked.length > 0) {
if (selectedFilters.checked.length > 0) {
withFilters = withFilters.filter(
(result: Result) =>
result.lifecycle && filters.checked.includes(result.lifecycle),
result.lifecycle &&
selectedFilters.checked.includes(result.lifecycle),
);
}
@@ -174,7 +175,7 @@ export const SearchResult = ({ searchQuery }: SearchResultProps) => {
setFilteredResults(withFilters);
}
}, [filters, searchQuery, results]);
}, [selectedFilters, searchQuery, results]);
if (loading) {
return <Progress />;
}
@@ -190,41 +191,58 @@ export const SearchResult = ({ searchQuery }: SearchResultProps) => {
}
const resetFilters = () => {
setFilters({
setSelectedFilters({
selected: 'All',
checked: [],
});
};
const updateSelected = (filter: string) => {
setFilters(prevState => ({
setSelectedFilters(prevState => ({
...prevState,
selected: filter,
}));
};
const updateChecked = (filter: string) => {
if (filters.checked.includes(filter)) {
setFilters(prevState => ({
if (selectedFilters.checked.includes(filter)) {
setSelectedFilters(prevState => ({
...prevState,
checked: prevState.checked.filter(item => item !== filter),
}));
return;
}
setFilters(prevState => ({
setSelectedFilters(prevState => ({
...prevState,
checked: [...prevState.checked, filter],
}));
};
const filterOptions = results.reduce(
(acc, curr) => {
if (curr.kind && acc.kind.indexOf(curr.kind) < 0) {
acc.kind.push(curr.kind);
}
if (curr.lifecycle && acc.lifecycle.indexOf(curr.lifecycle) < 0) {
acc.lifecycle.push(curr.lifecycle);
}
return acc;
},
{
kind: [] as Array<string>,
lifecycle: [] as Array<string>,
},
);
return (
<>
<Grid container>
{showFilters && (
<Grid item xs={3}>
<Filters
filters={filters}
filters={selectedFilters}
filterOptions={filterOptions}
resetFilters={resetFilters}
updateSelected={updateSelected}
updateChecked={updateChecked}
@@ -241,7 +259,8 @@ export const SearchResult = ({ searchQuery }: SearchResultProps) => {
searchQuery={searchQuery}
numberOfResults={filteredResults.length}
numberOfSelectedFilters={
(filters.selected !== 'All' ? 1 : 0) + filters.checked.length
(selectedFilters.selected !== 'All' ? 1 : 0) +
selectedFilters.checked.length
}
handleToggleFilters={() => toggleFilters(!showFilters)}
/>