visualifyjs 2.5.3-2.dev → 2.5.3-9-dev

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of visualifyjs might be problematic. Click here for more details.

Files changed (139) hide show
  1. package/.github/workflows/{static.yml.bak → build.yaml} +51 -51
  2. package/LICENSE +674 -674
  3. package/README.md +40 -58
  4. package/config-overrides.js +31 -31
  5. package/dist/visualify.js +3 -3
  6. package/docs/CLI.md +15 -0
  7. package/docs/{docs/README.md → README.md} +41 -65
  8. package/docs/{docs/Rechart → Rechart}/bar.md +190 -190
  9. package/docs/{docs/Rechart → Rechart}/funnel.md +193 -241
  10. package/docs/{docs/Rechart → Rechart}/line.md +355 -355
  11. package/docs/{docs/Rechart → Rechart}/pie.md +225 -225
  12. package/docs/{docs/Rechart → Rechart}/radar.md +253 -253
  13. package/docs/{docs/_404.md → _404.md} +51 -51
  14. package/docs/{docs/_coverpage.md → _coverpage.md} +11 -11
  15. package/docs/{docs/_sidebar.md → _sidebar.md} +42 -44
  16. package/docs/{docs/components → components}/dotBio.md +34 -34
  17. package/docs/{docs/components → components}/echart.md +82 -82
  18. package/docs/{docs/components → components}/html.md +34 -34
  19. package/docs/{docs/components → components}/macaron.md +145 -145
  20. package/docs/components/markdown.md +0 -0
  21. package/docs/{docs/components → components}/more.md +142 -142
  22. package/docs/{docs/components → components}/plotly.md +62 -62
  23. package/docs/{docs/components → components}/scatterL.md +70 -70
  24. package/docs/{docs/components → components}/visium.md +56 -56
  25. package/docs/{docs/configuration.md → configuration.md} +123 -121
  26. package/docs/{docs/deploy.md → deploy.md} +23 -31
  27. package/docs/index.html +70 -70
  28. package/docs/log.md +1 -0
  29. package/docs/manifest.json +23 -23
  30. package/docs/{docs/more-pages.md → more-pages.md} +23 -23
  31. package/docs/{docs/quickstart.md → quickstart.md} +115 -124
  32. package/docs/{docs/rechart-attributes.md → rechart-attributes.md} +74 -74
  33. package/docs/{docs/rechart-basic-usage.md → rechart-basic-usage.md} +162 -162
  34. package/docs/static/css/fluff-stuff.css +169 -169
  35. package/docs/static/css/font-awesome.min.css +4 -4
  36. package/docs/static/css/visualify.css +25 -25
  37. package/docs/static/js/configuration.js +448 -448
  38. package/docs/static/js/visualify.js +24 -23
  39. package/docs/theme.md +3 -0
  40. package/package.json +74 -83
  41. package/rollup.config.mjs +75 -75
  42. package/src/_css/404.css +115 -115
  43. package/src/_css/App.css +37 -37
  44. package/src/_css/autoSuggestion.css +26 -26
  45. package/src/_css/circular-progress.css +32 -32
  46. package/src/_css/index.css +36 -36
  47. package/src/_css/modern.css +24 -24
  48. package/src/_media/corner.svg +8 -8
  49. package/src/_media/download.svg +3 -3
  50. package/src/_media/logo.svg +14 -14
  51. package/src/_test/App.test.js +15 -15
  52. package/src/_utils/reportWebVitals.js +13 -13
  53. package/src/core/appContext.js +27 -27
  54. package/src/core/components/Scatter.js +188 -188
  55. package/src/core/components/ScatterBio.js +572 -572
  56. package/src/core/components/VisiumPlot.js +165 -165
  57. package/src/core/components/browser.js +42 -42
  58. package/src/core/components/dotplot.js +413 -413
  59. package/src/core/components/html.js +29 -29
  60. package/src/core/components/list.js +178 -178
  61. package/src/core/components/macaron.js +201 -201
  62. package/src/core/components/markdown.js +56 -56
  63. package/src/core/components/parser.scatterBio.js +579 -587
  64. package/src/core/components/ratio.js +80 -80
  65. package/src/core/components/scatterL.js +173 -173
  66. package/src/core/components/searchbar.js +131 -131
  67. package/src/core/components/selection.js +193 -193
  68. package/src/core/components/timeline.js +281 -281
  69. package/src/core/components/visium.js +97 -97
  70. package/src/core/fetch/condfetch.js +82 -82
  71. package/src/core/fetch/fetch.js +92 -92
  72. package/src/core/fetch/json.js +29 -29
  73. package/src/core/fetch/vfetch.js +42 -42
  74. package/src/core/liveEditor.js +44 -44
  75. package/src/core/modules/codeEditorWithPreview.js +104 -104
  76. package/src/core/modules/echarts/common.js +20 -20
  77. package/src/core/modules/echarts/presetHandler.js +41 -41
  78. package/src/core/modules/echarts/presets/esodev.chromium.js +172 -172
  79. package/src/core/modules/echarts/presets/esodev.codex.js +130 -130
  80. package/src/core/modules/echarts/presets/esodev.visium.js +123 -123
  81. package/src/core/modules/echarts/presets/mmtrbc.js +186 -186
  82. package/src/core/modules/echarts.js +71 -71
  83. package/src/core/modules/echartsUtils.js +43 -43
  84. package/src/core/modules/echartswitcher.js +152 -152
  85. package/src/core/modules/replotly/presetHandler.js +24 -24
  86. package/src/core/modules/replotly/presets/minimum.js +18 -18
  87. package/src/core/modules/replotly/presets/mmtrbc.dot.js +114 -114
  88. package/src/core/modules/replotly/presets/mmtrbc.violin.js +100 -100
  89. package/src/core/modules/replotly.js +71 -71
  90. package/src/core/pages/404.js +50 -50
  91. package/src/core/pages/error.js +27 -27
  92. package/src/core/pages/jsonPage.js +62 -62
  93. package/src/core/pages/loading.js +44 -44
  94. package/src/core/parser/echart.data.js +183 -183
  95. package/src/core/parser/echart.features.js +125 -125
  96. package/src/core/parser/echart.general.js +143 -147
  97. package/src/core/parser/echart.hilbert.js +57 -57
  98. package/src/core/parser/echart.parser.js +210 -210
  99. package/src/core/parser/echart.series.js +67 -67
  100. package/src/core/parser/echart.types.js +76 -76
  101. package/src/core/parser/plotly.config.js +10 -10
  102. package/src/core/parser/plotly.data.js +132 -132
  103. package/src/core/parser/plotly.layout.js +9 -9
  104. package/src/core/parser/plotly.violin.js +18 -18
  105. package/src/core/recharts.js +62 -62
  106. package/src/core/router/alias.js +49 -49
  107. package/src/core/router/jsonRouter.js +31 -31
  108. package/src/core/themes/modern.js +32 -32
  109. package/src/core/themes/themeSelector.js +33 -33
  110. package/src/core/visualify.js +47 -47
  111. package/src/core/widgets/circularProgress.js +23 -23
  112. package/src/core/widgets/controller.js +83 -83
  113. package/src/core/widgets/errorBoundary.js +36 -36
  114. package/src/core/widgets/footer.js +177 -177
  115. package/src/core/widgets/header.js +234 -234
  116. package/src/core/widgets/layout/Grid.js +31 -31
  117. package/src/core/widgets/layout.js +36 -36
  118. package/src/core/widgets/mapping.js +42 -42
  119. package/src/index.js +62 -62
  120. package/src/setupTests.js +5 -5
  121. package/docs/docs/CLI.md +0 -34
  122. package/docs/docs/Rechart/scatter.md +0 -298
  123. package/docs/docs/log.md +0 -9
  124. package/docs/docs/static/logo/favicon.ico +0 -0
  125. package/docs/docs/static/logo/logo_128x128.png +0 -0
  126. package/docs/docs/static/logo/logo_192x192.png +0 -0
  127. package/docs/docs/static/logo/logo_256x256.png +0 -0
  128. package/docs/docs/static/logo/logo_512x512.png +0 -0
  129. package/docs/docs/static/logo/logo_64x64.png +0 -0
  130. package/docs/docs/theme.md +0 -5
  131. /package/docs/{docs/Rechart → Rechart}/geo.md +0 -0
  132. /package/docs/{docs/Rechart → Rechart}/liquidfill.md +0 -0
  133. /package/docs/{docs/Rechart → Rechart}/polar.md +0 -0
  134. /package/docs/{docs/Rechart → Rechart}/sankey.md +0 -0
  135. /package/docs/{docs/Rechart/sunburst.md → Rechart/scatter.md} +0 -0
  136. /package/docs/{docs/Rechart/tree.md → Rechart/sunburst.md} +0 -0
  137. /package/docs/{docs/Rechart/wordcloud.md → Rechart/tree.md} +0 -0
  138. /package/docs/{docs/components/markdown.md → Rechart/wordcloud.md} +0 -0
  139. /package/docs/{docs/static → static}/_images/deploy-github-pages.png +0 -0
@@ -1,97 +1,97 @@
1
- /*
2
- * @Author : Lihao leolihao@arizona.edu
3
- * @Date : 2024-01-08 16:34:20
4
- * @FilePath : /visualifyjs/src/core/components/Visium.js
5
- * @Description :
6
- * Copyright (c) 2024 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
- */
8
- import React, { useEffect, useState } from 'react';
9
- import { useAppContext } from '../appContext';
10
- import conditionalFetch from '../fetch/condfetch';
11
- import EChartSwitcher from '../modules/echartswitcher';
12
- import Loading from '../pages/loading';
13
- import { isEmpty } from 'lodash';
14
-
15
- const Visium = ({ props, style }) => {
16
- const [loading, setLoading] = useState({
17
- active: true,
18
- message: 'Please Select the Section',
19
- });
20
- const { sharedData } = useAppContext();
21
- const [Options, setOptions] = useState(props);
22
-
23
- useEffect(() => {
24
- const { cellfrac, metadata, gene, image } = props.settings;
25
- if (!metadata || !gene || !image)
26
- throw new Error('missing metadata, gene, or image');
27
- let trigger = {
28
- metadata: metadata.trigger,
29
- gene: gene.trigger,
30
- image: image.trigger,
31
- };
32
-
33
- const updatePlot = async () => {
34
- try {
35
- const cellval = isEmpty(sharedData[cellfrac])
36
- ? 'All'
37
- : sharedData[cellfrac][0];
38
-
39
- if (sharedData?.[trigger.image]) {
40
- console.log('image trigger', sharedData?.[trigger.image]);
41
- const imageBuffer = await conditionalFetch(
42
- image,
43
- sharedData,
44
- {},
45
- );
46
-
47
- const blob = new Blob([new Uint8Array(imageBuffer.data)], {
48
- type: 'image/png',
49
- });
50
- const dataURL = URL.createObjectURL(blob);
51
-
52
- console.log('image', dataURL);
53
- setOptions((prev) => ({
54
- ...prev,
55
- config: {
56
- ...prev.config,
57
- overrides: {
58
- ...prev.config.overrides,
59
- backgroundColor: {
60
- image: dataURL,
61
- },
62
- },
63
- },
64
- }));
65
- }
66
-
67
- console.log('update plot', cellval, trigger);
68
- } catch (e) {
69
- setLoading({ active: true, message: e.message });
70
- }
71
- };
72
-
73
- updatePlot();
74
- }, [props, sharedData]);
75
-
76
- return (
77
- <div
78
- id={props.id}
79
- style={{ ...style, position: 'relative' }}>
80
- {loading.active && (
81
- <Loading
82
- message={loading.message}
83
- style={loading.style}
84
- />
85
- )}
86
- <EChartSwitcher
87
- props={Options}
88
- style={{
89
- opacity: loading.active ? 0 : 1,
90
- ...style,
91
- }}
92
- />
93
- </div>
94
- );
95
- };
96
-
97
- export default Visium;
1
+ /*
2
+ * @Author : Lihao leolihao@arizona.edu
3
+ * @Date : 2024-01-08 16:34:20
4
+ * @FilePath : /visualifyjs/src/core/components/Visium.js
5
+ * @Description :
6
+ * Copyright (c) 2024 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
+ */
8
+ import React, { useEffect, useState } from 'react';
9
+ import { useAppContext } from '../appContext';
10
+ import conditionalFetch from '../fetch/condfetch';
11
+ import EChartSwitcher from '../modules/echartswitcher';
12
+ import Loading from '../pages/loading';
13
+ import { isEmpty } from 'lodash';
14
+
15
+ const Visium = ({ props, style }) => {
16
+ const [loading, setLoading] = useState({
17
+ active: true,
18
+ message: 'Please Select the Section',
19
+ });
20
+ const { sharedData } = useAppContext();
21
+ const [Options, setOptions] = useState(props);
22
+
23
+ useEffect(() => {
24
+ const { cellfrac, metadata, gene, image } = props.settings;
25
+ if (!metadata || !gene || !image)
26
+ throw new Error('missing metadata, gene, or image');
27
+ let trigger = {
28
+ metadata: metadata.trigger,
29
+ gene: gene.trigger,
30
+ image: image.trigger,
31
+ };
32
+
33
+ const updatePlot = async () => {
34
+ try {
35
+ const cellval = isEmpty(sharedData[cellfrac])
36
+ ? 'All'
37
+ : sharedData[cellfrac][0];
38
+
39
+ if (sharedData?.[trigger.image]) {
40
+ console.log('image trigger', sharedData?.[trigger.image]);
41
+ const imageBuffer = await conditionalFetch(
42
+ image,
43
+ sharedData,
44
+ {},
45
+ );
46
+
47
+ const blob = new Blob([new Uint8Array(imageBuffer.data)], {
48
+ type: 'image/png',
49
+ });
50
+ const dataURL = URL.createObjectURL(blob);
51
+
52
+ console.log('image', dataURL);
53
+ setOptions((prev) => ({
54
+ ...prev,
55
+ config: {
56
+ ...prev.config,
57
+ overrides: {
58
+ ...prev.config.overrides,
59
+ backgroundColor: {
60
+ image: dataURL,
61
+ },
62
+ },
63
+ },
64
+ }));
65
+ }
66
+
67
+ console.log('update plot', cellval, trigger);
68
+ } catch (e) {
69
+ setLoading({ active: true, message: e.message });
70
+ }
71
+ };
72
+
73
+ updatePlot();
74
+ }, [props, sharedData]);
75
+
76
+ return (
77
+ <div
78
+ id={props.id}
79
+ style={{ ...style, position: 'relative' }}>
80
+ {loading.active && (
81
+ <Loading
82
+ message={loading.message}
83
+ style={loading.style}
84
+ />
85
+ )}
86
+ <EChartSwitcher
87
+ props={Options}
88
+ style={{
89
+ opacity: loading.active ? 0 : 1,
90
+ ...style,
91
+ }}
92
+ />
93
+ </div>
94
+ );
95
+ };
96
+
97
+ export default Visium;
@@ -1,82 +1,82 @@
1
- /*
2
- * @Author : Lihao leolihao@arizona.edu
3
- * @Date : 2023-12-27 17:34:06
4
- * @FilePath : /visualifyjs/src/core/fetch/condfetch.js
5
- * @Description :
6
- * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
- */
8
- import fetchApi from './vfetch';
9
- import { isEmpty } from 'lodash';
10
-
11
- const conditionalFetch = async (
12
- source,
13
- sharedData,
14
- title,
15
- visualify = {},
16
- body = null,
17
- ) => {
18
- const {
19
- name,
20
- method = 'GET',
21
- url,
22
- responseKey,
23
- mapping: api_mapping = visualify?.api_mapping ?? {},
24
- trigger,
25
- } = source;
26
-
27
- if (!name) throw new Error('name is required for api sources');
28
- if (!url) throw new Error('url is required for api sources');
29
-
30
- if (Array.isArray(trigger)) {
31
- // Handle complex trigger configurations
32
- const triggerValues = trigger.map((triggerItem) => {
33
- const triggerValue =
34
- sharedData[triggerItem.name] || sharedData[triggerItem];
35
- if (triggerItem.title && title) title.text = triggerValue;
36
-
37
- return triggerValue !== undefined &&
38
- triggerValue !== null &&
39
- triggerValue !== '' &&
40
- !isEmpty(triggerValue)
41
- ? api_mapping?.[triggerValue] || triggerValue
42
- : null;
43
- });
44
-
45
- if (triggerValues.some((val) => val === null)) {
46
- // If any trigger value is not available, skip this source
47
- return null;
48
- }
49
-
50
- // Replace multiple {trigger} placeholders in the URL with trigger values
51
- let finalUrl = url;
52
- triggerValues.forEach((triggerValue) => {
53
- finalUrl = finalUrl.replace('{trigger}', triggerValue);
54
- });
55
-
56
- const response = await fetchApi(finalUrl, method, body, {}, true);
57
-
58
- return responseKey ? response[responseKey] : response;
59
- } else if (trigger) {
60
- // Handle simple string trigger
61
- const triggerValue = sharedData[trigger.name] || sharedData[trigger];
62
-
63
- if (
64
- triggerValue !== undefined &&
65
- triggerValue !== null &&
66
- triggerValue !== '' &&
67
- !isEmpty(triggerValue)
68
- ) {
69
- if (trigger.title && title) title.text = triggerValue;
70
- const triggerVal = api_mapping?.[triggerValue] || triggerValue;
71
- const finalUrl = url.replace('{trigger}', triggerVal);
72
-
73
- const response = await fetchApi(finalUrl, method, null, {}, true);
74
- return responseKey ? response[responseKey] : response;
75
- }
76
- } else {
77
- const response = await fetchApi(url, method, null, {}, true);
78
- return responseKey ? response[responseKey] : response;
79
- }
80
- };
81
-
82
- export default conditionalFetch;
1
+ /*
2
+ * @Author : Lihao leolihao@arizona.edu
3
+ * @Date : 2023-12-27 17:34:06
4
+ * @FilePath : /visualifyjs/src/core/fetch/condfetch.js
5
+ * @Description :
6
+ * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
+ */
8
+ import fetchApi from './vfetch';
9
+ import { isEmpty } from 'lodash';
10
+
11
+ const conditionalFetch = async (
12
+ source,
13
+ sharedData,
14
+ title,
15
+ visualify = {},
16
+ body = null,
17
+ ) => {
18
+ const {
19
+ name,
20
+ method = 'GET',
21
+ url,
22
+ responseKey,
23
+ mapping: api_mapping = visualify?.api_mapping ?? {},
24
+ trigger,
25
+ } = source;
26
+
27
+ if (!name) throw new Error('name is required for api sources');
28
+ if (!url) throw new Error('url is required for api sources');
29
+
30
+ if (Array.isArray(trigger)) {
31
+ // Handle complex trigger configurations
32
+ const triggerValues = trigger.map((triggerItem) => {
33
+ const triggerValue =
34
+ sharedData[triggerItem.name] || sharedData[triggerItem];
35
+ if (triggerItem.title && title) title.text = triggerValue;
36
+
37
+ return triggerValue !== undefined &&
38
+ triggerValue !== null &&
39
+ triggerValue !== '' &&
40
+ !isEmpty(triggerValue)
41
+ ? api_mapping?.[triggerValue] || triggerValue
42
+ : null;
43
+ });
44
+
45
+ if (triggerValues.some((val) => val === null)) {
46
+ // If any trigger value is not available, skip this source
47
+ return null;
48
+ }
49
+
50
+ // Replace multiple {trigger} placeholders in the URL with trigger values
51
+ let finalUrl = url;
52
+ triggerValues.forEach((triggerValue) => {
53
+ finalUrl = finalUrl.replace('{trigger}', triggerValue);
54
+ });
55
+
56
+ const response = await fetchApi(finalUrl, method, body, {}, true);
57
+
58
+ return responseKey ? response[responseKey] : response;
59
+ } else if (trigger) {
60
+ // Handle simple string trigger
61
+ const triggerValue = sharedData[trigger.name] || sharedData[trigger];
62
+
63
+ if (
64
+ triggerValue !== undefined &&
65
+ triggerValue !== null &&
66
+ triggerValue !== '' &&
67
+ !isEmpty(triggerValue)
68
+ ) {
69
+ if (trigger.title && title) title.text = triggerValue;
70
+ const triggerVal = api_mapping?.[triggerValue] || triggerValue;
71
+ const finalUrl = url.replace('{trigger}', triggerVal);
72
+
73
+ const response = await fetchApi(finalUrl, method, null, {}, true);
74
+ return responseKey ? response[responseKey] : response;
75
+ }
76
+ } else {
77
+ const response = await fetchApi(url, method, null, {}, true);
78
+ return responseKey ? response[responseKey] : response;
79
+ }
80
+ };
81
+
82
+ export default conditionalFetch;
@@ -1,92 +1,92 @@
1
- /*
2
- * @Author : Lihao leolihao@arizona.edu
3
- * @Date : 2023-09-22 21:19:16
4
- * @FilePath : /visualifyjs/src/core/fetch/fetch.js
5
- * @Description :
6
- * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
- */
8
-
9
- const MAX_CACHE_SIZE = 512 * 1024 * 1024; // 512MB
10
-
11
- const cache = {};
12
- const lruOrder = [];
13
-
14
- // Function to manage the cache size and eviction
15
- const manageCache = (cacheKey, data) => {
16
- // Add the cacheKey to the LRU order
17
- lruOrder.push(cacheKey);
18
-
19
- // Check if the cache size exceeds the maximum limit
20
- let currentCacheSize = 0;
21
- for (const key of lruOrder) {
22
- if (cache[key]) {
23
- currentCacheSize += JSON.stringify(cache[key]).length;
24
- }
25
- if (currentCacheSize > MAX_CACHE_SIZE) {
26
- // Remove the least recently used item from the cache and the LRU order
27
- const lruKey = lruOrder.shift();
28
- delete cache[lruKey];
29
- }
30
- }
31
-
32
- // Cache the data
33
- cache[cacheKey] = data;
34
- };
35
-
36
- const simplefetch = async (url, options = {}) => {
37
- const { id = undefined, type, key, debug = false, bbox = {} } = options;
38
- const hasBbox = Object.keys(bbox).length > 0;
39
- const cacheKey = hasBbox ? `${id}_${JSON.stringify(bbox)}` : `${id}_nobbox`;
40
-
41
- if (cache[cacheKey]) {
42
- if (debug) console.warn('simplefetch: cache hit ', cacheKey);
43
- return cache[cacheKey];
44
- }
45
-
46
- if (typeof url === 'object') {
47
- if (id && id !== '') return url[id] ?? {};
48
- else return url;
49
- } else if (typeof url === 'string') {
50
- let result = {};
51
- if (type && type === 'gene' && (id === '' || id === undefined))
52
- return {};
53
- if (type && (type === 'gene' || type === 'metadata') && id && id !== '')
54
- url += (url.charAt(url.length - 1) === '/' ? '' : '/') + id;
55
- if (type && type === 'metadata' && id && id !== '' && hasBbox) {
56
- const { xMin, yMin, xMax, yMax } = bbox;
57
- url += `/${xMin}/${yMin}/${xMax}/${yMax}`;
58
- //console.log('simplefetch: url', url);
59
- }
60
-
61
- //console.log("simplefetch: fetch url", url);
62
- const res = await fetch(url, debug ? { mode: 'cors' } : {}); // using await here
63
- //console.log("simplefetch: fetch res", res);
64
-
65
- if (res.ok) {
66
- const data = await res.json(); // using await here
67
- if (data.code === 200) {
68
- if (key) {
69
- result = data[key];
70
- } else if (type === 'metadata') result = data.metadata;
71
- else if (type === 'gene') result = data.gene;
72
- else if (type === 'image') result = data.image;
73
- else result = data;
74
-
75
- // When caching data, use the manageCache function
76
- if (id && !cache[cacheKey]) {
77
- manageCache(cacheKey, result);
78
- }
79
-
80
- if (debug) console.log('simplefetch: fetch success', result);
81
- } else console.error('simplefetch: fetch failed', data.code, data.msg);
82
- } else console.error('simplefetch: fetch error', res);
83
-
84
- //console.log("simplefetch: after fetch", result);
85
- return result;
86
- } else {
87
- console.error('Unsupported type or Invalid url:', url);
88
- return {};
89
- }
90
- };
91
-
92
- export default simplefetch;
1
+ /*
2
+ * @Author : Lihao leolihao@arizona.edu
3
+ * @Date : 2023-09-22 21:19:16
4
+ * @FilePath : /visualifyjs/src/core/fetch/fetch.js
5
+ * @Description :
6
+ * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
+ */
8
+
9
+ const MAX_CACHE_SIZE = 512 * 1024 * 1024; // 512MB
10
+
11
+ const cache = {};
12
+ const lruOrder = [];
13
+
14
+ // Function to manage the cache size and eviction
15
+ const manageCache = (cacheKey, data) => {
16
+ // Add the cacheKey to the LRU order
17
+ lruOrder.push(cacheKey);
18
+
19
+ // Check if the cache size exceeds the maximum limit
20
+ let currentCacheSize = 0;
21
+ for (const key of lruOrder) {
22
+ if (cache[key]) {
23
+ currentCacheSize += JSON.stringify(cache[key]).length;
24
+ }
25
+ if (currentCacheSize > MAX_CACHE_SIZE) {
26
+ // Remove the least recently used item from the cache and the LRU order
27
+ const lruKey = lruOrder.shift();
28
+ delete cache[lruKey];
29
+ }
30
+ }
31
+
32
+ // Cache the data
33
+ cache[cacheKey] = data;
34
+ };
35
+
36
+ const simplefetch = async (url, options = {}) => {
37
+ const { id = undefined, type, key, debug = false, bbox = {} } = options;
38
+ const hasBbox = Object.keys(bbox).length > 0;
39
+ const cacheKey = hasBbox ? `${id}_${JSON.stringify(bbox)}` : `${id}_nobbox`;
40
+
41
+ if (cache[cacheKey]) {
42
+ if (debug) console.warn('simplefetch: cache hit ', cacheKey);
43
+ return cache[cacheKey];
44
+ }
45
+
46
+ if (typeof url === 'object') {
47
+ if (id && id !== '') return url[id] ?? {};
48
+ else return url;
49
+ } else if (typeof url === 'string') {
50
+ let result = {};
51
+ if (type && type === 'gene' && (id === '' || id === undefined))
52
+ return {};
53
+ if (type && (type === 'gene' || type === 'metadata') && id && id !== '')
54
+ url += (url.charAt(url.length - 1) === '/' ? '' : '/') + id;
55
+ if (type && type === 'metadata' && id && id !== '' && hasBbox) {
56
+ const { xMin, yMin, xMax, yMax } = bbox;
57
+ url += `/${xMin}/${yMin}/${xMax}/${yMax}`;
58
+ //console.log('simplefetch: url', url);
59
+ }
60
+
61
+ //console.log("simplefetch: fetch url", url);
62
+ const res = await fetch(url, debug ? { mode: 'cors' } : {}); // using await here
63
+ //console.log("simplefetch: fetch res", res);
64
+
65
+ if (res.ok) {
66
+ const data = await res.json(); // using await here
67
+ if (data.code === 200) {
68
+ if (key) {
69
+ result = data[key];
70
+ } else if (type === 'metadata') result = data.metadata;
71
+ else if (type === 'gene') result = data.gene;
72
+ else if (type === 'image') result = data.image;
73
+ else result = data;
74
+
75
+ // When caching data, use the manageCache function
76
+ if (id && !cache[cacheKey]) {
77
+ manageCache(cacheKey, result);
78
+ }
79
+
80
+ if (debug) console.log('simplefetch: fetch success', result);
81
+ } else console.error('simplefetch: fetch failed', data.code, data.msg);
82
+ } else console.error('simplefetch: fetch error', res);
83
+
84
+ //console.log("simplefetch: after fetch", result);
85
+ return result;
86
+ } else {
87
+ console.error('Unsupported type or Invalid url:', url);
88
+ return {};
89
+ }
90
+ };
91
+
92
+ export default simplefetch;
@@ -1,29 +1,29 @@
1
- /*
2
- * @Author : Lihao leolihao@arizona.edu
3
- * @Date : 2023-12-01 12:28:29
4
- * @FilePath : /visualifyjs/src/core/fetch/json.js
5
- * @Description :
6
- * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
- */
8
- function fetchJson(jsonFileName, externalURL) {
9
- let jsonUrl;
10
- if (externalURL) {
11
- jsonUrl = externalURL;
12
- } else {
13
- jsonUrl = `./${jsonFileName}.json`;
14
- }
15
-
16
- return fetch(jsonUrl).then((response) => {
17
- if (!response.ok) {
18
- throw new Error(`Failed to fetch JSON for ${jsonFileName}`);
19
- }
20
- if (
21
- !response.headers.get('content-type')?.includes('application/json')
22
- ) {
23
- throw new TypeError('Response not in JSON format');
24
- }
25
- return response.json();
26
- });
27
- }
28
-
29
- export default fetchJson;
1
+ /*
2
+ * @Author : Lihao leolihao@arizona.edu
3
+ * @Date : 2023-12-01 12:28:29
4
+ * @FilePath : /visualifyjs/src/core/fetch/json.js
5
+ * @Description :
6
+ * Copyright (c) 2023 by Lihao (leolihao@arizona.edu), All Rights Reserved.
7
+ */
8
+ function fetchJson(jsonFileName, externalURL) {
9
+ let jsonUrl;
10
+ if (externalURL) {
11
+ jsonUrl = externalURL;
12
+ } else {
13
+ jsonUrl = `./${jsonFileName}.json`;
14
+ }
15
+
16
+ return fetch(jsonUrl).then((response) => {
17
+ if (!response.ok) {
18
+ throw new Error(`Failed to fetch JSON for ${jsonFileName}`);
19
+ }
20
+ if (
21
+ !response.headers.get('content-type')?.includes('application/json')
22
+ ) {
23
+ throw new TypeError('Response not in JSON format');
24
+ }
25
+ return response.json();
26
+ });
27
+ }
28
+
29
+ export default fetchJson;