Run classification previews in the background with live progress
The preview endpoint held one HTTP request open while classifying serially at three-second pacing, so any real range meant minutes of a grayed-out button and per-row errors were invisible until the loop ended. Analyse now starts a single background run against its own snapshot; a progress endpoint reports analysed counts, proposed changes and errors as they happen, and the page polls it with a progress bar, pace-based estimate and a Stop button. Navigating away no longer orphans the run: the page re-attaches to it on return. A run that has produced no successful proposal and fails three times in a row with the identical error stops early and reports that error, so a wrong key or unsupported model surfaces in seconds instead of repeating across the whole paced range. Also normalize a null settings.private_names, which crashed the whole UI on a workspace that had never saved preferences.
This commit is contained in:
@@ -200,6 +200,20 @@ export interface Preview {
|
||||
unchanged: number;
|
||||
errors: { id: string; error: string }[];
|
||||
}
|
||||
// PreviewProgress is the live state of a background classification run.
|
||||
// Errors accumulate as they happen; preview is present only when done
|
||||
// without a fatal error.
|
||||
export interface PreviewProgress {
|
||||
id: string;
|
||||
total: number;
|
||||
analysed: number;
|
||||
changes: number;
|
||||
unchanged: number;
|
||||
errors: { id: string; error: string }[];
|
||||
done: boolean;
|
||||
error?: string;
|
||||
preview?: Preview;
|
||||
}
|
||||
export interface ProposedCategory {
|
||||
name: string;
|
||||
parent?: string;
|
||||
@@ -395,6 +409,7 @@ export function normalizeState(state: State): State {
|
||||
else if (!Array.isArray(state.data[key]))
|
||||
throw new Error(`The server state has invalid ${key}.`);
|
||||
}
|
||||
state.settings.private_names ??= [];
|
||||
for (const tx of state.data.transactions) tx.enrichment.tag_ids ??= [];
|
||||
for (const merchant of state.data.merchants) {
|
||||
merchant.aliases ??= [];
|
||||
|
||||
Reference in New Issue
Block a user