experimental rework of metricplot render and resize handling

This commit is contained in:
Christoph Kluge 2024-10-08 15:25:31 +02:00
parent 182f0f2c64
commit 89ec749172
2 changed files with 39 additions and 63 deletions

View File

@ -18,7 +18,6 @@
export let renderFor export let renderFor
let rows = [] let rows = []
let colWidth;
const isPlaceholder = x => x._is_placeholder === true const isPlaceholder = x => x._is_placeholder === true
function tile(items, itemsPerRow) { function tile(items, itemsPerRow) {
@ -48,11 +47,9 @@
<Row cols={{ xs: 1, sm: 1, md: 2, lg: itemsPerRow}}> <Row cols={{ xs: 1, sm: 1, md: 2, lg: itemsPerRow}}>
{#each row as item (item)} {#each row as item (item)}
<Col class="px-1"> <Col class="px-1">
<div bind:clientWidth={colWidth}> {#if !isPlaceholder(item)}
{#if !isPlaceholder(item)} <slot item={item}/>
<slot item={item} width={colWidth}/> {/if}
{/if}
</div>
</Col> </Col>
{/each} {/each}
</Row> </Row>

View File

@ -140,7 +140,7 @@
const subClusterTopology = getContext("getHardwareTopology")(cluster, subCluster); const subClusterTopology = getContext("getHardwareTopology")(cluster, subCluster);
const metricConfig = getContext("getMetricConfig")(cluster, subCluster, metric); const metricConfig = getContext("getMetricConfig")(cluster, subCluster, metric);
const clusterCockpitConfig = getContext("cc-config"); const clusterCockpitConfig = getContext("cc-config");
const resizeSleepTime = 250; const renderSleepTime = 100;
const normalLineColor = "#000000"; const normalLineColor = "#000000";
const lineWidth = const lineWidth =
clusterCockpitConfig.plot_general_lineWidth / window.devicePixelRatio; clusterCockpitConfig.plot_general_lineWidth / window.devicePixelRatio;
@ -164,13 +164,15 @@
let resampleResolutions; let resampleResolutions;
let resampleMinimum; let resampleMinimum;
let wrapperWidth = 0;
if (resampleConfig) { if (resampleConfig) {
resampleTrigger = Number(resampleConfig.trigger) resampleTrigger = Number(resampleConfig.trigger)
resampleResolutions = [...resampleConfig.resolutions]; resampleResolutions = [...resampleConfig.resolutions];
resampleMinimum = Math.min(...resampleConfig.resolutions); resampleMinimum = Math.min(...resampleConfig.resolutions);
} }
// converts the legend into a simple tooltip // UPLOT PLUGIN // converts the legend into a simple tooltip
function legendAsTooltipPlugin({ function legendAsTooltipPlugin({
className, className,
style = { backgroundColor: "rgba(255, 249, 196, 0.92)", color: "black" }, style = { backgroundColor: "rgba(255, 249, 196, 0.92)", color: "black" },
@ -246,6 +248,7 @@
} }
} }
// RETURN BG COLOR FROM THRESHOLD
function backgroundColor() { function backgroundColor() {
if ( if (
clusterCockpitConfig.plot_general_colorBackground == false || clusterCockpitConfig.plot_general_colorBackground == false ||
@ -272,6 +275,7 @@
return backgroundColors.normal; return backgroundColors.normal;
} }
// PREPARE UPLOT ...
function lineColor(i, n) { function lineColor(i, n) {
if (n >= lineColors.length) return lineColors[i % lineColors.length]; if (n >= lineColors.length) return lineColors[i % lineColors.length];
else return lineColors[Math.floor((i / n) * lineColors.length)]; else return lineColors[Math.floor((i / n) * lineColors.length)];
@ -333,15 +337,6 @@
plotData.push(statisticsSeries.median); plotData.push(statisticsSeries.median);
} }
/* deprecated: sparse data handled by uplot */
// if (forNode === true) {
// if (plotData[1][-1] != null && plotData[2][-1] != null && plotData[3][-1] != null) {
// if (plotData[1].length != 0) plotData[1].push(null);
// if (plotData[2].length != 0) plotData[2].push(null);
// if (plotData[3].length != 0) plotData[3].push(null);
// }
// }
plotSeries.push({ plotSeries.push({
label: "min", label: "min",
scale: "y", scale: "y",
@ -368,13 +363,6 @@
} else { } else {
for (let i = 0; i < series.length; i++) { for (let i = 0; i < series.length; i++) {
plotData.push(series[i].data); plotData.push(series[i].data);
/* deprecated: sparse data handled by uplot */
// if (forNode === true && plotData[1].length != 0) {
// if (plotData[1][-1] != null) {
// plotData[1].push(null);
// };
// };
plotSeries.push({ plotSeries.push({
label: label:
scope === "node" scope === "node"
@ -507,74 +495,65 @@
cursor: { drag: { x: true, y: true } }, cursor: { drag: { x: true, y: true } },
}; };
// RENDER HANDLING
let plotWrapper = null; let plotWrapper = null;
let uplot = null; let uplot = null;
let timeoutId = null; // let timeoutId = null;
let prevWidth = null,
prevHeight = null;
function render() { function render(func_width, func_height) {
if (!width || Number.isNaN(width) || width < 0) return; if (!uplot) { // Init uPlot
opts.width = func_width;
if (prevWidth != null && Math.abs(prevWidth - width) < 10) return; opts.height = func_height;
prevWidth = width;
prevHeight = height;
if (!uplot) {
opts.width = width;
opts.height = height;
if (zoomState) { if (zoomState) {
opts.scales = {...zoomState} opts.scales = {...zoomState}
} }
// console.log('Init Sizes ...', { width: opts.width, height: opts.height })
uplot = new uPlot(opts, plotData, plotWrapper); uplot = new uPlot(opts, plotData, plotWrapper);
} else { } else { // Update size
uplot.setSize({ width, height }); // console.log('Update uPlot ...', { width: func_width, height: func_height })
uplot.setSize({ width: func_width, height: func_height });
} }
} }
function onSizeChange() {
if (!uplot) return;
if (timeoutId != null) clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
timeoutId = null;
render();
}, resizeSleepTime);
}
$: if (series[0].data.length > 0) {
onSizeChange(width, height);
}
onMount(() => { onMount(() => {
// Setup Wrapper
if (series[0].data.length > 0) { if (series[0].data.length > 0) {
if (forNode) { if (forNode) {
plotWrapper.style.paddingTop = "0.5rem" plotWrapper.style.paddingTop = "0.5rem"
plotWrapper.style.paddingBottom = "0.5rem" plotWrapper.style.paddingBottom = "0.5rem"
} }
plotWrapper.style.backgroundColor = backgroundColor(); plotWrapper.style.backgroundColor = backgroundColor();
render(); plotWrapper.style.borderRadius = "5px";
} }
}); });
onDestroy(() => { onDestroy(() => {
// if (timeoutId != null) clearTimeout(timeoutId);
if (uplot) uplot.destroy(); if (uplot) uplot.destroy();
if (timeoutId != null) clearTimeout(timeoutId);
}); });
$: width = wrapperWidth;
// This renders uPlot initially and updates it on all size changes
$: if (width > 0 && height > 0) {
// console.log('Triggered render() ...')
// if (timeoutId != null) {
// clearTimeout(timeoutId);
// timeoutId = null;
// }
// timeoutId = setTimeout(render(width, height), renderSleepTime);
setTimeout(render(width, height), renderSleepTime);
}
</script> </script>
<!-- Define Wrapper and NoData Card -->
{#if series[0].data.length > 0} {#if series[0].data.length > 0}
<div bind:this={plotWrapper} class="cc-plot"/> <div bind:clientWidth={wrapperWidth} bind:this={plotWrapper}/>
{:else} {:else}
<Card class="mx-4" body color="warning" <Card class="mx-4" body color="warning"
>Cannot render plot: No series data returned for <code>{metric}</code></Card >Cannot render plot: No series data returned for <code>{metric}</code></Card
> >
{/if} {/if}
<style>
.cc-plot {
border-radius: 5px;
}
</style>