Let a Home tile lead where its figure does, and drop the logo nobody saw
`Tile` takes an optional link: Nodes and Flows running to /flows, Runs running to /runs, Failures down to the list further down the same page. Queue backlog and loop lag have no screen of their own and stay plain. `Logo`'s responsive variant carried a second `<img>` for the collapsed rail, but AppSidebar hides the whole logo when collapsed, so an ancestor `display: none` meant it never rendered in any state. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KYM38KSb4V4v2T71eifnZv
This commit is contained in:
@@ -19,34 +19,19 @@ export function Logo({
|
||||
const { resolvedTheme } = useTheme()
|
||||
const src = resolvedTheme === "dark" ? logoDark : logo
|
||||
|
||||
// The mark and the wordmark live in the same SVG, so the collapsed sidebar
|
||||
// shows the same asset cropped to a square rather than a separate icon file.
|
||||
const content =
|
||||
variant === "responsive" ? (
|
||||
<>
|
||||
// The mark and the wordmark live in the same SVG. The collapsed sidebar
|
||||
// hides the logo entirely (see AppSidebar), so "responsive" only needs to
|
||||
// hide itself the same way, not carry a second, cropped asset.
|
||||
const content = (
|
||||
<img
|
||||
src={src}
|
||||
alt="Fluksio"
|
||||
className={cn(
|
||||
"h-6 w-auto group-data-[collapsible=icon]:hidden",
|
||||
className,
|
||||
)}
|
||||
/>
|
||||
<img
|
||||
src={src}
|
||||
alt="Fluksio"
|
||||
className={cn(
|
||||
"size-5 object-contain hidden group-data-[collapsible=icon]:block",
|
||||
className,
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<img
|
||||
src={src}
|
||||
alt="Fluksio"
|
||||
className={cn(
|
||||
variant === "full" ? "h-6 w-auto" : "size-5 object-contain",
|
||||
variant === "full"
|
||||
? "h-6 w-auto"
|
||||
: variant === "responsive"
|
||||
? "h-6 w-auto group-data-[collapsible=icon]:hidden"
|
||||
: "size-5 object-contain",
|
||||
className,
|
||||
)}
|
||||
/>
|
||||
|
||||
@@ -375,7 +375,8 @@ export function HealthActivity({ range }: { range: Range }) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid content-start gap-3">
|
||||
{/* `id`: what the Failures tile on the overview above scrolls down to. */}
|
||||
<div id="failures" className="grid content-start gap-3">
|
||||
<ListHeader title="Failures" moment={failuresAt} />
|
||||
<div
|
||||
className={cn(
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { useQuery } from "@tanstack/react-query"
|
||||
import { Link } from "@tanstack/react-router"
|
||||
|
||||
import { type Range, RangePicker } from "@/components/Common/RangePicker"
|
||||
import { PANEL_SECTION } from "@/components/Flow/SidePanel"
|
||||
import { runOverviewQueryOptions } from "@/components/Runs/queries"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { dur, si } from "@/lib/utils"
|
||||
import { cn, dur, si } from "@/lib/utils"
|
||||
import {
|
||||
ago,
|
||||
CARD,
|
||||
@@ -17,19 +18,35 @@ function Tile({
|
||||
label,
|
||||
value,
|
||||
note,
|
||||
to,
|
||||
hash,
|
||||
}: {
|
||||
label: string
|
||||
value: string
|
||||
note?: string
|
||||
/** Where this figure is explained further, if anywhere obvious. */
|
||||
to?: string
|
||||
hash?: string
|
||||
}) {
|
||||
return (
|
||||
<div className={CARD}>
|
||||
const body = (
|
||||
<>
|
||||
<div className={PANEL_SECTION}>{label}</div>
|
||||
<div className="mt-1 text-2xl">{value}</div>
|
||||
{note ? (
|
||||
<div className="text-xs text-muted-foreground">{note}</div>
|
||||
) : null}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
return to ? (
|
||||
<Link
|
||||
to={to}
|
||||
hash={hash}
|
||||
className={cn(CARD, "transition-colors hover:bg-accent/50")}
|
||||
>
|
||||
{body}
|
||||
</Link>
|
||||
) : (
|
||||
<div className={CARD}>{body}</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -91,10 +108,14 @@ export function HealthOverview({
|
||||
? `${summary.nodes.error} failed to load`
|
||||
: "all loaded"
|
||||
}
|
||||
// Nodes belong to flows, not a list of their own — the flows table
|
||||
// is where a count and a load error are read node by node.
|
||||
to="/flows"
|
||||
/>
|
||||
<Tile
|
||||
label="Flows running"
|
||||
value={`${summary?.flows.running ?? 0}/${summary?.flows.total ?? 0}`}
|
||||
to="/flows"
|
||||
// Worst first, but all of them: a quarantine used to hide the
|
||||
// flows validation blocks, so the tile disagreed with the count
|
||||
// beside it. Zero and undefined both drop out of the filter.
|
||||
@@ -114,6 +135,7 @@ export function HealthOverview({
|
||||
label="Runs running"
|
||||
value={String(running)}
|
||||
note={queued ? `${queued} queued` : "none queued"}
|
||||
to="/runs"
|
||||
/>
|
||||
) : null}
|
||||
<Tile
|
||||
@@ -128,6 +150,10 @@ export function HealthOverview({
|
||||
? `latest ${ago(failures[0].ts)}`
|
||||
: "nothing recorded"
|
||||
}
|
||||
// Down to the failures list further down this same page, rather
|
||||
// than a route of its own.
|
||||
to="/"
|
||||
hash="failures"
|
||||
/>
|
||||
{/* Backlog leads: what is waiting is what says the engine is
|
||||
behind. `pending` is work already running, which reads as idle
|
||||
|
||||
Reference in New Issue
Block a user