From d21046303ad728b3e4357f8bd277fc676e642328 Mon Sep 17 00:00:00 2001 From: Anshul Date: Sun, 25 Jan 2026 02:58:52 +0530 Subject: [PATCH 1/3] persist state of import analysis table columns --- .../components/features/import/ImportFlow.vue | 1 + .../features/import/analysis/ImportAnalysisTable.vue | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/extralit-frontend/components/features/import/ImportFlow.vue b/extralit-frontend/components/features/import/ImportFlow.vue index ceca12b1f..194ebc1d4 100644 --- a/extralit-frontend/components/features/import/ImportFlow.vue +++ b/extralit-frontend/components/features/import/ImportFlow.vue @@ -36,6 +36,7 @@ :pdf-data="pdfData" :workspace="workspace" :loading="isAnalyzing" + :initial-document-actions="uploadData.documentActions" @update="handleAnalysisUpdate" @analysis-complete="handleAnalysisComplete" /> diff --git a/extralit-frontend/components/features/import/analysis/ImportAnalysisTable.vue b/extralit-frontend/components/features/import/analysis/ImportAnalysisTable.vue index b8a760646..0bb469096 100644 --- a/extralit-frontend/components/features/import/analysis/ImportAnalysisTable.vue +++ b/extralit-frontend/components/features/import/analysis/ImportAnalysisTable.vue @@ -107,13 +107,17 @@ export default { type: Boolean, default: false, }, + initialDocumentActions: { + type: Object as () => Record, + default: () => ({}), + }, }, emits: ["update", "analysis-complete"], data() { return { - localDocumentActions: {} as Record, + localDocumentActions: { ...this.initialDocumentActions } as Record, editableTableData: [] as any[], }; }, @@ -439,8 +443,10 @@ export default { analysisResult: { handler(newData: ImportAnalysisResponse) { if (newData) { - // Reset local document actions when new analysis data arrives - this.localDocumentActions = {}; + // Preserve status overrides when this step is remounted. + if (!this.initialDocumentActions || Object.keys(this.initialDocumentActions).length === 0) { + this.localDocumentActions = {}; + } // Emit the analysis complete event this.$emit("analysis-complete", newData); // Emit initial update From 060b248e7f5ccb967fabc1cb2886dcc1c75042ee Mon Sep 17 00:00:00 2001 From: Anshul Date: Sun, 1 Mar 2026 12:00:40 +0530 Subject: [PATCH 2/3] copilot changes applied --- .../components/features/import/ImportFlow.vue | 2 ++ .../import/analysis/ImportAnalysisTable.vue | 14 +++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/extralit-frontend/components/features/import/ImportFlow.vue b/extralit-frontend/components/features/import/ImportFlow.vue index 194ebc1d4..decaef802 100644 --- a/extralit-frontend/components/features/import/ImportFlow.vue +++ b/extralit-frontend/components/features/import/ImportFlow.vue @@ -274,6 +274,7 @@ export default { dataframeData: data.dataframeData || null, rawContent: data.rawContent || "", }; + this.uploadData.documentActions = {}; this.clearError(); }, @@ -283,6 +284,7 @@ export default { unmatchedFiles: data.unmatchedFiles || [], totalFiles: data.totalFiles || 0, }; + this.uploadData.documentActions = {}; this.clearError(); }, diff --git a/extralit-frontend/components/features/import/analysis/ImportAnalysisTable.vue b/extralit-frontend/components/features/import/analysis/ImportAnalysisTable.vue index 0bb469096..7e4048b90 100644 --- a/extralit-frontend/components/features/import/analysis/ImportAnalysisTable.vue +++ b/extralit-frontend/components/features/import/analysis/ImportAnalysisTable.vue @@ -443,10 +443,18 @@ export default { analysisResult: { handler(newData: ImportAnalysisResponse) { if (newData) { - // Preserve status overrides when this step is remounted. - if (!this.initialDocumentActions || Object.keys(this.initialDocumentActions).length === 0) { - this.localDocumentActions = {}; + // Filter persisted actions to only keys present in the new analysis, + // discarding stale entries from a previous Bib/PDF set + const validKeys = new Set(Object.keys(newData.documents ?? {})); + const filtered: Record = {}; + if (this.initialDocumentActions) { + for (const [key, status] of Object.entries(this.initialDocumentActions)) { + if (validKeys.has(key)) { + filtered[key] = status as ImportStatus; + } + } } + this.localDocumentActions = filtered; // Emit the analysis complete event this.$emit("analysis-complete", newData); // Emit initial update From 54858ac15d3a756b853ec3302a1b5d6e88e177f5 Mon Sep 17 00:00:00 2001 From: Anshul Date: Thu, 16 Jul 2026 16:43:47 +0530 Subject: [PATCH 3/3] test: cover import analysis action persistence --- .../analysis/ImportAnalysisTable.spec.ts | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 extralit-frontend/components/features/import/analysis/ImportAnalysisTable.spec.ts diff --git a/extralit-frontend/components/features/import/analysis/ImportAnalysisTable.spec.ts b/extralit-frontend/components/features/import/analysis/ImportAnalysisTable.spec.ts new file mode 100644 index 000000000..bf77d80df --- /dev/null +++ b/extralit-frontend/components/features/import/analysis/ImportAnalysisTable.spec.ts @@ -0,0 +1,49 @@ +import ImportAnalysisTable from "./ImportAnalysisTable.vue"; +import ImportFlow from "../ImportFlow.vue"; + +describe("ImportAnalysisTable document actions", () => { + it("restores persisted actions when the review step is remounted", () => { + const component = ImportAnalysisTable as any; + const state = component.data.call({ initialDocumentActions: { keep: "ignore" } }); + + expect(state.localDocumentActions).toEqual({ keep: "ignore" }); + expect(state.editableTableData).toEqual([]); + }); + + it("keeps only persisted actions that belong to the latest analysis", () => { + const component = ImportAnalysisTable as any; + const context = { + initialDocumentActions: { keep: "ignore", stale: "update" }, + localDocumentActions: {}, + $emit: vi.fn(), + emitUpdate: vi.fn(), + }; + + component.watch.analysisResult.handler.call(context, { + documents: { keep: {} }, + }); + + expect(context.localDocumentActions).toEqual({ keep: "ignore" }); + expect(context.$emit).toHaveBeenCalledWith("analysis-complete", { documents: { keep: {} } }); + expect(context.emitUpdate).toHaveBeenCalledOnce(); + }); +}); + +describe("ImportFlow input changes", () => { + it("clears persisted actions when the bibliography or PDFs change", () => { + const component = ImportFlow as any; + const context = { + bibData: {}, + pdfData: {}, + uploadData: { documentActions: { previous: "ignore" } }, + clearError: vi.fn(), + }; + + component.methods.handleBibUpdate.call(context, { fileName: "new.bib" }); + expect(context.uploadData.documentActions).toEqual({}); + + context.uploadData.documentActions = { previous: "ignore" }; + component.methods.handlePdfUpdate.call(context, { totalFiles: 1 }); + expect(context.uploadData.documentActions).toEqual({}); + }); +});