@haniffalab/cherita-react 0.2.0-dev.2024-05-21.ca7d726c → 0.2.0-dev.2024-09-26.f9979478

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 (32) hide show
  1. package/dist/App.scss +67 -12
  2. package/dist/components/Offcanvas/index.js +9 -6
  3. package/dist/components/dotplot/Dotplot.js +5 -189
  4. package/dist/components/dotplot/DotplotControls.js +197 -0
  5. package/dist/components/heatmap/Heatmap.js +5 -31
  6. package/dist/components/heatmap/HeatmapControls.js +36 -0
  7. package/dist/components/matrixplot/Matrixplot.js +5 -59
  8. package/dist/components/matrixplot/MatrixplotControls.js +65 -0
  9. package/dist/components/obs-list/ObsList.js +251 -93
  10. package/dist/components/obs-list/ObsValueList.js +101 -0
  11. package/dist/components/obsm-list/ObsmList.js +25 -16
  12. package/dist/components/scatterplot/Legend.js +28 -36
  13. package/dist/components/scatterplot/Scatterplot.js +303 -119
  14. package/dist/components/scatterplot/ScatterplotControls.js +93 -0
  15. package/dist/components/scatterplot/SpatialControls.js +172 -0
  16. package/dist/components/scatterplot/Toolbox.js +18 -72
  17. package/dist/components/search-bar/SearchBar.js +2 -2
  18. package/dist/components/search-bar/SearchResults.js +2 -2
  19. package/dist/components/var-list/VarList.js +102 -40
  20. package/dist/components/violin/Violin.js +7 -46
  21. package/dist/components/violin/ViolinControls.js +50 -0
  22. package/dist/constants/colorscales.js +28 -0
  23. package/dist/constants/constants.js +11 -43
  24. package/dist/context/DatasetContext.js +122 -23
  25. package/dist/helpers/color-helper.js +54 -21
  26. package/dist/helpers/zarr-helper.js +39 -17
  27. package/dist/index.js +17 -11
  28. package/dist/utils/LoadingIndicators.js +33 -0
  29. package/dist/utils/requests.js +1 -1
  30. package/dist/utils/search.js +4 -3
  31. package/package.json +10 -4
  32. package/dist/utils/LoadingSpinner.js +0 -44
@@ -4,51 +4,30 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.Scatterplot = Scatterplot;
7
- exports.ScatterplotControls = ScatterplotControls;
8
7
  var _react = _interopRequireWildcard(require("react"));
9
- var _lodash = _interopRequireDefault(require("lodash"));
10
- require("bootstrap/dist/css/bootstrap.min.css");
11
- var _react2 = _interopRequireDefault(require("@deck.gl/react"));
12
8
  var _layers = require("@deck.gl/layers");
13
- var _layers2 = require("@nebula.gl/layers");
9
+ var _react2 = require("@deck.gl/react");
10
+ var _freeSolidSvgIcons = require("@fortawesome/free-solid-svg-icons");
11
+ var _reactFontawesome = require("@fortawesome/react-fontawesome");
14
12
  var _editModes = require("@nebula.gl/edit-modes");
15
- var _Dropdown = _interopRequireDefault(require("react-bootstrap/Dropdown"));
16
- var _Toolbox = require("./Toolbox");
13
+ var _layers2 = require("@nebula.gl/layers");
14
+ var _turf = require("@turf/turf");
15
+ var _lodash = _interopRequireDefault(require("lodash"));
16
+ var _reactBootstrap = require("react-bootstrap");
17
17
  var _Legend = require("./Legend");
18
+ var _SpatialControls = require("./SpatialControls");
19
+ var _Toolbox = require("./Toolbox");
18
20
  var _constants = require("../../constants/constants");
19
21
  var _DatasetContext = require("../../context/DatasetContext");
22
+ var _colorHelper = require("../../helpers/color-helper");
20
23
  var _mapHelper = require("../../helpers/map-helper");
21
24
  var _zarrHelper = require("../../helpers/zarr-helper");
22
- var _colorHelper = require("../../helpers/color-helper");
23
- var _LoadingSpinner = require("../../utils/LoadingSpinner");
25
+ var _LoadingIndicators = require("../../utils/LoadingIndicators");
24
26
  var _jsxRuntime = require("react/jsx-runtime");
25
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
27
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
26
28
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
27
- function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
29
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
28
30
  window.deck.log.level = 1;
29
- function ScatterplotControls() {
30
- const dataset = (0, _DatasetContext.useDataset)();
31
- const dispatch = (0, _DatasetContext.useDatasetDispatch)();
32
- const colormapList = _constants.PLOTLY_COLORSCALES.map(item => /*#__PURE__*/(0, _jsxRuntime.jsx)(_Dropdown.default.Item, {
33
- active: dataset.controls.colorScale === item,
34
- onClick: () => {
35
- dispatch({
36
- type: "set.controls.colorScale",
37
- colorScale: item
38
- });
39
- },
40
- children: item
41
- }, item));
42
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Dropdown.default, {
43
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Dropdown.default.Toggle, {
44
- id: "dropdownColorscale",
45
- variant: "light",
46
- children: dataset.controls.colorScale
47
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Dropdown.default.Menu, {
48
- children: colormapList
49
- })]
50
- });
51
- }
52
31
  const INITIAL_VIEW_STATE = {
53
32
  longitude: 0,
54
33
  latitude: 0,
@@ -57,31 +36,32 @@ const INITIAL_VIEW_STATE = {
57
36
  pitch: 0,
58
37
  bearing: 0
59
38
  };
60
- const DEFAULT_DATA_POINT = {
61
- value: null,
62
- position: null,
63
- color: null
64
- };
65
39
  function Scatterplot(_ref) {
66
- var _dataset$selectedObs;
40
+ var _dataset$selectedObs, _dataset$selectedObs2, _dataset$selectedObs6, _dataset$selectedObs8, _dataset$selectedObs10, _features$features2, _obsmData$serverError, _xData$serverError, _obsData$serverError, _labelObsData$serverE, _obsmData$data;
67
41
  let {
68
42
  radius = 30
69
43
  } = _ref;
70
44
  const dataset = (0, _DatasetContext.useDataset)();
45
+ const dispatch = (0, _DatasetContext.useDatasetDispatch)();
71
46
  const {
72
- getScale,
73
47
  getColor
74
48
  } = (0, _colorHelper.useColor)();
75
49
  const [viewState, setViewState] = (0, _react.useState)(INITIAL_VIEW_STATE);
50
+ const [isRendering, setIsRendering] = (0, _react.useState)(true);
51
+ const [data, setData] = (0, _react.useState)({
52
+ ids: [],
53
+ positions: [],
54
+ values: [],
55
+ sliceValues: []
56
+ });
57
+
58
+ // EditableGeoJsonLayer
59
+ const [mode, setMode] = (0, _react.useState)(() => _editModes.ViewMode);
76
60
  const [features, setFeatures] = (0, _react.useState)({
77
61
  type: "FeatureCollection",
78
62
  features: []
79
63
  });
80
- const [mode, setMode] = (0, _react.useState)(() => _editModes.ViewMode);
81
64
  const [selectedFeatureIndexes, setSelectedFeatureIndexes] = (0, _react.useState)([]);
82
- const [featureState, setFeatureState] = (0, _react.useState)([]);
83
- const [scale, setScale] = (0, _react.useState)(() => getScale());
84
- const [data, setData] = (0, _react.useState)([]);
85
65
  const [obsmParams, setObsmParams] = (0, _react.useState)({
86
66
  url: dataset.url,
87
67
  path: "obsm/" + dataset.selectedObsm
@@ -92,8 +72,9 @@ function Scatterplot(_ref) {
92
72
  });
93
73
  const [obsParams, setObsParams] = (0, _react.useState)({
94
74
  url: dataset.url,
95
- path: "obs/" + ((_dataset$selectedObs = dataset.selectedObs) === null || _dataset$selectedObs === void 0 ? void 0 : _dataset$selectedObs.name) + "/codes"
75
+ path: "obs/" + ((_dataset$selectedObs = dataset.selectedObs) === null || _dataset$selectedObs === void 0 ? void 0 : _dataset$selectedObs.name) + (((_dataset$selectedObs2 = dataset.selectedObs) === null || _dataset$selectedObs2 === void 0 ? void 0 : _dataset$selectedObs2.type) === _constants.OBS_TYPES.CONTINUOUS ? "" : "/codes")
96
76
  });
77
+ const [labelObsParams, setLabelObsParams] = (0, _react.useState)([]);
97
78
 
98
79
  // needs to be wrapped in useMemo as it is an array an could cause an infinite loop otherwise
99
80
  const xSelection = (0, _react.useMemo)(() => {
@@ -103,6 +84,7 @@ function Scatterplot(_ref) {
103
84
  const obsmData = (0, _zarrHelper.useZarr)(obsmParams, null, _zarrHelper.GET_OPTIONS);
104
85
  const xData = (0, _zarrHelper.useZarr)(xParams, xSelection, _zarrHelper.GET_OPTIONS);
105
86
  const obsData = (0, _zarrHelper.useZarr)(obsParams, null, _zarrHelper.GET_OPTIONS);
87
+ const labelObsData = (0, _zarrHelper.useMultipleZarr)(labelObsParams, _zarrHelper.GET_OPTIONS);
106
88
  (0, _react.useEffect)(() => {
107
89
  setObsmParams(p => {
108
90
  return {
@@ -122,13 +104,22 @@ function Scatterplot(_ref) {
122
104
  }, [dataset.selectedVar]);
123
105
  (0, _react.useEffect)(() => {
124
106
  setObsParams(p => {
125
- var _dataset$selectedObs2;
107
+ var _dataset$selectedObs3, _dataset$selectedObs4;
126
108
  return {
127
109
  ...p,
128
- path: "obs/" + ((_dataset$selectedObs2 = dataset.selectedObs) === null || _dataset$selectedObs2 === void 0 ? void 0 : _dataset$selectedObs2.name) + "/codes"
110
+ path: "obs/" + ((_dataset$selectedObs3 = dataset.selectedObs) === null || _dataset$selectedObs3 === void 0 ? void 0 : _dataset$selectedObs3.name) + (((_dataset$selectedObs4 = dataset.selectedObs) === null || _dataset$selectedObs4 === void 0 ? void 0 : _dataset$selectedObs4.type) === _constants.OBS_TYPES.CONTINUOUS ? "" : "/codes")
129
111
  };
130
112
  });
131
113
  }, [dataset.selectedObs]);
114
+ (0, _react.useEffect)(() => {
115
+ setLabelObsParams(_lodash.default.map(dataset.labelObs, obs => {
116
+ return {
117
+ url: dataset.url,
118
+ path: "obs/" + obs.name + (obs.type === _constants.OBS_TYPES.CONTINUOUS ? "" : "/codes"),
119
+ key: obs.name
120
+ };
121
+ }));
122
+ }, [dataset.labelObs, dataset.url]);
132
123
  (0, _react.useEffect)(() => {
133
124
  setObsmParams(p => {
134
125
  return {
@@ -154,12 +145,12 @@ function Scatterplot(_ref) {
154
145
 
155
146
  (0, _react.useEffect)(() => {
156
147
  if (!obsmData.isPending && !obsmData.serverError) {
148
+ setIsRendering(true);
157
149
  setData(d => {
158
- return _lodash.default.map(obsmData.data, (p, index) => {
159
- return _lodash.default.defaults({
160
- position: p
161
- }, d === null || d === void 0 ? void 0 : d[index], DEFAULT_DATA_POINT);
162
- });
150
+ return {
151
+ ...d,
152
+ positions: obsmData.data
153
+ };
163
154
  });
164
155
  const mapHelper = new _mapHelper.MapHelper();
165
156
  const {
@@ -176,129 +167,322 @@ function Scatterplot(_ref) {
176
167
  };
177
168
  });
178
169
  } else if (!obsmData.isPending && obsmData.serverError) {
170
+ setIsRendering(true);
179
171
  setData(d => {
180
- return _lodash.default.map(d, e => {
181
- return _lodash.default.defaults({
182
- position: null
183
- }, e, DEFAULT_DATA_POINT);
184
- });
172
+ return {
173
+ ...d,
174
+ positions: []
175
+ };
185
176
  });
186
177
  }
187
178
  }, [dataset.selectedObsm, obsmData.data, obsmData.isPending, obsmData.serverError]);
179
+ const bounds = (0, _react.useMemo)(() => {
180
+ const {
181
+ latitude,
182
+ longitude,
183
+ zoom
184
+ } = new _mapHelper.MapHelper().fitBounds(data.positions);
185
+ return {
186
+ latitude,
187
+ longitude,
188
+ zoom
189
+ };
190
+ }, [data.positions]);
188
191
  (0, _react.useEffect)(() => {
189
- if (dataset.colorEncoding === "var") {
192
+ if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.VAR) {
193
+ setIsRendering(true);
190
194
  if (!xData.isPending && !xData.serverError) {
191
- const s = getScale(xData.data);
192
- setScale(() => s);
195
+ // @TODO: add condition to check obs slicing
193
196
  setData(d => {
194
- return _lodash.default.map(xData.data, (v, index) => {
195
- return _lodash.default.defaults({
196
- value: v,
197
- color: getColor(s, v)
198
- }, d === null || d === void 0 ? void 0 : d[index], DEFAULT_DATA_POINT);
199
- });
197
+ return {
198
+ ...d,
199
+ values: xData.data
200
+ };
200
201
  });
201
202
  } else if (!xData.isPending && xData.serverError) {
202
- const s = getScale();
203
- setScale(() => s);
204
203
  setData(d => {
205
- return _lodash.default.map(d, e => {
206
- return _lodash.default.defaults({
207
- value: null,
208
- color: null
209
- }, e, DEFAULT_DATA_POINT);
210
- });
204
+ return {
205
+ ...d,
206
+ values: []
207
+ };
211
208
  });
212
209
  }
213
210
  }
214
- }, [dataset.colorEncoding, xData.data, xData.isPending, xData.serverError, getScale, getColor]);
211
+ }, [dataset.colorEncoding, xData.data, xData.isPending, xData.serverError, getColor]);
215
212
  (0, _react.useEffect)(() => {
216
- if (dataset.colorEncoding === "obs") {
213
+ if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS) {
214
+ setIsRendering(true);
217
215
  if (!obsData.isPending && !obsData.serverError) {
218
- const s = getScale(obsData.data);
219
- setScale(() => s);
220
216
  setData(d => {
221
- return _lodash.default.map(obsData.data, (v, index) => {
222
- return _lodash.default.defaults({
223
- value: v,
224
- color: getColor(s, v)
225
- }, d === null || d === void 0 ? void 0 : d[index], DEFAULT_DATA_POINT);
226
- });
217
+ return {
218
+ ...d,
219
+ values: obsData.data
220
+ };
227
221
  });
228
222
  } else if (!obsData.isPending && obsData.serverError) {
229
- const s = getScale();
230
- setScale(() => s);
231
223
  setData(d => {
232
- return _lodash.default.map(d, e => {
233
- return _lodash.default.defaults({
234
- value: null,
235
- color: null
236
- }, e, DEFAULT_DATA_POINT);
237
- });
224
+ return {
225
+ ...d,
226
+ values: []
227
+ };
238
228
  });
239
229
  }
230
+ } else if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.VAR && dataset.sliceBy.obs) {
231
+ if (!obsData.isPending && !obsData.serverError) {
232
+ setData(d => {
233
+ return {
234
+ ...d,
235
+ sliceValues: obsData.data
236
+ };
237
+ });
238
+ } else if (!obsData.isPending && obsData.serverError) {
239
+ setData(d => {
240
+ return {
241
+ ...d,
242
+ sliceValues: []
243
+ };
244
+ });
245
+ }
246
+ }
247
+ }, [dataset.colorEncoding, obsData.data, obsData.isPending, obsData.serverError, dataset.sliceBy.obs]);
248
+ const isCategorical = (0, _react.useMemo)(() => {
249
+ if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS) {
250
+ var _dataset$selectedObs5;
251
+ return ((_dataset$selectedObs5 = dataset.selectedObs) === null || _dataset$selectedObs5 === void 0 ? void 0 : _dataset$selectedObs5.type) === _constants.OBS_TYPES.CATEGORICAL;
252
+ } else {
253
+ return false;
254
+ }
255
+ }, [dataset.colorEncoding, (_dataset$selectedObs6 = dataset.selectedObs) === null || _dataset$selectedObs6 === void 0 ? void 0 : _dataset$selectedObs6.type]);
256
+ const isInSlice = (0, _react.useCallback)((index, values, positions) => {
257
+ let inSlice = true;
258
+ if ((dataset.sliceBy.obs || isCategorical) && values) {
259
+ var _dataset$selectedObs7;
260
+ inSlice &= !_lodash.default.includes((_dataset$selectedObs7 = dataset.selectedObs) === null || _dataset$selectedObs7 === void 0 ? void 0 : _dataset$selectedObs7.omit, values[index]);
261
+ }
262
+ if (dataset.sliceBy.polygons && positions) {
263
+ inSlice &= _lodash.default.some(features === null || features === void 0 ? void 0 : features.features, (_f, i) => {
264
+ return (0, _turf.booleanPointInPolygon)((0, _turf.point)([positions[index][0], positions[index][1]]), features.features[i]);
265
+ });
266
+ }
267
+ return inSlice;
268
+ }, [(_dataset$selectedObs8 = dataset.selectedObs) === null || _dataset$selectedObs8 === void 0 ? void 0 : _dataset$selectedObs8.omit, dataset.sliceBy.obs, dataset.sliceBy.polygons, features.features, isCategorical]);
269
+ const {
270
+ filteredIndices,
271
+ valueMin,
272
+ valueMax,
273
+ slicedLength
274
+ } = (0, _react.useMemo)(() => {
275
+ if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.VAR) {
276
+ const {
277
+ filtered,
278
+ filteredIndices
279
+ } = _lodash.default.reduce(data.values, (acc, v, i) => {
280
+ if (isInSlice(i, data.sliceValues, data.positions)) {
281
+ acc.filtered.push(v);
282
+ acc.filteredIndices.add(i);
283
+ }
284
+ return acc;
285
+ }, {
286
+ filtered: [],
287
+ filteredIndices: new Set()
288
+ });
289
+ return {
290
+ filteredIndices: filteredIndices,
291
+ valueMin: _lodash.default.min(filtered),
292
+ valueMax: _lodash.default.max(filtered),
293
+ slicedLength: filtered.length
294
+ };
295
+ } else if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS) {
296
+ var _dataset$selectedObs9;
297
+ const isContinuous = ((_dataset$selectedObs9 = dataset.selectedObs) === null || _dataset$selectedObs9 === void 0 ? void 0 : _dataset$selectedObs9.type) === _constants.OBS_TYPES.CONTINUOUS;
298
+ const {
299
+ filtered,
300
+ filteredIndices
301
+ } = _lodash.default.reduce(data.values, (acc, v, i) => {
302
+ if (isInSlice(i, data.values, data.positions)) {
303
+ acc.filtered.push(v);
304
+ acc.filteredIndices.add(i);
305
+ }
306
+ return acc;
307
+ }, {
308
+ filtered: [],
309
+ filteredIndices: new Set()
310
+ });
311
+ return {
312
+ filteredIndices: filteredIndices,
313
+ valueMin: _lodash.default.min(isContinuous ? filtered : data.values),
314
+ valueMax: _lodash.default.max(isContinuous ? filtered : data.values),
315
+ slicedLength: filtered.length
316
+ };
317
+ } else {
318
+ return {
319
+ filteredIndices: null,
320
+ valueMin: _lodash.default.min(data.values),
321
+ valueMax: _lodash.default.max(data.values),
322
+ slicedLength: data.values.length
323
+ };
240
324
  }
241
- }, [dataset.colorEncoding, obsData.data, obsData.isPending, obsData.serverError, getScale, getColor]);
242
- const layers = (0, _react.useMemo)(() => {
325
+ }, [data.positions, data.sliceValues, data.values, dataset.colorEncoding, (_dataset$selectedObs10 = dataset.selectedObs) === null || _dataset$selectedObs10 === void 0 ? void 0 : _dataset$selectedObs10.type, isInSlice]);
326
+ (0, _react.useEffect)(() => {
327
+ dispatch({
328
+ type: "set.controls.valueRange",
329
+ valueRange: [valueMin, valueMax]
330
+ });
331
+ }, [dispatch, valueMax, valueMin]);
332
+ const {
333
+ min,
334
+ max
335
+ } = {
336
+ min: dataset.controls.range[0] * (valueMax - valueMin) + valueMin,
337
+ max: dataset.controls.range[1] * (valueMax - valueMin) + valueMin
338
+ };
339
+ const getFillColor = (0, _react.useCallback)((_d, _ref2) => {
340
+ let {
341
+ index
342
+ } = _ref2;
343
+ const grayOut = filteredIndices && !filteredIndices.has(index);
344
+ return getColor((data.values[index] - min) / (max - min), isCategorical, grayOut);
345
+ }, [data.values, filteredIndices, getColor, isCategorical, max, min]);
346
+ const memoizedLayers = (0, _react.useMemo)(() => {
243
347
  return [new _layers.ScatterplotLayer({
244
348
  id: "cherita-layer-scatterplot",
245
- data: data,
349
+ pickable: true,
350
+ data: data.positions,
246
351
  radiusScale: radius,
247
352
  radiusMinPixels: 1,
248
- getPosition: d => d.position,
249
- getFillColor: d => d.color,
250
- getRadius: 1
353
+ getPosition: d => d,
354
+ getFillColor: getFillColor,
355
+ getRadius: 1,
356
+ updateTriggers: {
357
+ getFillColor: getFillColor
358
+ }
251
359
  }), new _layers2.EditableGeoJsonLayer({
252
360
  id: "cherita-layer-draw",
253
361
  data: features,
254
362
  mode: mode,
255
363
  selectedFeatureIndexes,
256
- onEdit: _ref2 => {
364
+ onEdit: _ref3 => {
257
365
  let {
258
366
  updatedData,
259
367
  editType,
260
368
  editContext
261
- } = _ref2;
369
+ } = _ref3;
262
370
  setFeatures(updatedData);
263
371
  let updatedSelectedFeatureIndexes = selectedFeatureIndexes;
264
- setFeatureState({
265
- data: updatedData
266
- });
267
372
  if (editType === "addFeature") {
268
- // when a drawing is complete, the value of editType becomes addFeature
269
373
  const {
270
374
  featureIndexes
271
- } = editContext; //extracting indexes of current features selected
375
+ } = editContext;
272
376
  updatedSelectedFeatureIndexes = [...selectedFeatureIndexes, ...featureIndexes];
273
377
  }
274
- setSelectedFeatureIndexes(updatedSelectedFeatureIndexes); //now update your state
378
+ setSelectedFeatureIndexes(updatedSelectedFeatureIndexes);
379
+ },
380
+ // getFillColor: POLYGON_FILLCOLOR,
381
+ _subLayerProps: {
382
+ geojson: {
383
+ getFillColor: feature => {
384
+ if (selectedFeatureIndexes.some(i => features.features[i] === feature)) {
385
+ return _constants.SELECTED_POLYGON_FILLCOLOR;
386
+ } else {
387
+ return _constants.UNSELECTED_POLYGON_FILLCOLOR;
388
+ }
389
+ }
390
+ }
275
391
  }
276
392
  })];
277
- }, [data, features, mode, radius, selectedFeatureIndexes]);
393
+ }, [data.positions, features, getFillColor, mode, radius, selectedFeatureIndexes]);
394
+ const layers = (0, _react.useDeferredValue)(mode === _editModes.ViewMode ? memoizedLayers.reverse() : memoizedLayers); // draw scatterplot on top of polygons when in ViewMode
395
+
396
+ (0, _react.useEffect)(() => {
397
+ var _features$features;
398
+ if (!(features !== null && features !== void 0 && (_features$features = features.features) !== null && _features$features !== void 0 && _features$features.length)) {
399
+ dispatch({
400
+ type: "disable.slice.polygons"
401
+ });
402
+ }
403
+ }, [dispatch, features === null || features === void 0 || (_features$features2 = features.features) === null || _features$features2 === void 0 ? void 0 : _features$features2.length]);
278
404
  function onLayerClick(info) {
279
405
  if (mode !== _editModes.ViewMode) {
280
406
  // don't change selection while editing
281
407
  return;
282
408
  }
283
- setSelectedFeatureIndexes(info.object ? [info.index] : []);
409
+ setSelectedFeatureIndexes(f => info.object ? info.layer.id === "cherita-layer-draw" ? [info.index] : f : []);
284
410
  }
285
-
286
- // @TODO: add error message
411
+ const getTooltip = _ref4 => {
412
+ let {
413
+ object,
414
+ index
415
+ } = _ref4;
416
+ return object && dataset.labelObs.length && {
417
+ text: _lodash.default.map(labelObsData, (v, k) => {
418
+ const labelObs = _lodash.default.find(dataset.labelObs, o => o.name === k);
419
+ if (labelObs.type === _constants.OBS_TYPES.CONTINUOUS) {
420
+ return "".concat(k, ": ").concat(parseFloat(v === null || v === void 0 ? void 0 : v[index]).toLocaleString());
421
+ } else {
422
+ return "".concat(k, ": ").concat(labelObs.codesMap[v === null || v === void 0 ? void 0 : v[index]]);
423
+ }
424
+ }).join("\n")
425
+ };
426
+ };
427
+ const isPending = (isRendering || xData.isPending || obsmData.isPending) && !obsmData.isPending;
428
+ const error = dataset.selectedObsm && ((_obsmData$serverError = obsmData.serverError) === null || _obsmData$serverError === void 0 ? void 0 : _obsmData$serverError.length) || dataset.colorEncoding === _constants.COLOR_ENCODINGS.VAR && ((_xData$serverError = xData.serverError) === null || _xData$serverError === void 0 ? void 0 : _xData$serverError.length) || dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS && ((_obsData$serverError = obsData.serverError) === null || _obsData$serverError === void 0 ? void 0 : _obsData$serverError.length) || dataset.labelObs.lengh && ((_labelObsData$serverE = labelObsData.serverError) === null || _labelObsData$serverE === void 0 ? void 0 : _labelObsData$serverE.length);
287
429
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
288
430
  className: "cherita-scatterplot",
289
- children: [(obsmData.isPending || xData.isPending || obsmData.isPending) && /*#__PURE__*/(0, _jsxRuntime.jsx)(_LoadingSpinner.LoadingSpinner, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_react2.default, {
431
+ children: [obsmData.isPending && /*#__PURE__*/(0, _jsxRuntime.jsx)(_LoadingIndicators.LoadingSpinner, {
432
+ disableShrink: true
433
+ }), isPending && /*#__PURE__*/(0, _jsxRuntime.jsx)(_LoadingIndicators.LoadingLinear, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_react2.DeckGL, {
290
434
  viewState: viewState,
291
435
  onViewStateChange: e => setViewState(e.viewState),
292
- controller: true,
436
+ controller: {
437
+ doubleClickZoom: mode === _editModes.ViewMode
438
+ },
293
439
  layers: layers,
294
- onClick: onLayerClick
295
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Toolbox.Toolbox, {
440
+ onClick: onLayerClick,
441
+ getTooltip: getTooltip,
442
+ onAfterRender: () => {
443
+ setIsRendering(false);
444
+ },
445
+ useDevicePixels: false,
446
+ getCursor: _ref5 => {
447
+ let {
448
+ isDragging
449
+ } = _ref5;
450
+ return mode !== _editModes.ViewMode ? "crosshair" : isDragging ? "grabbing" : "grab";
451
+ }
452
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_SpatialControls.SpatialControls, {
296
453
  mode: mode,
297
454
  setMode: setMode,
298
- features: mode,
299
- setFeatures: setFeatures
300
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Legend.Legend, {
301
- scale: scale
455
+ features: features,
456
+ setFeatures: setFeatures,
457
+ selectedFeatureIndexes: selectedFeatureIndexes,
458
+ resetBounds: () => setViewState(bounds),
459
+ increaseZoom: () => setViewState(v => ({
460
+ ...v,
461
+ zoom: v.zoom + 1
462
+ })),
463
+ decreaseZoom: () => setViewState(v => ({
464
+ ...v,
465
+ zoom: v.zoom - 1
466
+ }))
467
+ }), error && !isPending && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
468
+ className: "cherita-alert",
469
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactBootstrap.Alert, {
470
+ variant: "danger",
471
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactFontawesome.FontAwesomeIcon, {
472
+ icon: _freeSolidSvgIcons.faTriangleExclamation
473
+ }), "Error loading data"]
474
+ })
475
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
476
+ className: "cherita-spatial-footer",
477
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Toolbox.Toolbox, {
478
+ mode: dataset.colorEncoding === _constants.COLOR_ENCODINGS.VAR ? dataset.selectedVar.name : dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS ? dataset.selectedObs.name : null,
479
+ obsLength: parseInt((_obsmData$data = obsmData.data) === null || _obsmData$data === void 0 ? void 0 : _obsmData$data.length),
480
+ slicedLength: parseInt(slicedLength)
481
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Legend.Legend, {
482
+ isCategorical: isCategorical,
483
+ min: min,
484
+ max: max
485
+ })]
302
486
  })]
303
487
  });
304
488
  }
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.ScatterplotControls = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _material = require("@mui/material");
9
+ var _lodash = _interopRequireDefault(require("lodash"));
10
+ var _reactBootstrap = require("react-bootstrap");
11
+ var _colorscales = require("../../constants/colorscales");
12
+ var _constants = require("../../constants/constants");
13
+ var _DatasetContext = require("../../context/DatasetContext");
14
+ var _jsxRuntime = require("react/jsx-runtime");
15
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
16
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
17
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
18
+ const ScatterplotControls = () => {
19
+ var _dataset$selectedObs;
20
+ const dataset = (0, _DatasetContext.useDataset)();
21
+ const dispatch = (0, _DatasetContext.useDatasetDispatch)();
22
+ const [sliderValue, setSliderValue] = _react.default.useState(dataset.controls.range || [0, 1]);
23
+ const isCategorical = dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS ? ((_dataset$selectedObs = dataset.selectedObs) === null || _dataset$selectedObs === void 0 ? void 0 : _dataset$selectedObs.type) === _constants.OBS_TYPES.CATEGORICAL : false;
24
+ const colormapList = _lodash.default.keys(_colorscales.COLORSCALES).map(key => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Dropdown.Item, {
25
+ active: dataset.controls.colorScale === key,
26
+ onClick: () => {
27
+ dispatch({
28
+ type: "set.controls.colorScale",
29
+ colorScale: key
30
+ });
31
+ },
32
+ children: key
33
+ }, key));
34
+ const valueLabelFormat = value => {
35
+ return (value * (dataset.controls.valueRange[1] - dataset.controls.valueRange[0]) + dataset.controls.valueRange[0]).toFixed(2);
36
+ };
37
+ const marks = [{
38
+ value: 0,
39
+ label: valueLabelFormat(0)
40
+ }, {
41
+ value: 1,
42
+ label: valueLabelFormat(1)
43
+ }];
44
+ const updateSlider = (_e, value) => {
45
+ setSliderValue(value);
46
+ };
47
+ const updateRange = (_e, value) => {
48
+ setSliderValue(value);
49
+ dispatch({
50
+ type: "set.controls.range",
51
+ range: sliderValue
52
+ });
53
+ };
54
+ (0, _react.useEffect)(() => {
55
+ setSliderValue(dataset.controls.range);
56
+ }, [dataset.controls.range]);
57
+ const rangeSlider = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.Box, {
58
+ className: "w-100",
59
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Typography, {
60
+ id: "colorscale-range",
61
+ gutterBottom: true,
62
+ children: "Colorscale range"
63
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Slider, {
64
+ "aria-labelledby": "colorscale-range",
65
+ min: 0,
66
+ max: 1,
67
+ step: 0.001,
68
+ value: sliderValue,
69
+ onChange: updateSlider,
70
+ onChangeCommitted: updateRange,
71
+ valueLabelDisplay: "auto",
72
+ getAriaValueText: valueLabelFormat,
73
+ valueLabelFormat: valueLabelFormat,
74
+ marks: marks,
75
+ disabled: isCategorical
76
+ })]
77
+ });
78
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
79
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactBootstrap.Dropdown, {
80
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Dropdown.Toggle, {
81
+ id: "dropdownColorscale",
82
+ variant: "light",
83
+ children: dataset.controls.colorScale
84
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Dropdown.Menu, {
85
+ children: colormapList
86
+ })]
87
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
88
+ className: "m-4",
89
+ children: rangeSlider
90
+ })]
91
+ });
92
+ };
93
+ exports.ScatterplotControls = ScatterplotControls;