function calculatePadding(datasets, yValueColumnIndices, belowPaddingPercentage = 0.1, abovePaddingPercentage = 0.1) { // Flatten all y-values across specified column indices into a single array, parsing them as floats const datasetValues = datasets.flatMap(dataset => yValueColumnIndices.map(index => parseFloat(Object.values(dataset)[index])).filter(value => !isNaN(value)) ); const minValue = Math.min(...datasetValues); const maxValue = Math.max(...datasetValues); // Calc range const range = maxValue - minValue; // Cal padding const belowPadding = range * belowPaddingPercentage; const abovePadding = range * abovePaddingPercentage; return { minPadding: minValue - belowPadding, maxPadding: maxValue + abovePadding }; } module.exports = (data, headers, elem) => { const ctx = api.$container.find(elem)[0].getContext("2d"); ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); const totalColumns = Object.values(data[0]).length; const yValueColumnIndices = Array.from({ length: totalColumns - 1 }, (_, i) => i + 1); const padding = calculatePadding(data, yValueColumnIndices); const datasets = headers.slice(1).map((header, index) => ({ label: header, data: data.map(item => ({ t: item[headers[0]], // First header is the x-value y: parseFloat(item[header]) // Convert y-values to float })), fill: false, borderColor: `hsl(${360 * index / headers.length}, 70%, 50%)`, // Example color generation lineTension: 0.01 })); const myLineChart = new Chart(ctx, { type: 'line', data: { datasets }, options: { plugins: { datalabels: { display: false } }, scales: { yAxes: [{ ticks: { suggestedMin: padding.minPadding, suggestedMax: padding.maxPadding, autoSkip: true, autoSkipPadding: 20 } }], xAxes: [{ type: 'time', time: { tooltipFormat: 'YYYY-MM-DD HH:mm:ss', displayFormats: { minute: 'YYYY-MM-DD HH:mm', hour: 'YYYY-MM-DD HH:mm', day: 'YYYY-MM-DD' } }, scaleLabel: { display: true, labelString: headers[0] // First header for x-axis label }, ticks: { maxRotation: 90, minRotation: 90, autoSkip: true, autoSkipPadding: 20 } }] }, legend: { display: true }, animation: { duration: 0 // Disable animations } } }); };