Skip to content

Commit ca503c6

Browse files
committed
fixing OntologySunburst.vue
1 parent 6fe1c28 commit ca503c6

1 file changed

Lines changed: 53 additions & 93 deletions

File tree

src/components/Ontologies/OntologySunburst.vue

Lines changed: 53 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,20 @@
11
<template>
22
<div class="highcharts-wrapper">
3-
<highcharts v-if="!loadingData" :options="sunburstOptions" />
3+
<highcharts
4+
v-if="!loadingData && isBrowser && modulesReady"
5+
:options="sunburstOptions"
6+
/>
47
</div>
58
</template>
69

710
<script>
11+
import { defineAsyncComponent } from "vue";
812
import { mapActions, mapGetters, mapState } from "vuex";
913
import { useTheme } from "vuetify";
10-
import Highcharts from "highcharts";
11-
import Sunburst from "highcharts/modules/sunburst";
12-
import Exporting from "highcharts/modules/exporting";
13-
import { defineAsyncComponent } from "vue"; //Implement Sunburst module for Highcharts
14-
15-
//Implement Sunburst module for Highcharts
16-
// check if Sunburst is a function, if not try .default
17-
if (typeof Sunburst === "function") {
18-
Sunburst(Highcharts);
19-
} else if (typeof Sunburst.default === "function") {
20-
Sunburst.default(Highcharts);
21-
}
22-
23-
if (typeof Exporting === "function") {
24-
Exporting(Highcharts);
25-
} else if (typeof Exporting.default === "function") {
26-
Exporting.default(Highcharts);
27-
}
2814
2915
export default {
3016
name: "OntologySunburst",
3117
components: {
32-
// Register highcharts asynchronously so it bypasses Server-Side Compilation checks safely
3318
highcharts: defineAsyncComponent(() =>
3419
import("highcharts-vue").then(
3520
(module) => module.Chart || module.default.Chart || module,
@@ -46,6 +31,8 @@ export default {
4631
},
4732
data() {
4833
return {
34+
isBrowser: false,
35+
modulesReady: false,
4936
options: {
5037
chart: {
5138
borderWidth: 0,
@@ -56,12 +43,8 @@ export default {
5643
fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
5744
},
5845
},
59-
credits: {
60-
enabled: false,
61-
},
62-
breadcrumbs: {
63-
enabled: false,
64-
},
46+
credits: { enabled: false },
47+
breadcrumbs: { enabled: false },
6548
title: {
6649
text: "Subject Browser",
6750
style: { color: "#DD7920", fontSize: "26px", fontWeight: 500 },
@@ -79,16 +62,16 @@ export default {
7962
colors: [
8063
"white",
8164
this.theme.computedThemes.value.fairSharingTheme.colors
82-
.subject_topLevel_3, // here
65+
.subject_topLevel_3,
8366
"white",
8467
"white",
8568
this.theme.computedThemes.value.fairSharingTheme.colors
86-
.subject_topLevel_1, // here
69+
.subject_topLevel_1,
8770
"white",
8871
"white",
8972
"white",
9073
this.theme.computedThemes.value.fairSharingTheme.colors
91-
.subject_topLevel_2, // here
74+
.subject_topLevel_2,
9275
],
9376
type: "sunburst",
9477
allowDrillToNode: true,
@@ -116,11 +99,7 @@ export default {
11699
},
117100
levelSize: { value: 2.3 },
118101
},
119-
{
120-
level: 2,
121-
colorByPoint: true,
122-
levelSize: { value: 3 },
123-
},
102+
{ level: 2, colorByPoint: true, levelSize: { value: 3 } },
124103
{
125104
level: 3,
126105
colorVariation: { key: "brightness", to: -0.5 },
@@ -136,27 +115,9 @@ export default {
136115
colorVariation: { key: "brightness", to: 0.5 },
137116
levelSize: { value: 2 },
138117
},
139-
{
140-
level: 6,
141-
colorVariation: {
142-
key: "brightness",
143-
to: 0.2,
144-
},
145-
},
146-
{
147-
level: 7,
148-
colorVariation: {
149-
key: "brightness",
150-
to: 0.5,
151-
},
152-
},
153-
{
154-
level: 8,
155-
colorVariation: {
156-
key: "brightness",
157-
to: 0.5,
158-
},
159-
},
118+
{ level: 6, colorVariation: { key: "brightness", to: 0.2 } },
119+
{ level: 7, colorVariation: { key: "brightness", to: 0.5 } },
120+
{ level: 8, colorVariation: { key: "brightness", to: 0.5 } },
160121
],
161122
},
162123
],
@@ -174,18 +135,12 @@ export default {
174135
},
175136
},
176137
exporting: {
177-
enabled: true, // explicit enable
138+
enabled: true,
178139
sourceWidth: 1500,
179140
sourceHeight: 1600,
180141
scale: 1,
181142
filename: "FAIRsharing Subject Sunburst",
182-
buttons: {
183-
contextButton: {
184-
// You can customize the menu symbol or position here if needed
185-
// symbol: 'menu',
186-
// align: 'right',
187-
},
188-
},
143+
buttons: { contextButton: {} },
189144
},
190145
subjectsArrList: [],
191146
nodeClicked: "",
@@ -196,15 +151,13 @@ export default {
196151
const _client = this;
197152
let options = { ..._client.options };
198153
options.series[0].data = _client.sunburstData;
199-
/* istanbul ignore next */
200154
options.series[0].point = {
201155
events: {
202156
click: function () {
203157
_client.processClickEvent(this);
204158
},
205159
},
206160
};
207-
/* istanbul ignore next */
208161
options.tooltip.formatter = function () {
209162
return _client.getTooltip(this.point);
210163
};
@@ -217,33 +170,47 @@ export default {
217170
"flattenedTree",
218171
]),
219172
},
220-
mounted() {
221-
this.flattenedOriginalTree(this.tree);
173+
async mounted() {
174+
if (typeof window !== "undefined") {
175+
this.isBrowser = true;
176+
177+
// 1. Await module initialization
178+
const { default: Highcharts } = await import("highcharts");
179+
const { default: Sunburst } = await import("highcharts/modules/sunburst");
180+
const { default: Exporting } = await import(
181+
"highcharts/modules/exporting"
182+
);
183+
184+
if (typeof Sunburst === "function") {
185+
Sunburst(Highcharts);
186+
} else if (Sunburst && typeof Sunburst.default === "function") {
187+
Sunburst.default(Highcharts);
188+
}
189+
190+
if (typeof Exporting === "function") {
191+
Exporting(Highcharts);
192+
} else if (Exporting && typeof Exporting.default === "function") {
193+
Exporting.default(Highcharts);
194+
}
195+
196+
// 2. FIX: Flip flag strictly AFTER modules attach to Highcharts
197+
this.modulesReady = true;
198+
}
199+
200+
if (this.tree) {
201+
this.flattenedOriginalTree(this.tree);
202+
}
222203
},
223204
methods: {
224-
/**
225-
* Recursively flattens a hierarchical tree structure into a single array of nodes.
226-
* Each node is added to the `subjectsArrList` array. If a node has children,
227-
* the method is called recursively on the children.
228-
*
229-
* @param {Array<Object>} tree - The hierarchical tree structure to be flattened. Each node may have a `children` property containing an array of child nodes.
230-
* @return {void} This method does not return a value. It modifies the `subjectsArrList` array in place.
231-
*/
232205
flattenedOriginalTree(tree) {
206+
if (!tree || !Array.isArray(tree)) return;
233207
tree.forEach((item) => {
234208
this.subjectsArrList.push(item);
235209
if (item["children"] && item["children"].length) {
236210
this.flattenedOriginalTree(item["children"]);
237211
}
238212
});
239213
},
240-
241-
/**
242-
* Handles click events on a node and performs routing or emits a selected subject node to the parent component.
243-
*
244-
* @param {Object} node - The node object that was clicked. This object contains properties such as `descendants_count`,`name`, `identifier`, and `ancestors` which are used in processing the click event.
245-
* @return {void} This method does not return any value. It performs routing or emits an event based on the clicked node.
246-
*/
247214
processClickEvent(node) {
248215
if (node.name !== "Subject") {
249216
if (node.descendants_count === 0) {
@@ -258,8 +225,6 @@ export default {
258225
}
259226
}
260227
261-
//If the node is clicked for the first time emit node, if the same node is clicked second time while it is active this means that node was already open.
262-
//Hence it's ancestor should be passed.
263228
if (node["ancestors"] && !node["ancestors"].length) {
264229
this.$emit("subjectNode", []);
265230
} else {
@@ -270,30 +235,25 @@ export default {
270235
this.nodeClicked = nodeAncestor;
271236
}
272237
273-
//Filter the selected subject from the arrayList and emit to the parent component
274238
let selectedSubject = this.subjectsArrList.filter(
275239
(n) => n.identifier === this.nodeClicked,
276240
);
277241
278-
//Adding key-value pair
279242
if (
243+
selectedSubject[0] &&
280244
selectedSubject[0]["children"] &&
281245
selectedSubject[0]["children"].length
282246
) {
283247
selectedSubject[0]["hasChildren"] = true;
284248
selectedSubject[0]["isSunburst"] = true;
285249
}
286250
287-
this.$emit("subjectNode", selectedSubject);
251+
if (selectedSubject[0]) {
252+
this.$emit("subjectNode", selectedSubject);
253+
}
288254
}
289255
}
290256
},
291-
292-
/**
293-
* Get ToolTip
294-
* @param point
295-
* @return {boolean|string}
296-
*/
297257
getTooltip(point) {
298258
return point.name === "Subjects"
299259
? false

0 commit comments

Comments
 (0)