diff --git a/src/components/JobHistory/index.jsx b/src/components/JobHistory/index.jsx
new file mode 100644
index 0000000..826e1b2
--- /dev/null
+++ b/src/components/JobHistory/index.jsx
@@ -0,0 +1,23 @@
+import JobList from "../JobList";
+import { useJobHistory } from "../../lib/paddles";
+import { Button, Typography, Box } from "@mui/material";
+
+
+const pageSize = 25;
+
+export default function JobHistory({description}) {
+ if (!description) {
+ return null;
+ }
+
+ const jobHistoryQuery = useJobHistory(description, pageSize);
+
+ return (
+
+
+ Past {pageSize} jobs with same description:
+
+
+
+ );
+}
diff --git a/src/components/JobList/index.tsx b/src/components/JobList/index.tsx
index f7fcca0..6102489 100644
--- a/src/components/JobList/index.tsx
+++ b/src/components/JobList/index.tsx
@@ -14,7 +14,7 @@ import { type Theme } from "@mui/material/styles";
import { formatDate, formatDuration } from "../../lib/utils";
import IconLink from "../../components/IconLink";
import Link from "../../components/Link";
-import type { Job, NodeJobs, Run } from "../../lib/paddles.d";
+import type { Job, JobList, Run } from "../../lib/paddles.d";
import { dirName } from "../../lib/utils";
import useDefaultTableOptions from "../../lib/table";
@@ -220,7 +220,7 @@ function JobDetailPanel(props: JobDetailPanelProps): ReactNode {
};
type JobListProps = {
- query: UseQueryResult | UseQueryResult;
+ query: UseQueryResult | UseQueryResult;
sortMode?: "time" | "id";
}
diff --git a/src/lib/paddles.d.ts b/src/lib/paddles.d.ts
index 6f6f9f8..9eb04d2 100644
--- a/src/lib/paddles.d.ts
+++ b/src/lib/paddles.d.ts
@@ -95,7 +95,7 @@ export type Node = {
machine_type: string;
};
-export type NodeJobs = {
+export type JobList = {
jobs?: Job[];
}
diff --git a/src/lib/paddles.ts b/src/lib/paddles.ts
index 905b79d..364a2d6 100644
--- a/src/lib/paddles.ts
+++ b/src/lib/paddles.ts
@@ -4,7 +4,7 @@ import type { UseQueryResult } from "@tanstack/react-query";
import type {
GetURLParams,
Run, Job,
- Node, NodeJobs,
+ Node, JobList,
StatsLocksResponse,
StatsJobsResponse,
} from "./paddles.d";
@@ -40,6 +40,8 @@ function getURL(endpoint: string, params?: GetURLParams) {
uri += "queued/";
delete params_[key];
break;
+ case "description":
+ break;
case "machine_type":
break;
default:
@@ -106,7 +108,24 @@ function useMachineTypes() {
});
}
-function useNodeJobs(name: string, params: GetURLParams): UseQueryResult {
+function useJobHistory(description: string, pageSize: number): UseQueryResult {
+ const url = getURL(`/jobs/`, { 'description': description, "pageSize": pageSize });
+ const query = useQuery(["job-history", { url }], {
+ select: (data: Job[]) => {
+ data.forEach((item) => {
+ item.id = item.job_id + "";
+ });
+ const resp: JobList = { 'jobs': data }
+ return resp;
+ },
+ cacheTime: 60 * 60,
+ staleTime: 60 * 60,
+ retry: 1,
+ });
+ return query;
+}
+
+function useNodeJobs(name: string, params: GetURLParams): UseQueryResult {
// 'page' and 'count' are mandatory query params for this paddles endpoint
params = { "page": params?.page || 0, "pageSize": params?.pageSize || 25 }
const url = getURL(`/nodes/${name}/jobs/`, params);
@@ -115,7 +134,7 @@ function useNodeJobs(name: string, params: GetURLParams): UseQueryResult {
item.id = item.job_id + "";
});
- const resp: NodeJobs = { 'jobs': data }
+ const resp: JobList = { 'jobs': data }
return resp;
},
});
@@ -235,4 +254,5 @@ export {
useNodes,
useStatsNodeLocks,
useStatsNodeJobs,
+ useJobHistory,
};
diff --git a/src/pages/Job/index.jsx b/src/pages/Job/index.jsx
index cf06f74..9222f78 100644
--- a/src/pages/Job/index.jsx
+++ b/src/pages/Job/index.jsx
@@ -5,6 +5,7 @@ import Typography from "@mui/material/Typography";
import Accordion from "@mui/material/Accordion";
import AccordionSummary from "@mui/material/AccordionSummary";
import AccordionDetails from "@mui/material/AccordionDetails";
+import Button from "@mui/material/Button";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
import ScheduleIcon from "@mui/icons-material/Schedule";
import PlayCircleOutlineIcon from "@mui/icons-material/PlayCircleOutline";
@@ -21,6 +22,8 @@ import Link from "../../components/Link";
import CodeBlock from "../../components/CodeBlock";
import { useJob } from "../../lib/paddles";
import { getDuration, dirName } from "../../lib/utils";
+import JobHistory from "../../components/JobHistory";
+import { useState } from "react";
function StatusIcon({ status }) {
const theme = useTheme();
@@ -155,6 +158,7 @@ function JobDetails({ query }) {
export default function Job() {
const { name, job_id } = useParams();
const query = useJob(name, job_id);
+ const [showJobHistory, toggleShowJobHistory] = useState(false);
return (
@@ -173,6 +177,15 @@ export default function Job() {
+
+ { showJobHistory ?
+ (query.data?.description ? : null)
+ :null
+ }
+
);