chore: empty state and project active cycle improvement (#3472)
* chore: pages empty state improvement * chore: workspace all issues empty state improvement * chore: profile issue empty state improvement * chore: empty state sm size updated * chore: project view empty state image updated * chore: dashboard widgets permission uodated * chore: draft issues and project issue empty state image * chore: active cycle label updated
This commit is contained in:
parent
5c912b8821
commit
6c6b764421
15 changed files with 215 additions and 131 deletions
|
|
@ -5,13 +5,14 @@ import { Tab } from "@headlessui/react";
|
|||
import useSWR from "swr";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// hooks
|
||||
import { useUser } from "hooks/store";
|
||||
import { useApplication, useUser } from "hooks/store";
|
||||
import useLocalStorage from "hooks/use-local-storage";
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// layouts
|
||||
import { AppLayout } from "layouts/app-layout";
|
||||
// components
|
||||
import { RecentPagesList, CreateUpdatePageModal } from "components/pages";
|
||||
import { EmptyState, getEmptyStateImagePath } from "components/empty-state";
|
||||
import { PagesHeader } from "components/headers";
|
||||
import { Spinner } from "@plane/ui";
|
||||
// types
|
||||
|
|
@ -19,6 +20,7 @@ import { NextPageWithLayout } from "lib/types";
|
|||
// constants
|
||||
import { PAGE_TABS_LIST } from "constants/page";
|
||||
import { useProjectPages } from "hooks/store/use-project-page";
|
||||
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||
|
||||
const AllPagesList = dynamic<any>(() => import("components/pages").then((a) => a.AllPagesList), {
|
||||
ssr: false,
|
||||
|
|
@ -47,9 +49,17 @@ const ProjectPagesPage: NextPageWithLayout = observer(() => {
|
|||
// states
|
||||
const [createUpdatePageModal, setCreateUpdatePageModal] = useState(false);
|
||||
// store
|
||||
const { currentUser, currentUserLoader } = useUser();
|
||||
const {
|
||||
currentUser,
|
||||
currentUserLoader,
|
||||
membership: { currentProjectRole },
|
||||
} = useUser();
|
||||
const {
|
||||
commandPalette: { toggleCreatePageModal },
|
||||
} = useApplication();
|
||||
|
||||
const { fetchProjectPages, fetchArchivedProjectPages, loader } = useProjectPages();
|
||||
const { fetchProjectPages, fetchArchivedProjectPages, loader, archivedPageLoader, projectPageIds, archivedPageIds } =
|
||||
useProjectPages();
|
||||
// hooks
|
||||
const {} = useUserAuth({ user: currentUser, isLoading: currentUserLoader });
|
||||
// local storage
|
||||
|
|
@ -84,7 +94,11 @@ const ProjectPagesPage: NextPageWithLayout = observer(() => {
|
|||
}
|
||||
};
|
||||
|
||||
if (loader)
|
||||
const EmptyStateImagePath = getEmptyStateImagePath("onboarding", "pages", currentUser?.theme.theme === "light");
|
||||
|
||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||
|
||||
if (loader || archivedPageLoader)
|
||||
return (
|
||||
<div className="flex items-center justify-center h-full w-full">
|
||||
<Spinner />
|
||||
|
|
@ -93,79 +107,100 @@ const ProjectPagesPage: NextPageWithLayout = observer(() => {
|
|||
|
||||
return (
|
||||
<>
|
||||
{workspaceSlug && projectId && (
|
||||
<CreateUpdatePageModal
|
||||
isOpen={createUpdatePageModal}
|
||||
handleClose={() => setCreateUpdatePageModal(false)}
|
||||
projectId={projectId.toString()}
|
||||
{projectPageIds && archivedPageIds && projectPageIds.length + archivedPageIds.length > 0 ? (
|
||||
<>
|
||||
{workspaceSlug && projectId && (
|
||||
<CreateUpdatePageModal
|
||||
isOpen={createUpdatePageModal}
|
||||
handleClose={() => setCreateUpdatePageModal(false)}
|
||||
projectId={projectId.toString()}
|
||||
/>
|
||||
)}
|
||||
<div className="flex h-full flex-col space-y-5 overflow-hidden p-6">
|
||||
<div className="flex justify-between gap-4">
|
||||
<h3 className="text-2xl font-semibold text-custom-text-100">Pages</h3>
|
||||
</div>
|
||||
<Tab.Group
|
||||
as={Fragment}
|
||||
defaultIndex={currentTabValue(pageTab)}
|
||||
onChange={(i) => {
|
||||
switch (i) {
|
||||
case 0:
|
||||
return setPageTab("Recent");
|
||||
case 1:
|
||||
return setPageTab("All");
|
||||
case 2:
|
||||
return setPageTab("Favorites");
|
||||
case 3:
|
||||
return setPageTab("Private");
|
||||
case 4:
|
||||
return setPageTab("Shared");
|
||||
case 5:
|
||||
return setPageTab("Archived");
|
||||
default:
|
||||
return setPageTab("All");
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Tab.List as="div" className="mb-6 flex items-center justify-between">
|
||||
<div className="flex flex-wrap items-center gap-4">
|
||||
{PAGE_TABS_LIST.map((tab) => (
|
||||
<Tab
|
||||
key={tab.key}
|
||||
className={({ selected }) =>
|
||||
`rounded-full border px-5 py-1.5 text-sm outline-none ${
|
||||
selected
|
||||
? "border-custom-primary bg-custom-primary text-white"
|
||||
: "border-custom-border-200 bg-custom-background-100 hover:bg-custom-background-90"
|
||||
}`
|
||||
}
|
||||
>
|
||||
{tab.title}
|
||||
</Tab>
|
||||
))}
|
||||
</div>
|
||||
</Tab.List>
|
||||
<Tab.Panels as={Fragment}>
|
||||
<Tab.Panel as="div" className="h-full space-y-5 overflow-y-auto">
|
||||
<RecentPagesList />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel as="div" className="h-full overflow-hidden">
|
||||
<AllPagesList />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel as="div" className="h-full overflow-hidden">
|
||||
<FavoritePagesList />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel as="div" className="h-full overflow-hidden">
|
||||
<PrivatePagesList />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel as="div" className="h-full overflow-hidden">
|
||||
<SharedPagesList />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel as="div" className="h-full overflow-hidden">
|
||||
<ArchivedPagesList />
|
||||
</Tab.Panel>
|
||||
</Tab.Panels>
|
||||
</Tab.Group>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<EmptyState
|
||||
image={EmptyStateImagePath}
|
||||
title="Write a note, a doc, or a full knowledge base. Get Galileo, Plane’s AI assistant, to help you get started"
|
||||
description="Pages are thoughts potting space in Plane. Take down meeting notes, format them easily, embed issues, lay them out using a library of components, and keep them all in your project’s context. To make short work of any doc, invoke Galileo, Plane’s AI, with a shortcut or the click of a button."
|
||||
primaryButton={{
|
||||
text: "Create your first page",
|
||||
onClick: () => toggleCreatePageModal(true),
|
||||
}}
|
||||
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.",
|
||||
}}
|
||||
size="lg"
|
||||
disabled={!isEditingAllowed}
|
||||
/>
|
||||
)}
|
||||
<div className="flex h-full flex-col space-y-5 overflow-hidden p-6">
|
||||
<div className="flex justify-between gap-4">
|
||||
<h3 className="text-2xl font-semibold text-custom-text-100">Pages</h3>
|
||||
</div>
|
||||
<Tab.Group
|
||||
as={Fragment}
|
||||
defaultIndex={currentTabValue(pageTab)}
|
||||
onChange={(i) => {
|
||||
switch (i) {
|
||||
case 0:
|
||||
return setPageTab("Recent");
|
||||
case 1:
|
||||
return setPageTab("All");
|
||||
case 2:
|
||||
return setPageTab("Favorites");
|
||||
case 3:
|
||||
return setPageTab("Private");
|
||||
case 4:
|
||||
return setPageTab("Shared");
|
||||
case 5:
|
||||
return setPageTab("Archived");
|
||||
default:
|
||||
return setPageTab("All");
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Tab.List as="div" className="mb-6 flex items-center justify-between">
|
||||
<div className="flex flex-wrap items-center gap-4">
|
||||
{PAGE_TABS_LIST.map((tab) => (
|
||||
<Tab
|
||||
key={tab.key}
|
||||
className={({ selected }) =>
|
||||
`rounded-full border px-5 py-1.5 text-sm outline-none ${
|
||||
selected
|
||||
? "border-custom-primary bg-custom-primary text-white"
|
||||
: "border-custom-border-200 bg-custom-background-100 hover:bg-custom-background-90"
|
||||
}`
|
||||
}
|
||||
>
|
||||
{tab.title}
|
||||
</Tab>
|
||||
))}
|
||||
</div>
|
||||
</Tab.List>
|
||||
<Tab.Panels as={Fragment}>
|
||||
<Tab.Panel as="div" className="h-full space-y-5 overflow-y-auto">
|
||||
<RecentPagesList />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel as="div" className="h-full overflow-hidden">
|
||||
<AllPagesList />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel as="div" className="h-full overflow-hidden">
|
||||
<FavoritePagesList />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel as="div" className="h-full overflow-hidden">
|
||||
<PrivatePagesList />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel as="div" className="h-full overflow-hidden">
|
||||
<SharedPagesList />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel as="div" className="h-full overflow-hidden">
|
||||
<ArchivedPagesList />
|
||||
</Tab.Panel>
|
||||
</Tab.Panels>
|
||||
</Tab.Group>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue