feat(web): redesign Overview as the homepage with a living graph backdrop
Some checks failed
ci / build-test (push) Has been cancelled
ci / docker-build (push) Has been cancelled

Overview replaces Tasks as the default route: a centered new-task entry
with live fleet metrics, a scrollable/filterable task table, and an
ambient canvas rendering of the real entity graph (autonomous camera
drift + mouse parallax) behind it. Tasks sidebar entry is removed;
its status-bucketing logic moves to lib/tasks.ts for reuse.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-12 11:07:36 +02:00
parent 0ed171507f
commit 6807e353e3
5 changed files with 510 additions and 442 deletions

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import Chat from './pages/Chat.svelte'
import Tasks from './pages/Tasks.svelte'
import Overview from './pages/Overview.svelte'
import Entities from './pages/Entities.svelte'
import Ops from './pages/Ops.svelte'
@@ -20,8 +19,6 @@
import { Separator } from '$lib/components/ui/separator'
import { Toaster } from '$lib/components/ui/sonner'
import PlusIcon from '@lucide/svelte/icons/plus'
import ListTodoIcon from '@lucide/svelte/icons/list-todo'
import MessageSquareIcon from '@lucide/svelte/icons/message-square'
import LayoutDashboardIcon from '@lucide/svelte/icons/layout-dashboard'
import DatabaseIcon from '@lucide/svelte/icons/database'
import PanelRightIcon from '@lucide/svelte/icons/panel-right'
@@ -31,7 +28,7 @@
import SearchIcon from '@lucide/svelte/icons/search'
import TrendingUpIcon from '@lucide/svelte/icons/trending-up'
let page = $state('tasks')
let page = $state('overview')
let routeParam = $state('')
let drawerOpen = $state(false)
@@ -40,9 +37,9 @@
onMount(() => {
function sync() {
const path = location.hash.slice(2) || 'tasks'
const path = location.hash.slice(2) || 'overview'
const [head, ...rest] = path.split('/')
page = head || 'tasks'
page = head || 'overview'
routeParam = rest.join('/')
}
sync()
@@ -114,20 +111,10 @@
<Sidebar.Content>
<Sidebar.Group>
<Sidebar.Menu>
<Sidebar.MenuItem>
<Sidebar.MenuButton isActive={page === 'tasks' || page === 'chat'} onclick={() => navigate('tasks')} tooltipContent="Tasks">
{#snippet child({ props })}
<button {...props}>
<ListTodoIcon />
<span>Tasks</span>
</button>
{/snippet}
</Sidebar.MenuButton>
</Sidebar.MenuItem>
{#each navItems as item}
<Sidebar.MenuItem>
<Sidebar.MenuButton
isActive={page === item.id}
isActive={page === item.id || (item.id === 'overview' && page === 'chat')}
onclick={() => navigate(item.id)}
tooltipContent={item.label}
>
@@ -166,7 +153,7 @@
<Sidebar.Trigger class="-ms-1" />
<Separator orientation="vertical" class="mx-2 data-[orientation=vertical]:h-4" />
{#if page === 'chat'}
<button type="button" class="text-sm text-muted-foreground hover:text-foreground" onclick={() => navigate('tasks')}>Tasks</button>
<button type="button" class="text-sm text-muted-foreground hover:text-foreground" onclick={() => navigate('overview')}>Overview</button>
<span class="text-muted-foreground">/</span>
<span class="text-base font-medium">Conversation</span>
{:else}
@@ -199,8 +186,6 @@
<main class="min-h-0 flex-1 overflow-hidden">
{#if page === 'overview'}
<Overview />
{:else if page === 'tasks'}
<Tasks />
{:else if page === 'entities'}
<Entities />
{:else if page === 'graph'}