@haniffalab/cherita-react 0.2.1-dev.2025-02-25.bc0e99e8 → 0.2.1-dev.2025-03-06.b4baf3a1
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.
- package/dist/components/full-page/FullPage.js +15 -15
- package/dist/components/full-page/FullPagePseudospatial.js +19 -43
- package/dist/components/offcanvas/index.js +3 -2
- package/dist/components/pseudospatial/Pseudospatial.js +9 -4
- package/dist/components/pseudospatial/PseudospatialToolbar.js +0 -17
- package/dist/components/scatterplot/Scatterplot.js +1 -1
- package/dist/context/DatasetContext.js +11 -6
- package/dist/helpers/map-helper.js +21 -16
- package/dist/helpers/zarr-helper.js +63 -57
- package/dist/utils/requests.js +2 -2
- package/dist/utils/zarrData.js +12 -4
- package/package.json +11 -11
- package/dist/components/pseudospatial/PseudospatialControls.js +0 -11
|
@@ -28,46 +28,46 @@ function FullPage({
|
|
|
28
28
|
varMode = _constants.SELECTION_MODES.SINGLE,
|
|
29
29
|
...props
|
|
30
30
|
}) {
|
|
31
|
-
const
|
|
31
|
+
const appRef = (0, _react.useRef)();
|
|
32
|
+
const [appDimensions, setAppDimensions] = (0, _react.useState)({
|
|
33
|
+
width: 0,
|
|
34
|
+
height: 0
|
|
35
|
+
});
|
|
32
36
|
const [showObs, setShowObs] = (0, _react.useState)(false);
|
|
33
37
|
const [showObsm, setShowObsm] = (0, _react.useState)(false);
|
|
34
38
|
const [showVars, setShowVars] = (0, _react.useState)(false);
|
|
35
39
|
const [showControls, setShowControls] = (0, _react.useState)(false);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
});
|
|
40
|
-
(0, _react.useLayoutEffect)(() => {
|
|
41
|
-
function updateDimensions() {
|
|
42
|
-
if (targetRef.current) {
|
|
40
|
+
(0, _react.useEffect)(() => {
|
|
41
|
+
const updateDimensions = () => {
|
|
42
|
+
if (appRef.current) {
|
|
43
43
|
// Get the distance from the top of the page to the target element
|
|
44
|
-
const rect =
|
|
44
|
+
const rect = appRef.current.getBoundingClientRect();
|
|
45
45
|
const distanceFromTop = rect.top + window.scrollY;
|
|
46
46
|
|
|
47
47
|
// Calculate the available height for the Cherita app
|
|
48
48
|
const availableHeight = window.innerHeight - distanceFromTop;
|
|
49
49
|
|
|
50
50
|
// Update the dimensions to fit the viewport minus the navbar height
|
|
51
|
-
|
|
52
|
-
width:
|
|
51
|
+
setAppDimensions({
|
|
52
|
+
width: appRef.current.offsetWidth,
|
|
53
53
|
height: availableHeight
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
|
-
}
|
|
56
|
+
};
|
|
57
57
|
window.addEventListener("resize", updateDimensions);
|
|
58
58
|
updateDimensions(); // Initial update
|
|
59
59
|
return () => window.removeEventListener("resize", updateDimensions);
|
|
60
60
|
}, []);
|
|
61
61
|
return /*#__PURE__*/_react.default.createElement("div", {
|
|
62
|
-
ref:
|
|
62
|
+
ref: appRef,
|
|
63
63
|
className: "cherita-app",
|
|
64
64
|
style: {
|
|
65
|
-
height:
|
|
65
|
+
height: appDimensions.height
|
|
66
66
|
}
|
|
67
67
|
}, /*#__PURE__*/_react.default.createElement(_DatasetContext.DatasetProvider, props, /*#__PURE__*/_react.default.createElement("div", {
|
|
68
68
|
className: "row g-0"
|
|
69
69
|
}, /*#__PURE__*/_react.default.createElement("div", {
|
|
70
|
-
className: "cherita-app-obs"
|
|
70
|
+
className: "cherita-app-obs modern-scrollbars border-end h-100"
|
|
71
71
|
}, /*#__PURE__*/_react.default.createElement(_ObsList.ObsColsList, null)), /*#__PURE__*/_react.default.createElement("div", {
|
|
72
72
|
className: "cherita-app-plot"
|
|
73
73
|
}, /*#__PURE__*/_react.default.createElement("div", {
|
|
@@ -37,8 +37,9 @@ function FullPage({
|
|
|
37
37
|
const [showControls, setShowControls] = (0, _react.useState)(false);
|
|
38
38
|
const [showPseudospatialControls, setShowPseudospatialControls] = (0, _react.useState)(false);
|
|
39
39
|
const [showModal, setShowModal] = (0, _react.useState)(false);
|
|
40
|
-
(0, _react.
|
|
41
|
-
|
|
40
|
+
const [pseudospatialPlotType, setpseudospatialPlotType] = (0, _react.useState)(null);
|
|
41
|
+
(0, _react.useEffect)(() => {
|
|
42
|
+
const updateDimensions = () => {
|
|
42
43
|
if (appRef.current) {
|
|
43
44
|
// Get the distance from the top of the page to the target element
|
|
44
45
|
const rect = appRef.current.getBoundingClientRect();
|
|
@@ -53,29 +54,11 @@ function FullPage({
|
|
|
53
54
|
height: availableHeight
|
|
54
55
|
});
|
|
55
56
|
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Initial calculation
|
|
59
|
-
updateDimensions();
|
|
60
|
-
|
|
61
|
-
// Event listener for resize
|
|
62
|
-
window.addEventListener("resize", updateDimensions);
|
|
63
|
-
|
|
64
|
-
// Handle dimension recalculation when accordion expands/collapses
|
|
65
|
-
const accordionItems = document.querySelectorAll(".accordion-item");
|
|
66
|
-
accordionItems.forEach(item => {
|
|
67
|
-
item.addEventListener("transitionend", updateDimensions);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
// Clean up event listeners
|
|
71
|
-
return () => {
|
|
72
|
-
window.removeEventListener("resize", updateDimensions);
|
|
73
|
-
accordionItems.forEach(item => {
|
|
74
|
-
item.removeEventListener("transitionend", updateDimensions);
|
|
75
|
-
});
|
|
76
57
|
};
|
|
77
|
-
|
|
78
|
-
|
|
58
|
+
window.addEventListener("resize", updateDimensions);
|
|
59
|
+
updateDimensions(); // Initial update
|
|
60
|
+
return () => window.removeEventListener("resize", updateDimensions);
|
|
61
|
+
}, []);
|
|
79
62
|
return /*#__PURE__*/_react.default.createElement("div", {
|
|
80
63
|
ref: appRef,
|
|
81
64
|
className: "cherita-app",
|
|
@@ -123,29 +106,16 @@ function FullPage({
|
|
|
123
106
|
variant: "link",
|
|
124
107
|
onClick: () => setShowModal(true)
|
|
125
108
|
}, /*#__PURE__*/_react.default.createElement(_reactFontawesome.FontAwesomeIcon, {
|
|
126
|
-
icon: _freeSolidSvgIcons.
|
|
127
|
-
})), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Button, {
|
|
128
|
-
variant: "link",
|
|
129
|
-
onClick: () => setShowModal(true)
|
|
130
|
-
}, /*#__PURE__*/_react.default.createElement(_reactFontawesome.FontAwesomeIcon, {
|
|
131
|
-
icon: _freeSolidSvgIcons.faChartLine
|
|
132
|
-
})), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Button, {
|
|
133
|
-
variant: "link",
|
|
134
|
-
onClick: () => setShowModal(true)
|
|
135
|
-
}, /*#__PURE__*/_react.default.createElement(_reactFontawesome.FontAwesomeIcon, {
|
|
136
|
-
icon: _freeSolidSvgIcons.faChartPie
|
|
137
|
-
})), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Button, {
|
|
138
|
-
variant: "link",
|
|
139
|
-
onClick: () => setShowModal(true)
|
|
140
|
-
}, /*#__PURE__*/_react.default.createElement(_reactFontawesome.FontAwesomeIcon, {
|
|
141
|
-
icon: _freeSolidSvgIcons.faChartArea
|
|
109
|
+
icon: _freeSolidSvgIcons.faArrowUpRightFromSquare
|
|
142
110
|
}))), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Card.Body, {
|
|
143
111
|
className: "d-flex flex-column p-0"
|
|
144
112
|
}, /*#__PURE__*/_react.default.createElement("div", {
|
|
145
113
|
className: "sidebar-pseudospatial"
|
|
146
114
|
}, /*#__PURE__*/_react.default.createElement(_Pseudospatial.Pseudospatial, {
|
|
147
115
|
className: "sidebar-pseudospatial",
|
|
148
|
-
|
|
116
|
+
plotType: pseudospatialPlotType,
|
|
117
|
+
setPlotType: setpseudospatialPlotType,
|
|
118
|
+
setShowControls: setShowPseudospatialControls
|
|
149
119
|
})), /*#__PURE__*/_react.default.createElement("div", {
|
|
150
120
|
className: "sidebar-features modern-scrollbars"
|
|
151
121
|
}, /*#__PURE__*/_react.default.createElement(_SearchBar.SearchBar, {
|
|
@@ -159,7 +129,12 @@ function FullPage({
|
|
|
159
129
|
centered: true
|
|
160
130
|
}, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Modal.Header, {
|
|
161
131
|
closeButton: true
|
|
162
|
-
}
|
|
132
|
+
}), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Modal.Body, null, /*#__PURE__*/_react.default.createElement(_Pseudospatial.Pseudospatial, {
|
|
133
|
+
plotType: pseudospatialPlotType,
|
|
134
|
+
setPlotType: setpseudospatialPlotType,
|
|
135
|
+
setShowControls: setShowPseudospatialControls,
|
|
136
|
+
height: 500
|
|
137
|
+
}))), /*#__PURE__*/_react.default.createElement(_offcanvas.OffcanvasObs, {
|
|
163
138
|
show: showObs,
|
|
164
139
|
handleClose: () => setShowObs(false)
|
|
165
140
|
}), /*#__PURE__*/_react.default.createElement(_offcanvas.OffcanvasVars, {
|
|
@@ -172,7 +147,8 @@ function FullPage({
|
|
|
172
147
|
}), /*#__PURE__*/_react.default.createElement(_offcanvas.OffcanvasControls, {
|
|
173
148
|
show: showPseudospatialControls,
|
|
174
149
|
handleClose: () => setShowPseudospatialControls(false),
|
|
175
|
-
Controls: _PseudospatialToolbar.PseudospatialToolbar
|
|
150
|
+
Controls: _PseudospatialToolbar.PseudospatialToolbar,
|
|
151
|
+
plotType: pseudospatialPlotType
|
|
176
152
|
}), /*#__PURE__*/_react.default.createElement(_offcanvas.OffcanvasObsm, {
|
|
177
153
|
show: showObsm,
|
|
178
154
|
handleClose: () => setShowObsm(false)
|
|
@@ -61,12 +61,13 @@ function OffcanvasVars({
|
|
|
61
61
|
function OffcanvasControls({
|
|
62
62
|
show,
|
|
63
63
|
handleClose,
|
|
64
|
-
Controls
|
|
64
|
+
Controls,
|
|
65
|
+
...props
|
|
65
66
|
}) {
|
|
66
67
|
return /*#__PURE__*/_react.default.createElement(_Offcanvas.default, {
|
|
67
68
|
show: show,
|
|
68
69
|
onHide: handleClose
|
|
69
70
|
}, /*#__PURE__*/_react.default.createElement(_Offcanvas.default.Header, {
|
|
70
71
|
closeButton: true
|
|
71
|
-
}, /*#__PURE__*/_react.default.createElement(_Offcanvas.default.Title, null, "Controls")), /*#__PURE__*/_react.default.createElement(_Offcanvas.default.Body, null, /*#__PURE__*/_react.default.createElement(Controls,
|
|
72
|
+
}, /*#__PURE__*/_react.default.createElement(_Offcanvas.default.Title, null, "Controls")), /*#__PURE__*/_react.default.createElement(_Offcanvas.default.Body, null, /*#__PURE__*/_react.default.createElement(Controls, props)));
|
|
72
73
|
}
|
|
@@ -79,7 +79,10 @@ function usePseudospatialData(plotType) {
|
|
|
79
79
|
function Pseudospatial({
|
|
80
80
|
showLegend = true,
|
|
81
81
|
sharedScaleRange = false,
|
|
82
|
-
|
|
82
|
+
height = 200,
|
|
83
|
+
setShowControls,
|
|
84
|
+
plotType,
|
|
85
|
+
setPlotType
|
|
83
86
|
}) {
|
|
84
87
|
const dataset = (0, _DatasetContext.useDataset)();
|
|
85
88
|
const [data, setData] = (0, _react.useState)([]);
|
|
@@ -88,7 +91,9 @@ function Pseudospatial({
|
|
|
88
91
|
getColor
|
|
89
92
|
} = (0, _colorHelper.useColor)();
|
|
90
93
|
const colorscale = (0, _react.useRef)(dataset.controls.colorScale);
|
|
91
|
-
|
|
94
|
+
(0, _react.useEffect)(() => {
|
|
95
|
+
setPlotType(dataset.colorEncoding === _constants.COLOR_ENCODINGS.VAR ? _constants.PSEUDOSPATIAL_PLOT_TYPES.GENE : dataset.selectedObs?.type === _constants.OBS_TYPES.CATEGORICAL || dataset.selectedObs?.type === _constants.OBS_TYPES.BOOLEAN ? _constants.PSEUDOSPATIAL_PLOT_TYPES.CATEGORICAL : dataset.selectedObs?.type === _constants.OBS_TYPES.CONTINUOUS ? _constants.PSEUDOSPATIAL_PLOT_TYPES.CONTINUOUS : _constants.PSEUDOSPATIAL_PLOT_TYPES.MASKS);
|
|
96
|
+
}, [dataset.colorEncoding, dataset.selectedObs?.type, setPlotType]);
|
|
92
97
|
const updateColorscale = (0, _react.useCallback)(colorscale => {
|
|
93
98
|
setLayout(l => {
|
|
94
99
|
return {
|
|
@@ -187,7 +192,7 @@ function Pseudospatial({
|
|
|
187
192
|
layout: {
|
|
188
193
|
...layout,
|
|
189
194
|
autosize: true,
|
|
190
|
-
height:
|
|
195
|
+
height: height
|
|
191
196
|
},
|
|
192
197
|
useResizeHandler: true,
|
|
193
198
|
className: "cherita-pseudospatial-plot",
|
|
@@ -203,7 +208,7 @@ function Pseudospatial({
|
|
|
203
208
|
ascent: 512,
|
|
204
209
|
descent: 0
|
|
205
210
|
},
|
|
206
|
-
click: () =>
|
|
211
|
+
click: () => setShowControls(prev => !prev)
|
|
207
212
|
}]
|
|
208
213
|
}
|
|
209
214
|
}), hasSelections && showLegend && /*#__PURE__*/_react.default.createElement(_Legend.Legend, {
|
|
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.PseudospatialToolbar = PseudospatialToolbar;
|
|
7
|
-
exports.PseudospatialToolbarLite = PseudospatialToolbarLite;
|
|
8
7
|
var _react = _interopRequireWildcard(require("react"));
|
|
9
8
|
var _freeSolidSvgIcons = require("@fortawesome/free-solid-svg-icons");
|
|
10
9
|
var _reactFontawesome = require("@fortawesome/react-fontawesome");
|
|
@@ -129,20 +128,4 @@ function PseudospatialToolbar({
|
|
|
129
128
|
return /*#__PURE__*/_react.default.createElement("div", {
|
|
130
129
|
className: "cherita-pseudospatial-toolbar"
|
|
131
130
|
}, /*#__PURE__*/_react.default.createElement(_reactBootstrap.ButtonGroup, null, /*#__PURE__*/_react.default.createElement(MaskSet, null)), /*#__PURE__*/_react.default.createElement(_reactBootstrap.ButtonGroup, null, plotType === _constants.PSEUDOSPATIAL_PLOT_TYPES.CATEGORICAL && /*#__PURE__*/_react.default.createElement(CategoricalMode, null)));
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// @TODO: add colormap, colorbar slider
|
|
135
|
-
function PseudospatialToolbarLite({
|
|
136
|
-
plotType
|
|
137
|
-
}) {
|
|
138
|
-
return /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown.Toggle, {
|
|
139
|
-
variant: "success",
|
|
140
|
-
id: "dropdown-basic"
|
|
141
|
-
}, /*#__PURE__*/_react.default.createElement(_reactFontawesome.FontAwesomeIcon, {
|
|
142
|
-
icon: _freeSolidSvgIcons.faChevronDown
|
|
143
|
-
})), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown.Menu, null, /*#__PURE__*/_react.default.createElement(MaskSet, null), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown.Item, {
|
|
144
|
-
href: "#/action-2"
|
|
145
|
-
}, "Another action"), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown.Item, {
|
|
146
|
-
href: "#/action-3"
|
|
147
|
-
}, "Something else")));
|
|
148
131
|
}
|
|
@@ -212,7 +212,7 @@ function Scatterplot({
|
|
|
212
212
|
value: (data.values[index] - min) / (max - min),
|
|
213
213
|
categorical: isCategorical,
|
|
214
214
|
grayOut: grayOut
|
|
215
|
-
});
|
|
215
|
+
}) || [0, 0, 0, 100];
|
|
216
216
|
}, [data.values, obsIndices, getColor, isCategorical, max, min]);
|
|
217
217
|
|
|
218
218
|
// @TODO: add support for pseudospatial hover to reflect in radius
|
|
@@ -23,17 +23,22 @@ const DatasetDispatchContext = exports.DatasetDispatchContext = /*#__PURE__*/(0,
|
|
|
23
23
|
const queryClient = new _reactQuery.QueryClient({
|
|
24
24
|
defaultOptions: {
|
|
25
25
|
queries: {
|
|
26
|
-
gcTime: 1000 * 60 *
|
|
26
|
+
gcTime: 1000 * 60 * 15,
|
|
27
|
+
// garbage collect after 15min of inactive
|
|
28
|
+
staleTime: 1000 * 60 * 60,
|
|
29
|
+
refetchOnMount: false,
|
|
30
|
+
refetchOnReconnect: false,
|
|
31
|
+
refetchOnWindowFocus: false
|
|
27
32
|
}
|
|
28
33
|
},
|
|
29
34
|
queryCache: new _reactQuery.QueryCache({
|
|
30
|
-
onError:
|
|
31
|
-
console.error(error
|
|
35
|
+
onError: error => {
|
|
36
|
+
console.error(error);
|
|
32
37
|
}
|
|
33
38
|
})
|
|
34
39
|
});
|
|
35
40
|
// Type of queries to store responses
|
|
36
|
-
const persistKeys = ["obs/cols", "var/names", "obsm/keys", "
|
|
41
|
+
const persistKeys = ["obs/cols", "var/names", "obsm/keys", "obs/bins", "obs/distribution"];
|
|
37
42
|
const persistOptions = {
|
|
38
43
|
persister: (0, _querySyncStoragePersister.createSyncStoragePersister)({
|
|
39
44
|
storage: window.localStorage
|
|
@@ -129,9 +134,9 @@ function DatasetProvider({
|
|
|
129
134
|
}));
|
|
130
135
|
} catch (err) {
|
|
131
136
|
if (err.code === 22 || err.code === 1014 || err.name === "QuotaExceededError" || err.name === "NS_ERROR_DOM_QUOTA_REACHED") {
|
|
132
|
-
console.
|
|
137
|
+
console.err("Browser storage quota exceeded");
|
|
133
138
|
} else {
|
|
134
|
-
console.
|
|
139
|
+
console.err(err);
|
|
135
140
|
}
|
|
136
141
|
}
|
|
137
142
|
}, [dataset]);
|
|
@@ -5,6 +5,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.MapHelper = void 0;
|
|
7
7
|
var _core = require("@deck.gl/core");
|
|
8
|
+
var _lodash = _interopRequireDefault(require("lodash"));
|
|
9
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
10
|
class MapHelper {
|
|
9
11
|
fitBounds(coords, {
|
|
10
12
|
width = 400,
|
|
@@ -20,18 +22,21 @@ class MapHelper {
|
|
|
20
22
|
latitude: 0,
|
|
21
23
|
zoom: 12
|
|
22
24
|
});
|
|
23
|
-
let latMin
|
|
24
|
-
let latMax
|
|
25
|
-
let lonMin
|
|
26
|
-
let lonMax
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
25
|
+
let latMin;
|
|
26
|
+
let latMax;
|
|
27
|
+
let lonMin;
|
|
28
|
+
let lonMax;
|
|
29
|
+
if (coords) {
|
|
30
|
+
latMin = _lodash.default.minBy(coords, c => c[1])[1];
|
|
31
|
+
latMax = _lodash.default.maxBy(coords, c => c[1])[1];
|
|
32
|
+
lonMin = _lodash.default.minBy(coords, c => c[0])[0];
|
|
33
|
+
lonMax = _lodash.default.maxBy(coords, c => c[0])[0];
|
|
34
|
+
} else {
|
|
35
|
+
latMin = 0;
|
|
36
|
+
latMax = 1;
|
|
37
|
+
lonMin = 0;
|
|
38
|
+
lonMax = 1;
|
|
39
|
+
}
|
|
35
40
|
const bounds = [[lonMin, latMin], [lonMax, latMax]];
|
|
36
41
|
const {
|
|
37
42
|
longitude,
|
|
@@ -39,10 +44,10 @@ class MapHelper {
|
|
|
39
44
|
zoom
|
|
40
45
|
} = view.fitBounds(bounds, {
|
|
41
46
|
padding: {
|
|
42
|
-
top:
|
|
43
|
-
bottom:
|
|
44
|
-
left:
|
|
45
|
-
right:
|
|
47
|
+
top: height * 0.05,
|
|
48
|
+
bottom: height * 0.075,
|
|
49
|
+
left: width * 0.05,
|
|
50
|
+
right: width * 0.05
|
|
46
51
|
}
|
|
47
52
|
});
|
|
48
53
|
return {
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.useZarr = exports.useMultipleZarr = exports.ZarrHelper = exports.GET_OPTIONS = void 0;
|
|
7
7
|
var _react = require("react");
|
|
8
|
+
var _reactQuery = require("@tanstack/react-query");
|
|
8
9
|
var _zarr = require("zarr");
|
|
9
10
|
const GET_OPTIONS = exports.GET_OPTIONS = {
|
|
10
11
|
concurrencyLimit: 10,
|
|
@@ -13,7 +14,7 @@ const GET_OPTIONS = exports.GET_OPTIONS = {
|
|
|
13
14
|
progress,
|
|
14
15
|
queueSize
|
|
15
16
|
}) => {
|
|
16
|
-
console.
|
|
17
|
+
console.debug(`${progress / queueSize * 100}% complete.`);
|
|
17
18
|
} // callback executed after each request
|
|
18
19
|
};
|
|
19
20
|
class ZarrHelper {
|
|
@@ -34,36 +35,40 @@ const fetchDataFromZarr = async (url, path, s, opts) => {
|
|
|
34
35
|
const result = await z.get(s, opts);
|
|
35
36
|
return result.data;
|
|
36
37
|
} catch (error) {
|
|
37
|
-
|
|
38
|
+
if (error instanceof _zarr.ArrayNotFoundError || error instanceof _zarr.GroupNotFoundError) {
|
|
39
|
+
error.status = 404;
|
|
40
|
+
}
|
|
41
|
+
throw error;
|
|
38
42
|
}
|
|
39
43
|
};
|
|
40
44
|
const useZarr = ({
|
|
41
45
|
url,
|
|
42
46
|
path
|
|
43
|
-
}, s = null, opts = {}) => {
|
|
47
|
+
}, s = null, options = GET_OPTIONS, opts = {}) => {
|
|
44
48
|
const {
|
|
45
49
|
enabled = true
|
|
46
50
|
} = opts;
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
|
|
51
|
+
const {
|
|
52
|
+
data = null,
|
|
53
|
+
isPending = false,
|
|
54
|
+
error: serverError = null
|
|
55
|
+
} = (0, _reactQuery.useQuery)({
|
|
56
|
+
queryKey: ["zarr", url, path, s],
|
|
57
|
+
queryFn: () => {
|
|
58
|
+
if (enabled) {
|
|
59
|
+
return fetchDataFromZarr(url, path, s, options);
|
|
60
|
+
} else {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
retry: (failureCount, {
|
|
65
|
+
error
|
|
66
|
+
}) => {
|
|
67
|
+
if ([400, 401, 403, 404, 422].includes(error?.status)) return false;
|
|
68
|
+
return failureCount < 3;
|
|
69
|
+
},
|
|
70
|
+
...opts
|
|
71
|
+
});
|
|
67
72
|
return {
|
|
68
73
|
data,
|
|
69
74
|
isPending,
|
|
@@ -71,48 +76,49 @@ const useZarr = ({
|
|
|
71
76
|
};
|
|
72
77
|
};
|
|
73
78
|
exports.useZarr = useZarr;
|
|
74
|
-
const fetchDataFromZarrs = async (inputs, opts) => {
|
|
75
|
-
try {
|
|
76
|
-
const results = await Promise.all(inputs.map(input => fetchDataFromZarr(input.url, input.path, input.s, opts)));
|
|
77
|
-
return results;
|
|
78
|
-
} catch (error) {
|
|
79
|
-
throw new Error(error.message);
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
79
|
const aggregateData = (inputs, data) => {
|
|
83
80
|
const dataObject = {};
|
|
84
|
-
|
|
85
|
-
const key =
|
|
86
|
-
dataObject[key] =
|
|
81
|
+
inputs.forEach((input, index) => {
|
|
82
|
+
const key = input.key;
|
|
83
|
+
dataObject[key] = data?.[index];
|
|
87
84
|
});
|
|
88
85
|
return dataObject;
|
|
89
86
|
};
|
|
90
|
-
|
|
91
|
-
// @TODO: return response of successfully fetched data when error occurs
|
|
92
|
-
const useMultipleZarr = (inputs, opts = {}, agg = aggregateData) => {
|
|
87
|
+
const useMultipleZarr = (inputs, options = GET_OPTIONS, opts = {}, agg = aggregateData) => {
|
|
93
88
|
const {
|
|
94
89
|
enabled = true
|
|
95
90
|
} = opts;
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
91
|
+
const combine = (0, _react.useCallback)(results => {
|
|
92
|
+
return {
|
|
93
|
+
data: agg(inputs, results.map(result => result.data)),
|
|
94
|
+
isPending: results.some(result => result.isPending),
|
|
95
|
+
serverError: results.find(result => result.error)
|
|
96
|
+
};
|
|
97
|
+
}, [agg, inputs]);
|
|
98
|
+
const {
|
|
99
|
+
data = null,
|
|
100
|
+
isPending = false,
|
|
101
|
+
serverError = null
|
|
102
|
+
} = (0, _reactQuery.useQueries)({
|
|
103
|
+
queries: inputs.map(input => ({
|
|
104
|
+
queryKey: ["zarr", input.url, input.path, input.s],
|
|
105
|
+
queryFn: () => {
|
|
106
|
+
if (enabled) {
|
|
107
|
+
return fetchDataFromZarr(input.url, input.path, input.s, options);
|
|
108
|
+
} else {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
retry: (failureCount, {
|
|
113
|
+
error
|
|
114
|
+
}) => {
|
|
115
|
+
if ([400, 401, 403, 404, 422].includes(error?.status)) return false;
|
|
116
|
+
return failureCount < 3;
|
|
117
|
+
},
|
|
118
|
+
...opts
|
|
119
|
+
})),
|
|
120
|
+
combine
|
|
121
|
+
});
|
|
116
122
|
return {
|
|
117
123
|
data,
|
|
118
124
|
isPending,
|
package/dist/utils/requests.js
CHANGED
|
@@ -45,7 +45,7 @@ const useFetch = (endpoint, params, opts = {
|
|
|
45
45
|
} = opts;
|
|
46
46
|
const {
|
|
47
47
|
data: fetchedData = null,
|
|
48
|
-
|
|
48
|
+
isPending = false,
|
|
49
49
|
error: serverError = null
|
|
50
50
|
} = (0, _reactQuery.useQuery)({
|
|
51
51
|
queryKey: [endpoint, params],
|
|
@@ -83,7 +83,7 @@ const useDebouncedFetch = (endpoint, params, delay = 500, opts = {
|
|
|
83
83
|
const debouncedParams = (0, _usehooks.useDebounce)(params, delay);
|
|
84
84
|
const {
|
|
85
85
|
data: fetchedData = null,
|
|
86
|
-
|
|
86
|
+
isPending = false,
|
|
87
87
|
error: serverError = null
|
|
88
88
|
} = (0, _reactQuery.useQuery)({
|
|
89
89
|
queryKey: [endpoint, debouncedParams],
|
package/dist/utils/zarrData.js
CHANGED
|
@@ -23,7 +23,9 @@ const useObsmData = (obsm = null) => {
|
|
|
23
23
|
path: "obsm/" + obsm
|
|
24
24
|
});
|
|
25
25
|
}, [dataset.url, obsm]);
|
|
26
|
-
return (0, _zarrHelper.useZarr)(obsmParams, null, _zarrHelper.GET_OPTIONS
|
|
26
|
+
return (0, _zarrHelper.useZarr)(obsmParams, null, _zarrHelper.GET_OPTIONS, {
|
|
27
|
+
enabled: !!obsm
|
|
28
|
+
});
|
|
27
29
|
};
|
|
28
30
|
exports.useObsmData = useObsmData;
|
|
29
31
|
const meanData = (_i, data) => {
|
|
@@ -55,7 +57,9 @@ const useXData = (agg = meanData) => {
|
|
|
55
57
|
};
|
|
56
58
|
}));
|
|
57
59
|
}, [dataset.url, dataset.selectedVar]);
|
|
58
|
-
return (0, _zarrHelper.useMultipleZarr)(xParams, _zarrHelper.GET_OPTIONS,
|
|
60
|
+
return (0, _zarrHelper.useMultipleZarr)(xParams, _zarrHelper.GET_OPTIONS, {
|
|
61
|
+
enabled: !!xParams.length
|
|
62
|
+
}, agg);
|
|
59
63
|
};
|
|
60
64
|
exports.useXData = useXData;
|
|
61
65
|
const useObsData = (obs = null) => {
|
|
@@ -71,7 +75,9 @@ const useObsData = (obs = null) => {
|
|
|
71
75
|
path: "obs/" + obs?.name + (obs?.type === _constants.OBS_TYPES.CATEGORICAL ? "/codes" : "")
|
|
72
76
|
});
|
|
73
77
|
}, [dataset.url, obs]);
|
|
74
|
-
return (0, _zarrHelper.useZarr)(obsParams, null, _zarrHelper.GET_OPTIONS
|
|
78
|
+
return (0, _zarrHelper.useZarr)(obsParams, null, _zarrHelper.GET_OPTIONS, {
|
|
79
|
+
enabled: !!obs
|
|
80
|
+
});
|
|
75
81
|
};
|
|
76
82
|
exports.useObsData = useObsData;
|
|
77
83
|
const useLabelObsData = () => {
|
|
@@ -92,6 +98,8 @@ const useLabelObsData = () => {
|
|
|
92
98
|
};
|
|
93
99
|
}));
|
|
94
100
|
}, [dataset.labelObs, dataset.url]);
|
|
95
|
-
return (0, _zarrHelper.useMultipleZarr)(labelObsParams, _zarrHelper.GET_OPTIONS
|
|
101
|
+
return (0, _zarrHelper.useMultipleZarr)(labelObsParams, _zarrHelper.GET_OPTIONS, {
|
|
102
|
+
enabled: !!labelObsParams.length
|
|
103
|
+
});
|
|
96
104
|
};
|
|
97
105
|
exports.useLabelObsData = useLabelObsData;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@haniffalab/cherita-react",
|
|
3
|
-
"version": "0.2.1-dev.2025-
|
|
3
|
+
"version": "0.2.1-dev.2025-03-06.b4baf3a1",
|
|
4
4
|
"author": "",
|
|
5
5
|
"license": "",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -22,14 +22,14 @@
|
|
|
22
22
|
"@mui/x-charts": "^7.7.1",
|
|
23
23
|
"@nebula.gl/editor": "^1.0.4",
|
|
24
24
|
"@nebula.gl/layers": "^1.0.4",
|
|
25
|
-
"@tanstack/query-sync-storage-persister": "
|
|
26
|
-
"@tanstack/react-query": "
|
|
27
|
-
"@tanstack/react-query-persist-client": "
|
|
25
|
+
"@tanstack/query-sync-storage-persister": "5.66",
|
|
26
|
+
"@tanstack/react-query": "5.66",
|
|
27
|
+
"@tanstack/react-query-persist-client": "5.66",
|
|
28
28
|
"@tanstack/react-virtual": "^3.7.0",
|
|
29
29
|
"@turf/turf": "^7.0.0",
|
|
30
30
|
"@uidotdev/usehooks": "^2.4.1",
|
|
31
31
|
"bootstrap": "^5.3.3",
|
|
32
|
-
"deck.gl": "
|
|
32
|
+
"deck.gl": "8.8.27",
|
|
33
33
|
"jquery": "^3.7.1",
|
|
34
34
|
"nebula.gl": "^1.0.4",
|
|
35
35
|
"numbro": "^2.5.0",
|
|
@@ -45,22 +45,22 @@
|
|
|
45
45
|
"react-dom": "^18.2.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@testing-library/dom": "^10.4.0",
|
|
49
|
-
"@testing-library/jest-dom": "^6.6.3",
|
|
50
|
-
"@testing-library/react": "^16.2.0",
|
|
51
|
-
"babel-jest": "^29.7.0",
|
|
52
48
|
"@babel/cli": "^7.22.5",
|
|
53
49
|
"@babel/core": "^7.22.5",
|
|
54
50
|
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
|
55
51
|
"@babel/preset-env": "^7.22.5",
|
|
56
52
|
"@babel/preset-react": "^7.22.5",
|
|
53
|
+
"@testing-library/dom": "^10.4.0",
|
|
54
|
+
"@testing-library/jest-dom": "^6.6.3",
|
|
55
|
+
"@testing-library/react": "^16.2.0",
|
|
56
|
+
"babel-jest": "^29.7.0",
|
|
57
57
|
"cpx": "^1.5.0",
|
|
58
58
|
"eslint": "^8.42.0",
|
|
59
59
|
"eslint-config-prettier": "^8.8.0",
|
|
60
60
|
"eslint-config-react-app": "^7.0.1",
|
|
61
|
+
"eslint-plugin-import": "^2.29.1",
|
|
61
62
|
"jest": "^29.7.0",
|
|
62
63
|
"jest-environment-jsdom": "^29.7.0",
|
|
63
|
-
"eslint-plugin-import": "^2.29.1",
|
|
64
64
|
"prettier": "^3.3.3",
|
|
65
65
|
"sass": "1.77.6",
|
|
66
66
|
"stylelint": "^16.10.0",
|
|
@@ -107,5 +107,5 @@
|
|
|
107
107
|
"url": "https://github.com/haniffalab/cherita-react/issues"
|
|
108
108
|
},
|
|
109
109
|
"homepage": "https://github.com/haniffalab/cherita-react#readme",
|
|
110
|
-
"prereleaseSha": "
|
|
110
|
+
"prereleaseSha": "b4baf3a1ea64f986ea5205c4ad0755a0ff933a4c"
|
|
111
111
|
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.PseudospatialControls = PseudospatialControls;
|
|
7
|
-
var _react = _interopRequireDefault(require("react"));
|
|
8
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
|
-
function PseudospatialControls() {
|
|
10
|
-
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null);
|
|
11
|
-
}
|