@haniffalab/cherita-react 1.0.0 → 1.1.0

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 (106) hide show
  1. package/LICENSE +1 -1
  2. package/dist/{components → cjs/components}/full-page/FullPage.js +32 -22
  3. package/dist/{components → cjs/components}/full-page/FullPagePseudospatial.js +7 -6
  4. package/dist/{components → cjs/components}/obs-list/ObsItem.js +88 -77
  5. package/dist/{components → cjs/components}/obs-list/ObsList.js +133 -50
  6. package/dist/cjs/components/obs-list/ObsToolbar.js +24 -0
  7. package/dist/{components → cjs/components}/obsm-list/ObsmList.js +8 -5
  8. package/dist/{components → cjs/components}/offcanvas/index.js +24 -20
  9. package/dist/{components → cjs/components}/pseudospatial/Pseudospatial.js +10 -9
  10. package/dist/{components → cjs/components}/pseudospatial/PseudospatialToolbar.js +4 -3
  11. package/dist/{components → cjs/components}/scatterplot/Scatterplot.js +33 -24
  12. package/dist/{components → cjs/components}/scatterplot/SpatialControls.js +43 -42
  13. package/dist/cjs/components/scatterplot/Toolbox.js +62 -0
  14. package/dist/{components → cjs/components}/search-bar/SearchBar.js +24 -7
  15. package/dist/{components → cjs/components}/search-bar/SearchResults.js +13 -17
  16. package/dist/{components → cjs/components}/var-list/VarItem.js +38 -29
  17. package/dist/{components → cjs/components}/var-list/VarList.js +59 -31
  18. package/dist/{components → cjs/components}/var-list/VarListToolbar.js +18 -14
  19. package/dist/{components → cjs/components}/var-list/VarSet.js +24 -20
  20. package/dist/{components → cjs/components}/violin/Violin.js +4 -3
  21. package/dist/{constants → cjs/constants}/constants.js +6 -2
  22. package/dist/{context → cjs/context}/DatasetContext.js +12 -11
  23. package/dist/{context → cjs/context}/FilterContext.js +4 -3
  24. package/dist/{context → cjs/context}/ZarrDataContext.js +4 -3
  25. package/dist/{helpers → cjs/helpers}/color-helper.js +12 -11
  26. package/dist/{helpers → cjs/helpers}/map-helper.js +8 -7
  27. package/dist/{helpers → cjs/helpers}/zarr-helper.js +30 -38
  28. package/dist/{utils → cjs/utils}/Filter.js +1 -1
  29. package/dist/{utils → cjs/utils}/Histogram.js +12 -8
  30. package/dist/{utils → cjs/utils}/ImageViewer.js +6 -5
  31. package/dist/{utils → cjs/utils}/Legend.js +8 -7
  32. package/dist/{utils → cjs/utils}/LoadingIndicators.js +5 -4
  33. package/dist/cjs/utils/Skeleton.js +19 -0
  34. package/dist/{utils → cjs/utils}/VirtualizedList.js +10 -9
  35. package/dist/{utils → cjs/utils}/requests.js +37 -39
  36. package/dist/{utils → cjs/utils}/string.js +9 -4
  37. package/dist/{utils → cjs/utils}/zarrData.js +12 -4
  38. package/dist/css/cherita.css +147 -152
  39. package/dist/css/cherita.css.map +1 -1
  40. package/dist/esm/components/dotplot/Dotplot.js +135 -0
  41. package/dist/esm/components/dotplot/DotplotControls.js +148 -0
  42. package/dist/esm/components/full-page/FullPage.js +143 -0
  43. package/dist/esm/components/full-page/FullPagePseudospatial.js +151 -0
  44. package/dist/esm/components/heatmap/Heatmap.js +105 -0
  45. package/dist/esm/components/heatmap/HeatmapControls.js +23 -0
  46. package/dist/esm/components/matrixplot/Matrixplot.js +107 -0
  47. package/dist/esm/components/matrixplot/MatrixplotControls.js +38 -0
  48. package/dist/esm/components/obs-list/ObsItem.js +484 -0
  49. package/dist/esm/components/obs-list/ObsList.js +338 -0
  50. package/dist/esm/components/obs-list/ObsToolbar.js +17 -0
  51. package/dist/esm/components/obsm-list/ObsmList.js +75 -0
  52. package/dist/esm/components/offcanvas/index.js +67 -0
  53. package/dist/esm/components/pseudospatial/Pseudospatial.js +228 -0
  54. package/dist/esm/components/pseudospatial/PseudospatialToolbar.js +123 -0
  55. package/dist/esm/components/scatterplot/Scatterplot.js +394 -0
  56. package/dist/esm/components/scatterplot/ScatterplotControls.js +71 -0
  57. package/dist/esm/components/scatterplot/SpatialControls.js +140 -0
  58. package/dist/esm/components/scatterplot/Toolbox.js +55 -0
  59. package/dist/esm/components/search-bar/SearchBar.js +90 -0
  60. package/dist/esm/components/search-bar/SearchResults.js +139 -0
  61. package/dist/esm/components/var-list/VarItem.js +254 -0
  62. package/dist/esm/components/var-list/VarList.js +291 -0
  63. package/dist/esm/components/var-list/VarListToolbar.js +87 -0
  64. package/dist/esm/components/var-list/VarSet.js +194 -0
  65. package/dist/esm/components/violin/Violin.js +141 -0
  66. package/dist/esm/components/violin/ViolinControls.js +24 -0
  67. package/dist/esm/constants/colorscales.js +22 -0
  68. package/dist/esm/constants/constants.js +88 -0
  69. package/dist/esm/context/DatasetContext.js +571 -0
  70. package/dist/esm/context/FilterContext.js +48 -0
  71. package/dist/esm/context/ZarrDataContext.js +26 -0
  72. package/dist/esm/helpers/color-helper.js +66 -0
  73. package/dist/esm/helpers/map-helper.js +53 -0
  74. package/dist/esm/helpers/zarr-helper.js +111 -0
  75. package/dist/esm/index.js +22 -0
  76. package/dist/esm/utils/Filter.js +147 -0
  77. package/dist/esm/utils/Histogram.js +44 -0
  78. package/dist/esm/utils/ImageViewer.js +27 -0
  79. package/dist/esm/utils/Legend.js +58 -0
  80. package/dist/esm/utils/LoadingIndicators.js +22 -0
  81. package/dist/esm/utils/Skeleton.js +12 -0
  82. package/dist/esm/utils/VirtualizedList.js +55 -0
  83. package/dist/esm/utils/errors.js +47 -0
  84. package/dist/esm/utils/requests.js +102 -0
  85. package/dist/esm/utils/search.js +39 -0
  86. package/dist/esm/utils/string.js +59 -0
  87. package/dist/esm/utils/zarrData.js +102 -0
  88. package/package.json +19 -7
  89. package/scss/cherita.scss +19 -50
  90. package/scss/components/accordions.scss +32 -0
  91. package/scss/components/layouts.scss +2 -1
  92. package/scss/components/lists.scss +14 -0
  93. package/dist/components/obs-list/ObsToolbar.js +0 -64
  94. package/dist/components/scatterplot/Toolbox.js +0 -31
  95. /package/dist/{components → cjs/components}/dotplot/Dotplot.js +0 -0
  96. /package/dist/{components → cjs/components}/dotplot/DotplotControls.js +0 -0
  97. /package/dist/{components → cjs/components}/heatmap/Heatmap.js +0 -0
  98. /package/dist/{components → cjs/components}/heatmap/HeatmapControls.js +0 -0
  99. /package/dist/{components → cjs/components}/matrixplot/Matrixplot.js +0 -0
  100. /package/dist/{components → cjs/components}/matrixplot/MatrixplotControls.js +0 -0
  101. /package/dist/{components → cjs/components}/scatterplot/ScatterplotControls.js +0 -0
  102. /package/dist/{components → cjs/components}/violin/ViolinControls.js +0 -0
  103. /package/dist/{constants → cjs/constants}/colorscales.js +0 -0
  104. /package/dist/{index.js → cjs/index.js} +0 -0
  105. /package/dist/{utils → cjs/utils}/errors.js +0 -0
  106. /package/dist/{utils → cjs/utils}/search.js +0 -0
package/LICENSE CHANGED
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
18
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
19
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
21
+ SOFTWARE.
@@ -23,11 +23,12 @@ var _Violin = require("../violin/Violin");
23
23
  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); }
24
24
  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; }
25
25
  function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
26
- function FullPage({
27
- children,
28
- varMode = _constants.SELECTION_MODES.SINGLE,
29
- ...props
30
- }) {
26
+ function FullPage(_ref) {
27
+ let {
28
+ children,
29
+ varMode = _constants.SELECTION_MODES.SINGLE,
30
+ ...props
31
+ } = _ref;
31
32
  const appRef = (0, _react.useRef)();
32
33
  const [appDimensions, setAppDimensions] = (0, _react.useState)({
33
34
  width: 0,
@@ -37,6 +38,7 @@ function FullPage({
37
38
  const [showObsm, setShowObsm] = (0, _react.useState)(false);
38
39
  const [showVars, setShowVars] = (0, _react.useState)(false);
39
40
  const [showControls, setShowControls] = (0, _react.useState)(false);
41
+ const [showModal, setShowModal] = (0, _react.useState)(false);
40
42
  (0, _react.useEffect)(() => {
41
43
  const updateDimensions = () => {
42
44
  if (appRef.current) {
@@ -64,14 +66,12 @@ function FullPage({
64
66
  style: {
65
67
  height: appDimensions.height
66
68
  }
67
- }, /*#__PURE__*/_react.default.createElement(_DatasetContext.DatasetProvider, props, /*#__PURE__*/_react.default.createElement("div", {
68
- className: "row g-0"
69
- }, /*#__PURE__*/_react.default.createElement("div", {
70
- className: "cherita-app-obs modern-scrollbars border-end h-100"
71
- }, /*#__PURE__*/_react.default.createElement(_ObsList.ObsColsList, null)), /*#__PURE__*/_react.default.createElement("div", {
72
- className: "cherita-app-plot"
73
- }, /*#__PURE__*/_react.default.createElement("div", {
74
- className: "position-relative"
69
+ }, /*#__PURE__*/_react.default.createElement(_DatasetContext.DatasetProvider, props, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Container, {
70
+ fluid: true,
71
+ className: "d-flex g-0",
72
+ style: {
73
+ height: appDimensions.height
74
+ }
75
75
  }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Navbar, {
76
76
  expand: "sm",
77
77
  bg: "primary",
@@ -95,18 +95,28 @@ function FullPage({
95
95
  className: "d-flex"
96
96
  }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Nav.Item, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Nav.Link, {
97
97
  onClick: () => setShowControls(true)
98
- }, "Controls"))))))), children), /*#__PURE__*/_react.default.createElement("div", {
99
- className: "cherita-app-var"
100
- }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Card, {
101
- className: "cherita-app-features"
102
- }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Card.Body, null, /*#__PURE__*/_react.default.createElement(_SearchBar.SearchBar, {
98
+ }, "Controls")))))), /*#__PURE__*/_react.default.createElement("div", {
99
+ className: "cherita-app-obs modern-scrollbars border-end h-100"
100
+ }, /*#__PURE__*/_react.default.createElement(_ObsList.ObsColsList, props)), /*#__PURE__*/_react.default.createElement("div", {
101
+ className: "cherita-app-canvas flex-grow-1"
102
+ }, children), /*#__PURE__*/_react.default.createElement("div", {
103
+ className: "cherita-app-sidebar p-3"
104
+ }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Card, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Card.Body, {
105
+ className: "d-flex flex-column p-0"
106
+ }, /*#__PURE__*/_react.default.createElement("div", {
107
+ className: "sidebar-features modern-scrollbars"
108
+ }, /*#__PURE__*/_react.default.createElement(_SearchBar.SearchBar, {
103
109
  searchDiseases: true,
104
110
  searchVar: true
105
111
  }), /*#__PURE__*/_react.default.createElement(_VarList.VarNamesList, {
106
112
  mode: varMode
107
- })))), /*#__PURE__*/_react.default.createElement("div", {
108
- className: "col"
109
- }, /*#__PURE__*/_react.default.createElement(_offcanvas.OffcanvasObs, {
113
+ })))))), /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Modal, {
114
+ show: showModal,
115
+ onHide: () => setShowModal(false),
116
+ centered: true
117
+ }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Modal.Header, {
118
+ closeButton: true
119
+ }), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Modal.Body, null)), /*#__PURE__*/_react.default.createElement(_offcanvas.OffcanvasObs, {
110
120
  show: showObs,
111
121
  handleClose: () => setShowObs(false)
112
122
  }), /*#__PURE__*/_react.default.createElement(_offcanvas.OffcanvasVars, {
@@ -119,7 +129,7 @@ function FullPage({
119
129
  }), /*#__PURE__*/_react.default.createElement(_offcanvas.OffcanvasObsm, {
120
130
  show: showObsm,
121
131
  handleClose: () => setShowObsm(false)
122
- })))));
132
+ }))));
123
133
  }
124
134
  function FullPageScatterplot(props) {
125
135
  return /*#__PURE__*/_react.default.createElement(FullPage, props, /*#__PURE__*/_react.default.createElement(_Scatterplot.Scatterplot, null));
@@ -21,11 +21,12 @@ var _SearchBar = require("../search-bar/SearchBar");
21
21
  var _VarList = require("../var-list/VarList");
22
22
  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); }
23
23
  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; }
24
- function FullPage({
25
- children,
26
- varMode = _constants.SELECTION_MODES.SINGLE,
27
- ...props
28
- }) {
24
+ function FullPage(_ref) {
25
+ let {
26
+ children,
27
+ varMode = _constants.SELECTION_MODES.SINGLE,
28
+ ...props
29
+ } = _ref;
29
30
  const appRef = (0, _react.useRef)();
30
31
  const [appDimensions, setAppDimensions] = (0, _react.useState)({
31
32
  width: 0,
@@ -96,7 +97,7 @@ function FullPage({
96
97
  onClick: () => setShowControls(true)
97
98
  }, "Controls")))))), /*#__PURE__*/_react.default.createElement("div", {
98
99
  className: "cherita-app-obs modern-scrollbars border-end h-100"
99
- }, /*#__PURE__*/_react.default.createElement(_ObsList.ObsColsList, null)), /*#__PURE__*/_react.default.createElement("div", {
100
+ }, /*#__PURE__*/_react.default.createElement(_ObsList.ObsColsList, props)), /*#__PURE__*/_react.default.createElement("div", {
100
101
  className: "cherita-app-canvas flex-grow-1"
101
102
  }, children), /*#__PURE__*/_react.default.createElement("div", {
102
103
  className: "cherita-app-sidebar p-3"
@@ -10,7 +10,6 @@ var _material = require("@mui/material");
10
10
  var _xCharts = require("@mui/x-charts");
11
11
  var _lodash = _interopRequireDefault(require("lodash"));
12
12
  var _reactBootstrap = require("react-bootstrap");
13
- var _ObsToolbar = require("./ObsToolbar");
14
13
  var _constants = require("../../constants/constants");
15
14
  var _DatasetContext = require("../../context/DatasetContext");
16
15
  var _FilterContext = require("../../context/FilterContext");
@@ -21,6 +20,7 @@ var _requests = require("../../utils/requests");
21
20
  var _string = require("../../utils/string");
22
21
  var _VirtualizedList = require("../../utils/VirtualizedList");
23
22
  var _zarrData = require("../../utils/zarrData");
23
+ var _ObsToolbar = require("./ObsToolbar");
24
24
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
25
25
  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); }
26
26
  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; }
@@ -121,30 +121,31 @@ const useFilteredObsData = obs => {
121
121
  pct: pct
122
122
  };
123
123
  };
124
- function CategoricalItem({
125
- value,
126
- label,
127
- code,
128
- stats = {
129
- value_counts: null,
130
- pct: null
131
- },
132
- isOmitted,
133
- min,
134
- max,
135
- onChange,
136
- histogramData = {
137
- data: null,
138
- isPending: false,
139
- altColor: false
140
- },
141
- filteredStats = {
142
- value_counts: null,
143
- pct: null
144
- },
145
- isSliced,
146
- showColor = true
147
- }) {
124
+ function CategoricalItem(_ref) {
125
+ let {
126
+ value,
127
+ label,
128
+ code,
129
+ stats = {
130
+ value_counts: null,
131
+ pct: null
132
+ },
133
+ isOmitted,
134
+ min,
135
+ max,
136
+ onChange,
137
+ histogramData = {
138
+ data: null,
139
+ isPending: false,
140
+ altColor: false
141
+ },
142
+ filteredStats = {
143
+ value_counts: null,
144
+ pct: null
145
+ },
146
+ isSliced,
147
+ showColor = true
148
+ } = _ref;
148
149
  const {
149
150
  getColor
150
151
  } = (0, _colorHelper.useColor)();
@@ -238,16 +239,17 @@ function CategoricalItem({
238
239
  })})`
239
240
  }))) : null)));
240
241
  }
241
- function CategoricalObs({
242
- obs,
243
- updateObs,
244
- toggleAll,
245
- toggleObs,
246
- toggleLabel,
247
- toggleSlice,
248
- toggleColor,
249
- showColor = true
250
- }) {
242
+ function CategoricalObs(_ref2) {
243
+ let {
244
+ obs,
245
+ updateObs,
246
+ toggleAll,
247
+ toggleObs,
248
+ toggleLabel,
249
+ toggleSlice,
250
+ toggleColor,
251
+ showColor = true
252
+ } = _ref2;
251
253
  const dataset = (0, _DatasetContext.useDataset)();
252
254
  const {
253
255
  isSliced
@@ -303,13 +305,13 @@ function CategoricalObs({
303
305
  }, [dataset.colorEncoding, filteredObsData?.pct, filteredObsData?.value_counts, isSliced, obs.codes, obs.omit, obs.value_counts, obs.values, obsHistograms.fetchedData, obsHistograms.isPending, totalCounts]);
304
306
  showColor &= dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS;
305
307
  return /*#__PURE__*/_react.default.createElement(_reactBootstrap.ListGroup, {
306
- variant: "flush"
307
- }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.ListGroup.Item, null, /*#__PURE__*/_react.default.createElement(_ObsToolbar.ObsToolbar, {
308
+ variant: "flush",
309
+ className: "cherita-list"
310
+ }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.ListGroup.Item, {
311
+ className: "cherita-list-item-unstyled"
312
+ }, /*#__PURE__*/_react.default.createElement(_ObsToolbar.ObsToolbar, {
308
313
  item: obs,
309
- onToggleAllObs: toggleAll,
310
- onToggleLabel: toggleLabel,
311
- onToggleSlice: toggleSlice,
312
- onToggleColor: toggleColor
314
+ onToggleAllObs: toggleAll
313
315
  })), /*#__PURE__*/_react.default.createElement(_VirtualizedList.VirtualizedList, {
314
316
  getDataAtIndex: getDataAtIndex,
315
317
  count: obs.values.length,
@@ -321,9 +323,10 @@ function CategoricalObs({
321
323
  showColor: showColor
322
324
  }));
323
325
  }
324
- function ObsContinuousStats({
325
- obs
326
- }) {
326
+ function ObsContinuousStats(_ref3) {
327
+ let {
328
+ obs
329
+ } = _ref3;
327
330
  const ENDPOINT = "obs/distribution";
328
331
  const dataset = (0, _DatasetContext.useDataset)();
329
332
  const params = {
@@ -337,31 +340,25 @@ function ObsContinuousStats({
337
340
  } = (0, _requests.useFetch)(ENDPOINT, params);
338
341
 
339
342
  // @TODO: fix width issue when min/max/etc values are too large
340
- return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
341
- className: "d-flex justify-content-between mt-3 align-items-center"
342
- }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Table, {
343
- size: "sm",
344
- className: "obs-continuous-stats",
345
- striped: true
346
- }, /*#__PURE__*/_react.default.createElement("tbody", null, /*#__PURE__*/_react.default.createElement("tr", null, /*#__PURE__*/_react.default.createElement("td", null, "Min"), /*#__PURE__*/_react.default.createElement("td", {
347
- className: "text-end"
348
- }, (0, _string.formatNumerical)(obs.min, _string.FORMATS.EXPONENTIAL))), /*#__PURE__*/_react.default.createElement("tr", null, /*#__PURE__*/_react.default.createElement("td", null, "Max"), /*#__PURE__*/_react.default.createElement("td", {
349
- className: "text-end"
350
- }, (0, _string.formatNumerical)(obs.max, _string.FORMATS.EXPONENTIAL))))), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Table, {
351
- size: "sm",
352
- className: "obs-continuous-stats",
353
- striped: true
354
- }, /*#__PURE__*/_react.default.createElement("tbody", null, /*#__PURE__*/_react.default.createElement("tr", null, /*#__PURE__*/_react.default.createElement("td", null, "Mean"), /*#__PURE__*/_react.default.createElement("td", {
355
- className: "text-end"
356
- }, (0, _string.formatNumerical)(obs.mean, _string.FORMATS.EXPONENTIAL))), /*#__PURE__*/_react.default.createElement("tr", null, /*#__PURE__*/_react.default.createElement("td", null, "Median"), /*#__PURE__*/_react.default.createElement("td", {
357
- className: "text-end"
358
- }, (0, _string.formatNumerical)(obs.median, _string.FORMATS.EXPONENTIAL))))), isPending && /*#__PURE__*/_react.default.createElement(_LoadingIndicators.LoadingLinear, null), !isPending && !serverError && /*#__PURE__*/_react.default.createElement("div", {
343
+ return /*#__PURE__*/_react.default.createElement(_reactBootstrap.ListGroup, {
344
+ variant: "flush",
345
+ className: "cherita-list"
346
+ }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.ListGroup.Item, {
347
+ className: "obs-item"
348
+ }, /*#__PURE__*/_react.default.createElement("h5", {
349
+ className: "mb-2"
350
+ }, "Statistics"), /*#__PURE__*/_react.default.createElement("div", {
351
+ className: "row"
352
+ }, /*#__PURE__*/_react.default.createElement("div", {
353
+ className: "col-md-7"
354
+ }, /*#__PURE__*/_react.default.createElement("p", {
355
+ className: "mb-1 small"
356
+ }, "Distribution of continuous values"), isPending && /*#__PURE__*/_react.default.createElement(_LoadingIndicators.LoadingLinear, null), !isPending && !serverError && /*#__PURE__*/_react.default.createElement("div", {
359
357
  className: "obs-distribution"
360
358
  }, /*#__PURE__*/_react.default.createElement(_xCharts.SparkLineChart, {
361
359
  data: fetchedData.kde_values[1],
362
360
  showHighlight: true,
363
- showTooltip: true // throws Maximum update depth exceeded error. Documented here: https://github.com/mui/mui-x/issues/13450
364
- ,
361
+ showTooltip: true,
365
362
  margin: {
366
363
  top: 10,
367
364
  right: 20,
@@ -378,17 +375,28 @@ function ObsContinuousStats({
378
375
  className: "feature-histogram-tooltip"
379
376
  }
380
377
  }
381
- }))));
378
+ }))), /*#__PURE__*/_react.default.createElement("div", {
379
+ className: "col-md-5 d-flex flex-column text-end"
380
+ }, /*#__PURE__*/_react.default.createElement("div", {
381
+ className: "d-flex justify-content-between"
382
+ }, /*#__PURE__*/_react.default.createElement("span", null, "Min"), " ", /*#__PURE__*/_react.default.createElement("span", null, (0, _string.formatNumerical)(obs.min, _string.FORMATS.EXPONENTIAL))), /*#__PURE__*/_react.default.createElement("div", {
383
+ className: "d-flex justify-content-between"
384
+ }, /*#__PURE__*/_react.default.createElement("span", null, "Max"), " ", /*#__PURE__*/_react.default.createElement("span", null, (0, _string.formatNumerical)(obs.max, _string.FORMATS.EXPONENTIAL))), /*#__PURE__*/_react.default.createElement("div", {
385
+ className: "d-flex justify-content-between"
386
+ }, /*#__PURE__*/_react.default.createElement("span", null, "Mean"), " ", /*#__PURE__*/_react.default.createElement("span", null, (0, _string.formatNumerical)(obs.mean, _string.FORMATS.EXPONENTIAL))), /*#__PURE__*/_react.default.createElement("div", {
387
+ className: "d-flex justify-content-between"
388
+ }, /*#__PURE__*/_react.default.createElement("span", null, "Median"), " ", /*#__PURE__*/_react.default.createElement("span", null, (0, _string.formatNumerical)(obs.median, _string.FORMATS.EXPONENTIAL)))))));
382
389
  }
383
- function ContinuousObs({
384
- obs,
385
- updateObs,
386
- toggleAll,
387
- toggleObs,
388
- toggleLabel,
389
- toggleSlice,
390
- toggleColor
391
- }) {
390
+ function ContinuousObs(_ref4) {
391
+ let {
392
+ obs,
393
+ updateObs,
394
+ toggleAll,
395
+ toggleObs,
396
+ toggleLabel,
397
+ toggleSlice,
398
+ toggleColor
399
+ } = _ref4;
392
400
  const ENDPOINT = "obs/bins";
393
401
  const dataset = (0, _DatasetContext.useDataset)();
394
402
  const {
@@ -461,8 +469,11 @@ function ContinuousObs({
461
469
  };
462
470
  };
463
471
  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, isPending && /*#__PURE__*/_react.default.createElement(_LoadingIndicators.LoadingLinear, null), !serverError && updatedObs && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.ListGroup, {
464
- variant: "flush"
465
- }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.ListGroup.Item, null, /*#__PURE__*/_react.default.createElement(_ObsToolbar.ObsToolbar, {
472
+ variant: "flush",
473
+ className: "cherita-list"
474
+ }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.ListGroup.Item, {
475
+ className: "cherita-list-item-unstyled"
476
+ }, /*#__PURE__*/_react.default.createElement(_ObsToolbar.ObsToolbar, {
466
477
  item: obs,
467
478
  onToggleAllObs: toggleAll,
468
479
  onToggleLabel: toggleLabel,
@@ -7,33 +7,67 @@ exports.ObsColsList = ObsColsList;
7
7
  var _react = _interopRequireWildcard(require("react"));
8
8
  var _freeSolidSvgIcons = require("@fortawesome/free-solid-svg-icons");
9
9
  var _reactFontawesome = require("@fortawesome/react-fontawesome");
10
+ var _Comment = _interopRequireDefault(require("@mui/icons-material/Comment"));
11
+ var _JoinInner = _interopRequireDefault(require("@mui/icons-material/JoinInner"));
12
+ var _WaterDrop = _interopRequireDefault(require("@mui/icons-material/WaterDrop"));
10
13
  var _lodash = _interopRequireDefault(require("lodash"));
11
14
  var _reactBootstrap = require("react-bootstrap");
12
15
  var _Accordion = _interopRequireDefault(require("react-bootstrap/Accordion"));
13
16
  var _AccordionButton = require("react-bootstrap/AccordionButton");
14
17
  var _AccordionContext = _interopRequireDefault(require("react-bootstrap/AccordionContext"));
15
- var _ObsItem = require("./ObsItem");
16
18
  var _constants = require("../../constants/constants");
17
19
  var _DatasetContext = require("../../context/DatasetContext");
18
20
  var _LoadingIndicators = require("../../utils/LoadingIndicators");
19
21
  var _requests = require("../../utils/requests");
22
+ var _ObsItem = require("./ObsItem");
20
23
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
21
24
  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); }
22
25
  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; }
23
- function ObsColsList({
24
- showColor = true
25
- }) {
26
+ // @TODO: integrate ObsAccordionToggle with ObsColsList active, expandedItems, etc. to avoid duplication
27
+
28
+ const ObsAccordionToggle = _ref => {
29
+ let {
30
+ children,
31
+ eventKey,
32
+ handleAccordionToggle
33
+ } = _ref;
34
+ const {
35
+ activeEventKey
36
+ } = (0, _react.useContext)(_AccordionContext.default);
37
+ const decoratedOnClick = (0, _AccordionButton.useAccordionButton)(eventKey, () => {
38
+ handleAccordionToggle(eventKey);
39
+ });
40
+ const isCurrentEventKey = Array.isArray(activeEventKey) ? activeEventKey.includes(eventKey) : activeEventKey === eventKey;
41
+ return /*#__PURE__*/_react.default.createElement("div", {
42
+ className: `obs-accordion-header ${isCurrentEventKey ? "active" : ""}`,
43
+ onClick: decoratedOnClick
44
+ }, /*#__PURE__*/_react.default.createElement("span", {
45
+ className: "obs-accordion-header-chevron"
46
+ }, /*#__PURE__*/_react.default.createElement(_reactFontawesome.FontAwesomeIcon, {
47
+ icon: isCurrentEventKey ? _freeSolidSvgIcons.faChevronDown : _freeSolidSvgIcons.faChevronRight
48
+ })), /*#__PURE__*/_react.default.createElement("span", {
49
+ className: "obs-accordion-header-title"
50
+ }, children));
51
+ };
52
+ function ObsColsList(_ref2) {
53
+ let {
54
+ showColor = true,
55
+ enableObsGroups = true
56
+ } = _ref2;
26
57
  const ENDPOINT = "obs/cols";
27
58
  const dataset = (0, _DatasetContext.useDataset)();
28
59
  const dispatch = (0, _DatasetContext.useDatasetDispatch)();
60
+ const [enableGroups, setEnableGroups] = (0, _react.useState)(enableObsGroups);
29
61
  const [obsCols, setObsCols] = (0, _react.useState)(null);
30
62
  const [active, setActive] = (0, _react.useState)(dataset.selectedObs?.name);
31
- const [expandedItems, setExpandedItems] = (0, _react.useState)(active ? {
32
- [active]: true
33
- } : {});
63
+ const [expandedItems, setExpandedItems] = (0, _react.useState)({});
34
64
  const [params, setParams] = (0, _react.useState)({
35
65
  url: dataset.url
36
66
  });
67
+ const obsGroups = (0, _react.useMemo)(() => ({
68
+ default: _lodash.default.union(_constants.DEFAULT_OBS_GROUP, dataset.obsGroups?.default),
69
+ ..._lodash.default.omit(dataset.obsGroups, "default")
70
+ }), [dataset.obsGroups]);
37
71
  (0, _react.useEffect)(() => {
38
72
  setParams(p => {
39
73
  return {
@@ -50,13 +84,26 @@ function ObsColsList({
50
84
  refetchOnMount: false
51
85
  });
52
86
  (0, _react.useEffect)(() => {
53
- if (!isPending && !serverError) {
87
+ if (!isPending && !serverError && fetchedData) {
54
88
  let filteredData = fetchedData;
55
- if (dataset.obsCols) {
56
- filteredData = _lodash.default.filter(filteredData, d => {
57
- return _lodash.default.includes(dataset.obsCols, d.name);
89
+
90
+ // filter to only obs within an obsGroup
91
+ if (enableGroups) {
92
+ const groupFiltered = _lodash.default.filter(filteredData, d => {
93
+ return _lodash.default.some(obsGroups, g => _lodash.default.includes(g, d.name));
58
94
  });
95
+ if (!!filteredData.length && !groupFiltered.length) {
96
+ setEnableGroups(false);
97
+ console.warn(`No obs found in obsGroups ${JSON.stringify(obsGroups)}, disabling obsGroups`);
98
+ } else {
99
+ filteredData = groupFiltered;
100
+ }
59
101
  }
102
+
103
+ // filter out discrete obs
104
+ filteredData = _lodash.default.filter(filteredData, d => {
105
+ return d.type !== _constants.OBS_TYPES.DISCRETE;
106
+ });
60
107
  setObsCols(_lodash.default.keyBy(_lodash.default.map(filteredData, d => {
61
108
  return {
62
109
  ...d,
@@ -65,7 +112,19 @@ function ObsColsList({
65
112
  };
66
113
  }), "name"));
67
114
  }
68
- }, [dataset.obsCols, fetchedData, isPending, serverError]);
115
+ }, [fetchedData, isPending, obsGroups, serverError, enableGroups]);
116
+ (0, _react.useEffect)(() => {
117
+ if (obsCols && Object.keys(expandedItems).length === 0) {
118
+ const initialExpanded = Object.keys(obsCols).reduce((acc, key) => {
119
+ acc[key] = false;
120
+ return acc;
121
+ }, {});
122
+ if (active && obsCols[active]) {
123
+ initialExpanded[active] = true;
124
+ }
125
+ setExpandedItems(initialExpanded);
126
+ }
127
+ }, [obsCols, expandedItems, active]);
69
128
 
70
129
  // @TODO: fix re-rendering performance issue
71
130
  (0, _react.useEffect)(() => {
@@ -74,9 +133,13 @@ function ObsColsList({
74
133
  setActive(dataset.selectedObs?.name);
75
134
  } else {
76
135
  setActive(null);
136
+ dispatch({
137
+ type: "select.obs",
138
+ obs: null
139
+ });
77
140
  }
78
141
  }
79
- }, [dataset.selectedObs, obsCols]);
142
+ }, [dataset.selectedObs, dispatch, obsCols]);
80
143
  const updateObs = updatedObs => {
81
144
  setObsCols(o => {
82
145
  return {
@@ -149,7 +212,7 @@ function ObsColsList({
149
212
  });
150
213
  dispatch({
151
214
  type: "set.colorEncoding",
152
- value: "obs"
215
+ value: _constants.COLOR_ENCODINGS.OBS
153
216
  });
154
217
  };
155
218
  const toggleObs = (item, value) => {
@@ -178,29 +241,10 @@ function ObsColsList({
178
241
  });
179
242
  }
180
243
  };
181
- function ObsAccordionToggle({
182
- children,
183
- eventKey
184
- }) {
185
- const {
186
- activeEventKey
187
- } = (0, _react.useContext)(_AccordionContext.default);
188
- const decoratedOnClick = (0, _AccordionButton.useAccordionButton)(eventKey, () => {
189
- handleAccordionToggle(eventKey);
190
- });
191
- const isCurrentEventKey = Array.isArray(activeEventKey) ? activeEventKey.includes(eventKey) : activeEventKey === eventKey;
192
- return /*#__PURE__*/_react.default.createElement("div", {
193
- className: `obs-accordion-header ${isCurrentEventKey ? "active" : ""}`,
194
- onClick: decoratedOnClick
195
- }, /*#__PURE__*/_react.default.createElement("span", {
196
- className: "obs-accordion-header-chevron"
197
- }, /*#__PURE__*/_react.default.createElement(_reactFontawesome.FontAwesomeIcon, {
198
- icon: isCurrentEventKey ? _freeSolidSvgIcons.faChevronDown : _freeSolidSvgIcons.faChevronRight
199
- })), /*#__PURE__*/_react.default.createElement("span", {
200
- className: "obs-accordion-header-title"
201
- }, children));
202
- }
203
- const obsList = _lodash.default.map(obsCols, (item, index) => {
244
+ const obsItem = item => {
245
+ if (!item) {
246
+ return null;
247
+ }
204
248
  if (item.type === _constants.OBS_TYPES.DISCRETE) {
205
249
  return null;
206
250
  }
@@ -208,22 +252,33 @@ function ObsColsList({
208
252
  const inSliceObs = dataset.sliceBy.obs && dataset.selectedObs?.name === item.name;
209
253
  const isColorEncoding = dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS && dataset.selectedObs?.name === item.name;
210
254
  return /*#__PURE__*/_react.default.createElement("div", {
255
+ className: "accordion-item",
211
256
  key: item.name
212
257
  }, /*#__PURE__*/_react.default.createElement(ObsAccordionToggle, {
213
- eventKey: item.name
214
- }, /*#__PURE__*/_react.default.createElement("div", null, item.name), /*#__PURE__*/_react.default.createElement("div", null, inLabelObs && /*#__PURE__*/_react.default.createElement(_reactFontawesome.FontAwesomeIcon, {
215
- className: "mx-1",
216
- icon: _freeSolidSvgIcons.faListOl,
217
- title: "In tooltip"
218
- }), inSliceObs && /*#__PURE__*/_react.default.createElement(_reactFontawesome.FontAwesomeIcon, {
219
- className: "mx-1",
220
- icon: _freeSolidSvgIcons.faScissors,
258
+ eventKey: item.name,
259
+ handleAccordionToggle: handleAccordionToggle
260
+ }, /*#__PURE__*/_react.default.createElement("div", null, item.name), /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("span", {
261
+ className: `mx-1 cursor-pointer ${inLabelObs ? "active-icon" : "text-muted opacity-50"}`,
262
+ onClick: event => {
263
+ event.stopPropagation();
264
+ toggleLabel(item);
265
+ },
266
+ title: "Add to tooltip"
267
+ }, /*#__PURE__*/_react.default.createElement(_Comment.default, null)), /*#__PURE__*/_react.default.createElement("span", {
268
+ className: `mx-1 cursor-pointer ${inSliceObs ? "active-icon" : "text-muted opacity-50"}`,
269
+ onClick: event => {
270
+ event.stopPropagation();
271
+ toggleSlice(item);
272
+ },
221
273
  title: "Filter applied"
222
- }), isColorEncoding && /*#__PURE__*/_react.default.createElement(_reactFontawesome.FontAwesomeIcon, {
223
- className: "mx-1",
224
- icon: _freeSolidSvgIcons.faDroplet,
274
+ }, /*#__PURE__*/_react.default.createElement(_JoinInner.default, null)), /*#__PURE__*/_react.default.createElement("span", {
275
+ className: `mx-1 cursor-pointer ${isColorEncoding ? "active-icon" : "text-muted opacity-50"}`,
276
+ onClick: event => {
277
+ event.stopPropagation();
278
+ toggleColor(item);
279
+ },
225
280
  title: "Is color encoding"
226
- }))), /*#__PURE__*/_react.default.createElement(_Accordion.default.Collapse, {
281
+ }, /*#__PURE__*/_react.default.createElement(_WaterDrop.default, null)))), /*#__PURE__*/_react.default.createElement(_Accordion.default.Collapse, {
227
282
  eventKey: item.name
228
283
  }, /*#__PURE__*/_react.default.createElement("div", {
229
284
  className: "obs-accordion-body"
@@ -247,9 +302,37 @@ function ObsColsList({
247
302
  toggleSlice: () => toggleSlice(item),
248
303
  toggleColor: () => toggleColor(item)
249
304
  })))));
305
+ };
306
+ const groupList = _lodash.default.map(_lodash.default.keys(obsGroups), group => {
307
+ const key = `group-${group}`;
308
+ const groupItems = _lodash.default.compact(_lodash.default.map(_lodash.default.sortBy(obsGroups[group], o => _lodash.default.lowerCase(o.name)), item => {
309
+ return obsItem(obsCols?.[item]);
310
+ }));
311
+ if (group === "default") {
312
+ return groupItems;
313
+ } else {
314
+ return /*#__PURE__*/_react.default.createElement(_Accordion.default.Item, {
315
+ key: key,
316
+ eventKey: key,
317
+ className: "obs-group-accordion-item"
318
+ }, /*#__PURE__*/_react.default.createElement(_Accordion.default.Header, {
319
+ className: "obs-group-accordion-header"
320
+ }, group), /*#__PURE__*/_react.default.createElement(_Accordion.default.Body, {
321
+ className: "obs-group-accordion-body"
322
+ }, groupItems));
323
+ }
250
324
  });
325
+ const obsList = enableGroups ? /*#__PURE__*/_react.default.createElement(_Accordion.default, {
326
+ className: "obs-group-accordion",
327
+ flush: true,
328
+ alwaysOpen: true
329
+ }, groupList) : _lodash.default.map(_lodash.default.sortBy(obsCols, o => _lodash.default.lowerCase(o.name)), item => obsItem(item));
251
330
  if (!serverError) {
252
- return /*#__PURE__*/_react.default.createElement("div", null, isPending && /*#__PURE__*/_react.default.createElement(_LoadingIndicators.LoadingSpinner, null), /*#__PURE__*/_react.default.createElement(_Accordion.default, {
331
+ return /*#__PURE__*/_react.default.createElement("div", {
332
+ className: "position-relative h-100"
333
+ }, isPending ? /*#__PURE__*/_react.default.createElement(_LoadingIndicators.LoadingSpinner, null) : !!obsCols && !_lodash.default.size(obsCols) ? /*#__PURE__*/_react.default.createElement(_reactBootstrap.Alert, {
334
+ variant: "danger"
335
+ }, "No observations found.") : /*#__PURE__*/_react.default.createElement(_Accordion.default, {
253
336
  flush: true,
254
337
  defaultActiveKey: [active],
255
338
  alwaysOpen: true,