From c9a5893c3f344406fc4aaca945757cf9786ba1a0 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Thu, 13 Jul 2023 19:44:53 +0530 Subject: [PATCH] chore: update favorite projects endpoint (#1522) * chore: upate favorite projects list endpoint * chore: add project button on the sidebar * refactor: sidebar favorite projects workflow --- apps/app/components/issues/modal.tsx | 10 +- apps/app/components/issues/select/project.tsx | 19 +- .../project/create-project-modal.tsx | 2 +- .../project/delete-project-modal.tsx | 42 ++-- apps/app/components/project/sidebar-list.tsx | 221 ++++-------------- .../project/single-project-card.tsx | 54 +++-- .../project/single-sidebar-project.tsx | 86 ++++++- apps/app/constants/fetch-keys.ts | 16 +- apps/app/hooks/use-projects.tsx | 11 +- .../projects/[projectId]/settings/control.tsx | 16 +- .../[projectId]/settings/features.tsx | 35 ++- .../projects/[projectId]/settings/index.tsx | 15 +- apps/app/services/project.service.ts | 20 +- apps/app/types/projects.d.ts | 12 - 14 files changed, 251 insertions(+), 308 deletions(-) diff --git a/apps/app/components/issues/modal.tsx b/apps/app/components/issues/modal.tsx index 4bcdc5c7e..d034afb11 100644 --- a/apps/app/components/issues/modal.tsx +++ b/apps/app/components/issues/modal.tsx @@ -7,7 +7,6 @@ import useSWR, { mutate } from "swr"; // headless ui import { Dialog, Transition } from "@headlessui/react"; // services -import projectService from "services/project.service"; import modulesService from "services/modules.service"; import issuesService from "services/issues.service"; import inboxServices from "services/inbox.service"; @@ -18,6 +17,7 @@ import useCalendarIssuesView from "hooks/use-calendar-issues-view"; import useToast from "hooks/use-toast"; import useInboxView from "hooks/use-inbox-view"; import useSpreadsheetIssuesView from "hooks/use-spreadsheet-issues-view"; +import useProjects from "hooks/use-projects"; // components import { IssueForm } from "components/issues"; // types @@ -27,7 +27,6 @@ import { PROJECT_ISSUES_DETAILS, PROJECT_ISSUES_LIST, USER_ISSUE, - PROJECTS_LIST, SUB_ISSUES, PROJECT_ISSUES_LIST_WITH_PARAMS, CYCLE_ISSUES_WITH_PARAMS, @@ -83,6 +82,8 @@ export const CreateUpdateIssueModal: React.FC = ({ const { params: spreadsheetParams } = useSpreadsheetIssuesView(); const { user } = useUser(); + const { projects } = useProjects(); + const { setToastAlert } = useToast(); if (cycleId) prePopulateData = { ...prePopulateData, cycle: cycleId as string }; @@ -102,11 +103,6 @@ export const CreateUpdateIssueModal: React.FC = ({ : null ); - const { data: projects } = useSWR( - workspaceSlug ? PROJECTS_LIST(workspaceSlug as string) : null, - workspaceSlug ? () => projectService.getProjects(workspaceSlug as string) : null - ); - useEffect(() => { if (projects && projects.length > 0) setActiveProject(projects?.find((p) => p.id === projectId)?.id ?? projects?.[0].id ?? null); diff --git a/apps/app/components/issues/select/project.tsx b/apps/app/components/issues/select/project.tsx index 12ee0a50c..39fd12491 100644 --- a/apps/app/components/issues/select/project.tsx +++ b/apps/app/components/issues/select/project.tsx @@ -1,15 +1,9 @@ -import { useRouter } from "next/router"; - -import useSWR from "swr"; - +// hooks +import useProjects from "hooks/use-projects"; // ui import { CustomSelect } from "components/ui"; // icons import { ClipboardDocumentListIcon } from "@heroicons/react/24/outline"; -// services -import projectService from "services/project.service"; -// fetch-keys -import { PROJECTS_LIST } from "constants/fetch-keys"; export interface IssueProjectSelectProps { value: string; @@ -22,14 +16,7 @@ export const IssueProjectSelect: React.FC = ({ onChange, setActiveProject, }) => { - const router = useRouter(); - const { workspaceSlug } = router.query; - - // Fetching Projects List - const { data: projects } = useSWR( - workspaceSlug ? PROJECTS_LIST(workspaceSlug as string) : null, - () => (workspaceSlug ? projectService.getProjects(workspaceSlug as string) : null) - ); + const { projects } = useProjects(); return ( = (props) => { .createProject(workspaceSlug as string, payload, user) .then((res) => { mutate( - PROJECTS_LIST(workspaceSlug as string), + PROJECTS_LIST(workspaceSlug as string, { is_favorite: "all" }), (prevData) => [res, ...(prevData ?? [])], false ); diff --git a/apps/app/components/project/delete-project-modal.tsx b/apps/app/components/project/delete-project-modal.tsx index 0a0266fbc..ae8be4684 100644 --- a/apps/app/components/project/delete-project-modal.tsx +++ b/apps/app/components/project/delete-project-modal.tsx @@ -1,4 +1,6 @@ -import React, { useEffect, useRef, useState } from "react"; +import React, { useEffect, useState } from "react"; + +import { useRouter } from "next/router"; import { mutate } from "swr"; @@ -13,7 +15,7 @@ import { ExclamationTriangleIcon } from "@heroicons/react/24/outline"; // ui import { DangerButton, Input, SecondaryButton } from "components/ui"; // types -import type { ICurrentUserResponse, IProject, IWorkspace } from "types"; +import type { ICurrentUserResponse, IProject } from "types"; // fetch-keys import { PROJECTS_LIST } from "constants/fetch-keys"; @@ -37,7 +39,8 @@ export const DeleteProjectModal: React.FC = ({ const [confirmDeleteMyProject, setConfirmDeleteMyProject] = useState(false); const [selectedProject, setSelectedProject] = useState(null); - const workspaceSlug = (data?.workspace as IWorkspace)?.slug; + const router = useRouter(); + const { workspaceSlug } = router.query; const { setToastAlert } = useToast(); @@ -64,26 +67,31 @@ export const DeleteProjectModal: React.FC = ({ }; const handleDeletion = async () => { - setIsDeleteLoading(true); if (!data || !workspaceSlug || !canDelete) return; + + setIsDeleteLoading(true); + + if (data.is_favorite) + mutate( + PROJECTS_LIST(workspaceSlug as string, { is_favorite: true }), + (prevData) => prevData?.filter((project: IProject) => project.id !== data.id), + false + ); + + mutate( + PROJECTS_LIST(workspaceSlug as string, { is_favorite: "all" }), + (prevData) => prevData?.filter((project: IProject) => project.id !== data.id), + false + ); + await projectService - .deleteProject(workspaceSlug, data.id, user) + .deleteProject(workspaceSlug as string, data.id, user) .then(() => { handleClose(); - mutate(PROJECTS_LIST(workspaceSlug), (prevData) => - prevData?.filter((project: IProject) => project.id !== data.id) - ); + if (onSuccess) onSuccess(); - setToastAlert({ - title: "Success", - type: "success", - message: "Project deleted successfully", - }); }) - .catch((error) => { - console.log(error); - setIsDeleteLoading(false); - }); + .catch(() => setIsDeleteLoading(false)); }; return ( diff --git a/apps/app/components/project/sidebar-list.tsx b/apps/app/components/project/sidebar-list.tsx index 1225efe96..c8dc567e7 100644 --- a/apps/app/components/project/sidebar-list.tsx +++ b/apps/app/components/project/sidebar-list.tsx @@ -2,26 +2,19 @@ import React, { useState, FC } from "react"; import { useRouter } from "next/router"; -import useSWR, { mutate } from "swr"; - -// icons -import { PlusIcon } from "@heroicons/react/24/outline"; // hooks import useToast from "hooks/use-toast"; import useTheme from "hooks/use-theme"; import useUserAuth from "hooks/use-user-auth"; -// services -import projectService from "services/project.service"; +import useProjects from "hooks/use-projects"; // components -import { CreateProjectModal, DeleteProjectModal, SingleSidebarProject } from "components/project"; -// ui -import { Loader } from "components/ui"; +import { DeleteProjectModal, SingleSidebarProject } from "components/project"; +// icons +import { PlusIcon } from "@heroicons/react/24/outline"; // helpers import { copyTextToClipboard } from "helpers/string.helper"; // types -import { IFavoriteProject, IProject } from "types"; -// fetch-keys -import { FAVORITE_PROJECTS_LIST, PROJECTS_LIST } from "constants/fetch-keys"; +import { IProject } from "types"; export const ProjectSidebarList: FC = () => { const [deleteProjectModal, setDeleteProjectModal] = useState(false); @@ -33,93 +26,11 @@ export const ProjectSidebarList: FC = () => { const { user } = useUserAuth(); - // states - const [isCreateProjectModal, setCreateProjectModal] = useState(false); - // theme const { collapsed: sidebarCollapse } = useTheme(); - // toast handler const { setToastAlert } = useToast(); - const { data: favoriteProjects } = useSWR( - workspaceSlug ? FAVORITE_PROJECTS_LIST(workspaceSlug.toString()) : null, - () => (workspaceSlug ? projectService.getFavoriteProjects(workspaceSlug.toString()) : null) - ); - - const { data: projects } = useSWR( - workspaceSlug ? PROJECTS_LIST(workspaceSlug as string) : null, - () => (workspaceSlug ? projectService.getProjects(workspaceSlug as string) : null) - ); - const normalProjects = projects?.filter((p) => !p.is_favorite) ?? []; - - const handleAddToFavorites = (project: IProject) => { - if (!workspaceSlug) return; - - projectService - .addProjectToFavorites(workspaceSlug as string, { - project: project.id, - }) - .then(() => { - mutate( - PROJECTS_LIST(workspaceSlug as string), - (prevData) => - (prevData ?? []).map((p) => ({ - ...p, - is_favorite: p.id === project.id ? true : p.is_favorite, - })), - false - ); - mutate(FAVORITE_PROJECTS_LIST(workspaceSlug as string)); - - setToastAlert({ - type: "success", - title: "Success!", - message: "Successfully added the project to favorites.", - }); - }) - .catch(() => { - setToastAlert({ - type: "error", - title: "Error!", - message: "Couldn't remove the project from favorites. Please try again.", - }); - }); - }; - - const handleRemoveFromFavorites = (project: IProject) => { - if (!workspaceSlug) return; - - projectService - .removeProjectFromFavorites(workspaceSlug as string, project.id) - .then(() => { - mutate( - PROJECTS_LIST(workspaceSlug as string), - (prevData) => - (prevData ?? []).map((p) => ({ - ...p, - is_favorite: p.id === project.id ? false : p.is_favorite, - })), - false - ); - mutate( - FAVORITE_PROJECTS_LIST(workspaceSlug as string), - (prevData) => (prevData ?? []).filter((p) => p.project !== project.id), - false - ); - - setToastAlert({ - type: "success", - title: "Success!", - message: "Successfully removed the project from favorites.", - }); - }) - .catch(() => { - setToastAlert({ - type: "error", - title: "Error!", - message: "Couldn't remove the project from favorites. Please try again.", - }); - }); - }; + const { projects: favoriteProjects } = useProjects(true); + const { projects: allProjects } = useProjects(); const handleDeleteProject = (project: IProject) => { setProjectToDelete(project); @@ -140,93 +51,61 @@ export const ProjectSidebarList: FC = () => { return ( <> - setDeleteProjectModal(false)} data={projectToDelete} user={user} /> -
+
{favoriteProjects && favoriteProjects.length > 0 && ( -
+
{!sidebarCollapse && (
Favorites
)} - {favoriteProjects.map((favoriteProject) => { - const project = favoriteProject.project_detail; - - return ( - handleDeleteProject(project)} - handleCopyText={() => handleCopyText(project.id)} - handleRemoveFromFavorites={() => handleRemoveFromFavorites(project)} - /> - ); - })} + {favoriteProjects.map((project) => ( + handleDeleteProject(project)} + handleCopyText={() => handleCopyText(project.id)} + shortContextMenu + /> + ))}
)} -
- {!sidebarCollapse && ( -
Projects
- )} - {projects ? ( - <> - {normalProjects.length > 0 ? ( - normalProjects.map((project) => ( - handleDeleteProject(project)} - handleCopyText={() => handleCopyText(project.id)} - handleAddToFavorites={() => handleAddToFavorites(project)} - /> - )) - ) : ( -
- {!sidebarCollapse && ( -

- You don{"'"}t have any project yet -

- )} - -
- )} - - ) : ( -
- -
- - - - -
-
- - - - -
-
-
- )} -
+ {allProjects && allProjects.length > 0 && ( +
+ {!sidebarCollapse && ( +
Projects
+ )} + {allProjects.map((project) => ( + handleDeleteProject(project)} + handleCopyText={() => handleCopyText(project.id)} + /> + ))} +
+ )} + {allProjects && allProjects.length === 0 && ( + + )}
); diff --git a/apps/app/components/project/single-project-card.tsx b/apps/app/components/project/single-project-card.tsx index a66df7413..f21ef3014 100644 --- a/apps/app/components/project/single-project-card.tsx +++ b/apps/app/components/project/single-project-card.tsx @@ -26,9 +26,9 @@ import { renderShortDateWithYearFormat } from "helpers/date-time.helper"; import { copyTextToClipboard, truncateText } from "helpers/string.helper"; import { renderEmoji } from "helpers/emoji.helper"; // types -import type { IFavoriteProject, IProject } from "types"; +import type { IProject } from "types"; // fetch-keys -import { FAVORITE_PROJECTS_LIST, PROJECTS_LIST } from "constants/fetch-keys"; +import { PROJECTS_LIST } from "constants/fetch-keys"; export type ProjectCardProps = { project: IProject; @@ -55,22 +55,23 @@ export const SingleProjectCard: React.FC = ({ const handleAddToFavorites = () => { if (!workspaceSlug) return; + mutate( + PROJECTS_LIST(workspaceSlug as string, { is_favorite: true }), + (prevData) => [...(prevData ?? []), { ...project, is_favorite: true }], + false + ); + mutate( + PROJECTS_LIST(workspaceSlug as string, { is_favorite: "all" }), + (prevData) => + (prevData ?? []).map((p) => (p.id === project.id ? { ...p, is_favorite: true } : p)), + false + ); + projectService .addProjectToFavorites(workspaceSlug as string, { project: project.id, }) .then(() => { - mutate( - PROJECTS_LIST(workspaceSlug as string), - (prevData) => - (prevData ?? []).map((p) => ({ - ...p, - is_favorite: p.id === project.id ? true : p.is_favorite, - })), - false - ); - mutate(FAVORITE_PROJECTS_LIST(workspaceSlug as string)); - setToastAlert({ type: "success", title: "Success!", @@ -89,24 +90,21 @@ export const SingleProjectCard: React.FC = ({ const handleRemoveFromFavorites = () => { if (!workspaceSlug || !project) return; + mutate( + PROJECTS_LIST(workspaceSlug as string, { is_favorite: true }), + (prevData) => (prevData ?? []).filter((p) => p.id !== project.id), + false + ); + mutate( + PROJECTS_LIST(workspaceSlug as string, { is_favorite: "all" }), + (prevData) => + (prevData ?? []).map((p) => (p.id === project.id ? { ...p, is_favorite: false } : p)), + false + ); + projectService .removeProjectFromFavorites(workspaceSlug as string, project.id) .then(() => { - mutate( - PROJECTS_LIST(workspaceSlug as string), - (prevData) => - (prevData ?? []).map((p) => ({ - ...p, - is_favorite: p.id === project.id ? false : p.is_favorite, - })), - false - ); - mutate( - FAVORITE_PROJECTS_LIST(workspaceSlug as string), - (prevData) => (prevData ?? []).filter((p) => p.project !== project.id), - false - ); - setToastAlert({ type: "success", title: "Success!", diff --git a/apps/app/components/project/single-sidebar-project.tsx b/apps/app/components/project/single-sidebar-project.tsx index 9ef6f7192..ec1ed0908 100644 --- a/apps/app/components/project/single-sidebar-project.tsx +++ b/apps/app/components/project/single-sidebar-project.tsx @@ -1,8 +1,14 @@ import Link from "next/link"; import { useRouter } from "next/router"; +import { mutate } from "swr"; + // headless ui import { Disclosure, Transition } from "@headlessui/react"; +// services +import projectService from "services/project.service"; +// hooks +import useToast from "hooks/use-toast"; // ui import { CustomMenu, Icon, Tooltip } from "components/ui"; // icons @@ -12,14 +18,15 @@ import { truncateText } from "helpers/string.helper"; import { renderEmoji } from "helpers/emoji.helper"; // types import { IProject } from "types"; +// fetch-keys +import { PROJECTS_LIST } from "constants/fetch-keys"; type Props = { project: IProject; sidebarCollapse: boolean; handleDeleteProject: () => void; handleCopyText: () => void; - handleAddToFavorites?: () => void; - handleRemoveFromFavorites?: () => void; + shortContextMenu?: boolean; }; const navigation = (workspaceSlug: string, projectId: string) => [ @@ -60,12 +67,65 @@ export const SingleSidebarProject: React.FC = ({ sidebarCollapse, handleDeleteProject, handleCopyText, - handleAddToFavorites, - handleRemoveFromFavorites, + shortContextMenu = false, }) => { const router = useRouter(); const { workspaceSlug, projectId } = router.query; + const { setToastAlert } = useToast(); + + const handleAddToFavorites = () => { + if (!workspaceSlug) return; + + mutate( + PROJECTS_LIST(workspaceSlug as string, { is_favorite: true }), + (prevData) => [...(prevData ?? []), { ...project, is_favorite: true }], + false + ); + mutate( + PROJECTS_LIST(workspaceSlug as string, { is_favorite: "all" }), + (prevData) => + (prevData ?? []).map((p) => (p.id === project.id ? { ...p, is_favorite: true } : p)), + false + ); + + projectService + .addProjectToFavorites(workspaceSlug as string, { + project: project.id, + }) + .catch(() => + setToastAlert({ + type: "error", + title: "Error!", + message: "Couldn't remove the project from favorites. Please try again.", + }) + ); + }; + + const handleRemoveFromFavorites = () => { + if (!workspaceSlug) return; + + mutate( + PROJECTS_LIST(workspaceSlug as string, { is_favorite: true }), + (prevData) => (prevData ?? []).filter((p) => p.id !== project.id), + false + ); + mutate( + PROJECTS_LIST(workspaceSlug as string, { is_favorite: "all" }), + (prevData) => + (prevData ?? []).map((p) => (p.id === project.id ? { ...p, is_favorite: false } : p)), + false + ); + + projectService.removeProjectFromFavorites(workspaceSlug as string, project.id).catch(() => + setToastAlert({ + type: "error", + title: "Error!", + message: "Couldn't remove the project from favorites. Please try again.", + }) + ); + }; + return ( {({ open }) => ( @@ -124,13 +184,15 @@ export const SingleSidebarProject: React.FC = ({ {!sidebarCollapse && ( - - - - Delete project - - - {handleAddToFavorites && ( + {!shortContextMenu && ( + + + + Delete project + + + )} + {!project.is_favorite && ( @@ -138,7 +200,7 @@ export const SingleSidebarProject: React.FC = ({ )} - {handleRemoveFromFavorites && ( + {project.is_favorite && ( diff --git a/apps/app/constants/fetch-keys.ts b/apps/app/constants/fetch-keys.ts index 70aca787b..b483c9e41 100644 --- a/apps/app/constants/fetch-keys.ts +++ b/apps/app/constants/fetch-keys.ts @@ -52,10 +52,18 @@ export const WORKSPACE_INVITATIONS = "WORKSPACE_INVITATIONS"; export const WORKSPACE_INVITATION = "WORKSPACE_INVITATION"; export const LAST_ACTIVE_WORKSPACE_AND_PROJECTS = "LAST_ACTIVE_WORKSPACE_AND_PROJECTS"; -export const PROJECTS_LIST = (workspaceSlug: string) => - `PROJECTS_LIST_${workspaceSlug.toUpperCase()}`; -export const FAVORITE_PROJECTS_LIST = (workspaceSlug: string) => - `FAVORITE_PROJECTS_LIST_${workspaceSlug.toUpperCase()}`; +export const PROJECTS_LIST = ( + workspaceSlug: string, + params: { + is_favorite: "all" | boolean; + } +) => { + if (!params) return `PROJECTS_LIST_${workspaceSlug.toUpperCase()}`; + + return `PROJECTS_LIST_${workspaceSlug.toUpperCase()}_${params.is_favorite + .toString() + .toUpperCase()}`; +}; export const PROJECT_DETAILS = (projectId: string) => `PROJECT_DETAILS_${projectId.toUpperCase()}`; export const PROJECT_MEMBERS = (projectId: string) => `PROJECT_MEMBERS_${projectId.toUpperCase()}`; diff --git a/apps/app/hooks/use-projects.tsx b/apps/app/hooks/use-projects.tsx index 3fc93cdb2..c537e3a62 100644 --- a/apps/app/hooks/use-projects.tsx +++ b/apps/app/hooks/use-projects.tsx @@ -11,14 +11,15 @@ import { IProject } from "types"; // fetch-keys import { PROJECTS_LIST } from "constants/fetch-keys"; -const useProjects = () => { - // router +const useProjects = (type?: "all" | boolean) => { const router = useRouter(); const { workspaceSlug } = router.query; - // api fetching + const { data: projects, mutate: mutateProjects } = useSWR( - workspaceSlug ? PROJECTS_LIST(workspaceSlug as string) : null, - workspaceSlug ? () => projectService.getProjects(workspaceSlug as string) : null + workspaceSlug ? PROJECTS_LIST(workspaceSlug as string, { is_favorite: type ?? "all" }) : null, + workspaceSlug + ? () => projectService.getProjects(workspaceSlug as string, { is_favorite: type ?? "all" }) + : null ); const recentProjects = [...(projects ?? [])] diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/control.tsx b/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/control.tsx index 7fe2bca6b..540bf2506 100644 --- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/control.tsx +++ b/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/control.tsx @@ -59,7 +59,7 @@ const ControlSettings: NextPage = () => { } = useForm({ defaultValues }); const onSubmit = async (formData: IProject) => { - if (!workspaceSlug || !projectId) return; + if (!workspaceSlug || !projectId || !projectDetails) return; const payload: Partial = { default_assignee: formData.default_assignee, @@ -70,7 +70,19 @@ const ControlSettings: NextPage = () => { .updateProject(workspaceSlug as string, projectId as string, payload, user) .then((res) => { mutate(PROJECT_DETAILS(projectId as string)); - mutate(PROJECTS_LIST(workspaceSlug as string)); + + if (projectDetails.is_favorite) + mutate( + PROJECTS_LIST(workspaceSlug as string, { + is_favorite: true, + }) + ); + + mutate( + PROJECTS_LIST(workspaceSlug as string, { + is_favorite: "all", + }) + ); setToastAlert({ title: "Success", diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/features.tsx b/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/features.tsx index e528b086f..098a4467b 100644 --- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/features.tsx +++ b/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/features.tsx @@ -21,10 +21,10 @@ import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs"; import { ContrastIcon, PeopleGroupIcon, ViewListIcon, InboxIcon } from "components/icons"; import { DocumentTextIcon } from "@heroicons/react/24/outline"; // types -import { IFavoriteProject, IProject } from "types"; +import { IProject } from "types"; import type { NextPage } from "next"; // fetch-keys -import { FAVORITE_PROJECTS_LIST, PROJECTS_LIST, PROJECT_DETAILS } from "constants/fetch-keys"; +import { PROJECTS_LIST, PROJECT_DETAILS } from "constants/fetch-keys"; const featuresList = [ { @@ -100,17 +100,16 @@ const FeaturesSettings: NextPage = () => { if (!workspaceSlug || !projectId || !projectDetails) return; if (projectDetails.is_favorite) - mutate( - FAVORITE_PROJECTS_LIST(workspaceSlug.toString()), + mutate( + PROJECTS_LIST(workspaceSlug.toString(), { + is_favorite: true, + }), (prevData) => prevData?.map((p) => { - if (p.project === projectId) + if (p.id === projectId) return { ...p, - project_detail: { - ...p.project_detail, - ...formData, - }, + ...formData, }; return p; @@ -119,7 +118,9 @@ const FeaturesSettings: NextPage = () => { ); mutate( - PROJECTS_LIST(workspaceSlug.toString()), + PROJECTS_LIST(workspaceSlug.toString(), { + is_favorite: "all", + }), (prevData) => prevData?.map((p) => { if (p.id === projectId) @@ -147,21 +148,13 @@ const FeaturesSettings: NextPage = () => { await projectService .updateProject(workspaceSlug as string, projectId as string, formData, user) - .then(() => { - mutate( - projectDetails.is_favorite - ? FAVORITE_PROJECTS_LIST(workspaceSlug.toString()) - : PROJECTS_LIST(workspaceSlug.toString()) - ); - mutate(PROJECT_DETAILS(projectId as string)); - }) - .catch((err) => { + .catch(() => setToastAlert({ type: "error", title: "Error!", message: "Project feature could not be updated. Please try again.", - }); - }); + }) + ); }; return ( diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/index.tsx b/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/index.tsx index 3ad95d473..fa4ac01ea 100644 --- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/index.tsx +++ b/apps/app/pages/[workspaceSlug]/projects/[projectId]/settings/index.tsx @@ -94,7 +94,20 @@ const GeneralSettings: NextPage = () => { (prevData) => ({ ...prevData, ...res }), false ); - mutate(PROJECTS_LIST(workspaceSlug as string)); + + if (projectDetails.is_favorite) + mutate( + PROJECTS_LIST(workspaceSlug as string, { + is_favorite: true, + }) + ); + + mutate( + PROJECTS_LIST(workspaceSlug as string, { + is_favorite: "all", + }) + ); + setToastAlert({ type: "success", title: "Success!", diff --git a/apps/app/services/project.service.ts b/apps/app/services/project.service.ts index 0e2f87c95..f9b23a51d 100644 --- a/apps/app/services/project.service.ts +++ b/apps/app/services/project.service.ts @@ -6,7 +6,6 @@ import trackEventServices from "services/track-event.service"; import type { GithubRepositoriesResponse, ICurrentUserResponse, - IFavoriteProject, IProject, IProjectBulkInviteFormData, IProjectMember, @@ -53,8 +52,15 @@ class ProjectServices extends APIService { }); } - async getProjects(workspaceSlug: string): Promise { - return this.get(`/api/workspaces/${workspaceSlug}/projects/`) + async getProjects( + workspaceSlug: string, + params: { + is_favorite: "all" | boolean; + } + ): Promise { + return this.get(`/api/workspaces/${workspaceSlug}/projects/`, { + params, + }) .then((response) => response?.data) .catch((error) => { throw error?.response?.data; @@ -298,14 +304,6 @@ class ProjectServices extends APIService { }); } - async getFavoriteProjects(workspaceSlug: string): Promise { - return this.get(`/api/workspaces/${workspaceSlug}/user-favorite-projects/`) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - async addProjectToFavorites( workspaceSlug: string, data: { diff --git a/apps/app/types/projects.d.ts b/apps/app/types/projects.d.ts index 818db5276..a9ba686cf 100644 --- a/apps/app/types/projects.d.ts +++ b/apps/app/types/projects.d.ts @@ -60,18 +60,6 @@ export interface IProjectLite { identifier: string; } -export interface IFavoriteProject { - created_at: Date; - created_by: string; - id: string; - project: string; - project_detail: IProject; - updated_at: Date; - updated_by: string; - user: string; - workspace: string; -} - type ProjectViewTheme = { issueView: TIssueViewOptions; groupByProperty: TIssueGroupByOptions;