Files
manage/frontend/src/pages/service-tabs/JobsTab.tsx
T

85 lines
2.5 KiB
TypeScript

/**
* JobsTab — operational content for the backups service page.
*
* Instance-scoped: hooks filter by instance.id so multi-instance setups
* show only the selected backups service's jobs, runs, and alerts.
*/
import { useState } from "react";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import {
useAcknowledgeAlert,
useBackupAlerts,
useBackupJobs,
useBackupRuns,
} from "../../hooks/useBackups";
import BackupAlertsTable from "../../components/BackupAlertsTable";
import BackupJobsTable from "../../components/BackupJobsTable";
import BackupRunsTable from "../../components/BackupRunsTable";
import type { ServiceInstance } from "../../types";
export function JobsTab({ instance }: { instance: ServiceInstance }) {
const [tab, setTab] = useState("jobs");
const { data: jobsData, isLoading: jobsLoading } = useBackupJobs(instance.id);
const { data: runsData, isLoading: runsLoading } = useBackupRuns(
undefined,
undefined,
instance.id,
);
const { data: alertsData, isLoading: alertsLoading } = useBackupAlerts(
undefined,
false,
undefined,
instance.id,
);
const acknowledgeMutation = useAcknowledgeAlert();
// Build a map of latest runs per job
const latestRuns = new Map();
if (runsData) {
for (const run of runsData) {
const existing = latestRuns.get(run.job_id);
if (!existing || run.started_at > existing.started_at) {
latestRuns.set(run.job_id, run);
}
}
}
const alertsLabel = alertsData ? `Alerts (${alertsData.length})` : "Alerts";
return (
<div className="space-y-4">
<Tabs value={tab} onValueChange={setTab}>
<TabsList>
<TabsTrigger value="jobs">Jobs</TabsTrigger>
<TabsTrigger value="runs">Runs</TabsTrigger>
<TabsTrigger value="alerts">{alertsLabel}</TabsTrigger>
</TabsList>
<TabsContent value="jobs">
{jobsLoading ? (
<p className="text-sm text-muted-foreground">Loading jobs</p>
) : (
<BackupJobsTable jobs={jobsData ?? []} latestRuns={latestRuns} />
)}
</TabsContent>
<TabsContent value="runs">
{runsLoading ? (
<p className="text-sm text-muted-foreground">Loading runs</p>
) : (
<BackupRunsTable runs={runsData ?? []} />
)}
</TabsContent>
<TabsContent value="alerts">
{alertsLoading ? (
<p className="text-sm text-muted-foreground">Loading alerts</p>
) : (
<BackupAlertsTable
alerts={alertsData ?? []}
onAcknowledge={(id) => acknowledgeMutation.mutate(id)}
/>
)}
</TabsContent>
</Tabs>
</div>
);
}