Skip to content

Commit

Permalink
feat: restructure navigation for console (#2484)
Browse files Browse the repository at this point in the history
  • Loading branch information
wesbillman authored Aug 23, 2024
1 parent cafa316 commit a60bce5
Show file tree
Hide file tree
Showing 14 changed files with 212 additions and 209 deletions.
3 changes: 2 additions & 1 deletion frontend/e2e/events.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { expect, ftlTest } from './ftl-test'

ftlTest('defaults to the events page', async ({ page }) => {
await page.goto('http://localhost:8892')
const eventsNavItem = page.getByRole('link', { name: 'Events' })

await expect(eventsNavItem).toHaveClass(/bg-indigo-600 text-white/)
await expect(eventsNavItem).toHaveClass(/bg-indigo-700 text-white/)
})
11 changes: 7 additions & 4 deletions frontend/e2e/ftl-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ const ftlTest = base.extend<{
page: any
}>({
page: async ({ page }, use) => {
await page.goto('http://localhost:8892')
await page.goto('http://localhost:8892/modules')
await page.waitForFunction(() => {
const element = document.querySelector('#deployments-count')
return element && element.textContent?.trim() === '2'
})
const timeItem = document.querySelector('li#module-tree-item-time');
const echoItem = document.querySelector('li#module-tree-item-echo');
return timeItem !== null && echoItem !== null;
});

await use(page)
},
})

export { ftlTest, expect }

6 changes: 3 additions & 3 deletions frontend/index.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!doctype html>
<html lang="en">
<html lang="en" class="h-full">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
Expand All @@ -8,8 +8,8 @@
<link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;700&display=swap" rel="stylesheet" />
</head>

<body class="bg-white dark:bg-slate-800 h-screen w-full overflow-hidden">
<div id="root"></div>
<body class="bg-white h-full w-full">
<div id="root" class="h-full"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
3 changes: 3 additions & 0 deletions frontend/src/features/infrastructure/InfrastructurePage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const InfrastructurePage = () => {
return <>Infrastructure</>
}
21 changes: 21 additions & 0 deletions frontend/src/features/modules/ModulesPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useMemo } from 'react'
import { useSchema } from '../../api/schema/use-schema'
import { ModulesTree } from './ModulesTree'
import { moduleTreeFromSchema } from './module.utils'

export const ModulesPage = () => {
const schema = useSchema()
const tree = useMemo(() => moduleTreeFromSchema(schema?.data || []), [schema?.data])

return (
<div className='flex h-full'>
<div className='w-64 h-full'>
<ModulesTree modules={tree} />
</div>

<div className='flex-1 py-2 px-4'>
<p>Content</p>
</div>
</div>
)
}
65 changes: 65 additions & 0 deletions frontend/src/features/modules/ModulesTree.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Disclosure, DisclosureButton, DisclosurePanel } from '@headlessui/react'
import { ChevronRightIcon } from '@heroicons/react/24/outline'
import { classNames } from '../../utils'
import type { ModuleTreeItem } from './module.utils'

export const ModulesTree = ({ modules }: { modules: ModuleTreeItem[] }) => {
return (
<div className='flex grow flex-col h-full gap-y-5 overflow-y-auto border-r border-gray-200 dark:border-gray-600 py-2 px-6'>
<nav className='flex flex-1 flex-col'>
<ul className='flex flex-1 flex-col gap-y-7'>
<li>
<ul className='-mx-2'>
{modules.map((item) => (
<li key={item.name} id={`module-tree-item-${item.name}`}>
{!item.children ? (
<a
href={item.href}
className={classNames(
item.current ? '' : 'hover:bg-gray-50 hover:dark:bg-gray-700',
'group flex gap-x-3 rounded-md px-2 text-sm font-semibold leading-6',
)}
>
<item.icon aria-hidden='true' className='size-3 shrink-0' />
{item.name}
</a>
) : (
<Disclosure as='div' defaultOpen={item.expanded}>
<DisclosureButton
className={classNames(
item.current ? '' : 'hover:bg-gray-50 hover:dark:bg-gray-700',
'group flex w-full items-center gap-x-2 rounded-md px-2 text-left text-sm font-semibold leading-6',
)}
>
<item.icon aria-hidden='true' className='size-4 shrink-0 ' />
{item.name}
<ChevronRightIcon aria-hidden='true' className='ml-auto h-5 w-5 shrink-0 group-data-[open]:rotate-90 group-data-[open]:text-gray-500' />
</DisclosureButton>
<DisclosurePanel as='ul' className='px-2'>
{item.children.map((subItem) => (
<li key={subItem.name}>
<DisclosureButton
as='a'
href={subItem.href}
className={classNames(
subItem.current ? '' : 'hover:bg-gray-50 hover:dark:bg-gray-700',
'group flex items-center gap-x-2 rounded-md pl-4 pr-2 text-sm leading-6',
)}
>
<subItem.icon aria-hidden='true' className='size-4 shrink-0' />
{subItem.name}
</DisclosureButton>
</li>
))}
</DisclosurePanel>
</Disclosure>
)}
</li>
))}
</ul>
</li>
</ul>
</nav>
</div>
)
}
52 changes: 52 additions & 0 deletions frontend/src/features/modules/module.utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
import {
ArrowDownOnSquareStackIcon,
BellAlertIcon,
BoltIcon,
CircleStackIcon,
CodeBracketIcon,
CogIcon,
LockClosedIcon,
RectangleGroupIcon,
} from '@heroicons/react/24/outline'
import type { ForwardRefExoticComponent, SVGProps } from 'react'
import type { Module } from '../../protos/xyz/block/ftl/v1/console/console_pb'
import type { PullSchemaResponse } from '../../protos/xyz/block/ftl/v1/ftl_pb'
import type { MetadataCalls, Ref } from '../../protos/xyz/block/ftl/v1/schema/schema_pb'
import { verbCalls } from '../verbs/verb.utils'

Expand Down Expand Up @@ -55,3 +67,43 @@ export const deploymentKeyModuleName = (deploymentKey: string) => {
}
return null
}

interface ModuleTreeChild {
name: string
href: string
icon: ForwardRefExoticComponent<SVGProps<SVGSVGElement> & { title?: string; titleId?: string }>
current?: boolean
}

export interface ModuleTreeItem {
name: string
href?: string
icon: ForwardRefExoticComponent<SVGProps<SVGSVGElement> & { title?: string; titleId?: string }>
current: boolean
expanded?: boolean
children?: ModuleTreeChild[]
}

export const moduleTreeFromSchema = (schema: PullSchemaResponse[]) => {
const tree: ModuleTreeItem[] = []

for (const module of schema) {
tree.push({
name: module.moduleName,
icon: RectangleGroupIcon,
current: false,
expanded: module.moduleName === 'echo',
children: [
{ name: 'Data', href: '#', icon: CodeBracketIcon },
{ name: 'Verb', href: '#', icon: BoltIcon },
{ name: 'Database', href: '#', icon: CircleStackIcon },
{ name: 'Config', href: '#', icon: CogIcon },
{ name: 'Secret', href: '#', icon: LockClosedIcon },
{ name: 'FSM', href: '#', icon: ArrowDownOnSquareStackIcon },
{ name: 'Pubsub', href: '#', icon: BellAlertIcon },
],
})
}

return tree
}
43 changes: 6 additions & 37 deletions frontend/src/layout/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,13 @@
import { Bars3Icon } from '@heroicons/react/24/outline'
import { useState } from 'react'
import { Outlet } from 'react-router-dom'
import useLocalStorage from '../hooks/use-local-storage'
import { bgColor, textColor } from '../utils'
import { Notification } from './Notification'
import { SidePanel } from './SidePanel'
import MobileNavigation from './navigation/MobileNavigation'
import { Navigation } from './navigation/Navigation'

export const Layout = () => {
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false)
const [isCollapsed, setIsCollapsed] = useLocalStorage('isNavCollapsed', false)

return (
<>
<div className={`h-screen ${bgColor} ${textColor}`}>
<div className={`${isMobileMenuOpen ? 'block' : 'hidden'} sm:hidden`}>
<MobileNavigation onClose={() => setIsMobileMenuOpen(false)} />
</div>

<div className={'flex justify-between items-center py-2 px-4 bg-indigo-600 sm:hidden'}>
<div className='flex shrink-0 items-center rounded-md hover:bg-indigo-700'>
<span className='text-2xl font-medium text-white'>FTL</span>
<span className='px-2 text-pink-400 text-2xl font-medium'></span>
</div>
<button type='button' title='open' onClick={() => setIsMobileMenuOpen(true)}>
<Bars3Icon className='h-6 w-6 text-white hover:bg-indigo-700' />
</button>
</div>

<div className={`flex flex-col h-full sm:grid ${isCollapsed ? 'sm:grid-cols-[4rem,1fr]' : 'sm:grid-cols-[13rem,1fr]'}`}>
<Navigation isCollapsed={isCollapsed} setIsCollapsed={setIsCollapsed} />
<main className='overflow-hidden flex-1'>
<Outlet />
</main>
</div>
</div>

<SidePanel />
<Notification />
</>
<div className='min-w-[800px] min-h-[600px] max-w-full max-h-full h-full flex flex-col dark:bg-gray-800 bg-white text-gray-700 dark:text-gray-200'>
<Navigation />
<main className='flex-1'>
<Outlet />
</main>
</div>
)
}
1 change: 0 additions & 1 deletion frontend/src/layout/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export * from './Layout'
export * from './Page'
59 changes: 0 additions & 59 deletions frontend/src/layout/navigation/MobileNavigation.tsx

This file was deleted.

Loading

0 comments on commit a60bce5

Please sign in to comment.