diff --git a/.kiro/specs/papers-library-importer/tasks.md b/.kiro/specs/papers-library-importer/tasks.md index da8b121d1..84796213f 100644 --- a/.kiro/specs/papers-library-importer/tasks.md +++ b/.kiro/specs/papers-library-importer/tasks.md @@ -237,7 +237,7 @@ - _Requirements: 4.1, 4.2, 4.4, 4.6, 4.7_ - [ ] 11. Add comprehensive error handling and validation -- [ ] 11.1 Implement robust error handling +- [x] 11.1 Implement robust error handling - Implement retry mechanisms for network and storage failures - Add workspace storage quota validation - _Requirements: 5.1, 5.2, 5.3, 5.5_ @@ -247,3 +247,10 @@ - Add cleanup of temporary files and partial uploads - _Requirements: 6.1, 6.2, 6.5, 6.6_ +- [x] 11.3 Fix ImportFlow next button enablement logic + - Fix canGoNext computed property in ImportFlow.vue to check dataframeData instead of parsedEntries + - Update handleBibUpdate method to properly populate parsedEntries from dataframeData + - Ensure next button is enabled after successful bibliography upload regardless of PDF upload status + - Test that flexible upload order works correctly (bibliography first or PDFs first) + - _Requirements: 1.7, 7.3_ + diff --git a/extralit-frontend/components/features/import/ImportFlow.vue b/extralit-frontend/components/features/import/ImportFlow.vue index 66f7d5a8b..ae222d1b6 100644 --- a/extralit-frontend/components/features/import/ImportFlow.vue +++ b/extralit-frontend/components/features/import/ImportFlow.vue @@ -61,7 +61,6 @@ export default { // Step data bibData: { fileName: "", - parsedEntries: [], dataframeData: null, rawContent: "", }, @@ -133,7 +132,9 @@ export default { // 1. Both bibliography and PDFs are uploaded, OR // 2. Only bibliography is uploaded (can import references without PDFs) return ( - this.bibData.parsedEntries.length > 0 && + this.bibData.dataframeData && + this.bibData.dataframeData.data && + this.bibData.dataframeData.data.length > 0 && !this.hasError && !!this.workspace ); @@ -200,7 +201,9 @@ export default { // Allow flexible upload order - can proceed if bibliography is uploaded // PDFs are optional for proceeding to analysis step isValid = - this.bibData.parsedEntries.length > 0 && + this.bibData.dataframeData && + this.bibData.dataframeData.data && + this.bibData.dataframeData.data.length > 0 && !this.hasError && !!this.workspace; break; @@ -240,7 +243,6 @@ export default { handleBibUpdate(data) { this.bibData = { fileName: data.fileName || "", - parsedEntries: data.parsedEntries || [], dataframeData: data.dataframeData || null, rawContent: data.rawContent || "", }; @@ -381,7 +383,7 @@ export default { hasDataToLose() { // Check if user has uploaded any data that would be lost on close return ( - this.bibData.parsedEntries.length > 0 || + (this.bibData.dataframeData && this.bibData.dataframeData.data && this.bibData.dataframeData.data.length > 0) || this.pdfData.totalFiles > 0 || Object.keys(this.uploadData.confirmedDocuments).length > 0 ); @@ -397,7 +399,6 @@ export default { // Reset all step data this.bibData = { fileName: "", - parsedEntries: [], dataframeData: null, rawContent: "", }; diff --git a/extralit-frontend/components/features/import/analysis/ImportAnalysisTable.vue b/extralit-frontend/components/features/import/analysis/ImportAnalysisTable.vue index b321a468a..cf23c7264 100644 --- a/extralit-frontend/components/features/import/analysis/ImportAnalysisTable.vue +++ b/extralit-frontend/components/features/import/analysis/ImportAnalysisTable.vue @@ -62,7 +62,6 @@ import "assets/icons/chevron-down"; import type { ImportAnalysisResponse, ImportStatus, - DataframeData, DocumentImportAnalysis, } from '~/v1/domain/entities/import/ImportAnalysis'; import { @@ -72,13 +71,14 @@ import { } from '../types'; import { useImportAnalysisTableViewModel } from './useImportAnalysisTableViewModel'; import { Workspace } from "~/v1/domain/entities/workspace/Workspace"; +import { TableData } from "~/v1/domain/entities/table/TableData"; export default { name: "ImportAnalysisTable", props: { dataframeData: { - type: Object as () => DataframeData | null, + type: Object as () => TableData | null, default: null, }, pdfData: { @@ -152,7 +152,6 @@ export default { canToggle: this.canToggleStatus(originalStatus) && !this.isAnalyzing, }; - // Add all other dataframe fields dynamically Object.keys(row).forEach(key => { if (!['reference', 'title', 'authors', 'author', 'year', 'filePaths'].includes(key)) { rowData[key] = row[key]; @@ -164,8 +163,9 @@ export default { }, tableData(): AnalysisTableRow[] { - // Only show rows with matched PDFs - return this.allTableData.filter(row => row.filePaths && row.filePaths.length > 0); + const filteredData = this.allTableData.filter(row => row.filePaths && row.filePaths.length > 0); + + return filteredData; }, referencesWithoutPdfsCount(): number { @@ -176,7 +176,7 @@ export default { return this.allTableData.filter(row => row.filePaths && row.filePaths.length > 0).length; }, - filteredDataframeData(): DataframeData | null { + filteredDataframeData(): TableData | null { if (!this.dataframeData) { return null; } diff --git a/extralit-frontend/components/features/import/analysis/useImportAnalysisTableViewModel.ts b/extralit-frontend/components/features/import/analysis/useImportAnalysisTableViewModel.ts index b14dc356f..db4a20985 100644 --- a/extralit-frontend/components/features/import/analysis/useImportAnalysisTableViewModel.ts +++ b/extralit-frontend/components/features/import/analysis/useImportAnalysisTableViewModel.ts @@ -1,8 +1,9 @@ import { ref, watch } from "vue"; import { useResolve } from "ts-injecty"; import { GetImportAnalysisUseCase } from "~/v1/domain/usecases/get-import-analysis-use-case"; -import type { ImportAnalysisResponse, ImportStatus, DataframeData } from "~/v1/domain/entities/import/ImportAnalysis"; +import type { ImportAnalysisResponse, ImportStatus } from "~/v1/domain/entities/import/ImportAnalysis"; import { Workspace } from "~/v1/domain/entities/workspace/Workspace"; +import { TableData } from "~/v1/domain/entities/table/TableData"; export function useImportAnalysisTableViewModel(props: any) { const isAnalyzing = ref(false); @@ -23,7 +24,7 @@ export function useImportAnalysisTableViewModel(props: any) { lastAnalysisKey.value = ""; }; - const analyzeImport = async (workspace: Workspace, dataframeData: DataframeData, matchedFiles: any[]) => { + const analyzeImport = async (workspace: Workspace, dataframeData: TableData, matchedFiles: any[]) => { if (!workspace || !dataframeData || dataframeData.data.length === 0) { return; } diff --git a/extralit-frontend/components/features/import/file-upload/CsvColumnSelection.vue b/extralit-frontend/components/features/import/file-upload/CsvColumnSelection.vue index 7e499757a..163e37ad5 100644 --- a/extralit-frontend/components/features/import/file-upload/CsvColumnSelection.vue +++ b/extralit-frontend/components/features/import/file-upload/CsvColumnSelection.vue @@ -85,7 +85,7 @@