diff --git a/web/components/view/root.tsx b/web/components/view/root.tsx index ab61e7c5c..42e6904a2 100644 --- a/web/components/view/root.tsx +++ b/web/components/view/root.tsx @@ -71,12 +71,12 @@ export const GlobalViewRoot: FC = observer((props) => { // creating new view const currentViewPayload = cloneDeep({ ...currentView, id: uuidV4() }); handleViewOperationsToggle("CREATE", currentViewPayload.id); - viewStore?.localViewCreate(currentViewPayload as TView); + viewStore?.localViewCreate(workspaceSlug, projectId, currentViewPayload as TView); } else { // if current view is available, create a new view with the same data const viewPayload = viewLocalPayload; handleViewOperationsToggle("CREATE", viewPayload.id); - viewStore?.localViewCreate(viewPayload as TView); + viewStore?.localViewCreate(workspaceSlug, projectId, viewPayload as TView); } } else { handleViewOperationsToggle("EDIT", viewId); @@ -84,14 +84,14 @@ export const GlobalViewRoot: FC = observer((props) => { } }, localViewCreateEditClear: async (viewId: string | undefined) => { - if (viewDetailCreateEditStore?.is_create && viewId) viewStore?.remove(viewId); + if (viewDetailCreateEditStore?.is_create && viewId) viewStore?.remove(workspaceSlug, projectId, viewId); if (viewDetailCreateEditStore?.is_editable && viewId) viewDetailCreateEditStore.resetChanges(); handleViewOperationsToggle(undefined, undefined); }, fetch: async () => { try { - await viewStore?.fetch(); + await viewStore?.fetch(workspaceSlug, projectId); } catch { setToastAlert({ type: "error", @@ -102,7 +102,7 @@ export const GlobalViewRoot: FC = observer((props) => { }, create: async (data: Partial) => { try { - await viewStore?.create(data); + await viewStore?.create(workspaceSlug, projectId, data); handleViewOperationsToggle(undefined, undefined); setToastAlert({ type: "success", @@ -119,7 +119,7 @@ export const GlobalViewRoot: FC = observer((props) => { }, remove: async (viewId: string) => { try { - await viewStore?.remove(viewId); + await viewStore?.remove(workspaceSlug, projectId, viewId); handleViewOperationsToggle(undefined, undefined); setToastAlert({ type: "success", @@ -152,13 +152,25 @@ export const GlobalViewRoot: FC = observer((props) => { } }, }), - [viewStore, viewDetailStore, setToastAlert, viewDetailCreateEditStore, handleViewOperationsToggle] + [ + workspaceSlug, + projectId, + viewStore, + viewDetailStore, + setToastAlert, + viewDetailCreateEditStore, + handleViewOperationsToggle, + ] ); // fetch all views useEffect(() => { const fetchViews = async () => { - await viewStore?.fetch(viewStore?.viewIds.length > 0 ? "mutation-loader" : "init-loader"); + await viewStore?.fetch( + workspaceSlug, + projectId, + viewStore?.viewIds.length > 0 ? "mutation-loader" : "init-loader" + ); }; if (workspaceSlug && viewType && viewStore) fetchViews(); }, [workspaceSlug, projectId, viewType, viewStore]); @@ -166,7 +178,7 @@ export const GlobalViewRoot: FC = observer((props) => { // fetch view by id useEffect(() => { const fetchViews = async () => { - viewId && (await viewStore?.fetchById(viewId)); + viewId && (await viewStore?.fetchById(workspaceSlug, projectId, viewId)); }; if (workspaceSlug && viewId && viewType && viewStore) fetchViews(); }, [workspaceSlug, projectId, viewId, viewType, viewStore]); diff --git a/web/store/view/root.store.ts b/web/store/view/root.store.ts index 66dd2e2dd..b9bbadb87 100644 --- a/web/store/view/root.store.ts +++ b/web/store/view/root.store.ts @@ -12,7 +12,7 @@ import { // types import { RootStore } from "store/root.store"; // constants -import { EViewPageType } from "constants/view"; +import { EViewPageType, VIEW_TYPES } from "constants/view"; export class GlobalViewRootStore { workspacePrivateViewStore: ViewRootStore; @@ -25,25 +25,16 @@ export class GlobalViewRootStore { { id: "assigned", name: "Assigned", - filters: { - assignees: store?.user?.currentUser?.id ? [store?.user?.currentUser?.id] : [], - }, is_local_view: true, }, { id: "created", name: "Created", - filters: { - created_by: store?.user?.currentUser?.id ? [store?.user?.currentUser?.id] : [], - }, is_local_view: true, }, { id: "subscribed", name: "Subscribed", - filters: { - subscriber: store?.user?.currentUser?.id ? [store?.user?.currentUser?.id] : [], - }, is_local_view: true, }, ]; @@ -52,7 +43,6 @@ export class GlobalViewRootStore { { id: "all-issues", name: "All Issues", - filters: {}, is_local_view: true, }, ]; @@ -62,28 +52,32 @@ export class GlobalViewRootStore { workspacePrivateDefaultViews, new WorkspacePrivateViewService(), new WorkspaceFiltersService(), - EViewPageType.ALL + EViewPageType.ALL, + VIEW_TYPES.WORKSPACE_PRIVATE_VIEWS ); this.workspacePublicViewStore = new ViewRootStore( this.store, workspacePublicDefaultViews, new WorkspacePublicViewService(), new WorkspaceFiltersService(), - EViewPageType.ALL + EViewPageType.ALL, + VIEW_TYPES.WORKSPACE_PUBLIC_VIEWS ); this.projectPrivateViewStore = new ViewRootStore( this.store, undefined, new ProjectPrivateViewService(), new ProjectFiltersService(), - EViewPageType.PROJECT + EViewPageType.PROJECT, + VIEW_TYPES.PROJECT_PRIVATE_VIEWS ); this.projectPublicViewStore = new ViewRootStore( this.store, undefined, new ProjectPublicViewService(), new ProjectFiltersService(), - EViewPageType.PROJECT + EViewPageType.PROJECT, + VIEW_TYPES.PROJECT_PUBLIC_VIEWS ); } } diff --git a/web/store/view/view-root.store.ts b/web/store/view/view-root.store.ts index 25f4d52e7..58b4370af 100644 --- a/web/store/view/view-root.store.ts +++ b/web/store/view/view-root.store.ts @@ -8,7 +8,7 @@ import { RootStore } from "store/root.store"; import { ViewStore } from "./view.store"; // types import { TUserViewService, TViewService } from "services/view/types"; -import { TView } from "@plane/types"; +import { TView, TViewTypes } from "@plane/types"; // constants import { EViewPageType } from "constants/view"; @@ -17,30 +17,31 @@ export type TLoader = "init-loader" | "mutation-loader" | "submitting" | undefin type TViewRootStore = { // observables loader: TLoader; - viewMap: Record; + viewMap: Record>>; // workspaceSlug/projectId, public/private, viewId -> ViewStore // computed viewIds: string[]; viewById: (viewId: string) => ViewStore | undefined; // actions - localViewCreate: (view: TView) => Promise; - fetch: (_loader?: TLoader) => Promise; - fetchById: (viewId: string) => Promise; - create: (view: Partial) => Promise; - remove: (viewId: string) => Promise; - duplicate: (viewId: string) => Promise; + localViewCreate: (workspaceSlug: string, projectId: string | undefined, view: TView) => Promise; + fetch: (workspaceSlug: string, projectId: string | undefined, _loader?: TLoader) => Promise; + fetchById: (workspaceSlug: string, projectId: string | undefined, viewId: string) => Promise; + create: (workspaceSlug: string, projectId: string | undefined, view: Partial) => Promise; + remove: (workspaceSlug: string, projectId: string | undefined, viewId: string) => Promise; + duplicate: (workspaceSlug: string, projectId: string | undefined, viewId: string) => Promise; }; export class ViewRootStore implements TViewRootStore { // observables loader: TLoader = "init-loader"; - viewMap: Record = {}; + viewMap: Record>> = {}; constructor( private store: RootStore, private defaultViews: TView[] = [], private service: TViewService, private userService: TUserViewService, - private viewPageType: EViewPageType + private viewPageType: EViewPageType, + private viewType: TViewTypes ) { makeObservable(this, { // observables @@ -60,7 +61,14 @@ export class ViewRootStore implements TViewRootStore { // computed get viewIds() { - const views = Object.values(this.viewMap); + const { workspaceSlug, projectId } = this.store.app.router; + if (!workspaceSlug) return []; + + const viewRootSlug = projectId ? projectId : workspaceSlug; + const views = this.viewMap?.[viewRootSlug]?.[this.viewType] + ? Object.values(this.viewMap?.[viewRootSlug]?.[this.viewType]) + : []; + const localViews = views.filter((view) => view.is_local_view); let apiViews = views.filter((view) => !view.is_local_view && !view.is_create); apiViews = reverse(sortBy(apiViews, "sort_order")); @@ -68,24 +76,31 @@ export class ViewRootStore implements TViewRootStore { return _viewIds as string[]; } - viewById = computedFn((viewId: string) => this.viewMap?.[viewId] || undefined); + viewById = computedFn((viewId: string) => { + const { workspaceSlug, projectId } = this.store.app.router; + if (!workspaceSlug) return undefined; + + const viewRootSlug = projectId ? projectId : workspaceSlug; + return this.viewMap?.[viewRootSlug]?.[this.viewType]?.[viewId] || undefined; + }); // actions - localViewCreate = async (view: TView) => { + localViewCreate = async (workspaceSlug: string, projectId: string | undefined, view: TView) => { + const viewRootSlug = projectId ? projectId : workspaceSlug; + runInAction(() => { if (view.id) set( this.viewMap, - [view.id], + [viewRootSlug, this.viewType, view.id], new ViewStore(this.store, view, this.service, this.userService, this.viewPageType) ); }); }; - fetch = async (_loader: TLoader = "init-loader") => { + fetch = async (workspaceSlug: string, projectId: string | undefined, _loader: TLoader = "init-loader") => { try { - const { workspaceSlug, projectId } = this.store.app.router; - if (!workspaceSlug) return; + const viewRootSlug = projectId ? projectId : workspaceSlug; this.loader = _loader; @@ -95,7 +110,7 @@ export class ViewRootStore implements TViewRootStore { if (view.id) set( this.viewMap, - [view.id], + [viewRootSlug, this.viewType, view.id], new ViewStore(this.store, view, this.service, this.userService, this.viewPageType) ); }); @@ -109,7 +124,7 @@ export class ViewRootStore implements TViewRootStore { if (view.id) set( this.viewMap, - [view.id], + [viewRootSlug, this.viewType, view.id], new ViewStore(this.store, view, this.service, this.userService, this.viewPageType) ); }); @@ -118,10 +133,9 @@ export class ViewRootStore implements TViewRootStore { } catch {} }; - fetchById = async (viewId: string) => { + fetchById = async (workspaceSlug: string, projectId: string | undefined, viewId: string) => { try { - const { workspaceSlug, projectId } = this.store.app.router; - if (!workspaceSlug || !viewId) return; + const viewRootSlug = projectId ? projectId : workspaceSlug; const userView = await this.userService.fetch(workspaceSlug, projectId); if (!userView) return; @@ -129,7 +143,7 @@ export class ViewRootStore implements TViewRootStore { let view: TView | undefined = undefined; if (["all-issues", "assigned", "created", "subscribed"].includes(viewId)) { - const currentView = { ...this.viewById(viewId) }; + const currentView = { ...this.viewById(viewId) } as TView; if (!currentView) return; view = currentView; @@ -150,17 +164,16 @@ export class ViewRootStore implements TViewRootStore { if (view?.id) set( this.viewMap, - [view.id], + [viewRootSlug, this.viewType, view.id], new ViewStore(this.store, view, this.service, this.userService, this.viewPageType) ); }); } catch {} }; - create = async (data: Partial) => { + create = async (workspaceSlug: string, projectId: string | undefined, data: Partial) => { try { - const { workspaceSlug, projectId } = this.store.app.router; - if (!workspaceSlug) return; + const viewRootSlug = projectId ? projectId : workspaceSlug; const view = await this.service.create(workspaceSlug, data, projectId); if (!view) return; @@ -169,33 +182,36 @@ export class ViewRootStore implements TViewRootStore { if (view.id) set( this.viewMap, - [view.id], + [viewRootSlug, this.viewType, view.id], new ViewStore(this.store, view, this.service, this.userService, this.viewPageType) ); }); - if (data.id) this.remove(data.id); + if (data.id) this.remove(workspaceSlug, projectId, data.id); } catch {} }; - remove = async (viewId: string) => { + remove = async (workspaceSlug: string, projectId: string | undefined, viewId: string) => { try { - const { workspaceSlug, projectId } = this.store.app.router; - if (!workspaceSlug || !viewId) return; + const viewRootSlug = projectId ? projectId : workspaceSlug; - if (this.viewMap?.[viewId] != undefined && !this.viewMap?.[viewId]?.is_create) + if ( + this.viewMap?.[viewRootSlug]?.[this.viewType]?.[viewId] != undefined && + !this.viewMap?.[viewRootSlug]?.[this.viewType]?.[viewId]?.is_create + ) await this.service.remove?.(workspaceSlug, viewId, projectId); runInAction(() => { - delete this.viewMap[viewId]; + delete this.viewMap?.[viewRootSlug]?.[this.viewType]?.[viewId]; }); } catch {} }; - duplicate = async (viewId: string) => { + duplicate = async (workspaceSlug: string, projectId: string | undefined, viewId: string) => { try { - const { workspaceSlug, projectId } = this.store.app.router; - if (!workspaceSlug || !this.service.duplicate) return; + if (!this.service.duplicate) return; + + const viewRootSlug = projectId ? projectId : workspaceSlug; const view = await this.service.duplicate(workspaceSlug, viewId, projectId); if (!view) return; @@ -204,7 +220,7 @@ export class ViewRootStore implements TViewRootStore { if (view.id) set( this.viewMap, - [view.id], + [viewRootSlug, this.viewType, view.id], new ViewStore(this.store, view, this.service, this.userService, this.viewPageType) ); }); diff --git a/web/store/view/view.store.ts b/web/store/view/view.store.ts index 432e2639d..6ecaf0b40 100644 --- a/web/store/view/view.store.ts +++ b/web/store/view/view.store.ts @@ -326,14 +326,13 @@ export class ViewStore extends FiltersHelper implements TViewStore { // actions update = async (viewData: TUpdateView) => { try { + if (!this.workspace || !this.id) return; + runInAction(() => { this.loader = "updating"; }); - const { workspaceSlug, projectId } = this.store.app.router; - if (!workspaceSlug || !this.id) return; - - const view = await this.service.update(workspaceSlug, this.id, viewData, projectId); + const view = await this.service.update(this.workspace, this.id, viewData, this.project); if (!view) return; runInAction(() => { @@ -350,10 +349,9 @@ export class ViewStore extends FiltersHelper implements TViewStore { lockView = async () => { try { - const { workspaceSlug, projectId } = this.store.app.router; - if (!workspaceSlug || !this.id || !this.service.lock) return; + if (!this.workspace || !this.id || !this.service.lock) return; - const view = await this.service.lock(workspaceSlug, this.id, projectId); + const view = await this.service.lock(this.workspace, this.id, this.project); if (!view) return; runInAction(() => { @@ -366,10 +364,9 @@ export class ViewStore extends FiltersHelper implements TViewStore { unlockView = async () => { try { - const { workspaceSlug, projectId } = this.store.app.router; - if (!workspaceSlug || !this.id || !this.service.unlock) return; + if (!this.workspace || !this.id || !this.service.unlock) return; - const view = await this.service.unlock(workspaceSlug, this.id, projectId); + const view = await this.service.unlock(this.workspace, this.id, this.project); if (!view) return; runInAction(() => { @@ -382,10 +379,9 @@ export class ViewStore extends FiltersHelper implements TViewStore { makeFavorite = async () => { try { - const { workspaceSlug, projectId } = this.store.app.router; - if (!workspaceSlug || !this.id || !this.service.makeFavorite) return; + if (!this.workspace || !this.id || !this.service.makeFavorite) return; - const view = await this.service.makeFavorite(workspaceSlug, this.id, projectId); + const view = await this.service.makeFavorite(this.workspace, this.id, this.project); if (!view) return; runInAction(() => { @@ -398,10 +394,9 @@ export class ViewStore extends FiltersHelper implements TViewStore { removeFavorite = async () => { try { - const { workspaceSlug, projectId } = this.store.app.router; - if (!workspaceSlug || !this.id || !this.service.removeFavorite) return; + if (!this.workspace || !this.id || !this.service.removeFavorite) return; - const view = await this.service.removeFavorite(workspaceSlug, this.id, projectId); + const view = await this.service.removeFavorite(this.workspace, this.id, this.project); if (!view) return; runInAction(() => {