Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WEB-1436] chore: pages improvement. #4657

Merged
merged 2 commits into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion web/components/command-palette/actions/project-actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export const CommandPaletteProjectActions: React.FC<Props> = (props) => {
onSelect={() => {
closePalette();
setTrackElement("Command palette");
toggleCreatePageModal(true);
toggleCreatePageModal({ isOpen: true });
}}
className="focus:outline-none"
>
Expand Down
9 changes: 5 additions & 4 deletions web/components/command-palette/command-palette.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export const CommandPalette: FC = observer(() => {
toggleCreateIssueModal,
isCreateCycleModalOpen,
toggleCreateCycleModal,
isCreatePageModalOpen,
createPageModal,
toggleCreatePageModal,
isCreateProjectModalOpen,
toggleCreateProjectModal,
Expand Down Expand Up @@ -150,7 +150,7 @@ export const CommandPalette: FC = observer(() => {
d: {
title: "Create a new page",
description: "Create a new page in the current project",
action: () => toggleCreatePageModal(true),
action: () => toggleCreatePageModal({ isOpen: true }),
},
m: {
title: "Create a new module",
Expand Down Expand Up @@ -297,8 +297,9 @@ export const CommandPalette: FC = observer(() => {
<CreatePageModal
workspaceSlug={workspaceSlug.toString()}
projectId={projectId.toString()}
isModalOpen={isCreatePageModalOpen}
handleModalClose={() => toggleCreatePageModal(false)}
isModalOpen={createPageModal.isOpen}
pageAccess={createPageModal.pageAccess}
handleModalClose={() => toggleCreatePageModal({ isOpen: false })}
redirectionEnabled
/>
</>
Expand Down
15 changes: 9 additions & 6 deletions web/components/headers/pages.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { FileText } from "lucide-react";
// hooks
// ui
import { Breadcrumbs, Button } from "@plane/ui";
// helpers
// components
import { BreadcrumbLink } from "@/components/common";
import { ProjectLogo } from "@/components/project";
import { EUserProjectRoles } from "@/constants/project";
// constants
// components
import { EPageAccess } from "@/constants/page";
import { EUserProjectRoles } from "@/constants/project";
// hooks
import { useCommandPalette, useEventTracker, useProject, useUser } from "@/hooks/store";

export const PagesHeader = observer(() => {
// router
const router = useRouter();
const { workspaceSlug } = router.query;
const { workspaceSlug, type: pageType } = router.query;
// store hooks
const { toggleCreatePageModal } = useCommandPalette();
const {
Expand Down Expand Up @@ -62,7 +62,10 @@ export const PagesHeader = observer(() => {
size="sm"
onClick={() => {
setTrackElement("Project pages page");
toggleCreatePageModal(true);
toggleCreatePageModal({
isOpen: true,
pageAccess: pageType === "private" ? EPageAccess.PRIVATE : EPageAccess.PUBLIC,
});
}}
>
Add Page
Expand Down
7 changes: 1 addition & 6 deletions web/components/pages/dropdowns/quick-actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,7 @@ export const PageQuickActions: React.FC<Props> = observer((props) => {

return (
<>
<DeletePageModal
isOpen={deletePageModal}
onClose={() => setDeletePageModal(false)}
pageId={pageId}
projectId={projectId}
/>
<DeletePageModal isOpen={deletePageModal} onClose={() => setDeletePageModal(false)} pageId={pageId} />
<ContextMenu parentRef={parentRef} items={MENU_ITEMS} />
<CustomMenu placement="bottom-end" ellipsis closeOnSelect>
{MENU_ITEMS.map((item) => {
Expand Down
4 changes: 2 additions & 2 deletions web/components/pages/header/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type Props = {
export const PagesListHeaderRoot: React.FC<Props> = observer((props) => {
const { pageType, projectId, workspaceSlug } = props;
// store hooks
const { filters, updateFilters, clearAllFilters } = useProjectPages(projectId);
const { filters, updateFilters, clearAllFilters } = useProjectPages();
const {
workspace: { workspaceMemberIds },
} = useMember();
Expand All @@ -52,7 +52,7 @@ export const PagesListHeaderRoot: React.FC<Props> = observer((props) => {
<div className="flex-shrink-0 h-[50px] w-full border-b border-custom-border-200 px-6 relative flex items-center gap-4 justify-between">
<PageTabNavigation workspaceSlug={workspaceSlug} projectId={projectId} pageType={pageType} />
<div className="h-full flex items-center gap-2 self-end">
<PageSearchInput projectId={projectId} />
<PageSearchInput />
<PageOrderByDropdown
sortBy={filters.sortBy}
sortKey={filters.sortKey}
Expand Down
2 changes: 1 addition & 1 deletion web/components/pages/list/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type TPagesListRoot = {
export const PagesListRoot: FC<TPagesListRoot> = observer((props) => {
const { pageType, projectId, workspaceSlug } = props;
// store hooks
const { getCurrentProjectFilteredPageIds } = useProjectPages(projectId);
const { getCurrentProjectFilteredPageIds } = useProjectPages();
// derived values
const filteredPageIds = getCurrentProjectFilteredPageIds(pageType);

Expand Down
7 changes: 2 additions & 5 deletions web/components/pages/list/search-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,12 @@ import { cn } from "@/helpers/common.helper";
import { useProjectPages } from "@/hooks/store";
import useOutsideClickDetector from "@/hooks/use-outside-click-detector";

export type TPageSearchInput = { projectId: string };

export const PageSearchInput: FC<TPageSearchInput> = observer((props) => {
const { projectId } = props;
export const PageSearchInput: FC = observer(() => {
// hooks
const {
filters: { searchQuery },
updateFilters,
} = useProjectPages(projectId);
} = useProjectPages();
// states
const [isSearchOpen, setIsSearchOpen] = useState(false);
// refs
Expand Down
15 changes: 10 additions & 5 deletions web/components/pages/modals/create-page-modal.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FC, useState } from "react";
import { FC, useEffect, useState } from "react";
import { useRouter } from "next/router";
// types
import { TPage } from "@plane/types";
Expand All @@ -15,28 +15,33 @@ type Props = {
workspaceSlug: string;
projectId: string;
isModalOpen: boolean;
pageAccess?: EPageAccess;
handleModalClose: () => void;
redirectionEnabled?: boolean;
};

export const CreatePageModal: FC<Props> = (props) => {
const { workspaceSlug, projectId, isModalOpen, handleModalClose, redirectionEnabled = false } = props;
const { workspaceSlug, projectId, isModalOpen, pageAccess, handleModalClose, redirectionEnabled = false } = props;
// states
const [pageFormData, setPageFormData] = useState<Partial<TPage>>({
id: undefined,
name: "",
access: EPageAccess.PUBLIC,
});
// router
const router = useRouter();
// store hooks
const { createPage } = useProjectPages(projectId);
const { createPage } = useProjectPages();
const { capturePageEvent } = useEventTracker();
const handlePageFormData = <T extends keyof TPage>(key: T, value: TPage[T]) =>
setPageFormData((prev) => ({ ...prev, [key]: value }));

// update page access in form data when page access from the store changes
useEffect(() => {
setPageFormData((prev) => ({ ...prev, access: pageAccess }));
}, [pageAccess]);

const handleStateClear = () => {
setPageFormData({ id: undefined, name: "", access: EPageAccess.PUBLIC });
setPageFormData({ id: undefined, name: "", access: pageAccess });
handleModalClose();
};

Expand Down
5 changes: 2 additions & 3 deletions web/components/pages/modals/delete-page-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,14 @@ type TConfirmPageDeletionProps = {
isOpen: boolean;
onClose: () => void;
pageId: string;
projectId: string;
};

export const DeletePageModal: React.FC<TConfirmPageDeletionProps> = observer((props) => {
const { pageId, projectId, isOpen, onClose } = props;
const { pageId, isOpen, onClose } = props;
// states
const [isDeleting, setIsDeleting] = useState(false);
// store hooks
const { removePage } = useProjectPages(projectId);
const { removePage } = useProjectPages();
const { capturePageEvent } = useEventTracker();
const page = usePage(pageId);

Expand Down
23 changes: 17 additions & 6 deletions web/components/pages/pages-list-main-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { PageLoader } from "@/components/pages";
// constants
import { EmptyStateType } from "@/constants/empty-state";
// hooks
import { EPageAccess } from "@/constants/page";
import { useCommandPalette, useProjectPages } from "@/hooks/store";
// assets
import AllFiltersImage from "public/empty-state/pages/all-filters.svg";
Expand All @@ -16,27 +17,37 @@ import NameFilterImage from "public/empty-state/pages/name-filter.svg";
type Props = {
children: React.ReactNode;
pageType: TPageNavigationTabs;
projectId: string;
};

export const PagesListMainContent: React.FC<Props> = observer((props) => {
const { children, pageType, projectId } = props;
const { children, pageType } = props;
// store hooks
const { loader, getCurrentProjectFilteredPageIds, getCurrentProjectPageIds, filters } = useProjectPages(projectId);
const { loader, isAnyPageAvailable, getCurrentProjectFilteredPageIds, getCurrentProjectPageIds, filters } =
useProjectPages();
const { toggleCreatePageModal } = useCommandPalette();
// 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
if (pageIds?.length === 0) {
if (!isAnyPageAvailable || pageIds?.length === 0) {
if (!isAnyPageAvailable) {
return (
<EmptyState
type={EmptyStateType.PROJECT_PAGE}
primaryButtonOnClick={() => {
toggleCreatePageModal({ isOpen: true });
}}
/>
);
}
if (pageType === "public")
return (
<EmptyState
type={EmptyStateType.PROJECT_PAGE_PUBLIC}
primaryButtonOnClick={() => {
toggleCreatePageModal(true);
toggleCreatePageModal({ isOpen: true, pageAccess: EPageAccess.PUBLIC });
}}
/>
);
Expand All @@ -45,7 +56,7 @@ export const PagesListMainContent: React.FC<Props> = observer((props) => {
<EmptyState
type={EmptyStateType.PROJECT_PAGE_PRIVATE}
primaryButtonOnClick={() => {
toggleCreatePageModal(true);
toggleCreatePageModal({ isOpen: true, pageAccess: EPageAccess.PRIVATE });
}}
/>
);
Expand Down
10 changes: 5 additions & 5 deletions web/components/pages/pages-list-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,18 @@ type TPageView = {
export const PagesListView: React.FC<TPageView> = observer((props) => {
const { workspaceSlug, projectId, pageType, children } = props;
// store hooks
const { getAllPages } = useProjectPages(projectId);
const { isAnyPageAvailable, getAllPages } = useProjectPages();
// fetching pages list
useSWR(projectId ? `PROJECT_PAGES_${projectId}` : null, projectId ? () => getAllPages(pageType) : null);

// pages loader
return (
<div className="relative w-full h-full overflow-hidden flex flex-col">
{/* tab header */}
<PagesListHeaderRoot pageType={pageType} projectId={projectId} workspaceSlug={workspaceSlug} />
<PagesListMainContent pageType={pageType} projectId={projectId}>
{children}
</PagesListMainContent>
{isAnyPageAvailable && (
<PagesListHeaderRoot pageType={pageType} projectId={projectId} workspaceSlug={workspaceSlug} />
)}
<PagesListMainContent pageType={pageType}>{children}</PagesListMainContent>
</div>
);
});
5 changes: 0 additions & 5 deletions web/constants/empty-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -486,11 +486,6 @@ const emptyStateDetails = {
path: "/empty-state/onboarding/pages",
primaryButton: {
text: "Create your first page",
comicBox: {
title: "A page can be a doc or a doc of docs.",
description:
"We wrote Nikhil and Meera’s love story. You could write your project’s mission, goals, and eventual vision.",
},
},
accessType: "project",
access: EUserProjectRoles.MEMBER,
Expand Down
10 changes: 10 additions & 0 deletions web/constants/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,13 @@ export const PAGE_SORT_BY_OPTIONS: {
{ key: "asc", label: "Ascending" },
{ key: "desc", label: "Descending" },
];

export type TCreatePageModal = {
isOpen: boolean;
pageAccess?: EPageAccess;
}

export const DEFAULT_CREATE_PAGE_MODAL_DATA: TCreatePageModal = {
isOpen: false,
pageAccess: EPageAccess.PUBLIC,
};
5 changes: 1 addition & 4 deletions web/hooks/store/pages/use-project-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,8 @@ import { StoreContext } from "@/lib/store-context";
// mobx store
import { IProjectPageStore } from "@/store/pages/project-page.store";

export const useProjectPages = (projectId: string | undefined): IProjectPageStore => {
export const useProjectPages = (): IProjectPageStore => {
const context = useContext(StoreContext);
if (context === undefined) throw new Error("useProjectPage must be used within StoreProvider");

if (!projectId) throw new Error("projectId must be passed as a property");

return context.projectPages;
};
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
const router = useRouter();
const { workspaceSlug, projectId, pageId } = router.query;
// store hooks
const { createPage, getPageById } = useProjectPages(projectId?.toString() ?? "");
const { createPage, getPageById } = useProjectPages();
const page = usePage(pageId?.toString() ?? "");
const { access, description_html, id, name } = page;
// editor markings hook
Expand Down
Loading
Loading