Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 60 additions & 6 deletions src/frontend/src/pages/modernizationPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { Light as SyntaxHighlighter } from "react-syntax-highlighter"
import { vs } from "react-syntax-highlighter/dist/esm/styles/hljs"
import sql from "react-syntax-highlighter/dist/cjs/languages/hljs/sql"
import { useNavigate, useParams } from "react-router-dom"
import { useState, useEffect, useCallback } from "react"
import { useState, useEffect, useCallback, useRef } from "react"
import { getApiUrl, headerBuilder } from '../api/config';
import BatchHistoryPanel from "../components/batchHistoryPanel"
import PanelRight from "../components/Panels/PanelRight";
Expand Down Expand Up @@ -501,6 +501,7 @@ const ModernizationPage = () => {
const [isZipButtonDisabled, setIsZipButtonDisabled] = useState(true);
const [fileLoading, setFileLoading] = useState(false);
const [lastActivityTime, setLastActivityTime] = useState<number>(Date.now());
const hasNavigatedRef = useRef(false);
//const [pageLoadTime] = useState<number>(Date.now());

// Fetch file content when a file is selected
Expand Down Expand Up @@ -536,12 +537,22 @@ const ModernizationPage = () => {
setBatchSummary(data);
if (data) {

const batchCompleted = data.status?.toLowerCase() === "completed" || data.status === "failed";
if (batchCompleted) {
const batchCompleted = data.status?.toLowerCase() === "completed" || data.status?.toLowerCase() === "failed";
const allFilesTerminal = data.files.every((file: any) =>
["completed", "failed", "error"].includes(file.status?.toLowerCase() || "")
);

if (batchCompleted || allFilesTerminal) {
setAllFilesCompleted(true);
if (data.hasFiles > 0) {
setIsZipButtonDisabled(false);
}
// Batch already finished (e.g., all files were harmful content) — navigate directly
if (!hasNavigatedRef.current) {
hasNavigatedRef.current = true;
navigate(`/batch-view/${batchId}`);
return;
}
}
// Transform the server response to an array of your FileItem objects
const fileItems: FileItem[] = data.files.map((file: any, index: number) => ({
Expand Down Expand Up @@ -725,7 +736,10 @@ const ModernizationPage = () => {
// Update files state when Redux fileList changes
useEffect(() => {
if (reduxFileList && reduxFileList.length > 0) {
setAllFilesCompleted(false);
// Only reset completion state if not already finalized
if (!allFilesCompleted) {
setAllFilesCompleted(false);
}
// Map the Redux fileList to our FileItem format
const fileItems: FileItem[] = reduxFileList.filter(file => file.type !== 'summary').map((file: any, index: number) => ({

Expand Down Expand Up @@ -832,8 +846,11 @@ const ModernizationPage = () => {
});

// Navigate only after all files have reached terminal states.
console.log("Processing complete (all files done), navigating to batch view page");
navigate(`/batch-view/${batchId}`);
if (!hasNavigatedRef.current) {
hasNavigatedRef.current = true;
console.log("Processing complete (all files done), navigating to batch view page");
navigate(`/batch-view/${batchId}`);
}
}
} catch (err) {
console.error("Failed to update summary status:", err);
Expand Down Expand Up @@ -996,6 +1013,43 @@ useEffect(() => {
return () => clearInterval(checkInactivity);
}, [lastActivityTime, files, allFilesCompleted, updateSummaryStatus, navigate, batchId]);

// Fallback polling: periodically re-fetch batch summary to catch cases where
// WebSocket events were missed (e.g., all files were harmful and processed
// before WebSocket connected). Polls every 5 seconds until all files are done.
useEffect(() => {
if (allFilesCompleted || !batchId || hasNavigatedRef.current) return;

const pollInterval = setInterval(async () => {
if (hasNavigatedRef.current || allFilesCompleted) {
clearInterval(pollInterval);
return;
}
try {
const data = await fetchBatchSummary(batchId);
if (!data) return;

const batchTerminal = ["completed", "failed"].includes(data.status?.toLowerCase() || "");
const allTerminal = data.files.every((file: any) =>
["completed", "failed", "error"].includes(file.status?.toLowerCase() || "")
);

if (batchTerminal || allTerminal) {
console.log("Fallback poll detected batch completion, navigating to batch view");
clearInterval(pollInterval);
setAllFilesCompleted(true);
if (!hasNavigatedRef.current) {
hasNavigatedRef.current = true;
navigate(`/batch-view/${batchId}`);
}
}
} catch (err) {
console.error("Fallback poll error:", err);
}
}, 5000);

return () => clearInterval(pollInterval);
}, [batchId, allFilesCompleted, navigate]);


useEffect(() => {
console.log('Current files state:', files);
Expand Down
Loading