From 5a01edae7a835996fbc38bee9a693131a1fda8d2 Mon Sep 17 00:00:00 2001 From: Sheen Capadngan Date: Sat, 29 Jun 2024 01:02:28 +0800 Subject: [PATCH] misc: added favorites to app layout selection --- frontend/src/layouts/AppLayout/AppLayout.tsx | 81 ++++++++++++++++--- .../src/pages/org/[id]/overview/index.tsx | 77 ++++++++++++------ 2 files changed, 123 insertions(+), 35 deletions(-) diff --git a/frontend/src/layouts/AppLayout/AppLayout.tsx b/frontend/src/layouts/AppLayout/AppLayout.tsx index 72351df88..7fc10df13 100644 --- a/frontend/src/layouts/AppLayout/AppLayout.tsx +++ b/frontend/src/layouts/AppLayout/AppLayout.tsx @@ -5,13 +5,14 @@ /* eslint-disable no-var */ /* eslint-disable func-names */ -import { useEffect, useMemo } from "react"; +import { useCallback, useEffect, useMemo } from "react"; import { Controller, useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; import Image from "next/image"; import Link from "next/link"; import { useRouter } from "next/router"; import { faGithub, faSlack } from "@fortawesome/free-brands-svg-icons"; +import { faStar } from "@fortawesome/free-regular-svg-icons"; import { faAngleDown, faArrowLeft, @@ -23,7 +24,8 @@ import { faInfo, faMobile, faPlus, - faQuestion + faQuestion, + faStar as faSolidStar } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { yupResolver } from "@hookform/resolvers/yup"; @@ -72,6 +74,8 @@ import { useRegisterUserAction, useSelectOrganization } from "@app/hooks/api"; +import { useUpdateUserProjectFavorites } from "@app/hooks/api/users/mutation"; +import { useGetUserProjectFavorites } from "@app/hooks/api/users/queries"; import { navigateUserToOrg } from "@app/views/Login/Login.utils"; import { CreateOrgModal } from "@app/views/Org/components"; @@ -122,6 +126,11 @@ export const AppLayout = ({ children }: LayoutProps) => { const { workspaces, currentWorkspace } = useWorkspace(); const { orgs, currentOrg } = useOrganization(); + const { data: projectFavorites } = useGetUserProjectFavorites(currentOrg?.id!); + const { mutateAsync: updateUserProjectFavorites } = useUpdateUserProjectFavorites(); + const nonFavoriteWorkspaces = workspaces.filter((w) => !projectFavorites?.includes(w.id)); + const favoriteWorkspaces = workspaces.filter((w) => projectFavorites?.includes(w.id)); + const { user } = useUser(); const { subscription } = useSubscription(); const workspaceId = currentWorkspace?.id || ""; @@ -271,6 +280,30 @@ export const AppLayout = ({ children }: LayoutProps) => { } }; + const addProjectToFavorites = useCallback( + (projectId: string) => { + if (currentOrg?.id) { + updateUserProjectFavorites({ + orgId: currentOrg?.id, + projectFavorites: [...(projectFavorites || []), projectId] + }); + } + }, + [currentOrg, projectFavorites] + ); + + const removeProjectFromFavorites = useCallback( + (projectId: string) => { + if (currentOrg?.id) { + updateUserProjectFavorites({ + orgId: currentOrg?.id, + projectFavorites: [...(projectFavorites || []).filter((entry) => entry !== projectId)] + }); + } + }, + [currentOrg, projectFavorites] + ); + return ( <>
@@ -451,19 +484,47 @@ export const AppLayout = ({ children }: LayoutProps) => { dropdownContainerClassName="text-bunker-200 bg-mineshaft-800 border border-mineshaft-600 z-50 max-h-96 border-gray-700" >
- {workspaces + {[...favoriteWorkspaces, ...nonFavoriteWorkspaces] .filter((ws) => ws.orgId === currentOrg?.id) .map(({ id, name }) => ( - - {name} - +
+ + {name} + +
+
+ {projectFavorites?.includes(id) ? ( + { + e.stopPropagation(); + removeProjectFromFavorites(id); + }} + /> + ) : ( + { + e.stopPropagation(); + addProjectToFavorites(id); + }} + /> + )} +
+
))}

diff --git a/frontend/src/pages/org/[id]/overview/index.tsx b/frontend/src/pages/org/[id]/overview/index.tsx index 5ff425c37..14fd6b5b0 100644 --- a/frontend/src/pages/org/[id]/overview/index.tsx +++ b/frontend/src/pages/org/[id]/overview/index.tsx @@ -619,7 +619,7 @@ const OrganizationPage = withPermission( {isFavorite ? ( { e.stopPropagation(); removeProjectFromFavorites(workspace.id); @@ -628,7 +628,7 @@ const OrganizationPage = withPermission( ) : ( { e.stopPropagation(); addProjectToFavorites(workspace.id); @@ -651,6 +651,49 @@ const OrganizationPage = withPermission( ); + const renderProjectListItem = (workspace: Workspace, isFavorite: boolean, index: number) => ( + // eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events +
{ + router.push(`/project/${workspace.id}/secrets/overview`); + localStorage.setItem("projectData.id", workspace.id); + }} + key={workspace.id} + className={`min-w-72 group grid h-14 cursor-pointer grid-cols-6 border-t border-l border-r border-mineshaft-600 bg-mineshaft-800 px-6 hover:bg-mineshaft-700 ${ + index === 0 && "rounded-t-md" + } ${index === filteredWorkspaces.length - 1 && "rounded-b-md border-b"}`} + > +
+ +
{workspace.name}
+
+
+
+ {workspace.environments?.length || 0} environments +
+ {isFavorite ? ( + { + e.stopPropagation(); + removeProjectFromFavorites(workspace.id); + }} + /> + ) : ( + { + e.stopPropagation(); + addProjectToFavorites(workspace.id); + }} + /> + )} +
+
+ ); + const projectsGridView = ( <> {favoriteWorkspaces.length > 0 && ( @@ -701,29 +744,13 @@ const OrganizationPage = withPermission( ))} - {filteredWorkspaces.map((workspace, ind) => ( - // eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events -
{ - router.push(`/project/${workspace.id}/secrets/overview`); - localStorage.setItem("projectData.id", workspace.id); - }} - key={workspace.id} - className={`min-w-72 group grid h-14 cursor-pointer grid-cols-6 border-t border-l border-r border-mineshaft-600 bg-mineshaft-800 px-6 hover:bg-mineshaft-700 ${ - ind === 0 && "rounded-t-md" - } ${ind === filteredWorkspaces.length - 1 && "rounded-b-md border-b"}`} - > -
- -
{workspace.name}
-
-
-
- {workspace.environments?.length || 0} environments -
-
-
- ))} + {[...favoriteWorkspaces, ...nonFavoriteWorkspaces].map((workspace, ind) => + renderProjectListItem( + workspace, + favoriteWorkspaces.some((w) => w.id === workspace.id), + ind + ) + )} );