Skip to content
New issue

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

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

Already on GitHub? # to your account

[WEB-904] chore: feature validation empty state #4145

Merged
merged 3 commits into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
52 changes: 52 additions & 0 deletions web/constants/empty-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ export enum EmptyStateType {
ACTIVE_CYCLE_LABEL_EMPTY_STATE = "active-cycle-label-empty-state",

DISABLED_PROJECT_INBOX = "disabled-project-inbox",
DISABLED_PROJECT_CYCLE = "disabled-project-cycle",
DISABLED_PROJECT_MODULE = "disabled-project-module",
DISABLED_PROJECT_VIEW = "disabled-project-view",
DISABLED_PROJECT_PAGE = "disabled-project-page",

INBOX_SIDEBAR_OPEN_TAB = "inbox-sidebar-open-tab",
INBOX_SIDEBAR_CLOSED_TAB = "inbox-sidebar-closed-tab",
Expand Down Expand Up @@ -634,6 +638,54 @@ const emptyStateDetails = {
text: "Manage features",
},
},
[EmptyStateType.DISABLED_PROJECT_CYCLE]: {
key: EmptyStateType.DISABLED_PROJECT_CYCLE,
title: "Cycles is not enabled for this project.",
description:
"Break work down by timeboxed chunks, work backwards from your project deadline to set dates, and make tangible progress as a team. Enable the cycles feature for your project to start using them.",
accessType: "project",
access: EUserProjectRoles.ADMIN,
path: "/empty-state/disabled-feature/cycles",
primaryButton: {
text: "Manage features",
},
},
[EmptyStateType.DISABLED_PROJECT_MODULE]: {
key: EmptyStateType.DISABLED_PROJECT_MODULE,
title: "Modules are not enabled for the project.",
description:
"A group of issues that belong to a logical, hierarchical parent form a module. Think of them as a way to track work by project milestones. Enable modules from project settings.",
accessType: "project",
access: EUserProjectRoles.ADMIN,
path: "/empty-state/disabled-feature/modules",
primaryButton: {
text: "Manage features",
},
},
[EmptyStateType.DISABLED_PROJECT_PAGE]: {
key: EmptyStateType.DISABLED_PROJECT_PAGE,
title: "Pages are not enabled for the project.",
description:
"Pages are thought spotting 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. Enable the pages feature to start creating them in your project.",
accessType: "project",
access: EUserProjectRoles.ADMIN,
path: "/empty-state/disabled-feature/pages",
primaryButton: {
text: "Manage features",
},
},
[EmptyStateType.DISABLED_PROJECT_VIEW]: {
key: EmptyStateType.DISABLED_PROJECT_VIEW,
title: "Views is not enabled for this project.",
description:
"Views are a set of saved filters that you use frequently or want easy access to. All your colleagues in a project can see everyone’s views and choose whichever suits their needs best. Enable views in the project settings to start using them.",
accessType: "project",
access: EUserProjectRoles.ADMIN,
path: "/empty-state/disabled-feature/views",
primaryButton: {
text: "Manage features",
},
},
[EmptyStateType.INBOX_SIDEBAR_OPEN_TAB]: {
key: EmptyStateType.INBOX_SIDEBAR_OPEN_TAB,
title: "No open issues",
Expand Down
15 changes: 13 additions & 2 deletions web/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const ProjectCyclesPage: NextPageWithLayout = observer(() => {
// store hooks
const { setTrackElement } = useEventTracker();
const { currentProjectCycleIds, loader } = useCycle();
const { getProjectById } = useProject();
const { getProjectById, currentProjectDetails } = useProject();
// router
const router = useRouter();
const { workspaceSlug, projectId, peekCycle } = router.query;
Expand All @@ -60,7 +60,18 @@ const ProjectCyclesPage: NextPageWithLayout = observer(() => {
updateFilters(projectId.toString(), { [key]: newValues });
};

if (!workspaceSlug || !projectId) return null;
if (!workspaceSlug || !projectId) return <></>;

// No access to cycle
if (currentProjectDetails?.cycle_view === false)
return (
<div className="flex items-center justify-center h-full w-full">
<EmptyState
type={EmptyStateType.DISABLED_PROJECT_CYCLE}
primaryButtonLink={`/${workspaceSlug}/projects/${projectId}/settings/features`}
/>
</div>
);

if (loader)
return (
Expand Down
19 changes: 17 additions & 2 deletions web/pages/[workspaceSlug]/projects/[projectId]/modules/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,23 @@ import { TModuleFilters } from "@plane/types";
// layouts
// components
import { PageHead } from "@/components/core";
import { EmptyState } from "@/components/empty-state";
import { ModulesListHeader } from "@/components/headers";
import { ModuleAppliedFiltersList, ModulesListView } from "@/components/modules";
// types
// hooks
import ModulesListMobileHeader from "@/components/modules/moduels-list-mobile-header";
import { EmptyStateType } from "@/constants/empty-state";
import { calculateTotalFilters } from "@/helpers/filter.helper";
import { useModuleFilter, useProject } from "@/hooks/store";
import { AppLayout } from "@/layouts/app-layout";
import { NextPageWithLayout } from "@/lib/types";

const ProjectModulesPage: NextPageWithLayout = observer(() => {
const router = useRouter();
const { projectId } = router.query;
const { workspaceSlug, projectId } = router.query;
// store
const { getProjectById } = useProject();
const { getProjectById, currentProjectDetails } = useProject();
const { currentProjectFilters, clearAllFilters, updateFilters } = useModuleFilter();
// derived values
const project = projectId ? getProjectById(projectId.toString()) : undefined;
Expand All @@ -38,6 +40,19 @@ const ProjectModulesPage: NextPageWithLayout = observer(() => {
[currentProjectFilters, projectId, updateFilters]
);

if (!workspaceSlug || !projectId) return <></>;

// No access to
if (currentProjectDetails?.module_view === false)
return (
<div className="flex items-center justify-center h-full w-full">
<EmptyState
type={EmptyStateType.DISABLED_PROJECT_MODULE}
primaryButtonLink={`/${workspaceSlug}/projects/${projectId}/settings/features`}
/>
</div>
);

return (
<>
<PageHead title={pageTitle} />
Expand Down
15 changes: 14 additions & 1 deletion web/pages/[workspaceSlug]/projects/[projectId]/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const ProjectPagesPage: NextPageWithLayout = observer(() => {
commandPalette: { toggleCreatePageModal },
} = useApplication();
const { setTrackElement } = useEventTracker();
const { getProjectById } = useProject();
const { getProjectById, currentProjectDetails } = useProject();
const { fetchProjectPages, fetchArchivedProjectPages, loader, archivedPageLoader, projectPageIds, archivedPageIds } =
useProjectPages();
// hooks
Expand All @@ -75,6 +75,19 @@ const ProjectPagesPage: NextPageWithLayout = observer(() => {
workspaceSlug && projectId ? () => fetchArchivedProjectPages(workspaceSlug.toString(), projectId.toString()) : null
);

if (!workspaceSlug || !projectId) return <></>;

// No access to
if (currentProjectDetails?.page_view === false)
return (
<div className="flex items-center justify-center h-full w-full">
<EmptyState
type={EmptyStateType.DISABLED_PROJECT_PAGE}
primaryButtonLink={`/${workspaceSlug}/projects/${projectId}/settings/features`}
/>
</div>
);

const currentTabValue = (tab: string | null) => {
switch (tab) {
case "Recent":
Expand Down
20 changes: 18 additions & 2 deletions web/pages/[workspaceSlug]/projects/[projectId]/views/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ import { observer } from "mobx-react";
import { useRouter } from "next/router";
// components
import { PageHead } from "@/components/core";
import { EmptyState } from "@/components/empty-state";
import { ProjectViewsHeader } from "@/components/headers";
import { ProjectViewsList } from "@/components/views";
// constants
import { EmptyStateType } from "@/constants/empty-state";
// hooks
import { useProject } from "@/hooks/store";
// layouts
Expand All @@ -15,13 +18,26 @@ import { NextPageWithLayout } from "@/lib/types";
const ProjectViewsPage: NextPageWithLayout = observer(() => {
// router
const router = useRouter();
const { projectId } = router.query;
const { workspaceSlug, projectId } = router.query;
// store
const { getProjectById } = useProject();
const { getProjectById, currentProjectDetails } = useProject();
// derived values
const project = projectId ? getProjectById(projectId.toString()) : undefined;
const pageTitle = project?.name ? `${project?.name} - Views` : undefined;

if (!workspaceSlug || !projectId) return <></>;

// No access to
if (currentProjectDetails?.issue_views_view === false)
return (
<div className="flex items-center justify-center h-full w-full">
<EmptyState
type={EmptyStateType.DISABLED_PROJECT_VIEW}
primaryButtonLink={`/${workspaceSlug}/projects/${projectId}/settings/features`}
/>
</div>
);

return (
<>
<PageHead title={pageTitle} />
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading