dashboard: fold schedule creation into the table view (closes #564)

The N3W SCH3DUL3 vertical form is gone. The schedules table now
carries an always-visible inline create row at the bottom — fill the
cells, click + to POST /api/schedules, the new schedule appears
above on the next refresh.

Per-column inputs match the display semantics:
- `next` → `<input type="datetime-local">` (defaults to now+5min)
- `every` → 4 mini d/h/m/s number inputs (blank/all-zero = one-shot)
- `body` → `<textarea rows=1>` expanding to 4em on focus-within
  so multi-line prompts still fit (closes mara's "prompt may still be
  multi-line" requirement)
- per-agent columns → checkbox (whole cell clickable via padded label)
- actions → + submit + ⌫ reset (clears the carry without POSTing)

`newScheduleCarry` module-scope object survives the paintAtomic
re-render so mid-typed values stick across schedule-list refreshes
(same pattern as `scheduleEditCarry` from #474).

H2 collapses from "N3W SCH3DUL3" + "QU3U3D SCH3DUL3S" down to a
single "SCH3DUL3S" since the section now does both. Empty-state
branch on `renderSchedulesList` is gone — the table always renders
because the create row is always there.

`#schedule-new-section` div + `renderScheduleNewForm` /
`readScheduleFormCarry` / `submitNewSchedule` and the
`.schedule-new-form` CSS selector all removed. The edit-form path
(#474 `renderScheduleEditForm` colspan'd row on `✎` toggle) is
unchanged — "edit mode is inline in the table" already shipped
there, this PR just adds the same mental model for create.

Validations match the old form: empty targets / empty body /
invalid datetime / non-integer interval each surface an `alert()`.
The + button shows a spinner while the POST is in flight, then
clears the carry + triggers `refreshSchedules()`.
This commit is contained in:
iris 2026-05-29 19:57:14 +02:00
commit 0deca50352
3 changed files with 341 additions and 157 deletions

View file

@ -133,26 +133,21 @@
</div>
</section>
<!-- SCH3DUL3S (#459): scheduled prompts. operator-direct creation
form at the top (POST /api/schedules, no approval gate), live
schedules list below (GET /api/schedules) with per-target
last-fired timestamps + result, plus per-target / whole-row
cancel buttons (POST /api/schedules/{id}/cancel). #444 backend
doesn't emit a SchedulesChanged dashboard event yet, so the
list re-fetches on tab activation + after each form/cancel
submit. Live SSE wiring is the future PR C. -->
<!-- SCH3DUL3S (#459, #564): scheduled prompts. Creation + edit
are folded into the same table now (#564) — empty bottom row
is the create form (fill cells, click ), inline-edit-row
expands on the `✎` toggle for existing schedules. Live
schedules list driven by GET /api/schedules; POST /api/schedules
to create, PATCH /api/schedules/{id} to edit, POST
/api/schedules/{id}/cancel for per-target / whole-row cancel.
#444 backend doesn't emit SchedulesChanged dashboard event yet,
so the list re-fetches on tab activation + after each submit /
cancel. Live SSE wiring is the future PR C. -->
<section class="tab-pane" id="tab-pane-schedules"
role="tabpanel" aria-labelledby="tab-schedules">
<h2> N3W SCH3DUL3 ◆</h2>
<h2>◆ SCH3DUL3S</h2>
<div class="divider">══════════════════════════════════════════════════════════════</div>
<p class="meta">queue a prompt to fire at a future time. operator-direct (no approval gate); recurring when an interval is set. targets are any known agent name or <code>operator</code> / <code>manager</code>.</p>
<div id="schedule-new-section">
<p class="meta">loading…</p>
</div>
<h2>◆ QU3U3D SCH3DUL3S ◆</h2>
<div class="divider">══════════════════════════════════════════════════════════════</div>
<p class="meta">all schedules currently in the table. expand each card to see per-target firing history. cancel a single target with the row button or the whole schedule with <code>✕ cancel all</code>.</p>
<p class="meta">all schedules currently in the table. fill the bottom row to queue a new schedule (operator-direct, no approval gate; recurring when an interval is set). cancel a single target with the row button or the whole schedule with <code>✕ cancel all</code>.</p>
<div id="schedules-section">
<p class="meta">loading…</p>
</div>