From c5206a7792c4994de46bfe1bee6580fb3326e372 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Wed, 19 Apr 2023 17:25:31 +0530 Subject: [PATCH] feat: separate filters for cycles and modules (#892) --- apps/app/contexts/issue-view.context.tsx | 152 ++++++++++++++++++++--- apps/app/services/cycles.service.ts | 2 +- apps/app/services/modules.service.ts | 6 +- apps/app/types/cycles.d.ts | 13 +- apps/app/types/modules.d.ts | 4 + 5 files changed, 156 insertions(+), 21 deletions(-) diff --git a/apps/app/contexts/issue-view.context.tsx b/apps/app/contexts/issue-view.context.tsx index 8205d9277..ff17007ab 100644 --- a/apps/app/contexts/issue-view.context.tsx +++ b/apps/app/contexts/issue-view.context.tsx @@ -8,6 +8,8 @@ import useSWR, { mutate } from "swr"; import ToastAlert from "components/toast-alert"; // services import projectService from "services/project.service"; +import cyclesService from "services/cycles.service"; +import modulesService from "services/modules.service"; import viewsService from "services/views.service"; // types import { @@ -18,7 +20,12 @@ import { TIssueOrderByOptions, } from "types"; // fetch-keys -import { USER_PROJECT_VIEW, VIEW_DETAILS } from "constants/fetch-keys"; +import { + CYCLE_DETAILS, + MODULE_DETAILS, + USER_PROJECT_VIEW, + VIEW_DETAILS, +} from "constants/fetch-keys"; export const issueViewContext = createContext({} as ContextType); @@ -171,7 +178,29 @@ const saveDataToServer = async (workspaceSlug: string, projectID: string, state: }); }; -const sendFilterDataToServer = async ( +const saveCycleFilters = async ( + workspaceSlug: string, + projectId: string, + cycleId: string, + state: any +) => { + await cyclesService.patchCycle(workspaceSlug, projectId, cycleId, { + ...state, + }); +}; + +const saveModuleFilters = async ( + workspaceSlug: string, + projectId: string, + moduleId: string, + state: any +) => { + await modulesService.patchModule(workspaceSlug, projectId, moduleId, { + ...state, + }); +}; + +const saveViewFilters = async ( workspaceSlug: string, projectId: string, viewId: string, @@ -206,7 +235,7 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> = const [state, dispatch] = useReducer(reducer, initialState); const router = useRouter(); - const { workspaceSlug, projectId, viewId } = router.query; + const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query; const { data: myViewProps, mutate: mutateMyViewProps } = useSWR( workspaceSlug && projectId ? USER_PROJECT_VIEW(projectId as string) : null, @@ -227,6 +256,30 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> = : null ); + const { data: cycleDetails, mutate: mutateCycleDetails } = useSWR( + workspaceSlug && projectId && cycleId ? CYCLE_DETAILS(cycleId as string) : null, + workspaceSlug && projectId && cycleId + ? () => + cyclesService.getCycleDetails( + workspaceSlug.toString(), + projectId.toString(), + cycleId.toString() + ) + : null + ); + + const { data: moduleDetails, mutate: mutateModuleDetails } = useSWR( + workspaceSlug && projectId && moduleId ? MODULE_DETAILS(moduleId.toString()) : null, + workspaceSlug && projectId && moduleId + ? () => + modulesService.getModuleDetails( + workspaceSlug.toString(), + projectId.toString(), + moduleId.toString() + ) + : null + ); + const setIssueView = useCallback( (property: TIssueViewOptions) => { dispatch({ @@ -352,9 +405,8 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> = const setFilters = useCallback( (property: Partial, saveToServer = true) => { Object.keys(property).forEach((key) => { - if (property[key as keyof typeof property]?.length === 0) { + if (property[key as keyof typeof property]?.length === 0) property[key as keyof typeof property] = null; - } }); dispatch({ @@ -369,22 +421,53 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> = if (!workspaceSlug || !projectId) return; - mutateMyViewProps((prevData) => { - if (!prevData) return prevData; + if (cycleId) { + mutateCycleDetails((prevData: any) => { + if (!prevData) return prevData; - return { - ...prevData, + return { + ...prevData, + view_props: { + filters: { + ...state.filters, + ...property, + }, + }, + }; + }, false); + + saveCycleFilters(workspaceSlug.toString(), projectId.toString(), cycleId.toString(), { view_props: { - ...state, filters: { ...state.filters, ...property, }, }, - }; - }, false); + }); + } else if (moduleId) { + mutateModuleDetails((prevData: any) => { + if (!prevData) return prevData; - if (viewId) { + return { + ...prevData, + view_props: { + filters: { + ...state.filters, + ...property, + }, + }, + }; + }, false); + + saveModuleFilters(workspaceSlug.toString(), projectId.toString(), moduleId.toString(), { + view_props: { + filters: { + ...state.filters, + ...property, + }, + }, + }); + } else if (viewId) { mutateViewDetails((prevData: any) => { if (!prevData) return prevData; return { @@ -396,13 +479,28 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> = }; }, false); if (saveToServer) - sendFilterDataToServer(workspaceSlug as string, projectId as string, viewId as string, { + saveViewFilters(workspaceSlug as string, projectId as string, viewId as string, { query_data: { ...state.filters, ...property, }, }); - } else if (saveToServer) + } else { + mutateMyViewProps((prevData) => { + if (!prevData) return prevData; + + return { + ...prevData, + view_props: { + ...state, + filters: { + ...state.filters, + ...property, + }, + }, + }; + }, false); + saveDataToServer(workspaceSlug as string, projectId as string, { ...state, filters: { @@ -410,8 +508,20 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> = ...property, }, }); + } }, - [projectId, workspaceSlug, state, mutateMyViewProps, viewId, mutateViewDetails] + [ + projectId, + workspaceSlug, + state, + mutateMyViewProps, + cycleId, + mutateCycleDetails, + moduleId, + mutateModuleDetails, + viewId, + mutateViewDetails, + ] ); const setNewDefaultView = useCallback(() => { @@ -439,11 +549,17 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> = payload: { ...myViewProps?.view_props, filters: { - ...(viewId ? viewDetails?.query_data : myViewProps?.view_props?.filters), + ...(cycleId + ? cycleDetails?.view_props.filters + : moduleId + ? moduleDetails?.view_props.filters + : viewId + ? viewDetails?.query_data + : myViewProps?.view_props?.filters), } as any, }, }); - }, [myViewProps, viewDetails, viewId]); + }, [myViewProps, cycleId, cycleDetails, moduleId, moduleDetails, viewId, viewDetails]); return ( ): Promise { return this.patch( `/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/`, diff --git a/apps/app/services/modules.service.ts b/apps/app/services/modules.service.ts index 5b7e2623a..89227982c 100644 --- a/apps/app/services/modules.service.ts +++ b/apps/app/services/modules.service.ts @@ -53,7 +53,11 @@ class ProjectIssuesServices extends APIService { }); } - async getModuleDetails(workspaceSlug: string, projectId: string, moduleId: string): Promise { + async getModuleDetails( + workspaceSlug: string, + projectId: string, + moduleId: string + ): Promise { return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/`) .then((response) => response?.data) .catch((error) => { diff --git a/apps/app/types/cycles.d.ts b/apps/app/types/cycles.d.ts index d39f0b140..760ba03d5 100644 --- a/apps/app/types/cycles.d.ts +++ b/apps/app/types/cycles.d.ts @@ -1,4 +1,12 @@ -import type { IUser, IIssue, IProject, IProjectLite, IWorkspace, IWorkspaceLite } from "types"; +import type { + IUser, + IIssue, + IProject, + IProjectLite, + IWorkspace, + IWorkspaceLite, + IIssueFilterOptions, +} from "types"; export interface ICycle { backlog_issues: number; @@ -21,6 +29,9 @@ export interface ICycle { unstarted_issues: number; updated_at: Date; updated_by: string; + view_props: { + filters: IIssueFilterOptions; + }; workspace: string; workspace_detail: IWorkspaceLite; } diff --git a/apps/app/types/modules.d.ts b/apps/app/types/modules.d.ts index 92f2ae199..3e2a326c4 100644 --- a/apps/app/types/modules.d.ts +++ b/apps/app/types/modules.d.ts @@ -6,6 +6,7 @@ import type { IWorkspace, IWorkspaceLite, IProjectLite, + IIssueFilterOptions, } from "types"; export interface IModule { @@ -45,6 +46,9 @@ export interface IModule { unstarted_issues: number; updated_at: Date; updated_by: string; + view_props: { + filters: IIssueFilterOptions; + }; workspace: string; workspace_detail: IWorkspaceLite; }