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:
Anmol Singh Bhatia 2024-01-25 18:00:45 +05:30 committed by GitHub
parent 5c912b8821
commit 6c6b764421
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 215 additions and 131 deletions

View file

@ -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, Planes 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 projects context. To make short work of any doc, invoke Galileo, Planes 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 Meeras love story. You could write your projects 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>
</>
);
});