Skip to content

Commit d1cdfd4

Browse files
committed
fix(custom-chart-web): fix static-source data merge
1 parent 57fa67f commit d1cdfd4

File tree

5 files changed

+86
-17
lines changed

5 files changed

+86
-17
lines changed

packages/pluggableWidgets/custom-chart-web/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66

77
## [Unreleased]
88

9+
### Fixed
10+
11+
- We fixed an issue where static data and source attribute wouldn't merge properly.
12+
913
## [1.2.3] - 2025-10-10
1014

1115
### Changed

packages/pluggableWidgets/custom-chart-web/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@mendix/custom-chart-web",
33
"widgetName": "CustomChart",
4-
"version": "1.2.3",
4+
"version": "1.2.4",
55
"description": "Create customizable charts with Plotly.js for advanced visualization needs",
66
"copyright": "© Mendix Technology BV 2025. All rights reserved.",
77
"license": "Apache-2.0",

packages/pluggableWidgets/custom-chart-web/src/package.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="utf-8" ?>
22
<package xmlns="http://www.mendix.com/package/1.0/">
3-
<clientModule name="CustomChart" version="1.2.3" xmlns="http://www.mendix.com/clientModule/1.0/">
3+
<clientModule name="CustomChart" version="1.2.4" xmlns="http://www.mendix.com/clientModule/1.0/">
44
<widgetFiles>
55
<widgetFile path="CustomChart.xml" />
66
</widgetFiles>

packages/pluggableWidgets/custom-chart-web/src/utils/utils.spec.ts

Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,75 @@ describe("parseData", () => {
1010
expect(parseData(staticData)).toEqual([{ x: [1], y: [2] }]);
1111
});
1212

13-
it("parses sampleData when attributeData and staticData are empty", () => {
14-
const sampleData = JSON.stringify([{ x: [3], y: [4] }]);
15-
expect(parseData(undefined, undefined, sampleData)).toEqual([{ x: [3], y: [4] }]);
13+
it("parses attributeData only", () => {
14+
const attributeData = JSON.stringify([{ x: [5], y: [6] }]);
15+
expect(parseData(undefined, attributeData)).toEqual([{ x: [5], y: [6] }]);
1616
});
1717

18-
it("parses attributeData and ignores sampleData if attributeData is present", () => {
19-
const attributeData = JSON.stringify([{ x: [5], y: [6] }]);
20-
const sampleData = JSON.stringify([{ x: [7], y: [8] }]);
21-
expect(parseData(undefined, attributeData, sampleData)).toEqual([{ x: [5], y: [6] }]);
18+
it("merges static and attribute traces by index with equal lengths", () => {
19+
const staticData = JSON.stringify([
20+
{ type: "bar", x: [1, 2, 3] },
21+
{ type: "line", x: [4, 5, 6] }
22+
]);
23+
const attributeData = JSON.stringify([{ y: [10, 20, 30] }, { y: [40, 50, 60] }]);
24+
expect(parseData(staticData, attributeData)).toEqual([
25+
{ type: "bar", x: [1, 2, 3], y: [10, 20, 30] },
26+
{ type: "line", x: [4, 5, 6], y: [40, 50, 60] }
27+
]);
28+
});
29+
30+
it("attribute data overrides static properties", () => {
31+
const staticData = JSON.stringify([{ name: "static", x: [1, 2] }]);
32+
const attributeData = JSON.stringify([{ name: "attribute", y: [3, 4] }]);
33+
expect(parseData(staticData, attributeData)).toEqual([{ name: "attribute", x: [1, 2], y: [3, 4] }]);
34+
});
35+
36+
it("appends extra static traces when static has more traces", () => {
37+
const staticData = JSON.stringify([
38+
{ type: "bar", x: [1] },
39+
{ type: "line", x: [2] },
40+
{ type: "scatter", x: [3] }
41+
]);
42+
const attributeData = JSON.stringify([{ y: [10] }]);
43+
expect(parseData(staticData, attributeData)).toEqual([
44+
{ type: "bar", x: [1], y: [10] },
45+
{ type: "line", x: [2] },
46+
{ type: "scatter", x: [3] }
47+
]);
48+
});
49+
50+
it("appends extra attribute traces when attribute has more traces", () => {
51+
const staticData = JSON.stringify([{ type: "bar", x: [1] }]);
52+
const attributeData = JSON.stringify([{ y: [10] }, { y: [20] }, { y: [30] }]);
53+
expect(parseData(staticData, attributeData)).toEqual([
54+
{ type: "bar", x: [1], y: [10] },
55+
{ y: [20] },
56+
{ y: [30] }
57+
]);
58+
});
59+
60+
it("returns empty array on invalid JSON", () => {
61+
expect(parseData("invalid json")).toEqual([]);
62+
});
63+
64+
it("merges sampleData with static when attributeData is empty", () => {
65+
const staticData = JSON.stringify([{ type: "bar", x: [1, 2, 3] }]);
66+
const sampleData = JSON.stringify([{ y: [10, 20, 30] }]);
67+
expect(parseData(staticData, undefined, sampleData)).toEqual([{ type: "bar", x: [1, 2, 3], y: [10, 20, 30] }]);
68+
});
69+
70+
it("ignores sampleData when attributeData is present", () => {
71+
const staticData = JSON.stringify([{ type: "bar", x: [1] }]);
72+
const attributeData = JSON.stringify([{ y: [10] }]);
73+
const sampleData = JSON.stringify([{ y: [99], name: "sample" }]);
74+
expect(parseData(staticData, attributeData, sampleData)).toEqual([{ type: "bar", x: [1], y: [10] }]);
75+
});
76+
77+
it("uses sampleData only when attributeData is empty array string", () => {
78+
const staticData = JSON.stringify([{ type: "line", x: [1] }]);
79+
const attributeData = JSON.stringify([]);
80+
const sampleData = JSON.stringify([{ y: [5] }]);
81+
expect(parseData(staticData, attributeData, sampleData)).toEqual([{ type: "line", x: [1], y: [5] }]);
2282
});
2383
});
2484

packages/pluggableWidgets/custom-chart-web/src/utils/utils.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,25 @@ import { Config, Data, Layout } from "plotly.js-dist-min";
33
import { ChartProps } from "../components/PlotlyChart";
44

55
export function parseData(staticData?: string, attributeData?: string, sampleData?: string): Data[] {
6-
let finalData: Data[] = [];
7-
86
try {
9-
const dataAttribute = attributeData ? JSON.parse(attributeData) : [];
10-
finalData = [...finalData, ...(staticData ? JSON.parse(staticData) : []), ...dataAttribute];
7+
const staticTraces: Data[] = staticData ? JSON.parse(staticData) : [];
8+
const attrTraces: Data[] = attributeData ? JSON.parse(attributeData) : [];
9+
10+
// Use sampleData as fallback when attributeData is empty
11+
const dynamicTraces: Data[] = attrTraces.length > 0 ? attrTraces : sampleData ? JSON.parse(sampleData) : [];
12+
13+
const maxLen = Math.max(staticTraces.length, dynamicTraces.length);
14+
const result: Data[] = [];
1115

12-
if (dataAttribute.length === 0) {
13-
finalData = [...finalData, ...(sampleData ? JSON.parse(sampleData) : [])];
16+
for (let i = 0; i < maxLen; i++) {
17+
result.push({ ...staticTraces[i], ...dynamicTraces[i] } as Data);
1418
}
19+
20+
return result;
1521
} catch (error) {
1622
console.error("Error parsing chart data:", error);
23+
return [];
1724
}
18-
19-
return finalData;
2025
}
2126

2227
export function parseLayout(staticLayout?: string, attributeLayout?: string, sampleLayout?: string): Partial<Layout> {

0 commit comments

Comments
 (0)