processing time

pull/1755/head
BasilBP 2025-09-29 12:25:59 +05:30
rodzic a8ab95131f
commit ec57a5fc77
3 zmienionych plików z 111 dodań i 82 usunięć

Wyświetl plik

@ -125,7 +125,8 @@ export default function MainMenu(props) {
...task,
progressPct,
status: taskStatus,
running_progress: taskDetail.running_progress || 0
running_progress: taskDetail.running_progress || 0,
processing_time: taskDetail.processing_time || null
};
} catch (e) {
// This catch block handles network errors or JSON parsing errors, but not 404s
@ -366,6 +367,7 @@ export default function MainMenu(props) {
} finally {
sessionStorage.removeItem('username');
props.setIsLogged(false);
navigate('/');
}
}} className="logout-dialog-btn">Yes</button>
<button onClick={() => setShowLogoutDialog(false)} className="logout-dialog-btn no">No</button>

Wyświetl plik

@ -374,6 +374,15 @@
background: #ddd;
color: #222;
}
.task-processing-time {
margin-top: 0.75rem;
}
.processing-time-text {
color: #718096;
font-size: 0.85rem;
font-weight: 400;
}
/* ====== THUMBNAILS ====== */
.task-thumbnail {

Wyświetl plik

@ -4,11 +4,23 @@ import ProjectViewer from "./ProjectContainer.jsx";
import Export from './Export.jsx';
import { authorizedFetch } from '../utils/api.js';
// New TaskBox component with thumbnail hover functionality
// Helper function from the first code block for processing time format
const formatProcessingTime = (milliseconds) => {
const totalSeconds = Math.floor(milliseconds / 1000);
const hours = Math.floor(totalSeconds / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const seconds = totalSeconds % 60;
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
};
// New TaskBox component with processing time functionality and second block's UI
const TaskBox = ({ task, onAction, onShowDeleteDialog, fetchJSON, isDeleteDialogOpen = false, openExportTaskId, setOpenExportTaskId }) => {
const [lastError, setLastError] = useState(null);
const [isHovering, setIsHovering] = useState(false);
const [thumbnailUrl, setThumbnailUrl] = useState(null);
// Added state for processing time
const [processingTime, setProcessingTime] = useState(null);
const fetchLastError = useCallback(async () => {
if (task.status === 30) {
@ -30,7 +42,11 @@ const TaskBox = ({ task, onAction, onShowDeleteDialog, fetchJSON, isDeleteDialog
useEffect(() => {
fetchLastError();
}, [fetchLastError]);
// Added logic for setting processing time on completion
if (task.status === 40 && task.processing_time && !processingTime) {
setProcessingTime(task.processing_time);
}
}, [fetchLastError, task, processingTime]); // Dependency array updated
const getStatusText = (statusCode) => {
switch (statusCode) {
@ -83,7 +99,7 @@ const TaskBox = ({ task, onAction, onShowDeleteDialog, fetchJSON, isDeleteDialog
</div>
</div>
<div className="task-id-row">
<span className="task-id">{task.id}</span>
<span className="task-id">ID: {task.id}</span>
</div>
<div className="task-content">
{effectiveStatus === 30 && lastError && (
@ -109,6 +125,12 @@ const TaskBox = ({ task, onAction, onShowDeleteDialog, fetchJSON, isDeleteDialog
)}
</div>
)}
{/* Processing Time Display added here, as per the first code block's functionality */}
{effectiveStatus === 40 && processingTime && (
<div className="task-processing-time">
<span className="processing-time-text">{formatProcessingTime(processingTime)}</span>
</div>
)}
</div>
<div className="task-actions">
{effectiveStatus === 20 && (
@ -148,17 +170,10 @@ const TaskBox = ({ task, onAction, onShowDeleteDialog, fetchJSON, isDeleteDialog
)}
</div>
</div>
{/* Thumbnail container outside the main content but inside the task-box */}
{/* Thumbnail container exactly as in the second code block (no click handler) */}
{isHovering && effectiveStatus === 40 && thumbnailUrl && (
<div className="task-thumbnail-wrapper">
<button
type="button"
className="thumbnail-button"
onClick={() => handleAction('view')}
title="View"
>
<img src={thumbnailUrl} alt={`Thumbnail for task ${task.id}`} className="task-thumbnail" />
</button>
</div>
)}
</div>
@ -169,9 +184,7 @@ const TaskBox = ({ task, onAction, onShowDeleteDialog, fetchJSON, isDeleteDialog
const Tasks = ({ runningTasks, loading, onRefresh, onTaskAction ,isViewing,exitView,selectedTask, filterProjectId, setFilterProjectId, projects }) => {
const [deleteDialogTask, setDeleteDialogTask] = useState(null);
const [filterProjectName, setFilterProjectName] = useState(null);
// Share delete dialog state with child components
const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);
// Add state to track the currently open Export dropdown
const [openExportTaskId, setOpenExportTaskId] = useState(null);
useEffect(() => {
@ -266,6 +279,7 @@ const Tasks = ({ runningTasks, loading, onRefresh, onTaskAction ,isViewing,exitV
<>
{categorizedTasks.running.length > 0 && (
<div className="task-category">
<h3>Running Tasks ({categorizedTasks.running.length})</h3>
<div className="tasks-grid">
{categorizedTasks.running.map((task) => (
<TaskBox
@ -284,6 +298,7 @@ const Tasks = ({ runningTasks, loading, onRefresh, onTaskAction ,isViewing,exitV
)}
{categorizedTasks.completed.length > 0 && (
<div className="task-category">
<h3>Completed Tasks ({categorizedTasks.completed.length})</h3>
<div className="tasks-grid">
{categorizedTasks.completed.map((task) => (
<TaskBox
@ -302,6 +317,7 @@ const Tasks = ({ runningTasks, loading, onRefresh, onTaskAction ,isViewing,exitV
)}
{categorizedTasks.failed.length > 0 && (
<div className="task-category">
<h3>Failed Tasks ({categorizedTasks.failed.length})</h3>
<div className="tasks-grid">
{categorizedTasks.failed.map((task) => (
<TaskBox
@ -320,6 +336,7 @@ const Tasks = ({ runningTasks, loading, onRefresh, onTaskAction ,isViewing,exitV
)}
{categorizedTasks.canceled.length > 0 && (
<div className="task-category">
<h3>Canceled Tasks ({categorizedTasks.canceled.length})</h3>
<div className="tasks-grid">
{categorizedTasks.canceled.map((task) => (
<TaskBox
@ -338,6 +355,7 @@ const Tasks = ({ runningTasks, loading, onRefresh, onTaskAction ,isViewing,exitV
)}
{categorizedTasks.queued.length > 0 && (
<div className="task-category">
<h3>Queued Tasks ({categorizedTasks.queued.length})</h3>
<div className="tasks-grid">
{categorizedTasks.queued.map((task) => (
<TaskBox