visualifyjs 2.5.3-2.dev → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (252) hide show
  1. package/.claude/mem/TIMELINE.md +36 -0
  2. package/.claude/mem/notes/2026-02-11-3d-visualization-docs-fix-external-script-solution.md +24 -0
  3. package/.claude/mem/notes/2026-02-11-3d-visualization-docs-fix-session-summary.md +43 -0
  4. package/.claude/mem/notes/2026-02-11-cli-fix-editor-command-alias.md +26 -0
  5. package/.claude/mem/notes/2026-02-11-phase-3-developer-experience-completed.md +51 -0
  6. package/.claude/mem/notes/2026-02-11-phase-4-web-workers-implementation-complete.md +59 -0
  7. package/.claude/mem/notes/2026-02-11-visualify-phase-2-3d-visualization-complete.md +50 -0
  8. package/.claude/mem/notes/2026-02-11-visualify-phase-2-committed-ready-for-phase-3.md +33 -0
  9. package/.claude/mem/notes/2026-02-11-visualify-phase-3-complete-developer-experience.md +52 -0
  10. package/.claude/mem/notes/2026-02-11-visualify-repository-cleanup-complete.md +28 -0
  11. package/.claude/mem/notes/2026-02-18-codebase-cleanup-docsify-plugin-documentation.md +37 -0
  12. package/.claude/mem/notes/2026-02-19-css-grid-layout-fix-displaycontents-on-vcontroller.md +18 -0
  13. package/.claude/mem/notes/2026-02-19-docsify-plugin-fixes-latex-and-visualify-code-bloc.md +26 -0
  14. package/.claude/mem/notes/2026-02-19-page-mode-docs-update-decisions.md +23 -0
  15. package/.claude/mem/notes/2026-02-19-react-context-infinite-re-render-loop-fix-pattern.md +31 -0
  16. package/.claude/mem/notes/2026-02-19-version-300-bump-and-build-fixes.md +32 -0
  17. package/.claude/mem/notes/2026-02-19-visualify-build-deployment-architecture-bug-fixes.md +25 -0
  18. package/.claude/mem/notes/2026-02-19-visualify-dist-iife-self-contained-build-config.md +30 -0
  19. package/.claude/mem/notes/2026-02-19-visualify-infinite-loop-i18n-fixes.md +31 -0
  20. package/.claude/mem/notes/2026-02-19-visualify-v3-bundle-splitting-docs-restructuring.md +32 -0
  21. package/.claude/mem/notes/2026-02-20-bundle-externalization-final-architecture.md +29 -0
  22. package/.claude/mem/notes/2026-02-20-chromium-page-fix-unstable-keys-and-double-event-b.md +27 -0
  23. package/.claude/mem/notes/2026-02-20-console-cleanup-bundle-optimization-commit.md +20 -0
  24. package/.claude/mem/notes/2026-02-20-dotbio-dot-plot-fix-useeffect-dependency.md +21 -0
  25. package/.claude/mem/notes/2026-02-20-public-folder-cleanup-and-readme-rewrite.md +25 -0
  26. package/.claude/mem/notes/2026-02-20-v300-release-and-beta-channel-strategy.md +29 -0
  27. package/.claude/mem/notes/2026-02-20-visium-background-image-unknown-legend-fix.md +19 -0
  28. package/.claude/mem/notes/2026-02-20-visualify-cdn-loader-bundle-externalization.md +34 -0
  29. package/.claude/mem/sessions/session-2026-02-20-031524.md +54 -0
  30. package/.claude/settings.local.json +21 -0
  31. package/.github/workflows/static.yml.bak +51 -51
  32. package/.sisyphus/boulder.json +65 -0
  33. package/.sisyphus/plans/phase-4-advanced-optimizations.md +217 -0
  34. package/LICENSE +674 -674
  35. package/README.md +94 -59
  36. package/config-overrides.js +31 -31
  37. package/dist/stats.html +4949 -0
  38. package/dist/visualify-3d.esm.js +1 -0
  39. package/dist/visualify-3d.js +1 -0
  40. package/dist/visualify-core.esm.js +1 -0
  41. package/dist/visualify-core.js +1 -0
  42. package/dist/visualify-docs.esm.js +1 -0
  43. package/dist/visualify-docs.js +1 -0
  44. package/dist/visualify-loader.js +1 -0
  45. package/dist/visualify-pages.esm.js +1 -0
  46. package/dist/visualify-pages.js +1 -0
  47. package/dist/visualify-portal.esm.js +1 -0
  48. package/dist/visualify-portal.js +1 -0
  49. package/dist/visualify-shared.js +26571 -0
  50. package/dist/visualify.js +1 -188
  51. package/docs/CHANGELOG.md +148 -0
  52. package/docs/cli/commands.md +513 -0
  53. package/docs/configuration/visualify-json.md +474 -0
  54. package/docs/docs/3d-visualization.md +374 -0
  55. package/docs/docs/CLI.md +303 -34
  56. package/docs/docs/README.md +65 -65
  57. package/docs/docs/Rechart/bar.md +190 -190
  58. package/docs/docs/Rechart/funnel.md +241 -241
  59. package/docs/docs/Rechart/line.md +355 -355
  60. package/docs/docs/Rechart/pie.md +225 -225
  61. package/docs/docs/Rechart/radar.md +253 -253
  62. package/docs/docs/Rechart/scatter.md +298 -298
  63. package/docs/docs/_404.md +51 -51
  64. package/docs/docs/_coverpage.md +11 -11
  65. package/docs/docs/_sidebar.md +54 -44
  66. package/docs/docs/components/dotBio.md +87 -34
  67. package/docs/docs/components/echart.md +171 -82
  68. package/docs/docs/components/html.md +61 -34
  69. package/docs/docs/components/macaron.md +156 -145
  70. package/docs/docs/components/markdown.md +42 -0
  71. package/docs/docs/components/more.md +183 -142
  72. package/docs/docs/components/plotly.md +132 -62
  73. package/docs/docs/components/scatterL.md +171 -70
  74. package/docs/docs/components/visium.md +112 -57
  75. package/docs/docs/configuration.md +121 -121
  76. package/docs/docs/deploy.md +31 -31
  77. package/docs/docs/docsify-plugin.md +655 -0
  78. package/docs/docs/hmr.md +165 -0
  79. package/docs/docs/i18n.md +332 -0
  80. package/docs/docs/log.md +30 -9
  81. package/docs/docs/more-pages.md +23 -23
  82. package/docs/docs/quickstart.md +148 -124
  83. package/docs/docs/rechart-attributes.md +74 -74
  84. package/docs/docs/rechart-basic-usage.md +160 -162
  85. package/docs/docs/theme.md +5 -5
  86. package/docs/docs/typescript.md +306 -0
  87. package/docs/docs/visual-editor.md +359 -0
  88. package/docs/index.html +85 -71
  89. package/docs/manifest.json +23 -23
  90. package/docs/migration/v3-migration.md +392 -0
  91. package/docs/static/css/fluff-stuff.css +169 -169
  92. package/docs/static/css/font-awesome.min.css +4 -4
  93. package/docs/static/css/visualify.css +6 -25
  94. package/docs/static/js/3d-viz-examples.js +181 -0
  95. package/docs/static/js/configuration.js +630 -448
  96. package/docs/static/js/visualify.js +1 -188
  97. package/package.json +106 -84
  98. package/rollup.config.mjs +766 -76
  99. package/src/_css/404.css +115 -115
  100. package/src/_css/App.css +37 -37
  101. package/src/_css/autoSuggestion.css +26 -26
  102. package/src/_css/circular-progress.css +32 -32
  103. package/src/_css/index.css +36 -36
  104. package/src/_css/modern.css +350 -25
  105. package/src/_media/corner.svg +8 -8
  106. package/src/_media/download.svg +3 -3
  107. package/src/_media/logo.svg +14 -14
  108. package/src/_test/App.test.js +15 -15
  109. package/src/_utils/reportWebVitals.js +13 -13
  110. package/src/a11y/README.md +177 -0
  111. package/src/a11y/aria-labels.js +339 -0
  112. package/src/a11y/color-contrast.js +535 -0
  113. package/src/a11y/index.js +197 -0
  114. package/src/a11y/keyboard-nav.js +523 -0
  115. package/src/a11y/styles.css +165 -0
  116. package/src/cli/commands/dev.js +214 -0
  117. package/src/cli/commands/docs.js +521 -0
  118. package/src/cli/commands/edit.js +379 -0
  119. package/src/cli/commands/init.js +213 -0
  120. package/src/cli/commands/portal.js +236 -0
  121. package/src/cli/dev-server.js +530 -0
  122. package/src/cli/hmr.js +456 -0
  123. package/src/cli/index.js +180 -0
  124. package/src/cli/utils/config.js +207 -0
  125. package/src/cli/utils/logger.js +241 -0
  126. package/src/config/defaults.ts +122 -0
  127. package/src/config/index.ts +72 -0
  128. package/src/config/loader.ts +478 -0
  129. package/src/config/schema.ts +227 -0
  130. package/src/config/validator.ts +337 -0
  131. package/src/core/appContext.js +34 -27
  132. package/src/core/components/Bar.js +383 -0
  133. package/src/core/components/Bar3D.js +473 -0
  134. package/src/core/components/LargeDatasetChart.js +296 -0
  135. package/src/core/components/Line3D.js +310 -0
  136. package/src/core/components/Scatter.js +392 -188
  137. package/src/core/components/Scatter3D.js +455 -0
  138. package/src/core/components/ScatterBio.js +601 -572
  139. package/src/core/components/Surface3D.js +326 -0
  140. package/src/core/components/ThreeCustom.js +648 -0
  141. package/src/core/components/ThreeScene.js +459 -0
  142. package/src/core/components/VisiumPlot.js +191 -165
  143. package/src/core/components/browser.js +42 -42
  144. package/src/core/components/dotplot.js +413 -413
  145. package/src/core/components/html.js +29 -29
  146. package/src/core/components/list.js +178 -178
  147. package/src/core/components/macaron.js +206 -201
  148. package/src/core/components/markdown.js +56 -56
  149. package/src/core/components/parser.scatterBio.js +582 -587
  150. package/src/core/components/ratio.js +82 -80
  151. package/src/core/components/scatterL.js +206 -173
  152. package/src/core/components/searchbar.js +156 -131
  153. package/src/core/components/selection.js +310 -193
  154. package/src/core/components/timeline.js +236 -281
  155. package/src/core/components/visium.js +114 -97
  156. package/src/core/data-processor.js +413 -0
  157. package/src/core/fetch/condfetch.js +82 -82
  158. package/src/core/fetch/fetch.js +92 -92
  159. package/src/core/fetch/json.js +29 -29
  160. package/src/core/fetch/vfetch.js +42 -42
  161. package/src/core/hmr-client.js +724 -0
  162. package/src/core/liveEditor.js +44 -44
  163. package/src/core/modules/codeEditorWithPreview.js +104 -104
  164. package/src/core/modules/echarts/common.js +20 -20
  165. package/src/core/modules/echarts/gl.js +228 -0
  166. package/src/core/modules/echarts/presetHandler.js +41 -41
  167. package/src/core/modules/echarts/presets/esodev.chromium.js +172 -172
  168. package/src/core/modules/echarts/presets/esodev.codex.js +130 -130
  169. package/src/core/modules/echarts/presets/esodev.visium.js +123 -123
  170. package/src/core/modules/echarts/presets/mmtrbc.js +186 -186
  171. package/src/core/modules/echarts.js +70 -71
  172. package/src/core/modules/echartsUtils.js +43 -43
  173. package/src/core/modules/echartswitcher.js +227 -152
  174. package/src/core/modules/replotly/presetHandler.js +24 -24
  175. package/src/core/modules/replotly/presets/minimum.js +18 -18
  176. package/src/core/modules/replotly/presets/mmtrbc.dot.js +114 -114
  177. package/src/core/modules/replotly/presets/mmtrbc.violin.js +100 -100
  178. package/src/core/modules/replotly.js +74 -71
  179. package/src/core/modules/threejs/Camera.js +373 -0
  180. package/src/core/modules/threejs/Lighting.js +459 -0
  181. package/src/core/modules/threejs/Renderer.js +364 -0
  182. package/src/core/modules/threejs/Scene.js +266 -0
  183. package/src/core/modules/threejs/index.js +155 -0
  184. package/src/core/pages/404.js +50 -50
  185. package/src/core/pages/error.js +27 -27
  186. package/src/core/pages/jsonPage.js +62 -62
  187. package/src/core/pages/loading.js +44 -44
  188. package/src/core/parser/echart.data.js +204 -183
  189. package/src/core/parser/echart.features.js +125 -125
  190. package/src/core/parser/echart.general.js +147 -147
  191. package/src/core/parser/echart.hilbert.js +57 -57
  192. package/src/core/parser/echart.parser.js +210 -210
  193. package/src/core/parser/echart.series.js +67 -67
  194. package/src/core/parser/echart.types.js +76 -76
  195. package/src/core/parser/plotly.config.js +10 -10
  196. package/src/core/parser/plotly.data.js +132 -132
  197. package/src/core/parser/plotly.layout.js +9 -9
  198. package/src/core/parser/plotly.violin.js +18 -18
  199. package/src/core/recharts.js +361 -62
  200. package/src/core/router/alias.js +49 -49
  201. package/src/core/router/jsonRouter.js +31 -31
  202. package/src/core/themes/modern.js +32 -32
  203. package/src/core/themes/themeSelector.js +33 -33
  204. package/src/core/visualify.js +213 -47
  205. package/src/core/widgets/circularProgress.js +23 -23
  206. package/src/core/widgets/controller.js +116 -83
  207. package/src/core/widgets/errorBoundary.js +36 -36
  208. package/src/core/widgets/footer.js +185 -177
  209. package/src/core/widgets/header.js +238 -234
  210. package/src/core/widgets/layout/Grid.js +31 -31
  211. package/src/core/widgets/layout.js +36 -36
  212. package/src/core/widgets/mapping.js +56 -42
  213. package/src/core/workers/data-worker.js +349 -0
  214. package/src/core/workers/worker-pool.js +396 -0
  215. package/src/docsify/bundle.js +215 -0
  216. package/src/docsify/markdown.js +271 -0
  217. package/src/docsify/plugin.js +268 -0
  218. package/src/editor/README.md +172 -0
  219. package/src/editor/components/ChartBuilder.jsx +341 -0
  220. package/src/editor/components/ChartTypeSidebar.jsx +91 -0
  221. package/src/editor/components/Editor.jsx +367 -0
  222. package/src/editor/components/Preview.jsx +446 -0
  223. package/src/editor/components/PropertyPanel.jsx +468 -0
  224. package/src/editor/components/StatusBar.jsx +85 -0
  225. package/src/editor/context/EditorContext.js +248 -0
  226. package/src/editor/hooks/useDebounce.js +32 -0
  227. package/src/editor/index.js +315 -0
  228. package/src/editor/styles/editor.css +637 -0
  229. package/src/editor/utils/chartValidator.js +263 -0
  230. package/src/entries/charts3d.js +70 -0
  231. package/src/entries/core.js +78 -0
  232. package/src/entries/docs.js +154 -0
  233. package/src/entries/pages.js +93 -0
  234. package/src/entries/portal.js +204 -0
  235. package/src/entries/shared.js +50 -0
  236. package/src/i18n/formatters.js +455 -0
  237. package/src/i18n/index.js +169 -0
  238. package/src/i18n/locales/ar.json +137 -0
  239. package/src/i18n/locales/de.json +137 -0
  240. package/src/i18n/locales/en.json +137 -0
  241. package/src/i18n/locales/es.json +137 -0
  242. package/src/i18n/locales/he.json +137 -0
  243. package/src/i18n/locales/zh.json +137 -0
  244. package/src/i18n/rtl.css +183 -0
  245. package/src/index.js +82 -62
  246. package/src/loader.js +103 -0
  247. package/src/setupTests.js +5 -5
  248. package/tsconfig.json +51 -0
  249. package/types/charts.d.ts +569 -0
  250. package/types/components.d.ts +441 -0
  251. package/types/config.d.ts +199 -0
  252. package/types/index.d.ts +353 -0
@@ -1,210 +1,210 @@
1
- /*
2
- * @Author : Lihao leolihao@arizona.edu
3
- * @Date : 2023-12-23 23:27:45
4
- * @FilePath : /visualifyjs/src/core/parser/echart.parser.js
5
- * @Description :
6
- * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
- */
8
- import conditionalFetch from '../fetch/condfetch';
9
- import { isEmpty } from 'lodash';
10
-
11
- const enableVisualMap = (series) => {
12
- if (!series || series.length === 0) return false;
13
- const seriesData = series[0].data;
14
- if (!seriesData) return false;
15
- // Check if the series data has z values (indicating 3D data)
16
- return seriesData.some((dataPoint) => dataPoint.value.length === 3);
17
- };
18
-
19
- const _fetch_data = async (parser = {}, Options = {}, sharedData) => {
20
- const { sources } = parser;
21
-
22
- let fetched_data = {}; // response from api
23
-
24
- const processSource = async (source) => {
25
- let resp = await conditionalFetch(
26
- source,
27
- sharedData,
28
- Options.title,
29
- Options.visualify,
30
- );
31
- if (resp) fetched_data[source.name] = resp;
32
- };
33
-
34
- if (Array.isArray(sources)) {
35
- await Promise.all(sources.map(processSource));
36
- } else if (typeof sources === 'object') {
37
- await processSource(sources);
38
- }
39
-
40
- if (isEmpty(fetched_data))
41
- throw new Error(parser?.startup_msg ?? 'No data fetched from api');
42
-
43
- return fetched_data;
44
- };
45
-
46
- export const _process_fetched_data = (
47
- fetched_data,
48
- parser = {},
49
- Options = {},
50
- ) => {
51
- Options.series = __process_fetched_data(
52
- fetched_data,
53
- parser,
54
- Options.visualify,
55
- );
56
- Options.legend.data = Options.series.map((item) => item.name);
57
-
58
- if (!enableVisualMap(Options.series)) {
59
- //console.log('disable visual map');
60
- Options.visualMap = [];
61
- }
62
- return Options;
63
- };
64
-
65
- const __process_fetched_data = (
66
- fetched_data,
67
- parser_config,
68
- visualify = {},
69
- ) => {
70
- //console.log('visualify', visualify);
71
- const {
72
- seriesBy = visualify?.seriesBy ?? null,
73
- mapping = visualify?.mapping ?? {},
74
- exclude = visualify?.exclude ?? [],
75
- symbol = visualify?.symbol ?? null,
76
- symbolSize = visualify?.symbolSize ?? null,
77
- merger = visualify?.merger ?? null,
78
- filter = visualify?.filter ?? null,
79
- } = parser_config;
80
- const { x = 'x', y = 'y', z = 'z', extra = [] } = mapping;
81
- const aggregatedData = {};
82
-
83
- for (const [key, data] of Object.entries(fetched_data)) {
84
- //console.log('processing data from api', key, data);
85
- if (!data) {
86
- return Object.values(aggregatedData);
87
- } else if (data && merger && merger[key]) {
88
- /*
89
- console.log(
90
- `processing data from merger:`,
91
- key,
92
- `merger`,
93
- merger[key],
94
- `data`,
95
- data,
96
- `with`,
97
- aggregatedData,
98
- );
99
- */
100
- // add extra properties to aggregatedData.data
101
- Object.values(aggregatedData).forEach((item) => {
102
- item.data.forEach((value) => {
103
- if (merger[key].item in value) {
104
- let tag = value[merger[key].item];
105
- let val = data[tag];
106
- if (merger[key].label) value[merger[key].label] = val;
107
- if (merger[key].visualMap) value.value.push(val);
108
- }
109
- });
110
- });
111
- } else {
112
- // if seriesBy is not defined, get the first key of data as the series
113
- const seriesKey = seriesBy ?? Object.keys(data)[0];
114
-
115
- if (data[seriesKey] === undefined || data === undefined) continue;
116
- data[seriesKey].forEach((item, index) => {
117
- if (exclude && exclude.includes(item)) return;
118
-
119
- const extraProperties = {};
120
- for (const property in mapping.extra) {
121
- if (data[extra[property]]) {
122
- extraProperties[property] =
123
- data[extra[property]][index];
124
- }
125
- }
126
-
127
- if (!data[x] || !data[y] || !parser_config.type) return;
128
-
129
- const point = data[z]
130
- ? [data[x][index], data[y][index], data[z][index]]
131
- : [data[x][index], data[y][index]];
132
-
133
- if (!aggregatedData[item]) {
134
- aggregatedData[item] = {
135
- name: item,
136
- type: parser_config.type,
137
- data: [],
138
- };
139
- if (symbol) aggregatedData[item].symbol = symbol;
140
- if (symbolSize)
141
- aggregatedData[item].symbolSize = symbolSize;
142
- }
143
-
144
- aggregatedData[item].data.push({
145
- value: point,
146
- ...extraProperties,
147
- });
148
- });
149
- }
150
- }
151
-
152
- let processed_data = Object.values(aggregatedData);
153
-
154
- if (filter) {
155
- for (let filter_key of Object.keys(filter)) {
156
- const filter_expression = filter[filter_key];
157
- //console.log('filter', filter_key, filter_expression);
158
- processed_data = processed_data.map((item) => {
159
- const filteredData = item.data.filter((dataPoint) => {
160
- try {
161
- const value = dataPoint[filter_key];
162
- if (value === undefined || value === null) return true;
163
-
164
- const match =
165
- filter_expression.match(/([><]=?)\s*(-?\d+)/);
166
- if (!match)
167
- throw new Error(
168
- 'Invalid filter expression for filter',
169
- );
170
-
171
- // Extract the operator and threshold value
172
- const operator = match[1];
173
- const threshold = parseInt(match[2]);
174
- // Evaluate the filter expression using the function
175
- return eval_filter(value, operator, threshold);
176
- } catch (err) {
177
- console.warn('error in filter', err);
178
- return false;
179
- }
180
- });
181
- return {
182
- ...item,
183
- data: filteredData,
184
- };
185
- });
186
- }
187
- }
188
-
189
- return processed_data;
190
- };
191
-
192
- // Define a function to evaluate filter expressions
193
- function eval_filter(value, operator, threshold) {
194
- switch (operator) {
195
- case '<':
196
- return value < threshold;
197
- case '<=':
198
- return value <= threshold;
199
- case '>':
200
- return value > threshold;
201
- case '>=':
202
- return value >= threshold;
203
- case '=':
204
- return value === threshold;
205
- default:
206
- throw new Error('Invalid operator in filter expression');
207
- }
208
- }
209
-
210
- export default _fetch_data;
1
+ /*
2
+ * @Author : Lihao leolihao@arizona.edu
3
+ * @Date : 2023-12-23 23:27:45
4
+ * @FilePath : /visualifyjs/src/core/parser/echart.parser.js
5
+ * @Description :
6
+ * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
+ */
8
+ import conditionalFetch from '../fetch/condfetch';
9
+ import { isEmpty } from 'lodash';
10
+
11
+ const enableVisualMap = (series) => {
12
+ if (!series || series.length === 0) return false;
13
+ const seriesData = series[0].data;
14
+ if (!seriesData) return false;
15
+ // Check if the series data has z values (indicating 3D data)
16
+ return seriesData.some((dataPoint) => dataPoint.value.length === 3);
17
+ };
18
+
19
+ const _fetch_data = async (parser = {}, Options = {}, sharedData) => {
20
+ const { sources } = parser;
21
+
22
+ let fetched_data = {}; // response from api
23
+
24
+ const processSource = async (source) => {
25
+ let resp = await conditionalFetch(
26
+ source,
27
+ sharedData,
28
+ Options.title,
29
+ Options.visualify,
30
+ );
31
+ if (resp) fetched_data[source.name] = resp;
32
+ };
33
+
34
+ if (Array.isArray(sources)) {
35
+ await Promise.all(sources.map(processSource));
36
+ } else if (typeof sources === 'object') {
37
+ await processSource(sources);
38
+ }
39
+
40
+ if (isEmpty(fetched_data))
41
+ throw new Error(parser?.startup_msg ?? 'No data fetched from api');
42
+
43
+ return fetched_data;
44
+ };
45
+
46
+ export const _process_fetched_data = (
47
+ fetched_data,
48
+ parser = {},
49
+ Options = {},
50
+ ) => {
51
+ Options.series = __process_fetched_data(
52
+ fetched_data,
53
+ parser,
54
+ Options.visualify,
55
+ );
56
+ Options.legend.data = Options.series.map((item) => item.name);
57
+
58
+ if (!enableVisualMap(Options.series)) {
59
+ //console.log('disable visual map');
60
+ Options.visualMap = [];
61
+ }
62
+ return Options;
63
+ };
64
+
65
+ const __process_fetched_data = (
66
+ fetched_data,
67
+ parser_config,
68
+ visualify = {},
69
+ ) => {
70
+ //console.log('visualify', visualify);
71
+ const {
72
+ seriesBy = visualify?.seriesBy ?? null,
73
+ mapping = visualify?.mapping ?? {},
74
+ exclude = visualify?.exclude ?? [],
75
+ symbol = visualify?.symbol ?? null,
76
+ symbolSize = visualify?.symbolSize ?? null,
77
+ merger = visualify?.merger ?? null,
78
+ filter = visualify?.filter ?? null,
79
+ } = parser_config;
80
+ const { x = 'x', y = 'y', z = 'z', extra = [] } = mapping;
81
+ const aggregatedData = {};
82
+
83
+ for (const [key, data] of Object.entries(fetched_data)) {
84
+ //console.log('processing data from api', key, data);
85
+ if (!data) {
86
+ return Object.values(aggregatedData);
87
+ } else if (data && merger && merger[key]) {
88
+ /*
89
+ console.log(
90
+ `processing data from merger:`,
91
+ key,
92
+ `merger`,
93
+ merger[key],
94
+ `data`,
95
+ data,
96
+ `with`,
97
+ aggregatedData,
98
+ );
99
+ */
100
+ // add extra properties to aggregatedData.data
101
+ Object.values(aggregatedData).forEach((item) => {
102
+ item.data.forEach((value) => {
103
+ if (merger[key].item in value) {
104
+ let tag = value[merger[key].item];
105
+ let val = data[tag];
106
+ if (merger[key].label) value[merger[key].label] = val;
107
+ if (merger[key].visualMap) value.value.push(val);
108
+ }
109
+ });
110
+ });
111
+ } else {
112
+ // if seriesBy is not defined, get the first key of data as the series
113
+ const seriesKey = seriesBy ?? Object.keys(data)[0];
114
+
115
+ if (data[seriesKey] === undefined || data === undefined) continue;
116
+ data[seriesKey].forEach((item, index) => {
117
+ if (exclude && exclude.includes(item)) return;
118
+
119
+ const extraProperties = {};
120
+ for (const property in mapping.extra) {
121
+ if (data[extra[property]]) {
122
+ extraProperties[property] =
123
+ data[extra[property]][index];
124
+ }
125
+ }
126
+
127
+ if (!data[x] || !data[y] || !parser_config.type) return;
128
+
129
+ const point = data[z]
130
+ ? [data[x][index], data[y][index], data[z][index]]
131
+ : [data[x][index], data[y][index]];
132
+
133
+ if (!aggregatedData[item]) {
134
+ aggregatedData[item] = {
135
+ name: item,
136
+ type: parser_config.type,
137
+ data: [],
138
+ };
139
+ if (symbol) aggregatedData[item].symbol = symbol;
140
+ if (symbolSize)
141
+ aggregatedData[item].symbolSize = symbolSize;
142
+ }
143
+
144
+ aggregatedData[item].data.push({
145
+ value: point,
146
+ ...extraProperties,
147
+ });
148
+ });
149
+ }
150
+ }
151
+
152
+ let processed_data = Object.values(aggregatedData);
153
+
154
+ if (filter) {
155
+ for (let filter_key of Object.keys(filter)) {
156
+ const filter_expression = filter[filter_key];
157
+ //console.log('filter', filter_key, filter_expression);
158
+ processed_data = processed_data.map((item) => {
159
+ const filteredData = item.data.filter((dataPoint) => {
160
+ try {
161
+ const value = dataPoint[filter_key];
162
+ if (value === undefined || value === null) return true;
163
+
164
+ const match =
165
+ filter_expression.match(/([><]=?)\s*(-?\d+)/);
166
+ if (!match)
167
+ throw new Error(
168
+ 'Invalid filter expression for filter',
169
+ );
170
+
171
+ // Extract the operator and threshold value
172
+ const operator = match[1];
173
+ const threshold = parseInt(match[2]);
174
+ // Evaluate the filter expression using the function
175
+ return eval_filter(value, operator, threshold);
176
+ } catch (err) {
177
+ console.warn('error in filter', err);
178
+ return false;
179
+ }
180
+ });
181
+ return {
182
+ ...item,
183
+ data: filteredData,
184
+ };
185
+ });
186
+ }
187
+ }
188
+
189
+ return processed_data;
190
+ };
191
+
192
+ // Define a function to evaluate filter expressions
193
+ function eval_filter(value, operator, threshold) {
194
+ switch (operator) {
195
+ case '<':
196
+ return value < threshold;
197
+ case '<=':
198
+ return value <= threshold;
199
+ case '>':
200
+ return value > threshold;
201
+ case '>=':
202
+ return value >= threshold;
203
+ case '=':
204
+ return value === threshold;
205
+ default:
206
+ throw new Error('Invalid operator in filter expression');
207
+ }
208
+ }
209
+
210
+ export default _fetch_data;
@@ -1,67 +1,67 @@
1
- /*
2
- * @Author : Lihao leolihao@arizona.edu
3
- * @Date : 2023-12-02 22:53:11
4
- * @FilePath : /visualifyjs/src/core/parser/echart.series.js
5
- * @Description :
6
- * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
- */
8
- export function _handleSeries(options, seriesObject, index) {
9
- setArrayEl(seriesObject, options, 'label', index);
10
- setArrayEl(seriesObject, options, 'labelLine', index);
11
- setArrayEl(seriesObject, options, 'itemStyle', index);
12
- setArrayEl(seriesObject, options, 'emphasis', index);
13
- // Handle Line Chart options
14
- if (seriesObject.type === 'line') {
15
- setArrayEl(seriesObject, options, 'smooth', index);
16
- setArrayEl(seriesObject, options, 'step', index);
17
- setArrayEl(seriesObject, options, 'areaStyle', index);
18
- } else if (seriesObject.type === 'pie') {
19
- setArrayEl(seriesObject, options, 'selectedMode', index);
20
- setArrayEl(seriesObject, options, 'roseType', index);
21
- if ('center' in options)
22
- seriesObject.center = getArray(options.center, index);
23
- if ('radius' in options)
24
- seriesObject.radius = getArray(options.radius, index);
25
- } else if (seriesObject.type === 'radar') {
26
- if ('radar' in options && Array.isArray(options.radar))
27
- seriesObject.radarIndex = index;
28
- } else if (seriesObject.type === 'funnel') {
29
- seriesObject.top = getArrayEl(options.top, index) ?? 60;
30
- seriesObject.bottom = getArrayEl(options.bottom, index) ?? 60;
31
- seriesObject.left = getArrayEl(options.left, index) ?? '10%';
32
- setArrayEl(seriesObject, options, 'right', index);
33
- seriesObject.width = getArrayEl(options.width, index) ?? '80%';
34
- setArrayEl(seriesObject, options, 'height', index);
35
- seriesObject.min = getArrayEl(options.min, index) ?? 0;
36
- seriesObject.max = getArrayEl(options.max, index) ?? 100;
37
- seriesObject.minSize = getArrayEl(options.minSize, index) ?? '0%';
38
- seriesObject.maxSize = getArrayEl(options.maxSize, index) ?? '100%';
39
- seriesObject.sort = getArrayEl(options.sort, index) ?? 'descending';
40
- seriesObject.gap = getArrayEl(options.gap, index) ?? 0;
41
- seriesObject.funnelAlign =
42
- getArrayEl(options.funnelAlign, index) ?? 'center';
43
- setArrayEl(seriesObject, options, 'z', index);
44
- }
45
- }
46
-
47
- function setArrayEl(sereis, options, param, index) {
48
- let val = getArrayEl(options[param], index);
49
- if (param in options && val) sereis[param] = val;
50
- }
51
-
52
- // Helper function to get the type for each series
53
- export function getArrayEl(value, index) {
54
- return Array.isArray(value)
55
- ? value[Math.min(index, value.length - 1)]
56
- : value;
57
- }
58
-
59
- function getArray(value, index) {
60
- let _inedx = Math.min(index, value.length - 1);
61
- if (Array.isArray(value) && Array.isArray(value[_inedx]))
62
- return value[_inedx];
63
- else if (Array.isArray(value)) return value;
64
- else return getArrayEl(value, index);
65
- }
66
-
67
- export default _handleSeries;
1
+ /*
2
+ * @Author : Lihao leolihao@arizona.edu
3
+ * @Date : 2023-12-02 22:53:11
4
+ * @FilePath : /visualifyjs/src/core/parser/echart.series.js
5
+ * @Description :
6
+ * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
+ */
8
+ export function _handleSeries(options, seriesObject, index) {
9
+ setArrayEl(seriesObject, options, 'label', index);
10
+ setArrayEl(seriesObject, options, 'labelLine', index);
11
+ setArrayEl(seriesObject, options, 'itemStyle', index);
12
+ setArrayEl(seriesObject, options, 'emphasis', index);
13
+ // Handle Line Chart options
14
+ if (seriesObject.type === 'line') {
15
+ setArrayEl(seriesObject, options, 'smooth', index);
16
+ setArrayEl(seriesObject, options, 'step', index);
17
+ setArrayEl(seriesObject, options, 'areaStyle', index);
18
+ } else if (seriesObject.type === 'pie') {
19
+ setArrayEl(seriesObject, options, 'selectedMode', index);
20
+ setArrayEl(seriesObject, options, 'roseType', index);
21
+ if ('center' in options)
22
+ seriesObject.center = getArray(options.center, index);
23
+ if ('radius' in options)
24
+ seriesObject.radius = getArray(options.radius, index);
25
+ } else if (seriesObject.type === 'radar') {
26
+ if ('radar' in options && Array.isArray(options.radar))
27
+ seriesObject.radarIndex = index;
28
+ } else if (seriesObject.type === 'funnel') {
29
+ seriesObject.top = getArrayEl(options.top, index) ?? 60;
30
+ seriesObject.bottom = getArrayEl(options.bottom, index) ?? 60;
31
+ seriesObject.left = getArrayEl(options.left, index) ?? '10%';
32
+ setArrayEl(seriesObject, options, 'right', index);
33
+ seriesObject.width = getArrayEl(options.width, index) ?? '80%';
34
+ setArrayEl(seriesObject, options, 'height', index);
35
+ seriesObject.min = getArrayEl(options.min, index) ?? 0;
36
+ seriesObject.max = getArrayEl(options.max, index) ?? 100;
37
+ seriesObject.minSize = getArrayEl(options.minSize, index) ?? '0%';
38
+ seriesObject.maxSize = getArrayEl(options.maxSize, index) ?? '100%';
39
+ seriesObject.sort = getArrayEl(options.sort, index) ?? 'descending';
40
+ seriesObject.gap = getArrayEl(options.gap, index) ?? 0;
41
+ seriesObject.funnelAlign =
42
+ getArrayEl(options.funnelAlign, index) ?? 'center';
43
+ setArrayEl(seriesObject, options, 'z', index);
44
+ }
45
+ }
46
+
47
+ function setArrayEl(sereis, options, param, index) {
48
+ let val = getArrayEl(options[param], index);
49
+ if (param in options && val) sereis[param] = val;
50
+ }
51
+
52
+ // Helper function to get the type for each series
53
+ export function getArrayEl(value, index) {
54
+ return Array.isArray(value)
55
+ ? value[Math.min(index, value.length - 1)]
56
+ : value;
57
+ }
58
+
59
+ function getArray(value, index) {
60
+ let _inedx = Math.min(index, value.length - 1);
61
+ if (Array.isArray(value) && Array.isArray(value[_inedx]))
62
+ return value[_inedx];
63
+ else if (Array.isArray(value)) return value;
64
+ else return getArrayEl(value, index);
65
+ }
66
+
67
+ export default _handleSeries;