<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>fleet-router dashboard</title>
<meta name="color-scheme" content="dark light">
<meta name="theme-color" content="#050505" media="(prefers-color-scheme: dark)">
<meta name="theme-color" content="#f6f6f3" media="(prefers-color-scheme: light)">
<meta name="robots" content="noindex">
<link rel="icon" href="favicon.svg" type="image/svg+xml">
<link rel="preload" href="fonts/inter.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="fonts/jetbrains-mono.woff2" as="font" type="font/woff2" crossorigin>
<script src="js/theme-boot.js"></script>
<link rel="stylesheet" href="app.css">
<script type="module" src="js/main.js"></script>
</head>
<body>
<a class="skip" href="#main">Skip to content</a>
<header class="masthead">
<div class="wrap masthead-row">
<a class="brand" href="#fleet" aria-label="fleet-router, fleet view">
<svg class="brand-mark" width="24" height="24" viewBox="0 0 32 32" aria-hidden="true" focusable="false">
<rect x="0.5" y="0.5" width="31" height="31" rx="4" class="brand-mark-field"/>
<path d="M4 11h8l5 5h11M4 21h8l5-5" fill="none" stroke-width="2" stroke-linejoin="round" class="brand-mark-dim"/>
<path d="M4 11h8l5 5h11" fill="none" stroke-width="2.5" stroke-linejoin="round" class="brand-mark-set"/>
<circle cx="26" cy="21" r="2.2" class="brand-mark-lamp"/>
</svg>
<span class="brand-name">fleet-router</span>
</a>
<p class="mast-meta" aria-live="off">
<span class="link-state" id="link-state" data-state="connecting">
<span class="lamp" aria-hidden="true"></span>
<span class="link-label">Connecting</span>
</span>
<span class="meta-item" id="meta-version"></span>
<span class="meta-item" id="meta-uptime"></span>
</p>
<nav class="views" aria-label="Views">
<a href="#fleet" data-view="fleet">Fleet</a>
<a href="#sessions" data-view="sessions">Sessions <span class="count" id="nav-sessions"></span></a>
<a href="#events" data-view="events">Events <span class="count" id="nav-events" hidden></span></a>
</nav>
<div class="mast-actions">
<button class="button button-quiet" id="control-button" type="button" hidden>
<span class="key" aria-hidden="true"></span>
<span class="control-label">Controls</span>
</button>
<button class="theme-toggle" id="theme-toggle" type="button" aria-label="Switch theme">
<svg class="icon-sun" width="18" height="18" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></svg>
<svg class="icon-moon" width="18" height="18" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M20 14.5A8 8 0 1 1 9.5 4a6.5 6.5 0 0 0 10.5 10.5z"/></svg>
</button>
</div>
</div>
</header>
<main id="main" class="wrap" tabindex="-1">
<section class="view" id="view-fleet" data-view="fleet" aria-labelledby="fleet-title">
<div class="view-head">
<h1 id="fleet-title">Fleet</h1>
<p class="view-summary" id="fleet-summary"></p>
<ul class="legend" aria-label="Upstream states">
<li><span class="key key-set" aria-hidden="true"></span>up</li>
<li><span class="key key-failover" aria-hidden="true"></span>failover</li>
<li><span class="key key-stale" aria-hidden="true"></span>stale</li>
<li><span class="key key-quarantine" aria-hidden="true"></span>quarantined</li>
<li><span class="key key-offline" aria-hidden="true"></span>down</li>
<li><span class="key key-idle" aria-hidden="true"></span>disabled</li>
<li><span class="key-line" aria-hidden="true"></span>finality data</li>
</ul>
</div>
<div id="listeners" class="listeners">
<p class="placeholder">Waiting for the first status update.</p>
</div>
<section class="recent" aria-labelledby="recent-title">
<div class="recent-head">
<h2 id="recent-title">Recent events</h2>
<a href="#events">All events</a>
</div>
<ol class="event-list" id="recent-events"></ol>
</section>
</section>
<section class="view" id="view-sessions" data-view="sessions" aria-labelledby="sessions-title" hidden>
<div class="view-head">
<h1 id="sessions-title">Sessions</h1>
<p class="view-summary" id="sessions-summary"></p>
</div>
<div class="toolbar">
<label class="field">
<span>Listener</span>
<select id="sessions-listener"><option value="">All</option></select>
</label>
<label class="field">
<span>Upstream</span>
<select id="sessions-upstream"><option value="">All</option></select>
</label>
<label class="field field-grow">
<span>Client</span>
<input id="sessions-search" type="search" placeholder="Filter by address" autocomplete="off" spellcheck="false">
</label>
</div>
<div class="table-scroll">
<table class="data" id="sessions-table">
<thead>
<tr>
<th scope="col" data-sort="client">Client</th>
<th scope="col" data-sort="upstream_name">Upstream</th>
<th scope="col" data-sort="age" class="num">Age</th>
<th scope="col" data-sort="start_block" class="num">Start block</th>
<th scope="col" data-sort="last_block" class="num">Last block</th>
<th scope="col" data-sort="blocks" class="num">Blocks</th>
<th scope="col" data-sort="bytes" class="num">Sent</th>
<th scope="col" data-sort="failovers" class="num">Failovers</th>
<th scope="col" class="col-actions"><span class="sr-only">Actions</span></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<p class="empty" id="sessions-empty" hidden></p>
</section>
<section class="view" id="view-events" data-view="events" aria-labelledby="events-title" hidden>
<div class="view-head">
<h1 id="events-title">Events</h1>
<p class="view-summary">The last 500 events the router kept in memory, newest first.</p>
</div>
<div class="toolbar">
<div class="segmented" role="radiogroup" aria-label="Level" id="events-level">
<button type="button" role="radio" aria-checked="true" data-level="">All</button>
<button type="button" role="radio" aria-checked="false" data-level="warn">Warnings</button>
<button type="button" role="radio" aria-checked="false" data-level="error">Errors</button>
</div>
<label class="field">
<span>Listener</span>
<select id="events-listener"><option value="">All</option></select>
</label>
</div>
<ol class="event-list event-list-full" id="all-events"></ol>
<p class="empty" id="events-empty" hidden>No events match these filters.</p>
</section>
</main>
<dialog class="sheet" id="upstream-dialog" aria-labelledby="upstream-dialog-title">
<form method="dialog" class="sheet-head">
<h2 id="upstream-dialog-title"></h2>
<button class="icon-button" value="close" aria-label="Close">
<svg width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"><path d="M3 3l10 10M13 3L3 13"/></svg>
</button>
</form>
<div class="sheet-body" id="upstream-dialog-body"></div>
</dialog>
<dialog class="sheet sheet-narrow" id="unlock-dialog" aria-labelledby="unlock-title">
<form class="sheet-form" id="unlock-form">
<div class="sheet-head">
<h2 id="unlock-title">Unlock controls</h2>
<button class="icon-button" type="button" data-close aria-label="Close">
<svg width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"><path d="M3 3l10 10M13 3L3 13"/></svg>
</button>
</div>
<div class="sheet-body">
<p>Enter the control token from this router's config. It stays in this browser tab only and is sent with each control request.</p>
<label class="field">
<span>Control token</span>
<input id="unlock-token" type="password" autocomplete="off" spellcheck="false" required>
</label>
<p class="form-error" id="unlock-error" role="alert" hidden></p>
<div class="sheet-actions">
<button class="button" type="button" data-close>Cancel</button>
<button class="button button-primary" type="submit">Unlock</button>
</div>
</div>
</form>
</dialog>
<dialog class="sheet sheet-narrow" id="info-dialog" aria-labelledby="info-title">
<form method="dialog">
<div class="sheet-head">
<h2 id="info-title"></h2>
<button class="icon-button" value="close" aria-label="Close">
<svg width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"><path d="M3 3l10 10M13 3L3 13"/></svg>
</button>
</div>
<div class="sheet-body" id="info-body"></div>
</form>
</dialog>
<dialog class="sheet sheet-narrow" id="confirm-dialog" aria-labelledby="confirm-title">
<form method="dialog">
<div class="sheet-head">
<h2 id="confirm-title"></h2>
</div>
<div class="sheet-body">
<p id="confirm-text"></p>
<div class="sheet-actions">
<button class="button" value="cancel">Cancel</button>
<button class="button button-warn" value="ok" id="confirm-ok"></button>
</div>
</div>
</form>
</dialog>
<div class="toasts" id="toasts" role="status" aria-live="polite" popover="manual"></div>
<div class="sr-only" id="announcer" aria-live="polite"></div>
<noscript><p class="wrap noscript">The dashboard needs JavaScript. The plain status page at <a href="../status">/status</a> works without it.</p></noscript>
</body>
</html>