@atolis-hq/wake 0.2.48 → 0.2.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -38,6 +38,10 @@ export const indexHtml = `<!DOCTYPE html>
|
|
|
38
38
|
.statusbar button { background: rgba(255, 255, 255, 0.08); border: 1px solid rgba(255, 255, 255, 0.18); color: #fff; border-radius: 6px; padding: 0.22rem 0.55rem; cursor: pointer; font-size: 0.78rem; }
|
|
39
39
|
.statusbar button:hover:not(:disabled) { border-color: var(--accent-light); background: rgba(45, 212, 191, 0.16); }
|
|
40
40
|
.statusbar button:disabled { cursor: wait; opacity: 0.62; }
|
|
41
|
+
.statusbar .pause-control { background: #5c1f1a; border-color: #ff8f7f; font-weight: 700; }
|
|
42
|
+
.statusbar .pause-control:hover:not(:disabled) { background: #733027; border-color: #ffd0c8; }
|
|
43
|
+
.statusbar .pause-control.is-paused { background: #1f4b34; border-color: #7fe3a3; }
|
|
44
|
+
.statusbar .pause-control.is-paused:hover:not(:disabled) { background: #276340; border-color: #c3f3d2; }
|
|
41
45
|
.pill { padding: 0.15rem 0.5rem; border-radius: 999px; font-size: 0.75rem; font-weight: 600; }
|
|
42
46
|
.pill-idle { background: #1f3d2c; color: #7fe3a3; }
|
|
43
47
|
.pill-polling { background: #1f3350; color: #7fb3ff; }
|
|
@@ -121,6 +125,7 @@ export const indexHtml = `<!DOCTYPE html>
|
|
|
121
125
|
</header>
|
|
122
126
|
<div class="statusbar">
|
|
123
127
|
<span id="loop-pill" class="pill">…</span>
|
|
128
|
+
<button id="pause-toggle" type="button" class="pause-control">Pause</button>
|
|
124
129
|
<button id="force-tick" type="button">Tick now</button>
|
|
125
130
|
<span id="status-summary" class="meta"></span>
|
|
126
131
|
</div>
|
|
@@ -184,6 +189,12 @@ async function postJson(path) {
|
|
|
184
189
|
return res.json();
|
|
185
190
|
}
|
|
186
191
|
|
|
192
|
+
async function deleteJson(path) {
|
|
193
|
+
const res = await fetch(API + path, { method: 'DELETE' });
|
|
194
|
+
if (!res.ok) throw new Error(path + ' -> ' + res.status);
|
|
195
|
+
return res.json();
|
|
196
|
+
}
|
|
197
|
+
|
|
187
198
|
function fmtMs(ms) {
|
|
188
199
|
if (ms === undefined || ms === null) return '—';
|
|
189
200
|
const s = Math.floor(ms / 1000);
|
|
@@ -220,6 +231,10 @@ async function renderStatusBar() {
|
|
|
220
231
|
const pill = document.getElementById('loop-pill');
|
|
221
232
|
pill.textContent = status.loopState;
|
|
222
233
|
pill.className = 'pill pill-' + status.loopState;
|
|
234
|
+
const pauseButton = document.getElementById('pause-toggle');
|
|
235
|
+
pauseButton.dataset.paused = String(status.paused);
|
|
236
|
+
pauseButton.textContent = status.paused ? 'Resume' : 'Pause';
|
|
237
|
+
pauseButton.classList.toggle('is-paused', status.paused);
|
|
223
238
|
const freshness = status.sourceFreshness.level;
|
|
224
239
|
const summary = document.getElementById('status-summary');
|
|
225
240
|
summary.textContent =
|
|
@@ -232,6 +247,23 @@ async function renderStatusBar() {
|
|
|
232
247
|
}
|
|
233
248
|
}
|
|
234
249
|
|
|
250
|
+
async function togglePause() {
|
|
251
|
+
const button = document.getElementById('pause-toggle');
|
|
252
|
+
const paused = button.dataset.paused === 'true';
|
|
253
|
+
button.disabled = true;
|
|
254
|
+
button.textContent = paused ? 'Resuming...' : 'Pausing...';
|
|
255
|
+
try {
|
|
256
|
+
if (paused) await deleteJson('/pause');
|
|
257
|
+
else await postJson('/pause');
|
|
258
|
+
await renderStatusBar();
|
|
259
|
+
switchView(currentView, { showLoading: false });
|
|
260
|
+
} catch (err) {
|
|
261
|
+
document.getElementById('status-summary').textContent = 'pause toggle failed: ' + err.message;
|
|
262
|
+
} finally {
|
|
263
|
+
button.disabled = false;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
235
267
|
async function forceTickNow() {
|
|
236
268
|
const button = document.getElementById('force-tick');
|
|
237
269
|
button.disabled = true;
|
|
@@ -842,6 +874,7 @@ document.getElementById('modal-overlay').addEventListener('click', (event) => {
|
|
|
842
874
|
}
|
|
843
875
|
});
|
|
844
876
|
document.getElementById('force-tick').addEventListener('click', forceTickNow);
|
|
877
|
+
document.getElementById('pause-toggle').addEventListener('click', togglePause);
|
|
845
878
|
|
|
846
879
|
renderStatusBar();
|
|
847
880
|
switchView('board');
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { createServer } from 'node:http';
|
|
2
2
|
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { mkdir, rm, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { dirname } from 'node:path';
|
|
3
5
|
import { createProjectionUpdater } from '../../core/projection-updater.js';
|
|
4
6
|
import { configuredTicketSource } from '../../domain/sources.js';
|
|
5
7
|
import { createEventEnvelope } from '../../lib/event-log.js';
|
|
@@ -155,6 +157,17 @@ async function handleRequest(req, res, options, now, projectionUpdater) {
|
|
|
155
157
|
sendJson(res, 202, request);
|
|
156
158
|
return;
|
|
157
159
|
}
|
|
160
|
+
if (req.method === 'POST' && resource === 'pause' && segments.length === 1) {
|
|
161
|
+
await mkdir(dirname(stateStore.paths.pauseFile), { recursive: true });
|
|
162
|
+
await writeFile(stateStore.paths.pauseFile, `${now().toISOString()}\n`, 'utf8');
|
|
163
|
+
sendJson(res, 200, { paused: true });
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (req.method === 'DELETE' && resource === 'pause' && segments.length === 1) {
|
|
167
|
+
await rm(stateStore.paths.pauseFile, { force: true });
|
|
168
|
+
sendJson(res, 200, { paused: false });
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
158
171
|
if (req.method === 'POST' &&
|
|
159
172
|
resource === 'runners' &&
|
|
160
173
|
segments.length === 3 &&
|
package/dist/src/version.js
CHANGED