diff --git a/apps/app/hooks/use-my-issues-filter.tsx b/apps/app/hooks/use-my-issues-filter.tsx index bd97427f58..8c5d3eaa5f 100644 --- a/apps/app/hooks/use-my-issues-filter.tsx +++ b/apps/app/hooks/use-my-issues-filter.tsx @@ -1,26 +1,18 @@ -import { useEffect, useState } from "react"; -import { useRouter } from "next/router"; -import useSWR from "swr"; +import { useState, useEffect, useCallback } from "react"; +import useSWR, { mutate } from "swr"; // services -import stateService from "services/state.service"; -import userService from "services/user.service"; +import workspaceService from "services/workspace.service"; // hooks import useUser from "hooks/use-user"; -// helpers -import { groupBy } from "helpers/array.helper"; -import { getStatesList } from "helpers/state.helper"; // types -import { Properties, NestedKeyOf, IIssue } from "types"; -// fetch-keys -import { STATES_LIST } from "constants/fetch-keys"; -// constants -import { PRIORITIES } from "constants/project"; +import { IWorkspaceMember, Properties } from "types"; +import { WORKSPACE_MEMBERS_ME } from "constants/fetch-keys"; const initialValues: Properties = { assignee: true, due_date: false, key: true, - labels: true, + labels: false, priority: false, state: true, sub_issue_count: false, @@ -29,99 +21,80 @@ const initialValues: Properties = { estimate: false, }; -// TODO: Refactor this logic -const useMyIssuesProperties = (issues?: IIssue[]) => { +const useMyIssuesProperties = (workspaceSlug?: string) => { const [properties, setProperties] = useState(initialValues); - const [groupByProperty, setGroupByProperty] = useState | null>(null); - - // FIXME: where this hook is used we may not have project id in the url - const router = useRouter(); - const { workspaceSlug, projectId } = router.query; const { user } = useUser(); - const { data: stateGroups } = useSWR( - workspaceSlug && projectId ? STATES_LIST(projectId as string) : null, - workspaceSlug && projectId - ? () => stateService.getStates(workspaceSlug as string, projectId as string) - : null - ); - const states = getStatesList(stateGroups ?? {}); - - useEffect(() => { - if (!user) return; - setProperties({ ...initialValues, ...user.my_issues_prop?.properties }); - setGroupByProperty(user.my_issues_prop?.groupBy ?? null); - }, [user]); - - const groupedByIssues: { - [key: string]: IIssue[]; - } = { - ...(groupByProperty === "state_detail.name" - ? Object.fromEntries( - states - ?.sort((a, b) => a.sequence - b.sequence) - ?.map((state) => [ - state.name, - issues?.filter((issue) => issue.state === state.name) ?? [], - ]) ?? [] - ) - : groupByProperty === "priority" - ? Object.fromEntries( - PRIORITIES.map((priority) => [ - priority, - issues?.filter((issue) => issue.priority === priority) ?? [], - ]) - ) - : {}), - ...groupBy(issues ?? [], groupByProperty ?? ""), - }; - - const setMyIssueProperty = (key: keyof Properties) => { - if (!user) return; - userService.updateUser({ my_issues_prop: { properties, groupBy: groupByProperty } }); - setProperties((prevData) => ({ - ...prevData, - [key]: !prevData[key], - })); - localStorage.setItem( - "my_issues_prop", - JSON.stringify({ - properties: { - ...properties, - [key]: !properties[key], - }, - groupBy: groupByProperty, - }) - ); - }; - - const setMyIssueGroupByProperty = (groupByProperty: NestedKeyOf | null) => { - if (!user) return; - userService.updateUser({ my_issues_prop: { properties, groupBy: groupByProperty } }); - setGroupByProperty(groupByProperty); - localStorage.setItem( - "my_issues_prop", - JSON.stringify({ properties, groupBy: groupByProperty }) - ); - }; - - useEffect(() => { - const viewProps = localStorage.getItem("my_issues_prop"); - if (viewProps) { - const { properties, groupBy } = JSON.parse(viewProps); - setProperties(properties); - setGroupByProperty(groupBy); + const { data: myWorkspace } = useSWR( + workspaceSlug ? WORKSPACE_MEMBERS_ME(workspaceSlug as string) : null, + workspaceSlug ? () => workspaceService.workspaceMemberMe(workspaceSlug as string) : null, + { + shouldRetryOnError: false, } - }, []); + ); - return { - filteredIssues: groupedByIssues, - groupByProperty, - properties, - setMyIssueProperty, - setMyIssueGroupByProperty, - } as const; + useEffect(() => { + if (!myWorkspace || !workspaceSlug || !user) return; + + setProperties({ ...initialValues, ...myWorkspace.view_props }); + + if (!myWorkspace.view_props) { + workspaceService.updateWorkspaceView(workspaceSlug, { + view_props: { ...initialValues }, + }); + } + }, [myWorkspace, workspaceSlug, user]); + + const updateIssueProperties = useCallback( + (key: keyof Properties) => { + if (!workspaceSlug || !user) return; + + setProperties((prev) => ({ ...prev, [key]: !prev[key] })); + + if (myWorkspace) { + mutate( + WORKSPACE_MEMBERS_ME(workspaceSlug.toString()), + (prevData) => { + if (!prevData) return; + return { + ...prevData, + view_props: { ...prevData?.view_props, [key]: !prevData.view_props?.[key] }, + }; + }, + false + ); + if (myWorkspace.view_props) { + workspaceService.updateWorkspaceView(workspaceSlug, { + view_props: { + ...myWorkspace.view_props, + [key]: !myWorkspace.view_props[key], + }, + }); + } else { + workspaceService.updateWorkspaceView(workspaceSlug, { + view_props: { ...initialValues }, + }); + } + } + }, + [workspaceSlug, myWorkspace, user] + ); + + const newProperties: Properties = { + assignee: properties.assignee, + due_date: properties.due_date, + key: properties.key, + labels: properties.labels, + priority: properties.priority, + state: properties.state, + sub_issue_count: properties.sub_issue_count, + attachment_count: properties.attachment_count, + link: properties.link, + estimate: properties.estimate, + }; + + return [newProperties, updateIssueProperties] as const; }; export default useMyIssuesProperties; diff --git a/apps/app/pages/[workspaceSlug]/me/my-issues.tsx b/apps/app/pages/[workspaceSlug]/me/my-issues.tsx index d742a7aa53..c66fcee553 100644 --- a/apps/app/pages/[workspaceSlug]/me/my-issues.tsx +++ b/apps/app/pages/[workspaceSlug]/me/my-issues.tsx @@ -14,7 +14,7 @@ import useIssues from "hooks/use-issues"; import { Spinner, EmptySpace, EmptySpaceItem, PrimaryButton } from "components/ui"; import { Breadcrumbs, BreadcrumbItem } from "components/breadcrumbs"; // hooks -import useIssuesProperties from "hooks/use-issue-properties"; +import useMyIssuesProperties from "hooks/use-my-issues-filter"; // types import { IIssue, Properties } from "types"; // components @@ -31,10 +31,7 @@ const MyIssuesPage: NextPage = () => { // fetching user issues const { myIssues } = useIssues(workspaceSlug as string); - const [properties, setProperties] = useIssuesProperties( - workspaceSlug ? (workspaceSlug as string) : undefined, - undefined - ); + const [properties, setProperties] = useMyIssuesProperties(workspaceSlug as string); return ( { + return this.post(`/api/workspaces/${workspaceSlug}/workspace-views/`, data) + .then((response) => response?.data) + .catch((error) => { + throw error?.response?.data; + }); + } + async updateWorkspaceMember( workspaceSlug: string, memberId: string, diff --git a/apps/app/types/workspace.d.ts b/apps/app/types/workspace.d.ts index fbb54d7594..a88a0f15bd 100644 --- a/apps/app/types/workspace.d.ts +++ b/apps/app/types/workspace.d.ts @@ -33,6 +33,19 @@ export interface IWorkspaceMemberInvitation { workspace: IWorkspace; } +export type Properties = { + assignee: boolean; + due_date: boolean; + labels: boolean; + key: boolean; + priority: boolean; + state: boolean; + sub_issue_count: boolean; + link: boolean; + attachment_count: boolean; + estimate: boolean; +}; + export interface IWorkspaceMember { readonly id: string; user: IUserLite; @@ -40,6 +53,7 @@ export interface IWorkspaceMember { member: IUserLite; role: 5 | 10 | 15 | 20; company_role: string | null; + view_props: Properties; created_at: Date; updated_at: Date; created_by: string;