From 3d60c2acd00891667b78efe062df7d173eccbd14 Mon Sep 17 00:00:00 2001 From: Thomas Heartman Date: Mon, 15 Apr 2024 13:17:53 +0200 Subject: [PATCH] feat: allow you to filter for "my projects" (#6855) This change adds filtering functionality to the project list filter buttons. In this case, "my projects" is defined as any project that is marked as a favorite OR (inclusive or) that you are a part of, as defined by your user profile. --- .../project/ProjectList/ProjectList.tsx | 16 +++++++-- .../should-display-in-my-projects.test.ts | 34 +++++++++++++++++++ .../should-display-in-my-projects.ts | 6 ++++ 3 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 frontend/src/component/project/ProjectList/should-display-in-my-projects.test.ts create mode 100644 frontend/src/component/project/ProjectList/should-display-in-my-projects.ts diff --git a/frontend/src/component/project/ProjectList/ProjectList.tsx b/frontend/src/component/project/ProjectList/ProjectList.tsx index 44d85caeeb..43db5f361b 100644 --- a/frontend/src/component/project/ProjectList/ProjectList.tsx +++ b/frontend/src/component/project/ProjectList/ProjectList.tsx @@ -31,6 +31,8 @@ import { ReactComponent as ProPlanIconLight } from 'assets/icons/pro-enterprise- import { safeRegExp } from '@server/util/escape-regex'; import { ThemeMode } from 'component/common/ThemeMode/ThemeMode'; import { useUiFlag } from 'hooks/useUiFlag'; +import { useProfile } from 'hooks/api/getters/useProfile/useProfile'; +import { shouldDisplayInMyProjects } from './should-display-in-my-projects'; const StyledDivContainer = styled('div')(({ theme }) => ({ display: 'flex', @@ -139,6 +141,7 @@ export const ProjectListNew = () => { const showProjectFilterButtons = useUiFlag('projectListFilterMyProjects'); const filters = ['All projects', 'My projects']; const [filter, setFilter] = useState(filters[0]); + const myProjects = new Set(useProfile().profile?.projects || []); useEffect(() => { const tableState: PageQueryType = {}; @@ -152,11 +155,18 @@ export const ProjectListNew = () => { }, [searchValue, setSearchParams]); const filteredProjects = useMemo(() => { + const preFilteredProjects = + showProjectFilterButtons && filter === 'My projects' + ? projects.filter(shouldDisplayInMyProjects(myProjects)) + : projects; + const regExp = safeRegExp(searchValue, 'i'); return ( searchValue - ? projects.filter((project) => regExp.test(project.name)) - : projects + ? preFilteredProjects.filter((project) => + regExp.test(project.name), + ) + : preFilteredProjects ).sort((a, b) => { if (a?.favorite && !b?.favorite) { return -1; @@ -166,7 +176,7 @@ export const ProjectListNew = () => { } return 0; }); - }, [projects, searchValue]); + }, [projects, searchValue, filter, myProjects, showProjectFilterButtons]); const handleHover = (projectId: string) => { if (fetchedProjects[projectId]) { diff --git a/frontend/src/component/project/ProjectList/should-display-in-my-projects.test.ts b/frontend/src/component/project/ProjectList/should-display-in-my-projects.test.ts new file mode 100644 index 0000000000..7f2ed351c0 --- /dev/null +++ b/frontend/src/component/project/ProjectList/should-display-in-my-projects.test.ts @@ -0,0 +1,34 @@ +import type { IProjectCard } from 'interfaces/project'; +import { shouldDisplayInMyProjects } from './should-display-in-my-projects'; + +test('should check that the project is a user project OR that it is a favorite', () => { + const myProjects = new Set(['my1', 'my2', 'my3']); + + const projects: IProjectCard[] = [ + { id: 'my1', favorite: true }, + { id: 'my2', favorite: false }, + { id: 'my3' }, + { id: 'fave-but-not-mine', favorite: true }, + { id: 'not-mine-not-fave', favorite: false }, + { id: 'not-mine-undefined-fave' }, + ].map(({ id, favorite }) => ({ + name: 'name', + id, + createdAt: '2024-04-15T11:09:52+02:00', + health: 100, + description: 'description', + featureCount: 100, + mode: 'open', + memberCount: 10, + favorite, + })); + + const filtered = projects.filter(shouldDisplayInMyProjects(myProjects)); + + expect(filtered).toMatchObject([ + { id: 'my1' }, + { id: 'my2' }, + { id: 'my3' }, + { id: 'fave-but-not-mine' }, + ]); +}); diff --git a/frontend/src/component/project/ProjectList/should-display-in-my-projects.ts b/frontend/src/component/project/ProjectList/should-display-in-my-projects.ts new file mode 100644 index 0000000000..742eb624e4 --- /dev/null +++ b/frontend/src/component/project/ProjectList/should-display-in-my-projects.ts @@ -0,0 +1,6 @@ +import type { IProjectCard } from 'interfaces/project'; + +export const shouldDisplayInMyProjects = + (myProjectIds: Set) => + (project: IProjectCard): boolean => + project.favorite || myProjectIds.has(project.id);