You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
4.1 KiB
135 lines
4.1 KiB
<script lang="ts">
|
|
import { onMount } from "svelte";
|
|
import type { Stat } from "../api";
|
|
import randomColor from "randomcolor";
|
|
|
|
import { Chart, registerables } from "chart.js";
|
|
Chart.register(...registerables);
|
|
|
|
export let stats: Stat[] = [];
|
|
|
|
const transformStats = (ostats) => {
|
|
const chartData = ostats.reduce((agg, x) => {
|
|
let root = agg[x.Header] || {
|
|
labels: [],
|
|
dataset: {
|
|
label: x.Header,
|
|
borderColor: randomColor({
|
|
luminosity: "dark",
|
|
}), //"rgb(75,192,192)",
|
|
data: [],
|
|
},
|
|
};
|
|
root.dataset.data = root.dataset.data.concat(x.Count);
|
|
root.labels = root.labels.concat(x.Time);
|
|
agg[x.Header] = root;
|
|
return agg;
|
|
}, {});
|
|
|
|
const finalChartData = Object.keys(chartData).map((x) => chartData[x]);
|
|
const finalChartLabels =
|
|
finalChartData.length > 0 ? finalChartData[0].labels : [];
|
|
return {
|
|
labels: finalChartLabels,
|
|
datasets: finalChartData.map((x) => x.dataset),
|
|
};
|
|
};
|
|
|
|
const generateChartOptions = (s: [], empty: Boolean = false) => {
|
|
let labels = [];
|
|
let datasets = [];
|
|
|
|
if (s && s.length > 0) {
|
|
({ labels, datasets } = transformStats(s));
|
|
}
|
|
|
|
var delayed;
|
|
return {
|
|
type: "line",
|
|
data: {
|
|
labels,
|
|
datasets,
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
scales: {
|
|
// x: {
|
|
// type: "time",
|
|
// ticks: {
|
|
// source: "auto",
|
|
// // Disabled rotation for performance
|
|
// maxRotation: 0,
|
|
// autoSkip: true,
|
|
// },
|
|
// },
|
|
y: {
|
|
stacked: true,
|
|
},
|
|
},
|
|
hoverRadius: 5,
|
|
interaction: {
|
|
mode: "nearest",
|
|
intersect: false,
|
|
axis: "x",
|
|
},
|
|
plugins: {
|
|
decimation: {
|
|
enabled: true,
|
|
algorithm: "lttb",
|
|
samples: 60,
|
|
},
|
|
},
|
|
animations: {
|
|
radius: {
|
|
duration: 150,
|
|
easing: "linear",
|
|
loop: (c) => c.active,
|
|
},
|
|
},
|
|
// animation: {
|
|
// onComplete: () => {
|
|
// delayed = true;
|
|
// },
|
|
// delay: (context) => {
|
|
// let delay = 0;
|
|
// if (
|
|
// context.type === "data" &&
|
|
// context.mode === "default" &&
|
|
// !delayed
|
|
// ) {
|
|
// delay =
|
|
// context.dataIndex * 30 +
|
|
// context.datasetIndex * 10;
|
|
// }
|
|
// return delay;
|
|
// },
|
|
// },
|
|
},
|
|
};
|
|
};
|
|
|
|
let canvas = null;
|
|
let chartInstance = null;
|
|
|
|
onMount(async () => {
|
|
const ctx = canvas.getContext("2d");
|
|
chartInstance = new Chart(ctx, generateChartOptions(stats, true));
|
|
});
|
|
|
|
const update = (s) => {
|
|
if (chartInstance) {
|
|
const { options, data } = generateChartOptions(s, false);
|
|
chartInstance.options = options;
|
|
chartInstance.data = data;
|
|
chartInstance.update();
|
|
}
|
|
};
|
|
|
|
$: update(stats);
|
|
</script>
|
|
|
|
<div style="position: relative; max-height: 384px; height: 384px; width: 100%;">
|
|
<canvas width="100%" height="100%" bind:this={canvas} />
|
|
</div>
|