mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
chore: setup inbox store and implement router store
This commit is contained in:
parent
cc56140912
commit
34e4b6e2ff
11
web/hooks/store/use-inbox.ts
Normal file
11
web/hooks/store/use-inbox.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { useContext } from "react";
|
||||
// mobx store
|
||||
import { StoreContext } from "contexts/store-context";
|
||||
// types
|
||||
import { IInboxRootStore } from "store/inbox";
|
||||
|
||||
export const useInbox = (): IInboxRootStore => {
|
||||
const context = useContext(StoreContext);
|
||||
if (context === undefined) throw new Error("useInbox must be used within StoreProvider");
|
||||
return context.inboxRoot;
|
||||
};
|
@ -52,17 +52,12 @@ export const WorkspaceAuthWrapper: FC<IWorkspaceAuthWrapper> = observer((props)
|
||||
workspaceSlug ? () => membership.fetchUserWorkspaceProjectsRole(workspaceSlug.toString()) : null
|
||||
);
|
||||
|
||||
console.log("workspaceMemberInfo", membership.workspaceMemberInfo);
|
||||
console.log("currentWorkspaceMemberInfo", membership.currentWorkspaceMemberInfo);
|
||||
console.log("hasPermissionToCurrentWorkspace", membership.hasPermissionToCurrentWorkspace);
|
||||
|
||||
// while data is being loaded
|
||||
if (!membership.currentWorkspaceMemberInfo && membership.hasPermissionToCurrentWorkspace === undefined) {
|
||||
return (
|
||||
<div className="grid h-screen place-items-center bg-custom-background-100 p-4">
|
||||
<div className="flex flex-col items-center gap-3 text-center">
|
||||
{/* <Spinner /> */}
|
||||
Not allowed
|
||||
<Spinner />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
26
web/lib/mobx/store-provider.tsx
Normal file
26
web/lib/mobx/store-provider.tsx
Normal file
@ -0,0 +1,26 @@
|
||||
import { createContext, useContext } from "react";
|
||||
import { RootStore } from "store/root.store";
|
||||
// mobx store
|
||||
|
||||
let rootStore: RootStore = new RootStore();
|
||||
|
||||
export const MobxStoreContext = createContext<RootStore>(rootStore);
|
||||
|
||||
const initializeStore = () => {
|
||||
const _rootStore: RootStore = rootStore ?? new RootStore();
|
||||
if (typeof window === "undefined") return _rootStore;
|
||||
if (!rootStore) rootStore = _rootStore;
|
||||
return _rootStore;
|
||||
};
|
||||
|
||||
export const MobxStoreProvider = ({ children }: any) => {
|
||||
const store: RootStore = initializeStore();
|
||||
return <MobxStoreContext.Provider value={store}>{children}</MobxStoreContext.Provider>;
|
||||
};
|
||||
|
||||
// hook
|
||||
export const useMobxStore = () => {
|
||||
const context = useContext(MobxStoreContext);
|
||||
if (context === undefined) throw new Error("useMobxStore must be used within MobxStoreProvider");
|
||||
return context;
|
||||
};
|
@ -1,4 +1,5 @@
|
||||
import { ReactNode, useEffect, useState, FC } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import useSWR from "swr";
|
||||
import { useTheme } from "next-themes";
|
||||
@ -15,10 +16,13 @@ const StoreWrapper: FC<IStoreWrapper> = observer((props) => {
|
||||
const { children } = props;
|
||||
// states
|
||||
const [dom, setDom] = useState<any>();
|
||||
// router
|
||||
const router = useRouter();
|
||||
// store hooks
|
||||
const {
|
||||
config: { fetchAppConfig },
|
||||
theme: { sidebarCollapsed, toggleSidebar },
|
||||
router: { setQuery },
|
||||
} = useApplication();
|
||||
const { currentUser } = useUser();
|
||||
// fetching application Config
|
||||
@ -32,9 +36,8 @@ const StoreWrapper: FC<IStoreWrapper> = observer((props) => {
|
||||
useEffect(() => {
|
||||
const localValue = localStorage && localStorage.getItem("app_sidebar_collapsed");
|
||||
const localBoolValue = localValue ? (localValue === "true" ? true : false) : false;
|
||||
if (localValue && sidebarCollapsed === undefined) {
|
||||
toggleSidebar(localBoolValue);
|
||||
}
|
||||
|
||||
if (localValue && sidebarCollapsed === undefined) toggleSidebar(localBoolValue);
|
||||
}, [sidebarCollapsed, currentUser, setTheme, toggleSidebar]);
|
||||
|
||||
/**
|
||||
@ -42,16 +45,18 @@ const StoreWrapper: FC<IStoreWrapper> = observer((props) => {
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (!currentUser) return;
|
||||
if (window) {
|
||||
setDom(window.document?.querySelector<HTMLElement>("[data-theme='custom']"));
|
||||
}
|
||||
if (window) setDom(window.document?.querySelector<HTMLElement>("[data-theme='custom']"));
|
||||
|
||||
setTheme(currentUser?.theme?.theme || "system");
|
||||
if (currentUser?.theme?.theme === "custom" && dom) {
|
||||
applyTheme(currentUser?.theme?.palette, false);
|
||||
} else unsetCustomCssVariables();
|
||||
if (currentUser?.theme?.theme === "custom" && dom) applyTheme(currentUser?.theme?.palette, false);
|
||||
else unsetCustomCssVariables();
|
||||
}, [currentUser, setTheme, dom]);
|
||||
|
||||
// TODO: set router values
|
||||
useEffect(() => {
|
||||
if (!router.query) return;
|
||||
|
||||
setQuery(router.query);
|
||||
}, [router.query, setQuery]);
|
||||
|
||||
return <>{children}</>;
|
||||
});
|
||||
|
@ -1,101 +0,0 @@
|
||||
import { ReactNode, useEffect, useState, FC } from "react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import useSWR from "swr";
|
||||
import { useTheme } from "next-themes";
|
||||
import { useRouter } from "next/router";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// helpers
|
||||
import { applyTheme, unsetCustomCssVariables } from "helpers/theme.helper";
|
||||
|
||||
interface IStoreWrapper {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
const StoreWrapper: FC<IStoreWrapper> = observer((props) => {
|
||||
const { children } = props;
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, cycleId, moduleId, globalViewId, viewId, inboxId, webhookId } = router.query;
|
||||
// store
|
||||
const {
|
||||
theme: { sidebarCollapsed, toggleSidebar },
|
||||
user: { currentUser },
|
||||
workspace: { setWorkspaceSlug },
|
||||
project: { setProjectId },
|
||||
cycle: { setCycleId },
|
||||
module: { setModuleId },
|
||||
globalViews: { setGlobalViewId },
|
||||
projectViews: { setViewId },
|
||||
inbox: { setInboxId },
|
||||
webhook: { setCurrentWebhookId },
|
||||
appConfig: { fetchAppConfig },
|
||||
} = useMobxStore();
|
||||
// fetching application Config
|
||||
useSWR("APP_CONFIG", () => fetchAppConfig(), { revalidateIfStale: false, revalidateOnFocus: false });
|
||||
// state
|
||||
const [dom, setDom] = useState<any>();
|
||||
// theme
|
||||
const { setTheme } = useTheme();
|
||||
|
||||
/**
|
||||
* Sidebar collapsed fetching from local storage
|
||||
*/
|
||||
useEffect(() => {
|
||||
const localValue = localStorage && localStorage.getItem("app_sidebar_collapsed");
|
||||
const localBoolValue = localValue ? (localValue === "true" ? true : false) : false;
|
||||
if (localValue && sidebarCollapsed === undefined) {
|
||||
toggleSidebar(localBoolValue);
|
||||
}
|
||||
}, [sidebarCollapsed, currentUser, setTheme, toggleSidebar]);
|
||||
|
||||
/**
|
||||
* Setting up the theme of the user by fetching it from local storage
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (!currentUser) return;
|
||||
if (window) {
|
||||
setDom(window.document?.querySelector<HTMLElement>("[data-theme='custom']"));
|
||||
}
|
||||
setTheme(currentUser?.theme?.theme || "system");
|
||||
if (currentUser?.theme?.theme === "custom" && dom) {
|
||||
applyTheme(currentUser?.theme?.palette, false);
|
||||
} else unsetCustomCssVariables();
|
||||
}, [currentUser, setTheme, dom]);
|
||||
|
||||
/**
|
||||
* Setting router info to the respective stores.
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (workspaceSlug) setWorkspaceSlug(workspaceSlug.toString());
|
||||
|
||||
setProjectId(projectId?.toString() ?? null);
|
||||
setCycleId(cycleId?.toString() ?? null);
|
||||
setModuleId(moduleId?.toString() ?? null);
|
||||
setGlobalViewId(globalViewId?.toString() ?? null);
|
||||
setViewId(viewId?.toString() ?? null);
|
||||
setInboxId(inboxId?.toString() ?? null);
|
||||
setCurrentWebhookId(webhookId?.toString() ?? undefined);
|
||||
}, [
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
cycleId,
|
||||
moduleId,
|
||||
globalViewId,
|
||||
viewId,
|
||||
inboxId,
|
||||
webhookId,
|
||||
setWorkspaceSlug,
|
||||
setProjectId,
|
||||
setCycleId,
|
||||
setModuleId,
|
||||
setGlobalViewId,
|
||||
setViewId,
|
||||
setInboxId,
|
||||
setCurrentWebhookId,
|
||||
]);
|
||||
|
||||
return <>{children}</>;
|
||||
});
|
||||
|
||||
export default StoreWrapper;
|
@ -1,10 +1,12 @@
|
||||
import { action, makeObservable, observable, computed } from "mobx";
|
||||
import { action, makeObservable, observable, computed, runInAction } from "mobx";
|
||||
import { ParsedUrlQuery } from "node:querystring";
|
||||
|
||||
export interface IRouterStore {
|
||||
// observables
|
||||
query: ParsedUrlQuery;
|
||||
// actions
|
||||
setQuery: (query: ParsedUrlQuery) => void;
|
||||
|
||||
// computed
|
||||
workspaceSlug: string | undefined;
|
||||
projectId: string | undefined;
|
||||
cycleId: string | undefined;
|
||||
@ -18,13 +20,15 @@ export interface IRouterStore {
|
||||
}
|
||||
|
||||
export class RouterStore implements IRouterStore {
|
||||
// observables
|
||||
query: ParsedUrlQuery = {};
|
||||
|
||||
constructor() {
|
||||
makeObservable(this, {
|
||||
// observables
|
||||
query: observable,
|
||||
// actions
|
||||
setQuery: action,
|
||||
|
||||
//computed
|
||||
workspaceSlug: computed,
|
||||
projectId: computed,
|
||||
@ -39,9 +43,11 @@ export class RouterStore implements IRouterStore {
|
||||
});
|
||||
}
|
||||
|
||||
setQuery(query: ParsedUrlQuery) {
|
||||
this.query = query;
|
||||
}
|
||||
setQuery = (query: ParsedUrlQuery) => {
|
||||
runInAction(() => {
|
||||
this.query = query;
|
||||
});
|
||||
};
|
||||
|
||||
get workspaceSlug() {
|
||||
return this.query?.workspaceSlug?.toString();
|
||||
|
134
web/store/inbox/inbox.store.ts
Normal file
134
web/store/inbox/inbox.store.ts
Normal file
@ -0,0 +1,134 @@
|
||||
import { observable, action, makeObservable, runInAction, computed } from "mobx";
|
||||
import { set } from "lodash";
|
||||
// services
|
||||
import { InboxService } from "services/inbox.service";
|
||||
// types
|
||||
import { RootStore } from "store/root.store";
|
||||
import { IInbox } from "types";
|
||||
|
||||
export interface IInboxStore {
|
||||
// states
|
||||
loader: boolean;
|
||||
error: any | null;
|
||||
// observables
|
||||
inboxesList: {
|
||||
[projectId: string]: IInbox[];
|
||||
};
|
||||
inboxDetails: {
|
||||
[inboxId: string]: IInbox;
|
||||
};
|
||||
// computed
|
||||
isInboxEnabled: boolean;
|
||||
// computed actions
|
||||
getInboxId: (projectId: string) => string | null;
|
||||
// actions
|
||||
fetchInboxesList: (workspaceSlug: string, projectId: string) => Promise<IInbox[]>;
|
||||
fetchInboxDetails: (workspaceSlug: string, projectId: string, inboxId: string) => Promise<IInbox>;
|
||||
}
|
||||
|
||||
export class InboxStore implements IInboxStore {
|
||||
// states
|
||||
loader: boolean = false;
|
||||
error: any | null = null;
|
||||
// observables
|
||||
inboxesList: {
|
||||
[projectId: string]: IInbox[];
|
||||
} = {};
|
||||
inboxDetails: {
|
||||
[inboxId: string]: IInbox;
|
||||
} = {};
|
||||
// root store
|
||||
rootStore;
|
||||
// services
|
||||
inboxService;
|
||||
|
||||
constructor(_rootStore: RootStore) {
|
||||
makeObservable(this, {
|
||||
// states
|
||||
loader: observable.ref,
|
||||
error: observable.ref,
|
||||
// observables
|
||||
inboxesList: observable,
|
||||
inboxDetails: observable,
|
||||
// computed
|
||||
isInboxEnabled: computed,
|
||||
// computed actions
|
||||
getInboxId: action,
|
||||
// actions
|
||||
fetchInboxesList: action,
|
||||
});
|
||||
|
||||
// root store
|
||||
this.rootStore = _rootStore;
|
||||
// services
|
||||
this.inboxService = new InboxService();
|
||||
}
|
||||
|
||||
get isInboxEnabled() {
|
||||
const projectId = this.rootStore.app.router.projectId;
|
||||
|
||||
if (!projectId) return false;
|
||||
|
||||
const projectDetails = this.rootStore.projectRoot.project.currentProjectDetails;
|
||||
|
||||
if (!projectDetails) return false;
|
||||
|
||||
return projectDetails.inbox_view;
|
||||
}
|
||||
|
||||
getInboxId = (projectId: string) => {
|
||||
const projectDetails = this.rootStore.projectRoot.project.getProjectById(projectId);
|
||||
|
||||
if (!projectDetails || !projectDetails.inbox_view) return null;
|
||||
|
||||
return this.inboxesList[projectId]?.[0]?.id ?? null;
|
||||
};
|
||||
|
||||
fetchInboxesList = async (workspaceSlug: string, projectId: string) => {
|
||||
try {
|
||||
runInAction(() => {
|
||||
this.loader = true;
|
||||
});
|
||||
|
||||
const inboxesResponse = await this.inboxService.getInboxes(workspaceSlug, projectId);
|
||||
|
||||
runInAction(() => {
|
||||
this.loader = false;
|
||||
set(this.inboxesList, projectId, inboxesResponse);
|
||||
});
|
||||
|
||||
return inboxesResponse;
|
||||
} catch (error) {
|
||||
runInAction(() => {
|
||||
this.loader = false;
|
||||
this.error = error;
|
||||
});
|
||||
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
fetchInboxDetails = async (workspaceSlug: string, projectId: string, inboxId: string) => {
|
||||
try {
|
||||
runInAction(() => {
|
||||
this.loader = true;
|
||||
});
|
||||
|
||||
const inboxDetailsResponse = await this.inboxService.getInboxById(workspaceSlug, projectId, inboxId);
|
||||
|
||||
runInAction(() => {
|
||||
this.loader = false;
|
||||
set(this.inboxDetails, inboxId, inboxDetailsResponse);
|
||||
});
|
||||
|
||||
return inboxDetailsResponse;
|
||||
} catch (error) {
|
||||
runInAction(() => {
|
||||
this.loader = false;
|
||||
this.error = error;
|
||||
});
|
||||
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
}
|
135
web/store/inbox/inbox_filter.store.ts
Normal file
135
web/store/inbox/inbox_filter.store.ts
Normal file
@ -0,0 +1,135 @@
|
||||
import { observable, action, makeObservable, runInAction, computed } from "mobx";
|
||||
import { set } from "lodash";
|
||||
// services
|
||||
import { InboxService } from "services/inbox.service";
|
||||
// types
|
||||
import { RootStore } from "store/root.store";
|
||||
import { IInbox, IInboxFilterOptions, IInboxQueryParams } from "types";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
|
||||
export interface IInboxFiltersStore {
|
||||
// states
|
||||
loader: boolean;
|
||||
error: any | null;
|
||||
// observables
|
||||
inboxFilters: {
|
||||
[inboxId: string]: { filters: IInboxFilterOptions };
|
||||
};
|
||||
// computed
|
||||
appliedFilters: IInboxQueryParams | null;
|
||||
// actions
|
||||
fetchInboxFilters: (workspaceSlug: string, projectId: string, inboxId: string) => Promise<IInbox>;
|
||||
updateInboxFilters: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
inboxId: string,
|
||||
filters: Partial<IInboxFilterOptions>
|
||||
) => Promise<void>;
|
||||
}
|
||||
|
||||
export class InboxFiltersStore implements IInboxFiltersStore {
|
||||
// states
|
||||
loader: boolean = false;
|
||||
error: any | null = null;
|
||||
// observables
|
||||
inboxFilters: {
|
||||
[inboxId: string]: { filters: IInboxFilterOptions };
|
||||
} = {};
|
||||
// root store
|
||||
rootStore;
|
||||
// services
|
||||
inboxService;
|
||||
|
||||
constructor(_rootStore: RootStore) {
|
||||
makeObservable(this, {
|
||||
// states
|
||||
loader: observable.ref,
|
||||
error: observable.ref,
|
||||
// observables
|
||||
inboxFilters: observable,
|
||||
// computed
|
||||
appliedFilters: computed,
|
||||
// actions
|
||||
fetchInboxFilters: action,
|
||||
updateInboxFilters: action,
|
||||
});
|
||||
|
||||
this.rootStore = _rootStore;
|
||||
this.inboxService = new InboxService();
|
||||
}
|
||||
|
||||
get appliedFilters(): IInboxQueryParams | null {
|
||||
const inboxId = this.rootStore.app.router.inboxId;
|
||||
|
||||
if (!inboxId) return null;
|
||||
|
||||
const filtersList = this.inboxFilters[inboxId]?.filters;
|
||||
|
||||
if (!filtersList) return null;
|
||||
|
||||
const filteredRouteParams: IInboxQueryParams = {
|
||||
priority: filtersList.priority ? filtersList.priority.join(",") : null,
|
||||
inbox_status: filtersList.inbox_status ? filtersList.inbox_status.join(",") : null,
|
||||
};
|
||||
|
||||
return filteredRouteParams;
|
||||
}
|
||||
|
||||
fetchInboxFilters = async (workspaceSlug: string, projectId: string, inboxId: string) => {
|
||||
try {
|
||||
runInAction(() => {
|
||||
this.loader = true;
|
||||
});
|
||||
|
||||
const issuesResponse = await this.inboxService.getInboxById(workspaceSlug, projectId, inboxId);
|
||||
|
||||
runInAction(() => {
|
||||
this.loader = false;
|
||||
set(this.inboxFilters, [inboxId], issuesResponse.view_props);
|
||||
});
|
||||
|
||||
return issuesResponse;
|
||||
} catch (error) {
|
||||
runInAction(() => {
|
||||
this.loader = false;
|
||||
this.error = error;
|
||||
});
|
||||
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
updateInboxFilters = async (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
inboxId: string,
|
||||
filters: Partial<IInboxFilterOptions>
|
||||
) => {
|
||||
const newViewProps = {
|
||||
...this.inboxFilters[inboxId],
|
||||
filters: {
|
||||
...this.inboxFilters[inboxId]?.filters,
|
||||
...filters,
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
runInAction(() => {
|
||||
set(this.inboxFilters, [inboxId], newViewProps);
|
||||
});
|
||||
|
||||
const userRole = this.rootStore.user.membership?.currentProjectRole || EUserProjectRoles.GUEST;
|
||||
if (userRole > EUserWorkspaceRoles.VIEWER)
|
||||
await this.inboxService.patchInbox(workspaceSlug, projectId, inboxId, { view_props: newViewProps });
|
||||
} catch (error) {
|
||||
runInAction(() => {
|
||||
this.error = error;
|
||||
});
|
||||
|
||||
this.fetchInboxFilters(workspaceSlug, projectId, inboxId);
|
||||
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
}
|
256
web/store/inbox/inbox_issue.store.ts
Normal file
256
web/store/inbox/inbox_issue.store.ts
Normal file
@ -0,0 +1,256 @@
|
||||
import { observable, action, makeObservable, runInAction, autorun } from "mobx";
|
||||
import { set } from "lodash";
|
||||
// services
|
||||
import { InboxService } from "services/inbox.service";
|
||||
// types
|
||||
import { RootStore } from "store/root.store";
|
||||
import { IInboxIssue, IIssue, TInboxStatus } from "types";
|
||||
// constants
|
||||
import { INBOX_ISSUE_SOURCE } from "constants/inbox";
|
||||
|
||||
export interface IInboxIssuesStore {
|
||||
// states
|
||||
loader: boolean;
|
||||
error: any | null;
|
||||
// observables
|
||||
issueMap: Record<string, IInboxIssue>;
|
||||
// computed actions
|
||||
getIssueById: (issueId: string) => IInboxIssue | null;
|
||||
// actions
|
||||
fetchIssues: (workspaceSlug: string, projectId: string, inboxId: string) => Promise<IInboxIssue[]>;
|
||||
fetchIssueDetails: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
inboxId: string,
|
||||
issueId: string
|
||||
) => Promise<IInboxIssue>;
|
||||
createIssue: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
inboxId: string,
|
||||
data: Partial<IIssue>
|
||||
) => Promise<IInboxIssue>;
|
||||
updateIssue: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
inboxId: string,
|
||||
issueId: string,
|
||||
data: Partial<IInboxIssue>
|
||||
) => Promise<void>;
|
||||
updateIssueStatus: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
inboxId: string,
|
||||
issueId: string,
|
||||
data: TInboxStatus
|
||||
) => Promise<void>;
|
||||
deleteIssue: (workspaceSlug: string, projectId: string, inboxId: string, issueId: string) => Promise<void>;
|
||||
}
|
||||
|
||||
export class InboxIssuesStore implements IInboxIssuesStore {
|
||||
// states
|
||||
loader: boolean = false;
|
||||
error: any | null = null;
|
||||
// observables
|
||||
issueMap: Record<string, IInboxIssue> = {};
|
||||
// root store
|
||||
rootStore;
|
||||
// services
|
||||
inboxService;
|
||||
|
||||
constructor(_rootStore: RootStore) {
|
||||
makeObservable(this, {
|
||||
// states
|
||||
loader: observable.ref,
|
||||
error: observable.ref,
|
||||
// observables
|
||||
issueMap: observable,
|
||||
// computed actions
|
||||
getIssueById: action,
|
||||
// actions
|
||||
fetchIssues: action,
|
||||
fetchIssueDetails: action,
|
||||
createIssue: action,
|
||||
updateIssue: action,
|
||||
updateIssueStatus: action,
|
||||
deleteIssue: action,
|
||||
});
|
||||
|
||||
// root store
|
||||
this.rootStore = _rootStore;
|
||||
// services
|
||||
this.inboxService = new InboxService();
|
||||
|
||||
autorun(() => {
|
||||
const routerStore = this.rootStore.app.router;
|
||||
|
||||
const workspaceSlug = routerStore?.workspaceSlug;
|
||||
const projectId = routerStore?.projectId;
|
||||
const inboxId = routerStore?.inboxId;
|
||||
|
||||
if (workspaceSlug && projectId && inboxId && this.rootStore.inboxRoot.inboxFilters.inboxFilters[inboxId])
|
||||
this.fetchIssues(workspaceSlug, projectId, inboxId);
|
||||
});
|
||||
}
|
||||
|
||||
getIssueById = (issueId: string): IInboxIssue | null => this.issueMap[issueId] ?? null;
|
||||
|
||||
fetchIssues = async (workspaceSlug: string, projectId: string, inboxId: string) => {
|
||||
try {
|
||||
runInAction(() => {
|
||||
this.loader = true;
|
||||
});
|
||||
|
||||
const queryParams = this.rootStore.inboxRoot.inboxFilters.appliedFilters ?? undefined;
|
||||
|
||||
const issuesResponse = await this.inboxService.getInboxIssues(workspaceSlug, projectId, inboxId, queryParams);
|
||||
|
||||
runInAction(() => {
|
||||
this.loader = false;
|
||||
issuesResponse.forEach((issue) => {
|
||||
set(this.issueMap, issue.issue_inbox?.[0].id, issue);
|
||||
});
|
||||
});
|
||||
|
||||
return issuesResponse;
|
||||
} catch (error) {
|
||||
runInAction(() => {
|
||||
this.loader = false;
|
||||
this.error = error;
|
||||
});
|
||||
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
fetchIssueDetails = async (workspaceSlug: string, projectId: string, inboxId: string, issueId: string) => {
|
||||
try {
|
||||
runInAction(() => {
|
||||
this.loader = true;
|
||||
});
|
||||
|
||||
const issueResponse = await this.inboxService.getInboxIssueById(workspaceSlug, projectId, inboxId, issueId);
|
||||
|
||||
runInAction(() => {
|
||||
this.loader = false;
|
||||
set(this.issueMap, issueId, issueResponse);
|
||||
});
|
||||
|
||||
return issueResponse;
|
||||
} catch (error) {
|
||||
runInAction(() => {
|
||||
this.loader = false;
|
||||
this.error = error;
|
||||
});
|
||||
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
createIssue = async (workspaceSlug: string, projectId: string, inboxId: string, data: Partial<IIssue>) => {
|
||||
const payload = {
|
||||
issue: {
|
||||
name: data.name,
|
||||
description: data.description,
|
||||
description_html: data.description_html,
|
||||
priority: data.priority,
|
||||
},
|
||||
source: INBOX_ISSUE_SOURCE,
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await this.inboxService.createInboxIssue(workspaceSlug, projectId, inboxId, payload);
|
||||
|
||||
runInAction(() => {
|
||||
set(this.issueMap, response.issue_inbox?.[0].id, response);
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
runInAction(() => {
|
||||
this.error = error;
|
||||
});
|
||||
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
updateIssue = async (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
inboxId: string,
|
||||
issueId: string,
|
||||
data: Partial<IInboxIssue>
|
||||
) => {
|
||||
const issueDetails = this.rootStore.inboxRoot.inboxIssues.getIssueById(issueId);
|
||||
|
||||
try {
|
||||
runInAction(() => {
|
||||
set(this.issueMap, issueId, {
|
||||
...issueDetails,
|
||||
...data,
|
||||
});
|
||||
});
|
||||
|
||||
await this.inboxService.patchInboxIssue(workspaceSlug, projectId, inboxId, issueId, { issue: data });
|
||||
} catch (error) {
|
||||
runInAction(() => {
|
||||
this.error = error;
|
||||
});
|
||||
|
||||
this.rootStore.inboxRoot.inboxIssues.fetchIssues(workspaceSlug, projectId, inboxId);
|
||||
this.fetchIssueDetails(workspaceSlug, projectId, inboxId, issueId);
|
||||
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
updateIssueStatus = async (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
inboxId: string,
|
||||
issueId: string,
|
||||
data: TInboxStatus
|
||||
) => {
|
||||
const issueDetails = this.rootStore.inboxRoot.inboxIssues.getIssueById(issueId);
|
||||
|
||||
try {
|
||||
runInAction(() => {
|
||||
set(this.issueMap, [issueId, "issue_inbox", 0], {
|
||||
...issueDetails?.issue_inbox?.[0],
|
||||
...data,
|
||||
});
|
||||
});
|
||||
|
||||
await this.inboxService.markInboxStatus(workspaceSlug, projectId, inboxId, issueId, data);
|
||||
} catch (error) {
|
||||
runInAction(() => {
|
||||
this.error = error;
|
||||
});
|
||||
|
||||
this.rootStore.inboxRoot.inboxIssues.fetchIssues(workspaceSlug, projectId, inboxId);
|
||||
this.fetchIssueDetails(workspaceSlug, projectId, inboxId, issueId);
|
||||
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
deleteIssue = async (workspaceSlug: string, projectId: string, inboxId: string, issueId: string) => {
|
||||
try {
|
||||
runInAction(() => {
|
||||
delete this.issueMap[issueId];
|
||||
});
|
||||
|
||||
await this.inboxService.deleteInboxIssue(workspaceSlug, projectId, inboxId, issueId);
|
||||
} catch (error) {
|
||||
runInAction(() => {
|
||||
this.error = error;
|
||||
});
|
||||
|
||||
this.rootStore.inboxRoot.inboxIssues.fetchIssues(workspaceSlug, projectId, inboxId);
|
||||
this.fetchIssueDetails(workspaceSlug, projectId, inboxId, issueId);
|
||||
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
}
|
33
web/store/inbox/index.ts
Normal file
33
web/store/inbox/index.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { makeAutoObservable } from "mobx";
|
||||
// types
|
||||
import { RootStore } from "store/root.store";
|
||||
import { IInboxIssuesStore, InboxIssuesStore } from "./inbox_issue.store";
|
||||
import { IInboxFiltersStore, InboxFiltersStore } from "./inbox_filter.store";
|
||||
import { IInboxStore, InboxStore } from "./inbox.store";
|
||||
|
||||
export interface IInboxRootStore {
|
||||
// sub-stores
|
||||
inbox: IInboxStore;
|
||||
inboxFilters: IInboxFiltersStore;
|
||||
inboxIssues: IInboxIssuesStore;
|
||||
}
|
||||
|
||||
export class InboxRootStore implements IInboxRootStore {
|
||||
// root store
|
||||
rootStore: RootStore;
|
||||
// sub-stores
|
||||
inbox: IInboxStore;
|
||||
inboxFilters: IInboxFiltersStore;
|
||||
inboxIssues: IInboxIssuesStore;
|
||||
|
||||
constructor(_rootStore: RootStore) {
|
||||
makeAutoObservable(this, {});
|
||||
|
||||
// root store
|
||||
this.rootStore = _rootStore;
|
||||
// sub-stores
|
||||
this.inbox = new InboxStore(_rootStore);
|
||||
this.inboxFilters = new InboxFiltersStore(_rootStore);
|
||||
this.inboxIssues = new InboxIssuesStore(_rootStore);
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@ import { IStateStore, StateStore } from "./state.store";
|
||||
import { IPageStore, PageStore } from "./page.store";
|
||||
import { ILabelRootStore, LabelRootStore } from "./label";
|
||||
import { IMemberRootStore, MemberRootStore } from "./member";
|
||||
import { IInboxRootStore, InboxRootStore } from "./inbox";
|
||||
|
||||
enableStaticRendering(typeof window === "undefined");
|
||||
|
||||
@ -22,6 +23,7 @@ export class RootStore {
|
||||
projectRoot: IProjectRootStore;
|
||||
labelRoot: ILabelRootStore;
|
||||
memberRoot: IMemberRootStore;
|
||||
inboxRoot: IInboxRootStore;
|
||||
cycle: ICycleStore;
|
||||
module: IModuleStore;
|
||||
projectView: IProjectViewStore;
|
||||
@ -36,6 +38,7 @@ export class RootStore {
|
||||
this.projectRoot = new ProjectRootStore(this);
|
||||
this.labelRoot = new LabelRootStore(this);
|
||||
this.memberRoot = new MemberRootStore(this);
|
||||
this.inboxRoot = new InboxRootStore(this);
|
||||
// independent stores
|
||||
this.state = new StateStore(this);
|
||||
this.issue = new IssueRootStore(this);
|
||||
|
@ -7,6 +7,7 @@ import { WorkspaceService } from "services/workspace.service";
|
||||
// interfaces
|
||||
import { IWorkspaceMemberMe, IProjectMember, IUserProjectsRole } from "types";
|
||||
import { RootStore } from "../root.store";
|
||||
// constants
|
||||
import { EUserProjectRoles } from "constants/project";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
|
||||
@ -128,15 +129,8 @@ export class UserMembershipStore implements IUserMembershipStore {
|
||||
try {
|
||||
const response = await this.workspaceService.workspaceMemberMe(workspaceSlug);
|
||||
|
||||
console.log("response", response);
|
||||
|
||||
let memberInfo = this.workspaceMemberInfo;
|
||||
if (!memberInfo) memberInfo = {};
|
||||
memberInfo[workspaceSlug] = { ...response };
|
||||
|
||||
runInAction(() => {
|
||||
this.workspaceMemberInfo = memberInfo;
|
||||
// set(this.workspaceMemberInfo, [workspaceSlug], response);
|
||||
set(this.workspaceMemberInfo, [workspaceSlug], response);
|
||||
set(this.hasPermissionToWorkspace, [workspaceSlug], true);
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user