feat(admin): report pair scan outcomes and cancellation (#193)

This commit is contained in:
Vito Sansevero
2026-10-17 06:52:53 -07:00
parent 752dff9098
commit 2e49d1fadb
3 changed files with 36 additions and 10 deletions
+19
View File
@@ -76,3 +76,22 @@ test("progressLabel summarises a running scan for the minimized pill", () => {
assert.equal(progressLabel(running), "Scanning 42% · 84 files · 12 prompts");
assert.equal(progressLabel(initialState()), "");
});
test('pair totals survive completion and cancellation closes the running state', () => {
const running=reduceScanEvent(initialState(),{type:'progress',progress:30,processed:3});
const done=reduceScanEvent(running,{type:'complete',pairs_added:2,pair_links_added:3,enriched:1,unchanged:4,ambiguous:1,failed:2});
assert.deepEqual([done.pairs_added,done.pair_links_added,done.enriched,done.unchanged,done.ambiguous,done.failed],[2,3,1,4,1,2]);
const cancelled=reduceScanEvent(running,{type:'cancelled',processed:3,pairs_added:1});
assert.equal(cancelled.status,'done');
assert.equal(cancelled.cancelled,true);
assert.equal(cancelled.statusText,'Scan cancelled.');
assert.equal(cancelled.progress,30);
});
test('completion label reports pair enrichment, unresolved work and failures', () => {
const {completionLabel}=require('../../web/js/scan-progress.js');
const state=reduceScanEvent(initialState(),{type:'complete',processed:10,found:8,added:1,linked:2,pairs_added:3,pair_links_added:4,enriched:2,unchanged:1,ambiguous:1,unresolved:2,conflict:1,failed:1});
assert.match(completionLabel(state),/3 new pairs, 4 pair links/);
assert.match(completionLabel(state),/4 need review, 1 failed/);
assert.match(completionLabel({...state,cancelled:true}),/^Scan cancelled!/);
});
+2 -7
View File
@@ -2353,7 +2353,7 @@
if (this.scanState.status === ScanProgress.RUNNING) {
// A scan we were following ended while we were disconnected.
const last = status.last_event;
const terminal = last && (last.type === "complete" || last.type === "error");
const terminal = last && (last.type === "complete" || last.type === "cancelled" || last.type === "error");
this.applyScanEvent(
terminal ? last : { type: "error", message: "the server no longer reports a running scan" }
);
@@ -2418,13 +2418,8 @@
}
completeScan(state) {
const { processed, found, added, linked } = state;
document.getElementById("scanPill").classList.add("hidden");
const linkedText = linked > 0 ? `, linked ${linked} images to existing prompts` : '';
this.showNotification(
`Scan completed! Processed ${processed} files, found ${found} prompts, added ${added} new prompts to database${linkedText}.`,
"success"
);
this.showNotification(ScanProgress.completionLabel(state), "success");
// Auto-close after a short delay so the completion message is visible
setTimeout(() => {
+15 -3
View File
@@ -55,12 +55,18 @@
found: num(event.found, state.found),
};
}
if (event.type === "complete") {
if (event.type === "complete" || event.type === "cancelled") {
const counts = Object.fromEntries(
['pairs_added','pair_links_added','enriched','unchanged','ambiguous','unresolved','conflict','failed']
.map(key => [key, num(event[key], state[key] || 0)])
);
return {
...state,
...counts,
status: DONE,
progress: 100,
statusText: "Scan completed!",
cancelled: event.type === "cancelled",
progress: event.type === "cancelled" ? state.progress : 100,
statusText: event.type === "cancelled" ? "Scan cancelled." : "Scan completed!",
processed: num(event.processed, state.processed),
found: num(event.found, state.found),
added: num(event.added, state.added),
@@ -93,8 +99,14 @@
return `Scanning ${pct}% · ${state.processed} files · ${state.found} prompts`;
}
function completionLabel(state) {
const review = (state.ambiguous || 0) + (state.unresolved || 0) + (state.conflict || 0);
return `${state.cancelled ? 'Scan cancelled' : 'Scan completed'}! Processed ${state.processed} files, found ${state.found} prompts; ${state.added} new image records, ${state.linked} links, ${state.enriched || 0} enriched, ${state.unchanged || 0} unchanged; ${state.pairs_added || 0} new pairs, ${state.pair_links_added || 0} pair links; ${review} need review, ${state.failed || 0} failed.`;
}
const api = {
initialState,
completionLabel,
reduceScanEvent,
fromStatus,
dismissAction,