feat: views added to cycles, fix: overflowing issues
This commit is contained in:
commit
9c18f6fc71
94 changed files with 5316 additions and 2277 deletions
|
|
@ -15,16 +15,14 @@ const DefaultTopBar: React.FC = () => {
|
|||
<a className="flex">
|
||||
<span className="sr-only">Plane</span>
|
||||
<h2 className="text-2xl font-semibold">
|
||||
Plan<span className="text-indigo-600">e</span>
|
||||
Plan<span className="text-theme">e</span>
|
||||
</h2>
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
{user && (
|
||||
<div>
|
||||
<p className="text-sm text-gray-500">
|
||||
logged in as {user.first_name}
|
||||
</p>
|
||||
<p className="text-sm text-gray-500">logged in as {user.first_name}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
21
apps/app/layouts/Navbar/Header.tsx
Normal file
21
apps/app/layouts/Navbar/Header.tsx
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
type Props = {
|
||||
breadcrumbs?: JSX.Element;
|
||||
left?: JSX.Element;
|
||||
right?: JSX.Element;
|
||||
};
|
||||
|
||||
const Header: React.FC<Props> = ({ breadcrumbs, left, right }) => {
|
||||
return (
|
||||
<>
|
||||
<div className="w-full bg-gray-50 border-b border-gray-200 flex justify-between items-center px-5 py-4">
|
||||
<div className="flex items-center gap-2">
|
||||
{breadcrumbs}
|
||||
{left}
|
||||
</div>
|
||||
{right}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Header;
|
||||
|
|
@ -10,8 +10,6 @@ import authenticationService from "lib/services/authentication.service";
|
|||
import useUser from "lib/hooks/useUser";
|
||||
import useTheme from "lib/hooks/useTheme";
|
||||
import useToast from "lib/hooks/useToast";
|
||||
// components
|
||||
import CreateProjectModal from "components/project/CreateProjectModal";
|
||||
// headless ui
|
||||
import { Dialog, Disclosure, Menu, Transition } from "@headlessui/react";
|
||||
// icons
|
||||
|
|
@ -108,7 +106,6 @@ const userLinks = [
|
|||
|
||||
const Sidebar: React.FC = () => {
|
||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
||||
const [isCreateProjectModal, setCreateProjectModal] = useState(false);
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
|
|
@ -124,7 +121,6 @@ const Sidebar: React.FC = () => {
|
|||
|
||||
return (
|
||||
<nav className="h-full">
|
||||
<CreateProjectModal isOpen={isCreateProjectModal} setIsOpen={setCreateProjectModal} />
|
||||
<Transition.Root show={sidebarOpen} as={React.Fragment}>
|
||||
<Dialog as="div" className="relative z-40 md:hidden" onClose={setSidebarOpen}>
|
||||
<Transition.Child
|
||||
|
|
@ -557,7 +553,13 @@ const Sidebar: React.FC = () => {
|
|||
<button
|
||||
type="button"
|
||||
className="group flex justify-center items-center gap-2 w-full rounded-md p-2 text-sm bg-theme text-white"
|
||||
onClick={() => setCreateProjectModal(true)}
|
||||
onClick={() => {
|
||||
const e = new KeyboardEvent("keydown", {
|
||||
ctrlKey: true,
|
||||
key: "p",
|
||||
});
|
||||
document.dispatchEvent(e);
|
||||
}}
|
||||
>
|
||||
<PlusIcon className="h-5 w-5" />
|
||||
{!sidebarCollapse && "Create Project"}
|
||||
|
|
|
|||
201
apps/app/layouts/Navbar/main-sidebar.tsx
Normal file
201
apps/app/layouts/Navbar/main-sidebar.tsx
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
import React, { useState } from "react";
|
||||
// next
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
// hooks
|
||||
import useTheme from "lib/hooks/useTheme";
|
||||
// components
|
||||
import ProjectsList from "components/sidebar/projects-list";
|
||||
import WorkspaceOptions from "components/sidebar/workspace-options";
|
||||
// headless ui
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
// icons
|
||||
import {
|
||||
ArrowPathIcon,
|
||||
Bars3Icon,
|
||||
Cog6ToothIcon,
|
||||
RectangleStackIcon,
|
||||
UserGroupIcon,
|
||||
XMarkIcon,
|
||||
ArrowLongLeftIcon,
|
||||
QuestionMarkCircleIcon,
|
||||
} from "@heroicons/react/24/outline";
|
||||
// constants
|
||||
import { classNames } from "constants/common";
|
||||
|
||||
const navigation = (projectId: string) => [
|
||||
{
|
||||
name: "Issues",
|
||||
href: `/projects/${projectId}/issues`,
|
||||
icon: RectangleStackIcon,
|
||||
},
|
||||
{
|
||||
name: "Cycles",
|
||||
href: `/projects/${projectId}/cycles`,
|
||||
icon: ArrowPathIcon,
|
||||
},
|
||||
{
|
||||
name: "Members",
|
||||
href: `/projects/${projectId}/members`,
|
||||
icon: UserGroupIcon,
|
||||
},
|
||||
{
|
||||
name: "Settings",
|
||||
href: `/projects/${projectId}/settings`,
|
||||
icon: Cog6ToothIcon,
|
||||
},
|
||||
];
|
||||
|
||||
const Sidebar: React.FC = () => {
|
||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const { projectId } = router.query;
|
||||
|
||||
const { collapsed: sidebarCollapse, toggleCollapsed } = useTheme();
|
||||
|
||||
return (
|
||||
<nav className="h-screen">
|
||||
<Transition.Root show={sidebarOpen} as={React.Fragment}>
|
||||
<Dialog as="div" className="relative z-40 md:hidden" onClose={setSidebarOpen}>
|
||||
<Transition.Child
|
||||
as={React.Fragment}
|
||||
enter="transition-opacity ease-linear duration-300"
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
leave="transition-opacity ease-linear duration-300"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="fixed inset-0 bg-gray-600 bg-opacity-75" />
|
||||
</Transition.Child>
|
||||
|
||||
<div className="fixed inset-0 z-40 flex">
|
||||
<Transition.Child
|
||||
as={React.Fragment}
|
||||
enter="transition ease-in-out duration-300 transform"
|
||||
enterFrom="-translate-x-full"
|
||||
enterTo="translate-x-0"
|
||||
leave="transition ease-in-out duration-300 transform"
|
||||
leaveFrom="translate-x-0"
|
||||
leaveTo="-translate-x-full"
|
||||
>
|
||||
<Dialog.Panel className="relative flex w-full max-w-xs flex-1 flex-col bg-white">
|
||||
<Transition.Child
|
||||
as={React.Fragment}
|
||||
enter="ease-in-out duration-300"
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
leave="ease-in-out duration-300"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="absolute top-0 right-0 -mr-12 pt-2">
|
||||
<button
|
||||
type="button"
|
||||
className="ml-1 flex h-10 w-10 items-center justify-center rounded-full focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white"
|
||||
onClick={() => setSidebarOpen(false)}
|
||||
>
|
||||
<span className="sr-only">Close sidebar</span>
|
||||
<XMarkIcon className="h-6 w-6 text-white" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
</Transition.Child>
|
||||
<div className="h-0 flex-1 overflow-y-auto pt-5 pb-4">
|
||||
<nav className="mt-5 space-y-1 px-2">
|
||||
{projectId &&
|
||||
navigation(projectId as string).map((item) => (
|
||||
<Link href={item.href} key={item.name}>
|
||||
<a
|
||||
className={classNames(
|
||||
item.href === router.asPath
|
||||
? "bg-gray-100 text-gray-900"
|
||||
: "text-gray-600 hover:bg-gray-50 hover:text-gray-900",
|
||||
"group flex items-center px-2 py-2 text-base font-medium rounded-md"
|
||||
)}
|
||||
>
|
||||
<item.icon
|
||||
className={classNames(
|
||||
item.href === router.asPath
|
||||
? "text-gray-500"
|
||||
: "text-gray-400 group-hover:text-gray-500",
|
||||
"mr-4 flex-shrink-0 h-6 w-6"
|
||||
)}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{item.name}
|
||||
</a>
|
||||
</Link>
|
||||
))}
|
||||
</nav>
|
||||
</div>
|
||||
</Dialog.Panel>
|
||||
</Transition.Child>
|
||||
<div className="w-14 flex-shrink-0" />
|
||||
</div>
|
||||
</Dialog>
|
||||
</Transition.Root>
|
||||
<div
|
||||
className={`${
|
||||
sidebarCollapse ? "" : "w-auto md:w-64"
|
||||
} h-full hidden md:inset-y-0 md:flex md:flex-col`}
|
||||
>
|
||||
<div className="h-full flex flex-1 flex-col border-r border-gray-200">
|
||||
<div className="h-full flex flex-1 flex-col pt-2">
|
||||
<WorkspaceOptions sidebarCollapse={sidebarCollapse} />
|
||||
<ProjectsList navigation={navigation} sidebarCollapse={sidebarCollapse} />
|
||||
<div
|
||||
className={`px-2 py-2 w-full self-baseline flex items-center bg-primary ${
|
||||
sidebarCollapse ? "flex-col-reverse" : ""
|
||||
}`}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
className={`flex items-center gap-3 px-2 py-2 text-xs font-medium rounded-md text-gray-500 hover:bg-gray-100 hover:text-gray-900 outline-none ${
|
||||
sidebarCollapse ? "justify-center w-full" : ""
|
||||
}`}
|
||||
onClick={() => toggleCollapsed()}
|
||||
>
|
||||
<ArrowLongLeftIcon
|
||||
className={`h-4 w-4 text-gray-500 group-hover:text-gray-900 flex-shrink-0 duration-300 ${
|
||||
sidebarCollapse ? "rotate-180" : ""
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={`flex items-center gap-3 px-2 py-2 text-xs font-medium rounded-md text-gray-500 hover:bg-gray-100 hover:text-gray-900 outline-none ${
|
||||
sidebarCollapse ? "justify-center w-full" : ""
|
||||
}`}
|
||||
onClick={() => {
|
||||
const e = new KeyboardEvent("keydown", {
|
||||
ctrlKey: true,
|
||||
key: "h",
|
||||
});
|
||||
document.dispatchEvent(e);
|
||||
}}
|
||||
title="Help"
|
||||
>
|
||||
<QuestionMarkCircleIcon className="h-4 w-4 text-gray-500" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="sticky top-0 z-10 bg-white pl-1 pt-1 sm:pl-3 sm:pt-3 md:hidden">
|
||||
<button
|
||||
type="button"
|
||||
className="-ml-0.5 -mt-0.5 inline-flex h-12 w-12 items-center justify-center rounded-md text-gray-500 hover:text-gray-900 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500"
|
||||
onClick={() => setSidebarOpen(true)}
|
||||
>
|
||||
<span className="sr-only">Open sidebar</span>
|
||||
<Bars3Icon className="h-6 w-6" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
|
||||
export default Sidebar;
|
||||
41
apps/app/layouts/Navbar/settings-sidebar.tsx
Normal file
41
apps/app/layouts/Navbar/settings-sidebar.tsx
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
// next
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
type Props = {
|
||||
links: Array<{
|
||||
label: string;
|
||||
href: string;
|
||||
}>;
|
||||
};
|
||||
|
||||
const SettingsSidebar: React.FC<Props> = ({ links }) => {
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<nav className="h-screen w-72 border-r border-gray-200">
|
||||
<div className="h-full p-2 pt-4">
|
||||
<h2 className="text-lg font-medium leading-5">Settings</h2>
|
||||
<div className="mt-3">
|
||||
{links.map((link, index) => (
|
||||
<h4 key={index}>
|
||||
<Link href={link.href}>
|
||||
<a
|
||||
className={`${
|
||||
link.href === router.asPath
|
||||
? "bg-theme text-white"
|
||||
: "hover:bg-indigo-100 focus:bg-indigo-100"
|
||||
} flex items-center gap-3 p-2 text-xs font-medium rounded-md outline-none`}
|
||||
>
|
||||
{link.label}
|
||||
</a>
|
||||
</Link>
|
||||
</h4>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
|
||||
export default SettingsSidebar;
|
||||
Loading…
Add table
Add a link
Reference in a new issue