forked from github/plane
chore: update all layout selections (#2641)
This commit is contained in:
parent
41e9d5d7e3
commit
79cad16aba
@ -1,6 +1,6 @@
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { GanttChartSquare, LayoutGrid, List, Plus } from "lucide-react";
|
import { Plus } from "lucide-react";
|
||||||
// mobx store
|
// mobx store
|
||||||
import { useMobxStore } from "lib/mobx/store-provider";
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
// hooks
|
// hooks
|
||||||
@ -8,23 +8,9 @@ import useLocalStorage from "hooks/use-local-storage";
|
|||||||
// ui
|
// ui
|
||||||
import { Breadcrumbs, Button, Tooltip, DiceIcon } from "@plane/ui";
|
import { Breadcrumbs, Button, Tooltip, DiceIcon } from "@plane/ui";
|
||||||
// helper
|
// helper
|
||||||
import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper";
|
|
||||||
import { renderEmoji } from "helpers/emoji.helper";
|
import { renderEmoji } from "helpers/emoji.helper";
|
||||||
|
// constants
|
||||||
const moduleViewOptions: { type: "list" | "grid" | "gantt_chart"; icon: any }[] = [
|
import { MODULE_VIEW_LAYOUTS } from "constants/module";
|
||||||
{
|
|
||||||
type: "list",
|
|
||||||
icon: List,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "grid",
|
|
||||||
icon: LayoutGrid,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "gantt_chart",
|
|
||||||
icon: GanttChartSquare,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const ModulesListHeader: React.FC = observer(() => {
|
export const ModulesListHeader: React.FC = observer(() => {
|
||||||
// router
|
// router
|
||||||
@ -68,23 +54,26 @@ export const ModulesListHeader: React.FC = observer(() => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
{moduleViewOptions.map((option) => (
|
<div className="flex items-center gap-1 p-1 rounded bg-custom-background-80">
|
||||||
<Tooltip
|
{MODULE_VIEW_LAYOUTS.map((layout) => (
|
||||||
key={option.type}
|
<Tooltip key={layout.key} tooltipContent={layout.title}>
|
||||||
tooltipContent={<span className="capitalize">{replaceUnderscoreIfSnakeCase(option.type)} Layout</span>}
|
<button
|
||||||
position="bottom"
|
type="button"
|
||||||
>
|
className={`w-7 h-[22px] rounded grid place-items-center transition-all hover:bg-custom-background-100 overflow-hidden group ${
|
||||||
<button
|
modulesView == layout.key ? "bg-custom-background-100 shadow-custom-shadow-2xs" : ""
|
||||||
type="button"
|
}`}
|
||||||
className={`grid h-7 w-7 place-items-center rounded p-1 outline-none duration-300 hover:bg-custom-sidebar-background-80 ${
|
onClick={() => setModulesView(layout.key)}
|
||||||
modulesView === option.type ? "bg-custom-sidebar-background-80" : "text-custom-sidebar-text-200"
|
>
|
||||||
}`}
|
<layout.icon
|
||||||
onClick={() => setModulesView(option.type)}
|
strokeWidth={2}
|
||||||
>
|
className={`h-3.5 w-3.5 ${
|
||||||
<option.icon className="h-3.5 w-3.5" />
|
modulesView == layout.key ? "text-custom-text-100" : "text-custom-text-200"
|
||||||
</button>
|
}`}
|
||||||
</Tooltip>
|
/>
|
||||||
))}
|
</button>
|
||||||
|
</Tooltip>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
<Button
|
<Button
|
||||||
variant="primary"
|
variant="primary"
|
||||||
prependIcon={<Plus />}
|
prependIcon={<Plus />}
|
||||||
|
@ -82,7 +82,7 @@ export const PrioritySelect: React.FC<Props> = ({
|
|||||||
: value === "low"
|
: value === "low"
|
||||||
? "text-green-500"
|
? "text-green-500"
|
||||||
: "text-custom-text-200"
|
: "text-custom-text-200"
|
||||||
} ${value === "urgent" && highlightUrgentPriority ? "text-white" : "text-red-500"}`}
|
} ${value === "urgent" ? (highlightUrgentPriority ? "text-white" : "text-red-500") : ""}`}
|
||||||
/>
|
/>
|
||||||
{showTitle && <span className="capitalize text-xs">{value}</span>}
|
{showTitle && <span className="capitalize text-xs">{value}</span>}
|
||||||
</div>
|
</div>
|
||||||
|
@ -23,18 +23,21 @@ export const CYCLE_TAB_LIST = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const CYCLE_VIEWS = [
|
export const CYCLE_VIEW_LAYOUTS = [
|
||||||
{
|
{
|
||||||
key: "list",
|
key: "list",
|
||||||
icon: List,
|
icon: List,
|
||||||
|
title: "List layout",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "board",
|
key: "board",
|
||||||
icon: LayoutGrid,
|
icon: LayoutGrid,
|
||||||
|
title: "Grid layout",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "gantt",
|
key: "gantt",
|
||||||
icon: GanttChartSquare,
|
icon: GanttChartSquare,
|
||||||
|
title: "Gantt layout",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { GanttChartSquare, LayoutGrid, List } from "lucide-react";
|
||||||
// types
|
// types
|
||||||
import { TModuleStatus } from "types";
|
import { TModuleStatus } from "types";
|
||||||
|
|
||||||
@ -51,3 +52,21 @@ export const MODULE_STATUS: {
|
|||||||
bgColor: "bg-red-50",
|
bgColor: "bg-red-50",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const MODULE_VIEW_LAYOUTS: { key: "list" | "grid" | "gantt_chart"; icon: any; title: string }[] = [
|
||||||
|
{
|
||||||
|
key: "list",
|
||||||
|
icon: List,
|
||||||
|
title: "List layout",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "grid",
|
||||||
|
icon: LayoutGrid,
|
||||||
|
title: "Grid layout",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "gantt_chart",
|
||||||
|
icon: GanttChartSquare,
|
||||||
|
title: "Gantt layout",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
37
web/constants/page.ts
Normal file
37
web/constants/page.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { LayoutGrid, List } from "lucide-react";
|
||||||
|
|
||||||
|
export const PAGE_VIEW_LAYOUTS = [
|
||||||
|
{
|
||||||
|
key: "list",
|
||||||
|
icon: List,
|
||||||
|
title: "List layout",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "detailed",
|
||||||
|
icon: LayoutGrid,
|
||||||
|
title: "Detailed layout",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const PAGE_TABS_LIST: { key: string; title: string }[] = [
|
||||||
|
{
|
||||||
|
key: "recent",
|
||||||
|
title: "Recent",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "all",
|
||||||
|
title: "All",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "favorites",
|
||||||
|
title: "Favorites",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "created-by-me",
|
||||||
|
title: "Created by me",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "created-by-others",
|
||||||
|
title: "Created by others",
|
||||||
|
},
|
||||||
|
];
|
@ -31,7 +31,7 @@ export const UserAuthWrapper: FC<IUserAuthWrapper> = (props) => {
|
|||||||
|
|
||||||
if (!currentUser && !error) {
|
if (!currentUser && !error) {
|
||||||
return (
|
return (
|
||||||
<div className="h-screen grid place-items-center p-4">
|
<div className="h-screen grid place-items-center p-4 bg-custom-background-100">
|
||||||
<div className="flex flex-col items-center gap-3 text-center">
|
<div className="flex flex-col items-center gap-3 text-center">
|
||||||
<Spinner />
|
<Spinner />
|
||||||
</div>
|
</div>
|
||||||
|
@ -20,11 +20,9 @@ import emptyCycle from "public/empty-state/cycle.svg";
|
|||||||
import { TCycleView, TCycleLayout } from "types";
|
import { TCycleView, TCycleLayout } from "types";
|
||||||
import { NextPageWithLayout } from "types/app";
|
import { NextPageWithLayout } from "types/app";
|
||||||
// constants
|
// constants
|
||||||
import { CYCLE_TAB_LIST, CYCLE_VIEWS } from "constants/cycle";
|
import { CYCLE_TAB_LIST, CYCLE_VIEW_LAYOUTS } from "constants/cycle";
|
||||||
// lib cookie
|
// lib cookie
|
||||||
import { setLocalStorage, getLocalStorage } from "lib/local-storage";
|
import { setLocalStorage, getLocalStorage } from "lib/local-storage";
|
||||||
// helpers
|
|
||||||
import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper";
|
|
||||||
|
|
||||||
const ProjectCyclesPage: NextPageWithLayout = observer(() => {
|
const ProjectCyclesPage: NextPageWithLayout = observer(() => {
|
||||||
const [createModal, setCreateModal] = useState(false);
|
const [createModal, setCreateModal] = useState(false);
|
||||||
@ -118,7 +116,7 @@ const ProjectCyclesPage: NextPageWithLayout = observer(() => {
|
|||||||
handleCurrentView(CYCLE_TAB_LIST[i].key as TCycleView);
|
handleCurrentView(CYCLE_TAB_LIST[i].key as TCycleView);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex flex-col sm:flex-row gap-4 justify-between border-b border-custom-border-300 px-4 sm:px-5 pb-4 sm:pb-0">
|
<div className="flex flex-col sm:flex-row gap-4 justify-between items-end sm:items-center border-b border-custom-border-200 px-4 sm:px-5 pb-4 sm:pb-0">
|
||||||
<Tab.List as="div" className="flex items-center overflow-x-scroll">
|
<Tab.List as="div" className="flex items-center overflow-x-scroll">
|
||||||
{CYCLE_TAB_LIST.map((tab) => (
|
{CYCLE_TAB_LIST.map((tab) => (
|
||||||
<Tab
|
<Tab
|
||||||
@ -133,28 +131,28 @@ const ProjectCyclesPage: NextPageWithLayout = observer(() => {
|
|||||||
</Tab>
|
</Tab>
|
||||||
))}
|
))}
|
||||||
</Tab.List>
|
</Tab.List>
|
||||||
{CYCLE_VIEWS && CYCLE_VIEWS.length > 0 && cycleStore?.cycleView != "active" && (
|
{cycleStore?.cycleView != "active" && (
|
||||||
<div className="justify-end sm:justify-start flex items-center gap-x-1">
|
<div className="flex items-center gap-1 p-1 rounded bg-custom-background-80">
|
||||||
{CYCLE_VIEWS.map((view) => {
|
{CYCLE_VIEW_LAYOUTS.map((layout) => {
|
||||||
if (view.key === "gantt" && cycleStore?.cycleView === "draft") return null;
|
if (layout.key === "gantt" && cycleStore?.cycleView === "draft") return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip
|
<Tooltip key={layout.key} tooltipContent={layout.title}>
|
||||||
key={view.key}
|
|
||||||
tooltipContent={
|
|
||||||
<span className="capitalize">{replaceUnderscoreIfSnakeCase(view.key)} Layout</span>
|
|
||||||
}
|
|
||||||
position="bottom"
|
|
||||||
>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={`grid h-7 w-7 place-items-center rounded p-1 outline-none duration-300 hover:bg-custom-sidebar-background-80 ${
|
className={`w-7 h-[22px] rounded grid place-items-center transition-all hover:bg-custom-background-100 overflow-hidden group ${
|
||||||
cycleStore?.cycleLayout === view.key
|
cycleStore?.cycleLayout == layout.key
|
||||||
? "bg-custom-sidebar-background-80"
|
? "bg-custom-background-100 shadow-custom-shadow-2xs"
|
||||||
: "text-custom-sidebar-text-200"
|
: ""
|
||||||
}`}
|
}`}
|
||||||
onClick={() => handleCurrentLayout(view.key as TCycleLayout)}
|
onClick={() => handleCurrentLayout(layout.key as TCycleLayout)}
|
||||||
>
|
>
|
||||||
<view.icon className="h-3.5 w-3.5" />
|
<layout.icon
|
||||||
|
strokeWidth={2}
|
||||||
|
className={`h-3.5 w-3.5 ${
|
||||||
|
cycleStore?.cycleLayout == layout.key ? "text-custom-text-100" : "text-custom-text-200"
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
</button>
|
</button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
);
|
);
|
||||||
|
@ -5,16 +5,18 @@ import { Tab } from "@headlessui/react";
|
|||||||
// hooks
|
// hooks
|
||||||
import useLocalStorage from "hooks/use-local-storage";
|
import useLocalStorage from "hooks/use-local-storage";
|
||||||
import useUserAuth from "hooks/use-user-auth";
|
import useUserAuth from "hooks/use-user-auth";
|
||||||
// icons
|
|
||||||
import { LayoutGrid, List } from "lucide-react";
|
|
||||||
// layouts
|
// layouts
|
||||||
import { AppLayout } from "layouts/app-layout";
|
import { AppLayout } from "layouts/app-layout";
|
||||||
// components
|
// components
|
||||||
import { RecentPagesList, CreateUpdatePageModal, TPagesListProps } from "components/pages";
|
import { RecentPagesList, CreateUpdatePageModal, TPagesListProps } from "components/pages";
|
||||||
import { PagesHeader } from "components/headers";
|
import { PagesHeader } from "components/headers";
|
||||||
|
// ui
|
||||||
|
import { Tooltip } from "@plane/ui";
|
||||||
// types
|
// types
|
||||||
import { TPageViewProps } from "types";
|
import { TPageViewProps } from "types";
|
||||||
import { NextPageWithLayout } from "types/app";
|
import { NextPageWithLayout } from "types/app";
|
||||||
|
// constants
|
||||||
|
import { PAGE_TABS_LIST, PAGE_VIEW_LAYOUTS } from "constants/page";
|
||||||
|
|
||||||
const AllPagesList = dynamic<TPagesListProps>(() => import("components/pages").then((a) => a.AllPagesList), {
|
const AllPagesList = dynamic<TPagesListProps>(() => import("components/pages").then((a) => a.AllPagesList), {
|
||||||
ssr: false,
|
ssr: false,
|
||||||
@ -32,8 +34,6 @@ const OtherPagesList = dynamic<TPagesListProps>(() => import("components/pages")
|
|||||||
ssr: false,
|
ssr: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const tabsList = ["Recent", "All", "Favorites", "Created by me", "Created by others"];
|
|
||||||
|
|
||||||
const ProjectPagesPage: NextPageWithLayout = () => {
|
const ProjectPagesPage: NextPageWithLayout = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId } = router.query;
|
const { workspaceSlug, projectId } = router.query;
|
||||||
@ -77,25 +77,25 @@ const ProjectPagesPage: NextPageWithLayout = () => {
|
|||||||
<div className="space-y-5 p-8 h-full overflow-hidden flex flex-col">
|
<div className="space-y-5 p-8 h-full overflow-hidden flex flex-col">
|
||||||
<div className="flex gap-4 justify-between">
|
<div className="flex gap-4 justify-between">
|
||||||
<h3 className="text-2xl font-semibold text-custom-text-100">Pages</h3>
|
<h3 className="text-2xl font-semibold text-custom-text-100">Pages</h3>
|
||||||
<div className="flex gap-x-1">
|
<div className="flex items-center gap-1 p-1 rounded bg-custom-background-80">
|
||||||
<button
|
{PAGE_VIEW_LAYOUTS.map((layout) => (
|
||||||
type="button"
|
<Tooltip key={layout.key} tooltipContent={layout.title}>
|
||||||
className={`grid h-7 w-7 place-items-center rounded p-1 outline-none duration-300 hover:bg-custom-background-80 ${
|
<button
|
||||||
viewType === "list" ? "bg-custom-background-80" : ""
|
type="button"
|
||||||
}`}
|
className={`w-7 h-[22px] rounded grid place-items-center transition-all hover:bg-custom-background-100 overflow-hidden group ${
|
||||||
onClick={() => setViewType("list")}
|
viewType == layout.key ? "bg-custom-background-100 shadow-custom-shadow-2xs" : ""
|
||||||
>
|
}`}
|
||||||
<List className="h-4 w-4" />
|
onClick={() => setViewType(layout.key as TPageViewProps)}
|
||||||
</button>
|
>
|
||||||
<button
|
<layout.icon
|
||||||
type="button"
|
strokeWidth={2}
|
||||||
className={`grid h-7 w-7 place-items-center rounded p-1 outline-none duration-300 hover:bg-custom-background-80 ${
|
className={`h-3.5 w-3.5 ${
|
||||||
viewType === "detailed" ? "bg-custom-background-80" : ""
|
viewType == layout.key ? "text-custom-text-100" : "text-custom-text-200"
|
||||||
}`}
|
}`}
|
||||||
onClick={() => setViewType("detailed")}
|
/>
|
||||||
>
|
</button>
|
||||||
<LayoutGrid className="h-4 w-4" />
|
</Tooltip>
|
||||||
</button>
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Tab.Group
|
<Tab.Group
|
||||||
@ -121,9 +121,9 @@ const ProjectPagesPage: NextPageWithLayout = () => {
|
|||||||
>
|
>
|
||||||
<Tab.List as="div" className="mb-6 flex items-center justify-between">
|
<Tab.List as="div" className="mb-6 flex items-center justify-between">
|
||||||
<div className="flex gap-4 items-center flex-wrap">
|
<div className="flex gap-4 items-center flex-wrap">
|
||||||
{tabsList.map((tab, index) => (
|
{PAGE_TABS_LIST.map((tab) => (
|
||||||
<Tab
|
<Tab
|
||||||
key={`${tab}-${index}`}
|
key={tab.key}
|
||||||
className={({ selected }) =>
|
className={({ selected }) =>
|
||||||
`rounded-full border px-5 py-1.5 text-sm outline-none ${
|
`rounded-full border px-5 py-1.5 text-sm outline-none ${
|
||||||
selected
|
selected
|
||||||
@ -132,7 +132,7 @@ const ProjectPagesPage: NextPageWithLayout = () => {
|
|||||||
}`
|
}`
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{tab}
|
{tab.title}
|
||||||
</Tab>
|
</Tab>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user