swarm-ui: the schedules are a folded card on the messages tab
The schedules tab is gone from the nav. Its page, unchanged inside, is a card on /messages under the broadcast card that starts shut and reads nothing until opened; its add button and refresh picker move into the card's body. /schedules redirects to /messages. Docs follow.
This commit is contained in:
parent
d269c06d58
commit
bdef828df3
3 changed files with 65 additions and 42 deletions
|
|
@ -2,7 +2,7 @@
|
|||
// operator, reminders and compaction to an agent, as the swarm's controller
|
||||
// streams them (`GET /api/messages/stream`), across all hives. Above the
|
||||
// list, a folded **broadcast** card holds the composer that sends one message
|
||||
// to several agents.
|
||||
// to several agents, and a folded **schedules** card holds the scheduled prompts.
|
||||
//
|
||||
// The stream sends the chosen window of history first, then the live tail. A
|
||||
// message an agent drained with an in-turn `recv` is missing, because it starts
|
||||
|
|
@ -14,6 +14,7 @@ import { useLayoutEffect, useRef, useState } from "preact/hooks";
|
|||
import { Badge, type BadgeTone } from "@hive/shared/badge.js";
|
||||
import { Row } from "@hive/shared/term-row.js";
|
||||
import { BroadcastComposer } from "../broadcast/BroadcastComposer.js";
|
||||
import { SchedulesCard } from "../schedules/SchedulesPage.js";
|
||||
import { Disclosure } from "../../ui/disclosure/Disclosure.js";
|
||||
import { Panel } from "../../ui/panel/Panel.js";
|
||||
import { SelectField } from "../../ui/select-field/SelectField.js";
|
||||
|
|
@ -96,6 +97,7 @@ export function MessagesPage() {
|
|||
>
|
||||
{composerBuilt ? <BroadcastComposer /> : null}
|
||||
</Disclosure>
|
||||
<SchedulesCard />
|
||||
<Panel
|
||||
title="messages"
|
||||
icon="💬"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
/* The bar at the top of the schedules card: the add button, then the refresh
|
||||
picker, to the right. */
|
||||
.ui-schedules-bar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 0.5em 0.75em;
|
||||
margin-block-end: 0.5em;
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// <SchedulesPage> — the swarm's scheduled prompts, one card per schedule.
|
||||
// <SchedulesCard> — the swarm's scheduled prompts, one card per schedule, folded on the messages tab.
|
||||
// Backed by swarm-controller's `GET/POST /api/schedules` and
|
||||
// `PATCH/DELETE /api/schedules/{id}`; the controller is the only writer of
|
||||
// the schedule store and computes each schedule's `next_fire_unix`, so
|
||||
|
|
@ -15,7 +15,8 @@ import { readApiError, type ProblemDetails } from "@hive/shared/api-error.js";
|
|||
import { Button } from "../../ui/button/Button.js";
|
||||
import { ConfirmDialog } from "../../ui/confirm-dialog/ConfirmDialog.js";
|
||||
import { FilterableView } from "../../ui/filterable-view/FilterableView.js";
|
||||
import { Panel } from "../../ui/panel/Panel.js";
|
||||
import "./SchedulesPage.css";
|
||||
import { LazyDisclosure } from "../../ui/disclosure/LazyDisclosure.js";
|
||||
import {
|
||||
RefreshIntervalPicker,
|
||||
type RefreshIntervalMs,
|
||||
|
|
@ -57,7 +58,7 @@ const COLUMNS: TableColumn<Schedule>[] = [
|
|||
},
|
||||
];
|
||||
|
||||
export function SchedulesPage() {
|
||||
function SchedulesBody() {
|
||||
const [intervalMs, setIntervalMs] =
|
||||
useState<RefreshIntervalMs>(DEFAULT_INTERVAL_MS);
|
||||
const {
|
||||
|
|
@ -145,26 +146,21 @@ export function SchedulesPage() {
|
|||
}
|
||||
|
||||
return (
|
||||
<Panel
|
||||
title="schedules"
|
||||
icon="⏰"
|
||||
actions={
|
||||
<>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={() => setCreating(true)}
|
||||
disabled={creating}
|
||||
>
|
||||
+ schedule
|
||||
</Button>
|
||||
<RefreshIntervalPicker
|
||||
id="schedules-refresh"
|
||||
value={intervalMs}
|
||||
onChange={setIntervalMs}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<>
|
||||
<div class="ui-schedules-bar">
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={() => setCreating(true)}
|
||||
disabled={creating}
|
||||
>
|
||||
+ schedule
|
||||
</Button>
|
||||
<RefreshIntervalPicker
|
||||
id="schedules-refresh"
|
||||
value={intervalMs}
|
||||
onChange={setIntervalMs}
|
||||
/>
|
||||
</div>
|
||||
{error ? (
|
||||
<ApiErrorPanel context="failed to load the schedules" problem={error} />
|
||||
) : null}
|
||||
|
|
@ -226,6 +222,20 @@ export function SchedulesPage() {
|
|||
</p>
|
||||
) : null}
|
||||
</ConfirmDialog>
|
||||
</Panel>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// A folded card on the messages tab: the scheduled prompts, read and polled
|
||||
// only once it is opened.
|
||||
export function SchedulesCard() {
|
||||
return (
|
||||
<LazyDisclosure
|
||||
title="schedules"
|
||||
icon="⏰"
|
||||
hint="prompts sent to agents at set times: add, edit, pause, remove"
|
||||
>
|
||||
<SchedulesBody />
|
||||
</LazyDisclosure>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue