Skip to content
This repository has been archived by the owner on Aug 13, 2024. It is now read-only.

Commit

Permalink
wip: front dashboard
Browse files Browse the repository at this point in the history
  • Loading branch information
evoxmusic committed Dec 14, 2023
1 parent 8538505 commit dd9212a
Show file tree
Hide file tree
Showing 13 changed files with 325 additions and 168 deletions.
2 changes: 1 addition & 1 deletion backend/src/catalog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ pub async fn exec_catalog_service_validate_scripts(
Path((catalog_slug, service_slug)): Path<(String, String)>,
Json(req): Json<ExecValidateScriptRequest>,
) -> (StatusCode, Json<JobResponse>) {
let (catalog, service) = match get_catalog_and_service(&yaml_config, catalog_slug.as_str(), service_slug.as_str()) {
let (_, service) = match get_catalog_and_service(&yaml_config, catalog_slug.as_str(), service_slug.as_str()) {
Ok((catalog, service)) => (catalog, service),
Err(err) => return err
};
Expand Down
2 changes: 1 addition & 1 deletion frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="UTF-8"/>
<link href="/vite.svg" rel="icon" type="image/svg+xml"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<title>Vite + React + TS</title>
<title>Torii - Internal Developer Portal</title>
</head>
<body>
<div id="root"></div>
Expand Down
30 changes: 30 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
"preview": "vite preview"
},
"dependencies": {
"@headlessui/react": "^1.7.17",
"@heroicons/react": "^2.0.18",
"@radix-ui/react-slot": "^1.0.2",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
Expand Down
1 change: 1 addition & 0 deletions frontend/public/env.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
window.env = {};
264 changes: 264 additions & 0 deletions frontend/src/components/AppShell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
import React, {Fragment, useState} from 'react'
import {Dialog, Disclosure, Transition} from '@headlessui/react'
import {Bars3Icon, BeakerIcon, ChevronRightIcon, ClipboardIcon, HomeIcon, ShieldCheckIcon, XMarkIcon,} from '@heroicons/react/24/outline'
import {classNames} from "@/lib/utils.ts";

class NavigationItem {
name: string
href: string
icon: any
current: boolean
disabled: boolean
children?: NavigationChildrenItem[]

constructor(name: string, href: string, icon: any, current: boolean, disabled: boolean, children?: NavigationChildrenItem[]) {
this.name = name
this.href = href
this.icon = icon
this.current = current
this.disabled = disabled
this.children = children
}
}

class NavigationChildrenItem {
name: string
href: string
current: boolean

constructor(name: string, href: string, current: boolean) {
this.name = name
this.href = href
this.current = current
}

}

const navigation: NavigationItem[] = [
new NavigationItem('Dashboard', '#', HomeIcon, false, true),
new NavigationItem('Self Service', '#', BeakerIcon, true, false, [
new NavigationChildrenItem('Default', '/catalogs', true),
new NavigationChildrenItem('Toto', '/services', false),
]),
new NavigationItem('Scorecard', '#', ClipboardIcon, false, true),
new NavigationItem('Audit', '#', ShieldCheckIcon, false, true),
]


export default function AppShell() {
const [sidebarOpen, setSidebarOpen] = useState(false)
const [currentTabTitle, setCurrentTabTitle] = useState(navigation.find((item) => item.current)?.name)

function setCurrentTabHelper(navItem: NavigationItem, subItem?: NavigationChildrenItem) {
if (subItem) {
setCurrentTabTitle(`${navItem.name} > ${subItem.name}`)
} else {
setCurrentTabTitle(navItem.name)
}

// TODO change sub item selected if needed and load data
}

return (
<>
{/*
This example requires updating your template:
```
<html class="h-full bg-white">
<body class="h-full">
```
*/}
<div>
<Transition.Root show={sidebarOpen} as={Fragment}>
<Dialog as="div" className="relative z-50 lg:hidden" onClose={setSidebarOpen}>
<Transition.Child
as={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-900/80"/>
</Transition.Child>

<div className="fixed inset-0 flex">
<Transition.Child
as={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 mr-16 flex w-full max-w-xs flex-1">
<Transition.Child
as={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 left-full top-0 flex w-16 justify-center pt-5">
<button type="button" className="-m-2.5 p-2.5" 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>
{/* Sidebar component, swap this element with another sidebar if you like */}
<div className="flex grow flex-col gap-y-5 overflow-y-auto bg-white px-6 pb-2">
<div className="flex h-16 shrink-0 items-center">
{/*<img*/}
{/* className="h-8 w-auto"*/}
{/* src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=600"*/}
{/* alt="Your Company"*/}
{/*/>*/}
<h1 className="text-2xl font-semibold text-gray-900">Torii</h1>
</div>
<nav className="flex flex-1 flex-col">
<ul role="list" className="flex flex-1 flex-col gap-y-7">
<li>
<ul role="list" className="-mx-2 space-y-1">
{navigation.map((item) => getNavigationJsx(item, setCurrentTabHelper))}
</ul>
</li>
</ul>
</nav>
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</Dialog>
</Transition.Root>

{/* Static sidebar for desktop */}
<div className="hidden lg:fixed lg:inset-y-0 lg:z-50 lg:flex lg:w-72 lg:flex-col">
{/* Sidebar component, swap this element with another sidebar if you like */}
<div className="flex grow flex-col gap-y-5 overflow-y-auto border-r border-gray-200 bg-white px-6">
<div className="flex h-16 shrink-0 items-center">
{/*<img*/}
{/* className="h-8 w-auto"*/}
{/* src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=600"*/}
{/* alt="Your Company"*/}
{/*/>*/}
<h1 className="text-2xl font-semibold text-gray-900">Torii</h1>
</div>
<nav className="flex flex-1 flex-col">
<ul role="list" className="flex flex-1 flex-col gap-y-7">
<li>
<ul role="list" className="-mx-2 space-y-1">
{navigation.map((item) => getNavigationJsx(item, setCurrentTabHelper))}
</ul>
</li>
{/*<li className="-mx-6 mt-auto">*/}
{/* <a*/}
{/* href="#"*/}
{/* className="flex items-center gap-x-4 px-6 py-3 text-sm font-semibold leading-6 text-gray-900 hover:bg-gray-50"*/}
{/* >*/}
{/* <img*/}
{/* className="h-8 w-8 rounded-full bg-gray-50"*/}
{/* src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"*/}
{/* alt=""*/}
{/* />*/}
{/* <span className="sr-only">Your profile</span>*/}
{/* <span aria-hidden="true">Tom Cook</span>*/}
{/* </a>*/}
{/*</li>*/}
</ul>
</nav>
</div>
</div>

<div className="sticky top-0 z-40 flex items-center gap-x-6 bg-white px-4 py-4 shadow-sm sm:px-6 lg:hidden">
<button type="button" className="-m-2.5 p-2.5 text-gray-700 lg:hidden" onClick={() => setSidebarOpen(true)}>
<span className="sr-only">Open sidebar</span>
<Bars3Icon className="h-6 w-6" aria-hidden="true"/>
</button>
<div className="flex-1 text-sm font-semibold leading-6 text-gray-900">{currentTabTitle}</div>
{/*<a href="#">*/}
{/* <span className="sr-only">Your profile</span>*/}
{/* <img*/}
{/* className="h-8 w-8 rounded-full bg-gray-50"*/}
{/* src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"*/}
{/* alt=""*/}
{/* />*/}
{/*</a>*/}
</div>

<main className="py-10 lg:pl-72">
<div className="px-4 sm:px-6 lg:px-8">{/* Your content */}</div>
</main>
</div>
</>
)
}

function getNavigationJsx(
item: NavigationItem,
onItemClicked: (item: NavigationItem, subItem?: NavigationChildrenItem) => void,
): JSX.Element {
return <li key={item.name}>
{!item.children ? (
<a
href={item.href}
className={classNames(
item.current ? 'bg-gray-50' : 'hover:bg-gray-50',
'group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold text-gray-700',
item.disabled && 'cursor-not-allowed opacity-50'
)}
onClick={() => onItemClicked(item, undefined)}
>
<item.icon className="h-6 w-6 shrink-0 text-gray-400" aria-hidden="true"/>
{item.name}
</a>
) : (
<Disclosure as="div">
{({open}) => (
<>
<Disclosure.Button
className={classNames(
item.current ? 'bg-gray-50' : 'hover:bg-gray-50',
'flex items-center w-full text-left rounded-md p-2 gap-x-3 text-sm leading-6 font-semibold text-gray-700',
item.disabled && 'cursor-not-allowed opacity-50'
)}
>
<item.icon className="h-6 w-6 shrink-0 text-gray-400" aria-hidden="true"/>
{item.name}
<ChevronRightIcon
className={classNames(
open ? 'rotate-90 text-gray-500' : 'text-gray-400',
'ml-auto h-5 w-5 shrink-0'
)}
aria-hidden="true"
/>
</Disclosure.Button>
<Disclosure.Panel as="ul" className="mt-1 px-2">
{item.children?.map((subItem) => (
<li key={subItem.name}>
{/* 44px */}
<Disclosure.Button
as="a"
href={subItem.href}
className={classNames(
subItem.current ? 'bg-gray-50' : 'hover:bg-gray-50',
'block rounded-md py-2 pr-2 pl-9 text-sm leading-6 text-gray-700'
)}
onClick={() => onItemClicked(item, subItem)}
>
{subItem.name}
</Disclosure.Button>
</li>
))}
</Disclosure.Panel>
</>
)}
</Disclosure>
)}
</li>
}
11 changes: 11 additions & 0 deletions frontend/src/components/SelfService.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
interface Props {
catalogSlug: string
}

export default function SelfService({catalogSlug}: Props) {
return (
<p id="zero-state">
Select a catalog to get started {catalogSlug}.
</p>
)
}
Loading

0 comments on commit dd9212a

Please sign in to comment.