@haniffalab/cherita-react 1.2.0 → 1.3.0-dev.2025-05-29.ee7e9b72

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 (91) hide show
  1. package/dist/cjs/components/controls/Controls.js +60 -0
  2. package/dist/cjs/components/dotplot/Dotplot.js +47 -38
  3. package/dist/cjs/components/dotplot/DotplotControls.js +77 -114
  4. package/dist/cjs/components/full-page/FullPage.js +29 -33
  5. package/dist/cjs/components/full-page/FullPagePseudospatial.js +30 -33
  6. package/dist/cjs/components/heatmap/Heatmap.js +33 -22
  7. package/dist/cjs/components/heatmap/HeatmapControls.js +2 -19
  8. package/dist/cjs/components/matrixplot/Matrixplot.js +35 -24
  9. package/dist/cjs/components/matrixplot/MatrixplotControls.js +4 -34
  10. package/dist/cjs/components/obs-list/ObsItem.js +63 -51
  11. package/dist/cjs/components/obs-list/ObsList.js +53 -48
  12. package/dist/cjs/components/obsm-list/ObsmList.js +17 -12
  13. package/dist/cjs/components/offcanvas/index.js +14 -11
  14. package/dist/cjs/components/pseudospatial/Pseudospatial.js +78 -68
  15. package/dist/cjs/components/pseudospatial/PseudospatialToolbar.js +27 -21
  16. package/dist/cjs/components/scatterplot/Scatterplot.js +82 -76
  17. package/dist/cjs/components/scatterplot/ScatterplotControls.js +18 -31
  18. package/dist/cjs/components/scatterplot/SpatialControls.js +53 -23
  19. package/dist/cjs/components/scatterplot/Toolbox.js +1 -18
  20. package/dist/cjs/components/search-bar/SearchBar.js +156 -59
  21. package/dist/cjs/components/search-bar/SearchInfo.js +182 -0
  22. package/dist/cjs/components/search-bar/SearchResults.js +90 -60
  23. package/dist/cjs/components/var-list/VarItem.js +52 -75
  24. package/dist/cjs/components/var-list/VarList.js +47 -172
  25. package/dist/cjs/components/var-list/VarListToolbar.js +7 -8
  26. package/dist/cjs/components/var-list/VarSet.js +66 -57
  27. package/dist/cjs/components/violin/Violin.js +54 -43
  28. package/dist/cjs/components/violin/ViolinControls.js +4 -20
  29. package/dist/cjs/context/DatasetContext.js +26 -513
  30. package/dist/cjs/context/FilterContext.js +9 -8
  31. package/dist/cjs/context/SettingsContext.js +539 -0
  32. package/dist/cjs/context/ZarrDataContext.js +1 -2
  33. package/dist/cjs/helpers/color-helper.js +8 -8
  34. package/dist/cjs/helpers/zarr-helper.js +19 -16
  35. package/dist/cjs/utils/Filter.js +25 -21
  36. package/dist/cjs/utils/Histogram.js +4 -3
  37. package/dist/cjs/utils/ImageViewer.js +1 -2
  38. package/dist/cjs/utils/Legend.js +18 -12
  39. package/dist/cjs/utils/LoadingIndicators.js +1 -1
  40. package/dist/cjs/utils/VirtualizedList.js +16 -13
  41. package/dist/cjs/utils/errors.js +20 -22
  42. package/dist/cjs/utils/requests.js +13 -10
  43. package/dist/cjs/utils/zarrData.js +31 -50
  44. package/dist/css/cherita.css +84 -24
  45. package/dist/css/cherita.css.map +1 -1
  46. package/dist/esm/components/controls/Controls.js +51 -0
  47. package/dist/esm/components/dotplot/Dotplot.js +47 -37
  48. package/dist/esm/components/dotplot/DotplotControls.js +77 -112
  49. package/dist/esm/components/full-page/FullPage.js +29 -32
  50. package/dist/esm/components/full-page/FullPagePseudospatial.js +30 -32
  51. package/dist/esm/components/heatmap/Heatmap.js +32 -20
  52. package/dist/esm/components/heatmap/HeatmapControls.js +3 -20
  53. package/dist/esm/components/matrixplot/Matrixplot.js +34 -22
  54. package/dist/esm/components/matrixplot/MatrixplotControls.js +5 -35
  55. package/dist/esm/components/obs-list/ObsItem.js +63 -49
  56. package/dist/esm/components/obs-list/ObsList.js +53 -47
  57. package/dist/esm/components/obsm-list/ObsmList.js +17 -11
  58. package/dist/esm/components/offcanvas/index.js +14 -11
  59. package/dist/esm/components/pseudospatial/Pseudospatial.js +77 -66
  60. package/dist/esm/components/pseudospatial/PseudospatialToolbar.js +27 -20
  61. package/dist/esm/components/scatterplot/Scatterplot.js +81 -74
  62. package/dist/esm/components/scatterplot/ScatterplotControls.js +18 -29
  63. package/dist/esm/components/scatterplot/SpatialControls.js +54 -23
  64. package/dist/esm/components/scatterplot/Toolbox.js +1 -18
  65. package/dist/esm/components/search-bar/SearchBar.js +156 -59
  66. package/dist/esm/components/search-bar/SearchInfo.js +173 -0
  67. package/dist/esm/components/search-bar/SearchResults.js +91 -60
  68. package/dist/esm/components/var-list/VarItem.js +53 -76
  69. package/dist/esm/components/var-list/VarList.js +47 -171
  70. package/dist/esm/components/var-list/VarListToolbar.js +6 -6
  71. package/dist/esm/components/var-list/VarSet.js +67 -57
  72. package/dist/esm/components/violin/Violin.js +53 -41
  73. package/dist/esm/components/violin/ViolinControls.js +5 -21
  74. package/dist/esm/context/DatasetContext.js +25 -510
  75. package/dist/esm/context/FilterContext.js +8 -6
  76. package/dist/esm/context/SettingsContext.js +528 -0
  77. package/dist/esm/helpers/color-helper.js +8 -8
  78. package/dist/esm/helpers/zarr-helper.js +19 -16
  79. package/dist/esm/utils/Filter.js +25 -21
  80. package/dist/esm/utils/Histogram.js +4 -3
  81. package/dist/esm/utils/Legend.js +17 -10
  82. package/dist/esm/utils/LoadingIndicators.js +1 -1
  83. package/dist/esm/utils/VirtualizedList.js +15 -11
  84. package/dist/esm/utils/errors.js +20 -22
  85. package/dist/esm/utils/requests.js +13 -10
  86. package/dist/esm/utils/zarrData.js +33 -51
  87. package/package.json +6 -3
  88. package/scss/cherita.scss +50 -9
  89. package/scss/components/layouts.scss +24 -13
  90. package/scss/components/lists.scss +10 -0
  91. package/scss/components/plots.scss +3 -5
@@ -1,16 +1,22 @@
1
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
2
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
3
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
4
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
5
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
1
6
  import React, { useEffect, useState } from "react";
2
7
  import { faTimes } from "@fortawesome/free-solid-svg-icons";
3
8
  import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
4
9
  import _ from "lodash";
5
10
  import { Alert, Button, ListGroup } from "react-bootstrap";
6
11
  import ButtonGroup from "react-bootstrap/ButtonGroup";
7
- import { SELECTION_MODES, VAR_SORT } from "../../constants/constants";
8
- import { useDataset, useDatasetDispatch } from "../../context/DatasetContext";
9
- import { LoadingSpinner } from "../../utils/LoadingIndicators";
10
- import { useFetch } from "../../utils/requests";
11
12
  import { VarItem } from "./VarItem";
12
13
  import { VarListToolbar } from "./VarListToolbar";
13
14
  import { VarSet } from "./VarSet";
15
+ import { SELECTION_MODES, VAR_SORT } from "../../constants/constants";
16
+ import { useDataset } from "../../context/DatasetContext";
17
+ import { useSettings, useSettingsDispatch } from "../../context/SettingsContext";
18
+ import { LoadingSpinner } from "../../utils/LoadingIndicators";
19
+ import { useFetch } from "../../utils/requests";
14
20
  const useVarMean = function (varKeys) {
15
21
  let enabled = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
16
22
  const ENDPOINT = "matrix/mean";
@@ -26,13 +32,12 @@ const useVarMean = function (varKeys) {
26
32
  });
27
33
  useEffect(() => {
28
34
  setParams(p => {
29
- return {
30
- ...p,
35
+ return _objectSpread(_objectSpread({}, p), {}, {
31
36
  varKeys: _.map(varKeys, v => v.isSet ? {
32
37
  name: v.name,
33
38
  indices: v.vars.map(v => v.index)
34
39
  } : v.index)
35
- };
40
+ });
36
41
  });
37
42
  }, [varKeys]);
38
43
  return useFetch(ENDPOINT, params, {
@@ -45,173 +50,50 @@ const useVarMean = function (varKeys) {
45
50
  const sortMeans = (i, means) => {
46
51
  return means[i.name] || _.min(_.values(means)) - 1;
47
52
  };
48
-
49
- // @TODO: display where disease data comes from
50
- // add to disease dataset metadata
51
- function DiseaseVarList(_ref) {
52
- let {
53
- makeListItem
54
- } = _ref;
55
- const ENDPOINT = "disease/genes";
56
- const dataset = useDataset();
57
- const dispatch = useDatasetDispatch();
58
- const [diseaseVars, setDiseaseVars] = useState([]);
59
- const [sortedDiseaseVars, setSortedDiseaseVars] = useState([]);
60
- const [params, setParams] = useState({
61
- url: dataset.url,
62
- col: dataset.varNamesCol,
63
- diseaseId: dataset.selectedDisease?.id,
64
- diseaseDatasets: dataset.diseaseDatasets
65
- });
66
- useEffect(() => {
67
- setParams(p => {
68
- return {
69
- ...p,
70
- diseaseId: dataset.selectedDisease?.id
71
- };
72
- });
73
- }, [dataset.selectedDisease]);
74
- const diseaseData = useFetch(ENDPOINT, params, {
75
- enabled: !!params.diseaseId,
76
- refetchOnMount: false
77
- });
78
- useEffect(() => {
79
- if (!diseaseData.isPending && !diseaseData.serverError) {
80
- setDiseaseVars(diseaseData.fetchedData);
81
- }
82
- }, [diseaseData.fetchedData, diseaseData.isPending, diseaseData.serverError]);
83
- const varMeans = useVarMean(diseaseVars, !!diseaseVars?.length && dataset.varSort.disease.sort === VAR_SORT.MATRIX);
84
- useEffect(() => {
85
- if (dataset.varSort.disease.sort === VAR_SORT.MATRIX) {
86
- if (!varMeans.isPending && !varMeans.serverError) {
87
- setSortedDiseaseVars(_.orderBy(diseaseVars, o => {
88
- return sortMeans(o, varMeans.fetchedData);
89
- }, dataset.varSort.disease.sortOrder));
90
- }
91
- } else if (dataset.varSort.disease.sort === VAR_SORT.NAME) {
92
- setSortedDiseaseVars(_.orderBy(diseaseVars, "name", dataset.varSort.disease.sortOrder));
93
- } else {
94
- setSortedDiseaseVars(diseaseVars);
95
- }
96
- }, [dataset.varSort.disease.sort, dataset.varSort.disease.sortOrder, diseaseVars, varMeans.fetchedData, varMeans.isPending, varMeans.serverError]);
97
- const diseaseVarList = _.map(sortedDiseaseVars, item => {
98
- return makeListItem(item, true);
99
- });
100
- const isPending = diseaseData.isPending || varMeans.isPending && dataset.varSort.disease.sort === VAR_SORT.MATRIX;
101
- return /*#__PURE__*/React.createElement(React.Fragment, null, dataset.selectedDisease && (!isPending && !diseaseVars?.length ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
102
- className: "d-flex justify-content-between mt-3"
103
- }, /*#__PURE__*/React.createElement("h5", null, "Disease genes")), /*#__PURE__*/React.createElement(Alert, {
104
- variant: "light"
105
- }, "No disease genes found.")) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
106
- className: "d-flex justify-content-between my-2"
107
- }, /*#__PURE__*/React.createElement("h5", null, "Disease genes"), /*#__PURE__*/React.createElement(ButtonGroup, {
108
- "aria-label": "Feature options",
109
- size: "sm"
110
- }, /*#__PURE__*/React.createElement(Button, {
111
- variant: "info",
112
- onClick: () => {
113
- dispatch({
114
- type: "reset.disease"
115
- });
116
- }
117
- }, /*#__PURE__*/React.createElement(FontAwesomeIcon, {
118
- icon: faTimes,
119
- className: "me-1"
120
- }), "Clear"))), /*#__PURE__*/React.createElement("p", null, dataset.selectedDisease?.name), /*#__PURE__*/React.createElement(VarListToolbar, {
121
- varType: "disease"
122
- }), /*#__PURE__*/React.createElement("div", {
123
- className: "position-relative"
124
- }, isPending && /*#__PURE__*/React.createElement(LoadingSpinner, null), /*#__PURE__*/React.createElement(ListGroup, {
125
- variant: "flush",
126
- className: "cherita-list"
127
- }, diseaseVarList)))));
128
- }
129
- export function VarNamesList(_ref2) {
53
+ export function VarNamesList(_ref) {
54
+ var _settings$selectedVar, _settings$selectedVar2;
130
55
  let {
131
56
  mode = SELECTION_MODES.SINGLE,
132
- displayName = "genes",
133
- showDiseaseVarList = true
134
- } = _ref2;
135
- const dataset = useDataset();
136
- const dispatch = useDatasetDispatch();
137
- const [varButtons, setVarButtons] = useState(mode === SELECTION_MODES.SINGLE ? dataset.selectedVar ? _.unionWith([dataset.selectedVar], dataset.varSets, _.isEqual) : [...dataset.varSets] : [...dataset.selectedMultiVar, ...dataset.varSets]);
138
- const [active, setActive] = useState(mode === SELECTION_MODES.SINGLE ? dataset.selectedVar?.matrix_index || dataset.selectedVar?.name : dataset.selectedMultiVar.map(i => i.matrix_index || i.name));
139
- const [sortedVarButtons, setSortedVarButtons] = useState([]);
57
+ displayName = "genes"
58
+ } = _ref;
59
+ const settings = useSettings();
60
+ const dispatch = useSettingsDispatch();
61
+ const [active, setActive] = useState(mode === SELECTION_MODES.SINGLE ? ((_settings$selectedVar = settings.selectedVar) === null || _settings$selectedVar === void 0 ? void 0 : _settings$selectedVar.matrix_index) || ((_settings$selectedVar2 = settings.selectedVar) === null || _settings$selectedVar2 === void 0 ? void 0 : _settings$selectedVar2.name) : settings.selectedMultiVar.map(i => i.matrix_index || i.name));
62
+ const [sortedVars, setSortedVars] = useState([]);
140
63
  useEffect(() => {
141
64
  if (mode === SELECTION_MODES.SINGLE) {
142
- setVarButtons(v => {
143
- if (dataset.selectedVar) {
144
- return _.unionWith(v, [dataset.selectedVar], _.isEqual);
145
- } else {
146
- return v;
147
- }
148
- });
149
- setActive(dataset.selectedVar?.matrix_index || dataset.selectedVar?.name);
65
+ var _settings$selectedVar3, _settings$selectedVar4;
66
+ setActive(((_settings$selectedVar3 = settings.selectedVar) === null || _settings$selectedVar3 === void 0 ? void 0 : _settings$selectedVar3.matrix_index) || ((_settings$selectedVar4 = settings.selectedVar) === null || _settings$selectedVar4 === void 0 ? void 0 : _settings$selectedVar4.name));
150
67
  }
151
- }, [mode, dataset.selectedVar]);
68
+ }, [mode, settings.selectedVar]);
152
69
  useEffect(() => {
153
70
  if (mode === SELECTION_MODES.MULTIPLE) {
154
- setVarButtons(v => {
155
- if (dataset.selectedMultiVar.length) {
156
- return _.unionWith(v, dataset.selectedMultiVar, _.isEqual);
157
- } else {
158
- return v;
159
- }
160
- });
161
- setActive(dataset.selectedMultiVar.map(i => i.matrix_index || i.name));
71
+ setActive(settings.selectedMultiVar.map(i => i.matrix_index || i.name));
162
72
  }
163
- }, [mode, dataset.selectedMultiVar]);
164
- useEffect(() => {
165
- setVarButtons(v => {
166
- const updated = _.compact(_.map(v, i => {
167
- if (i.isSet) {
168
- return dataset.varSets.find(s => s.name === i.name);
169
- } else return i;
170
- }));
171
- const newSets = _.difference(dataset.varSets, updated);
172
- return [...updated, ...newSets];
173
- });
174
- if (mode === SELECTION_MODES.SINGLE) {
175
- if (dataset.selectedVar?.isSet) {
176
- const selectedSet = dataset.varSets.find(s => s.name === dataset.selectedVar.name);
177
- dispatch({
178
- type: "select.var",
179
- var: selectedSet
180
- });
181
- }
182
- } else {
183
- dispatch({
184
- type: "update.multivar",
185
- vars: dataset.varSets
186
- });
187
- }
188
- }, [mode, dataset.varSets, dataset.selectedVar?.isSet, dataset.selectedVar?.name, dispatch]);
189
- const varMeans = useVarMean(varButtons, dataset.varSort.var.sort === VAR_SORT.MATRIX);
73
+ }, [mode, settings.selectedMultiVar]);
74
+ const varMeans = useVarMean(settings.vars, settings.varSort.var.sort === VAR_SORT.MATRIX);
190
75
 
191
- // @TODO: deferr sortedVarButtons ?
76
+ // @TODO: deferr sortedVars ?
192
77
  useEffect(() => {
193
- if (dataset.varSort.var.sort === VAR_SORT.MATRIX) {
78
+ if (settings.varSort.var.sort === VAR_SORT.MATRIX) {
194
79
  if (!varMeans.isPending && !varMeans.serverError && varMeans.fetchedData) {
195
- setSortedVarButtons(_.orderBy(varButtons, o => {
80
+ setSortedVars(_.orderBy(settings.vars, o => {
196
81
  return sortMeans(o, varMeans.fetchedData);
197
- }, dataset.varSort.var.sortOrder));
82
+ }, settings.varSort.var.sortOrder));
198
83
  }
199
- } else if (dataset.varSort.var.sort === VAR_SORT.NAME) {
200
- setSortedVarButtons(_.orderBy(varButtons, "name", dataset.varSort.var.sortOrder));
84
+ } else if (settings.varSort.var.sort === VAR_SORT.NAME) {
85
+ setSortedVars(_.orderBy(settings.vars, "name", settings.varSort.var.sortOrder));
201
86
  } else {
202
- setSortedVarButtons(varButtons);
87
+ setSortedVars(settings.vars);
203
88
  }
204
- }, [dataset.varSort.var.sort, dataset.varSort.var.sortOrder, varButtons, varMeans.isPending, varMeans.serverError, varMeans.fetchedData]);
205
- const makeListItem = function (item) {
206
- let isDiseaseGene = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
89
+ }, [settings.varSort.var.sort, settings.varSort.var.sortOrder, varMeans.isPending, varMeans.serverError, varMeans.fetchedData, settings.vars]);
90
+ const makeListItem = item => {
207
91
  return /*#__PURE__*/React.createElement(ListGroup.Item, {
208
92
  key: item.matrix_index
209
93
  }, /*#__PURE__*/React.createElement(VarItem, {
210
94
  item: item,
211
95
  active: active,
212
- setVarButtons: setVarButtons,
213
- mode: mode,
214
- isDiseaseGene: isDiseaseGene
96
+ mode: mode
215
97
  }));
216
98
  };
217
99
  const makeSetListItem = set => {
@@ -223,7 +105,7 @@ export function VarNamesList(_ref2) {
223
105
  mode: mode
224
106
  }));
225
107
  };
226
- const varList = _.map(sortedVarButtons, item => {
108
+ const varList = _.map(sortedVars, item => {
227
109
  if (item.isSet) {
228
110
  return makeSetListItem(item);
229
111
  } else {
@@ -232,17 +114,17 @@ export function VarNamesList(_ref2) {
232
114
  });
233
115
  const newSetName = () => {
234
116
  let n = 1;
235
- let setName = `Set ${n}`;
236
- const setNameExists = name => {
237
- return dataset.varSets.some(set => set.name === name);
117
+ let setName = "Set ".concat(n);
118
+ const nameExists = name => {
119
+ return settings.vars.some(v => v.name === name);
238
120
  };
239
- while (setNameExists(setName)) {
121
+ while (nameExists(setName)) {
240
122
  n++;
241
- setName = `Set ${n}`;
123
+ setName = "Set ".concat(n);
242
124
  }
243
125
  return setName;
244
126
  };
245
- const isPending = varMeans.isPending && dataset.varSort.var.sort === VAR_SORT.MATRIX;
127
+ const isPending = varMeans.isPending && settings.varSort.var.sort === VAR_SORT.MATRIX;
246
128
  return /*#__PURE__*/React.createElement("div", {
247
129
  className: "position-relative"
248
130
  }, /*#__PURE__*/React.createElement("div", {
@@ -256,8 +138,8 @@ export function VarNamesList(_ref2) {
256
138
  variant: "info",
257
139
  onClick: () => {
258
140
  dispatch({
259
- type: "add.varSet",
260
- varSet: {
141
+ type: "add.var",
142
+ var: {
261
143
  name: newSetName(),
262
144
  vars: [],
263
145
  isSet: true
@@ -267,12 +149,8 @@ export function VarNamesList(_ref2) {
267
149
  }, "New set"), /*#__PURE__*/React.createElement(Button, {
268
150
  variant: "info",
269
151
  onClick: () => {
270
- setVarButtons([]);
271
- dispatch({
272
- type: mode === SELECTION_MODES.SINGLE ? "reset.var" : "reset.multiVar"
273
- });
274
152
  dispatch({
275
- type: "reset.varSets"
153
+ type: "reset.vars"
276
154
  });
277
155
  }
278
156
  }, /*#__PURE__*/React.createElement(FontAwesomeIcon, {
@@ -285,7 +163,5 @@ export function VarNamesList(_ref2) {
285
163
  }, isPending && /*#__PURE__*/React.createElement(LoadingSpinner, null), /*#__PURE__*/React.createElement(ListGroup, {
286
164
  variant: "flush",
287
165
  className: "cherita-list"
288
- }, varList)))), /*#__PURE__*/React.createElement(React.Fragment, null, showDiseaseVarList && /*#__PURE__*/React.createElement(DiseaseVarList, {
289
- makeListItem: makeListItem
290
- }))));
166
+ }, varList))))));
291
167
  }
@@ -3,18 +3,18 @@ import { faArrowDown19, faArrowDownAZ, faArrowUp91, faArrowUpZA, faXmark } from
3
3
  import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
4
4
  import { ToggleButton, ToggleButtonGroup } from "react-bootstrap";
5
5
  import { VAR_SORT, VAR_SORT_ORDER } from "../../constants/constants";
6
- import { useDataset, useDatasetDispatch } from "../../context/DatasetContext";
6
+ import { useSettings, useSettingsDispatch } from "../../context/SettingsContext";
7
7
 
8
8
  // @TODO: set option for "var" and "disease"
9
9
  export function VarListToolbar(_ref) {
10
10
  let {
11
11
  varType = "var"
12
12
  } = _ref;
13
- const dataset = useDataset();
14
- const dispatch = useDatasetDispatch();
15
- const [sort, setSort] = useState(dataset.varSort.var.sort);
16
- const [nameSortOrder, setNameSortOrder] = useState(dataset.varSort.var.sortOrder);
17
- const [matrixSortOrder, setMatrixSortOrder] = useState(dataset.varSort.var.sortOrder);
13
+ const settings = useSettings();
14
+ const dispatch = useSettingsDispatch();
15
+ const [sort, setSort] = useState(settings.varSort.var.sort);
16
+ const [nameSortOrder, setNameSortOrder] = useState(settings.varSort.var.sortOrder);
17
+ const [matrixSortOrder, setMatrixSortOrder] = useState(settings.varSort.var.sortOrder);
18
18
  const handleSort = (sortValue, sortOrder, setSortOrder) => {
19
19
  if (sort !== sortValue) {
20
20
  setSort(sortValue);
@@ -1,13 +1,12 @@
1
1
  import React, { useState } from "react";
2
- import { faCircleInfo, faDroplet, faTrash } from "@fortawesome/free-solid-svg-icons";
2
+ import { faChevronDown, faChevronUp, faCircleInfo, faDroplet, faPlus, faTrash } from "@fortawesome/free-solid-svg-icons";
3
3
  import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
4
- import { List } from "@mui/icons-material";
5
4
  import _ from "lodash";
6
5
  import { Button, Collapse, ListGroup, OverlayTrigger, Tooltip } from "react-bootstrap";
6
+ import { SelectionItem } from "./VarItem";
7
7
  import { COLOR_ENCODINGS, SELECTION_MODES } from "../../constants/constants";
8
- import { useDataset, useDatasetDispatch } from "../../context/DatasetContext";
9
- import { SearchBar } from "../search-bar/SearchBar";
10
- import { SingleSelectionItem } from "./VarItem";
8
+ import { useSettings, useSettingsDispatch } from "../../context/SettingsContext";
9
+ import { SearchModal } from "../search-bar/SearchBar";
11
10
 
12
11
  // @TODO: add button to score genes and plot
13
12
 
@@ -18,20 +17,22 @@ const addVarToSet = (dispatch, set, v) => {
18
17
  var: v
19
18
  });
20
19
  };
21
- function SingleSelectionSet(_ref) {
20
+ function SelectionSet(_ref) {
22
21
  let {
23
22
  set,
24
23
  isActive,
25
24
  selectSet,
26
25
  removeSet,
27
26
  removeSetVar,
28
- showSearchBar = true
27
+ isMultiple = false
29
28
  } = _ref;
30
29
  const [openSet, setOpenSet] = useState(false);
30
+ const [showModal, setShowModal] = useState(false);
31
+ const [searchText, setSearchText] = useState("");
31
32
  const varList = set.vars.length ? _.map(set.vars, v => {
32
33
  return /*#__PURE__*/React.createElement(ListGroup.Item, {
33
34
  key: v.name
34
- }, /*#__PURE__*/React.createElement(SingleSelectionItem, {
35
+ }, /*#__PURE__*/React.createElement(SelectionItem, {
35
36
  item: v,
36
37
  showSetColorEncoding: false,
37
38
  removeVar: () => removeSetVar(v)
@@ -46,16 +47,37 @@ function SingleSelectionSet(_ref) {
46
47
  }
47
48
  }, /*#__PURE__*/React.createElement("div", {
48
49
  className: "d-flex justify-content-between align-items-center w-100"
49
- }, /*#__PURE__*/React.createElement("div", null, set.name), /*#__PURE__*/React.createElement("div", {
50
+ }, /*#__PURE__*/React.createElement("div", {
51
+ className: "ellipsis-text",
52
+ title: set.name
53
+ }, set.name), /*#__PURE__*/React.createElement("div", {
50
54
  className: "d-flex align-items-center gap-1"
51
55
  }, /*#__PURE__*/React.createElement(OverlayTrigger, {
52
56
  placement: "top",
53
57
  overlay: /*#__PURE__*/React.createElement(Tooltip, null, "This set represents the mean value of its features")
54
58
  }, /*#__PURE__*/React.createElement(FontAwesomeIcon, {
55
59
  icon: faCircleInfo
56
- })), /*#__PURE__*/React.createElement(List, null), /*#__PURE__*/React.createElement(Button, {
60
+ })), /*#__PURE__*/React.createElement(Button, {
61
+ type: "button",
62
+ variant: "outline-primary",
63
+ className: "m-0 p-0 px-1",
64
+ disabled: !set.vars.length,
65
+ title: "Open set"
66
+ }, /*#__PURE__*/React.createElement(FontAwesomeIcon, {
67
+ icon: openSet ? faChevronUp : faChevronDown
68
+ })), /*#__PURE__*/React.createElement(Button, {
69
+ type: "button",
70
+ variant: "outline-primary",
71
+ className: "m-0 p-0 px-1",
72
+ onClick: e => {
73
+ e.stopPropagation();
74
+ setShowModal(true);
75
+ },
76
+ title: "Add to set"
77
+ }, /*#__PURE__*/React.createElement(FontAwesomeIcon, {
78
+ icon: faPlus
79
+ })), /*#__PURE__*/React.createElement(Button, {
57
80
  type: "button",
58
- key: set.name,
59
81
  variant: isActive ? "primary" : "outline-primary",
60
82
  className: "m-0 p-0 px-1",
61
83
  onClick: e => {
@@ -66,6 +88,10 @@ function SingleSelectionSet(_ref) {
66
88
  title: "Set as color encoding"
67
89
  }, /*#__PURE__*/React.createElement(FontAwesomeIcon, {
68
90
  icon: faDroplet
91
+ }), isMultiple && /*#__PURE__*/React.createElement(FontAwesomeIcon, {
92
+ icon: faPlus,
93
+ size: "xs",
94
+ className: "ps-xs-1"
69
95
  })), /*#__PURE__*/React.createElement(Button, {
70
96
  type: "button",
71
97
  className: "m-0 p-0 px-1",
@@ -81,45 +107,30 @@ function SingleSelectionSet(_ref) {
81
107
  in: openSet
82
108
  }, /*#__PURE__*/React.createElement("div", {
83
109
  className: "mt-2"
84
- }, showSearchBar &&
85
- /*#__PURE__*/
86
- // @TODO: fix how results are displayed, should be placed on top of parent components
87
- React.createElement(SearchBar, {
88
- handleSelect: (d, i) => addVarToSet(d, set, i)
89
- }), /*#__PURE__*/React.createElement("div", {
90
- className: "mx-2"
91
110
  }, /*#__PURE__*/React.createElement(ListGroup, {
92
111
  variant: "flush",
93
- className: "cherita-list"
94
- }, varList)))));
95
- }
96
- function MultipleSelectionSet(_ref2) {
97
- let {
98
- set,
99
- isActive,
100
- toggleSet
101
- } = _ref2;
102
- return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
103
- className: "d-flex"
104
- }, /*#__PURE__*/React.createElement("div", {
105
- className: "flex-grow-1"
106
- }, /*#__PURE__*/React.createElement(Button, {
107
- type: "button",
108
- key: set.name,
109
- variant: isActive ? "primary" : "outline-primary",
110
- className: "m-0 p-0 px-1",
111
- onClick: toggleSet,
112
- title: set.name
113
- }, set.name))));
112
+ className: "cherita-list var-set-list"
113
+ }, varList))), /*#__PURE__*/React.createElement(SearchModal, {
114
+ show: showModal,
115
+ handleClose: () => setShowModal(false),
116
+ text: searchText,
117
+ setText: setSearchText,
118
+ displayText: "features",
119
+ handleSelect: (d, i) => {
120
+ addVarToSet(d, set, i);
121
+ },
122
+ searchVar: true,
123
+ searchDiseases: false
124
+ }));
114
125
  }
115
- export function VarSet(_ref3) {
126
+ export function VarSet(_ref2) {
116
127
  let {
117
128
  set,
118
129
  active,
119
130
  mode = SELECTION_MODES.SINGLE
120
- } = _ref3;
121
- const dataset = useDataset();
122
- const dispatch = useDatasetDispatch();
131
+ } = _ref2;
132
+ const settings = useSettings();
133
+ const dispatch = useSettingsDispatch();
123
134
  const selectSet = () => {
124
135
  if (mode === SELECTION_MODES.SINGLE) {
125
136
  dispatch({
@@ -153,8 +164,8 @@ export function VarSet(_ref3) {
153
164
  }
154
165
  }
155
166
  dispatch({
156
- type: "remove.varSet",
157
- varSet: set
167
+ type: "remove.var",
168
+ var: set
158
169
  });
159
170
  };
160
171
  const removeSetVar = v => {
@@ -165,28 +176,27 @@ export function VarSet(_ref3) {
165
176
  });
166
177
  };
167
178
  const toggleSet = () => {
168
- if (active.includes(set.name)) {
169
- dispatch({
170
- type: "deselect.multivar",
171
- var: set
172
- });
173
- } else {
174
- selectSet();
175
- }
179
+ dispatch({
180
+ type: "toggle.multivar",
181
+ var: set
182
+ });
176
183
  };
177
184
  if (set && mode === SELECTION_MODES.SINGLE) {
178
- return /*#__PURE__*/React.createElement(SingleSelectionSet, {
185
+ return /*#__PURE__*/React.createElement(SelectionSet, {
179
186
  set: set,
180
- isActive: dataset.colorEncoding === COLOR_ENCODINGS.VAR && active === set.name,
187
+ isActive: settings.colorEncoding === COLOR_ENCODINGS.VAR && active === set.name,
181
188
  selectSet: selectSet,
182
189
  removeSet: removeSet,
183
190
  removeSetVar: v => removeSetVar(v)
184
191
  });
185
192
  } else if (mode === SELECTION_MODES.MULTIPLE) {
186
- return /*#__PURE__*/React.createElement(MultipleSelectionSet, {
193
+ return /*#__PURE__*/React.createElement(SelectionSet, {
187
194
  set: set,
188
195
  isActive: _.includes(active, set.name),
189
- toggleSet: () => toggleSet(set)
196
+ selectSet: toggleSet,
197
+ removeSet: removeSet,
198
+ removeSetVar: v => removeSetVar(v),
199
+ isMultiple: true
190
200
  });
191
201
  } else {
192
202
  return null;