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 + } + );