Skip to content

Commit 5ff3b50

Browse files
committed
Fix a bug with stacked bar charts
Fix #727
1 parent 539d5aa commit 5ff3b50

File tree

2 files changed

+39
-27
lines changed

2 files changed

+39
-27
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
- Useful to reset a connection to the database after each request.
2626
- Fix a bug where the `sqlpage.header` function would not work with headers containing uppercase letters.
2727
- Fix a bug where the table component would not sort columns that contained a space in their name.
28+
- Fix a bug where stacked bar charts would not stack the bars correctly in some cases.
2829

2930
## 0.31.0 (2024-11-24)
3031

sqlpage/apexcharts.js

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -46,35 +46,45 @@ sqlpage_chart = (() => {
4646
]),
4747
);
4848

49-
/** @typedef { { [name:string]: {data:{x:number,y:number}[], name:string} } } Series */
49+
/** @typedef { { [name:string]: {data:{x:number|string|Date,y:number}[], name:string} } } Series */
5050

5151
/**
52-
* @param {Series} series
53-
* @returns {Series} */
52+
* Aligns series data points by their x-axis categories, ensuring all series have data points
53+
* for each unique category. Missing values are filled with zeros. Categories are sorted.
54+
*
55+
* @example
56+
* // Input series:
57+
* const series = [
58+
* { name: "A", data: [{x: "Jan", y: 10}, {x: "Mar", y: 30}] },
59+
* { name: "B", data: [{x: "Jan", y: 20}, {x: "Feb", y: 25}] }
60+
* ];
61+
*
62+
* // Output after align_categories:
63+
* // [
64+
* // { name: "A", data: [{x: "Feb", y: 0}, {x: "Jan", y: 10}, {x: "Mar", y: 30}] },
65+
* // { name: "B", data: [{x: "Feb", y: 25}, {x: "Jan", y: 20}, {x: "Mar", y: 0}] }
66+
* // ]
67+
*
68+
* @param {Series[string][]} series - Array of series objects, each containing name and data points
69+
* @returns {Series[string][]} Aligned series with consistent categories across all series
70+
*/
5471
function align_categories(series) {
55-
const new_series = series.map((s) => ({ name: s.name, data: [] }));
56-
let category = null;
57-
do {
58-
category = null;
59-
series.forEach((s, s_i) => {
60-
const point = s.data[0];
61-
let new_point = { x: category, y: 0 };
62-
if (point) {
63-
if (category == null) category = point.x;
64-
if (category === point.x) {
65-
new_point = s.data.shift();
66-
}
67-
}
68-
new_series[s_i].data.push(new_point);
69-
});
70-
for (const s of new_series) {
71-
s.data[s.data.length - 1].x = category;
72-
}
73-
} while (category != null);
74-
for (const s of new_series) {
75-
s.data.pop();
76-
}
77-
return new_series;
72+
// Collect all unique categories
73+
const categories = new Set(series.flatMap(s => s.data.map(p => p.x)));
74+
const sortedCategories = Array.from(categories).sort();
75+
76+
// Create a map of category -> value for each series
77+
return series.map(s => {
78+
const valueMap = new Map(s.data.map(point => [point.x, point.y]));
79+
80+
return {
81+
name: s.name,
82+
data: sortedCategories.map(category => ({
83+
x: category,
84+
y: valueMap.get(category) || 0
85+
}))
86+
};
87+
});
7888
}
7989

8090
/** @param {HTMLElement} c */
@@ -155,7 +165,7 @@ sqlpage_chart = (() => {
155165
? (_val, { seriesIndex, w }) => w.config.series[seriesIndex].name
156166
: data.type === "pie"
157167
? (value, { seriesIndex, w }) =>
158-
`${w.config.labels[seriesIndex]}: ${value.toFixed()}%`
168+
`${w.config.labels[seriesIndex]}: ${value.toFixed()}%`
159169
: (value) => value.toLocaleString(),
160170
},
161171
fill: {
@@ -235,6 +245,7 @@ sqlpage_chart = (() => {
235245
series,
236246
};
237247
if (labels) options.labels = labels;
248+
console.log("Rendering chart", options);
238249
const chart = new ApexCharts(chartContainer, options);
239250
chart.render();
240251
if (window.charts) window.charts.push(chart);

0 commit comments

Comments
 (0)