dashboard: reset-timer checkbox on recurring fire-now
Manually firing a recurring schedule now offers a "reset timer" checkbox
(default on) in the confirm dialog: when checked, the fire-now POST sends
{reset_timer:true} and the backend re-arms next_fire_at to now + interval.
Unchecking keeps today's behaviour (extra out-of-band pulse, cadence
intact). One-shot schedules omit the checkbox — they're consumed regardless.
The result flash shows "— timer reset" when the backend reports timer_reset.
Pairs with the backend reset_timer/timer_reset work. Closes #1848.
This commit is contained in:
parent
905b38b6c7
commit
4b318a809a
1 changed files with 20 additions and 7 deletions
|
|
@ -737,7 +737,7 @@ function renderScheduleRow(s, agents) {
|
|||
}, '↯');
|
||||
fireBtn.title = isOneShot
|
||||
? 'fire once — one-shot, consumed after the manual fire'
|
||||
: 'fire once now — recurring, next regular fire unaffected';
|
||||
: 'fire once now — recurring; choose whether to reset the next-fire timer';
|
||||
if (!activeTargets.length) {
|
||||
fireBtn.disabled = true;
|
||||
fireBtn.title = 'every target is cancelled — nothing to fire';
|
||||
|
|
@ -986,14 +986,25 @@ async function submitEditSchedule(originalSchedule, form_) {
|
|||
}
|
||||
async function fireScheduleNow(id, isOneShot, targets, btn) {
|
||||
const targetList = targets.length ? targets.join(', ') : '(no active targets)';
|
||||
// Recurring schedules get a "reset timer" checkbox (default on): firing
|
||||
// now also re-arms the next regular fire to now + interval. One-shot is
|
||||
// consumed regardless, so the flag is moot there (no checkbox).
|
||||
const checkboxes = isOneShot ? [] : [{
|
||||
name: 'reset_timer',
|
||||
label: 'reset timer — re-arm next fire to now + interval',
|
||||
checked: true,
|
||||
}];
|
||||
const prompt = isOneShot
|
||||
? `fire schedule #${id} now to ${targetList}?\n\n`
|
||||
+ 'this is a ONE-SHOT — firing now consumes the schedule. '
|
||||
+ 'the scheduled fire time will no longer trigger.'
|
||||
: `fire schedule #${id} now to ${targetList}?\n\n`
|
||||
+ 'this is RECURRING — sends an extra pulse out-of-band. '
|
||||
+ 'the regular cadence keeps firing on schedule.';
|
||||
if (!(await themedConfirm({ message: prompt, danger: true }))) return;
|
||||
+ 'leave "reset timer" on to re-arm the next regular fire to '
|
||||
+ 'now + interval; uncheck it to keep the existing cadence.';
|
||||
const confirmRes = await themedConfirm({ message: prompt, danger: true, checkboxes });
|
||||
if (!confirmRes) return;
|
||||
const resetTimer = !!confirmRes.reset_timer;
|
||||
// Capture child nodes so we can restore on error, then replace
|
||||
// with DOM-built content (textContent + element children rather
|
||||
// than innerHTML — the format string only carries server-side
|
||||
|
|
@ -1015,6 +1026,7 @@ async function fireScheduleNow(id, isOneShot, targets, btn) {
|
|||
const resp = await fetch('/api/schedules/' + encodeURIComponent(id) + '/fire-now', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ reset_timer: resetTimer }),
|
||||
});
|
||||
if (!resp.ok) {
|
||||
const text = await resp.text().catch(() => '');
|
||||
|
|
@ -1022,9 +1034,9 @@ async function fireScheduleNow(id, isOneShot, targets, btn) {
|
|||
restoreBtn();
|
||||
return;
|
||||
}
|
||||
// Backend returns FireNowReport { ok, failed, missing, one_shot_consumed }.
|
||||
// Flash the per-target outcome on the button itself so the operator
|
||||
// sees the result immediately, then refresh to pick up the
|
||||
// Backend returns FireNowReport { ok, failed, missing, one_shot_consumed,
|
||||
// timer_reset }. Flash the per-target outcome on the button itself so the
|
||||
// operator sees the result immediately, then refresh to pick up the
|
||||
// authoritative per-target `last_result` annotations.
|
||||
let report = null;
|
||||
try { report = await resp.json(); } catch { /* shape drift / empty body — ignore */ }
|
||||
|
|
@ -1033,7 +1045,8 @@ async function fireScheduleNow(id, isOneShot, targets, btn) {
|
|||
if (report.ok) bits.push(report.ok + ' ok');
|
||||
if (report.failed) bits.push(report.failed + ' failed');
|
||||
if (report.missing) bits.push(report.missing + ' missing');
|
||||
const suffix = report.one_shot_consumed ? ' — consumed' : '';
|
||||
const suffix = report.one_shot_consumed ? ' — consumed'
|
||||
: (report.timer_reset ? ' — timer reset' : '');
|
||||
while (btn.firstChild) btn.removeChild(btn.firstChild);
|
||||
btn.textContent = '↯ fired: ' + (bits.join(', ') || 'no targets') + suffix;
|
||||
btn.classList.add('btn-fire-now-flashed');
|
||||
|
|
|
|||
Loading…
Reference in a new issue