feat: refactor di alcune cose e grafici
parent
b9073cebbb
commit
6d3b35ee66
@ -0,0 +1,20 @@
|
||||
import { useEffect, useState } from 'preact/hooks'
|
||||
import { Plot } from './Plot.jsx'
|
||||
import { server } from '../utils.js'
|
||||
|
||||
export const GraphCard = ({ label, url }) => {
|
||||
const [samples, setSamples] = useState([])
|
||||
|
||||
useEffect(() => {
|
||||
if (url) {
|
||||
server.get(url).then(data => setSamples(data))
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div class="card">
|
||||
<div class="label">{label}</div>
|
||||
<div class="graph">{url && <Plot samples={samples} />}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -1,13 +1,83 @@
|
||||
import d3 from 'd3'
|
||||
import * as d3 from 'd3'
|
||||
import { useEffect, useRef } from 'preact/hooks'
|
||||
|
||||
// export const Plot = ({ samples }) => {
|
||||
// const mountElement = el => {
|
||||
// d3.select(el).append('svg')
|
||||
// }
|
||||
|
||||
// return <div class="d3-plot" ref={mountElement}></div>
|
||||
// }
|
||||
// set the dimensions and margins of the graph
|
||||
const margin = { top: 10, right: 10, bottom: 30, left: 30 }
|
||||
|
||||
export const Plot = ({ samples }) => {
|
||||
return <div class="d3-plot">Work in progress...</div>
|
||||
if (samples.length === 0) {
|
||||
return <>Loading...</>
|
||||
}
|
||||
|
||||
const data = samples.map(({ timestamp, value }) => ({
|
||||
timestamp: d3.isoParse(timestamp),
|
||||
value: value,
|
||||
}))
|
||||
|
||||
const plotRef = useRef(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (plotRef.current) {
|
||||
const el = plotRef.current
|
||||
|
||||
const width = el.offsetWidth - margin.left - margin.right
|
||||
const height = el.offsetHeight - margin.top - margin.bottom
|
||||
|
||||
const svg = d3
|
||||
.select(el)
|
||||
.append('svg')
|
||||
.attr('width', el.offsetWidth)
|
||||
.attr('height', el.offsetHeight)
|
||||
.append('g')
|
||||
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
|
||||
|
||||
const x = d3
|
||||
.scaleTime()
|
||||
.domain(
|
||||
d3.extent(data, function (d) {
|
||||
return d.timestamp
|
||||
})
|
||||
)
|
||||
.range([0, width])
|
||||
|
||||
const y = d3
|
||||
.scaleLinear()
|
||||
.domain([
|
||||
0,
|
||||
d3.max(data, function (d) {
|
||||
return +d.value
|
||||
}),
|
||||
])
|
||||
.range([height, 0])
|
||||
|
||||
svg.append('g')
|
||||
.attr('transform', 'translate(0,' + height + ')')
|
||||
.call(d3.axisBottom(x))
|
||||
|
||||
svg.append('g').call(d3.axisLeft(y))
|
||||
|
||||
const line = svg.append('g')
|
||||
|
||||
line.append('path')
|
||||
.datum(data)
|
||||
.attr('fill', 'none')
|
||||
.attr('stroke', 'steelblue')
|
||||
.attr('stroke-width', 2)
|
||||
.attr(
|
||||
'd',
|
||||
d3
|
||||
.line()
|
||||
.x(d => x(d.timestamp))
|
||||
.y(d => y(d.value))
|
||||
)
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (plotRef.current) {
|
||||
plotRef.current.firstChild.remove()
|
||||
}
|
||||
}
|
||||
}, [plotRef])
|
||||
|
||||
return <div class="d3-plot" ref={plotRef}></div>
|
||||
}
|
||||
|
@ -1,6 +1,100 @@
|
||||
import { GraphCard } from './components/Graph.jsx'
|
||||
|
||||
const LOGO = String.raw`
|
||||
_______________________ _______ _______ _______ _
|
||||
( ____ \__ __( ____ ( ____ ( ____ ( ____ ( )
|
||||
| ( \/ ) ( | ( \/ ( \/ ( \/ ( \//
|
||||
| (_____ | | | (__ | (__ | (__ | (__
|
||||
(_____ ) | | | __) | __) | __) | __)
|
||||
) | | | | ( | ( | ( | (
|
||||
/\____) | | | | (____/\ ) | ) | (____/\
|
||||
\_______) )_( (_______// |/ (_______/
|
||||
`.trim()
|
||||
|
||||
export const DashboardPage = ({}) => {
|
||||
return <>Dashboard Page</>
|
||||
return (
|
||||
<>
|
||||
<div class="sidebar">
|
||||
<div class="top">
|
||||
<div class="logo">
|
||||
<pre>
|
||||
<code>{LOGO}</code>
|
||||
</pre>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="icon">
|
||||
<span class="material-symbols-outlined">dashboard</span>
|
||||
</div>
|
||||
<div class="label">Overview</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="icon">
|
||||
<span class="material-symbols-outlined">device_thermostat</span>
|
||||
</div>
|
||||
<div class="label">Temperature</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="icon">
|
||||
<span class="material-symbols-outlined"> speed </span>
|
||||
</div>
|
||||
<div class="label">CPU</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="icon">
|
||||
<span class="material-symbols-outlined">swap_vert</span>
|
||||
</div>
|
||||
<div class="label">Network</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="icon">
|
||||
<span class="material-symbols-outlined"> memory </span>
|
||||
</div>
|
||||
<div class="label">Memory</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="icon">
|
||||
<span class="material-symbols-outlined">database</span>
|
||||
</div>
|
||||
<div class="label">Storage</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="icon">
|
||||
<span class="material-symbols-outlined">view_list</span>
|
||||
</div>
|
||||
<div class="label">Jobs</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<div class="item link">
|
||||
<div class="icon">
|
||||
<img src="/public/logo-gitea.svg" alt="logo gitea" />
|
||||
</div>
|
||||
<div class="label">
|
||||
<a href="https://git.phc.dm.unipi.it/phc/cluster-dashboard">Dashboard</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item link">
|
||||
<div class="icon">
|
||||
<img src="/public/logo-gitea.svg" alt="logo gitea" />
|
||||
</div>
|
||||
<div class="label">
|
||||
<a href="https://git.phc.dm.unipi.it/fdurastante/cpar2023">cpar2023</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main">
|
||||
<GraphCard label="Uptime" />
|
||||
<GraphCard label="CPU" />
|
||||
<GraphCard label="Storage" />
|
||||
<GraphCard label="Memory" />
|
||||
<GraphCard label="Network" />
|
||||
<GraphCard label="Temperature" url="/api/stats/temperature" />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export const JobsPage = ({}) => {
|
||||
return <>Jobs Page</>
|
||||
}
|
||||
|
@ -0,0 +1,19 @@
|
||||
export const server = {
|
||||
async get(url) {
|
||||
const res = await fetch(url)
|
||||
return await res.json()
|
||||
},
|
||||
async post(url, data) {
|
||||
const res = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
|
||||
return await res.json()
|
||||
},
|
||||
}
|
||||
|
||||
window.server = server
|
Loading…
Reference in New Issue