forked from github/plane
style: new empty state ui (#2923)
This commit is contained in:
parent
db510dcfcd
commit
d5853405ca
113
web/components/common/new-empty-state.tsx
Normal file
113
web/components/common/new-empty-state.tsx
Normal file
@ -0,0 +1,113 @@
|
||||
import React, { useState } from "react";
|
||||
|
||||
import Image from "next/image";
|
||||
|
||||
// ui
|
||||
import { Button } from "@plane/ui";
|
||||
|
||||
type Props = {
|
||||
title: string;
|
||||
description?: React.ReactNode;
|
||||
image: any;
|
||||
comicBox?: {
|
||||
direction: "left" | "right";
|
||||
title: string;
|
||||
description: string;
|
||||
extraPadding?: boolean;
|
||||
};
|
||||
primaryButton?: {
|
||||
icon?: any;
|
||||
text: string;
|
||||
onClick: () => void;
|
||||
};
|
||||
secondaryButton?: React.ReactNode;
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
export const NewEmptyState: React.FC<Props> = ({
|
||||
title,
|
||||
description,
|
||||
image,
|
||||
primaryButton,
|
||||
secondaryButton,
|
||||
disabled = false,
|
||||
comicBox,
|
||||
}) => {
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
|
||||
const handleMouseEnter = () => {
|
||||
setIsHovered(true);
|
||||
};
|
||||
|
||||
const handleMouseLeave = () => {
|
||||
setIsHovered(false);
|
||||
};
|
||||
return (
|
||||
<div className=" flex flex-col justify-center items-center h-full w-full ">
|
||||
<div className="border border-custom-border-200 rounded-xl px-10 py-7 flex flex-col gap-5 max-w-6xl m-5 md:m-16 shadow-sm">
|
||||
<h3 className="font-semibold text-2xl">{title}</h3>
|
||||
{description && <p className=" text-lg">{description}</p>}
|
||||
<div className="relative w-full max-w-6xl">
|
||||
<Image src={image} className="w-52 sm:w-60" alt={primaryButton?.text} />
|
||||
</div>
|
||||
|
||||
<div className="flex justify-center items-start relative">
|
||||
{primaryButton && (
|
||||
<Button
|
||||
className={`max-w-min m-3 relative !px-6 ${comicBox?.direction === "left" ? "flex-row-reverse" : ""}`}
|
||||
size="lg"
|
||||
variant="primary"
|
||||
onClick={primaryButton.onClick}
|
||||
disabled={disabled}
|
||||
>
|
||||
{primaryButton.text}
|
||||
<div
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
className={`bg-blue-300 absolute ${
|
||||
comicBox?.direction === "left" ? "left-0 ml-2" : "right-0 mr-2"
|
||||
} h-2.5 w-2.5 z-10 rounded-full animate-ping`}
|
||||
/>
|
||||
<div
|
||||
className={`bg-blue-400/40 absolute ${
|
||||
comicBox?.direction === "left" ? "left-0 ml-2.5" : "right-0 mr-2.5"
|
||||
} h-1.5 w-1.5 rounded-full`}
|
||||
/>
|
||||
</Button>
|
||||
)}
|
||||
{comicBox &&
|
||||
isHovered &&
|
||||
(comicBox.direction === "right" ? (
|
||||
<div
|
||||
className={`flex max-w-sm absolute top-0 left-1/2 ${
|
||||
comicBox?.extraPadding ? "ml-[125px]" : "ml-[90px]"
|
||||
} pb-5`}
|
||||
>
|
||||
<div className="relative w-0 h-0 border-t-[11px] mt-5 border-custom-border-200 border-b-[11px] border-r-[11px] border-y-transparent">
|
||||
<div className="absolute top-[-10px] right-[-12px] w-0 h-0 border-t-[10px] border-custom-background-100 border-b-[10px] border-r-[10px] border-y-transparent" />
|
||||
</div>
|
||||
<div className="border border-custom-border-200 rounded-md bg-custom-background-100">
|
||||
<h1 className="p-5">
|
||||
<h3 className="font-semibold text-lg">{comicBox?.title}</h3>
|
||||
<h4 className="text-sm mt-1">{comicBox?.description}</h4>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-row-reverse max-w-sm absolute top-0 right-1/2 mr-[90px] pb-5">
|
||||
<div className="relative w-0 h-0 border-t-[11px] mt-5 border-custom-border-200 border-b-[11px] border-l-[11px] border-y-transparent">
|
||||
<div className="absolute top-[-10px] left-[-12px] w-0 h-0 border-t-[10px] border-custom-background-100 border-b-[10px] border-l-[10px] border-y-transparent" />
|
||||
</div>
|
||||
<div className="border border-custom-border-200 rounded-md bg-custom-background-100">
|
||||
<h1 className="p-5">
|
||||
<h3 className="font-semibold text-lg">{comicBox?.title}</h3>
|
||||
<h4 className="text-sm mt-1">{comicBox?.description}</h4>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
@ -5,8 +5,9 @@ import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// components
|
||||
import { EmptyState } from "components/common";
|
||||
// assets
|
||||
import emptyIssue from "public/empty-state/issue.svg";
|
||||
import emptyIssue from "public/empty-state/empty_issues.webp";
|
||||
import { EProjectStore } from "store/command-palette.store";
|
||||
import { NewEmptyState } from "components/common/new-empty-state";
|
||||
|
||||
export const ProjectEmptyState: React.FC = observer(() => {
|
||||
const {
|
||||
@ -16,12 +17,18 @@ export const ProjectEmptyState: React.FC = observer(() => {
|
||||
|
||||
return (
|
||||
<div className="h-full w-full grid place-items-center">
|
||||
<EmptyState
|
||||
title="Project issues will appear here"
|
||||
description="Issues help you track individual pieces of work. With Issues, keep track of what's going on, who is working on it, and what's done."
|
||||
<NewEmptyState
|
||||
title="Create an issue and assign it to someone, even yourself"
|
||||
description="Think of issues as jobs, tasks, work, or JTBD. Which we like.An issue and its sub-issues are usually time-based actionables assigned to members of your team. Your team creates, assigns, and completes issues to move your project towards its goal."
|
||||
image={emptyIssue}
|
||||
comicBox={{
|
||||
title: "Issues are building blocks in Plane.",
|
||||
direction: "left",
|
||||
description:
|
||||
"Redesign the Plane UI, Rebrand the company, or Launch the new fuel injection system are examples of issues that likely have sub-issues.",
|
||||
}}
|
||||
primaryButton={{
|
||||
text: "New issue",
|
||||
text: "Create your first issue",
|
||||
icon: <PlusIcon className="h-3 w-3" strokeWidth={2} />,
|
||||
onClick: () => {
|
||||
setTrackElement("PROJECT_EMPTY_STATE");
|
||||
|
@ -68,20 +68,23 @@ export const CycleLayoutRoot: React.FC = observer(() => {
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{/* <CycleEmptyState workspaceSlug={workspaceSlug} projectId={projectId} cycleId={cycleId} /> */}
|
||||
<div className="h-full w-full overflow-auto">
|
||||
{activeLayout === "list" ? (
|
||||
<CycleListLayout />
|
||||
) : activeLayout === "kanban" ? (
|
||||
<CycleKanBanLayout />
|
||||
) : activeLayout === "calendar" ? (
|
||||
<CycleCalendarLayout />
|
||||
) : activeLayout === "gantt_chart" ? (
|
||||
<CycleGanttLayout />
|
||||
) : activeLayout === "spreadsheet" ? (
|
||||
<CycleSpreadsheetLayout />
|
||||
) : null}
|
||||
</div>
|
||||
{Object.keys(getIssues ?? {}).length == 0 ? (
|
||||
<CycleEmptyState workspaceSlug={workspaceSlug} projectId={projectId} cycleId={cycleId} />
|
||||
) : (
|
||||
<div className="h-full w-full overflow-auto">
|
||||
{activeLayout === "list" ? (
|
||||
<CycleListLayout />
|
||||
) : activeLayout === "kanban" ? (
|
||||
<CycleKanBanLayout />
|
||||
) : activeLayout === "calendar" ? (
|
||||
<CycleCalendarLayout />
|
||||
) : activeLayout === "gantt_chart" ? (
|
||||
<CycleGanttLayout />
|
||||
) : activeLayout === "spreadsheet" ? (
|
||||
<CycleSpreadsheetLayout />
|
||||
) : null}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
@ -53,20 +53,24 @@ export const ModuleLayoutRoot: React.FC = observer(() => {
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{Object.keys(getIssues ?? {}).length == 0 ? (
|
||||
<ModuleEmptyState workspaceSlug={workspaceSlug} projectId={projectId} moduleId={moduleId} />
|
||||
) : (
|
||||
<div className="h-full w-full overflow-auto">
|
||||
{activeLayout === "list" ? (
|
||||
<ModuleListLayout />
|
||||
) : activeLayout === "kanban" ? (
|
||||
<ModuleKanBanLayout />
|
||||
) : activeLayout === "calendar" ? (
|
||||
<ModuleCalendarLayout />
|
||||
) : activeLayout === "gantt_chart" ? (
|
||||
<ModuleGanttLayout />
|
||||
) : activeLayout === "spreadsheet" ? (
|
||||
<ModuleSpreadsheetLayout />
|
||||
) : null}
|
||||
</div>
|
||||
)}
|
||||
{/* <ModuleEmptyState workspaceSlug={workspaceSlug} projectId={projectId} moduleId={moduleId} /> */}
|
||||
<div className="h-full w-full overflow-auto">
|
||||
{activeLayout === "list" ? (
|
||||
<ModuleListLayout />
|
||||
) : activeLayout === "kanban" ? (
|
||||
<ModuleKanBanLayout />
|
||||
) : activeLayout === "calendar" ? (
|
||||
<ModuleCalendarLayout />
|
||||
) : activeLayout === "gantt_chart" ? (
|
||||
<ModuleGanttLayout />
|
||||
) : activeLayout === "spreadsheet" ? (
|
||||
<ModuleSpreadsheetLayout />
|
||||
) : null}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
@ -53,20 +53,23 @@ export const ProjectLayoutRoot: React.FC = observer(() => {
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{/* {(activeLayout === "list" || activeLayout === "spreadsheet") && issueCount === 0 && <ProjectEmptyState />} */}
|
||||
<div className="w-full h-full relative overflow-auto">
|
||||
{activeLayout === "list" ? (
|
||||
<ListLayout />
|
||||
) : activeLayout === "kanban" ? (
|
||||
<KanBanLayout />
|
||||
) : activeLayout === "calendar" ? (
|
||||
<CalendarLayout />
|
||||
) : activeLayout === "gantt_chart" ? (
|
||||
<GanttLayout />
|
||||
) : activeLayout === "spreadsheet" ? (
|
||||
<ProjectSpreadsheetLayout />
|
||||
) : null}
|
||||
</div>
|
||||
{Object.keys(getIssues ?? {}).length == 0 ? (
|
||||
<ProjectEmptyState />
|
||||
) : (
|
||||
<div className="w-full h-full relative overflow-auto">
|
||||
{activeLayout === "list" ? (
|
||||
<ListLayout />
|
||||
) : activeLayout === "kanban" ? (
|
||||
<KanBanLayout />
|
||||
) : activeLayout === "calendar" ? (
|
||||
<CalendarLayout />
|
||||
) : activeLayout === "gantt_chart" ? (
|
||||
<GanttLayout />
|
||||
) : activeLayout === "spreadsheet" ? (
|
||||
<ProjectSpreadsheetLayout />
|
||||
) : null}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
@ -11,7 +11,8 @@ import { EmptyState } from "components/common";
|
||||
// ui
|
||||
import { Loader } from "@plane/ui";
|
||||
// assets
|
||||
import emptyModule from "public/empty-state/module.svg";
|
||||
import emptyModule from "public/empty-state/empty_modules.webp";
|
||||
import { NewEmptyState } from "components/common/new-empty-state";
|
||||
|
||||
export const ModulesListView: React.FC = observer(() => {
|
||||
const router = useRouter();
|
||||
@ -78,13 +79,19 @@ export const ModulesListView: React.FC = observer(() => {
|
||||
{modulesView === "gantt_chart" && <ModulesListGanttChartView />}
|
||||
</>
|
||||
) : (
|
||||
<EmptyState
|
||||
title="Manage your project with modules"
|
||||
description="Modules are smaller, focused projects that help you group and organize issues."
|
||||
<NewEmptyState
|
||||
title="Map your project milestones to Modules and track aggregated work easily."
|
||||
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. They have their own periods and deadlines as well as analytics to help you see how close or far you are from a milestone."
|
||||
image={emptyModule}
|
||||
comicBox={{
|
||||
title: "Modules help group work by hierarchy.",
|
||||
direction: "right",
|
||||
description:
|
||||
"A cart module, a chassis module, and a warehouse module are all good example of this grouping.",
|
||||
}}
|
||||
primaryButton={{
|
||||
icon: <Plus className="h-4 w-4" />,
|
||||
text: "New Module",
|
||||
text: "Build your first module",
|
||||
onClick: () => commandPaletteStore.toggleCreateModuleModal(true),
|
||||
}}
|
||||
/>
|
||||
|
@ -12,6 +12,8 @@ import { CompletedIssuesGraph, IssuesList, IssuesPieChart, IssuesStats } from "c
|
||||
import { Button } from "@plane/ui";
|
||||
// images
|
||||
import emptyDashboard from "public/empty-state/dashboard.svg";
|
||||
import { NewEmptyState } from "components/common/new-empty-state";
|
||||
import emptyProject from "public/empty-state/dashboard_empty_project.webp";
|
||||
|
||||
export const WorkspaceDashboardView = observer(() => {
|
||||
// router
|
||||
@ -19,7 +21,12 @@ export const WorkspaceDashboardView = observer(() => {
|
||||
const { workspaceSlug } = router.query;
|
||||
// store
|
||||
|
||||
const { user: userStore, project: projectStore, commandPalette: commandPaletteStore, trackEvent: { setTrackElement } } = useMobxStore();
|
||||
const {
|
||||
user: userStore,
|
||||
project: projectStore,
|
||||
commandPalette: commandPaletteStore,
|
||||
trackEvent: { setTrackElement },
|
||||
} = useMobxStore();
|
||||
|
||||
const user = userStore.currentUser;
|
||||
const projects = workspaceSlug ? projectStore.projects[workspaceSlug.toString()] : null;
|
||||
@ -65,22 +72,23 @@ export const WorkspaceDashboardView = observer(() => {
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="bg-custom-primary-100/5 flex justify-between gap-5 md:gap-8">
|
||||
<div className="p-5 md:p-8 pr-0">
|
||||
<h5 className="text-xl font-semibold">Create a project</h5>
|
||||
<p className="mt-2 mb-5">Manage your projects by creating issues, cycles, modules, views and pages.</p>
|
||||
<Button variant="primary" size="sm" onClick={() => {
|
||||
setTrackElement("DASHBOARD_PAGE");
|
||||
commandPaletteStore.toggleCreateProjectModal(true)
|
||||
}
|
||||
}>
|
||||
Create Project
|
||||
</Button>
|
||||
</div>
|
||||
<div className="hidden md:block self-end overflow-hidden pt-8">
|
||||
<Image src={emptyDashboard} alt="Empty Dashboard" />
|
||||
</div>
|
||||
</div>
|
||||
<NewEmptyState
|
||||
image={emptyProject}
|
||||
title="Overview of your projects, activity, and metrics"
|
||||
description="When you have created a project and have issues assigned, you will see metrics, activity, and things you care about here. This is personalized to your role in projects, so project admins will see more than members."
|
||||
comicBox={{
|
||||
title: "Everything starts with a project in Plane",
|
||||
direction: "right",
|
||||
description: "A project could be a product’s roadmap, a marketing campaign, or launching a new car.",
|
||||
}}
|
||||
primaryButton={{
|
||||
text: "Build your first project",
|
||||
onClick: () => {
|
||||
setTrackElement("DASHBOARD_PAGE");
|
||||
commandPaletteStore.toggleCreateProjectModal(true);
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)
|
||||
) : null}
|
||||
</div>
|
||||
|
@ -7,9 +7,10 @@ import { ProjectCard } from "components/project";
|
||||
import { EmptyState } from "components/project/empty-state";
|
||||
import { Loader } from "@plane/ui";
|
||||
// images
|
||||
import emptyProject from "public/empty-state/Project_full_screen.svg";
|
||||
import emptyProject from "public/empty-state/empty_project.webp";
|
||||
// icons
|
||||
import { Plus } from "lucide-react";
|
||||
import { NewEmptyState } from "components/common/new-empty-state";
|
||||
|
||||
export interface IProjectCardList {
|
||||
workspaceSlug: string;
|
||||
@ -18,7 +19,11 @@ export interface IProjectCardList {
|
||||
export const ProjectCardList: FC<IProjectCardList> = observer((props) => {
|
||||
const { workspaceSlug } = props;
|
||||
// store
|
||||
const { project: projectStore, commandPalette: commandPaletteStore, trackEvent: { setTrackElement } } = useMobxStore();
|
||||
const {
|
||||
project: projectStore,
|
||||
commandPalette: commandPaletteStore,
|
||||
trackEvent: { setTrackElement },
|
||||
} = useMobxStore();
|
||||
|
||||
const projects = workspaceSlug ? projectStore.projects[workspaceSlug.toString()] : null;
|
||||
|
||||
@ -50,17 +55,21 @@ export const ProjectCardList: FC<IProjectCardList> = observer((props) => {
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<EmptyState
|
||||
<NewEmptyState
|
||||
image={emptyProject}
|
||||
title="Why no fly 😔"
|
||||
description="Let’s take off, cap’n!"
|
||||
title="Start a Project"
|
||||
description="Think of each project as the parent for goal-oriented work. Projects are where Jobs, Cycles, and Modules live and, along with your colleagues, help you achieve that goal."
|
||||
comicBox={{
|
||||
title: "Everything starts with a project in Plane",
|
||||
direction: "right",
|
||||
description: "A project could be a product’s roadmap, a marketing campaign, or launching a new car.",
|
||||
}}
|
||||
primaryButton={{
|
||||
icon: <Plus className="h-4 w-4" />,
|
||||
text: "Start something new",
|
||||
text: "Start your first project",
|
||||
onClick: () => {
|
||||
setTrackElement("PROJECTS_EMPTY_STATE");
|
||||
commandPaletteStore.toggleCreateProjectModal(true)
|
||||
}
|
||||
commandPaletteStore.toggleCreateProjectModal(true);
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
@ -17,13 +17,14 @@ import emptyAnalytics from "public/empty-state/analytics.svg";
|
||||
import { ANALYTICS_TABS } from "constants/analytics";
|
||||
// type
|
||||
import { NextPageWithLayout } from "types/app";
|
||||
import { NewEmptyState } from "components/common/new-empty-state";
|
||||
|
||||
const AnalyticsPage: NextPageWithLayout = observer(() => {
|
||||
// store
|
||||
const {
|
||||
project: { workspaceProjects },
|
||||
commandPalette: { toggleCreateProjectModal },
|
||||
trackEvent: { setTrackElement }
|
||||
trackEvent: { setTrackElement },
|
||||
} = useMobxStore();
|
||||
|
||||
return (
|
||||
@ -36,10 +37,11 @@ const AnalyticsPage: NextPageWithLayout = observer(() => {
|
||||
<Tab
|
||||
key={tab.key}
|
||||
className={({ selected }) =>
|
||||
`rounded-3xl border border-custom-border-200 px-4 py-2 text-xs hover:bg-custom-background-80 ${selected ? "bg-custom-background-80" : ""
|
||||
`rounded-3xl border border-custom-border-200 px-4 py-2 text-xs hover:bg-custom-background-80 ${
|
||||
selected ? "bg-custom-background-80" : ""
|
||||
}`
|
||||
}
|
||||
onClick={() => { }}
|
||||
onClick={() => {}}
|
||||
>
|
||||
{tab.title}
|
||||
</Tab>
|
||||
@ -66,8 +68,8 @@ const AnalyticsPage: NextPageWithLayout = observer(() => {
|
||||
text: "New Project",
|
||||
onClick: () => {
|
||||
setTrackElement("ANALYTICS_EMPTY_STATE");
|
||||
toggleCreateProjectModal(true)
|
||||
}
|
||||
toggleCreateProjectModal(true);
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
|
@ -14,7 +14,7 @@ import { CyclesView, ActiveCycleDetails, CycleCreateUpdateModal } from "componen
|
||||
import { EmptyState } from "components/common";
|
||||
import { Tooltip } from "@plane/ui";
|
||||
// images
|
||||
import emptyCycle from "public/empty-state/cycle.svg";
|
||||
import emptyCycle from "public/empty-state/empty_cycles.webp";
|
||||
// types
|
||||
import { TCycleView, TCycleLayout } from "types";
|
||||
import { NextPageWithLayout } from "types/app";
|
||||
@ -22,13 +22,14 @@ import { NextPageWithLayout } from "types/app";
|
||||
import { CYCLE_TAB_LIST, CYCLE_VIEW_LAYOUTS } from "constants/cycle";
|
||||
// lib cookie
|
||||
import { setLocalStorage, getLocalStorage } from "lib/local-storage";
|
||||
import { NewEmptyState } from "components/common/new-empty-state";
|
||||
// TODO: use-local-storage hook instead of lib file.
|
||||
|
||||
const ProjectCyclesPage: NextPageWithLayout = observer(() => {
|
||||
const [createModal, setCreateModal] = useState(false);
|
||||
// store
|
||||
const { project: projectStore, cycle: cycleStore } = useMobxStore();
|
||||
const { projectCycles } = cycleStore
|
||||
const { projectCycles } = cycleStore;
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, peekCycle } = router.query;
|
||||
@ -73,7 +74,7 @@ const ProjectCyclesPage: NextPageWithLayout = observer(() => {
|
||||
|
||||
const cycleView = cycleStore?.cycleView;
|
||||
const cycleLayout = cycleStore?.cycleLayout;
|
||||
const totalCycles = projectCycles?.length ?? 0
|
||||
const totalCycles = projectCycles?.length ?? 0;
|
||||
|
||||
if (!workspaceSlug || !projectId) return null;
|
||||
|
||||
@ -87,13 +88,19 @@ const ProjectCyclesPage: NextPageWithLayout = observer(() => {
|
||||
/>
|
||||
{totalCycles === 0 ? (
|
||||
<div className="h-full grid place-items-center">
|
||||
<EmptyState
|
||||
title="Plan your project with cycles"
|
||||
description="Cycle is a custom time period in which a team works to complete items on their backlog."
|
||||
<NewEmptyState
|
||||
title="Group and timebox your work in Cycles."
|
||||
description="Break work down by timeboxed chunks, work backwards from your project deadline to set dates, and make tangible progress as a team."
|
||||
image={emptyCycle}
|
||||
comicBox={{
|
||||
title: "Cycles are repetitive time-boxes.",
|
||||
direction: "right",
|
||||
description:
|
||||
"A sprint, an iteration, and or any other term you use for weekly or fortnightly tracking of work is a cycle.",
|
||||
}}
|
||||
primaryButton={{
|
||||
icon: <Plus className="h-4 w-4" />,
|
||||
text: "New Cycle",
|
||||
text: "Set your first cycle",
|
||||
onClick: () => {
|
||||
setCreateModal(true);
|
||||
},
|
||||
|
BIN
web/public/empty-state/dashboard_empty_project.webp
Normal file
BIN
web/public/empty-state/dashboard_empty_project.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
BIN
web/public/empty-state/empty_cycles.webp
Normal file
BIN
web/public/empty-state/empty_cycles.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
BIN
web/public/empty-state/empty_issues.webp
Normal file
BIN
web/public/empty-state/empty_issues.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 59 KiB |
BIN
web/public/empty-state/empty_modules.webp
Normal file
BIN
web/public/empty-state/empty_modules.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
BIN
web/public/empty-state/empty_project.webp
Normal file
BIN
web/public/empty-state/empty_project.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
Loading…
Reference in New Issue
Block a user