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;