[PE-238] refactor: page store hooks (#6409)
* refactor: page store hooks * fix: page details instances * fix: build errors * refactor: page store hooks * fix: minor bug
This commit is contained in:
parent
dd11ebf335
commit
827f47809b
30 changed files with 216 additions and 103 deletions
|
|
@ -19,7 +19,9 @@ import { IssuePeekOverview } from "@/components/issues";
|
||||||
import { PageRoot, TPageRootConfig, TPageRootHandlers } from "@/components/pages";
|
import { PageRoot, TPageRootConfig, TPageRootHandlers } from "@/components/pages";
|
||||||
// hooks
|
// hooks
|
||||||
import { useEditorConfig } from "@/hooks/editor";
|
import { useEditorConfig } from "@/hooks/editor";
|
||||||
import { useEditorAsset, useProjectPage, useProjectPages, useWorkspace } from "@/hooks/store";
|
import { useEditorAsset, useWorkspace } from "@/hooks/store";
|
||||||
|
// plane web hooks
|
||||||
|
import { EPageStoreType, usePage, usePageStore } from "@/plane-web/hooks/store";
|
||||||
// plane web services
|
// plane web services
|
||||||
import { WorkspaceService } from "@/plane-web/services";
|
import { WorkspaceService } from "@/plane-web/services";
|
||||||
// services
|
// services
|
||||||
|
|
@ -31,13 +33,16 @@ const projectPageVersionService = new ProjectPageVersionService();
|
||||||
const PageDetailsPage = observer(() => {
|
const PageDetailsPage = observer(() => {
|
||||||
const { workspaceSlug, projectId, pageId } = useParams();
|
const { workspaceSlug, projectId, pageId } = useParams();
|
||||||
// store hooks
|
// store hooks
|
||||||
const { createPage, getPageById } = useProjectPages();
|
const { createPage, fetchPageDetails } = usePageStore(EPageStoreType.PROJECT);
|
||||||
const page = useProjectPage(pageId?.toString() ?? "");
|
const page = usePage({
|
||||||
|
pageId: pageId?.toString() ?? "",
|
||||||
|
storeType: EPageStoreType.PROJECT,
|
||||||
|
});
|
||||||
const { getWorkspaceBySlug } = useWorkspace();
|
const { getWorkspaceBySlug } = useWorkspace();
|
||||||
const { uploadEditorAsset } = useEditorAsset();
|
const { uploadEditorAsset } = useEditorAsset();
|
||||||
// derived values
|
// derived values
|
||||||
const workspaceId = workspaceSlug ? (getWorkspaceBySlug(workspaceSlug.toString())?.id ?? "") : "";
|
const workspaceId = workspaceSlug ? (getWorkspaceBySlug(workspaceSlug.toString())?.id ?? "") : "";
|
||||||
const { canCurrentUserAccessPage, id, name, updateDescription } = page;
|
const { canCurrentUserAccessPage, id, name, updateDescription } = page ?? {};
|
||||||
// entity search handler
|
// entity search handler
|
||||||
const fetchEntityCallback = useCallback(
|
const fetchEntityCallback = useCallback(
|
||||||
async (payload: TSearchEntityRequestPayload) =>
|
async (payload: TSearchEntityRequestPayload) =>
|
||||||
|
|
@ -53,7 +58,7 @@ const PageDetailsPage = observer(() => {
|
||||||
const { error: pageDetailsError } = useSWR(
|
const { error: pageDetailsError } = useSWR(
|
||||||
workspaceSlug && projectId && pageId ? `PAGE_DETAILS_${pageId}` : null,
|
workspaceSlug && projectId && pageId ? `PAGE_DETAILS_${pageId}` : null,
|
||||||
workspaceSlug && projectId && pageId
|
workspaceSlug && projectId && pageId
|
||||||
? () => getPageById(workspaceSlug?.toString(), projectId?.toString(), pageId.toString())
|
? () => fetchPageDetails(workspaceSlug?.toString(), projectId?.toString(), pageId.toString())
|
||||||
: null,
|
: null,
|
||||||
{
|
{
|
||||||
revalidateIfStale: true,
|
revalidateIfStale: true,
|
||||||
|
|
@ -70,8 +75,8 @@ const PageDetailsPage = observer(() => {
|
||||||
return await projectPageVersionService.fetchAllVersions(workspaceSlug.toString(), projectId.toString(), pageId);
|
return await projectPageVersionService.fetchAllVersions(workspaceSlug.toString(), projectId.toString(), pageId);
|
||||||
},
|
},
|
||||||
fetchDescriptionBinary: async () => {
|
fetchDescriptionBinary: async () => {
|
||||||
if (!workspaceSlug || !projectId || !page.id) return;
|
if (!workspaceSlug || !projectId || !id) return;
|
||||||
return await projectPageService.fetchDescriptionBinary(workspaceSlug.toString(), projectId.toString(), page.id);
|
return await projectPageService.fetchDescriptionBinary(workspaceSlug.toString(), projectId.toString(), id);
|
||||||
},
|
},
|
||||||
fetchEntity: fetchEntityCallback,
|
fetchEntity: fetchEntityCallback,
|
||||||
fetchVersionDetails: async (pageId, versionId) => {
|
fetchVersionDetails: async (pageId, versionId) => {
|
||||||
|
|
@ -84,9 +89,9 @@ const PageDetailsPage = observer(() => {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
getRedirectionLink: (pageId) => `/${workspaceSlug}/projects/${projectId}/pages/${pageId}`,
|
getRedirectionLink: (pageId) => `/${workspaceSlug}/projects/${projectId}/pages/${pageId}`,
|
||||||
updateDescription,
|
updateDescription: updateDescription ?? (async () => {}),
|
||||||
}),
|
}),
|
||||||
[createPage, fetchEntityCallback, page.id, projectId, updateDescription, workspaceSlug]
|
[createPage, fetchEntityCallback, id, projectId, updateDescription, workspaceSlug]
|
||||||
);
|
);
|
||||||
// page root config
|
// page root config
|
||||||
const pageRootConfig: TPageRootConfig = useMemo(
|
const pageRootConfig: TPageRootConfig = useMemo(
|
||||||
|
|
@ -145,6 +150,8 @@ const PageDetailsPage = observer(() => {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!page) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageHead title={name} />
|
<PageHead title={name} />
|
||||||
|
|
@ -154,6 +161,7 @@ const PageDetailsPage = observer(() => {
|
||||||
config={pageRootConfig}
|
config={pageRootConfig}
|
||||||
handlers={pageRootHandlers}
|
handlers={pageRootHandlers}
|
||||||
page={page}
|
page={page}
|
||||||
|
storeType={EPageStoreType.PROJECT}
|
||||||
webhookConnectionParams={webhookConnectionParams}
|
webhookConnectionParams={webhookConnectionParams}
|
||||||
workspaceSlug={workspaceSlug?.toString() ?? ""}
|
workspaceSlug={workspaceSlug?.toString() ?? ""}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,13 @@ import { PageEditInformationPopover } from "@/components/pages";
|
||||||
import { convertHexEmojiToDecimal } from "@/helpers/emoji.helper";
|
import { convertHexEmojiToDecimal } from "@/helpers/emoji.helper";
|
||||||
import { getPageName } from "@/helpers/page.helper";
|
import { getPageName } from "@/helpers/page.helper";
|
||||||
// hooks
|
// hooks
|
||||||
import { useProjectPage, useProject } from "@/hooks/store";
|
import { useProject } from "@/hooks/store";
|
||||||
import { usePlatformOS } from "@/hooks/use-platform-os";
|
import { usePlatformOS } from "@/hooks/use-platform-os";
|
||||||
// plane web components
|
// plane web components
|
||||||
import { ProjectBreadcrumb } from "@/plane-web/components/breadcrumbs";
|
import { ProjectBreadcrumb } from "@/plane-web/components/breadcrumbs";
|
||||||
import { PageDetailsHeaderExtraActions } from "@/plane-web/components/pages";
|
import { PageDetailsHeaderExtraActions } from "@/plane-web/components/pages";
|
||||||
|
// plane web hooks
|
||||||
|
import { EPageStoreType, usePage } from "@/plane-web/hooks/store";
|
||||||
|
|
||||||
export interface IPagesHeaderProps {
|
export interface IPagesHeaderProps {
|
||||||
showButton?: boolean;
|
showButton?: boolean;
|
||||||
|
|
@ -32,7 +34,12 @@ export const PageDetailsHeader = observer(() => {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
// store hooks
|
// store hooks
|
||||||
const { currentProjectDetails, loader } = useProject();
|
const { currentProjectDetails, loader } = useProject();
|
||||||
const page = useProjectPage(pageId?.toString() ?? "");
|
const page = usePage({
|
||||||
|
pageId: pageId?.toString() ?? "",
|
||||||
|
storeType: EPageStoreType.PROJECT,
|
||||||
|
});
|
||||||
|
if (!page) return null;
|
||||||
|
// derived values
|
||||||
const { name, logo_props, updatePageLogo, isContentEditable } = page;
|
const { name, logo_props, updatePageLogo, isContentEditable } = page;
|
||||||
// use platform
|
// use platform
|
||||||
const { isMobile } = usePlatformOS();
|
const { isMobile } = usePlatformOS();
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,11 @@ import { Breadcrumbs, Button, Header, setToast, TOAST_TYPE } from "@plane/ui";
|
||||||
// helpers
|
// helpers
|
||||||
import { BreadcrumbLink } from "@/components/common";
|
import { BreadcrumbLink } from "@/components/common";
|
||||||
// hooks
|
// hooks
|
||||||
import { useEventTracker, useProject, useProjectPages } from "@/hooks/store";
|
import { useEventTracker, useProject } from "@/hooks/store";
|
||||||
// plane web
|
// plane web
|
||||||
import { ProjectBreadcrumb } from "@/plane-web/components/breadcrumbs";
|
import { ProjectBreadcrumb } from "@/plane-web/components/breadcrumbs";
|
||||||
|
// plane web hooks
|
||||||
|
import { EPageStoreType, usePageStore } from "@/plane-web/hooks/store";
|
||||||
|
|
||||||
export const PagesListHeader = observer(() => {
|
export const PagesListHeader = observer(() => {
|
||||||
// states
|
// states
|
||||||
|
|
@ -27,7 +29,7 @@ export const PagesListHeader = observer(() => {
|
||||||
const pageType = searchParams.get("type");
|
const pageType = searchParams.get("type");
|
||||||
// store hooks
|
// store hooks
|
||||||
const { currentProjectDetails, loader } = useProject();
|
const { currentProjectDetails, loader } = useProject();
|
||||||
const { canCurrentUserCreatePage, createPage } = useProjectPages();
|
const { canCurrentUserCreatePage, createPage } = usePageStore(EPageStoreType.PROJECT);
|
||||||
const { setTrackElement } = useEventTracker();
|
const { setTrackElement } = useEventTracker();
|
||||||
// handle page create
|
// handle page create
|
||||||
const handleCreatePage = async () => {
|
const handleCreatePage = async () => {
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ import { PagesListRoot, PagesListView } from "@/components/pages";
|
||||||
import { useProject, useUserPermissions } from "@/hooks/store";
|
import { useProject, useUserPermissions } from "@/hooks/store";
|
||||||
import { useAppRouter } from "@/hooks/use-app-router";
|
import { useAppRouter } from "@/hooks/use-app-router";
|
||||||
import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path";
|
import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path";
|
||||||
|
// plane web hooks
|
||||||
|
import { EPageStoreType } from "@/plane-web/hooks/store";
|
||||||
|
|
||||||
const ProjectPagesPage = observer(() => {
|
const ProjectPagesPage = observer(() => {
|
||||||
// router
|
// router
|
||||||
|
|
@ -63,11 +65,12 @@ const ProjectPagesPage = observer(() => {
|
||||||
<>
|
<>
|
||||||
<PageHead title={pageTitle} />
|
<PageHead title={pageTitle} />
|
||||||
<PagesListView
|
<PagesListView
|
||||||
workspaceSlug={workspaceSlug.toString()}
|
|
||||||
projectId={projectId.toString()}
|
|
||||||
pageType={currentPageType()}
|
pageType={currentPageType()}
|
||||||
|
projectId={projectId.toString()}
|
||||||
|
storeType={EPageStoreType.PROJECT}
|
||||||
|
workspaceSlug={workspaceSlug.toString()}
|
||||||
>
|
>
|
||||||
<PagesListRoot pageType={currentPageType()} />
|
<PagesListRoot pageType={currentPageType()} storeType={EPageStoreType.PROJECT} />
|
||||||
</PagesListView>
|
</PagesListView>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ import { CreatePageModal } from "@/components/pages";
|
||||||
import { CreateUpdateProjectViewModal } from "@/components/views";
|
import { CreateUpdateProjectViewModal } from "@/components/views";
|
||||||
// hooks
|
// hooks
|
||||||
import { useCommandPalette } from "@/hooks/store";
|
import { useCommandPalette } from "@/hooks/store";
|
||||||
|
// plane web hooks
|
||||||
|
import { EPageStoreType } from "@/plane-web/hooks/store";
|
||||||
|
|
||||||
export type TProjectLevelModalsProps = {
|
export type TProjectLevelModalsProps = {
|
||||||
workspaceSlug: string;
|
workspaceSlug: string;
|
||||||
|
|
@ -53,6 +55,7 @@ export const ProjectLevelModals = observer((props: TProjectLevelModalsProps) =>
|
||||||
pageAccess={createPageModal.pageAccess}
|
pageAccess={createPageModal.pageAccess}
|
||||||
handleModalClose={() => toggleCreatePageModal({ isOpen: false })}
|
handleModalClose={() => toggleCreatePageModal({ isOpen: false })}
|
||||||
redirectionEnabled
|
redirectionEnabled
|
||||||
|
storeType={EPageStoreType.PROJECT}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
2
web/ce/hooks/store/index.ts
Normal file
2
web/ce/hooks/store/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./use-page-store";
|
||||||
|
export * from "./use-page";
|
||||||
24
web/ce/hooks/store/use-page-store.ts
Normal file
24
web/ce/hooks/store/use-page-store.ts
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { useContext } from "react";
|
||||||
|
// context
|
||||||
|
import { StoreContext } from "@/lib/store-context";
|
||||||
|
// mobx store
|
||||||
|
import { IProjectPageStore } from "@/store/pages/project-page.store";
|
||||||
|
|
||||||
|
export enum EPageStoreType {
|
||||||
|
PROJECT = "PROJECT_PAGE",
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TReturnType = {
|
||||||
|
[EPageStoreType.PROJECT]: IProjectPageStore;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const usePageStore = <T extends EPageStoreType>(storeType: T): TReturnType[T] => {
|
||||||
|
const context = useContext(StoreContext);
|
||||||
|
if (context === undefined) throw new Error("usePageStore must be used within StoreProvider");
|
||||||
|
|
||||||
|
if (storeType === EPageStoreType.PROJECT) {
|
||||||
|
return context.projectPages;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(`Invalid store type: ${storeType}`);
|
||||||
|
};
|
||||||
23
web/ce/hooks/store/use-page.ts
Normal file
23
web/ce/hooks/store/use-page.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { useContext } from "react";
|
||||||
|
// mobx store
|
||||||
|
import { StoreContext } from "@/lib/store-context";
|
||||||
|
// plane web hooks
|
||||||
|
import { EPageStoreType, usePageStore } from "@/plane-web/hooks/store";
|
||||||
|
|
||||||
|
export type TArgs = {
|
||||||
|
pageId: string;
|
||||||
|
storeType: EPageStoreType;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const usePage = (args: TArgs) => {
|
||||||
|
const { pageId, storeType } = args;
|
||||||
|
// context
|
||||||
|
const context = useContext(StoreContext);
|
||||||
|
// store hooks
|
||||||
|
const pageStore = usePageStore(storeType);
|
||||||
|
|
||||||
|
if (context === undefined) throw new Error("usePage must be used within StoreProvider");
|
||||||
|
if (!pageId) throw new Error("pageId is required");
|
||||||
|
|
||||||
|
return pageStore.getPageById(pageId);
|
||||||
|
};
|
||||||
|
|
@ -30,6 +30,7 @@ import { usePageOperations } from "@/hooks/use-page-operations";
|
||||||
// plane web components
|
// plane web components
|
||||||
import { MovePageModal } from "@/plane-web/components/pages";
|
import { MovePageModal } from "@/plane-web/components/pages";
|
||||||
// plane web hooks
|
// plane web hooks
|
||||||
|
import { EPageStoreType } from "@/plane-web/hooks/store";
|
||||||
import { usePageFlag } from "@/plane-web/hooks/use-page-flag";
|
import { usePageFlag } from "@/plane-web/hooks/use-page-flag";
|
||||||
// store types
|
// store types
|
||||||
import { TPageInstance } from "@/store/pages/base-page";
|
import { TPageInstance } from "@/store/pages/base-page";
|
||||||
|
|
@ -55,10 +56,11 @@ type Props = {
|
||||||
optionsOrder: TPageActions[];
|
optionsOrder: TPageActions[];
|
||||||
page: TPageInstance;
|
page: TPageInstance;
|
||||||
parentRef?: React.RefObject<HTMLElement>;
|
parentRef?: React.RefObject<HTMLElement>;
|
||||||
|
storeType: EPageStoreType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PageActions: React.FC<Props> = observer((props) => {
|
export const PageActions: React.FC<Props> = observer((props) => {
|
||||||
const { editorRef, extraOptions, optionsOrder, page, parentRef } = props;
|
const { editorRef, extraOptions, optionsOrder, page, parentRef, storeType } = props;
|
||||||
// states
|
// states
|
||||||
const [deletePageModal, setDeletePageModal] = useState(false);
|
const [deletePageModal, setDeletePageModal] = useState(false);
|
||||||
const [movePageModal, setMovePageModal] = useState(false);
|
const [movePageModal, setMovePageModal] = useState(false);
|
||||||
|
|
@ -175,7 +177,12 @@ export const PageActions: React.FC<Props> = observer((props) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MovePageModal isOpen={movePageModal} onClose={() => setMovePageModal(false)} page={page} />
|
<MovePageModal isOpen={movePageModal} onClose={() => setMovePageModal(false)} page={page} />
|
||||||
<DeletePageModal isOpen={deletePageModal} onClose={() => setDeletePageModal(false)} page={page} />
|
<DeletePageModal
|
||||||
|
isOpen={deletePageModal}
|
||||||
|
onClose={() => setDeletePageModal(false)}
|
||||||
|
page={page}
|
||||||
|
storeType={storeType}
|
||||||
|
/>
|
||||||
{parentRef && <ContextMenu parentRef={parentRef} items={arrangedOptions} />}
|
{parentRef && <ContextMenu parentRef={parentRef} items={arrangedOptions} />}
|
||||||
<CustomMenu placement="bottom-end" optionsClassName="max-h-[90vh]" ellipsis closeOnSelect>
|
<CustomMenu placement="bottom-end" optionsClassName="max-h-[90vh]" ellipsis closeOnSelect>
|
||||||
{arrangedOptions.map((item) => {
|
{arrangedOptions.map((item) => {
|
||||||
|
|
|
||||||
|
|
@ -12,16 +12,19 @@ import { PageInfoPopover, PageOptionsDropdown } from "@/components/pages";
|
||||||
import { renderFormattedDate } from "@/helpers/date-time.helper";
|
import { renderFormattedDate } from "@/helpers/date-time.helper";
|
||||||
// hooks
|
// hooks
|
||||||
import useOnlineStatus from "@/hooks/use-online-status";
|
import useOnlineStatus from "@/hooks/use-online-status";
|
||||||
|
// plane web hooks
|
||||||
|
import { EPageStoreType } from "@/plane-web/hooks/store";
|
||||||
// store
|
// store
|
||||||
import { TPageInstance } from "@/store/pages/base-page";
|
import { TPageInstance } from "@/store/pages/base-page";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
editorRef: EditorRefApi;
|
editorRef: EditorRefApi;
|
||||||
page: TPageInstance;
|
page: TPageInstance;
|
||||||
|
storeType: EPageStoreType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PageExtraOptions: React.FC<Props> = observer((props) => {
|
export const PageExtraOptions: React.FC<Props> = observer((props) => {
|
||||||
const { editorRef, page } = props;
|
const { editorRef, page, storeType } = props;
|
||||||
// derived values
|
// derived values
|
||||||
const {
|
const {
|
||||||
archived_at,
|
archived_at,
|
||||||
|
|
@ -84,7 +87,7 @@ export const PageExtraOptions: React.FC<Props> = observer((props) => {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<PageInfoPopover editorRef={editorRef} page={page} />
|
<PageInfoPopover editorRef={editorRef} page={page} />
|
||||||
<PageOptionsDropdown editorRef={editorRef} page={page} />
|
<PageOptionsDropdown editorRef={editorRef} page={page} storeType={storeType} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ import { Header, EHeaderVariant } from "@plane/ui";
|
||||||
import { PageExtraOptions, PageSummaryPopover, PageToolbar } from "@/components/pages";
|
import { PageExtraOptions, PageSummaryPopover, PageToolbar } from "@/components/pages";
|
||||||
// hooks
|
// hooks
|
||||||
import { usePageFilters } from "@/hooks/use-page-filters";
|
import { usePageFilters } from "@/hooks/use-page-filters";
|
||||||
|
// plane web hooks
|
||||||
|
import { EPageStoreType } from "@/plane-web/hooks/store";
|
||||||
// store
|
// store
|
||||||
import { TPageInstance } from "@/store/pages/base-page";
|
import { TPageInstance } from "@/store/pages/base-page";
|
||||||
|
|
||||||
|
|
@ -13,10 +15,11 @@ type Props = {
|
||||||
page: TPageInstance;
|
page: TPageInstance;
|
||||||
setSidePeekVisible: (sidePeekState: boolean) => void;
|
setSidePeekVisible: (sidePeekState: boolean) => void;
|
||||||
sidePeekVisible: boolean;
|
sidePeekVisible: boolean;
|
||||||
|
storeType: EPageStoreType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PageEditorMobileHeaderRoot: React.FC<Props> = observer((props) => {
|
export const PageEditorMobileHeaderRoot: React.FC<Props> = observer((props) => {
|
||||||
const { editorRef, page, setSidePeekVisible, sidePeekVisible } = props;
|
const { editorRef, page, setSidePeekVisible, sidePeekVisible, storeType } = props;
|
||||||
// derived values
|
// derived values
|
||||||
const { isContentEditable } = page;
|
const { isContentEditable } = page;
|
||||||
// page filters
|
// page filters
|
||||||
|
|
@ -33,7 +36,7 @@ export const PageEditorMobileHeaderRoot: React.FC<Props> = observer((props) => {
|
||||||
setSidePeekVisible={setSidePeekVisible}
|
setSidePeekVisible={setSidePeekVisible}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<PageExtraOptions editorRef={editorRef} page={page} />
|
<PageExtraOptions editorRef={editorRef} page={page} storeType={storeType} />
|
||||||
</Header>
|
</Header>
|
||||||
<Header variant={EHeaderVariant.TERNARY}>
|
<Header variant={EHeaderVariant.TERNARY}>
|
||||||
{isContentEditable && editorRef && <PageToolbar editorRef={editorRef} />}
|
{isContentEditable && editorRef && <PageToolbar editorRef={editorRef} />}
|
||||||
|
|
|
||||||
|
|
@ -15,16 +15,19 @@ import { copyTextToClipboard } from "@/helpers/string.helper";
|
||||||
// hooks
|
// hooks
|
||||||
import { usePageFilters } from "@/hooks/use-page-filters";
|
import { usePageFilters } from "@/hooks/use-page-filters";
|
||||||
import { useQueryParams } from "@/hooks/use-query-params";
|
import { useQueryParams } from "@/hooks/use-query-params";
|
||||||
|
// plane web hooks
|
||||||
|
import { EPageStoreType } from "@/plane-web/hooks/store";
|
||||||
// store
|
// store
|
||||||
import { TPageInstance } from "@/store/pages/base-page";
|
import { TPageInstance } from "@/store/pages/base-page";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
editorRef: EditorRefApi | null;
|
editorRef: EditorRefApi | null;
|
||||||
page: TPageInstance;
|
page: TPageInstance;
|
||||||
|
storeType: EPageStoreType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PageOptionsDropdown: React.FC<Props> = observer((props) => {
|
export const PageOptionsDropdown: React.FC<Props> = observer((props) => {
|
||||||
const { editorRef, page } = props;
|
const { editorRef, page, storeType } = props;
|
||||||
// states
|
// states
|
||||||
const [isExportModalOpen, setIsExportModalOpen] = useState(false);
|
const [isExportModalOpen, setIsExportModalOpen] = useState(false);
|
||||||
// router
|
// router
|
||||||
|
|
@ -136,6 +139,7 @@ export const PageOptionsDropdown: React.FC<Props> = observer((props) => {
|
||||||
"export",
|
"export",
|
||||||
]}
|
]}
|
||||||
page={page}
|
page={page}
|
||||||
|
storeType={storeType}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ import { PageEditorMobileHeaderRoot, PageExtraOptions, PageSummaryPopover, PageT
|
||||||
import { cn } from "@/helpers/common.helper";
|
import { cn } from "@/helpers/common.helper";
|
||||||
// hooks
|
// hooks
|
||||||
import { usePageFilters } from "@/hooks/use-page-filters";
|
import { usePageFilters } from "@/hooks/use-page-filters";
|
||||||
|
// plane web hooks
|
||||||
|
import { EPageStoreType } from "@/plane-web/hooks/store";
|
||||||
// store
|
// store
|
||||||
import { TPageInstance } from "@/store/pages/base-page";
|
import { TPageInstance } from "@/store/pages/base-page";
|
||||||
|
|
||||||
|
|
@ -16,10 +18,11 @@ type Props = {
|
||||||
page: TPageInstance;
|
page: TPageInstance;
|
||||||
setSidePeekVisible: (sidePeekState: boolean) => void;
|
setSidePeekVisible: (sidePeekState: boolean) => void;
|
||||||
sidePeekVisible: boolean;
|
sidePeekVisible: boolean;
|
||||||
|
storeType: EPageStoreType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PageEditorHeaderRoot: React.FC<Props> = observer((props) => {
|
export const PageEditorHeaderRoot: React.FC<Props> = observer((props) => {
|
||||||
const { editorReady, editorRef, page, setSidePeekVisible, sidePeekVisible } = props;
|
const { editorReady, editorRef, page, setSidePeekVisible, sidePeekVisible, storeType } = props;
|
||||||
// derived values
|
// derived values
|
||||||
const { isContentEditable } = page;
|
const { isContentEditable } = page;
|
||||||
// page filters
|
// page filters
|
||||||
|
|
@ -52,7 +55,7 @@ export const PageEditorHeaderRoot: React.FC<Props> = observer((props) => {
|
||||||
<PageToolbar editorRef={editorRef?.current} />
|
<PageToolbar editorRef={editorRef?.current} />
|
||||||
)}
|
)}
|
||||||
</Header.LeftItem>
|
</Header.LeftItem>
|
||||||
<PageExtraOptions editorRef={resolvedEditorRef} page={page} />
|
<PageExtraOptions editorRef={resolvedEditorRef} page={page} storeType={storeType} />
|
||||||
</Header>
|
</Header>
|
||||||
<div className="md:hidden">
|
<div className="md:hidden">
|
||||||
<PageEditorMobileHeaderRoot
|
<PageEditorMobileHeaderRoot
|
||||||
|
|
@ -60,6 +63,7 @@ export const PageEditorHeaderRoot: React.FC<Props> = observer((props) => {
|
||||||
page={page}
|
page={page}
|
||||||
sidePeekVisible={sidePeekVisible}
|
sidePeekVisible={sidePeekVisible}
|
||||||
setSidePeekVisible={setSidePeekVisible}
|
setSidePeekVisible={setSidePeekVisible}
|
||||||
|
storeType={storeType}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ import {
|
||||||
import { useAppRouter } from "@/hooks/use-app-router";
|
import { useAppRouter } from "@/hooks/use-app-router";
|
||||||
import { usePageFallback } from "@/hooks/use-page-fallback";
|
import { usePageFallback } from "@/hooks/use-page-fallback";
|
||||||
import { useQueryParams } from "@/hooks/use-query-params";
|
import { useQueryParams } from "@/hooks/use-query-params";
|
||||||
|
// plane web hooks
|
||||||
|
import { EPageStoreType } from "@/plane-web/hooks/store";
|
||||||
// store
|
// store
|
||||||
import { TPageInstance } from "@/store/pages/base-page";
|
import { TPageInstance } from "@/store/pages/base-page";
|
||||||
|
|
||||||
|
|
@ -36,12 +38,13 @@ type TPageRootProps = {
|
||||||
config: TPageRootConfig;
|
config: TPageRootConfig;
|
||||||
handlers: TPageRootHandlers;
|
handlers: TPageRootHandlers;
|
||||||
page: TPageInstance;
|
page: TPageInstance;
|
||||||
|
storeType: EPageStoreType;
|
||||||
webhookConnectionParams: TWebhookConnectionQueryParams;
|
webhookConnectionParams: TWebhookConnectionQueryParams;
|
||||||
workspaceSlug: string;
|
workspaceSlug: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PageRoot = observer((props: TPageRootProps) => {
|
export const PageRoot = observer((props: TPageRootProps) => {
|
||||||
const { config, handlers, page, webhookConnectionParams, workspaceSlug } = props;
|
const { config, handlers, page, storeType, webhookConnectionParams, workspaceSlug } = props;
|
||||||
// states
|
// states
|
||||||
const [editorReady, setEditorReady] = useState(false);
|
const [editorReady, setEditorReady] = useState(false);
|
||||||
const [hasConnectionFailed, setHasConnectionFailed] = useState(false);
|
const [hasConnectionFailed, setHasConnectionFailed] = useState(false);
|
||||||
|
|
@ -107,6 +110,7 @@ export const PageRoot = observer((props: TPageRootProps) => {
|
||||||
page={page}
|
page={page}
|
||||||
setSidePeekVisible={(state) => setSidePeekVisible(state)}
|
setSidePeekVisible={(state) => setSidePeekVisible(state)}
|
||||||
sidePeekVisible={sidePeekVisible}
|
sidePeekVisible={sidePeekVisible}
|
||||||
|
storeType={storeType}
|
||||||
/>
|
/>
|
||||||
<PageEditorBody
|
<PageEditorBody
|
||||||
config={config}
|
config={config}
|
||||||
|
|
|
||||||
|
|
@ -16,19 +16,22 @@ import {
|
||||||
// helpers
|
// helpers
|
||||||
import { calculateTotalFilters } from "@/helpers/filter.helper";
|
import { calculateTotalFilters } from "@/helpers/filter.helper";
|
||||||
// hooks
|
// hooks
|
||||||
import { useMember, useProjectPages } from "@/hooks/store";
|
import { useMember } from "@/hooks/store";
|
||||||
|
// plane web hooks
|
||||||
|
import { EPageStoreType, usePageStore } from "@/plane-web/hooks/store";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
pageType: TPageNavigationTabs;
|
pageType: TPageNavigationTabs;
|
||||||
projectId: string;
|
projectId: string;
|
||||||
|
storeType: EPageStoreType;
|
||||||
workspaceSlug: string;
|
workspaceSlug: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PagesListHeaderRoot: React.FC<Props> = observer((props) => {
|
export const PagesListHeaderRoot: React.FC<Props> = observer((props) => {
|
||||||
const { pageType, projectId, workspaceSlug } = props;
|
const { pageType, projectId, storeType, workspaceSlug } = props;
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
// store hooks
|
// store hooks
|
||||||
const { filters, updateFilters, clearAllFilters } = useProjectPages();
|
const { filters, updateFilters, clearAllFilters } = usePageStore(storeType);
|
||||||
const {
|
const {
|
||||||
workspace: { workspaceMemberIds },
|
workspace: { workspaceMemberIds },
|
||||||
} = useMember();
|
} = useMember();
|
||||||
|
|
|
||||||
|
|
@ -13,15 +13,19 @@ import { getFileURL } from "@/helpers/file.helper";
|
||||||
// hooks
|
// hooks
|
||||||
import { useMember } from "@/hooks/store";
|
import { useMember } from "@/hooks/store";
|
||||||
import { usePageOperations } from "@/hooks/use-page-operations";
|
import { usePageOperations } from "@/hooks/use-page-operations";
|
||||||
|
// plane web hooks
|
||||||
|
import { EPageStoreType } from "@/plane-web/hooks/store";
|
||||||
|
// store
|
||||||
import { TPageInstance } from "@/store/pages/base-page";
|
import { TPageInstance } from "@/store/pages/base-page";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
page: TPageInstance;
|
page: TPageInstance;
|
||||||
parentRef: React.RefObject<HTMLElement>;
|
parentRef: React.RefObject<HTMLElement>;
|
||||||
|
storeType: EPageStoreType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const BlockItemAction: FC<Props> = observer((props) => {
|
export const BlockItemAction: FC<Props> = observer((props) => {
|
||||||
const { page, parentRef } = props;
|
const { page, parentRef, storeType } = props;
|
||||||
// store hooks
|
// store hooks
|
||||||
const { getUserDetails } = useMember();
|
const { getUserDetails } = useMember();
|
||||||
// page operations
|
// page operations
|
||||||
|
|
@ -80,6 +84,7 @@ export const BlockItemAction: FC<Props> = observer((props) => {
|
||||||
]}
|
]}
|
||||||
page={page}
|
page={page}
|
||||||
parentRef={parentRef}
|
parentRef={parentRef}
|
||||||
|
storeType={storeType}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -11,20 +11,26 @@ import { BlockItemAction } from "@/components/pages/list";
|
||||||
import { getPageName } from "@/helpers/page.helper";
|
import { getPageName } from "@/helpers/page.helper";
|
||||||
// hooks
|
// hooks
|
||||||
import { usePlatformOS } from "@/hooks/use-platform-os";
|
import { usePlatformOS } from "@/hooks/use-platform-os";
|
||||||
import { TUsePage } from "@/store/pages/base-page";
|
// plane web hooks
|
||||||
|
import { EPageStoreType, usePage } from "@/plane-web/hooks/store";
|
||||||
|
|
||||||
type TPageListBlock = {
|
type TPageListBlock = {
|
||||||
pageId: string;
|
pageId: string;
|
||||||
usePage: TUsePage;
|
storeType: EPageStoreType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PageListBlock: FC<TPageListBlock> = observer((props) => {
|
export const PageListBlock: FC<TPageListBlock> = observer((props) => {
|
||||||
const { pageId, usePage } = props;
|
const { pageId, storeType } = props;
|
||||||
// refs
|
// refs
|
||||||
const parentRef = useRef(null);
|
const parentRef = useRef(null);
|
||||||
// hooks
|
// hooks
|
||||||
const page = usePage(pageId);
|
const page = usePage({
|
||||||
|
pageId,
|
||||||
|
storeType,
|
||||||
|
});
|
||||||
const { isMobile } = usePlatformOS();
|
const { isMobile } = usePlatformOS();
|
||||||
|
// handle page check
|
||||||
|
if (!page) return null;
|
||||||
// derived values
|
// derived values
|
||||||
const { name, logo_props, getRedirectionLink } = page;
|
const { name, logo_props, getRedirectionLink } = page;
|
||||||
|
|
||||||
|
|
@ -41,7 +47,7 @@ export const PageListBlock: FC<TPageListBlock> = observer((props) => {
|
||||||
}
|
}
|
||||||
title={getPageName(name)}
|
title={getPageName(name)}
|
||||||
itemLink={getRedirectionLink()}
|
itemLink={getRedirectionLink()}
|
||||||
actionableItems={<BlockItemAction page={page} parentRef={parentRef} />}
|
actionableItems={<BlockItemAction page={page} parentRef={parentRef} storeType={storeType} />}
|
||||||
isMobile={isMobile}
|
isMobile={isMobile}
|
||||||
parentRef={parentRef}
|
parentRef={parentRef}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -4,19 +4,20 @@ import { observer } from "mobx-react";
|
||||||
import { TPageNavigationTabs } from "@plane/types";
|
import { TPageNavigationTabs } from "@plane/types";
|
||||||
// components
|
// components
|
||||||
import { ListLayout } from "@/components/core/list";
|
import { ListLayout } from "@/components/core/list";
|
||||||
// hooks
|
// plane web hooks
|
||||||
import { useProjectPage, useProjectPages } from "@/hooks/store";
|
import { EPageStoreType, usePageStore } from "@/plane-web/hooks/store";
|
||||||
// components
|
// components
|
||||||
import { PageListBlock } from "./";
|
import { PageListBlock } from "./";
|
||||||
|
|
||||||
type TPagesListRoot = {
|
type TPagesListRoot = {
|
||||||
pageType: TPageNavigationTabs;
|
pageType: TPageNavigationTabs;
|
||||||
|
storeType: EPageStoreType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PagesListRoot: FC<TPagesListRoot> = observer((props) => {
|
export const PagesListRoot: FC<TPagesListRoot> = observer((props) => {
|
||||||
const { pageType } = props;
|
const { pageType, storeType } = props;
|
||||||
// store hooks
|
// store hooks
|
||||||
const { getCurrentProjectFilteredPageIds } = useProjectPages();
|
const { getCurrentProjectFilteredPageIds } = usePageStore(storeType);
|
||||||
// derived values
|
// derived values
|
||||||
const filteredPageIds = getCurrentProjectFilteredPageIds(pageType);
|
const filteredPageIds = getCurrentProjectFilteredPageIds(pageType);
|
||||||
|
|
||||||
|
|
@ -24,7 +25,7 @@ export const PagesListRoot: FC<TPagesListRoot> = observer((props) => {
|
||||||
return (
|
return (
|
||||||
<ListLayout>
|
<ListLayout>
|
||||||
{filteredPageIds.map((pageId) => (
|
{filteredPageIds.map((pageId) => (
|
||||||
<PageListBlock key={pageId} pageId={pageId} usePage={useProjectPage} />
|
<PageListBlock key={pageId} pageId={pageId} storeType={storeType} />
|
||||||
))}
|
))}
|
||||||
</ListLayout>
|
</ListLayout>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,10 @@ import { EModalPosition, EModalWidth, ModalCore } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
import { PageForm } from "@/components/pages";
|
import { PageForm } from "@/components/pages";
|
||||||
// hooks
|
// hooks
|
||||||
import { useProjectPages, useEventTracker } from "@/hooks/store";
|
import { useEventTracker } from "@/hooks/store";
|
||||||
import { useAppRouter } from "@/hooks/use-app-router";
|
import { useAppRouter } from "@/hooks/use-app-router";
|
||||||
|
// plane web hooks
|
||||||
|
import { EPageStoreType, usePageStore } from "@/plane-web/hooks/store";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
workspaceSlug: string;
|
workspaceSlug: string;
|
||||||
|
|
@ -17,10 +19,19 @@ type Props = {
|
||||||
pageAccess?: EPageAccess;
|
pageAccess?: EPageAccess;
|
||||||
handleModalClose: () => void;
|
handleModalClose: () => void;
|
||||||
redirectionEnabled?: boolean;
|
redirectionEnabled?: boolean;
|
||||||
|
storeType: EPageStoreType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CreatePageModal: FC<Props> = (props) => {
|
export const CreatePageModal: FC<Props> = (props) => {
|
||||||
const { workspaceSlug, projectId, isModalOpen, pageAccess, handleModalClose, redirectionEnabled = false } = props;
|
const {
|
||||||
|
workspaceSlug,
|
||||||
|
projectId,
|
||||||
|
isModalOpen,
|
||||||
|
pageAccess,
|
||||||
|
handleModalClose,
|
||||||
|
redirectionEnabled = false,
|
||||||
|
storeType,
|
||||||
|
} = props;
|
||||||
// states
|
// states
|
||||||
const [pageFormData, setPageFormData] = useState<Partial<TPage>>({
|
const [pageFormData, setPageFormData] = useState<Partial<TPage>>({
|
||||||
id: undefined,
|
id: undefined,
|
||||||
|
|
@ -30,7 +41,7 @@ export const CreatePageModal: FC<Props> = (props) => {
|
||||||
// router
|
// router
|
||||||
const router = useAppRouter();
|
const router = useAppRouter();
|
||||||
// store hooks
|
// store hooks
|
||||||
const { createPage } = useProjectPages();
|
const { createPage } = usePageStore(storeType);
|
||||||
const { capturePageEvent } = useEventTracker();
|
const { capturePageEvent } = useEventTracker();
|
||||||
const handlePageFormData = <T extends keyof TPage>(key: T, value: TPage[T]) =>
|
const handlePageFormData = <T extends keyof TPage>(key: T, value: TPage[T]) =>
|
||||||
setPageFormData((prev) => ({ ...prev, [key]: value }));
|
setPageFormData((prev) => ({ ...prev, [key]: value }));
|
||||||
|
|
|
||||||
|
|
@ -7,21 +7,25 @@ import { PAGE_DELETED } from "@plane/constants";
|
||||||
import { AlertModalCore, TOAST_TYPE, setToast } from "@plane/ui";
|
import { AlertModalCore, TOAST_TYPE, setToast } from "@plane/ui";
|
||||||
// constants
|
// constants
|
||||||
// hooks
|
// hooks
|
||||||
import { useEventTracker, useProjectPages } from "@/hooks/store";
|
import { useEventTracker } from "@/hooks/store";
|
||||||
|
// plane web hooks
|
||||||
|
import { EPageStoreType, usePageStore } from "@/plane-web/hooks/store";
|
||||||
|
// store
|
||||||
import { TPageInstance } from "@/store/pages/base-page";
|
import { TPageInstance } from "@/store/pages/base-page";
|
||||||
|
|
||||||
type TConfirmPageDeletionProps = {
|
type TConfirmPageDeletionProps = {
|
||||||
page: TPageInstance;
|
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
|
page: TPageInstance;
|
||||||
|
storeType: EPageStoreType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DeletePageModal: React.FC<TConfirmPageDeletionProps> = observer((props) => {
|
export const DeletePageModal: React.FC<TConfirmPageDeletionProps> = observer((props) => {
|
||||||
const { page, isOpen, onClose } = props;
|
const { isOpen, onClose, page, storeType } = props;
|
||||||
// states
|
// states
|
||||||
const [isDeleting, setIsDeleting] = useState(false);
|
const [isDeleting, setIsDeleting] = useState(false);
|
||||||
// store hooks
|
// store hooks
|
||||||
const { removePage } = useProjectPages();
|
const { removePage } = usePageStore(storeType);
|
||||||
const { capturePageEvent } = useEventTracker();
|
const { capturePageEvent } = useEventTracker();
|
||||||
if (!page || !page.id) return null;
|
if (!page || !page.id) return null;
|
||||||
// derived values
|
// derived values
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,10 @@ import { TPageNavigationTabs } from "@plane/types";
|
||||||
// components
|
// components
|
||||||
import { DetailedEmptyState } from "@/components/empty-state";
|
import { DetailedEmptyState } from "@/components/empty-state";
|
||||||
import { PageLoader } from "@/components/pages";
|
import { PageLoader } from "@/components/pages";
|
||||||
import { useCommandPalette, useProjectPages, useUserPermissions } from "@/hooks/store";
|
import { useCommandPalette, useUserPermissions } from "@/hooks/store";
|
||||||
import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path";
|
import { useResolvedAssetPath } from "@/hooks/use-resolved-asset-path";
|
||||||
|
// plane web hooks
|
||||||
|
import { EPageStoreType, usePageStore } from "@/plane-web/hooks/store";
|
||||||
// assets
|
// assets
|
||||||
import AllFiltersImage from "@/public/empty-state/pages/all-filters.svg";
|
import AllFiltersImage from "@/public/empty-state/pages/all-filters.svg";
|
||||||
import NameFilterImage from "@/public/empty-state/pages/name-filter.svg";
|
import NameFilterImage from "@/public/empty-state/pages/name-filter.svg";
|
||||||
|
|
@ -16,15 +18,16 @@ import NameFilterImage from "@/public/empty-state/pages/name-filter.svg";
|
||||||
type Props = {
|
type Props = {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
pageType: TPageNavigationTabs;
|
pageType: TPageNavigationTabs;
|
||||||
|
storeType: EPageStoreType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PagesListMainContent: React.FC<Props> = observer((props) => {
|
export const PagesListMainContent: React.FC<Props> = observer((props) => {
|
||||||
const { children, pageType } = props;
|
const { children, pageType, storeType } = props;
|
||||||
// plane hooks
|
// plane hooks
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
// store hooks
|
// store hooks
|
||||||
const { loader, isAnyPageAvailable, getCurrentProjectFilteredPageIds, getCurrentProjectPageIds, filters } =
|
const { loader, isAnyPageAvailable, getCurrentProjectFilteredPageIds, getCurrentProjectPageIds, filters } =
|
||||||
useProjectPages();
|
usePageStore(storeType);
|
||||||
const { toggleCreatePageModal } = useCommandPalette();
|
const { toggleCreatePageModal } = useCommandPalette();
|
||||||
const { allowPermissions } = useUserPermissions();
|
const { allowPermissions } = useUserPermissions();
|
||||||
// derived values
|
// derived values
|
||||||
|
|
|
||||||
|
|
@ -3,24 +3,25 @@ import useSWR from "swr";
|
||||||
import { TPageNavigationTabs } from "@plane/types";
|
import { TPageNavigationTabs } from "@plane/types";
|
||||||
// components
|
// components
|
||||||
import { PagesListHeaderRoot, PagesListMainContent } from "@/components/pages";
|
import { PagesListHeaderRoot, PagesListMainContent } from "@/components/pages";
|
||||||
// hooks
|
// plane web hooks
|
||||||
import { useProjectPages } from "@/hooks/store";
|
import { EPageStoreType, usePageStore } from "@/plane-web/hooks/store";
|
||||||
|
|
||||||
type TPageView = {
|
type TPageView = {
|
||||||
workspaceSlug: string;
|
|
||||||
projectId: string;
|
|
||||||
pageType: TPageNavigationTabs;
|
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
pageType: TPageNavigationTabs;
|
||||||
|
projectId: string;
|
||||||
|
storeType: EPageStoreType;
|
||||||
|
workspaceSlug: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PagesListView: React.FC<TPageView> = observer((props) => {
|
export const PagesListView: React.FC<TPageView> = observer((props) => {
|
||||||
const { workspaceSlug, projectId, pageType, children } = props;
|
const { children, pageType, projectId, storeType, workspaceSlug } = props;
|
||||||
// store hooks
|
// store hooks
|
||||||
const { isAnyPageAvailable, getAllPages } = useProjectPages();
|
const { isAnyPageAvailable, fetchPagesList } = usePageStore(storeType);
|
||||||
// fetching pages list
|
// fetching pages list
|
||||||
useSWR(
|
useSWR(
|
||||||
workspaceSlug && projectId && pageType ? `PROJECT_PAGES_${projectId}` : null,
|
workspaceSlug && projectId && pageType ? `PROJECT_PAGES_${projectId}` : null,
|
||||||
workspaceSlug && projectId && pageType ? () => getAllPages(workspaceSlug, projectId, pageType) : null
|
workspaceSlug && projectId && pageType ? () => fetchPagesList(workspaceSlug, projectId, pageType) : null
|
||||||
);
|
);
|
||||||
|
|
||||||
// pages loader
|
// pages loader
|
||||||
|
|
@ -28,9 +29,16 @@ export const PagesListView: React.FC<TPageView> = observer((props) => {
|
||||||
<div className="relative w-full h-full overflow-hidden flex flex-col">
|
<div className="relative w-full h-full overflow-hidden flex flex-col">
|
||||||
{/* tab header */}
|
{/* tab header */}
|
||||||
{isAnyPageAvailable && (
|
{isAnyPageAvailable && (
|
||||||
<PagesListHeaderRoot pageType={pageType} projectId={projectId} workspaceSlug={workspaceSlug} />
|
<PagesListHeaderRoot
|
||||||
|
pageType={pageType}
|
||||||
|
projectId={projectId}
|
||||||
|
storeType={storeType}
|
||||||
|
workspaceSlug={workspaceSlug}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
<PagesListMainContent pageType={pageType}>{children}</PagesListMainContent>
|
<PagesListMainContent pageType={pageType} storeType={storeType}>
|
||||||
|
{children}
|
||||||
|
</PagesListMainContent>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
export * from "./estimates";
|
export * from "./estimates";
|
||||||
export * from "./notifications";
|
export * from "./notifications";
|
||||||
export * from "./pages";
|
|
||||||
export * from "./use-app-theme";
|
export * from "./use-app-theme";
|
||||||
export * from "./use-calendar-view";
|
export * from "./use-calendar-view";
|
||||||
export * from "./use-command-palette";
|
export * from "./use-command-palette";
|
||||||
|
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
export * from "./use-page";
|
|
||||||
export * from "./use-project-page";
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
import { useContext } from "react";
|
|
||||||
// mobx store
|
|
||||||
import { StoreContext } from "@/lib/store-context";
|
|
||||||
import { TUsePage } from "@/store/pages/base-page";
|
|
||||||
// store
|
|
||||||
import { TProjectPage } from "@/store/pages/project-page";
|
|
||||||
|
|
||||||
export const useProjectPage: TUsePage = (pageId: string | undefined): TProjectPage => {
|
|
||||||
const context = useContext(StoreContext);
|
|
||||||
if (context === undefined) throw new Error("usePage must be used within StoreProvider");
|
|
||||||
|
|
||||||
if (!pageId) return {} as TProjectPage;
|
|
||||||
|
|
||||||
return context.projectPages.data?.[pageId] ?? {};
|
|
||||||
};
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
import { useContext } from "react";
|
|
||||||
// context
|
|
||||||
import { StoreContext } from "@/lib/store-context";
|
|
||||||
// mobx store
|
|
||||||
import { IProjectPageStore } from "@/store/pages/project-page.store";
|
|
||||||
|
|
||||||
export const useProjectPages = (): IProjectPageStore => {
|
|
||||||
const context = useContext(StoreContext);
|
|
||||||
if (context === undefined) throw new Error("useProjectPage must be used within StoreProvider");
|
|
||||||
return context.projectPages;
|
|
||||||
};
|
|
||||||
|
|
@ -8,7 +8,9 @@ import {
|
||||||
// helpers
|
// helpers
|
||||||
import { getPageName } from "@/helpers/page.helper";
|
import { getPageName } from "@/helpers/page.helper";
|
||||||
// hooks
|
// hooks
|
||||||
import { useProject, useProjectPage, useProjectView, useCycle, useModule } from "@/hooks/store";
|
import { useProject, useProjectView, useCycle, useModule } from "@/hooks/store";
|
||||||
|
// plane web hooks
|
||||||
|
import { EPageStoreType, usePage } from "@/plane-web/hooks/store";
|
||||||
|
|
||||||
export const useFavoriteItemDetails = (workspaceSlug: string, favorite: IFavorite) => {
|
export const useFavoriteItemDetails = (workspaceSlug: string, favorite: IFavorite) => {
|
||||||
const favoriteItemId = favorite?.entity_data?.id;
|
const favoriteItemId = favorite?.entity_data?.id;
|
||||||
|
|
@ -23,7 +25,10 @@ export const useFavoriteItemDetails = (workspaceSlug: string, favorite: IFavorit
|
||||||
const { getModuleById } = useModule();
|
const { getModuleById } = useModule();
|
||||||
|
|
||||||
// derived values
|
// derived values
|
||||||
const pageDetail = useProjectPage(favoriteItemId ?? "");
|
const pageDetail = usePage({
|
||||||
|
pageId: favoriteItemId ?? "",
|
||||||
|
storeType: EPageStoreType.PROJECT,
|
||||||
|
});
|
||||||
const viewDetails = getViewById(favoriteItemId ?? "");
|
const viewDetails = getViewById(favoriteItemId ?? "");
|
||||||
const cycleDetail = getCycleById(favoriteItemId ?? "");
|
const cycleDetail = getCycleById(favoriteItemId ?? "");
|
||||||
const moduleDetail = getModuleById(favoriteItemId ?? "");
|
const moduleDetail = getModuleById(favoriteItemId ?? "");
|
||||||
|
|
@ -40,7 +45,7 @@ export const useFavoriteItemDetails = (workspaceSlug: string, favorite: IFavorit
|
||||||
itemIcon = getFavoriteItemIcon("project", currentProjectDetails?.logo_props || favoriteItemLogoProps);
|
itemIcon = getFavoriteItemIcon("project", currentProjectDetails?.logo_props || favoriteItemLogoProps);
|
||||||
break;
|
break;
|
||||||
case "page":
|
case "page":
|
||||||
itemTitle = getPageName(pageDetail.name || favoriteItemName);
|
itemTitle = getPageName(pageDetail?.name || favoriteItemName);
|
||||||
itemIcon = getFavoriteItemIcon("page", pageDetail?.logo_props || favoriteItemLogoProps);
|
itemIcon = getFavoriteItemIcon("page", pageDetail?.logo_props || favoriteItemLogoProps);
|
||||||
break;
|
break;
|
||||||
case "view":
|
case "view":
|
||||||
|
|
|
||||||
|
|
@ -64,8 +64,6 @@ export type TPageInstance = TBasePage &
|
||||||
getRedirectionLink: () => string;
|
getRedirectionLink: () => string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TUsePage = (pageId: string | undefined) => TPageInstance;
|
|
||||||
|
|
||||||
export class BasePage implements TBasePage {
|
export class BasePage implements TBasePage {
|
||||||
// loaders
|
// loaders
|
||||||
isSubmitting: TNameDescriptionLoader = "saved";
|
isSubmitting: TNameDescriptionLoader = "saved";
|
||||||
|
|
|
||||||
|
|
@ -39,16 +39,16 @@ export interface IProjectPageStore {
|
||||||
// helper actions
|
// helper actions
|
||||||
getCurrentProjectPageIds: (pageType: TPageNavigationTabs) => string[] | undefined;
|
getCurrentProjectPageIds: (pageType: TPageNavigationTabs) => string[] | undefined;
|
||||||
getCurrentProjectFilteredPageIds: (pageType: TPageNavigationTabs) => string[] | undefined;
|
getCurrentProjectFilteredPageIds: (pageType: TPageNavigationTabs) => string[] | undefined;
|
||||||
pageById: (pageId: string) => TProjectPage | undefined;
|
getPageById: (pageId: string) => TProjectPage | undefined;
|
||||||
updateFilters: <T extends keyof TPageFilters>(filterKey: T, filterValue: TPageFilters[T]) => void;
|
updateFilters: <T extends keyof TPageFilters>(filterKey: T, filterValue: TPageFilters[T]) => void;
|
||||||
clearAllFilters: () => void;
|
clearAllFilters: () => void;
|
||||||
// actions
|
// actions
|
||||||
getAllPages: (
|
fetchPagesList: (
|
||||||
workspaceSlug: string,
|
workspaceSlug: string,
|
||||||
projectId: string,
|
projectId: string,
|
||||||
pageType: TPageNavigationTabs
|
pageType: TPageNavigationTabs
|
||||||
) => Promise<TPage[] | undefined>;
|
) => Promise<TPage[] | undefined>;
|
||||||
getPageById: (workspaceSlug: string, projectId: string, pageId: string) => Promise<TPage | undefined>;
|
fetchPageDetails: (workspaceSlug: string, projectId: string, pageId: string) => Promise<TPage | undefined>;
|
||||||
createPage: (pageData: Partial<TPage>) => Promise<TPage | undefined>;
|
createPage: (pageData: Partial<TPage>) => Promise<TPage | undefined>;
|
||||||
removePage: (pageId: string) => Promise<void>;
|
removePage: (pageId: string) => Promise<void>;
|
||||||
movePage: (workspaceSlug: string, projectId: string, pageId: string, newProjectId: string) => Promise<void>;
|
movePage: (workspaceSlug: string, projectId: string, pageId: string, newProjectId: string) => Promise<void>;
|
||||||
|
|
@ -82,8 +82,8 @@ export class ProjectPageStore implements IProjectPageStore {
|
||||||
updateFilters: action,
|
updateFilters: action,
|
||||||
clearAllFilters: action,
|
clearAllFilters: action,
|
||||||
// actions
|
// actions
|
||||||
getAllPages: action,
|
fetchPagesList: action,
|
||||||
getPageById: action,
|
fetchPageDetails: action,
|
||||||
createPage: action,
|
createPage: action,
|
||||||
removePage: action,
|
removePage: action,
|
||||||
movePage: action,
|
movePage: action,
|
||||||
|
|
@ -164,7 +164,7 @@ export class ProjectPageStore implements IProjectPageStore {
|
||||||
* @description get the page store by id
|
* @description get the page store by id
|
||||||
* @param {string} pageId
|
* @param {string} pageId
|
||||||
*/
|
*/
|
||||||
pageById = computedFn((pageId: string) => this.data?.[pageId] || undefined);
|
getPageById = computedFn((pageId: string) => this.data?.[pageId] || undefined);
|
||||||
|
|
||||||
updateFilters = <T extends keyof TPageFilters>(filterKey: T, filterValue: TPageFilters[T]) => {
|
updateFilters = <T extends keyof TPageFilters>(filterKey: T, filterValue: TPageFilters[T]) => {
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
|
|
@ -183,7 +183,7 @@ export class ProjectPageStore implements IProjectPageStore {
|
||||||
/**
|
/**
|
||||||
* @description fetch all the pages
|
* @description fetch all the pages
|
||||||
*/
|
*/
|
||||||
getAllPages = async (workspaceSlug: string, projectId: string, pageType: TPageNavigationTabs) => {
|
fetchPagesList = async (workspaceSlug: string, projectId: string, pageType: TPageNavigationTabs) => {
|
||||||
try {
|
try {
|
||||||
if (!workspaceSlug || !projectId) return undefined;
|
if (!workspaceSlug || !projectId) return undefined;
|
||||||
|
|
||||||
|
|
@ -216,11 +216,11 @@ export class ProjectPageStore implements IProjectPageStore {
|
||||||
* @description fetch the details of a page
|
* @description fetch the details of a page
|
||||||
* @param {string} pageId
|
* @param {string} pageId
|
||||||
*/
|
*/
|
||||||
getPageById = async (workspaceSlug: string, projectId: string, pageId: string) => {
|
fetchPageDetails = async (workspaceSlug: string, projectId: string, pageId: string) => {
|
||||||
try {
|
try {
|
||||||
if (!workspaceSlug || !projectId || !pageId) return undefined;
|
if (!workspaceSlug || !projectId || !pageId) return undefined;
|
||||||
|
|
||||||
const currentPageId = this.pageById(pageId);
|
const currentPageId = this.getPageById(pageId);
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.loader = currentPageId ? `mutation-loader` : `init-loader`;
|
this.loader = currentPageId ? `mutation-loader` : `init-loader`;
|
||||||
this.error = undefined;
|
this.error = undefined;
|
||||||
|
|
|
||||||
1
web/ee/hooks/store/index.ts
Normal file
1
web/ee/hooks/store/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export * from "ce/hooks/store";
|
||||||
Loading…
Add table
Add a link
Reference in a new issue