forked from github/plane
[WEB-994] fix: pages list mutation between projects (#4179)
* fix: pages list mutation between projects * fix: page tab logic * chore: remove pageType from the project pages store * chore: rename computed helper functions
This commit is contained in:
parent
d58bc03db6
commit
7507cb0a0f
@ -1,19 +1,24 @@
|
||||
import { FC } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
// types
|
||||
import { TPageNavigationTabs } from "@plane/types";
|
||||
// hooks
|
||||
import { useProjectPages } from "@/hooks/store";
|
||||
// components
|
||||
import { PageListBlock } from "./";
|
||||
|
||||
type TPagesListRoot = {
|
||||
workspaceSlug: string;
|
||||
pageType: TPageNavigationTabs;
|
||||
projectId: string;
|
||||
workspaceSlug: string;
|
||||
};
|
||||
|
||||
export const PagesListRoot: FC<TPagesListRoot> = observer((props) => {
|
||||
const { workspaceSlug, projectId } = props;
|
||||
// hooks
|
||||
const { filteredPageIds } = useProjectPages(projectId);
|
||||
const { pageType, projectId, workspaceSlug } = props;
|
||||
// store hooks
|
||||
const { getCurrentProjectFilteredPageIds } = useProjectPages(projectId);
|
||||
// derived values
|
||||
const filteredPageIds = getCurrentProjectFilteredPageIds(pageType);
|
||||
|
||||
if (!filteredPageIds) return <></>;
|
||||
return (
|
||||
|
@ -42,21 +42,18 @@ export const PageTabNavigation: FC<TPageTabNavigation> = (props) => {
|
||||
href={`/${workspaceSlug}/projects/${projectId}/pages?type=${tab.key}`}
|
||||
onClick={(e) => handleTabClick(e, tab.key)}
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
className={cn(`p-3 py-4 text-sm font-medium transition-all`, {
|
||||
"text-custom-primary-100": tab.key === pageType,
|
||||
})}
|
||||
>
|
||||
{tab.label}
|
||||
</div>
|
||||
<div
|
||||
className={cn(`rounded-t border-t-2 transition-all`, {
|
||||
"border-custom-primary-100": tab.key === pageType,
|
||||
"border-transparent": tab.key !== pageType,
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
className={cn(`block p-3 py-4 text-sm font-medium transition-all`, {
|
||||
"text-custom-primary-100": tab.key === pageType,
|
||||
})}
|
||||
>
|
||||
{tab.label}
|
||||
</span>
|
||||
<div
|
||||
className={cn(`rounded-t border-t-2 transition-all border-transparent`, {
|
||||
"border-custom-primary-100": tab.key === pageType,
|
||||
})}
|
||||
/>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
|
@ -22,7 +22,10 @@ type Props = {
|
||||
export const PagesListMainContent: React.FC<Props> = observer((props) => {
|
||||
const { children, pageType, projectId } = props;
|
||||
// store hooks
|
||||
const { loader, filteredPageIds, pageIds, filters } = useProjectPages(projectId);
|
||||
const { loader, getCurrentProjectFilteredPageIds, getCurrentProjectPageIds, filters } = useProjectPages(projectId);
|
||||
// derived values
|
||||
const pageIds = getCurrentProjectPageIds(pageType);
|
||||
const filteredPageIds = getCurrentProjectFilteredPageIds(pageType);
|
||||
|
||||
if (loader === "init-loader") return <PageLoader />;
|
||||
// if no pages exist in the active page type
|
||||
|
@ -18,10 +18,7 @@ export const PagesListView: React.FC<TPageView> = observer((props) => {
|
||||
// store hooks
|
||||
const { getAllPages } = useProjectPages(projectId);
|
||||
// fetching pages list
|
||||
useSWR(
|
||||
projectId && pageType ? `PROJECT_PAGES_${projectId}_${pageType}` : null,
|
||||
projectId && pageType ? () => getAllPages(pageType) : null
|
||||
);
|
||||
useSWR(projectId ? `PROJECT_PAGES_${projectId}` : null, projectId ? () => getAllPages(pageType) : null);
|
||||
|
||||
// pages loader
|
||||
return (
|
||||
|
@ -36,7 +36,11 @@ const ProjectPagesPage: NextPageWithLayout = observer(() => {
|
||||
projectId={projectId.toString()}
|
||||
pageType={currentPageType()}
|
||||
>
|
||||
<PagesListRoot workspaceSlug={workspaceSlug.toString()} projectId={projectId.toString()} />
|
||||
<PagesListRoot
|
||||
pageType={currentPageType()}
|
||||
workspaceSlug={workspaceSlug.toString()}
|
||||
projectId={projectId.toString()}
|
||||
/>
|
||||
</PagesListView>
|
||||
);
|
||||
});
|
||||
|
@ -1,12 +1,14 @@
|
||||
import set from "lodash/set";
|
||||
import unset from "lodash/unset";
|
||||
import { makeObservable, observable, runInAction, action, computed } from "mobx";
|
||||
import { makeObservable, observable, runInAction, action } from "mobx";
|
||||
import { computedFn } from "mobx-utils";
|
||||
// types
|
||||
import { TPage, TPageFilters, TPageNavigationTabs } from "@plane/types";
|
||||
// helpers
|
||||
import { filterPagesByPageType, orderPages, shouldFilterPage } from "@/helpers/page.helper";
|
||||
// services
|
||||
import { PageService } from "@/services/page.service";
|
||||
// store
|
||||
import { IPageStore, PageStore } from "@/store/pages/page.store";
|
||||
import { RootStore } from "../root.store";
|
||||
|
||||
@ -17,14 +19,12 @@ type TError = { title: string; description: string };
|
||||
export interface IProjectPageStore {
|
||||
// observables
|
||||
loader: TLoader;
|
||||
pageType: TPageNavigationTabs;
|
||||
data: Record<string, IPageStore>; // pageId => PageStore
|
||||
error: TError | undefined;
|
||||
filters: TPageFilters;
|
||||
// computed
|
||||
pageIds: string[] | undefined;
|
||||
filteredPageIds: string[] | undefined;
|
||||
// helper actions
|
||||
getCurrentProjectPageIds: (pageType: TPageNavigationTabs) => string[] | undefined;
|
||||
getCurrentProjectFilteredPageIds: (pageType: TPageNavigationTabs) => string[] | undefined;
|
||||
pageById: (pageId: string) => IPageStore | undefined;
|
||||
updateFilters: <T extends keyof TPageFilters>(filterKey: T, filterValue: TPageFilters[T]) => void;
|
||||
clearAllFilters: () => void;
|
||||
@ -38,7 +38,6 @@ export interface IProjectPageStore {
|
||||
export class ProjectPageStore implements IProjectPageStore {
|
||||
// observables
|
||||
loader: TLoader = "init-loader";
|
||||
pageType: TPageNavigationTabs = "public";
|
||||
data: Record<string, IPageStore> = {}; // pageId => PageStore
|
||||
error: TError | undefined = undefined;
|
||||
filters: TPageFilters = {
|
||||
@ -53,13 +52,9 @@ export class ProjectPageStore implements IProjectPageStore {
|
||||
makeObservable(this, {
|
||||
// observables
|
||||
loader: observable.ref,
|
||||
pageType: observable.ref,
|
||||
data: observable,
|
||||
error: observable,
|
||||
filters: observable,
|
||||
// computed
|
||||
pageIds: computed,
|
||||
filteredPageIds: computed,
|
||||
// helper actions
|
||||
updateFilters: action,
|
||||
clearAllFilters: action,
|
||||
@ -73,26 +68,35 @@ export class ProjectPageStore implements IProjectPageStore {
|
||||
this.service = new PageService();
|
||||
}
|
||||
|
||||
get pageIds() {
|
||||
/**
|
||||
* @description get the current project page ids based on the pageType
|
||||
* @param {TPageNavigationTabs} pageType
|
||||
*/
|
||||
getCurrentProjectPageIds = computedFn((pageType: TPageNavigationTabs) => {
|
||||
const { projectId } = this.store.app.router;
|
||||
if (!projectId) return undefined;
|
||||
|
||||
// helps to filter pages based on the pageType
|
||||
const pagesByType = filterPagesByPageType(this.pageType, Object.values(this?.data || {}));
|
||||
let pagesByType = filterPagesByPageType(pageType, Object.values(this?.data || {}));
|
||||
pagesByType = pagesByType.filter((p) => p.project === projectId);
|
||||
|
||||
const pages = (pagesByType.map((page) => page.id) as string[]) || undefined;
|
||||
|
||||
return pages ?? undefined;
|
||||
}
|
||||
});
|
||||
|
||||
get filteredPageIds() {
|
||||
/**
|
||||
* @description get the current project filtered page ids based on the pageType
|
||||
* @param {TPageNavigationTabs} pageType
|
||||
*/
|
||||
getCurrentProjectFilteredPageIds = computedFn((pageType: TPageNavigationTabs) => {
|
||||
const { projectId } = this.store.app.router;
|
||||
if (!projectId) return undefined;
|
||||
|
||||
// helps to filter pages based on the pageType
|
||||
const pagesByType = filterPagesByPageType(this.pageType, Object.values(this?.data || {}));
|
||||
const pagesByType = filterPagesByPageType(pageType, Object.values(this?.data || {}));
|
||||
let filteredPages = pagesByType.filter(
|
||||
(p) =>
|
||||
p.project === projectId &&
|
||||
p.name?.toLowerCase().includes(this.filters.searchQuery.toLowerCase()) &&
|
||||
shouldFilterPage(p, this.filters.filters)
|
||||
);
|
||||
@ -101,15 +105,14 @@ export class ProjectPageStore implements IProjectPageStore {
|
||||
const pages = (filteredPages.map((page) => page.id) as string[]) || undefined;
|
||||
|
||||
return pages ?? undefined;
|
||||
}
|
||||
|
||||
pageById = computedFn((pageId: string) => {
|
||||
const { projectId } = this.store.app.router;
|
||||
if (!projectId) return undefined;
|
||||
|
||||
return this.data?.[pageId] || undefined;
|
||||
});
|
||||
|
||||
/**
|
||||
* @description get the page store by id
|
||||
* @param {string} pageId
|
||||
*/
|
||||
pageById = computedFn((pageId: string) => this.data?.[pageId] || undefined);
|
||||
|
||||
updateFilters = <T extends keyof TPageFilters>(filterKey: T, filterValue: TPageFilters[T]) => {
|
||||
runInAction(() => {
|
||||
set(this.filters, [filterKey], filterValue);
|
||||
@ -125,17 +128,15 @@ export class ProjectPageStore implements IProjectPageStore {
|
||||
});
|
||||
|
||||
/**
|
||||
* @description fetch all the pages based on the navigation tab
|
||||
* @param {TPageNavigationTabs} pageType
|
||||
* @description fetch all the pages
|
||||
*/
|
||||
getAllPages = async (pageType: TPageNavigationTabs) => {
|
||||
try {
|
||||
const { workspaceSlug, projectId } = this.store.app.router;
|
||||
if (!workspaceSlug || !projectId) return undefined;
|
||||
|
||||
const currentPageIds = this.pageIds;
|
||||
const currentPageIds = this.getCurrentProjectPageIds(pageType);
|
||||
runInAction(() => {
|
||||
this.pageType = pageType;
|
||||
this.loader = currentPageIds && currentPageIds.length > 0 ? `mutation-loader` : `init-loader`;
|
||||
this.error = undefined;
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user