Make Stop stop: no replay, no restart, immediate feedback
Build — Windows, Linux & macOS / GDPRScanner / linux (push) Has been cancelled
Build — Windows, Linux & macOS / GDPRScanner / macos (push) Has been cancelled
Build — Windows, Linux & macOS / GDPRScanner / windows (push) Has been cancelled
Build — Windows, Linux & macOS / Create GitHub Release (push) Has been cancelled
Build — Windows, Linux & macOS / GDPRScanner / linux (push) Has been cancelled
Build — Windows, Linux & macOS / GDPRScanner / macos (push) Has been cancelled
Build — Windows, Linux & macOS / GDPRScanner / windows (push) Has been cancelled
Build — Windows, Linux & macOS / Create GitHub Release (push) Has been cancelled
Pressing Stop could look like the scan restarting, and for scheduled jobs it really did restart the Google stage. - Scheduler: check the abort flag between stages and never clear the Google abort after a Stop (that started a fresh all-users Google scan). A stopped job is recorded as "cancelled" and skips email/retention; scheduler_done carries cancelled=true. - SSE: scan_cancelled and file_scan_done now end the current scan like scan_done, and sse.replay_messages() never replays a finished scan. Previously a stopped M365 scan (and every file scan) stayed "current", so each reconnect replayed it and re-showed Stop + progress. - Frontend: scan_cancelled clears the M365 running flag and only tears down the UI when no Google/file scan is still running; scheduler_done / scheduler_error clear all running flags. - run_scan: Stop during collection now ends the scan (checkpoint, finish, scan_cancelled) instead of announcing scan_start / "Scanning…". - Stop button: switches to a disabled "Stopping…" state on click; all show/hide goes through _setStopBtnDisplay(), which resets it when hidden or when a new scan starts. Adds tests/test_stop_scan.py (10 tests). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit was merged in pull request #2.
This commit is contained in:
1 parent
9cf23da907
commit
606d8e944b
12 files changed
+372
-64
No files matched your search
+56
-21
@@ -317,7 +317,7 @@ function _attachScanListeners(source) {
|
||||
else if (phaseSrc === 'file') { S._fileScanRunning = true; }
|
||||
else { S._m365ScanRunning = true; }
|
||||
document.getElementById('scanBtn').disabled = true;
|
||||
document.getElementById('stopBtn').style.display = 'inline-block';
|
||||
_setStopBtnDisplay('inline-block');
|
||||
_renderProgressSegments();
|
||||
}
|
||||
_setProgressPhase(d.phase);
|
||||
@@ -330,9 +330,9 @@ function _attachScanListeners(source) {
|
||||
: (d.total > 0 ? Math.round((d.index || d.completed || 0) / d.total * 100) : 0);
|
||||
S._srcPct[src] = pct;
|
||||
// If reconnecting mid-scan the running flag may not be set yet — ensure segment exists
|
||||
if (src === 'm365' && !S._m365ScanRunning) { S._m365ScanRunning = true; document.getElementById('scanBtn').disabled = true; document.getElementById('stopBtn').style.display = 'inline-block'; _renderProgressSegments(); }
|
||||
if (src === 'google' && !S._googleScanRunning) { S._googleScanRunning = true; document.getElementById('scanBtn').disabled = true; document.getElementById('stopBtn').style.display = 'inline-block'; _renderProgressSegments(); }
|
||||
if (src === 'file' && !S._fileScanRunning) { S._fileScanRunning = true; document.getElementById('scanBtn').disabled = true; document.getElementById('stopBtn').style.display = 'inline-block'; _renderProgressSegments(); }
|
||||
if (src === 'm365' && !S._m365ScanRunning) { S._m365ScanRunning = true; document.getElementById('scanBtn').disabled = true; _setStopBtnDisplay('inline-block'); _renderProgressSegments(); }
|
||||
if (src === 'google' && !S._googleScanRunning) { S._googleScanRunning = true; document.getElementById('scanBtn').disabled = true; _setStopBtnDisplay('inline-block'); _renderProgressSegments(); }
|
||||
if (src === 'file' && !S._fileScanRunning) { S._fileScanRunning = true; document.getElementById('scanBtn').disabled = true; _setStopBtnDisplay('inline-block'); _renderProgressSegments(); }
|
||||
var fill = document.getElementById('progressFill_' + src);
|
||||
if (fill) fill.style.width = pct + '%';
|
||||
document.getElementById('progressFile').textContent = d.file || '';
|
||||
@@ -368,15 +368,20 @@ function _attachScanListeners(source) {
|
||||
log((d.file ? d.file + ': ' : '') + d.error, 'err');
|
||||
});
|
||||
source.addEventListener('scan_cancelled', function() {
|
||||
if (S._userStartedScan) {
|
||||
// scan_cancelled is the M365 engine's "stopped" event. Clear its running
|
||||
// flag (leaving it set made later replays/status polls treat the stopped
|
||||
// scan as live) and, like scan_done, only tear down the UI once no Google
|
||||
// or file scan is still running.
|
||||
S._m365ScanRunning = false;
|
||||
var _anyRunning = S._googleScanRunning || S._fileScanRunning;
|
||||
if (S._userStartedScan && !_anyRunning) {
|
||||
S._userStartedScan = false;
|
||||
if (S.es) { S.es.close(); S.es = null; }
|
||||
}
|
||||
document.getElementById('scanBtn').disabled = false;
|
||||
document.getElementById('stopBtn').style.display = 'none';
|
||||
_clearProgressBar();
|
||||
setLogLive('');
|
||||
log('Scan stopped.', 'warn');
|
||||
document.getElementById('scanBtn').disabled = _anyRunning;
|
||||
_setStopBtnDisplay(_anyRunning ? 'inline-block' : 'none');
|
||||
if (_anyRunning) { _renderProgressSegments(); } else { _clearProgressBar(); setLogLive(''); }
|
||||
log(t('m365_scan_stopped', 'Scan stopped.'), 'warn');
|
||||
});
|
||||
source.addEventListener('scan_done', function(e) {
|
||||
var d = JSON.parse(e.data);
|
||||
@@ -401,7 +406,7 @@ function _attachScanListeners(source) {
|
||||
}
|
||||
if (!_anyRunning) setLogLive('');
|
||||
document.getElementById('scanBtn').disabled = _anyRunning;
|
||||
document.getElementById('stopBtn').style.display = _anyRunning ? 'inline-block' : 'none';
|
||||
_setStopBtnDisplay(_anyRunning ? 'inline-block' : 'none');
|
||||
if (!_anyRunning) _clearProgressBar();
|
||||
document.getElementById('statsSection').style.display = 'block';
|
||||
document.getElementById('statScanned').textContent = d.total_scanned;
|
||||
@@ -437,7 +442,7 @@ function _attachScanListeners(source) {
|
||||
}
|
||||
setLogLive('');
|
||||
document.getElementById('scanBtn').disabled = false;
|
||||
document.getElementById('stopBtn').style.display = 'none';
|
||||
_setStopBtnDisplay('none');
|
||||
_clearProgressBar();
|
||||
document.getElementById('statsSection').style.display = 'block';
|
||||
document.getElementById('statsPill').style.display = 'block';
|
||||
@@ -466,7 +471,7 @@ function _attachScanListeners(source) {
|
||||
}
|
||||
setLogLive('');
|
||||
document.getElementById('scanBtn').disabled = false;
|
||||
document.getElementById('stopBtn').style.display = 'none';
|
||||
_setStopBtnDisplay('none');
|
||||
_clearProgressBar();
|
||||
document.getElementById('statsSection').style.display = 'block';
|
||||
document.getElementById('statsPill').style.display = 'block';
|
||||
@@ -502,7 +507,7 @@ function _attachSchedulerListeners(source) {
|
||||
log('\uD83D\uDD50 ' + t('m365_sched_title','Scheduled scan') + ': ' + (d.job_name||'') + '\u2026');
|
||||
// Show progress UI so scan_phase / scan_progress events are visible
|
||||
document.getElementById('scanBtn').disabled = true;
|
||||
document.getElementById('stopBtn').style.display = 'inline-block';
|
||||
_setStopBtnDisplay('inline-block', true);
|
||||
S._srcPct = { m365: 0, google: 0, file: 0 }; S._m365ScanRunning = true; _renderProgressSegments();
|
||||
_setProgressPhase((d.job_name||'') + '\u2026');
|
||||
document.getElementById('progressFile').textContent = '';
|
||||
@@ -512,25 +517,32 @@ function _attachSchedulerListeners(source) {
|
||||
// scheduler_started was missed (e.g. browser reconnected mid-scan)
|
||||
console.log('[SSE] scan_start received');
|
||||
document.getElementById('scanBtn').disabled = true;
|
||||
document.getElementById('stopBtn').style.display = 'inline-block';
|
||||
_setStopBtnDisplay('inline-block');
|
||||
// Ensure at least the M365 segment is rendered (scan_start is M365-only)
|
||||
if (!S._m365ScanRunning) { S._m365ScanRunning = true; _renderProgressSegments(); }
|
||||
});
|
||||
source.addEventListener('scheduler_done', function(e) {
|
||||
var d = JSON.parse(e.data);
|
||||
console.log('[SSE] scheduler_done received:', d);
|
||||
// The job's stages are all over — scheduler_started set the M365 flag
|
||||
S._m365ScanRunning = S._googleScanRunning = S._fileScanRunning = false;
|
||||
document.getElementById('scanBtn').disabled = false;
|
||||
document.getElementById('stopBtn').style.display = 'none';
|
||||
_setStopBtnDisplay('none');
|
||||
_clearProgressBar();
|
||||
log('\u2713 ' + t('m365_sched_title','Scheduled scan') + ' ' + (d.job_name||'') + ' \u2014 ' + (d.flagged||0) + ' flagged', 'ok');
|
||||
if (d.cancelled) {
|
||||
log('\u23f9 ' + t('m365_sched_title','Scheduled scan') + ' ' + (d.job_name||'') + ' \u2014 ' + t('m365_sched_stopped','stopped') + ' (' + (d.flagged||0) + ' flagged)', 'warn');
|
||||
} else {
|
||||
log('\u2713 ' + t('m365_sched_title','Scheduled scan') + ' ' + (d.job_name||'') + ' \u2014 ' + (d.flagged||0) + ' flagged', 'ok');
|
||||
}
|
||||
markOverdueCards();
|
||||
loadTrend();
|
||||
});
|
||||
source.addEventListener('scheduler_error', function(e) {
|
||||
var d = JSON.parse(e.data);
|
||||
console.log('[SSE] scheduler_error received:', d);
|
||||
S._m365ScanRunning = S._googleScanRunning = S._fileScanRunning = false;
|
||||
document.getElementById('scanBtn').disabled = false;
|
||||
document.getElementById('stopBtn').style.display = 'none';
|
||||
_setStopBtnDisplay('none');
|
||||
_clearProgressBar();
|
||||
log('\u26A0 ' + t('m365_sched_title','Scheduled scan') + ' failed: ' + (d.error||''), 'err');
|
||||
});
|
||||
@@ -564,7 +576,7 @@ function startScan(resume) {
|
||||
S._progressCurrentUser = '';
|
||||
_renderProgressSegments();
|
||||
document.getElementById('scanBtn').disabled = true;
|
||||
document.getElementById('stopBtn').style.display = 'inline-block';
|
||||
_setStopBtnDisplay('inline-block', true);
|
||||
// progress segments rendered by _renderProgressSegments() called above
|
||||
document.getElementById('progressFile').textContent = '';
|
||||
_setProgressPhase(t('scan_preparing', 'Preparing…'));
|
||||
@@ -594,7 +606,7 @@ function startScan(resume) {
|
||||
if (label === 'google') S._googleScanRunning = false;
|
||||
if (!S._m365ScanRunning && !S._googleScanRunning && !S._fileScanRunning) {
|
||||
document.getElementById('scanBtn').disabled = false;
|
||||
document.getElementById('stopBtn').style.display = 'none';
|
||||
_setStopBtnDisplay('none');
|
||||
if (S.es) { S.es.close(); S.es = null; }
|
||||
S._userStartedScan = false;
|
||||
}
|
||||
@@ -664,8 +676,30 @@ function startScan(resume) {
|
||||
|
||||
}
|
||||
|
||||
// Show/hide the Stop button. Hiding — or passing fresh=true when a new scan
|
||||
// starts — resets it from its "Stopping…" state, so a new scan always gets a
|
||||
// normal, clickable Stop button even if a previous scan never reported its end.
|
||||
function _setStopBtnDisplay(display, fresh) {
|
||||
const btn = document.getElementById('stopBtn');
|
||||
if (!btn) return;
|
||||
btn.style.display = display;
|
||||
if (display === 'none' || fresh) {
|
||||
btn.disabled = false;
|
||||
btn.textContent = t('m365_btn_stop', 'Stop');
|
||||
}
|
||||
}
|
||||
|
||||
function stopScan() {
|
||||
fetch('/api/scan/stop', {method:'POST'});
|
||||
// Immediate feedback: the scan only notices the stop between items, which
|
||||
// can take a while (e.g. OCR on a large PDF). Stays "Stopping…" until the
|
||||
// scan's done/stopped event hides the button.
|
||||
const btn = document.getElementById('stopBtn');
|
||||
if (btn) { btn.disabled = true; btn.textContent = t('m365_btn_stopping', 'Stopping…'); }
|
||||
log(t('m365_scan_stopping', 'Stopping scan — finishing the current item…'), 'warn');
|
||||
fetch('/api/scan/stop', {method:'POST'}).catch(function(e) {
|
||||
if (btn) { btn.disabled = false; btn.textContent = t('m365_btn_stop', 'Stop'); }
|
||||
log('Stop failed: ' + e, 'err');
|
||||
});
|
||||
}
|
||||
|
||||
// ── Trend sparkline (#7) ──────────────────────────────────────────────────────
|
||||
@@ -795,6 +829,7 @@ window._attachScanListeners = _attachScanListeners;
|
||||
window._attachSchedulerListeners = _attachSchedulerListeners;
|
||||
window.startScan = startScan;
|
||||
window.stopScan = stopScan;
|
||||
window._setStopBtnDisplay = _setStopBtnDisplay;
|
||||
window.drawSparkline = drawSparkline;
|
||||
window.loadTrend = loadTrend;
|
||||
window.updateStats = updateStats;
|
||||
Reference in new issue
Block a user