[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:
Aaryan Khandelwal 2024-04-15 12:50:22 +05:30 committed by GitHub
parent d58bc03db6
commit 7507cb0a0f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 59 additions and 52 deletions

View File

@ -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 (

View File

@ -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>

View File

@ -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

View File

@ -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 (

View File

@ -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>
);
});

View File

@ -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;
});