From 052079c72ec682371932e2b5c5a13bfa3f331dd7 Mon Sep 17 00:00:00 2001 From: Dakshesh Jain Date: Tue, 20 Dec 2022 17:57:17 +0530 Subject: [PATCH 1/3] feat: reset to default view, and create new default view --- apps/app/constants/theme.context.constants.ts | 1 + apps/app/contexts/theme.context.tsx | 61 +++++++++++++++---- apps/app/lib/hooks/useIssuesFilter.tsx | 4 ++ apps/app/lib/services/project.service.ts | 5 +- .../projects/[projectId]/issues/index.tsx | 19 ++++++ apps/app/types/projects.d.ts | 2 + 6 files changed, 80 insertions(+), 12 deletions(-) diff --git a/apps/app/constants/theme.context.constants.ts b/apps/app/constants/theme.context.constants.ts index f170511ed..8961a442f 100644 --- a/apps/app/constants/theme.context.constants.ts +++ b/apps/app/constants/theme.context.constants.ts @@ -4,3 +4,4 @@ export const SET_ISSUE_VIEW = "SET_ISSUE_VIEW"; export const SET_GROUP_BY_PROPERTY = "SET_GROUP_BY_PROPERTY"; export const SET_ORDER_BY_PROPERTY = "SET_ORDER_BY_PROPERTY"; export const SET_FILTER_ISSUES = "SET_FILTER_ISSUES"; +export const RESET_TO_DEFAULT = "RESET_TO_DEFAULT"; diff --git a/apps/app/contexts/theme.context.tsx b/apps/app/contexts/theme.context.tsx index b363524b8..7f62df4f6 100644 --- a/apps/app/contexts/theme.context.tsx +++ b/apps/app/contexts/theme.context.tsx @@ -9,13 +9,14 @@ import { SET_GROUP_BY_PROPERTY, SET_ORDER_BY_PROPERTY, SET_FILTER_ISSUES, + RESET_TO_DEFAULT, } from "constants/theme.context.constants"; // components import ToastAlert from "components/toast-alert"; // hooks import useUser from "lib/hooks/useUser"; // constants -import { PROJECT_MEMBERS, USER_PROJECT_VIEW } from "constants/fetch-keys"; +import { USER_PROJECT_VIEW } from "constants/fetch-keys"; // services import projectService from "lib/services/project.service"; @@ -31,7 +32,8 @@ type ReducerActionType = { | typeof SET_ISSUE_VIEW | typeof SET_ORDER_BY_PROPERTY | typeof SET_FILTER_ISSUES - | typeof SET_GROUP_BY_PROPERTY; + | typeof SET_GROUP_BY_PROPERTY + | typeof RESET_TO_DEFAULT; payload?: Partial; }; @@ -46,6 +48,8 @@ type ContextType = { setGroupByProperty: (property: NestedKeyOf | null) => void; setOrderBy: (property: NestedKeyOf | null) => void; setFilterIssue: (property: "activeIssue" | "backlogIssue" | null) => void; + resetFilterToDefault: () => void; + setNewFilterDefaultView: () => void; }; type StateType = Theme; @@ -70,8 +74,7 @@ export const reducer: ReducerFunctionType = (state, action) => { }; return newState; case REHYDRATE_THEME: { - const newState = payload; - return { ...initialState, ...newState }; + return { ...initialState, ...payload }; } case SET_ISSUE_VIEW: { const newState = { @@ -113,6 +116,12 @@ export const reducer: ReducerFunctionType = (state, action) => { ...newState, }; } + case RESET_TO_DEFAULT: { + return { + ...initialState, + ...payload, + }; + } default: { return state; } @@ -120,18 +129,27 @@ export const reducer: ReducerFunctionType = (state, action) => { }; const saveDataToServer = async (workspaceSlug: string, projectID: string, state: any) => { - await projectService.setProjectView(workspaceSlug, projectID, state); + await projectService.setProjectView(workspaceSlug, projectID, { + view_props: state, + }); +}; + +const setNewDefault = async (workspaceSlug: string, projectID: string, state: any) => { + await projectService.setProjectView(workspaceSlug, projectID, { + view_props: state, + default_props: state, + }); }; export const ThemeContextProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { const [state, dispatch] = useReducer(reducer, initialState); - const { activeProject, activeWorkspace, user } = useUser(); + const { activeProject, activeWorkspace } = useUser(); - const { data: projectMember } = useSWR( - activeWorkspace && activeProject ? PROJECT_MEMBERS(activeProject.id) : null, + const { data: myViewProps, mutate: mutateMyViewProps } = useSWR( + activeWorkspace && activeProject ? USER_PROJECT_VIEW(activeProject.id) : null, activeWorkspace && activeProject - ? () => projectService.projectMembers(activeWorkspace.slug, activeProject.id) + ? () => projectService.projectMemberMe(activeWorkspace.slug, activeProject.id) : null ); @@ -191,6 +209,7 @@ export const ThemeContextProvider: React.FC<{ children: React.ReactNode }> = ({ }, [activeProject, activeWorkspace, state] ); + const setFilterIssue = useCallback( (property: "activeIssue" | "backlogIssue" | null) => { dispatch({ @@ -209,12 +228,30 @@ export const ThemeContextProvider: React.FC<{ children: React.ReactNode }> = ({ [activeProject, activeWorkspace, state] ); + const setNewDefaultView = useCallback(() => { + if (!activeWorkspace || !activeProject) return; + setNewDefault(activeWorkspace.slug, activeProject.id, state); + }, [activeProject, activeWorkspace, state]); + + const resetToDefault = useCallback(() => { + dispatch({ + type: RESET_TO_DEFAULT, + payload: myViewProps?.default_props, + }); + if (!activeWorkspace || !activeProject) return; + saveDataToServer(activeWorkspace.slug, activeProject.id, myViewProps?.default_props).then( + () => { + mutateMyViewProps(); + } + ); + }, [activeProject, activeWorkspace, myViewProps, mutateMyViewProps]); + useEffect(() => { dispatch({ type: REHYDRATE_THEME, - payload: projectMember?.find((member) => member.member.id === user?.id)?.view_props, + payload: myViewProps?.view_props, }); - }, [projectMember, user]); + }, [myViewProps]); return ( = ({ setOrderBy, filterIssue: state.filterIssue, setFilterIssue, + resetFilterToDefault: resetToDefault, + setNewFilterDefaultView: setNewDefaultView, }} > diff --git a/apps/app/lib/hooks/useIssuesFilter.tsx b/apps/app/lib/hooks/useIssuesFilter.tsx index 30bc42db9..d6ee0089a 100644 --- a/apps/app/lib/hooks/useIssuesFilter.tsx +++ b/apps/app/lib/hooks/useIssuesFilter.tsx @@ -17,6 +17,8 @@ const useIssuesFilter = (projectIssues: IIssue[]) => { setOrderBy, filterIssue, setFilterIssue, + resetFilterToDefault, + setNewFilterDefaultView, } = useTheme(); const { states } = useUser(); @@ -95,6 +97,8 @@ const useIssuesFilter = (projectIssues: IIssue[]) => { setOrderBy, filterIssue, setFilterIssue, + resetFilterToDefault, + setNewFilterDefaultView, } as const; }; diff --git a/apps/app/lib/services/project.service.ts b/apps/app/lib/services/project.service.ts index 92996f0e5..bd78427c7 100644 --- a/apps/app/lib/services/project.service.ts +++ b/apps/app/lib/services/project.service.ts @@ -230,7 +230,10 @@ class ProjectServices extends APIService { async setProjectView( workspacSlug: string, projectId: string, - data: ProjectViewTheme + data: { + view_props?: ProjectViewTheme; + default_props?: ProjectViewTheme; + } ): Promise { await this.post(PROJECT_VIEW_ENDPOINT(workspacSlug, projectId), data) .then((response) => { diff --git a/apps/app/pages/projects/[projectId]/issues/index.tsx b/apps/app/pages/projects/[projectId]/issues/index.tsx index bf6ec78ad..2f3bdcdb9 100644 --- a/apps/app/pages/projects/[projectId]/issues/index.tsx +++ b/apps/app/pages/projects/[projectId]/issues/index.tsx @@ -142,6 +142,8 @@ const ProjectIssues: NextPage = () => { setFilterIssue, orderBy, filterIssue, + resetFilterToDefault, + setNewFilterDefaultView, } = useIssuesFilter(projectIssues?.results.filter((p) => p.parent === null) ?? []); useEffect(() => { @@ -292,6 +294,23 @@ const ProjectIssues: NextPage = () => { ))} +
+
+ + +
diff --git a/apps/app/types/projects.d.ts b/apps/app/types/projects.d.ts index 8c4e114ef..4a83b90ba 100644 --- a/apps/app/types/projects.d.ts +++ b/apps/app/types/projects.d.ts @@ -31,7 +31,9 @@ export interface IProjectMember { workspace: IWorkspace; comment: string; role: 5 | 10 | 15 | 20; + view_props: ProjectViewTheme; + default_props: ProjectViewTheme; created_at: Date; updated_at: Date; From f80f4b8c234817b63fa234b5388d417596cd3768 Mon Sep 17 00:00:00 2001 From: Dakshesh Jain Date: Tue, 20 Dec 2022 19:37:58 +0530 Subject: [PATCH 2/3] fix: sidebar collapsed hydration, changing list view type causing errors --- apps/app/contexts/theme.context.tsx | 67 +++++++++++++------ apps/app/lib/hooks/useIssuesFilter.tsx | 6 +- .../projects/[projectId]/issues/index.tsx | 13 ++-- 3 files changed, 56 insertions(+), 30 deletions(-) diff --git a/apps/app/contexts/theme.context.tsx b/apps/app/contexts/theme.context.tsx index 7f62df4f6..fb9085fe0 100644 --- a/apps/app/contexts/theme.context.tsx +++ b/apps/app/contexts/theme.context.tsx @@ -44,12 +44,13 @@ type ContextType = { groupByProperty: NestedKeyOf | null; filterIssue: "activeIssue" | "backlogIssue" | null; toggleCollapsed: () => void; - setIssueView: (display: "list" | "kanban") => void; setGroupByProperty: (property: NestedKeyOf | null) => void; setOrderBy: (property: NestedKeyOf | null) => void; setFilterIssue: (property: "activeIssue" | "backlogIssue" | null) => void; resetFilterToDefault: () => void; setNewFilterDefaultView: () => void; + setIssueViewToKanban: () => void; + setIssueViewToList: () => void; }; type StateType = Theme; @@ -72,9 +73,12 @@ export const reducer: ReducerFunctionType = (state, action) => { ...state, collapsed: !state.collapsed, }; + localStorage.setItem("collapsed", JSON.stringify(newState.collapsed)); return newState; case REHYDRATE_THEME: { - return { ...initialState, ...payload }; + let collapsed: any = localStorage.getItem("collapsed"); + collapsed = collapsed ? JSON.parse(collapsed) : false; + return { ...initialState, ...payload, collapsed }; } case SET_ISSUE_VIEW: { const newState = { @@ -159,23 +163,47 @@ export const ThemeContextProvider: React.FC<{ children: React.ReactNode }> = ({ }); }, []); - const setIssueView = useCallback( - (display: "list" | "kanban") => { - dispatch({ - type: SET_ISSUE_VIEW, - payload: { - issueView: display, - }, - }); + const setIssueViewToKanban = useCallback(() => { + dispatch({ + type: SET_ISSUE_VIEW, + payload: { + issueView: "kanban", + }, + }); + dispatch({ + type: SET_GROUP_BY_PROPERTY, + payload: { + groupByProperty: "state_detail.name", + }, + }); + if (!activeWorkspace || !activeProject) return; + saveDataToServer(activeWorkspace.slug, activeProject.id, { + ...state, + issueView: "kanban", + groupByProperty: "state_detail.name", + }); + }, [activeWorkspace, activeProject, state]); - if (!activeWorkspace || !activeProject) return; - saveDataToServer(activeWorkspace.slug, activeProject.id, { - ...state, - issueView: display, - }); - }, - [activeProject, activeWorkspace, state] - ); + const setIssueViewToList = useCallback(() => { + dispatch({ + type: SET_ISSUE_VIEW, + payload: { + issueView: "list", + }, + }); + dispatch({ + type: SET_GROUP_BY_PROPERTY, + payload: { + groupByProperty: null, + }, + }); + if (!activeWorkspace || !activeProject) return; + saveDataToServer(activeWorkspace.slug, activeProject.id, { + ...state, + issueView: "list", + groupByProperty: null, + }); + }, [activeWorkspace, activeProject, state]); const setGroupByProperty = useCallback( (property: NestedKeyOf | null) => { @@ -259,7 +287,6 @@ export const ThemeContextProvider: React.FC<{ children: React.ReactNode }> = ({ collapsed: state.collapsed, toggleCollapsed, issueView: state.issueView, - setIssueView, groupByProperty: state.groupByProperty, setGroupByProperty, orderBy: state.orderBy, @@ -268,6 +295,8 @@ export const ThemeContextProvider: React.FC<{ children: React.ReactNode }> = ({ setFilterIssue, resetFilterToDefault: resetToDefault, setNewFilterDefaultView: setNewDefaultView, + setIssueViewToKanban, + setIssueViewToList, }} > diff --git a/apps/app/lib/hooks/useIssuesFilter.tsx b/apps/app/lib/hooks/useIssuesFilter.tsx index d6ee0089a..baa87ba69 100644 --- a/apps/app/lib/hooks/useIssuesFilter.tsx +++ b/apps/app/lib/hooks/useIssuesFilter.tsx @@ -10,7 +10,6 @@ import type { IIssue } from "types"; const useIssuesFilter = (projectIssues: IIssue[]) => { const { issueView, - setIssueView, groupByProperty, setGroupByProperty, orderBy, @@ -19,6 +18,8 @@ const useIssuesFilter = (projectIssues: IIssue[]) => { setFilterIssue, resetFilterToDefault, setNewFilterDefaultView, + setIssueViewToKanban, + setIssueViewToList, } = useTheme(); const { states } = useUser(); @@ -90,7 +91,6 @@ const useIssuesFilter = (projectIssues: IIssue[]) => { return { groupedByIssues, issueView, - setIssueView, groupByProperty, setGroupByProperty, orderBy, @@ -99,6 +99,8 @@ const useIssuesFilter = (projectIssues: IIssue[]) => { setFilterIssue, resetFilterToDefault, setNewFilterDefaultView, + setIssueViewToKanban, + setIssueViewToList, } as const; }; diff --git a/apps/app/pages/projects/[projectId]/issues/index.tsx b/apps/app/pages/projects/[projectId]/issues/index.tsx index 2f3bdcdb9..440ac5813 100644 --- a/apps/app/pages/projects/[projectId]/issues/index.tsx +++ b/apps/app/pages/projects/[projectId]/issues/index.tsx @@ -134,7 +134,6 @@ const ProjectIssues: NextPage = () => { const { issueView, - setIssueView, groupByProperty, setGroupByProperty, groupedByIssues, @@ -144,6 +143,8 @@ const ProjectIssues: NextPage = () => { filterIssue, resetFilterToDefault, setNewFilterDefaultView, + setIssueViewToKanban, + setIssueViewToList, } = useIssuesFilter(projectIssues?.results.filter((p) => p.parent === null) ?? []); useEffect(() => { @@ -171,10 +172,7 @@ const ProjectIssues: NextPage = () => { className={`h-7 w-7 p-1 grid place-items-center rounded hover:bg-gray-200 duration-300 outline-none ${ issueView === "list" ? "bg-gray-200" : "" }`} - onClick={() => { - setIssueView("list"); - setGroupByProperty(null); - }} + onClick={() => setIssueViewToList()} > @@ -183,10 +181,7 @@ const ProjectIssues: NextPage = () => { className={`h-7 w-7 p-1 grid place-items-center rounded hover:bg-gray-200 duration-300 outline-none ${ issueView === "kanban" ? "bg-gray-200" : "" }`} - onClick={() => { - setIssueView("kanban"); - setGroupByProperty("state_detail.name"); - }} + onClick={() => setIssueViewToKanban()} > From 2dfa9e12cb0f3ef3ca765b6d5febec2c24706c97 Mon Sep 17 00:00:00 2001 From: Dakshesh Jain Date: Tue, 20 Dec 2022 19:40:40 +0530 Subject: [PATCH 3/3] fix: build error --- .../pages/projects/[projectId]/cycles/[cycleId].tsx | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/apps/app/pages/projects/[projectId]/cycles/[cycleId].tsx b/apps/app/pages/projects/[projectId]/cycles/[cycleId].tsx index 666f92e6a..8fe449dbc 100644 --- a/apps/app/pages/projects/[projectId]/cycles/[cycleId].tsx +++ b/apps/app/pages/projects/[projectId]/cycles/[cycleId].tsx @@ -126,7 +126,6 @@ const SingleCycle: React.FC = () => { const { issueView, - setIssueView, groupByProperty, setGroupByProperty, groupedByIssues, @@ -134,6 +133,8 @@ const SingleCycle: React.FC = () => { setFilterIssue, orderBy, filterIssue, + setIssueViewToKanban, + setIssueViewToList, } = useIssuesFilter(cycleIssuesArray ?? []); const openCreateIssueModal = ( @@ -269,10 +270,7 @@ const SingleCycle: React.FC = () => { className={`h-7 w-7 p-1 grid place-items-center rounded hover:bg-gray-200 duration-300 outline-none ${ issueView === "list" ? "bg-gray-200" : "" }`} - onClick={() => { - setIssueView("list"); - setGroupByProperty(null); - }} + onClick={() => setIssueViewToList()} > @@ -281,10 +279,7 @@ const SingleCycle: React.FC = () => { className={`h-7 w-7 p-1 grid place-items-center rounded hover:bg-gray-200 duration-300 outline-none ${ issueView === "kanban" ? "bg-gray-200" : "" }`} - onClick={() => { - setIssueView("kanban"); - setGroupByProperty("state_detail.name"); - }} + onClick={() => setIssueViewToKanban()} >