Migrate Pie and Polar components

This commit is contained in:
Christoph Kluge 2025-07-01 17:25:52 +02:00
parent 1ad80efab6
commit 48150ffc8b
3 changed files with 196 additions and 187 deletions

View File

@ -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>

View File

@ -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>

View File

@ -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();