diff --git a/src/main/main.ts b/src/main/main.ts index 1fc72e20..f5dee18c 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -387,7 +387,7 @@ export const createWindow = async (visible: boolean = true) => { }; mainWindow = new BrowserWindow({ - show: false, + show: true, //set to max with on mac screen width: 1560, height: 1024, @@ -459,18 +459,6 @@ export const createWindow = async (visible: boolean = true) => { }); - mainWindow.on('ready-to-show', () => { - if (!mainWindow) { - throw new Error('"mainWindow" is not defined'); - } - mainWindow.show() - // if (process.env.START_MINIMIZED) { - // mainWindow.minimize(); - // } else { - // mainWindow.show(); - // } - }); - ipcMain.on('show-dev-tools', (event) => { try { console.log('OPENING DEVTOOLS!'); @@ -1101,15 +1089,4 @@ ipcMain.on('open-platform-export-folder', (event, company, name) => { const exportFolderPath = path.join(app.getPath('userData'), 'surfer_data', company, name); console.log('exportFolderPath', exportFolderPath); shell.openPath(exportFolderPath); -}); - -// app.on('before-quit', (event) => { -// event.preventDefault(); // Prevent the app from quitting immediately -// mainWindow?.webContents.send('stop-all-jobs'); -// }); - -// // ... rest of the existing code ... - -// ipcMain.on('jobs-stopped', () => { -// app.exit(0); // Now we can safely exit the app -// }); +}); \ No newline at end of file diff --git a/src/renderer/Surfer.tsx b/src/renderer/Surfer.tsx index cc11820c..48c40b5f 100644 --- a/src/renderer/Surfer.tsx +++ b/src/renderer/Surfer.tsx @@ -64,19 +64,10 @@ function Surfer() { dispatch(setCurrentRoute(route)); }); - const handleStopAllJobs = async () => { - console.log('Stopping all jobs...'); - await dispatch(stopAllJobs()); - window.electron.ipcRenderer.send('jobs-stopped'); - }; - - window.electron.ipcRenderer.on('stop-all-jobs', handleStopAllJobs); - // Cleanup return () => { window.removeEventListener('keydown', handleKeyDown); window.electron.ipcRenderer.removeAllListeners('route-change'); - window.electron.ipcRenderer.removeListener('stop-all-jobs', handleStopAllJobs); }; }, [dispatch, contentScale]); diff --git a/src/renderer/components/PlatformDashboard.jsx b/src/renderer/components/PlatformDashboard.jsx index 0d5585fb..26bef2f1 100644 --- a/src/renderer/components/PlatformDashboard.jsx +++ b/src/renderer/components/PlatformDashboard.jsx @@ -1,16 +1,14 @@ import React, { useEffect, useState, useCallback, useRef } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { startRun, toggleRunVisibility, setExportRunning, updateExportStatus, addRun } from '../state/actions'; -import { useTheme } from './ui/theme-provider'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "./ui/table"; import { Button } from "./ui/button"; import { ArrowUpRight, ArrowRight, Check, X, Link, Download, Search, ChevronLeft, ChevronRight, HardDriveDownload, Folder, Eye } from 'lucide-react'; -import { openDB } from 'idb'; import { Input } from "./ui/input"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter } from "./ui/dialog"; import { Checkbox } from "./ui/checkbox"; import { Progress } from "./ui/progress"; -import RunDetailsPage from './RunDetails'; +import RunDetails from './RunDetails'; import ConfettiExplosion from 'react-confetti-explosion'; import { Tooltip, TooltipProvider, TooltipTrigger, TooltipContent } from "./ui/tooltip"; import { Info } from 'lucide-react'; @@ -22,13 +20,10 @@ import { MoonLoader } from 'react-spinners'; const PlatformDashboard = ({ onPlatformClick, webviewRef }) => { const dispatch = useDispatch(); const runs = useSelector(state => state.app.runs); - const activeRuns = runs.filter( - (run) => run.status === 'pending' || run.status === 'running', - ); + const [searchTerm, setSearchTerm] = useState(''); const [currentPage, setCurrentPage] = useState(1); const itemsPerPage = 20; - const { theme } = useTheme(); // Get the current theme const [dbUpdateTrigger, setDbUpdateTrigger] = useState(0); const dbRef = useRef(null); const [selectedRun, setSelectedRun] = useState(null); @@ -41,9 +36,6 @@ const PlatformDashboard = ({ onPlatformClick, webviewRef }) => { const [allPlatforms, setAllPlatforms] = useState([]); - const LOGO_SIZE = 24; // Set a consistent size for all logos - - useEffect(() => { // Listen for runs request from main process const handleGetRunsRequest = () => { @@ -59,39 +51,9 @@ useEffect(() => { }; }, [runs]); - const loadRuns = useCallback(async () => { - const db = await openDB('dataExtractionDB', 1, { - upgrade(db) { - db.createObjectStore('runs', { keyPath: 'id' }); - }, - }); - dbRef.current = db; - const loadedRuns = await db.getAll('runs'); - }, [dispatch]); - useEffect(() => { - loadRuns(); - return () => { - if (dbRef.current) { - dbRef.current.close(); - } - }; - }, [loadRuns, dbUpdateTrigger]); - - useEffect(() => { - const handleDbChange = () => { - setDbUpdateTrigger(prev => prev + 1); - }; - - window.electron.ipcRenderer.on('db-changed', handleDbChange); - - return () => { - window.electron.ipcRenderer.removeListener('db-changed', handleDbChange); - }; - }, []); - - const getLatestRun = useCallback((platformId) => { + const getLatestRun = (platformId) => { const platformRuns = runs.filter(run => run.platformId === platformId); if (platformRuns.length === 0) return null; @@ -100,7 +62,7 @@ useEffect(() => { const currentDate = current.startDate ? new Date(current.startDate) : new Date(0); return currentDate > latestDate ? current : latest; }); - }, [runs]); + }; useEffect(() => { @@ -152,7 +114,7 @@ useEffect(() => { return () => { window.electron.ipcRenderer.removeListener('element-found', handleElementFound); }; - }, [connectedPlatforms]); + }, [allPlatforms]); // useEffect(() => { // const runisUpdateds = async () => { @@ -270,100 +232,77 @@ useEffect(() => { setSelectedRun(null); }; -const renderResults = (platform) => { +const renderRunStatus = (platform) => { const latestRun = getLatestRun(platform.id); - const exportRunning = isExportRunning(platform.id); - const isHovered = hoveredPlatformId === platform.id; + if (!latestRun || latestRun.status !== 'running' || !latestRun.logs) return null; - return ( -
-
-
- {!latestRun || latestRun.status === 'idle' ? ( -
-
-
- ) : ( - renderRunStatus(latestRun, platform) - )} -
- {/* {latestRun && latestRun.status === 'running' && ( -
- {showLogs(platform)} -
- )} */} -
-
- ); -}; + // // Show loading spinner if no logs yet + // if (!latestRun.logs || latestRun.logs.length === 0) { + // return
; + // } - const renderRunStatus = (latestRun, platform) => { - if (!latestRun || !latestRun.logs || latestRun.logs.length === 0) { - return
- } const logLines = latestRun.logs.split('\n'); - switch (latestRun.status) { - case 'running': + + switch (latestRun.status) { + case 'running': return (
-
-
-
-
-                {logLines.map((line, index) => (
-                  
-                    {line}
-                    {index < logLines.length - 1 && '\n'}
-                  
-                ))}
-              
-
-
+
+
+              {logLines.map((line, index) => (
+                
+                  {line}
+                  {index < logLines.length - 1 && '\n'}
+                
+              ))}
+            
); - case 'success': - return ( -
- {completedRuns[latestRun.id] && ( - - )} -
window.electron.ipcRenderer.send('open-folder', latestRun.exportPath)} - style={{ cursor: 'pointer' }} - > - -
- - - onViewRunDetails(latestRun, platform)} - > - {formatLastRunTime(latestRun.exportDate || latestRun.startDate)} - - -
- ); - case 'error': - case 'stopped': - return ( -
- - onViewRunDetails(latestRun, platform)}> - Export {latestRun.status === 'error' ? 'failed' : 'stopped'} - + case 'success': + return ( +
+ {completedRuns[latestRun.id] && ( + + )} +
window.electron.ipcRenderer.send('open-folder', latestRun.exportPath)} + style={{ cursor: 'pointer' }} + > +
- ); - default: - return Unknown status; - } - }; + - + onViewRunDetails(latestRun, platform)} + > + {formatLastRunTime(latestRun.exportDate || latestRun.startDate)} + + +
+ ); + + case 'error': + case 'stopped': + return ( +
+ + onViewRunDetails(latestRun, platform)}> + - {formatLastRunTime(latestRun.endDate)} + +
+ ); + + default: + return null; + } +}; useEffect(() => { const logContainers = document.querySelectorAll('#log-container'); @@ -454,7 +393,7 @@ const renderResults = (platform) => { onClick={() => onPlatformClick(platform)} > {platformLogos[platform.id] && ( - {platform.name} + {platform.name} )}

@@ -470,7 +409,7 @@ const renderResults = (platform) => {

{platform.description || 'No description available'}

- {renderResults(platform)} + {renderRunStatus(platform)}
@@ -543,7 +482,7 @@ const renderResults = (platform) => {
)} {selectedRun && ( - { const dispatch = useDispatch(); const reduxRuns = useSelector(state => state.app.runs); const activeRunIndex = useSelector((state) => state.app.activeRunIndex); - const [run, setRun] = useState(null); - const [selectedTaskId, setSelectedTaskId] = useState(null); + const run = reduxRuns.find(r => r.id === runId); + const [selectedTaskId, setSelectedTaskId] = useState(() => run?.tasks[0]?.id || null); const [expandedSteps, setExpandedSteps] = useState({}); - const [, forceUpdate] = useState(); const [artifacts, setArtifacts] = useState([]); const [currentArtifactIndex, setCurrentArtifactIndex] = useState(0); const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false); - useEffect(() => { - const loadRun = async () => { - // Check if the run exists in Redux state - const reduxRun = reduxRuns.find(r => r.id === runId); - - if (reduxRun) { - setRun(reduxRun); - if (reduxRun.tasks.length > 0) { - setSelectedTaskId(reduxRun.tasks[0].id); - } - } else { - // If not in Redux, load from IndexedDB - const db = await openDB('dataExtractionDB', 1); - const loadedRun = await db.get('runs', runId); - - if (loadedRun) { - // Ensure the first task and its first step are running - if (loadedRun.tasks.length > 0) { - loadedRun.tasks[0].status = 'running'; - loadedRun.tasks[0].startTime = loadedRun.tasks[0].startTime || new Date().toISOString(); - if (loadedRun.tasks[0].steps.length > 0) { - loadedRun.tasks[0].steps[0].status = 'running'; - loadedRun.tasks[0].steps[0].startTime = loadedRun.tasks[0].steps[0].startTime || new Date().toISOString(); - } - } - - setRun(loadedRun); - if (loadedRun.tasks.length > 0) { - setSelectedTaskId(loadedRun.tasks[0].id); - } - } - } - }; - loadRun(); - - // Set up an interval to force update every second - const interval = setInterval(() => forceUpdate({}), 1000); - - // Clean up the interval on component unmount - return () => clearInterval(interval); - }, [runId, reduxRuns]); - useEffect(() => { if (run?.status === 'success' && run?.exportPath) { window.electron.ipcRenderer.send('get-artifact-files', run.exportPath); @@ -120,7 +76,7 @@ const RunDetails = ({ runId, onClose, platform }) => { dispatch(stopRun(activeRun.id)); console.log("Stopping run:", activeRun.id); // Remove the run from Redux state - dispatch(closeRun(activeRun.id)); + // dispatch(closeRun(activeRun.id)); // Adjust active run index if necessary if (activeRunIndex >= reduxRuns.length - 1) { diff --git a/src/renderer/components/WebviewManager.tsx b/src/renderer/components/WebviewManager.tsx index 53f36569..76de91b8 100644 --- a/src/renderer/components/WebviewManager.tsx +++ b/src/renderer/components/WebviewManager.tsx @@ -332,8 +332,8 @@ const WebviewManager: React.FC = ({ dispatch(stopRun(activeRun.id)); console.log('Stopping run:', activeRun.id); - // Remove the run from Redux state - dispatch(closeRun(activeRun.id)); + // // Remove the run from Redux state + // dispatch(closeRun(activeRun.id)); } }; diff --git a/src/renderer/pages/Home.jsx b/src/renderer/pages/Home.jsx index ebb9c9fd..2ab1d868 100644 --- a/src/renderer/pages/Home.jsx +++ b/src/renderer/pages/Home.jsx @@ -2,7 +2,6 @@ import React from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { setCurrentRoute, updateBreadcrumb } from '../state/actions'; import DataExtractionTable from '../components/PlatformDashboard'; -import RunDetailsPage from '../components/RunDetails'; const Home = () => { const dispatch = useDispatch(); diff --git a/src/renderer/pages/Platform.jsx b/src/renderer/pages/Platform.jsx index fe500bfd..1da6d475 100644 --- a/src/renderer/pages/Platform.jsx +++ b/src/renderer/pages/Platform.jsx @@ -12,8 +12,7 @@ import { setCurrentRoute, updateBreadcrumb } from '../state/actions'; import { formatLastRunTime } from '../helpers'; const Platform = ({ platform }) => { - const allRuns = useSelector(state => state.app.runs); - const runs = allRuns + const runs = useSelector(state => state.app.runs) .filter(run => run.platformId === platform.id) .sort((a, b) => { const dateA = new Date(a.exportDate || a.startDate); @@ -21,17 +20,12 @@ const Platform = ({ platform }) => { return dateB - dateA; }); - const [expandedRuns, setExpandedRuns] = useState({}); - const [selectedRunId, setSelectedRunId] = useState(null); + const [selectedRun, setSelectedRun] = useState(null); const dispatch = useDispatch(); - const toggleRunExpansion = (runId) => { - setExpandedRuns(prev => ({ ...prev, [runId]: !prev[runId] })); - }; const handleDeleteAllData = async () => { try { - await deleteRunsForPlatformFromDB(platform.id); dispatch(deleteRunsForPlatform(platform.id)); setRuns([]); } catch (error) { @@ -39,6 +33,14 @@ const Platform = ({ platform }) => { } }; + const onViewRunDetails = (run) => { + setSelectedRun({ run, platform }); + }; + + const handleCloseDetails = () => { + setSelectedRun(null); + }; + return (
@@ -65,7 +67,10 @@ const Platform = ({ platform }) => { {runs.map((run) => { return ( - + onViewRunDetails(run)} + > {formatLastRunTime(run.exportDate || run.startDate)} @@ -73,7 +78,6 @@ const Platform = ({ platform }) => { {run.status} - ); })} @@ -107,9 +111,9 @@ const Platform = ({ platform }) => { - {selectedRunId && ( + {selectedRun && ( diff --git a/src/renderer/state/actions.ts b/src/renderer/state/actions.ts index f4273c13..8504e56b 100644 --- a/src/renderer/state/actions.ts +++ b/src/renderer/state/actions.ts @@ -58,10 +58,6 @@ export const updateStepStatus = (runId: string, taskId: string, stepId: string, payload: { runId, taskId, stepId, status, startTime, endTime, logs }, }); -export const updateTaskStatus = (runId: string, taskId: string, status: ITask['status'], startTime?: string, endTime?: string, logs?: string) => ({ - type: 'UPDATE_TASK_STATUS', - payload: { runId, taskId, status, startTime, endTime, logs }, -}); export const deleteRunsForPlatform = (platformId: string) => ({ type: 'DELETE_RUNS_FOR_PLATFORM', diff --git a/src/renderer/state/reducers.ts b/src/renderer/state/reducers.ts index 2b30c182..a7d2702b 100644 --- a/src/renderer/state/reducers.ts +++ b/src/renderer/state/reducers.ts @@ -88,28 +88,7 @@ const appReducer = (state = initialAppState.app, action: any) => { : run ) }; - case 'UPDATE_TASK_STATUS': - return { - ...state, - runs: state.runs.map(run => - run.id === action.payload.runId - ? { - ...run, - tasks: run.tasks.map(task => - task.id === action.payload.taskId - ? { - ...task, - status: action.payload.status, - startTime: action.payload.startTime, - endTime: action.payload.endTime, - logs: action.payload.logs || task.logs - } - : task - ) - } - : run - ) - }; + case 'STOP_RUN': return { ...state,