From ba485ea6b3af91675770de41bd9f1db199370aa2 Mon Sep 17 00:00:00 2001 From: Vallari Date: Fri, 11 Aug 2023 15:00:33 +0530 Subject: [PATCH] add nodes/:name page Other minor additions: 1. In nodes table, add links in 'name' column 2. Add 'hideFooter' prop in DataGrid component Signed-off-by: Vallari --- src/App.tsx | 2 ++ src/components/DataGrid/index.jsx | 1 + src/components/JobList/index.tsx | 6 ++-- src/components/NodeList/index.tsx | 26 ++++++++++------ src/lib/paddles.d.ts | 4 +++ src/lib/paddles.ts | 26 +++++++++++++++- src/pages/Node/index.tsx | 51 +++++++++++++++++++++++++++++++ 7 files changed, 103 insertions(+), 13 deletions(-) create mode 100644 src/pages/Node/index.tsx diff --git a/src/App.tsx b/src/App.tsx index cdaa845..aa221a4 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -10,6 +10,7 @@ import Run from "./pages/Run"; import Job from "./pages/Job"; import Queue from "./pages/Queue"; import Nodes from "./pages/Nodes"; +import Node from "./pages/Node"; import "./App.css"; @@ -37,6 +38,7 @@ function App(props: AppProps) { } /> } /> + } /> } /> } /> } /> diff --git a/src/components/DataGrid/index.jsx b/src/components/DataGrid/index.jsx index 45fc1e3..1df0303 100644 --- a/src/components/DataGrid/index.jsx +++ b/src/components/DataGrid/index.jsx @@ -169,6 +169,7 @@ export default function DataGrid(props) { filterModel={props.filterModel} onFilterModelChange={props.onFilterModelChange} columns={props.columns} + hideFooter={props.hideFooter} /> diff --git a/src/components/JobList/index.tsx b/src/components/JobList/index.tsx index 1b3d2bd..ec385ac 100644 --- a/src/components/JobList/index.tsx +++ b/src/components/JobList/index.tsx @@ -18,7 +18,7 @@ import type { UseQueryResult } from "@tanstack/react-query"; import { formatDate, formatDuration } from "../../lib/utils"; import DataGrid from "../../components/DataGrid"; import IconLink from "../../components/IconLink"; -import type { Run } from "../../lib/paddles.d"; +import type { Run, NodeJobs } from "../../lib/paddles.d"; import sentryIcon from "./assets/sentry.svg"; @@ -138,7 +138,7 @@ const columns: GridColDef[] = [ ]; interface JobListProps { - query: UseQueryResult; + query: UseQueryResult | UseQueryResult; params: DecodedValueMap; setter: SetQuery; } @@ -164,7 +164,7 @@ export default function JobList({ query, params, setter }: JobListProps) { { + return {params.value}; + }, }, { field: "machine_type", @@ -72,6 +77,15 @@ interface NodeListProps { setter: SetQuery; } +export function nodeRowClass(params: GridRowClassNameParams) { + const isUp = params.row.up; + const isLocked = params.row.locked; + if (!isUp) { + return 'node-down'; + } + return isLocked ? 'node-locked' : 'node-available'; +} + export default function NodeList({ params, setter }:NodeListProps) { const debouncedParams = useDebounce(params, 500); const query = useNodes(debouncedParams); @@ -100,17 +114,11 @@ export default function NodeList({ params, setter }:NodeListProps) { ], }, }} + hideFooter={true} filterMode="client" filterModel={filterModel} onFilterModelChange={onFilterModelChange} - getRowClassName={(params: GridRowClassNameParams) => { - const isUp = params.row.up; - const isLocked = params.row.locked; - if (!isUp) { - return 'node-down'; - } - return isLocked ? 'node-locked' : 'node-available' - }} + getRowClassName={nodeRowClass} /> ); } diff --git a/src/lib/paddles.d.ts b/src/lib/paddles.d.ts index 1323dee..e7b28e6 100644 --- a/src/lib/paddles.d.ts +++ b/src/lib/paddles.d.ts @@ -42,3 +42,7 @@ export type Node = { locked_by: string | null; machine_type: string; }; + +export type NodeJobs = { + jobs?: Job[]; +} diff --git a/src/lib/paddles.ts b/src/lib/paddles.ts index c3fa486..e96c12d 100644 --- a/src/lib/paddles.ts +++ b/src/lib/paddles.ts @@ -1,7 +1,7 @@ import { useQuery } from "@tanstack/react-query"; import type { UseQueryResult } from "@tanstack/react-query"; -import type { GetURLParams, Run, Job, Node } from "./paddles.d"; +import type { GetURLParams, Run, Job, Node, NodeJobs } from "./paddles.d"; const PADDLES_SERVER = import.meta.env.VITE_PADDLES_SERVER || "https://paddles.front.sepia.ceph.com"; @@ -94,6 +94,28 @@ function useMachineTypes() { return useQuery(["machine_types", { url }]); } +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); + const query = useQuery(["nodes", { url }], { + select: (data: Job[]) => { + data.forEach((item) => { + item.id = item.job_id; + }); + const resp: NodeJobs = { 'jobs': data } + return resp; + }, + }); + return query; +} + +function useNode(name: string): UseQueryResult { + const url = getURL(`/nodes/${name}/`); + const query = useQuery(["node", { url }]); + return query; +} + function useNodes(params: GetURLParams): UseQueryResult { const params_ = JSON.parse(JSON.stringify(params || {})); @@ -131,5 +153,7 @@ export { useJob, useSuites, useStatuses, + useNode, + useNodeJobs, useNodes, }; diff --git a/src/pages/Node/index.tsx b/src/pages/Node/index.tsx new file mode 100644 index 0000000..c927925 --- /dev/null +++ b/src/pages/Node/index.tsx @@ -0,0 +1,51 @@ +import { useParams } from "react-router-dom"; +import { useQueryParams, NumberParam } from "use-query-params"; +import Typography from "@mui/material/Typography"; +import { Helmet } from "react-helmet"; + +import DataGrid from "../../components/DataGrid"; +import JobList from "../../components/JobList"; +import { nodeRowClass, columns as nodeColumns} from "../../components/NodeList"; +import type { RunParams } from "../../lib/paddles.d"; + +import { useNode, useNodeJobs } from "../../lib/paddles"; + +export default function Node() { + const [params, setParams] = useQueryParams({ + page: NumberParam, + pageSize: NumberParam, + }); + const { name } = useParams(); + const detailsQuery = useNode(name === undefined ? "" : name); + const jobsQuery = useNodeJobs(name === undefined ? "" : name, params); + + if (detailsQuery === null) return 404; + if (detailsQuery.isError) return null; + + if (jobsQuery === null) return 404; + if (jobsQuery.isError) return null; + + return ( +
+ + Node - Pulpito + + + Node: {name} + + +
+
+ + +
+
+
+ ); +}