diff --git a/web/contexts/app-root.context.tsx b/web/contexts/app-root.context.tsx deleted file mode 100644 index 48ce0a4112..0000000000 --- a/web/contexts/app-root.context.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { createContext, useContext } from "react"; -// mobx store -import { AppRootStore, IAppRootStore } from "store/application"; - -let appRootStore: IAppRootStore = new AppRootStore(); - -export const AppRootStoreContext = createContext(appRootStore); - -const initializeStore = () => { - const _appRootStore: IAppRootStore = appRootStore ?? new AppRootStore(); - if (typeof window === "undefined") return _appRootStore; - if (!appRootStore) appRootStore = _appRootStore; - return _appRootStore; -}; - -export const AppRootStoreProvider = ({ children }: any) => { - const store: IAppRootStore = initializeStore(); - return {children}; -}; - -export const useAppRootStore = () => { - const context = useContext(AppRootStoreContext); - if (context === undefined) throw new Error("useMobxStore must be used within MobxStoreProvider"); - return context; -}; diff --git a/web/contexts/issue-view.context.tsx b/web/contexts/issue-view.context.tsx deleted file mode 100644 index 562dd3e44f..0000000000 --- a/web/contexts/issue-view.context.tsx +++ /dev/null @@ -1,445 +0,0 @@ -import { createContext, useCallback, useEffect, useReducer } from "react"; -import { useRouter } from "next/router"; -import useSWR, { mutate } from "swr"; -// components -import ToastAlert from "components/toast-alert"; -// services -import { ProjectService, ProjectMemberService } from "services/project"; -import { CycleService } from "services/cycle.service"; -import { ModuleService } from "services/module.service"; -import { ViewService } from "services/view.service"; -// types -import { IIssueFilterOptions, IProjectMember, IIssueDisplayFilterOptions, IProjectViewProps } from "types"; -// fetch-keys -import { CYCLE_DETAILS, MODULE_DETAILS, USER_PROJECT_VIEW, VIEW_DETAILS } from "constants/fetch-keys"; - -const projectService = new ProjectService(); -const projectMemberService = new ProjectMemberService(); -const cycleService = new CycleService(); -const moduleService = new ModuleService(); -const viewService = new ViewService(); - -export const issueViewContext = createContext({} as ContextType); - -type ReducerActionType = { - type: "REHYDRATE_THEME" | "SET_DISPLAY_FILTERS" | "SET_FILTERS" | "RESET_TO_DEFAULT"; - payload?: Partial; -}; - -type ContextType = IProjectViewProps & { - setDisplayFilters: (displayFilter: Partial) => void; - setFilters: (filters: Partial, saveToServer?: boolean) => void; - resetFilterToDefault: () => void; - setNewFilterDefaultView: () => void; -}; - -type StateType = IProjectViewProps; -type ReducerFunctionType = (state: StateType, action: ReducerActionType) => StateType; - -export const initialState: StateType = { - display_filters: { - group_by: null, - layout: "list", - order_by: "-created_at", - show_empty_groups: true, - sub_issue: true, - }, - filters: { - priority: null, - assignees: null, - labels: null, - state: null, - state_group: null, - mentions: null, - subscriber: null, - created_by: null, - start_date: null, - target_date: null, - }, -}; - -export const reducer: ReducerFunctionType = (state, action) => { - const { type, payload } = action; - - switch (type) { - case "REHYDRATE_THEME": { - let collapsed: any = localStorage.getItem("collapsed"); - collapsed = collapsed ? JSON.parse(collapsed) : false; - - return { ...initialState, ...payload, collapsed }; - } - - case "SET_DISPLAY_FILTERS": { - const newState = { - ...state, - display_filters: { - ...state.display_filters, - ...payload, - }, - issueView: payload?.display_filters?.layout || "list", - }; - - return { - ...state, - ...newState, - }; - } - - case "SET_FILTERS": { - const newState = { - ...state, - filters: { - ...state.filters, - ...payload?.filters, - }, - }; - - return { - ...state, - ...newState, - }; - } - - case "RESET_TO_DEFAULT": { - return { - ...initialState, - ...payload, - }; - } - - default: { - return state; - } - } -}; - -const saveDataToServer = async (workspaceSlug: string, projectId: string, state: IProjectViewProps) => { - mutate( - workspaceSlug && projectId ? USER_PROJECT_VIEW(projectId as string) : null, - (prevData) => { - if (!prevData) return prevData; - - return { - ...prevData, - view_props: state, - }; - }, - false - ); - - await projectService.setProjectView(workspaceSlug, projectId, { - view_props: state, - }); -}; - -const saveCycleFilters = async (workspaceSlug: string, projectId: string, cycleId: string, state: any) => { - await cycleService.patchCycle(workspaceSlug, projectId, cycleId, { - ...state, - }); -}; - -const saveModuleFilters = async (workspaceSlug: string, projectId: string, moduleId: string, state: any) => { - await moduleService.patchModule(workspaceSlug, projectId, moduleId, { - ...state, - }); -}; - -const saveViewFilters = async (workspaceSlug: string, projectId: string, viewId: string, state: any) => { - await viewService.patchView(workspaceSlug, projectId, viewId, { - ...state, - }); -}; - -const setNewDefault = async (workspaceSlug: string, projectId: string, state: any) => { - mutate( - workspaceSlug && projectId ? USER_PROJECT_VIEW(projectId as string) : null, - (prevData) => { - if (!prevData) return prevData; - - return { - ...prevData, - view_props: state, - }; - }, - false - ); - - await projectService.setProjectView(workspaceSlug, projectId, { - view_props: state, - default_props: state, - }); -}; - -export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { - const [state, dispatch] = useReducer(reducer, initialState); - - const router = useRouter(); - const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query; - - const { data: myViewProps, mutate: mutateMyViewProps } = useSWR( - workspaceSlug && projectId ? USER_PROJECT_VIEW(projectId as string) : null, - workspaceSlug && projectId - ? () => projectMemberService.projectMemberMe(workspaceSlug as string, projectId as string) - : null - ); - - const { data: viewDetails, mutate: mutateViewDetails } = useSWR( - workspaceSlug && projectId && viewId ? VIEW_DETAILS(viewId as string) : null, - workspaceSlug && projectId && viewId - ? () => viewService.getViewDetails(workspaceSlug as string, projectId as string, viewId as string) - : null - ); - - const { data: cycleDetails, mutate: mutateCycleDetails } = useSWR( - workspaceSlug && projectId && cycleId ? CYCLE_DETAILS(cycleId as string) : null, - workspaceSlug && projectId && cycleId - ? () => cycleService.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 - ? () => moduleService.getModuleDetails(workspaceSlug.toString(), projectId.toString(), moduleId.toString()) - : null - ); - - const setDisplayFilters = useCallback( - (displayFilter: Partial) => { - dispatch({ - type: "SET_DISPLAY_FILTERS", - payload: { - display_filters: { - ...state.display_filters, - ...displayFilter, - }, - }, - }); - - const additionalProperties: Partial = { - group_by: displayFilter.group_by ?? state.display_filters?.group_by, - order_by: displayFilter.order_by ?? state.display_filters?.order_by, - }; - - if (displayFilter.layout && displayFilter.layout === "kanban" && state.display_filters?.group_by === null) { - additionalProperties.group_by = "state"; - dispatch({ - type: "SET_DISPLAY_FILTERS", - payload: { - display_filters: { - group_by: "state", - }, - }, - }); - } - if (displayFilter.layout && displayFilter.layout === "calendar") { - additionalProperties.group_by = null; - dispatch({ - type: "SET_DISPLAY_FILTERS", - payload: { - display_filters: { - group_by: null, - }, - }, - }); - } - if (displayFilter.layout && displayFilter.layout === "gantt_chart") { - additionalProperties.order_by = "sort_order"; - dispatch({ - type: "SET_DISPLAY_FILTERS", - payload: { - display_filters: { - order_by: "sort_order", - }, - }, - }); - } - - if (!workspaceSlug || !projectId) return; - - saveDataToServer(workspaceSlug as string, projectId as string, { - ...state, - display_filters: { - ...state.display_filters, - ...displayFilter, - ...additionalProperties, - }, - }); - }, - [workspaceSlug, projectId, state] - ); - - const setFilters = useCallback( - (property: Partial, saveToServer = true) => { - Object.keys(property).forEach((key) => { - if (property[key as keyof typeof property]?.length === 0) property[key as keyof typeof property] = null; - }); - - dispatch({ - type: "SET_FILTERS", - payload: { - filters: { - ...state.filters, - ...property, - }, - }, - }); - - if (!workspaceSlug || !projectId) return; - - if (cycleId) { - mutateCycleDetails((prevData: any) => { - if (!prevData) return prevData; - - return { - ...prevData, - view_props: { - filters: { - ...state.filters, - ...property, - }, - }, - }; - }, false); - - saveCycleFilters(workspaceSlug.toString(), projectId.toString(), cycleId.toString(), { - view_props: { - filters: { - ...state.filters, - ...property, - }, - }, - }); - } else if (moduleId) { - mutateModuleDetails((prevData: any) => { - if (!prevData) return prevData; - - 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 { - ...prevData, - query_data: { - ...state.filters, - ...property, - }, - }; - }, false); - if (saveToServer) - saveViewFilters(workspaceSlug as string, projectId as string, viewId as string, { - query_data: { - ...state.filters, - ...property, - }, - }); - } else { - mutateMyViewProps((prevData: any) => { - if (!prevData) return prevData; - - return { - ...prevData, - view_props: { - ...state, - filters: { - ...state.filters, - ...property, - }, - }, - }; - }, false); - - saveDataToServer(workspaceSlug as string, projectId as string, { - ...state, - filters: { - ...state.filters, - ...property, - }, - }); - } - }, - [ - projectId, - workspaceSlug, - state, - mutateMyViewProps, - cycleId, - mutateCycleDetails, - moduleId, - mutateModuleDetails, - viewId, - mutateViewDetails, - ] - ); - - const setNewDefaultView = useCallback(() => { - if (!workspaceSlug || !projectId) return; - - setNewDefault(workspaceSlug as string, projectId as string, state).then(() => { - mutateMyViewProps(); - }); - }, [projectId, workspaceSlug, state, mutateMyViewProps]); - - const resetToDefault = useCallback(() => { - dispatch({ - type: "RESET_TO_DEFAULT", - payload: myViewProps?.default_props, - }); - - if (!workspaceSlug || !projectId || !myViewProps) return; - - saveDataToServer(workspaceSlug as string, projectId as string, myViewProps.default_props); - }, [projectId, workspaceSlug, myViewProps]); - - useEffect(() => { - dispatch({ - type: "REHYDRATE_THEME", - payload: { - ...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, cycleId, cycleDetails, moduleId, moduleDetails, viewId, viewDetails]); - - return ( - - - {children} - - ); -}; diff --git a/web/contexts/page.context.tsx b/web/contexts/page.context.tsx deleted file mode 100644 index cb83a687ce..0000000000 --- a/web/contexts/page.context.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { createContext, useContext } from "react"; -// mobx store -import { PageStore } from "store/page.store"; -import { AppRootStore } from "store/application"; -import { useAppRootStore } from "./app-root.context"; - -export const PageContext = createContext(undefined); - -let pageStore: PageStore | undefined; - -export const PageStoreProvider = ({ children }: any) => { - const appRootStore = useAppRootStore(); - pageStore = pageStore ?? new PageStore(appRootStore); - return {children}; -}; - -export const usePage = () => { - const context = useContext(PageContext); - if (context === undefined) throw new Error("usePage must be used within AppRootStoreContext"); - return context; -}; diff --git a/web/contexts/user.context.tsx b/web/contexts/user.context.tsx deleted file mode 100644 index aeca99900e..0000000000 --- a/web/contexts/user.context.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import React, { createContext, ReactElement } from "react"; -import useSWR, { KeyedMutator } from "swr"; -// services -import { UserService } from "services/user.service"; -// constants -import { CURRENT_USER } from "constants/fetch-keys"; -// types -import type { IUser } from "types"; - -interface IUserContextProps { - user?: IUser; - isUserLoading: boolean; - mutateUser: KeyedMutator; - assignedIssuesLength?: number; - workspaceInvitesLength?: number; -} - -// services -const userService = new UserService(); - -export const UserContext = createContext({} as IUserContextProps); - -export const UserProvider = ({ children }: { children: ReactElement }) => { - // API to fetch user information - const { data, error, mutate } = useSWR(CURRENT_USER, () => userService.currentUser(), { - shouldRetryOnError: false, - }); - - return ( - - {children} - - ); -}; diff --git a/web/hooks/use-project-details.tsx b/web/hooks/use-project-details.tsx deleted file mode 100644 index 4a6fdd690e..0000000000 --- a/web/hooks/use-project-details.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { useRouter } from "next/router"; - -import useSWR from "swr"; - -// services -import { ProjectService } from "services/project"; -// fetch-keys -import { PROJECT_DETAILS } from "constants/fetch-keys"; - -const projectService = new ProjectService(); - -const useProjectDetails = () => { - const router = useRouter(); - const { workspaceSlug, projectId } = router.query; - - const { - data: projectDetails, - error: projectDetailsError, - mutate: mutateProjectDetails, - } = useSWR( - workspaceSlug && projectId ? PROJECT_DETAILS(projectId as string) : null, - workspaceSlug && projectId ? () => projectService.getProject(workspaceSlug as string, projectId as string) : null - ); - - return { - projectDetails, - projectDetailsError, - mutateProjectDetails, - }; -}; - -export default useProjectDetails; diff --git a/web/hooks/use-user-auth.tsx b/web/hooks/use-user-auth.tsx index a443fdb412..efcd945f30 100644 --- a/web/hooks/use-user-auth.tsx +++ b/web/hooks/use-user-auth.tsx @@ -25,7 +25,7 @@ const useUserAuth = (props: Props) => { if (!user) return; const firstWorkspace = Object.values(userWorkspaces ?? {})?.[0]; - const lastActiveWorkspace = userWorkspaces.find((workspsace) => workspsace.id === user?.last_workspace_id); + const lastActiveWorkspace = userWorkspaces.find((workspace) => workspace.id === user?.last_workspace_id); if (lastActiveWorkspace) { router.push(`/${lastActiveWorkspace.slug}`); diff --git a/web/hooks/use-user.tsx b/web/hooks/use-user.tsx deleted file mode 100644 index 97518fed6c..0000000000 --- a/web/hooks/use-user.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { useEffect } from "react"; -import { useRouter } from "next/router"; -import useSWR from "swr"; -// services -import { UserService } from "services/user.service"; -// constants -import { CURRENT_USER } from "constants/fetch-keys"; -// types -import type { IUser } from "types"; - -// services -const userService = new UserService(); - -export default function useUser({ redirectTo = "", redirectIfFound = false, options = {} } = {}) { - const router = useRouter(); - // API to fetch user information - const { data, isLoading, error, mutate } = useSWR(CURRENT_USER, () => userService.currentUser(), options); - - const user = error ? undefined : data; - - useEffect(() => { - // if no redirect needed, just return (example: already on /dashboard) - // if user data not yet there (fetch in progress, logged in or not) then don't do anything yet - if (!redirectTo || !user) return; - - if ( - // If redirectTo is set, redirect if the user was not found. - (redirectTo && !redirectIfFound) || - // If redirectIfFound is also set, redirect if the user was found - (redirectIfFound && user) - ) { - router.push(redirectTo); - return; - // const nextLocation = router.asPath.split("?next=")[1]; - // if (nextLocation) { - // router.push(nextLocation as string); - // return; - // } else { - // router.push("/"); - // return; - // } - } - }, [user, redirectIfFound, redirectTo, router]); - - return { - user, - isUserLoading: isLoading, - mutateUser: mutate, - userError: error, - // assignedIssuesLength: user?.assigned_issues ?? 0, - // workspaceInvitesLength: user?.workspace_invites ?? 0, - }; -} diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/archived-issues/index.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/archived-issues/index.tsx index 60adda066c..75e243216b 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/archived-issues/index.tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/archived-issues/index.tsx @@ -3,7 +3,6 @@ import { useRouter } from "next/router"; // layouts import { AppLayout } from "layouts/app-layout"; // contexts -import { IssueViewContextProvider } from "contexts/issue-view.context"; import { ArchivedIssueLayoutRoot } from "components/issues"; // ui import { ArchiveIcon } from "@plane/ui"; @@ -37,11 +36,9 @@ const ProjectArchivedIssuesPage: NextPageWithLayout = () => { ProjectArchivedIssuesPage.getLayout = function getLayout(page: ReactElement) { return ( - - } withProjectWrapper> - {page} - - + } withProjectWrapper> + {page} + ); }; diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/draft-issues/index.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/draft-issues/index.tsx index d669fe9437..9e6dbd3746 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/draft-issues/index.tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/draft-issues/index.tsx @@ -1,16 +1,13 @@ import { ReactElement } from "react"; import { useRouter } from "next/router"; +import { X, PenSquare } from "lucide-react"; // layouts import { AppLayout } from "layouts/app-layout"; -// contexts -import { IssueViewContextProvider } from "contexts/issue-view.context"; -// ui +// components +import { DraftIssueLayoutRoot } from "components/issues/issue-layouts/roots/draft-issue-layout-root"; import { ProjectDraftIssueHeader } from "components/headers"; -// icons -import { X, PenSquare } from "lucide-react"; // types import { NextPageWithLayout } from "types/app"; -import { DraftIssueLayoutRoot } from "components/issues/issue-layouts/roots/draft-issue-layout-root"; const ProjectDraftIssuesPage: NextPageWithLayout = () => { const router = useRouter(); @@ -36,11 +33,9 @@ const ProjectDraftIssuesPage: NextPageWithLayout = () => { ProjectDraftIssuesPage.getLayout = function getLayout(page: ReactElement) { return ( - - } withProjectWrapper> - {page} - - + } withProjectWrapper> + {page} + ); }; diff --git a/web/store/application/app-config.store.ts b/web/store/application/app-config.store.ts index 5b38a82923..9dd9a1c4c6 100644 --- a/web/store/application/app-config.store.ts +++ b/web/store/application/app-config.store.ts @@ -29,12 +29,11 @@ export class AppConfigStore implements IAppConfigStore { /** * Fetches the app config from the API */ - fetchAppConfig = async () => { - return await this.appConfigService.envConfig().then((config) => { + fetchAppConfig = async () => + await this.appConfigService.envConfig().then((config) => { runInAction(() => { this.envConfig = config; }); return config; }); - }; } diff --git a/web/store/application/instance.store.ts b/web/store/application/instance.store.ts index cb5f57d000..e0c23e748b 100644 --- a/web/store/application/instance.store.ts +++ b/web/store/application/instance.store.ts @@ -88,14 +88,13 @@ export class InstanceStore implements IInstanceStore { * update instance info * @param data */ - updateInstanceInfo = async (data: Partial) => { - return await this.instanceService.updateInstanceInfo(data).then((response) => { + updateInstanceInfo = async (data: Partial) => + await this.instanceService.updateInstanceInfo(data).then((response) => { runInAction(() => { this.instance = response; }); return response; }); - }; /** * fetch instace configurations from API @@ -117,12 +116,11 @@ export class InstanceStore implements IInstanceStore { * update instance configurations * @param data */ - updateInstanceConfigurations = async (data: Partial) => { - return await this.instanceService.updateInstanceConfigurations(data).then((response) => { + updateInstanceConfigurations = async (data: Partial) => + await this.instanceService.updateInstanceConfigurations(data).then((response) => { runInAction(() => { this.configurations = this.configurations ? [...this.configurations, ...response] : response; }); return response; }); - }; } diff --git a/web/store/project-view.store.ts b/web/store/project-view.store.ts index f32d383aac..fff7fcf2ea 100644 --- a/web/store/project-view.store.ts +++ b/web/store/project-view.store.ts @@ -84,8 +84,8 @@ export class ProjectViewStore implements IProjectViewStore { * @param projectId * @returns Promise */ - fetchViews = async (workspaceSlug: string, projectId: string) => { - return await this.viewService.getViews(workspaceSlug, projectId).then((response) => { + fetchViews = async (workspaceSlug: string, projectId: string) => + await this.viewService.getViews(workspaceSlug, projectId).then((response) => { runInAction(() => { response.forEach((view) => { set(this.viewMap, [view.id], view); @@ -93,7 +93,6 @@ export class ProjectViewStore implements IProjectViewStore { }); return response; }); - }; /** * Fetches view details for a specific view @@ -102,14 +101,13 @@ export class ProjectViewStore implements IProjectViewStore { * @param viewId * @returns Promise */ - fetchViewDetails = async (workspaceSlug: string, projectId: string, viewId: string): Promise => { - return await this.viewService.getViewDetails(workspaceSlug, projectId, viewId).then((response) => { + fetchViewDetails = async (workspaceSlug: string, projectId: string, viewId: string): Promise => + await this.viewService.getViewDetails(workspaceSlug, projectId, viewId).then((response) => { runInAction(() => { set(this.viewMap, [viewId], response); }); return response; }); - }; /** * Creates a new view for a specific project and adds it to the store @@ -118,14 +116,13 @@ export class ProjectViewStore implements IProjectViewStore { * @param data * @returns Promise */ - createView = async (workspaceSlug: string, projectId: string, data: Partial): Promise => { - return await this.viewService.createView(workspaceSlug, projectId, data).then((response) => { + createView = async (workspaceSlug: string, projectId: string, data: Partial): Promise => + await this.viewService.createView(workspaceSlug, projectId, data).then((response) => { runInAction(() => { set(this.viewMap, [response.id], response); }); return response; }); - }; /** * Updates a view details of specific view and updates it in the store