import { Disclosure, DisclosureButton, DisclosurePanel, Menu, MenuButton, MenuItem, MenuItems, } from "@headlessui/react"; import { Bars3Icon, BeakerIcon, ChartBarIcon, Cog6ToothIcon, PlayIcon, RectangleStackIcon, XMarkIcon, } from "@heroicons/react/24/outline"; import { Link, Outlet, useLocation, useMatches } from "react-router"; import { ErrorState } from "../components/state"; import { ToastProvider } from "../components/toast"; import { DemoModeProvider } from "../lib/demo-mode"; import { useToggleDemoMode } from "../lib/mutations"; import { useAuthMe } from "../lib/queries"; const allNavigation = [ { name: "Workflows", href: "/workflows", icon: RectangleStackIcon, demoOnly: true }, { name: "Runs", href: "/runs", icon: PlayIcon, demoOnly: false }, { name: "Insights", href: "/insights", icon: ChartBarIcon, demoOnly: true }, { name: "Settings", href: "/settings", icon: Cog6ToothIcon, demoOnly: false }, ]; export function getVisibleNavigation(demoMode: boolean) { return allNavigation.filter((item) => !item.demoOnly || demoMode); } function classNames(...classes: Array) { return classes.filter(Boolean).join(" "); } export default function AppShell() { const { data: auth, error, isLoading } = useAuthMe(); const { pathname } = useLocation(); const matches = useMatches(); const toggleDemoModeMutation = useToggleDemoMode(); if (isLoading && !auth) { return
; } if (error || !auth) { return (
); } const { user, provider, demoMode } = auth; const navigation = getVisibleNavigation(demoMode); const currentNav = navigation.find((item) => pathname.startsWith(item.href)); const title = currentNav?.name ?? ""; const lastMatch = matches[matches.length - 1]; const handle = lastMatch?.handle as { headerExtra?: React.ReactNode } | undefined; const headerExtra = handle?.headerExtra; const hideHeader = matches.some((m) => (m.handle as { hideHeader?: boolean } | undefined)?.hideHeader); const wide = matches.some((m) => (m.handle as { wide?: boolean } | undefined)?.wide); const fullHeight = matches.some( (m) => (m.handle as { fullHeight?: boolean } | undefined)?.fullHeight, ); const maxWidth = wide ? "" : "max-w-5xl"; async function toggleDemoMode() { await toggleDemoModeMutation.trigger({ enabled: !demoMode }); } return (
Fabro
{navigation.map((item) => { const current = pathname.startsWith(item.href); return (
Open user menu Profile
Open main menu
{navigation.map((item) => { const current = pathname.startsWith(item.href); return ( ); })}
{user.name}
{user.email}
Profile {provider !== "tailscale" && (
Sign out
)}
{!hideHeader && (

{title}

{headerExtra &&
{headerExtra}
}
)}
); }