mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2025-07-02 11:43:49 +02:00
Migrate Pie and Polar components
This commit is contained in:
parent
1ad80efab6
commit
48150ffc8b
@ -12,80 +12,86 @@
|
|||||||
- `colors ['rgb(x,y,z)', ...]`: Color range used for segments; upstream used for legend
|
- `colors ['rgb(x,y,z)', ...]`: Color range used for segments; upstream used for legend
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<script context="module">
|
<script module>
|
||||||
// http://tsitsul.in/blog/coloropt/ : 12 colors normal
|
// http://tsitsul.in/blog/coloropt/ : 12 colors normal
|
||||||
export const colors = [
|
export const colors = [
|
||||||
'rgb(235,172,35)',
|
'rgb(235,172,35)',
|
||||||
'rgb(184,0,88)',
|
'rgb(184,0,88)',
|
||||||
'rgb(0,140,249)',
|
'rgb(0,140,249)',
|
||||||
'rgb(0,110,0)',
|
'rgb(0,110,0)',
|
||||||
'rgb(0,187,173)',
|
'rgb(0,187,173)',
|
||||||
'rgb(209,99,230)',
|
'rgb(209,99,230)',
|
||||||
'rgb(178,69,2)',
|
'rgb(178,69,2)',
|
||||||
'rgb(255,146,135)',
|
'rgb(255,146,135)',
|
||||||
'rgb(89,84,214)',
|
'rgb(89,84,214)',
|
||||||
'rgb(0,198,248)',
|
'rgb(0,198,248)',
|
||||||
'rgb(135,133,0)',
|
'rgb(135,133,0)',
|
||||||
'rgb(0,167,108)',
|
'rgb(0,167,108)',
|
||||||
'rgb(189,189,189)'
|
'rgb(189,189,189)'
|
||||||
]
|
];
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Chart from 'chart.js/auto'
|
/* Ignore Double Script Section Error in IDE */
|
||||||
import { onMount } from 'svelte';
|
import Chart from 'chart.js/auto';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
export let canvasId = "pie-default"
|
/* Svelte 5 Props */
|
||||||
export let size
|
let {
|
||||||
export let sliceLabel
|
canvasId = "pie-default",
|
||||||
export let quantities
|
size,
|
||||||
export let entities
|
sliceLabel,
|
||||||
export let displayLegend = false
|
quantities,
|
||||||
|
entities,
|
||||||
|
displayLegend = false,
|
||||||
|
} = $props();
|
||||||
|
|
||||||
const data = {
|
/* Const Init */
|
||||||
labels: entities,
|
const data = {
|
||||||
datasets: [
|
labels: entities,
|
||||||
{
|
datasets: [
|
||||||
label: sliceLabel,
|
{
|
||||||
data: quantities,
|
label: sliceLabel,
|
||||||
fill: 1,
|
data: quantities,
|
||||||
backgroundColor: colors.slice(0, quantities.length)
|
fill: 1,
|
||||||
}
|
backgroundColor: colors.slice(0, quantities.length)
|
||||||
]
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
animation: false,
|
||||||
|
plugins: {
|
||||||
|
legend: {
|
||||||
|
display: displayLegend
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const options = {
|
/* On Mount */
|
||||||
maintainAspectRatio: false,
|
onMount(() => {
|
||||||
animation: false,
|
new Chart(
|
||||||
plugins: {
|
document.getElementById(canvasId),
|
||||||
legend: {
|
{
|
||||||
display: displayLegend
|
type: 'pie',
|
||||||
}
|
data: data,
|
||||||
}
|
options: options
|
||||||
}
|
}
|
||||||
|
);
|
||||||
onMount(() => {
|
|
||||||
new Chart(
|
|
||||||
document.getElementById(canvasId),
|
|
||||||
{
|
|
||||||
type: 'pie',
|
|
||||||
data: data,
|
|
||||||
options: options
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- <div style="width: 500px;"><canvas id="dimensions"></canvas></div><br/> -->
|
<!-- <div style="width: 500px;"><canvas id="dimensions"></canvas></div><br/> -->
|
||||||
<div class="chart-container" style="--container-width: {size}; --container-height: {size}">
|
<div class="chart-container" style="--container-width: {size}; --container-height: {size}">
|
||||||
<canvas id={canvasId}></canvas>
|
<canvas id={canvasId}></canvas>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.chart-container {
|
.chart-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
height: var(--container-height);
|
height: var(--container-height);
|
||||||
width: var(--container-width);
|
width: var(--container-width);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -8,136 +8,139 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getContext, onMount } from 'svelte'
|
import { onMount } from 'svelte'
|
||||||
import Chart from 'chart.js/auto'
|
import Chart from 'chart.js/auto'
|
||||||
import {
|
import {
|
||||||
Chart as ChartJS,
|
Chart as ChartJS,
|
||||||
Title,
|
Title,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
Legend,
|
Legend,
|
||||||
Filler,
|
Filler,
|
||||||
PointElement,
|
PointElement,
|
||||||
RadialLinearScale,
|
RadialLinearScale,
|
||||||
LineElement
|
LineElement
|
||||||
} from 'chart.js';
|
} from 'chart.js';
|
||||||
|
|
||||||
ChartJS.register(
|
/* Register Chart.js Components */
|
||||||
Title,
|
ChartJS.register(
|
||||||
Tooltip,
|
Title,
|
||||||
Legend,
|
Tooltip,
|
||||||
Filler,
|
Legend,
|
||||||
PointElement,
|
Filler,
|
||||||
RadialLinearScale,
|
PointElement,
|
||||||
LineElement
|
RadialLinearScale,
|
||||||
|
LineElement
|
||||||
|
);
|
||||||
|
|
||||||
|
/* Svelte 5 Props */
|
||||||
|
let {
|
||||||
|
polarMetrics = [],
|
||||||
|
polarData = [],
|
||||||
|
canvasId = "polar-default",
|
||||||
|
height = 350,
|
||||||
|
} = $props();
|
||||||
|
|
||||||
|
/* Const Init */
|
||||||
|
const options = {
|
||||||
|
maintainAspectRatio: true,
|
||||||
|
animation: false,
|
||||||
|
scales: { // fix scale
|
||||||
|
r: {
|
||||||
|
suggestedMin: 0.0,
|
||||||
|
suggestedMax: 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Derived */
|
||||||
|
const labels = $derived(polarMetrics
|
||||||
|
.filter((m) => (m.peak != null))
|
||||||
|
.map(pm => pm.name)
|
||||||
|
.sort(function (a, b) {return ((a > b) ? 1 : ((b > a) ? -1 : 0))})
|
||||||
|
);
|
||||||
|
|
||||||
|
const data = $derived({
|
||||||
|
labels: labels,
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: 'Max',
|
||||||
|
data: loadData('max'), // Node Scope Only
|
||||||
|
fill: 1,
|
||||||
|
backgroundColor: 'rgba(0, 0, 255, 0.25)',
|
||||||
|
borderColor: 'rgb(0, 0, 255)',
|
||||||
|
pointBackgroundColor: 'rgb(0, 0, 255)',
|
||||||
|
pointBorderColor: '#fff',
|
||||||
|
pointHoverBackgroundColor: '#fff',
|
||||||
|
pointHoverBorderColor: 'rgb(0, 0, 255)'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Avg',
|
||||||
|
data: loadData('avg'), // Node Scope Only
|
||||||
|
fill: 2,
|
||||||
|
backgroundColor: 'rgba(255, 210, 0, 0.25)',
|
||||||
|
borderColor: 'rgb(255, 210, 0)',
|
||||||
|
pointBackgroundColor: 'rgb(255, 210, 0)',
|
||||||
|
pointBorderColor: '#fff',
|
||||||
|
pointHoverBackgroundColor: '#fff',
|
||||||
|
pointHoverBorderColor: 'rgb(255, 210, 0)'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Min',
|
||||||
|
data: loadData('min'), // Node Scope Only
|
||||||
|
fill: true,
|
||||||
|
backgroundColor: 'rgba(255, 0, 0, 0.25)',
|
||||||
|
borderColor: 'rgb(255, 0, 0)',
|
||||||
|
pointBackgroundColor: 'rgb(255, 0, 0)',
|
||||||
|
pointBorderColor: '#fff',
|
||||||
|
pointHoverBackgroundColor: '#fff',
|
||||||
|
pointHoverBorderColor: 'rgb(255, 0, 0)'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
/* Functions */
|
||||||
|
function loadData(type) {
|
||||||
|
if (labels && (type == 'avg' || type == 'min' ||type == 'max')) {
|
||||||
|
return getValues(type)
|
||||||
|
} else if (!labels) {
|
||||||
|
console.warn("Empty 'polarMetrics' array prop! Cannot render Polar representation.")
|
||||||
|
} else {
|
||||||
|
console.warn('Unknown Type For Polar Data (must be one of [min, max, avg])')
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper
|
||||||
|
const getValues = (type) => labels.map(name => {
|
||||||
|
// Peak is adapted and scaled for job shared state
|
||||||
|
const peak = polarMetrics.find(m => m?.name == name)?.peak
|
||||||
|
const metric = polarData.find(m => m?.name == name)?.data
|
||||||
|
const value = (peak && metric) ? (metric[type] / peak) : 0
|
||||||
|
return value <= 1. ? value : 1.
|
||||||
|
})
|
||||||
|
|
||||||
|
/* On Mount */
|
||||||
|
onMount(() => {
|
||||||
|
new Chart(
|
||||||
|
document.getElementById(canvasId),
|
||||||
|
{
|
||||||
|
type: 'radar',
|
||||||
|
data: data,
|
||||||
|
options: options,
|
||||||
|
height: height
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
});
|
||||||
|
|
||||||
export let polarMetrics = [];
|
|
||||||
export let polarData = [];
|
|
||||||
export let canvasId = "polar-default";
|
|
||||||
export let height = 350;
|
|
||||||
|
|
||||||
const labels = polarMetrics
|
|
||||||
.filter((m) => (m.peak != null))
|
|
||||||
.map(pm => pm.name)
|
|
||||||
.sort(function (a, b) {return ((a > b) ? 1 : ((b > a) ? -1 : 0))});
|
|
||||||
|
|
||||||
function loadData(type) {
|
|
||||||
if (labels && (type == 'avg' || type == 'min' ||type == 'max')) {
|
|
||||||
return getValues(type)
|
|
||||||
} else if (!labels) {
|
|
||||||
console.warn("Empty 'polarMetrics' array prop! Cannot render Polar representation.")
|
|
||||||
} else {
|
|
||||||
console.warn('Unknown Type For Polar Data (must be one of [min, max, avg])')
|
|
||||||
}
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper
|
|
||||||
|
|
||||||
const getValues = (type) => labels.map(name => {
|
|
||||||
// Peak is adapted and scaled for job shared state
|
|
||||||
const peak = polarMetrics.find(m => m?.name == name)?.peak
|
|
||||||
const metric = polarData.find(m => m?.name == name)?.data
|
|
||||||
const value = (peak && metric) ? (metric[type] / peak) : 0
|
|
||||||
return value <= 1. ? value : 1.
|
|
||||||
})
|
|
||||||
|
|
||||||
// Chart JS Objects
|
|
||||||
|
|
||||||
const data = {
|
|
||||||
labels: labels,
|
|
||||||
datasets: [
|
|
||||||
{
|
|
||||||
label: 'Max',
|
|
||||||
data: loadData('max'), // Node Scope Only
|
|
||||||
fill: 1,
|
|
||||||
backgroundColor: 'rgba(0, 0, 255, 0.25)',
|
|
||||||
borderColor: 'rgb(0, 0, 255)',
|
|
||||||
pointBackgroundColor: 'rgb(0, 0, 255)',
|
|
||||||
pointBorderColor: '#fff',
|
|
||||||
pointHoverBackgroundColor: '#fff',
|
|
||||||
pointHoverBorderColor: 'rgb(0, 0, 255)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Avg',
|
|
||||||
data: loadData('avg'), // Node Scope Only
|
|
||||||
fill: 2,
|
|
||||||
backgroundColor: 'rgba(255, 210, 0, 0.25)',
|
|
||||||
borderColor: 'rgb(255, 210, 0)',
|
|
||||||
pointBackgroundColor: 'rgb(255, 210, 0)',
|
|
||||||
pointBorderColor: '#fff',
|
|
||||||
pointHoverBackgroundColor: '#fff',
|
|
||||||
pointHoverBorderColor: 'rgb(255, 210, 0)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Min',
|
|
||||||
data: loadData('min'), // Node Scope Only
|
|
||||||
fill: true,
|
|
||||||
backgroundColor: 'rgba(255, 0, 0, 0.25)',
|
|
||||||
borderColor: 'rgb(255, 0, 0)',
|
|
||||||
pointBackgroundColor: 'rgb(255, 0, 0)',
|
|
||||||
pointBorderColor: '#fff',
|
|
||||||
pointHoverBackgroundColor: '#fff',
|
|
||||||
pointHoverBorderColor: 'rgb(255, 0, 0)'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
// No custom defined options but keep for clarity
|
|
||||||
const options = {
|
|
||||||
maintainAspectRatio: true,
|
|
||||||
animation: false,
|
|
||||||
scales: { // fix scale
|
|
||||||
r: {
|
|
||||||
suggestedMin: 0.0,
|
|
||||||
suggestedMax: 1.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
new Chart(
|
|
||||||
document.getElementById(canvasId),
|
|
||||||
{
|
|
||||||
type: 'radar',
|
|
||||||
data: data,
|
|
||||||
options: options,
|
|
||||||
height: height
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- <div style="width: 500px;"><canvas id="dimensions"></canvas></div><br/> -->
|
<!-- <div style="width: 500px;"><canvas id="dimensions"></canvas></div><br/> -->
|
||||||
<div class="chart-container">
|
<div class="chart-container">
|
||||||
<canvas id={canvasId}></canvas>
|
<canvas id={canvasId}></canvas>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.chart-container {
|
.chart-container {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
@ -17,9 +17,9 @@
|
|||||||
CardBody,
|
CardBody,
|
||||||
Spinner
|
Spinner
|
||||||
} from "@sveltestrap/sveltestrap";
|
} from "@sveltestrap/sveltestrap";
|
||||||
import Polar from "../../generic/plots/Polar.svelte";
|
|
||||||
import { findJobFootprintThresholds } from "../../generic/utils.js";
|
import { findJobFootprintThresholds } from "../../generic/utils.js";
|
||||||
|
import Polar from "../../generic/plots/Polar.svelte";
|
||||||
|
|
||||||
/* Svelte 5 Props */
|
/* Svelte 5 Props */
|
||||||
let { job } = $props();
|
let { job } = $props();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user