notify router: deliveries log, dry-run hit counts, api and page
This commit is contained in:
parent
6dd9d0086e
commit
ed1fd053e7
24 changed files with 1848 additions and 40 deletions
|
|
@ -19,6 +19,7 @@ import {
|
|||
type RefreshIntervalMs,
|
||||
} from "../../ui/refresh-interval/RefreshInterval.js";
|
||||
import { fetchJson, usePolled } from "../../ui/polled/usePolled.js";
|
||||
import { Deliveries } from "./Deliveries.js";
|
||||
import {
|
||||
duplicateFlow,
|
||||
newFlow,
|
||||
|
|
@ -32,11 +33,21 @@ import {
|
|||
type Flow,
|
||||
type FlowsView,
|
||||
} from "./FlowTypes.js";
|
||||
import {
|
||||
DELIVERIES_URL,
|
||||
DRY_RUN_URL,
|
||||
hitsOf,
|
||||
unavailableText,
|
||||
type Deliveries as DeliveriesView,
|
||||
type DryRun,
|
||||
} from "./RouterLive.js";
|
||||
import "./NotificationsPage.css";
|
||||
|
||||
const DEFAULT_INTERVAL_MS: RefreshIntervalMs = 30_000;
|
||||
|
||||
function FlowTree({ flow }: { flow: Flow }) {
|
||||
// `hits`, when the dry run covers this flow, puts the number of the newest events
|
||||
// that reached each node beside it.
|
||||
function FlowTree({ flow, hits }: { flow: Flow; hits?: Map<string, number> }) {
|
||||
return (
|
||||
<ul class="notify-flow-tree">
|
||||
{treeRows(flow).map(({ node, depth }) => (
|
||||
|
|
@ -47,6 +58,11 @@ function FlowTree({ flow }: { flow: Flow }) {
|
|||
>
|
||||
<span class="notify-node-kind">{node.kind}</span>
|
||||
<span class="notify-node-text">{describeNode(node)}</span>
|
||||
{hits ? (
|
||||
<span class="notify-node-hits" title="events of the last dry run">
|
||||
{hits.get(node.id) ?? 0}
|
||||
</span>
|
||||
) : null}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
|
@ -63,6 +79,18 @@ export function NotificationsPage() {
|
|||
} = usePolled(intervalMs, (signal) =>
|
||||
fetchJson<FlowsView>("/api/notify/flows", signal),
|
||||
);
|
||||
// The router's own answers. Either is 503 while the running router predates
|
||||
// it, which the page says in place of the section.
|
||||
const { data: dry, error: dryError } = usePolled(intervalMs, (signal) =>
|
||||
fetchJson<DryRun>(DRY_RUN_URL, signal),
|
||||
);
|
||||
const { data: deliveries, error: deliveriesError } = usePolled(
|
||||
intervalMs,
|
||||
(signal) => fetchJson<DeliveriesView>(DELIVERIES_URL, signal),
|
||||
);
|
||||
// A failed poll keeps the last answer; the counts are shown only while the
|
||||
// latest poll worked.
|
||||
const shown = dryError ? null : dry;
|
||||
const [pending, setPending] = useState(false);
|
||||
const [actionError, setActionError] = useState<ProblemDetails | null>(null);
|
||||
const [newName, setNewName] = useState("");
|
||||
|
|
@ -149,6 +177,15 @@ export function NotificationsPage() {
|
|||
{!error && view === null ? <p>loading…</p> : null}
|
||||
{view ? (
|
||||
<div class="notify-flows">
|
||||
{dryError ? (
|
||||
<p class="notify-unavailable">
|
||||
{unavailableText("hit counts", dryError)}
|
||||
</p>
|
||||
) : dry ? (
|
||||
<p class="notify-dry-run">
|
||||
counts: events that reached each node, of the newest {dry.events}
|
||||
</p>
|
||||
) : null}
|
||||
<h3>built-in flows</h3>
|
||||
{view.builtins.map((flow) => {
|
||||
const on = !view.disabled_builtins.includes(flow.id);
|
||||
|
|
@ -164,7 +201,7 @@ export function NotificationsPage() {
|
|||
onChange={(checked) => setBuiltin(flow.id, checked)}
|
||||
/>
|
||||
</div>
|
||||
<FlowTree flow={flow} />
|
||||
<FlowTree flow={flow} hits={hitsOf(shown, flow.id)} />
|
||||
<Button disabled={pending} onClick={() => void duplicate(flow)}>
|
||||
duplicate to edit
|
||||
</Button>
|
||||
|
|
@ -202,9 +239,19 @@ export function NotificationsPage() {
|
|||
duplicate
|
||||
</Button>
|
||||
</div>
|
||||
<FlowTree flow={flow} />
|
||||
<FlowTree flow={flow} hits={hitsOf(shown, flow.id)} />
|
||||
</Card>
|
||||
))}
|
||||
<h3>recent deliveries</h3>
|
||||
{deliveriesError ? (
|
||||
<p class="notify-unavailable">
|
||||
{unavailableText("the deliveries log", deliveriesError)}
|
||||
</p>
|
||||
) : deliveries ? (
|
||||
<Deliveries rows={deliveries.rows} />
|
||||
) : (
|
||||
<p>loading…</p>
|
||||
)}
|
||||
</div>
|
||||
) : null}
|
||||
</Panel>
|
||||
|
|
|
|||
Loading…
Reference in a new issue