2025-06-21 12:49:04 +00:00
|
|
|
import { getUser } from '@/auth/authService';
|
|
|
|
|
import type { User } from 'oidc-client-ts';
|
|
|
|
|
import React, { useEffect, useState } from 'react';
|
2025-06-21 17:26:45 +00:00
|
|
|
import AlertError from './AlertError';
|
2025-06-23 19:45:53 +00:00
|
|
|
import { Spinner } from './Spinner';
|
2025-06-21 12:49:04 +00:00
|
|
|
import { HoverCard, HoverCardContent, HoverCardTrigger } from './ui/hover-card';
|
|
|
|
|
import { Progress } from './ui/progress';
|
|
|
|
|
|
|
|
|
|
interface ModalProps {
|
|
|
|
|
taskID: string | null;
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-22 21:20:42 +00:00
|
|
|
const fetchTaskStatusData = async (user: User, taskID: string) => {
|
2025-06-21 12:49:04 +00:00
|
|
|
const accessToken = user?.access_token;
|
|
|
|
|
const response = await fetch(`/api/task_status?task_id=${taskID}`, {
|
|
|
|
|
method: 'GET',
|
|
|
|
|
headers: {
|
|
|
|
|
'Authorization': `Bearer ${accessToken}`, // Pass the token
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
if (!response.ok) {
|
|
|
|
|
throw new Error(`Failed to fetch task status: ${response.status}`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const data =
|
|
|
|
|
await response.json();
|
|
|
|
|
return data;
|
|
|
|
|
};
|
|
|
|
|
|
2025-06-22 21:20:42 +00:00
|
|
|
type TaskStatus = string
|
|
|
|
|
// enum TaskStatus {
|
|
|
|
|
// QUEUED = 'queued',
|
|
|
|
|
// PROCESSING = 'processing',
|
|
|
|
|
// COMPLETED = 'completed',
|
|
|
|
|
// FAILED = 'failed',
|
|
|
|
|
// }
|
2025-06-21 12:49:04 +00:00
|
|
|
|
2025-06-22 21:20:42 +00:00
|
|
|
// const taskStatusToProgress = (taskStatus: TaskStatus): number => {
|
|
|
|
|
// switch (taskStatus) {
|
|
|
|
|
// case TaskStatus.QUEUED:
|
|
|
|
|
// return 0.33; // Queued status
|
|
|
|
|
// case TaskStatus.PROCESSING:
|
|
|
|
|
// return 0.66; // Processing status
|
|
|
|
|
// case TaskStatus.COMPLETED:
|
|
|
|
|
// return 1.0; // Completed status
|
|
|
|
|
// default:
|
|
|
|
|
// throw new Error('Unknown task status: ' + status);
|
|
|
|
|
// }
|
|
|
|
|
// }
|
2025-06-21 12:49:04 +00:00
|
|
|
|
2025-06-22 21:20:42 +00:00
|
|
|
// const getTaskStatus = (status: string): TaskStatus => {
|
|
|
|
|
// switch (status.toLowerCase()) {
|
|
|
|
|
// case 'queued':
|
|
|
|
|
// return TaskStatus.QUEUED;
|
|
|
|
|
// case 'processing':
|
|
|
|
|
// return TaskStatus.PROCESSING;
|
|
|
|
|
// case 'completed':
|
|
|
|
|
// return TaskStatus.COMPLETED;
|
|
|
|
|
// case 'failed':
|
|
|
|
|
// return TaskStatus.FAILED;
|
|
|
|
|
// default:
|
|
|
|
|
// throw new Error('Unknown task status: ' + status);
|
|
|
|
|
// }
|
|
|
|
|
// };
|
2025-06-21 12:49:04 +00:00
|
|
|
|
|
|
|
|
const ActiveQuery: React.FC<ModalProps> = ({
|
|
|
|
|
taskID
|
|
|
|
|
}) => {
|
|
|
|
|
const [user, setUser] = useState<User | null>(null);
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
getUser().then(setUser);
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
const [progressPercentage, setProgressPercentage] = useState<number>(0);
|
2025-06-22 21:20:42 +00:00
|
|
|
const [taskStatus, setTaskStatus] = useState<TaskStatus | null>("PENDING");
|
2025-06-21 12:49:04 +00:00
|
|
|
const [lastUpdateTime, setLastUpdateTime] = useState<Date>(new Date());
|
2025-06-21 17:26:45 +00:00
|
|
|
const [fetchStatusError, setFetchStatusError] = useState<string | null>(null);
|
|
|
|
|
const [alertDialogIsOpen, setAlertDialogIsOpen] = useState(false);
|
2025-06-21 12:49:04 +00:00
|
|
|
|
2025-06-22 21:20:42 +00:00
|
|
|
const fetchTaskStatus = async (interval: NodeJS.Timeout) => {
|
|
|
|
|
if (!user || !taskID) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
let data = null
|
|
|
|
|
try {
|
|
|
|
|
data = await fetchTaskStatusData(user, taskID);
|
|
|
|
|
} catch (error: any) {
|
|
|
|
|
clearInterval(interval);
|
|
|
|
|
setTaskStatus("FAILURE")
|
|
|
|
|
setAlertDialogIsOpen(true)
|
|
|
|
|
if (error instanceof Error) {
|
|
|
|
|
setFetchStatusError(error.message)
|
|
|
|
|
} else {
|
|
|
|
|
setFetchStatusError('Failed to update task status: ' + error.toString())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!data) {
|
|
|
|
|
clearInterval(interval);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
setLastUpdateTime(new Date());
|
|
|
|
|
// const taskStatus = getTaskStatus(data.status);
|
|
|
|
|
const taskStatus = data.status;
|
2025-06-23 19:45:53 +00:00
|
|
|
setTaskStatus(taskStatus);
|
|
|
|
|
if (taskStatus === "FAILURE" || taskStatus === "REVOKED") {
|
2025-06-22 21:20:42 +00:00
|
|
|
clearInterval(interval);
|
2025-06-23 19:45:53 +00:00
|
|
|
throw new Error('Task failed. status: ' + taskStatus);
|
2025-06-22 21:20:42 +00:00
|
|
|
}
|
|
|
|
|
// const progress = taskStatusToProgress(taskStatus);
|
|
|
|
|
const parsedResult = JSON.parse(data.result)
|
|
|
|
|
setProgressPercentage(parsedResult.progress * 100);
|
|
|
|
|
if (taskStatus === "SUCCESS") {
|
|
|
|
|
clearInterval(interval);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2025-06-21 12:49:04 +00:00
|
|
|
// fetch status periodically
|
|
|
|
|
// maybe move to ws one day
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const interval = setInterval
|
2025-06-22 21:20:42 +00:00
|
|
|
(() => fetchTaskStatus(interval), 5000); // every 5 seconds
|
2025-06-21 12:49:04 +00:00
|
|
|
return () => clearInterval(interval);
|
|
|
|
|
}, [taskID]);
|
|
|
|
|
|
|
|
|
|
if (!taskID) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<div>
|
|
|
|
|
<HoverCard>
|
|
|
|
|
<HoverCardTrigger>
|
2025-06-21 17:26:45 +00:00
|
|
|
{taskStatus && <>Task status: {taskStatus} </>}
|
2025-06-21 12:49:04 +00:00
|
|
|
<Progress value={progressPercentage} />
|
2025-06-23 19:45:53 +00:00
|
|
|
{taskStatus && taskStatus !== 'SUCCESS' && taskStatus !== 'FAILURE' && taskStatus !== 'REVOKED' && <Spinner />}
|
2025-06-21 12:49:04 +00:00
|
|
|
</HoverCardTrigger>
|
|
|
|
|
<HoverCardContent>
|
|
|
|
|
Task ID: {taskID}
|
|
|
|
|
<br />
|
|
|
|
|
Last updated: {lastUpdateTime.toLocaleString()}
|
|
|
|
|
</HoverCardContent>
|
|
|
|
|
</HoverCard>
|
|
|
|
|
</div>
|
2025-06-21 17:26:45 +00:00
|
|
|
<AlertError message={fetchStatusError} open={alertDialogIsOpen} setIsOpen={setAlertDialogIsOpen} />
|
2025-06-21 12:49:04 +00:00
|
|
|
</>
|
|
|
|
|
)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default ActiveQuery;
|