From bc539e0d01aced29975cff6d2dda529cda128e42 Mon Sep 17 00:00:00 2001 From: Vamsi Krishna <46787868+vamsikrishnamathala@users.noreply.github.com> Date: Thu, 20 Mar 2025 14:03:24 +0530 Subject: [PATCH] [WEB-3175]fix: favorites menu (#6773) * fix: favrotites menu open * fix: open fav menu on starring projec * chore: added constant for hardcoded text --- packages/constants/src/workspace.ts | 1 + .../cycles/list/cycle-list-item-action.tsx | 18 +++++++++++++++--- .../components/modules/module-card-item.tsx | 7 ++++++- .../modules/module-list-item-action.tsx | 6 ++++++ .../pages/editor/header/extra-options.tsx | 16 +++++++++++++--- web/core/components/project/card.tsx | 12 +++++++++++- .../components/views/view-list-item-action.tsx | 15 +++++++++++---- .../sidebar/favorites/favorites-menu.tsx | 3 ++- web/core/hooks/use-page-operations.ts | 16 +++++++++++++--- 9 files changed, 78 insertions(+), 16 deletions(-) diff --git a/packages/constants/src/workspace.ts b/packages/constants/src/workspace.ts index cddc1a56c..06c9fb659 100644 --- a/packages/constants/src/workspace.ts +++ b/packages/constants/src/workspace.ts @@ -325,6 +325,7 @@ export const WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS_LINKS: IWorkspaceSidebarN WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS["projects"], ]; +export const IS_FAVORITE_MENU_OPEN = "is_favorite_menu_open"; export const WORKSPACE_DEFAULT_SEARCH_RESULT: IWorkspaceSearchResults = { results: { workspace: [], diff --git a/web/core/components/cycles/list/cycle-list-item-action.tsx b/web/core/components/cycles/list/cycle-list-item-action.tsx index b7fc40666..bc627fdf2 100644 --- a/web/core/components/cycles/list/cycle-list-item-action.tsx +++ b/web/core/components/cycles/list/cycle-list-item-action.tsx @@ -6,7 +6,14 @@ import { useParams, usePathname, useSearchParams } from "next/navigation"; import { useForm } from "react-hook-form"; import { Eye, Users } from "lucide-react"; // types -import { CYCLE_FAVORITED, CYCLE_UNFAVORITED, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { + CYCLE_FAVORITED, + CYCLE_UNFAVORITED, + EUserPermissions, + EUserPermissionsLevel, + IS_FAVORITE_MENU_OPEN, +} from "@plane/constants"; +import { useLocalStorage } from "@plane/hooks"; import { useTranslation } from "@plane/i18n"; import { ICycle, TCycleGroups } from "@plane/types"; // ui @@ -15,8 +22,6 @@ import { Avatar, AvatarGroup, FavoriteStar, LayersIcon, Tooltip, TransferIcon, s import { CycleQuickActions, TransferIssuesModal } from "@/components/cycles"; import { DateRangeDropdown } from "@/components/dropdowns"; import { ButtonAvatars } from "@/components/dropdowns/member/avatar"; -// constants -// helpers import { getDate } from "@/helpers/date-time.helper"; import { getFileURL } from "@/helpers/file.helper"; // hooks @@ -59,6 +64,12 @@ export const CycleListItemAction: FC = observer((props) => { const { captureEvent } = useEventTracker(); const { allowPermissions } = useUserPermissions(); + // local storage + const { setValue: toggleFavoriteMenu, storedValue: isFavoriteMenuOpen } = useLocalStorage( + IS_FAVORITE_MENU_OPEN, + false + ); + const { getUserDetails } = useMember(); // form @@ -91,6 +102,7 @@ export const CycleListItemAction: FC = observer((props) => { const addToFavoritePromise = addCycleToFavorites(workspaceSlug?.toString(), projectId.toString(), cycleId).then( () => { + if (!isFavoriteMenuOpen) toggleFavoriteMenu(true); captureEvent(CYCLE_FAVORITED, { cycle_id: cycleId, element: "List layout", diff --git a/web/core/components/modules/module-card-item.tsx b/web/core/components/modules/module-card-item.tsx index 9585755ee..2204738cf 100644 --- a/web/core/components/modules/module-card-item.tsx +++ b/web/core/components/modules/module-card-item.tsx @@ -13,7 +13,9 @@ import { MODULE_UNFAVORITED, EUserPermissions, EUserPermissionsLevel, + IS_FAVORITE_MENU_OPEN, } from "@plane/constants"; +import { useLocalStorage } from "@plane/hooks"; import { IModule } from "@plane/types"; import { Card, @@ -30,7 +32,6 @@ import { DateRangeDropdown } from "@/components/dropdowns"; import { ButtonAvatars } from "@/components/dropdowns/member/avatar"; import { ModuleQuickActions } from "@/components/modules"; import { ModuleStatusDropdown } from "@/components/modules/module-status-dropdown"; -// constants // helpers import { getDate, renderFormattedPayloadDate } from "@/helpers/date-time.helper"; import { generateQueryParams } from "@/helpers/router.helper"; @@ -59,6 +60,9 @@ export const ModuleCardItem: React.FC = observer((props) => { const { getUserDetails } = useMember(); const { captureEvent } = useEventTracker(); + // local storage + const { setValue: toggleFavoriteMenu, storedValue } = useLocalStorage(IS_FAVORITE_MENU_OPEN, false); + // derived values const moduleDetails = getModuleById(moduleId); const isEditingAllowed = allowPermissions( @@ -76,6 +80,7 @@ export const ModuleCardItem: React.FC = observer((props) => { const addToFavoritePromise = addModuleToFavorites(workspaceSlug.toString(), projectId.toString(), moduleId).then( () => { + if (!storedValue) toggleFavoriteMenu(true); captureEvent(MODULE_FAVORITED, { module_id: moduleId, element: "Grid layout", diff --git a/web/core/components/modules/module-list-item-action.tsx b/web/core/components/modules/module-list-item-action.tsx index 1f929751d..7a1b37a65 100644 --- a/web/core/components/modules/module-list-item-action.tsx +++ b/web/core/components/modules/module-list-item-action.tsx @@ -12,7 +12,9 @@ import { MODULE_UNFAVORITED, EUserPermissions, EUserPermissionsLevel, + IS_FAVORITE_MENU_OPEN, } from "@plane/constants"; +import { useLocalStorage } from "@plane/hooks"; import { useTranslation } from "@plane/i18n"; import { IModule } from "@plane/types"; // ui @@ -45,6 +47,8 @@ export const ModuleListItemAction: FC = observer((props) => { const { t } = useTranslation(); + // local storage + const { setValue: toggleFavoriteMenu, storedValue } = useLocalStorage(IS_FAVORITE_MENU_OPEN, false); // derived values const moduleStatus = MODULE_STATUS.find((status) => status.value === moduleDetails.status); @@ -63,6 +67,8 @@ export const ModuleListItemAction: FC = observer((props) => { const addToFavoritePromise = addModuleToFavorites(workspaceSlug.toString(), projectId.toString(), moduleId).then( () => { + // open favorites menu if closed + if (!storedValue) toggleFavoriteMenu(true); captureEvent(MODULE_FAVORITED, { module_id: moduleId, element: "Grid layout", diff --git a/web/core/components/pages/editor/header/extra-options.tsx b/web/core/components/pages/editor/header/extra-options.tsx index dfcfee53c..0b81d1452 100644 --- a/web/core/components/pages/editor/header/extra-options.tsx +++ b/web/core/components/pages/editor/header/extra-options.tsx @@ -1,8 +1,12 @@ "use client"; import { observer } from "mobx-react"; +// constants +import { IS_FAVORITE_MENU_OPEN } from "@plane/constants"; // editor import { EditorRefApi } from "@plane/editor"; +// plane hooks +import { useLocalStorage } from "@plane/hooks"; // ui import { ArchiveIcon, FavoriteStar, setToast, TOAST_TYPE, Tooltip } from "@plane/ui"; // components @@ -37,6 +41,11 @@ export const PageExtraOptions: React.FC = observer((props) => { } = page; // use online status const { isOnline } = useOnlineStatus(); + // local storage + const { setValue: toggleFavoriteMenu, storedValue: isFavoriteMenuOpen } = useLocalStorage( + IS_FAVORITE_MENU_OPEN, + false + ); // favorite handler const handleFavorite = () => { if (is_favorite) { @@ -48,13 +57,14 @@ export const PageExtraOptions: React.FC = observer((props) => { }) ); } else { - addToFavorites().then(() => + addToFavorites().then(() => { + if (!isFavoriteMenuOpen) toggleFavoriteMenu(true); setToast({ type: TOAST_TYPE.SUCCESS, title: "Success!", message: "Page added to favorites.", - }) - ); + }); + }); } }; diff --git a/web/core/components/project/card.tsx b/web/core/components/project/card.tsx index 304ecab33..73b7c641d 100644 --- a/web/core/components/project/card.tsx +++ b/web/core/components/project/card.tsx @@ -6,7 +6,8 @@ import Link from "next/link"; import { useParams } from "next/navigation"; import { ArchiveRestoreIcon, Check, ExternalLink, LinkIcon, Lock, Settings, Trash2, UserPlus } from "lucide-react"; // types -import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { EUserPermissions, EUserPermissionsLevel, IS_FAVORITE_MENU_OPEN } from "@plane/constants"; +import { useLocalStorage } from "@plane/hooks"; import type { IProject } from "@plane/types"; // ui import { @@ -68,6 +69,11 @@ export const ProjectCard: React.FC = observer((props) => { const hasMemberRole = project.member_role === EUserPermissions.MEMBER; // archive const isArchived = !!project.archived_at; + // local storage + const { setValue: toggleFavoriteMenu, storedValue: isFavoriteMenuOpen } = useLocalStorage( + IS_FAVORITE_MENU_OPEN, + false + ); const handleAddToFavorites = () => { if (!workspaceSlug) return; @@ -78,6 +84,10 @@ export const ProjectCard: React.FC = observer((props) => { success: { title: "Success!", message: () => "Project added to favorites.", + actionItems: () => { + if (!isFavoriteMenuOpen) toggleFavoriteMenu(true); + return <>; + }, }, error: { title: "Error!", diff --git a/web/core/components/views/view-list-item-action.tsx b/web/core/components/views/view-list-item-action.tsx index 9ec4a0288..eaeb412ef 100644 --- a/web/core/components/views/view-list-item-action.tsx +++ b/web/core/components/views/view-list-item-action.tsx @@ -3,13 +3,13 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { Earth, Lock } from "lucide-react"; // types -import { EViewAccess, EUserPermissions, EUserPermissionsLevel } from "@plane/constants"; +import { EViewAccess, EUserPermissions, EUserPermissionsLevel, IS_FAVORITE_MENU_OPEN } from "@plane/constants"; +import { useLocalStorage } from "@plane/hooks"; import { IProjectView } from "@plane/types"; // ui import { Tooltip, FavoriteStar } from "@plane/ui"; // components import { DeleteProjectViewModal, CreateUpdateProjectViewModal, ViewQuickActions } from "@/components/views"; -// constants // helpers import { calculateTotalFilters } from "@/helpers/filter.helper"; import { getPublishViewLink } from "@/helpers/project-views.helpers"; @@ -37,6 +37,12 @@ export const ViewListItemAction: FC = observer((props) => { const { addViewToFavorites, removeViewFromFavorites } = useProjectView(); const { getUserDetails } = useMember(); + // local storage + const { setValue: toggleFavoriteMenu, storedValue: isFavoriteOpen } = useLocalStorage( + IS_FAVORITE_MENU_OPEN, + false + ); + // derived values const isEditingAllowed = allowPermissions( [EUserPermissions.ADMIN, EUserPermissions.MEMBER], @@ -50,10 +56,11 @@ export const ViewListItemAction: FC = observer((props) => { const publishLink = getPublishViewLink(view?.anchor); // handlers - const handleAddToFavorites = () => { + const handleAddToFavorites = async () => { if (!workspaceSlug || !projectId) return; - addViewToFavorites(workspaceSlug.toString(), projectId.toString(), view.id); + await addViewToFavorites(workspaceSlug.toString(), projectId.toString(), view.id); + if (!isFavoriteOpen) toggleFavoriteMenu(true); }; const handleRemoveFromFavorites = () => { diff --git a/web/core/components/workspace/sidebar/favorites/favorites-menu.tsx b/web/core/components/workspace/sidebar/favorites/favorites-menu.tsx index bbb98aab4..bfd08056d 100644 --- a/web/core/components/workspace/sidebar/favorites/favorites-menu.tsx +++ b/web/core/components/workspace/sidebar/favorites/favorites-menu.tsx @@ -13,6 +13,7 @@ import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import { ChevronRight, FolderPlus } from "lucide-react"; import { Disclosure, Transition } from "@headlessui/react"; +import { IS_FAVORITE_MENU_OPEN } from "@plane/constants"; import { useTranslation } from "@plane/i18n"; // ui import { IFavorite } from "@plane/types"; @@ -54,7 +55,7 @@ export const SidebarFavoritesMenu = observer(() => { const { isMobile } = usePlatformOS(); // local storage - const { setValue: toggleFavoriteMenu, storedValue } = useLocalStorage("is_favorite_menu_open", false); + const { setValue: toggleFavoriteMenu, storedValue } = useLocalStorage(IS_FAVORITE_MENU_OPEN, false); // derived values const isFavoriteMenuOpen = !!storedValue; // refs diff --git a/web/core/hooks/use-page-operations.ts b/web/core/hooks/use-page-operations.ts index d16fd1c04..85862d828 100644 --- a/web/core/hooks/use-page-operations.ts +++ b/web/core/hooks/use-page-operations.ts @@ -1,4 +1,6 @@ import { useMemo } from "react"; +// plane constants +import { IS_FAVORITE_MENU_OPEN } from "@plane/constants"; // plane editor import { EditorRefApi } from "@plane/editor"; // plane types @@ -11,6 +13,8 @@ import { copyUrlToClipboard } from "@/helpers/string.helper"; import { useCollaborativePageActions } from "@/hooks/use-collaborative-page-actions"; // store types import { TPageInstance } from "@/store/pages/base-page"; +// local storage +import useLocalStorage from "./use-local-storage"; export type TPageOperations = { toggleLock: () => void; @@ -46,6 +50,11 @@ export const usePageOperations = ( } = page; // collaborative actions const { executeCollaborativeAction } = useCollaborativePageActions(props); + // local storage + const { setValue: toggleFavoriteMenu, storedValue: isfavoriteMenuOpen } = useLocalStorage( + IS_FAVORITE_MENU_OPEN, + false + ); // page operations const pageOperations: TPageOperations = useMemo(() => { const pageLink = getRedirectionLink(); @@ -141,13 +150,14 @@ export const usePageOperations = ( }) ); } else { - addToFavorites().then(() => + addToFavorites().then(() => { + if (!isfavoriteMenuOpen) toggleFavoriteMenu(true); setToast({ type: TOAST_TYPE.SUCCESS, title: "Success!", message: "Page added to favorites.", - }) - ); + }); + }); } }, toggleLock: async () => {