Loading...
;
+ }
+
+ if (!user?.is_admin) {
+ return (
+
+
+
Background Jobs
+
+
+
+
+
+
+ {successMessage &&
{successMessage}
}
+ {statusError &&
{statusError}
}
+
+ {/* PyPI Cache Jobs Section */}
+
+
+
+
+ PyPI Cache Jobs
+
+ {failedTasks.length > 0 && (
+
+ )}
+
+
+ {loadingStatus && !cacheStatus ? (
+ Loading job status...
+ ) : (
+ <>
+ {/* Status Cards */}
+
+
+
{cacheStatus?.pending ?? 0}
+
Pending
+
+
+
{cacheStatus?.in_progress ?? 0}
+
In Progress
+
+
+
{cacheStatus?.completed ?? 0}
+
Completed
+
+
+
{cacheStatus?.failed ?? 0}
+
Failed
+
+
+
+ {totalJobs === 0 ? (
+ No cache jobs yet. Jobs are created when packages are downloaded through the PyPI proxy.
+ ) : failedTasks.length === 0 ? (
+ All jobs completed successfully.
+ ) : (
+ <>
+ Failed Tasks
+
+
+
+ | Package |
+ Error |
+ Attempts |
+ Depth |
+ Failed At |
+ Actions |
+
+
+
+ {failedTasks.map((task) => (
+
+ | {task.package} |
+
+ {task.error || 'Unknown error'}
+ |
+ {task.attempts} |
+ {task.depth} |
+
+ {task.failed_at
+ ? new Date(task.failed_at).toLocaleString()
+ : '-'}
+ |
+
+
+ |
+
+ ))}
+
+
+ >
+ )}
+ >
+ )}
+
+
+ {/* Placeholder for future job types */}
+
+
+
+
+ NPM Cache Jobs
+ Coming Soon
+
+
+ NPM proxy support is planned for a future release.
+
+
+ );
+}
+
+export default AdminJobsPage;
diff --git a/frontend/src/types.ts b/frontend/src/types.ts
index 8469560..f06f8d0 100644
--- a/frontend/src/types.ts
+++ b/frontend/src/types.ts
@@ -557,3 +557,26 @@ export interface UpstreamSourceTestResult {
source_id: string;
source_name: string;
}
+
+// PyPI Cache Job types
+export interface PyPICacheStatus {
+ pending: number;
+ in_progress: number;
+ completed: number;
+ failed: number;
+}
+
+export interface PyPICacheTask {
+ id: string;
+ package: string;
+ error: string | null;
+ attempts: number;
+ depth: number;
+ failed_at: string | null;
+}
+
+export interface PyPICacheRetryResponse {
+ message: string;
+ task_id?: string;
+ count?: number;
+}