@haniffalab/cherita-react 0.1.12 → 0.2.0-dev.2024-02-12.9498443

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.
@@ -10,11 +10,11 @@ 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 _lodash = _interopRequireDefault(require("lodash"));
14
13
  var _DatasetContext = require("../../context/DatasetContext");
15
14
  var _constants = require("../../constants/constants");
16
15
  var _requests = require("../../utils/requests");
17
16
  var _reactBootstrap = require("react-bootstrap");
17
+ var _LoadingSpinner = require("../../utils/LoadingSpinner");
18
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); }
19
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; }
20
20
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -173,6 +173,7 @@ function DotplotControls() {
173
173
  }, "Autoscale"))));
174
174
  }
175
175
  function Dotplot() {
176
+ var ENDPOINT = "dotplot";
176
177
  var dataset = (0, _DatasetContext.useDataset)();
177
178
  var dispatch = (0, _DatasetContext.useDatasetDispatch)();
178
179
  var colorscale = (0, _react.useRef)(dataset.controls.colorScale);
@@ -188,8 +189,40 @@ function Dotplot() {
188
189
  _useState8 = _slicedToArray(_useState7, 2),
189
190
  hasSelections = _useState8[0],
190
191
  setHasSelections = _useState8[1];
192
+ var _useState9 = (0, _react.useState)({
193
+ url: dataset.url,
194
+ selectedObs: dataset.selectedObs,
195
+ selectedMultiVar: dataset.selectedMultiVar.map(function (i) {
196
+ return i.name;
197
+ }),
198
+ standardScale: dataset.controls.standardScale,
199
+ meanOnlyExpressed: dataset.controls.meanOnlyExpressed,
200
+ expressionCutoff: dataset.controls.expressionCutoff
201
+ }),
202
+ _useState10 = _slicedToArray(_useState9, 2),
203
+ params = _useState10[0],
204
+ setParams = _useState10[1];
191
205
  // @TODO: set default scale
192
206
 
207
+ (0, _react.useEffect)(function () {
208
+ if (dataset.selectedObs && dataset.selectedMultiVar.length) {
209
+ setHasSelections(true);
210
+ } else {
211
+ setHasSelections(false);
212
+ }
213
+ setParams(function (p) {
214
+ return _objectSpread(_objectSpread({}, p), {}, {
215
+ url: dataset.url,
216
+ selectedObs: dataset.selectedObs,
217
+ selectedMultiVar: dataset.selectedMultiVar.map(function (i) {
218
+ return i.name;
219
+ }),
220
+ standardScale: dataset.controls.standardScale,
221
+ meanOnlyExpressed: dataset.controls.meanOnlyExpressed,
222
+ expressionCutoff: dataset.controls.expressionCutoff
223
+ });
224
+ });
225
+ }, [dataset.url, dataset.selectedObs, dataset.selectedMultiVar, dataset.controls.standardScale, dataset.controls.meanOnlyExpressed, dataset.controls.expressionCutoff]);
193
226
  var updateColorscale = (0, _react.useCallback)(function (colorscale) {
194
227
  setLayout(function (l) {
195
228
  return _objectSpread(_objectSpread({}, l), {}, {
@@ -199,56 +232,28 @@ function Dotplot() {
199
232
  });
200
233
  });
201
234
  }, []);
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", {
207
- url: dataset.url,
208
- selectedObs: dataset.selectedObs,
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
- }
234
- });
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]);
235
+ var _useDebouncedFetch = (0, _requests.useDebouncedFetch)(ENDPOINT, params, 500, {
236
+ enabled: !!params.selectedObs && !!params.selectedMultiVar.length
237
+ }),
238
+ fetchedData = _useDebouncedFetch.fetchedData,
239
+ isPending = _useDebouncedFetch.isPending,
240
+ serverError = _useDebouncedFetch.serverError;
243
241
  (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]);
242
+ if (hasSelections && !isPending && !serverError) {
243
+ setData(fetchedData.data);
244
+ setLayout(fetchedData.layout);
245
+ dispatch({
246
+ type: "set.controls.colorAxis",
247
+ colorAxis: {
248
+ dmin: fetchedData.range.min.toFixed(1),
249
+ dmax: fetchedData.range.max.toFixed(1),
250
+ cmin: fetchedData.range.min.toFixed(1),
251
+ cmax: fetchedData.range.max.toFixed(1)
252
+ }
253
+ });
254
+ updateColorscale(colorscale.current);
255
+ }
256
+ }, [fetchedData, isPending, serverError, hasSelections, dispatch, updateColorscale]);
252
257
  (0, _react.useEffect)(function () {
253
258
  colorscale.current = dataset.controls.colorScale;
254
259
  updateColorscale(colorscale.current);
@@ -263,20 +268,28 @@ function Dotplot() {
263
268
  });
264
269
  });
265
270
  }, [dataset.controls.colorAxis.cmin, dataset.controls.colorAxis.cmax]);
266
- if (hasSelections) {
271
+ if (!serverError) {
272
+ if (hasSelections) {
273
+ return /*#__PURE__*/_react.default.createElement("div", {
274
+ className: "cherita-dotplot position-relative"
275
+ }, isPending && /*#__PURE__*/_react.default.createElement(_LoadingSpinner.LoadingSpinner, null), /*#__PURE__*/_react.default.createElement(_reactPlotly.default, {
276
+ data: data,
277
+ layout: layout,
278
+ useResizeHandler: true,
279
+ style: {
280
+ maxWidth: "100%",
281
+ maxHeight: "100%"
282
+ }
283
+ }));
284
+ }
267
285
  return /*#__PURE__*/_react.default.createElement("div", {
268
286
  className: "cherita-dotplot"
269
- }, /*#__PURE__*/_react.default.createElement(_reactPlotly.default, {
270
- data: data,
271
- layout: layout,
272
- useResizeHandler: true,
273
- style: {
274
- maxWidth: "100%",
275
- maxHeight: "100%"
276
- }
277
- }));
287
+ }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Alert, {
288
+ variant: "light"
289
+ }, "Select features and a category"));
290
+ } else {
291
+ return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Alert, {
292
+ variant: "danger"
293
+ }, serverError.message));
278
294
  }
279
- return /*#__PURE__*/_react.default.createElement("div", {
280
- className: "cherita-dotplot"
281
- }, /*#__PURE__*/_react.default.createElement("p", null, "Select OBS and VAR"));
282
295
  }
@@ -7,16 +7,16 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports.Heatmap = Heatmap;
8
8
  exports.HeatmapControls = HeatmapControls;
9
9
  require("bootstrap/dist/css/bootstrap.min.css");
10
- var _Dropdown = _interopRequireDefault(require("react-bootstrap/Dropdown"));
10
+ var _reactBootstrap = require("react-bootstrap");
11
11
  var _react = _interopRequireWildcard(require("react"));
12
12
  var _reactPlotly = _interopRequireDefault(require("react-plotly.js"));
13
- var _lodash = _interopRequireDefault(require("lodash"));
14
13
  var _DatasetContext = require("../../context/DatasetContext");
15
14
  var _constants = require("../../constants/constants");
16
15
  var _requests = require("../../utils/requests");
16
+ var _LoadingSpinner = require("../../utils/LoadingSpinner");
17
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
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); }
18
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; }
19
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
20
20
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
21
21
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
22
22
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
@@ -32,7 +32,7 @@ function HeatmapControls() {
32
32
  var dataset = (0, _DatasetContext.useDataset)();
33
33
  var dispatch = (0, _DatasetContext.useDatasetDispatch)();
34
34
  var colormapList = _constants.PLOTLY_COLORSCALES.map(function (item) {
35
- return /*#__PURE__*/_react.default.createElement(_Dropdown.default.Item, {
35
+ return /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown.Item, {
36
36
  key: item,
37
37
  active: dataset.controls.colorScale === item,
38
38
  onClick: function onClick() {
@@ -43,12 +43,13 @@ function HeatmapControls() {
43
43
  }
44
44
  }, item);
45
45
  });
46
- return /*#__PURE__*/_react.default.createElement(_Dropdown.default, null, /*#__PURE__*/_react.default.createElement(_Dropdown.default.Toggle, {
46
+ return /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown.Toggle, {
47
47
  id: "dropdownColorscale",
48
48
  variant: "light"
49
- }, dataset.controls.colorScale), /*#__PURE__*/_react.default.createElement(_Dropdown.default.Menu, null, colormapList));
49
+ }, dataset.controls.colorScale), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown.Menu, null, colormapList));
50
50
  }
51
51
  function Heatmap() {
52
+ var ENDPOINT = "heatmap";
52
53
  var dataset = (0, _DatasetContext.useDataset)();
53
54
  var colorscale = (0, _react.useRef)(dataset.controls.colorScale);
54
55
  var _useState = (0, _react.useState)([]),
@@ -63,6 +64,32 @@ function Heatmap() {
63
64
  _useState6 = _slicedToArray(_useState5, 2),
64
65
  hasSelections = _useState6[0],
65
66
  setHasSelections = _useState6[1];
67
+ var _useState7 = (0, _react.useState)({
68
+ url: dataset.url,
69
+ selectedObs: dataset.selectedObs,
70
+ selectedMultiVar: dataset.selectedMultiVar.map(function (i) {
71
+ return i.name;
72
+ })
73
+ }),
74
+ _useState8 = _slicedToArray(_useState7, 2),
75
+ params = _useState8[0],
76
+ setParams = _useState8[1];
77
+ (0, _react.useEffect)(function () {
78
+ if (dataset.selectedObs && dataset.selectedMultiVar.length) {
79
+ setHasSelections(true);
80
+ } else {
81
+ setHasSelections(false);
82
+ }
83
+ setParams(function (p) {
84
+ return _objectSpread(_objectSpread({}, p), {}, {
85
+ url: dataset.url,
86
+ selectedObs: dataset.selectedObs,
87
+ selectedMultiVar: dataset.selectedMultiVar.map(function (i) {
88
+ return i.name;
89
+ })
90
+ });
91
+ });
92
+ }, [dataset.selectedMultiVar, dataset.selectedObs, dataset.url]);
66
93
  var updateColorscale = (0, _react.useCallback)(function (colorscale) {
67
94
  setLayout(function (l) {
68
95
  return _objectSpread(_objectSpread({}, l), {}, {
@@ -72,62 +99,45 @@ function Heatmap() {
72
99
  });
73
100
  });
74
101
  }, []);
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", {
80
- url: dataset.url,
81
- selectedObs: dataset.selectedObs,
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]);
102
+ var _useDebouncedFetch = (0, _requests.useDebouncedFetch)(ENDPOINT, params, 500, {
103
+ enabled: !!params.selectedObs && !!params.selectedMultiVar.length
104
+ }),
105
+ fetchedData = _useDebouncedFetch.fetchedData,
106
+ isPending = _useDebouncedFetch.isPending,
107
+ serverError = _useDebouncedFetch.serverError;
104
108
  (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]);
109
+ if (hasSelections && !isPending && !serverError) {
110
+ setData(fetchedData.data);
111
+ setLayout(fetchedData.layout);
112
+ updateColorscale(colorscale.current);
113
+ }
114
+ }, [fetchedData, hasSelections, isPending, serverError, updateColorscale]);
113
115
  (0, _react.useEffect)(function () {
114
116
  colorscale.current = dataset.controls.colorScale;
115
117
  updateColorscale(colorscale.current);
116
118
  }, [dataset.controls.colorScale, updateColorscale]);
117
- if (hasSelections) {
119
+ if (!serverError) {
120
+ if (hasSelections) {
121
+ return /*#__PURE__*/_react.default.createElement("div", {
122
+ className: "cherita-heatmap position-relative"
123
+ }, isPending && /*#__PURE__*/_react.default.createElement(_LoadingSpinner.LoadingSpinner, null), /*#__PURE__*/_react.default.createElement(_reactPlotly.default, {
124
+ data: data,
125
+ layout: layout,
126
+ useResizeHandler: true,
127
+ style: {
128
+ maxWidth: "100%",
129
+ maxHeight: "100%"
130
+ }
131
+ }));
132
+ }
118
133
  return /*#__PURE__*/_react.default.createElement("div", {
119
134
  className: "cherita-heatmap"
120
- }, /*#__PURE__*/_react.default.createElement(_reactPlotly.default, {
121
- data: data,
122
- layout: layout,
123
- useResizeHandler: true,
124
- style: {
125
- maxWidth: "100%",
126
- maxHeight: "100%"
127
- }
128
- }));
135
+ }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Alert, {
136
+ variant: "light"
137
+ }, "Select features and a category"));
138
+ } else {
139
+ return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Alert, {
140
+ variant: "danger"
141
+ }, serverError.message));
129
142
  }
130
- return /*#__PURE__*/_react.default.createElement("div", {
131
- className: "cherita-heatmap"
132
- }, /*#__PURE__*/_react.default.createElement("p", null, "Select OBS and VAR"));
133
143
  }
@@ -7,17 +7,16 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports.Matrixplot = Matrixplot;
8
8
  exports.MatrixplotControls = MatrixplotControls;
9
9
  require("bootstrap/dist/css/bootstrap.min.css");
10
- var _Dropdown = _interopRequireDefault(require("react-bootstrap/Dropdown"));
11
10
  var _react = _interopRequireWildcard(require("react"));
12
11
  var _reactPlotly = _interopRequireDefault(require("react-plotly.js"));
13
- var _lodash = _interopRequireDefault(require("lodash"));
14
12
  var _DatasetContext = require("../../context/DatasetContext");
15
13
  var _constants = require("../../constants/constants");
16
14
  var _reactBootstrap = require("react-bootstrap");
17
15
  var _requests = require("../../utils/requests");
16
+ var _LoadingSpinner = require("../../utils/LoadingSpinner");
17
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18
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); }
19
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; }
20
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
20
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
22
21
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
23
22
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
@@ -33,7 +32,7 @@ function MatrixplotControls() {
33
32
  var dataset = (0, _DatasetContext.useDataset)();
34
33
  var dispatch = (0, _DatasetContext.useDatasetDispatch)();
35
34
  var colorScaleList = _constants.PLOTLY_COLORSCALES.map(function (item) {
36
- return /*#__PURE__*/_react.default.createElement(_Dropdown.default.Item, {
35
+ return /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown.Item, {
37
36
  key: item,
38
37
  active: dataset.controls.colorScale === item,
39
38
  onClick: function onClick() {
@@ -45,7 +44,7 @@ function MatrixplotControls() {
45
44
  }, item);
46
45
  });
47
46
  var standardScaleList = _constants.MATRIXPLOT_STANDARDSCALES.map(function (item) {
48
- return /*#__PURE__*/_react.default.createElement(_Dropdown.default.Item, {
47
+ return /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown.Item, {
49
48
  key: item.value,
50
49
  active: dataset.controls.standardScale === item.name,
51
50
  onClick: function onClick() {
@@ -56,15 +55,16 @@ function MatrixplotControls() {
56
55
  }
57
56
  }, item.name);
58
57
  });
59
- 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, {
58
+ return /*#__PURE__*/_react.default.createElement(_reactBootstrap.ButtonToolbar, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.ButtonGroup, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown.Toggle, {
60
59
  id: "dropdownColorscale",
61
60
  variant: "light"
62
- }, 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, {
61
+ }, dataset.controls.colorScale), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown.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(_reactBootstrap.Dropdown, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown.Toggle, {
63
62
  id: "dropdownStandardScale",
64
63
  variant: "light"
65
- }, dataset.controls.standardScale), /*#__PURE__*/_react.default.createElement(_Dropdown.default.Menu, null, standardScaleList)))));
64
+ }, dataset.controls.standardScale), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown.Menu, null, standardScaleList)))));
66
65
  }
67
66
  function Matrixplot() {
67
+ var ENDPOINT = "matrixplot";
68
68
  var dataset = (0, _DatasetContext.useDataset)();
69
69
  var colorscale = (0, _react.useRef)(dataset.controls.colorScale);
70
70
  var _useState = (0, _react.useState)([]),
@@ -79,6 +79,34 @@ function Matrixplot() {
79
79
  _useState6 = _slicedToArray(_useState5, 2),
80
80
  hasSelections = _useState6[0],
81
81
  setHasSelections = _useState6[1];
82
+ var _useState7 = (0, _react.useState)({
83
+ url: dataset.url,
84
+ selectedObs: dataset.selectedObs,
85
+ selectedMultiVar: dataset.selectedMultiVar.map(function (i) {
86
+ return i.name;
87
+ }),
88
+ standardScale: dataset.controls.standardScale
89
+ }),
90
+ _useState8 = _slicedToArray(_useState7, 2),
91
+ params = _useState8[0],
92
+ setParams = _useState8[1];
93
+ (0, _react.useEffect)(function () {
94
+ if (dataset.selectedObs && dataset.selectedMultiVar.length) {
95
+ setHasSelections(true);
96
+ } else {
97
+ setHasSelections(false);
98
+ }
99
+ setParams(function (p) {
100
+ return _objectSpread(_objectSpread({}, p), {}, {
101
+ url: dataset.url,
102
+ selectedObs: dataset.selectedObs,
103
+ selectedMultiVar: dataset.selectedMultiVar.map(function (i) {
104
+ return i.name;
105
+ }),
106
+ standardScale: dataset.controls.standardScale
107
+ });
108
+ });
109
+ }, [dataset.controls.standardScale, dataset.selectedMultiVar, dataset.selectedObs, dataset.url]);
82
110
  var updateColorscale = (0, _react.useCallback)(function (colorscale) {
83
111
  setLayout(function (l) {
84
112
  return _objectSpread(_objectSpread({}, l), {}, {
@@ -88,63 +116,45 @@ function Matrixplot() {
88
116
  });
89
117
  });
90
118
  }, []);
91
- var update = (0, _react.useMemo)(function () {
92
- var func = function func(abortController) {
93
- if (dataset.selectedObs && dataset.selectedMultiVar.length) {
94
- setHasSelections(true);
95
- (0, _requests.fetchData)("matrixplot", {
96
- url: dataset.url,
97
- selectedObs: dataset.selectedObs,
98
- selectedMultiVar: dataset.selectedMultiVar.map(function (i) {
99
- return i.name;
100
- }),
101
- standardScale: dataset.controls.standardScale
102
- }, abortController.signal).then(function (data) {
103
- setData(data.data);
104
- setLayout(data.layout);
105
- updateColorscale(colorscale.current);
106
- }).catch(function (response) {
107
- if (response.name !== "AbortError") {
108
- response.json().then(function (json) {
109
- console.log(json.message);
110
- });
111
- }
112
- });
113
- } else {
114
- setHasSelections(false);
115
- }
116
- };
117
- // delay invoking the fetch function to avoid firing requests
118
- // while dependencies might still be getting updated by the user
119
- return _lodash.default.debounce(func, 500);
120
- }, [dataset.url, dataset.selectedObs, dataset.selectedMultiVar, dataset.controls.standardScale, updateColorscale]);
119
+ var _useDebouncedFetch = (0, _requests.useDebouncedFetch)(ENDPOINT, params, 500, {
120
+ enabled: !!params.selectedObs && !!params.selectedMultiVar.length
121
+ }),
122
+ fetchedData = _useDebouncedFetch.fetchedData,
123
+ isPending = _useDebouncedFetch.isPending,
124
+ serverError = _useDebouncedFetch.serverError;
121
125
  (0, _react.useEffect)(function () {
122
- // create an abort controller to pass into each fetch function
123
- // to abort previous incompleted requests when a new request is fired
124
- var abortController = new AbortController();
125
- update(abortController);
126
- return function () {
127
- abortController.abort();
128
- };
129
- }, [update]);
126
+ if (hasSelections && !isPending && !serverError) {
127
+ setData(fetchedData.data);
128
+ setLayout(fetchedData.layout);
129
+ updateColorscale(colorscale.current);
130
+ }
131
+ }, [fetchedData, hasSelections, isPending, serverError, updateColorscale]);
130
132
  (0, _react.useEffect)(function () {
131
133
  colorscale.current = dataset.controls.colorScale;
132
134
  updateColorscale(colorscale.current);
133
135
  }, [dataset.controls.colorScale, updateColorscale]);
134
- if (hasSelections) {
136
+ if (!serverError) {
137
+ if (hasSelections) {
138
+ return /*#__PURE__*/_react.default.createElement("div", {
139
+ className: "cherita-matrixplot position-relative"
140
+ }, isPending && /*#__PURE__*/_react.default.createElement(_LoadingSpinner.LoadingSpinner, null), /*#__PURE__*/_react.default.createElement(_reactPlotly.default, {
141
+ data: data,
142
+ layout: layout,
143
+ useResizeHandler: true,
144
+ style: {
145
+ maxWidth: "100%",
146
+ maxHeight: "100%"
147
+ }
148
+ }));
149
+ }
135
150
  return /*#__PURE__*/_react.default.createElement("div", {
136
151
  className: "cherita-matrixplot"
137
- }, /*#__PURE__*/_react.default.createElement(_reactPlotly.default, {
138
- data: data,
139
- layout: layout,
140
- useResizeHandler: true,
141
- style: {
142
- maxWidth: "100%",
143
- maxHeight: "100%"
144
- }
145
- }));
152
+ }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Alert, {
153
+ variant: "light"
154
+ }, "Select features and a category"));
155
+ } else {
156
+ return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Alert, {
157
+ variant: "danger"
158
+ }, serverError.message));
146
159
  }
147
- return /*#__PURE__*/_react.default.createElement("div", {
148
- className: "cherita-matrixplot"
149
- }, /*#__PURE__*/_react.default.createElement("p", null, "Select OBS and VAR"));
150
160
  }