diff --git a/web-interface/bun.lock b/web-interface/bun.lock index b37b8a5..92b083d 100644 --- a/web-interface/bun.lock +++ b/web-interface/bun.lock @@ -9,6 +9,7 @@ "@tanstack/react-router": "latest", "@tanstack/react-router-devtools": "latest", "@tanstack/router-plugin": "^1.132.0", + "date-fns": "^4.1.0", "lucide-react": "^0.545.0", "react": "^19.2.0", "react-dom": "^19.2.0", @@ -511,6 +512,8 @@ "data-urls": ["data-urls@7.0.0", "", { "dependencies": { "whatwg-mimetype": "^5.0.0", "whatwg-url": "^16.0.0" } }, "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA=="], + "date-fns": ["date-fns@4.1.0", "", {}, "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg=="], + "dayjs": ["dayjs@1.11.20", "", {}, "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ=="], "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], diff --git a/web-interface/package.json b/web-interface/package.json index b9e0451..a423092 100644 --- a/web-interface/package.json +++ b/web-interface/package.json @@ -20,6 +20,7 @@ "@tanstack/react-router": "latest", "@tanstack/react-router-devtools": "latest", "@tanstack/router-plugin": "^1.132.0", + "date-fns": "^4.1.0", "lucide-react": "^0.545.0", "react": "^19.2.0", "react-dom": "^19.2.0", diff --git a/web-interface/src/components/Buttons.tsx b/web-interface/src/components/Buttons.tsx index 1225fc8..aa655b2 100644 --- a/web-interface/src/components/Buttons.tsx +++ b/web-interface/src/components/Buttons.tsx @@ -14,8 +14,7 @@ const fontSizeStyles = { base: 'text-base', lg: 'text-lg', xl: 'text-xl', -}; - +} type ButtonVariant = keyof typeof variantStyles type ButtonFontSize = keyof typeof fontSizeStyles @@ -34,7 +33,7 @@ export function Button({ return ( @@ -186,30 +214,35 @@ function JobCard({ {/* Info grid */}
- - - - - - + + + + + + - + - - + +
{/* Component Usage Chart */} - + ) } @@ -235,10 +268,12 @@ function handleDelete(id: string) { } function JobsPage() { + const jobs = Route.useLoaderData() + return (
- {sampleJobs.map((job) => ( + {jobs.map((job) => ( void +}) { + return ( + + + + + + {/* Info grid */} +
+
+ + + + +
+
+ + + + +
+
+
+

Jobs

+ +
+ + + + + + + + + {machine.jobs.map((job) => ( + + + + + ))} + +
IDAccessed
+ + {job.id} + + + {format(job.accessed, 'yyyy-MM-dd')} +
+
+
+
+
+ + {/* Component Usage Chart */} + +
+ ) +} + function RouteComponent() { - return
Hello "/machines"!
+ function handleProvision(machineId: string) { + // TODO: Implement + console.log(`Provisioned ${machineId}`) + } + + const machines = Route.useLoaderData() + + return ( +
+
+ {machines.map((machine) => ( + + ))} +
+
+ ) } diff --git a/web-interface/src/types/job.ts b/web-interface/src/types/job.ts new file mode 100644 index 0000000..4737778 --- /dev/null +++ b/web-interface/src/types/job.ts @@ -0,0 +1,16 @@ +import type { BaseMachine } from '#/types/machine.ts' + +export type BaseJob = { + id: string + created: Date + accessed: Date + dockerImage: string + usageHistory: UsageData[] // the usage of the resources of the machine allocated to this specific job +} + +export type UsageData = { + component: string // Component that we observe. E.g. GPU, CPU, etc. + observations: number[] +} + +export type Job = BaseJob & { machine: BaseMachine } diff --git a/web-interface/src/types/machine.ts b/web-interface/src/types/machine.ts new file mode 100644 index 0000000..78d92ea --- /dev/null +++ b/web-interface/src/types/machine.ts @@ -0,0 +1,17 @@ +import type { BaseJob, UsageData } from '#/types/job.ts' + +export type BaseMachine = { + id: string + isAvailable: boolean + purpose: string + gpu: string + cpu: string + diskUsage: string + ramUsage: string + cpuUsage: string + network: { down: string; up: string } + ip: string + usageHistory: UsageData[] // the usage of the total machine resources +} + +export type Machine = BaseMachine & { jobs: BaseJob[] }