mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2024-12-26 05:19:05 +01:00
Improve Histogram.svelte
- Add bold axis labels - Labels defined as element props xlabel and ylabel - Label offset dynamic to plot height (10 percent) - Add adjustable gaps between bars
This commit is contained in:
parent
46baa6e534
commit
d1c47f4359
@ -152,7 +152,8 @@
|
|||||||
<Histogram
|
<Histogram
|
||||||
width={colWidth1 - 25} height={300}
|
width={colWidth1 - 25} height={300}
|
||||||
data={$mainQuery.data.topUsers.sort((a, b) => b.count - a.count).map(({ count }, idx) => ({ count, value: idx }))}
|
data={$mainQuery.data.topUsers.sort((a, b) => b.count - a.count).map(({ count }, idx) => ({ count, value: idx }))}
|
||||||
label={(x) => x < $mainQuery.data.topUsers.length ? $mainQuery.data.topUsers[Math.floor(x)].name : '0'} />
|
label={(x) => x < $mainQuery.data.topUsers.length ? $mainQuery.data.topUsers[Math.floor(x)].name : '0'}
|
||||||
|
xlabel="User Name" ylabel="Number of Jobs" />
|
||||||
{/key}
|
{/key}
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
@ -173,7 +174,8 @@
|
|||||||
<Histogram
|
<Histogram
|
||||||
width={colWidth1 - 25} height={300}
|
width={colWidth1 - 25} height={300}
|
||||||
data={$mainQuery.data.topProjects.sort((a, b) => b.count - a.count).map(({ count }, idx) => ({ count, value: idx }))}
|
data={$mainQuery.data.topProjects.sort((a, b) => b.count - a.count).map(({ count }, idx) => ({ count, value: idx }))}
|
||||||
label={(x) => x < $mainQuery.data.topProjects.length ? $mainQuery.data.topProjects[Math.floor(x)].name : '0'} />
|
label={(x) => x < $mainQuery.data.topProjects.length ? $mainQuery.data.topProjects[Math.floor(x)].name : '0'}
|
||||||
|
xlabel="Project Code" ylabel="Number of Jobs" />
|
||||||
{/key}
|
{/key}
|
||||||
</Col>
|
</Col>
|
||||||
<Col class="px-4 py-2">
|
<Col class="px-4 py-2">
|
||||||
@ -192,7 +194,8 @@
|
|||||||
{#key $mainQuery.data.stats}
|
{#key $mainQuery.data.stats}
|
||||||
<Histogram
|
<Histogram
|
||||||
width={colWidth2 - 25} height={300}
|
width={colWidth2 - 25} height={300}
|
||||||
data={$mainQuery.data.stats[0].histDuration} />
|
data={$mainQuery.data.stats[0].histDuration}
|
||||||
|
xlabel="Current Runtime in Hours [h]" ylabel="Number of Jobs" />
|
||||||
{/key}
|
{/key}
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
@ -201,7 +204,8 @@
|
|||||||
{#key $mainQuery.data.stats}
|
{#key $mainQuery.data.stats}
|
||||||
<Histogram
|
<Histogram
|
||||||
width={colWidth2 - 25} height={300}
|
width={colWidth2 - 25} height={300}
|
||||||
data={$mainQuery.data.stats[0].histNumNodes} />
|
data={$mainQuery.data.stats[0].histNumNodes}
|
||||||
|
xlabel="Allocated Nodes" ylabel="Number of Jobs" />
|
||||||
{/key}
|
{/key}
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<!--
|
<!--
|
||||||
@component
|
@component
|
||||||
Properties:
|
Properties:
|
||||||
- width, height: Number
|
- width, height: Number
|
||||||
@ -20,6 +20,8 @@
|
|||||||
export let data
|
export let data
|
||||||
export let width
|
export let width
|
||||||
export let height
|
export let height
|
||||||
|
export let xlabel
|
||||||
|
export let ylabel
|
||||||
export let min = null
|
export let min = null
|
||||||
export let max = null
|
export let max = null
|
||||||
export let label = formatNumber
|
export let label = formatNumber
|
||||||
@ -72,9 +74,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function render() {
|
function render() {
|
||||||
const h = height - paddingTop - paddingBottom
|
const labelOffset = Math.floor(height * 0.1)
|
||||||
|
const h = height - paddingTop - paddingBottom - labelOffset
|
||||||
const w = width - paddingLeft - paddingRight
|
const w = width - paddingLeft - paddingRight
|
||||||
const barWidth = Math.ceil(w / (maxValue + 1))
|
const barGap = 5
|
||||||
|
const barWidth = Math.ceil(w / (maxValue + 1)) - barGap
|
||||||
|
|
||||||
if (Number.isNaN(barWidth))
|
if (Number.isNaN(barWidth))
|
||||||
return
|
return
|
||||||
@ -83,9 +87,14 @@
|
|||||||
const getCanvasY = (count) => (h - (count / maxCount) * h) + paddingTop
|
const getCanvasY = (count) => (h - (count / maxCount) * h) + paddingTop
|
||||||
|
|
||||||
// X Axis
|
// X Axis
|
||||||
ctx.font = `${fontSize}px ${fontFamily}`
|
ctx.font = `bold ${fontSize}px ${fontFamily}`
|
||||||
ctx.fillStyle = 'black'
|
ctx.fillStyle = 'black'
|
||||||
|
if (xlabel != '') {
|
||||||
|
let textWidth = ctx.measureText(xlabel).width
|
||||||
|
ctx.fillText(xlabel, Math.floor((width / 2) - (textWidth / 2) + barGap), height - Math.floor(labelOffset / 2))
|
||||||
|
}
|
||||||
ctx.textAlign = 'center'
|
ctx.textAlign = 'center'
|
||||||
|
ctx.font = `${fontSize}px ${fontFamily}`
|
||||||
if (min != null && max != null) {
|
if (min != null && max != null) {
|
||||||
const stepsizeX = getStepSize(max - min, w, 75)
|
const stepsizeX = getStepSize(max - min, w, 75)
|
||||||
let startX = 0
|
let startX = 0
|
||||||
@ -94,19 +103,28 @@
|
|||||||
|
|
||||||
for (let x = startX; x < max; x += stepsizeX) {
|
for (let x = startX; x < max; x += stepsizeX) {
|
||||||
let px = ((x - min) / (max - min)) * (w - barWidth) + paddingLeft + (barWidth / 2.)
|
let px = ((x - min) / (max - min)) * (w - barWidth) + paddingLeft + (barWidth / 2.)
|
||||||
ctx.fillText(`${formatNumber(x)}`, px, height - paddingBottom + 15)
|
ctx.fillText(`${formatNumber(x)}`, px, height - paddingBottom - Math.floor(labelOffset / 2))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const stepsizeX = getStepSize(maxValue, w, 120)
|
const stepsizeX = getStepSize(maxValue, w, 120)
|
||||||
for (let x = 0; x <= maxValue; x += stepsizeX) {
|
for (let x = 0; x <= maxValue; x += stepsizeX) {
|
||||||
ctx.fillText(label(x), getCanvasX(x), height - paddingBottom + 15)
|
ctx.fillText(label(x), getCanvasX(x), height - paddingBottom - Math.floor(labelOffset / 2))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Y Axis
|
// Y Axis
|
||||||
ctx.fillStyle = 'black'
|
ctx.fillStyle = 'black'
|
||||||
ctx.strokeStyle = '#bbbbbb'
|
ctx.strokeStyle = '#bbbbbb'
|
||||||
|
ctx.font = `bold ${fontSize}px ${fontFamily}`
|
||||||
|
if (ylabel != '') {
|
||||||
|
ctx.save()
|
||||||
|
ctx.translate(15, Math.floor(h / 2))
|
||||||
|
ctx.rotate(-Math.PI / 2)
|
||||||
|
ctx.fillText(ylabel, 0, 0)
|
||||||
|
ctx.restore()
|
||||||
|
}
|
||||||
ctx.textAlign = 'right'
|
ctx.textAlign = 'right'
|
||||||
|
ctx.font = `${fontSize}px ${fontFamily}`
|
||||||
ctx.beginPath()
|
ctx.beginPath()
|
||||||
const stepsizeY = getStepSize(maxCount, h, 50)
|
const stepsizeY = getStepSize(maxCount, h, 50)
|
||||||
for (let y = stepsizeY; y <= maxCount; y += stepsizeY) {
|
for (let y = stepsizeY; y <= maxCount; y += stepsizeY) {
|
||||||
@ -130,10 +148,10 @@
|
|||||||
// Fat lines left and below plotting area
|
// Fat lines left and below plotting area
|
||||||
ctx.strokeStyle = 'black'
|
ctx.strokeStyle = 'black'
|
||||||
ctx.beginPath()
|
ctx.beginPath()
|
||||||
ctx.moveTo(0, height - paddingBottom)
|
ctx.moveTo(0, height - paddingBottom - labelOffset)
|
||||||
ctx.lineTo(width, height - paddingBottom)
|
ctx.lineTo(width, height - paddingBottom - labelOffset)
|
||||||
ctx.moveTo(paddingLeft, 0)
|
ctx.moveTo(paddingLeft, 0)
|
||||||
ctx.lineTo(paddingLeft, height- paddingBottom)
|
ctx.lineTo(paddingLeft, height - Math.floor(labelOffset / 2))
|
||||||
ctx.stroke()
|
ctx.stroke()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,4 +225,4 @@
|
|||||||
max: max
|
max: max
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
Loading…
Reference in New Issue
Block a user