@haniffalab/cherita-react 0.1.9 → 0.1.11

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/README.md CHANGED
@@ -1 +1,25 @@
1
- # react-wt.js
1
+ # Cherita
2
+
3
+ ## Development
4
+
5
+ Install [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)
6
+
7
+ Install packages
8
+
9
+ ```sh
10
+ npm i
11
+ ```
12
+
13
+ Create a ``.env`` file within ``sites/demo`` to store environment variables for Vite to use. Within it set ``VITE_API_URL`` to the backend API url like
14
+
15
+ ```sh
16
+ VITE_API_URL=http://localhost:5000/api/
17
+ ```
18
+
19
+ Run the demo app
20
+
21
+ ```sh
22
+ npm run start-demo
23
+ ```
24
+
25
+ The app will automatically reload when changes are made
@@ -10,8 +10,10 @@ require("bootstrap/dist/css/bootstrap.min.css");
10
10
  var _Dropdown = _interopRequireDefault(require("react-bootstrap/Dropdown"));
11
11
  var _react = _interopRequireWildcard(require("react"));
12
12
  var _reactPlotly = _interopRequireDefault(require("react-plotly.js"));
13
- var _DatasetContext = require("../context/DatasetContext");
14
- var _constants = require("../constants/constants");
13
+ var _lodash = _interopRequireDefault(require("lodash"));
14
+ var _DatasetContext = require("../../context/DatasetContext");
15
+ var _constants = require("../../constants/constants");
16
+ var _requests = require("../../utils/requests");
15
17
  var _reactBootstrap = require("react-bootstrap");
16
18
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
17
19
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
@@ -27,99 +29,89 @@ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o =
27
29
  function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
28
30
  function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } }
29
31
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
30
- function DotplotControls(_ref) {
31
- var scaleRange = _ref.scaleRange,
32
- expressionCutoff = _ref.expressionCutoff,
33
- meanOnlyExpressed = _ref.meanOnlyExpressed,
34
- dataRange = _ref.dataRange,
35
- setScaleRange = _ref.setScaleRange,
36
- setExpressionCutoff = _ref.setExpressionCutoff,
37
- setMeanOnlyExpressed = _ref.setMeanOnlyExpressed,
38
- setStandardScale = _ref.setStandardScale;
32
+ function DotplotControls() {
39
33
  var dataset = (0, _DatasetContext.useDataset)();
40
34
  var dispatch = (0, _DatasetContext.useDatasetDispatch)();
41
- var _useState = (0, _react.useState)(dataset.colorscale),
35
+ var _useState = (0, _react.useState)({
36
+ standardScale: dataset.controls.standardScale,
37
+ expressionCutoff: dataset.controls.expressionCutoff,
38
+ colorAxis: {
39
+ cmin: dataset.controls.colorAxis.cmin,
40
+ cmax: dataset.controls.colorAxis.cmax
41
+ }
42
+ }),
42
43
  _useState2 = _slicedToArray(_useState, 2),
43
- activeColorscale = _useState2[0],
44
- setActiveColorscale = _useState2[1];
45
- var _useState3 = (0, _react.useState)("None"),
46
- _useState4 = _slicedToArray(_useState3, 2),
47
- activeStandardScale = _useState4[0],
48
- setActiveStandardScale = _useState4[1];
49
- var _useState5 = (0, _react.useState)(expressionCutoff),
50
- _useState6 = _slicedToArray(_useState5, 2),
51
- cutoff = _useState6[0],
52
- setCutoff = _useState6[1];
53
- var scaleMinRef = (0, _react.useRef)(null);
54
- var scaleMaxRef = (0, _react.useRef)(null);
55
- var standardScaleOptions = [{
56
- value: null,
57
- name: "None"
58
- }, {
59
- value: "group",
60
- name: "Group"
61
- }, {
62
- value: "var",
63
- name: "Var"
64
- }];
44
+ controls = _useState2[0],
45
+ setControls = _useState2[1];
65
46
  (0, _react.useEffect)(function () {
66
- setActiveColorscale(dataset.colorscale);
67
- }, [dataset.colorscale]);
68
- (0, _react.useEffect)(function () {
69
- scaleMinRef.current.value = scaleRange.min;
70
- scaleMaxRef.current.value = scaleRange.max;
71
- }, [scaleRange]);
72
- var colormapList = _constants.PLOTLY_COLORSCALES.map(function (item) {
47
+ setControls(function (c) {
48
+ return _objectSpread(_objectSpread({}, c), {}, {
49
+ colorAxis: {
50
+ cmin: dataset.controls.colorAxis.cmin,
51
+ cmax: dataset.controls.colorAxis.cmax
52
+ }
53
+ });
54
+ });
55
+ }, [dataset.controls.colorAxis.cmin, dataset.controls.colorAxis.cmax]);
56
+ var colorScaleList = _constants.PLOTLY_COLORSCALES.map(function (item) {
73
57
  return /*#__PURE__*/_react.default.createElement(_Dropdown.default.Item, {
74
58
  key: item,
75
- active: activeColorscale === item,
59
+ active: dataset.controls.colorScale === item,
76
60
  onClick: function onClick() {
77
61
  dispatch({
78
- type: "colorscaleSelected",
79
- colorscale: item
62
+ type: "set.controls.colorScale",
63
+ colorScale: item
80
64
  });
81
65
  }
82
66
  }, item);
83
67
  });
84
- var standardScaleList = standardScaleOptions.map(function (item) {
68
+ var standardScaleList = _constants.DOTPLOT_STANDARDSCALES.map(function (item) {
85
69
  return /*#__PURE__*/_react.default.createElement(_Dropdown.default.Item, {
86
70
  key: item.value,
87
- active: activeStandardScale === item.name,
71
+ active: dataset.controls.standardScale === item.value,
88
72
  onClick: function onClick() {
89
- setActiveStandardScale(item.name);
90
- setStandardScale(item.value);
73
+ dispatch({
74
+ type: "set.controls.standardScale",
75
+ standardScale: item.value
76
+ });
91
77
  }
92
78
  }, item.name);
93
79
  });
94
80
  return /*#__PURE__*/_react.default.createElement(_reactBootstrap.ButtonToolbar, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.ButtonGroup, null, /*#__PURE__*/_react.default.createElement(_Dropdown.default, null, /*#__PURE__*/_react.default.createElement(_Dropdown.default.Toggle, {
95
81
  id: "dropdownColorscale",
96
82
  variant: "light"
97
- }, dataset.colorscale), /*#__PURE__*/_react.default.createElement(_Dropdown.default.Menu, null, colormapList))), /*#__PURE__*/_react.default.createElement(_reactBootstrap.ButtonGroup, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.InputGroup, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.InputGroup.Text, null, "Standard scale"), /*#__PURE__*/_react.default.createElement(_Dropdown.default, null, /*#__PURE__*/_react.default.createElement(_Dropdown.default.Toggle, {
83
+ }, dataset.controls.colorScale), /*#__PURE__*/_react.default.createElement(_Dropdown.default.Menu, null, colorScaleList))), /*#__PURE__*/_react.default.createElement(_reactBootstrap.ButtonGroup, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.InputGroup, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.InputGroup.Text, null, "Standard scale"), /*#__PURE__*/_react.default.createElement(_Dropdown.default, null, /*#__PURE__*/_react.default.createElement(_Dropdown.default.Toggle, {
98
84
  id: "dropdownStandardScale",
99
85
  variant: "light"
100
- }, activeStandardScale), /*#__PURE__*/_react.default.createElement(_Dropdown.default.Menu, null, standardScaleList)))), /*#__PURE__*/_react.default.createElement(_reactBootstrap.ButtonGroup, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.ToggleButton, {
86
+ }, dataset.controls.standardScale), /*#__PURE__*/_react.default.createElement(_Dropdown.default.Menu, null, standardScaleList)))), /*#__PURE__*/_react.default.createElement(_reactBootstrap.ButtonGroup, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.ToggleButton, {
101
87
  id: "toggleMeanOnlyExpressed",
102
88
  type: "checkbox",
103
89
  variant: "outline-primary",
104
- checked: meanOnlyExpressed,
90
+ checked: dataset.controls.meanOnlyExpressed,
105
91
  onChange: function onChange() {
106
- setMeanOnlyExpressed(function (c) {
107
- return !c;
92
+ dispatch({
93
+ type: "set.controls.meanOnlyExpressed",
94
+ meanOnlyExpressed: !dataset.controls.meanOnlyExpressed
108
95
  });
109
96
  }
110
97
  }, "Average only above cutoff")), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Form, {
111
98
  onSubmit: function onSubmit(e) {
112
99
  e.preventDefault();
113
- setExpressionCutoff(parseFloat(cutoff));
100
+ dispatch({
101
+ type: "set.controls.expressionCutoff",
102
+ expressionCutoff: parseFloat(controls.expressionCutoff)
103
+ });
114
104
  }
115
105
  }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.InputGroup, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.InputGroup.Text, null, "Expression Cutoff"), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Form.Control, {
116
106
  size: "sm",
117
107
  type: "number",
118
108
  step: "0.1",
119
109
  min: 0.0,
120
- value: cutoff,
110
+ value: controls.expressionCutoff,
121
111
  onChange: function onChange(e) {
122
- setCutoff(e.target.value);
112
+ setControls(_objectSpread(_objectSpread({}, controls), {}, {
113
+ expressionCutoff: e.target.value
114
+ }));
123
115
  }
124
116
  }), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Button, {
125
117
  type: "submit",
@@ -127,35 +119,44 @@ function DotplotControls(_ref) {
127
119
  }, "Apply"))), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Form, {
128
120
  onSubmit: function onSubmit(e) {
129
121
  e.preventDefault();
130
- var formData = new FormData(e.target),
131
- formDataObj = Object.fromEntries(formData.entries());
132
- setScaleRange({
133
- min: parseFloat(formDataObj.scaleMin),
134
- max: parseFloat(formDataObj.scaleMax)
122
+ dispatch({
123
+ type: "set.controls.colorAxis.crange",
124
+ cmin: controls.colorAxis.cmin,
125
+ cmax: controls.colorAxis.cmax
135
126
  });
136
127
  }
137
128
  }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.InputGroup, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.InputGroup.Text, null, "Colorscale"), /*#__PURE__*/_react.default.createElement(_reactBootstrap.InputGroup.Text, null, "min"), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Form.Control, {
138
- ref: scaleMinRef,
139
129
  name: "scaleMin",
140
130
  size: "sm",
141
131
  type: "number",
142
- step: "0.1",
143
- min: 0.0,
144
- max: scaleRange.max,
145
- defaultValue: scaleRange.min
132
+ value: controls.colorAxis.cmin,
133
+ step: 0.1,
134
+ min: Math.min(dataset.controls.colorAxis.dmin, 0.0),
135
+ max: dataset.controls.colorAxis.dmax,
136
+ onChange: function onChange(e) {
137
+ setControls(_objectSpread(_objectSpread({}, controls), {}, {
138
+ colorAxis: _objectSpread(_objectSpread({}, controls.colorAxis), {}, {
139
+ cmin: e.target.value
140
+ })
141
+ }));
142
+ }
146
143
  }), /*#__PURE__*/_react.default.createElement(_reactBootstrap.InputGroup.Text, null, "max"), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Form.Control, {
147
- ref: scaleMaxRef,
148
144
  name: "scaleMax",
149
145
  size: "sm",
150
146
  type: "number",
151
- step: "0.1",
152
- min: scaleRange.min,
153
- max: dataRange.max,
154
- defaultValue: scaleRange.max,
147
+ value: controls.colorAxis.cmax,
148
+ step: 0.1,
149
+ min: controls.colorAxis.cmin,
150
+ max: dataset.controls.colorAxis.dmax,
155
151
  onChange: function onChange(e) {
156
- if (parseFloat(e.target.value) > dataRange.max) {
157
- e.target.value = dataRange.max.toFixed(1);
152
+ if (parseFloat(e.target.value) > dataset.controls.colorAxis.dmax) {
153
+ e.target.value = dataset.controls.colorAxis.dmax.toFixed(1);
158
154
  }
155
+ setControls(_objectSpread(_objectSpread({}, controls), {}, {
156
+ colorAxis: _objectSpread(_objectSpread({}, controls.colorAxis), {}, {
157
+ cmax: e.target.value
158
+ })
159
+ }));
159
160
  }
160
161
  }), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Button, {
161
162
  type: "submit",
@@ -163,55 +164,32 @@ function DotplotControls(_ref) {
163
164
  }, "Apply"), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Button, {
164
165
  variant: "outline-primary",
165
166
  onClick: function onClick() {
166
- var scale = {
167
- min: 0.0,
168
- max: dataRange.max.toFixed(1)
169
- };
170
- setScaleRange(scale);
167
+ dispatch({
168
+ type: "set.controls.colorAxis.crange",
169
+ cmin: dataset.controls.colorAxis.dmin,
170
+ cmax: dataset.controls.colorAxis.dmax
171
+ });
171
172
  }
172
173
  }, "Autoscale"))));
173
174
  }
174
175
  function Dotplot() {
175
176
  var dataset = (0, _DatasetContext.useDataset)();
176
- var colorscale = (0, _react.useRef)(dataset.colorscale);
177
- var _useState7 = (0, _react.useState)([]),
177
+ var dispatch = (0, _DatasetContext.useDatasetDispatch)();
178
+ var colorscale = (0, _react.useRef)(dataset.controls.colorScale);
179
+ var _useState3 = (0, _react.useState)([]),
180
+ _useState4 = _slicedToArray(_useState3, 2),
181
+ data = _useState4[0],
182
+ setData = _useState4[1];
183
+ var _useState5 = (0, _react.useState)({}),
184
+ _useState6 = _slicedToArray(_useState5, 2),
185
+ layout = _useState6[0],
186
+ setLayout = _useState6[1];
187
+ var _useState7 = (0, _react.useState)(false),
178
188
  _useState8 = _slicedToArray(_useState7, 2),
179
- data = _useState8[0],
180
- setData = _useState8[1];
181
- var _useState9 = (0, _react.useState)({}),
182
- _useState10 = _slicedToArray(_useState9, 2),
183
- layout = _useState10[0],
184
- setLayout = _useState10[1];
185
- var _useState11 = (0, _react.useState)(false),
186
- _useState12 = _slicedToArray(_useState11, 2),
187
- hasSelections = _useState12[0],
188
- setHasSelections = _useState12[1];
189
- var _useState13 = (0, _react.useState)(0.0),
190
- _useState14 = _slicedToArray(_useState13, 2),
191
- expressionCutoff = _useState14[0],
192
- setExpressionCutoff = _useState14[1];
193
- var _useState15 = (0, _react.useState)(false),
194
- _useState16 = _slicedToArray(_useState15, 2),
195
- meanOnlyExpressed = _useState16[0],
196
- setMeanOnlyExpressed = _useState16[1];
197
- var _useState17 = (0, _react.useState)(null),
198
- _useState18 = _slicedToArray(_useState17, 2),
199
- standardScale = _useState18[0],
200
- setStandardScale = _useState18[1];
201
- var _useState19 = (0, _react.useState)({
202
- min: 0.0,
203
- max: 0.0
204
- }),
205
- _useState20 = _slicedToArray(_useState19, 2),
206
- dataRange = _useState20[0],
207
- setDataRange = _useState20[1];
208
- var _useState21 = (0, _react.useState)({
209
- min: null,
210
- max: null
211
- }),
212
- _useState22 = _slicedToArray(_useState21, 2),
213
- scaleRange = _useState22[0],
214
- setScaleRange = _useState22[1];
189
+ hasSelections = _useState8[0],
190
+ setHasSelections = _useState8[1];
191
+ // @TODO: set default scale
192
+
215
193
  var updateColorscale = (0, _react.useCallback)(function (colorscale) {
216
194
  setLayout(function (l) {
217
195
  return _objectSpread(_objectSpread({}, l), {}, {
@@ -221,70 +199,74 @@ function Dotplot() {
221
199
  });
222
200
  });
223
201
  }, []);
224
- (0, _react.useEffect)(function () {
225
- console.log("fetchdata");
226
- if (dataset.selectedObs && dataset.selectedMultiVar.length) {
227
- setHasSelections(true);
228
- fetch(new URL("dotplot", process.env.REACT_APP_API_URL), {
229
- method: "POST",
230
- mode: "cors",
231
- headers: {
232
- "Content-Type": "application/json",
233
- Accept: "application/json"
234
- },
235
- body: JSON.stringify({
202
+ var update = (0, _react.useMemo)(function () {
203
+ var func = function func(abortController) {
204
+ if (dataset.selectedObs && dataset.selectedMultiVar.length) {
205
+ setHasSelections(true);
206
+ (0, _requests.fetchData)("dotplot", {
236
207
  url: dataset.url,
237
208
  selectedObs: dataset.selectedObs,
238
- selectedMultiVar: dataset.selectedMultiVar,
239
- expressionCutoff: expressionCutoff,
240
- meanOnlyExpressed: meanOnlyExpressed,
241
- standardScale: standardScale
242
- })
243
- }).then(function (response) {
244
- return response.json();
245
- }).then(function (data) {
246
- setData(data.data);
247
- setLayout(data.layout);
248
- setDataRange(data.range);
249
- setScaleRange(function (s) {
250
- return {
251
- min: 0.0,
252
- max: data.range.max.toFixed(1)
253
- };
209
+ selectedMultiVar: dataset.selectedMultiVar.map(function (i) {
210
+ return i.name;
211
+ }),
212
+ standardScale: dataset.controls.standardScale,
213
+ meanOnlyExpressed: dataset.controls.meanOnlyExpressed,
214
+ expressionCutoff: dataset.controls.expressionCutoff
215
+ }, abortController.signal).then(function (data) {
216
+ setData(data.data);
217
+ setLayout(data.layout);
218
+ dispatch({
219
+ type: "set.controls.colorAxis",
220
+ colorAxis: {
221
+ dmin: data.range.min.toFixed(1),
222
+ dmax: data.range.max.toFixed(1),
223
+ cmin: data.range.min.toFixed(1),
224
+ cmax: data.range.max.toFixed(1)
225
+ }
226
+ });
227
+ updateColorscale(colorscale.current);
228
+ }).catch(function (response) {
229
+ if (response.name !== "AbortError") {
230
+ response.json().then(function (json) {
231
+ console.log(json.message);
232
+ });
233
+ }
254
234
  });
255
- updateColorscale(colorscale.current);
256
- });
257
- } else {
258
- setHasSelections(false);
259
- }
260
- }, [dataset.url, dataset.selectedObs, dataset.selectedMultiVar, expressionCutoff, meanOnlyExpressed, standardScale, updateColorscale]);
235
+ } else {
236
+ setHasSelections(false);
237
+ }
238
+ };
239
+ // delay invoking the fetch function to avoid firing requests
240
+ // while dependencies might still be getting updated by the user
241
+ return _lodash.default.debounce(func, 500);
242
+ }, [dataset.url, dataset.selectedObs, dataset.selectedMultiVar, dataset.controls.standardScale, dataset.controls.meanOnlyExpressed, dataset.controls.expressionCutoff, updateColorscale, dispatch]);
243
+ (0, _react.useEffect)(function () {
244
+ // create an abort controller to pass into each fetch function
245
+ // to abort previous incompleted requests when a new request is fired
246
+ var abortController = new AbortController();
247
+ update(abortController);
248
+ return function () {
249
+ abortController.abort();
250
+ };
251
+ }, [update]);
261
252
  (0, _react.useEffect)(function () {
262
- colorscale.current = dataset.colorscale;
253
+ colorscale.current = dataset.controls.colorScale;
263
254
  updateColorscale(colorscale.current);
264
- }, [dataset.colorscale, updateColorscale]);
255
+ }, [dataset.controls.colorScale, updateColorscale]);
265
256
  (0, _react.useEffect)(function () {
266
257
  setLayout(function (l) {
267
258
  return _objectSpread(_objectSpread({}, l), {}, {
268
259
  coloraxis: _objectSpread(_objectSpread({}, l.coloraxis), {}, {
269
- cmin: scaleRange.min,
270
- cmax: scaleRange.max
260
+ cmin: dataset.controls.colorAxis.cmin,
261
+ cmax: dataset.controls.colorAxis.cmax
271
262
  })
272
263
  });
273
264
  });
274
- }, [scaleRange]);
265
+ }, [dataset.controls.colorAxis.cmin, dataset.controls.colorAxis.cmax]);
275
266
  if (hasSelections) {
276
267
  return /*#__PURE__*/_react.default.createElement("div", {
277
- className: "container text-center"
278
- }, /*#__PURE__*/_react.default.createElement("h5", null, dataset.url), /*#__PURE__*/_react.default.createElement(DotplotControls, {
279
- scaleRange: scaleRange,
280
- expressionCutoff: expressionCutoff,
281
- meanOnlyExpressed: meanOnlyExpressed,
282
- dataRange: dataRange,
283
- setScaleRange: setScaleRange,
284
- setExpressionCutoff: setExpressionCutoff,
285
- setMeanOnlyExpressed: setMeanOnlyExpressed,
286
- setStandardScale: setStandardScale
287
- }), /*#__PURE__*/_react.default.createElement(_reactPlotly.default, {
268
+ className: "cherita-dotplot"
269
+ }, /*#__PURE__*/_react.default.createElement(_reactPlotly.default, {
288
270
  data: data,
289
271
  layout: layout,
290
272
  useResizeHandler: true,
@@ -295,6 +277,6 @@ function Dotplot() {
295
277
  }));
296
278
  }
297
279
  return /*#__PURE__*/_react.default.createElement("div", {
298
- className: "h-100"
299
- }, /*#__PURE__*/_react.default.createElement("h5", null, dataset.url), /*#__PURE__*/_react.default.createElement("p", null, "Select OBS and VAR"));
280
+ className: "cherita-dotplot"
281
+ }, /*#__PURE__*/_react.default.createElement("p", null, "Select OBS and VAR"));
300
282
  }
@@ -10,8 +10,10 @@ require("bootstrap/dist/css/bootstrap.min.css");
10
10
  var _Dropdown = _interopRequireDefault(require("react-bootstrap/Dropdown"));
11
11
  var _react = _interopRequireWildcard(require("react"));
12
12
  var _reactPlotly = _interopRequireDefault(require("react-plotly.js"));
13
- var _DatasetContext = require("../context/DatasetContext");
14
- var _constants = require("../constants/constants");
13
+ var _lodash = _interopRequireDefault(require("lodash"));
14
+ var _DatasetContext = require("../../context/DatasetContext");
15
+ var _constants = require("../../constants/constants");
16
+ var _requests = require("../../utils/requests");
15
17
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
16
18
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
17
19
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -29,21 +31,14 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
29
31
  function HeatmapControls() {
30
32
  var dataset = (0, _DatasetContext.useDataset)();
31
33
  var dispatch = (0, _DatasetContext.useDatasetDispatch)();
32
- var _useState = (0, _react.useState)(dataset.colorscale),
33
- _useState2 = _slicedToArray(_useState, 2),
34
- active = _useState2[0],
35
- setActive = _useState2[1];
36
- (0, _react.useEffect)(function () {
37
- setActive(dataset.colorscale);
38
- }, [dataset.colorscale]);
39
34
  var colormapList = _constants.PLOTLY_COLORSCALES.map(function (item) {
40
35
  return /*#__PURE__*/_react.default.createElement(_Dropdown.default.Item, {
41
36
  key: item,
42
- active: active === item,
37
+ active: dataset.controls.colorScale === item,
43
38
  onClick: function onClick() {
44
39
  dispatch({
45
- type: "colorscaleSelected",
46
- colorscale: item
40
+ type: "set.controls.colorScale",
41
+ colorScale: item
47
42
  });
48
43
  }
49
44
  }, item);
@@ -51,67 +46,78 @@ function HeatmapControls() {
51
46
  return /*#__PURE__*/_react.default.createElement(_Dropdown.default, null, /*#__PURE__*/_react.default.createElement(_Dropdown.default.Toggle, {
52
47
  id: "dropdownColorscale",
53
48
  variant: "light"
54
- }, dataset.colorscale), /*#__PURE__*/_react.default.createElement(_Dropdown.default.Menu, null, colormapList));
49
+ }, dataset.controls.colorScale), /*#__PURE__*/_react.default.createElement(_Dropdown.default.Menu, null, colormapList));
55
50
  }
56
51
  function Heatmap() {
57
52
  var dataset = (0, _DatasetContext.useDataset)();
58
- var colorscale = (0, _react.useRef)(dataset.colorscale);
59
- var _useState3 = (0, _react.useState)([]),
53
+ var colorscale = (0, _react.useRef)(dataset.controls.colorScale);
54
+ var _useState = (0, _react.useState)([]),
55
+ _useState2 = _slicedToArray(_useState, 2),
56
+ data = _useState2[0],
57
+ setData = _useState2[1];
58
+ var _useState3 = (0, _react.useState)({}),
60
59
  _useState4 = _slicedToArray(_useState3, 2),
61
- data = _useState4[0],
62
- setData = _useState4[1];
63
- var _useState5 = (0, _react.useState)({}),
60
+ layout = _useState4[0],
61
+ setLayout = _useState4[1];
62
+ var _useState5 = (0, _react.useState)(false),
64
63
  _useState6 = _slicedToArray(_useState5, 2),
65
- layout = _useState6[0],
66
- setLayout = _useState6[1];
67
- var _useState7 = (0, _react.useState)(false),
68
- _useState8 = _slicedToArray(_useState7, 2),
69
- hasSelections = _useState8[0],
70
- setHasSelections = _useState8[1];
64
+ hasSelections = _useState6[0],
65
+ setHasSelections = _useState6[1];
71
66
  var updateColorscale = (0, _react.useCallback)(function (colorscale) {
72
- setData(function (d) {
73
- return d.map(function (i) {
74
- return _objectSpread(_objectSpread({}, i), {}, {
67
+ setLayout(function (l) {
68
+ return _objectSpread(_objectSpread({}, l), {}, {
69
+ coloraxis: _objectSpread(_objectSpread({}, l.coloraxis), {}, {
75
70
  colorscale: colorscale
76
- });
71
+ })
77
72
  });
78
73
  });
79
74
  }, []);
80
- (0, _react.useEffect)(function () {
81
- if (dataset.selectedObs && dataset.selectedMultiVar.length) {
82
- setHasSelections(true);
83
- fetch(new URL("heatmap", process.env.REACT_APP_API_URL), {
84
- method: "POST",
85
- mode: "cors",
86
- headers: {
87
- "Content-Type": "application/json",
88
- Accept: "application/json"
89
- },
90
- body: JSON.stringify({
75
+ var update = (0, _react.useMemo)(function () {
76
+ var func = function func(abortController) {
77
+ if (dataset.selectedObs && dataset.selectedMultiVar.length) {
78
+ setHasSelections(true);
79
+ (0, _requests.fetchData)("heatmap", {
91
80
  url: dataset.url,
92
81
  selectedObs: dataset.selectedObs,
93
- selectedMultiVar: dataset.selectedMultiVar
94
- })
95
- }).then(function (response) {
96
- return response.json();
97
- }).then(function (data) {
98
- setData(data.data);
99
- setLayout(data.layout);
100
- updateColorscale(colorscale.current);
101
- });
102
- } else {
103
- setHasSelections(false);
104
- }
105
- }, [dataset.url, dataset.selectedObs, dataset.selectedMultiVar, updateColorscale]);
82
+ selectedMultiVar: dataset.selectedMultiVar.map(function (i) {
83
+ return i.name;
84
+ })
85
+ }, abortController.signal).then(function (data) {
86
+ setData(data.data);
87
+ setLayout(data.layout);
88
+ updateColorscale(colorscale.current);
89
+ }).catch(function (response) {
90
+ if (response.name !== "AbortError") {
91
+ response.json().then(function (json) {
92
+ console.log(json.message);
93
+ });
94
+ }
95
+ });
96
+ } else {
97
+ setHasSelections(false);
98
+ }
99
+ };
100
+ // delay invoking the fetch function to avoid firing requests
101
+ // while dependencies might still be getting updated by the user
102
+ return _lodash.default.debounce(func, 500);
103
+ }, [dataset.selectedMultiVar, dataset.selectedObs, dataset.url, updateColorscale]);
104
+ (0, _react.useEffect)(function () {
105
+ // create an abort controller to pass into each fetch function
106
+ // to abort previous incompleted requests when a new request is fired
107
+ var abortController = new AbortController();
108
+ update(abortController);
109
+ return function () {
110
+ abortController.abort();
111
+ };
112
+ }, [update]);
106
113
  (0, _react.useEffect)(function () {
107
- console.log("update colorscale");
108
- colorscale.current = dataset.colorscale;
114
+ colorscale.current = dataset.controls.colorScale;
109
115
  updateColorscale(colorscale.current);
110
- }, [dataset.colorscale, updateColorscale]);
116
+ }, [dataset.controls.colorScale, updateColorscale]);
111
117
  if (hasSelections) {
112
118
  return /*#__PURE__*/_react.default.createElement("div", {
113
- className: "container text-center"
114
- }, /*#__PURE__*/_react.default.createElement("h5", null, dataset.url), /*#__PURE__*/_react.default.createElement(HeatmapControls, null), /*#__PURE__*/_react.default.createElement(_reactPlotly.default, {
119
+ className: "cherita-heatmap"
120
+ }, /*#__PURE__*/_react.default.createElement(_reactPlotly.default, {
115
121
  data: data,
116
122
  layout: layout,
117
123
  useResizeHandler: true,
@@ -122,6 +128,6 @@ function Heatmap() {
122
128
  }));
123
129
  }
124
130
  return /*#__PURE__*/_react.default.createElement("div", {
125
- className: "h-100"
126
- }, /*#__PURE__*/_react.default.createElement("h5", null, dataset.url), /*#__PURE__*/_react.default.createElement("p", null, "Select OBS and VAR"));
131
+ className: "cherita-heatmap"
132
+ }, /*#__PURE__*/_react.default.createElement("p", null, "Select OBS and VAR"));
127
133
  }