2024-01-30 11:15:14 +00:00
|
|
|
import { action, computed, makeObservable, observable, runInAction } from "mobx";
|
2024-02-08 18:11:30 +00:00
|
|
|
import { computedFn } from "mobx-utils";
|
2024-02-02 08:22:38 +00:00
|
|
|
import set from "lodash/set";
|
2024-02-07 06:00:06 +00:00
|
|
|
import sortBy from "lodash/sortBy";
|
|
|
|
import reverse from "lodash/reverse";
|
2024-01-30 08:56:59 +00:00
|
|
|
// stores
|
|
|
|
import { RootStore } from "store/root.store";
|
2024-02-02 08:22:38 +00:00
|
|
|
import { ViewStore } from "./view.store";
|
2024-01-30 08:56:59 +00:00
|
|
|
// types
|
2024-02-08 18:11:30 +00:00
|
|
|
import { TUserViewService, TViewService } from "services/view/types";
|
2024-02-14 14:36:59 +00:00
|
|
|
import { TView, TViewTypes } from "@plane/types";
|
2024-02-13 13:11:34 +00:00
|
|
|
// constants
|
|
|
|
import { EViewPageType } from "constants/view";
|
2024-01-30 08:56:59 +00:00
|
|
|
|
2024-02-05 14:39:17 +00:00
|
|
|
export type TLoader = "init-loader" | "mutation-loader" | "submitting" | undefined;
|
2024-01-30 08:56:59 +00:00
|
|
|
|
2024-02-02 08:22:38 +00:00
|
|
|
type TViewRootStore = {
|
2024-01-30 08:56:59 +00:00
|
|
|
// observables
|
2024-02-05 14:39:17 +00:00
|
|
|
loader: TLoader;
|
2024-02-14 14:36:59 +00:00
|
|
|
viewMap: Record<string, Record<string, Record<string, ViewStore>>>; // workspaceSlug/projectId, public/private, viewId -> ViewStore
|
2024-01-30 08:56:59 +00:00
|
|
|
// computed
|
|
|
|
viewIds: string[];
|
2024-02-02 08:22:38 +00:00
|
|
|
viewById: (viewId: string) => ViewStore | undefined;
|
2024-01-30 08:56:59 +00:00
|
|
|
// actions
|
2024-02-14 14:36:59 +00:00
|
|
|
localViewCreate: (workspaceSlug: string, projectId: string | undefined, view: TView) => Promise<void>;
|
|
|
|
fetch: (workspaceSlug: string, projectId: string | undefined, _loader?: TLoader) => Promise<void>;
|
|
|
|
fetchById: (workspaceSlug: string, projectId: string | undefined, viewId: string) => Promise<void>;
|
|
|
|
create: (workspaceSlug: string, projectId: string | undefined, view: Partial<TView>) => Promise<void>;
|
|
|
|
remove: (workspaceSlug: string, projectId: string | undefined, viewId: string) => Promise<void>;
|
|
|
|
duplicate: (workspaceSlug: string, projectId: string | undefined, viewId: string) => Promise<void>;
|
2024-01-30 08:56:59 +00:00
|
|
|
};
|
|
|
|
|
2024-02-02 08:22:38 +00:00
|
|
|
export class ViewRootStore implements TViewRootStore {
|
2024-02-05 14:39:17 +00:00
|
|
|
// observables
|
|
|
|
loader: TLoader = "init-loader";
|
2024-02-14 14:36:59 +00:00
|
|
|
viewMap: Record<string, Record<string, Record<string, ViewStore>>> = {};
|
2024-01-30 08:56:59 +00:00
|
|
|
|
2024-02-08 18:11:30 +00:00
|
|
|
constructor(
|
|
|
|
private store: RootStore,
|
|
|
|
private defaultViews: TView[] = [],
|
|
|
|
private service: TViewService,
|
2024-02-13 13:11:34 +00:00
|
|
|
private userService: TUserViewService,
|
2024-02-14 14:36:59 +00:00
|
|
|
private viewPageType: EViewPageType,
|
|
|
|
private viewType: TViewTypes
|
2024-02-08 18:11:30 +00:00
|
|
|
) {
|
2024-01-30 08:56:59 +00:00
|
|
|
makeObservable(this, {
|
|
|
|
// observables
|
2024-02-05 14:39:17 +00:00
|
|
|
loader: observable.ref,
|
|
|
|
viewMap: observable,
|
2024-01-30 08:56:59 +00:00
|
|
|
// computed
|
|
|
|
viewIds: computed,
|
|
|
|
// actions
|
2024-02-05 14:39:17 +00:00
|
|
|
localViewCreate: action,
|
2024-02-07 06:00:06 +00:00
|
|
|
fetch: action,
|
2024-02-08 18:11:30 +00:00
|
|
|
fetchById: action,
|
2024-01-30 08:56:59 +00:00
|
|
|
create: action,
|
2024-01-31 06:07:02 +00:00
|
|
|
remove: action,
|
2024-01-30 08:56:59 +00:00
|
|
|
duplicate: action,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// computed
|
|
|
|
get viewIds() {
|
2024-02-14 14:36:59 +00:00
|
|
|
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])
|
|
|
|
: [];
|
|
|
|
|
2024-02-07 06:00:06 +00:00
|
|
|
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"));
|
|
|
|
const _viewIds = [...localViews.map((view) => view.id), ...apiViews.map((view) => view.id)];
|
|
|
|
return _viewIds as string[];
|
2024-01-30 08:56:59 +00:00
|
|
|
}
|
|
|
|
|
2024-02-14 14:36:59 +00:00
|
|
|
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;
|
|
|
|
});
|
2024-01-30 08:56:59 +00:00
|
|
|
|
|
|
|
// actions
|
2024-02-14 14:36:59 +00:00
|
|
|
localViewCreate = async (workspaceSlug: string, projectId: string | undefined, view: TView) => {
|
|
|
|
const viewRootSlug = projectId ? projectId : workspaceSlug;
|
|
|
|
|
2024-02-07 06:00:06 +00:00
|
|
|
runInAction(() => {
|
2024-02-13 13:11:34 +00:00
|
|
|
if (view.id)
|
|
|
|
set(
|
|
|
|
this.viewMap,
|
2024-02-14 14:36:59 +00:00
|
|
|
[viewRootSlug, this.viewType, view.id],
|
2024-02-13 13:11:34 +00:00
|
|
|
new ViewStore(this.store, view, this.service, this.userService, this.viewPageType)
|
|
|
|
);
|
2024-02-07 06:00:06 +00:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2024-02-14 14:36:59 +00:00
|
|
|
fetch = async (workspaceSlug: string, projectId: string | undefined, _loader: TLoader = "init-loader") => {
|
2024-02-07 06:00:06 +00:00
|
|
|
try {
|
2024-02-14 14:36:59 +00:00
|
|
|
const viewRootSlug = projectId ? projectId : workspaceSlug;
|
2024-01-30 08:56:59 +00:00
|
|
|
|
2024-02-08 18:11:30 +00:00
|
|
|
this.loader = _loader;
|
|
|
|
|
2024-02-05 14:39:17 +00:00
|
|
|
if (this.defaultViews && this.defaultViews.length > 0)
|
2024-02-07 06:00:06 +00:00
|
|
|
runInAction(() => {
|
|
|
|
this.defaultViews?.forEach((view) => {
|
2024-02-13 13:11:34 +00:00
|
|
|
if (view.id)
|
|
|
|
set(
|
|
|
|
this.viewMap,
|
2024-02-14 14:36:59 +00:00
|
|
|
[viewRootSlug, this.viewType, view.id],
|
2024-02-13 13:11:34 +00:00
|
|
|
new ViewStore(this.store, view, this.service, this.userService, this.viewPageType)
|
|
|
|
);
|
2024-02-07 06:00:06 +00:00
|
|
|
});
|
2024-02-05 14:39:17 +00:00
|
|
|
});
|
|
|
|
|
2024-02-07 06:00:06 +00:00
|
|
|
const views = await this.service.fetch(workspaceSlug, projectId);
|
|
|
|
if (!views) return;
|
2024-01-30 08:56:59 +00:00
|
|
|
|
2024-02-07 06:00:06 +00:00
|
|
|
runInAction(() => {
|
|
|
|
views.forEach((view) => {
|
2024-02-13 13:11:34 +00:00
|
|
|
if (view.id)
|
|
|
|
set(
|
|
|
|
this.viewMap,
|
2024-02-14 14:36:59 +00:00
|
|
|
[viewRootSlug, this.viewType, view.id],
|
2024-02-13 13:11:34 +00:00
|
|
|
new ViewStore(this.store, view, this.service, this.userService, this.viewPageType)
|
|
|
|
);
|
2024-02-07 06:00:06 +00:00
|
|
|
});
|
|
|
|
this.loader = undefined;
|
2024-01-30 08:56:59 +00:00
|
|
|
});
|
2024-02-07 06:00:06 +00:00
|
|
|
} catch {}
|
2024-01-30 08:56:59 +00:00
|
|
|
};
|
|
|
|
|
2024-02-14 14:36:59 +00:00
|
|
|
fetchById = async (workspaceSlug: string, projectId: string | undefined, viewId: string) => {
|
2024-02-08 18:11:30 +00:00
|
|
|
try {
|
2024-02-14 14:36:59 +00:00
|
|
|
const viewRootSlug = projectId ? projectId : workspaceSlug;
|
2024-02-08 18:11:30 +00:00
|
|
|
|
|
|
|
const userView = await this.userService.fetch(workspaceSlug, projectId);
|
|
|
|
if (!userView) return;
|
|
|
|
|
2024-02-14 13:44:18 +00:00
|
|
|
let view: TView | undefined = undefined;
|
2024-02-13 13:11:34 +00:00
|
|
|
|
2024-02-08 18:11:30 +00:00
|
|
|
if (["all-issues", "assigned", "created", "subscribed"].includes(viewId)) {
|
2024-02-14 14:36:59 +00:00
|
|
|
const currentView = { ...this.viewById(viewId) } as TView;
|
2024-02-14 13:44:18 +00:00
|
|
|
if (!currentView) return;
|
2024-02-08 18:11:30 +00:00
|
|
|
|
2024-02-14 13:44:18 +00:00
|
|
|
view = currentView;
|
|
|
|
view.filters = userView.filters;
|
|
|
|
view.display_filters = userView.display_filters;
|
|
|
|
view.display_properties = userView.display_properties;
|
2024-02-08 18:11:30 +00:00
|
|
|
} else {
|
2024-02-14 13:44:18 +00:00
|
|
|
const currentView = await this.service.fetchById(workspaceSlug, viewId, projectId);
|
|
|
|
if (!currentView) return;
|
2024-02-08 18:11:30 +00:00
|
|
|
|
2024-02-14 13:44:18 +00:00
|
|
|
view = currentView;
|
2024-02-08 18:11:30 +00:00
|
|
|
view?.display_filters && (view.display_filters = userView.display_filters);
|
|
|
|
view?.display_properties && (view.display_properties = userView.display_properties);
|
|
|
|
}
|
2024-02-14 13:44:18 +00:00
|
|
|
|
|
|
|
if (!view) return;
|
|
|
|
runInAction(() => {
|
|
|
|
if (view?.id)
|
|
|
|
set(
|
|
|
|
this.viewMap,
|
2024-02-14 14:36:59 +00:00
|
|
|
[viewRootSlug, this.viewType, view.id],
|
2024-02-14 13:44:18 +00:00
|
|
|
new ViewStore(this.store, view, this.service, this.userService, this.viewPageType)
|
|
|
|
);
|
|
|
|
});
|
2024-02-08 18:11:30 +00:00
|
|
|
} catch {}
|
|
|
|
};
|
|
|
|
|
2024-02-14 14:36:59 +00:00
|
|
|
create = async (workspaceSlug: string, projectId: string | undefined, data: Partial<TView>) => {
|
2024-02-07 06:00:06 +00:00
|
|
|
try {
|
2024-02-14 14:36:59 +00:00
|
|
|
const viewRootSlug = projectId ? projectId : workspaceSlug;
|
2024-01-30 08:56:59 +00:00
|
|
|
|
2024-02-07 06:00:06 +00:00
|
|
|
const view = await this.service.create(workspaceSlug, data, projectId);
|
|
|
|
if (!view) return;
|
2024-01-30 08:56:59 +00:00
|
|
|
|
2024-02-07 06:00:06 +00:00
|
|
|
runInAction(() => {
|
2024-02-13 13:11:34 +00:00
|
|
|
if (view.id)
|
|
|
|
set(
|
|
|
|
this.viewMap,
|
2024-02-14 14:36:59 +00:00
|
|
|
[viewRootSlug, this.viewType, view.id],
|
2024-02-13 13:11:34 +00:00
|
|
|
new ViewStore(this.store, view, this.service, this.userService, this.viewPageType)
|
|
|
|
);
|
2024-02-07 06:00:06 +00:00
|
|
|
});
|
|
|
|
|
2024-02-14 14:36:59 +00:00
|
|
|
if (data.id) this.remove(workspaceSlug, projectId, data.id);
|
2024-02-07 06:00:06 +00:00
|
|
|
} catch {}
|
2024-01-30 08:56:59 +00:00
|
|
|
};
|
|
|
|
|
2024-02-14 14:36:59 +00:00
|
|
|
remove = async (workspaceSlug: string, projectId: string | undefined, viewId: string) => {
|
2024-02-07 06:00:06 +00:00
|
|
|
try {
|
2024-02-14 14:36:59 +00:00
|
|
|
const viewRootSlug = projectId ? projectId : workspaceSlug;
|
2024-01-30 08:56:59 +00:00
|
|
|
|
2024-02-14 14:36:59 +00:00
|
|
|
if (
|
|
|
|
this.viewMap?.[viewRootSlug]?.[this.viewType]?.[viewId] != undefined &&
|
|
|
|
!this.viewMap?.[viewRootSlug]?.[this.viewType]?.[viewId]?.is_create
|
|
|
|
)
|
2024-02-07 06:00:06 +00:00
|
|
|
await this.service.remove?.(workspaceSlug, viewId, projectId);
|
2024-01-30 08:56:59 +00:00
|
|
|
|
2024-02-07 06:00:06 +00:00
|
|
|
runInAction(() => {
|
2024-02-14 14:36:59 +00:00
|
|
|
delete this.viewMap?.[viewRootSlug]?.[this.viewType]?.[viewId];
|
2024-02-07 06:00:06 +00:00
|
|
|
});
|
|
|
|
} catch {}
|
2024-01-30 08:56:59 +00:00
|
|
|
};
|
|
|
|
|
2024-02-14 14:36:59 +00:00
|
|
|
duplicate = async (workspaceSlug: string, projectId: string | undefined, viewId: string) => {
|
2024-02-07 06:00:06 +00:00
|
|
|
try {
|
2024-02-14 14:36:59 +00:00
|
|
|
if (!this.service.duplicate) return;
|
|
|
|
|
|
|
|
const viewRootSlug = projectId ? projectId : workspaceSlug;
|
2024-01-30 08:56:59 +00:00
|
|
|
|
2024-02-07 06:00:06 +00:00
|
|
|
const view = await this.service.duplicate(workspaceSlug, viewId, projectId);
|
|
|
|
if (!view) return;
|
2024-01-30 08:56:59 +00:00
|
|
|
|
2024-02-07 06:00:06 +00:00
|
|
|
runInAction(() => {
|
2024-02-13 13:11:34 +00:00
|
|
|
if (view.id)
|
|
|
|
set(
|
|
|
|
this.viewMap,
|
2024-02-14 14:36:59 +00:00
|
|
|
[viewRootSlug, this.viewType, view.id],
|
2024-02-13 13:11:34 +00:00
|
|
|
new ViewStore(this.store, view, this.service, this.userService, this.viewPageType)
|
|
|
|
);
|
2024-02-07 06:00:06 +00:00
|
|
|
});
|
|
|
|
} catch {}
|
2024-01-30 08:56:59 +00:00
|
|
|
};
|
|
|
|
}
|