1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-09-05 17:53:12 +02:00

feat: project list frontend filter

This commit is contained in:
Tymoteusz Czech 2024-04-15 18:31:48 +02:00
parent 279d3431eb
commit df29999d38
No known key found for this signature in database
GPG Key ID: 133555230D88D75F

View File

@ -1,5 +1,6 @@
import { useContext, useEffect, useMemo, useState } from 'react'; import { useContext, useMemo, useState } from 'react';
import { Link, useNavigate, useSearchParams } from 'react-router-dom'; import { Link, useNavigate } from 'react-router-dom';
import { BooleanParam, StringParam, withDefault } from 'use-query-params';
import { mutate } from 'swr'; import { mutate } from 'swr';
import { getProjectFetcher } from 'hooks/api/getters/useProject/getProjectFetcher'; import { getProjectFetcher } from 'hooks/api/getters/useProject/getProjectFetcher';
import useProjects from 'hooks/api/getters/useProjects/useProjects'; import useProjects from 'hooks/api/getters/useProjects/useProjects';
@ -31,6 +32,7 @@ import { ReactComponent as ProPlanIconLight } from 'assets/icons/pro-enterprise-
import { safeRegExp } from '@server/util/escape-regex'; import { safeRegExp } from '@server/util/escape-regex';
import { ThemeMode } from 'component/common/ThemeMode/ThemeMode'; import { ThemeMode } from 'component/common/ThemeMode/ThemeMode';
import { useUiFlag } from 'hooks/useUiFlag'; import { useUiFlag } from 'hooks/useUiFlag';
import { usePersistentTableState } from 'hooks/usePersistentTableState';
import { useProfile } from 'hooks/api/getters/useProfile/useProfile'; import { useProfile } from 'hooks/api/getters/useProfile/useProfile';
import { shouldDisplayInMyProjects } from './should-display-in-my-projects'; import { shouldDisplayInMyProjects } from './should-display-in-my-projects';
@ -75,8 +77,6 @@ const StyledButtonGroup = styled(ToggleButtonGroup)(({ theme }) => ({
}, },
})); }));
type PageQueryType = Partial<Record<'search', string>>;
type projectMap = { type projectMap = {
[index: string]: boolean; [index: string]: boolean;
}; };
@ -131,32 +131,34 @@ export const ProjectListNew = () => {
const { projects, loading, error, refetch } = useProjects(); const { projects, loading, error, refetch } = useProjects();
const [fetchedProjects, setFetchedProjects] = useState<projectMap>({}); const [fetchedProjects, setFetchedProjects] = useState<projectMap>({});
const { isOss } = useUiConfig(); const { isOss } = useUiConfig();
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md')); const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
const [searchParams, setSearchParams] = useSearchParams();
const [searchValue, setSearchValue] = useState(
searchParams.get('search') || '',
);
const showProjectFilterButtons = useUiFlag('projectListFilterMyProjects'); const showProjectFilterButtons = useUiFlag('projectListFilterMyProjects');
const filters = ['All projects', 'My projects'];
const [filter, setFilter] = useState(filters[0]);
const myProjects = new Set(useProfile().profile?.projects || []); const myProjects = new Set(useProfile().profile?.projects || []);
useEffect(() => { const filterOptions = [
const tableState: PageQueryType = {}; {
if (searchValue) { label: 'All projects',
tableState.search = searchValue; value: false,
} },
{
label: 'My projects',
value: true,
},
];
setSearchParams(tableState, { const stateConfig = {
replace: true, myProjects: withDefault(BooleanParam, false),
}); search: withDefault(StringParam, ''),
}, [searchValue, setSearchParams]); };
const [filterState, setFilterState] = usePersistentTableState(
`projects-list`,
stateConfig,
);
const searchValue = filterState.search;
const filteredProjects = useMemo(() => { const filteredProjects = useMemo(() => {
const preFilteredProjects = const preFilteredProjects =
showProjectFilterButtons && filter === 'My projects' showProjectFilterButtons && filterState.myProjects
? projects.filter(shouldDisplayInMyProjects(myProjects)) ? projects.filter(shouldDisplayInMyProjects(myProjects))
: projects; : projects;
@ -176,7 +178,13 @@ export const ProjectListNew = () => {
} }
return 0; return 0;
}); });
}, [projects, searchValue, filter, myProjects, showProjectFilterButtons]); }, [
projects,
searchValue,
filterState.myProjects,
myProjects,
showProjectFilterButtons,
]);
const handleHover = (projectId: string) => { const handleHover = (projectId: string) => {
if (fetchedProjects[projectId]) { if (fetchedProjects[projectId]) {
@ -218,21 +226,23 @@ export const ProjectListNew = () => {
aria-label='project list filter' aria-label='project list filter'
size='small' size='small'
color='primary' color='primary'
value={filter} value={filterState.myProjects}
exclusive exclusive
onChange={(event, value) => { onChange={(event, value) => {
if (value !== null) { if (value !== null) {
setFilter(value); setFilterState({
myProjects: value,
});
} }
}} }}
> >
{filters.map((filter) => { {filterOptions.map((filter) => {
return ( return (
<ToggleButton <ToggleButton
key={filter} key={`${filter.value}`}
value={filter} value={filter.value}
> >
{filter} {filter.label}
</ToggleButton> </ToggleButton>
); );
})} })}
@ -248,7 +258,9 @@ export const ProjectListNew = () => {
<> <>
<Search <Search
initialValue={searchValue} initialValue={searchValue}
onChange={setSearchValue} onChange={(search) =>
setFilterState({ search })
}
/> />
<PageHeader.Divider /> <PageHeader.Divider />
</> </>
@ -274,7 +286,9 @@ export const ProjectListNew = () => {
show={ show={
<Search <Search
initialValue={searchValue} initialValue={searchValue}
onChange={setSearchValue} onChange={(search) =>
setFilterState({ search })
}
/> />
} }
/> />