@haniffalab/cherita-react 1.2.0-dev.2025-04-30.0a204a1c → 1.2.0-dev.2025-05-16.4367ee63

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.
@@ -4,11 +4,19 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.SearchBar = SearchBar;
7
+ exports.SearchModal = SearchModal;
7
8
  var _react = _interopRequireWildcard(require("react"));
9
+ var _Close = _interopRequireDefault(require("@mui/icons-material/Close"));
8
10
  var _Search = _interopRequireDefault(require("@mui/icons-material/Search"));
9
- var _lodash = _interopRequireDefault(require("lodash"));
10
11
  var _reactBootstrap = require("react-bootstrap");
12
+ var _Col = _interopRequireDefault(require("react-bootstrap/Col"));
13
+ var _Container = _interopRequireDefault(require("react-bootstrap/Container"));
14
+ var _Nav = _interopRequireDefault(require("react-bootstrap/Nav"));
15
+ var _Row = _interopRequireDefault(require("react-bootstrap/Row"));
16
+ var _Tab = _interopRequireDefault(require("react-bootstrap/Tab"));
17
+ var _SearchInfo = require("./SearchInfo");
11
18
  var _SearchResults = require("./SearchResults");
19
+ var _constants = require("../../constants/constants");
12
20
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
21
  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); }
14
22
  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,77 +31,164 @@ function onVarSelect(dispatch, item) {
23
31
  });
24
32
  dispatch({
25
33
  type: "set.colorEncoding",
26
- value: "var"
34
+ value: _constants.COLOR_ENCODINGS.VAR
27
35
  });
28
36
  }
29
- function SearchBar(_ref) {
37
+ function addVarSet(dispatch, _ref) {
30
38
  let {
31
- searchVar = true,
32
- searchDiseases = false,
33
- handleSelect = onVarSelect
39
+ name,
40
+ vars
34
41
  } = _ref;
35
- const [showSuggestions, setShowSuggestions] = (0, _react.useState)(false);
36
- const [text, setText] = (0, _react.useState)("");
37
- const inputRef = (0, _react.useRef)(null);
38
- const displayText = [...(searchVar ? ["features"] : []), ...(searchDiseases ? ["diseases"] : [])].join(" and ");
39
- (0, _react.useEffect)(() => {
40
- if (text.length > 0) {
41
- setShowSuggestions(true);
42
+ dispatch({
43
+ type: "add.varSet",
44
+ varSet: {
45
+ name: name,
46
+ vars: vars,
47
+ isSet: true
42
48
  }
43
- }, [text]);
44
-
45
- //@TODO: Abstract styles
46
- return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Form, {
49
+ });
50
+ }
51
+ const FEATURE_TYPE = {
52
+ VAR: "var",
53
+ DISEASE: "disease"
54
+ };
55
+ function SearchModal(_ref2) {
56
+ let {
57
+ show,
58
+ handleClose,
59
+ text,
60
+ setText,
61
+ displayText,
62
+ handleSelect = onVarSelect,
63
+ searchVar,
64
+ searchDiseases
65
+ } = _ref2;
66
+ const [tab, setTab] = (0, _react.useState)("var");
67
+ const [selectedResult, setSelectedResult] = (0, _react.useState)({
68
+ var: null,
69
+ disease: null
70
+ });
71
+ const [varResultsLength, setVarResultsLength] = (0, _react.useState)(null);
72
+ const [diseaseResultsLength, setDiseaseResultsLength] = (0, _react.useState)(null);
73
+ return /*#__PURE__*/_react.default.createElement(_reactBootstrap.Modal, {
74
+ show: show,
75
+ onHide: handleClose,
76
+ size: "xl"
77
+ }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Modal.Header, {
78
+ className: "bg-primary"
79
+ }, /*#__PURE__*/_react.default.createElement(_Container.default, {
80
+ className: "gx-0"
81
+ }, /*#__PURE__*/_react.default.createElement(_Row.default, null, /*#__PURE__*/_react.default.createElement(_Col.default, {
82
+ xs: 12
83
+ }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Form, {
47
84
  onSubmit: e => {
48
85
  e.preventDefault();
49
86
  }
50
- }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.FormGroup, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.InputGroup, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Form.Control, {
51
- ref: inputRef,
52
- onFocus: () => {
53
- setShowSuggestions(text.length > 0);
54
- },
55
- onBlur: () => {
56
- _lodash.default.delay(() => {
57
- setShowSuggestions(false);
58
- }, 150);
59
- },
87
+ }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.FormGroup, null, /*#__PURE__*/_react.default.createElement("div", {
88
+ className: "d-flex align-items-center"
89
+ }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.InputGroup, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.InputGroup.Text, null, /*#__PURE__*/_react.default.createElement(_Search.default, null)), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Form.Control, {
90
+ autoFocus: true,
60
91
  type: "text",
61
92
  placeholder: "Search " + displayText,
62
93
  value: text,
63
94
  onChange: e => {
64
95
  setText(e.target.value);
65
- },
66
- style: {
67
- paddingLeft: "2.5rem",
68
- borderRadius: "5px"
69
- }
70
- }), /*#__PURE__*/_react.default.createElement("div", {
71
- style: {
72
- position: "absolute",
73
- left: "10px",
74
- top: "50%",
75
- transform: "translateY(-50%)",
76
- pointerEvents: "none",
77
- zIndex: 10
96
+ setSelectedResult({
97
+ var: null,
98
+ disease: null
99
+ });
100
+ setVarResultsLength(null);
101
+ setDiseaseResultsLength(null);
78
102
  }
79
- }, /*#__PURE__*/_react.default.createElement(_Search.default, null))), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown, {
80
- show: showSuggestions,
81
- onMouseDown: e => {
103
+ }), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Button, {
104
+ variant: "light",
105
+ onClick: handleClose
106
+ }, /*#__PURE__*/_react.default.createElement(_Close.default, null)))))))))), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Modal.Body, {
107
+ className: "p-0"
108
+ }, /*#__PURE__*/_react.default.createElement(_Container.default, null, /*#__PURE__*/_react.default.createElement(_Row.default, null, /*#__PURE__*/_react.default.createElement(_Col.default, {
109
+ xs: 12,
110
+ md: 8
111
+ }, /*#__PURE__*/_react.default.createElement(_Tab.default.Container, {
112
+ activeKey: tab,
113
+ onSelect: k => setTab(k)
114
+ }, /*#__PURE__*/_react.default.createElement(_Row.default, {
115
+ className: "w-100"
116
+ }, /*#__PURE__*/_react.default.createElement(_Col.default, {
117
+ sm: 3,
118
+ className: "py-3 border-end"
119
+ }, /*#__PURE__*/_react.default.createElement(_Nav.default, {
120
+ variant: "pills",
121
+ className: "flex-column"
122
+ }, searchVar && /*#__PURE__*/_react.default.createElement(_Nav.default.Item, null, /*#__PURE__*/_react.default.createElement(_Nav.default.Link, {
123
+ eventKey: FEATURE_TYPE.VAR
124
+ }, "Genes", " ", !!varResultsLength && `(${varResultsLength})`)), searchDiseases && /*#__PURE__*/_react.default.createElement(_Nav.default.Item, null, /*#__PURE__*/_react.default.createElement(_Nav.default.Link, {
125
+ eventKey: FEATURE_TYPE.DISEASE
126
+ }, "Diseases", " ", !!diseaseResultsLength && `(${diseaseResultsLength})`)))), /*#__PURE__*/_react.default.createElement(_Col.default, {
127
+ sm: 9,
128
+ className: "py-3"
129
+ }, /*#__PURE__*/_react.default.createElement(_Tab.default.Content, null, searchVar && /*#__PURE__*/_react.default.createElement(_Tab.default.Pane, {
130
+ eventKey: FEATURE_TYPE.VAR
131
+ }, /*#__PURE__*/_react.default.createElement(_SearchResults.VarSearchResults, {
132
+ text: text,
133
+ handleSelect: handleSelect,
134
+ selectedResult: selectedResult.var,
135
+ setSelectedResult: item => setSelectedResult(prev => {
136
+ return {
137
+ ...prev,
138
+ var: item
139
+ };
140
+ }),
141
+ setResultsLength: setVarResultsLength
142
+ })), searchDiseases && /*#__PURE__*/_react.default.createElement(_Tab.default.Pane, {
143
+ eventKey: FEATURE_TYPE.DISEASE
144
+ }, /*#__PURE__*/_react.default.createElement(_SearchResults.DiseasesSearchResults, {
145
+ text: text,
146
+ selectedResult: selectedResult.disease,
147
+ setSelectedResult: item => setSelectedResult(prev => {
148
+ return {
149
+ ...prev,
150
+ disease: item
151
+ };
152
+ }),
153
+ setResultsLength: setDiseaseResultsLength
154
+ }))))))), /*#__PURE__*/_react.default.createElement(_Col.default, {
155
+ xs: 12,
156
+ md: 4,
157
+ className: "bg-light p-3 search-modal-info"
158
+ }, selectedResult[tab] ? tab === FEATURE_TYPE.DISEASE ? /*#__PURE__*/_react.default.createElement(_SearchInfo.DiseaseInfo, {
159
+ disease: selectedResult.disease,
160
+ handleSelect: handleSelect,
161
+ addVarSet: addVarSet
162
+ }) : /*#__PURE__*/_react.default.createElement(_SearchInfo.VarInfo, {
163
+ varItem: selectedResult.var
164
+ }) : /*#__PURE__*/_react.default.createElement("div", {
165
+ className: "text-muted"
166
+ }, "No result selected"))))));
167
+ }
168
+ function SearchBar(_ref3) {
169
+ let {
170
+ searchVar = true,
171
+ searchDiseases = false
172
+ } = _ref3;
173
+ const [text, setText] = (0, _react.useState)("");
174
+ const displayText = [...(searchVar ? ["features"] : []), ...(searchDiseases ? ["diseases"] : [])].join(" and ");
175
+ const [showModal, setShowModal] = (0, _react.useState)(false);
176
+ return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Form, {
177
+ onSubmit: e => {
82
178
  e.preventDefault();
83
- },
84
- onSelect: () => {
85
- inputRef.current.blur();
86
- }
87
- }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown.Menu, {
88
- style: {
89
- width: "90%"
90
179
  }
91
- }, searchVar && /*#__PURE__*/_react.default.createElement(_SearchResults.VarSearchResults, {
92
- text: text,
93
- setShowSuggestions: setShowSuggestions,
94
- handleSelect: handleSelect
95
- }), searchVar && searchDiseases && /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown.Divider, null), searchDiseases && /*#__PURE__*/_react.default.createElement(_SearchResults.DiseasesSearchResults, {
180
+ }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.FormGroup, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.InputGroup, null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.InputGroup.Text, null, /*#__PURE__*/_react.default.createElement(_Search.default, null)), /*#__PURE__*/_react.default.createElement(_reactBootstrap.Form.Control, {
181
+ onClick: () => setShowModal(true),
182
+ type: "text",
183
+ placeholder: "Search " + displayText,
184
+ defaultValue: text
185
+ })))), /*#__PURE__*/_react.default.createElement(SearchModal, {
186
+ show: showModal,
96
187
  text: text,
97
- setShowSuggestions: setShowSuggestions
98
- }))))));
188
+ setText: setText,
189
+ displayText: displayText,
190
+ searchVar: searchVar,
191
+ searchDiseases: searchDiseases,
192
+ handleClose: () => setShowModal(false)
193
+ }));
99
194
  }
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.DiseaseInfo = DiseaseInfo;
7
+ exports.VarInfo = VarInfo;
8
+ var _react = _interopRequireWildcard(require("react"));
9
+ var _freeSolidSvgIcons = require("@fortawesome/free-solid-svg-icons");
10
+ var _reactFontawesome = require("@fortawesome/react-fontawesome");
11
+ var _lodash = _interopRequireDefault(require("lodash"));
12
+ var _reactBootstrap = require("react-bootstrap");
13
+ var _constants = require("../../constants/constants");
14
+ var _DatasetContext = require("../../context/DatasetContext");
15
+ var _requests = require("../../utils/requests");
16
+ var _VarItem = require("../var-list/VarItem");
17
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
18
+ 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); }
19
+ 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; }
20
+ function VarInfo(_ref) {
21
+ let {
22
+ varItem
23
+ } = _ref;
24
+ const ENDPOINT = "disease/gene";
25
+ const dataset = (0, _DatasetContext.useDataset)();
26
+ const [params, setParams] = (0, _react.useState)({
27
+ geneName: varItem.name,
28
+ diseaseDatasets: dataset.diseaseDatasets
29
+ });
30
+ (0, _react.useEffect)(() => {
31
+ setParams(p => {
32
+ return {
33
+ ...p,
34
+ geneName: varItem.name
35
+ };
36
+ });
37
+ }, [varItem.name]);
38
+ const {
39
+ fetchedData,
40
+ isPending,
41
+ serverError
42
+ } = (0, _requests.useFetch)(ENDPOINT, params, {
43
+ refetchOnMount: false,
44
+ enabled: !!dataset.diseaseDatasets.length
45
+ });
46
+ const hasDiseaseInfo = !isPending && !serverError && !!fetchedData?.length;
47
+ return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("h5", null, varItem.name), !!dataset.diseaseDatasets.length && isPending && /*#__PURE__*/_react.default.createElement("p", null, "Loading..."), hasDiseaseInfo && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("h6", null, "Associated diseases"), /*#__PURE__*/_react.default.createElement(_VarItem.VarDiseaseInfo, {
48
+ data: fetchedData
49
+ })));
50
+ }
51
+ const useVarMean = function (varKeys) {
52
+ let enabled = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
53
+ const ENDPOINT = "matrix/mean";
54
+ const dataset = (0, _DatasetContext.useDataset)();
55
+ const [params, setParams] = (0, _react.useState)({
56
+ url: dataset.url,
57
+ varKeys: _lodash.default.map(varKeys, v => v.isSet ? {
58
+ name: v.name,
59
+ indices: v.vars.map(v => v.index)
60
+ } : v.index),
61
+ // obsIndices:
62
+ varNamesCol: dataset.varNamesCol
63
+ });
64
+ (0, _react.useEffect)(() => {
65
+ setParams(p => {
66
+ return {
67
+ ...p,
68
+ varKeys: _lodash.default.map(varKeys, v => v.isSet ? {
69
+ name: v.name,
70
+ indices: v.vars.map(v => v.index)
71
+ } : v.index)
72
+ };
73
+ });
74
+ }, [varKeys]);
75
+ return (0, _requests.useFetch)(ENDPOINT, params, {
76
+ enabled: enabled,
77
+ refetchOnMount: false
78
+ });
79
+ };
80
+
81
+ // ensure nulls are lowest values
82
+ const sortMeans = (i, means) => {
83
+ return means[i.name] || _lodash.default.min(_lodash.default.values(means)) - 1;
84
+ };
85
+ function DiseaseInfo(_ref2) {
86
+ let {
87
+ disease,
88
+ handleSelect,
89
+ addVarSet
90
+ } = _ref2;
91
+ const ENDPOINT = "disease/genes";
92
+ const dataset = (0, _DatasetContext.useDataset)();
93
+ const dispatch = (0, _DatasetContext.useDatasetDispatch)();
94
+ const [diseaseVars, setDiseaseVars] = (0, _react.useState)([]);
95
+ const [sortedDiseaseVars, setSortedDiseaseVars] = (0, _react.useState)([]);
96
+ const [params, setParams] = (0, _react.useState)({
97
+ url: dataset.url,
98
+ col: dataset.varNamesCol,
99
+ diseaseDatasets: dataset.diseaseDatasets,
100
+ diseaseId: disease.id
101
+ });
102
+ (0, _react.useEffect)(() => {
103
+ setParams(p => {
104
+ return {
105
+ ...p,
106
+ diseaseId: disease.id
107
+ };
108
+ });
109
+ }, [disease]);
110
+ const diseaseData = (0, _requests.useFetch)(ENDPOINT, params, {
111
+ enabled: !!params.diseaseId,
112
+ refetchOnMount: true
113
+ });
114
+ (0, _react.useEffect)(() => {
115
+ if (!diseaseData.isPending && !diseaseData.serverError) {
116
+ setDiseaseVars(diseaseData.fetchedData);
117
+ }
118
+ }, [diseaseData.fetchedData, diseaseData.isPending, diseaseData.serverError]);
119
+ const varMeans = useVarMean(diseaseVars, !!diseaseVars?.length && dataset.varSort.disease.sort === _constants.VAR_SORT.MATRIX);
120
+ (0, _react.useEffect)(() => {
121
+ if (dataset.varSort.disease.sort === _constants.VAR_SORT.MATRIX) {
122
+ if (!varMeans.isPending && !varMeans.serverError) {
123
+ setSortedDiseaseVars(_lodash.default.orderBy(diseaseVars, o => {
124
+ return sortMeans(o, varMeans.fetchedData);
125
+ }, dataset.varSort.disease.sortOrder));
126
+ }
127
+ } else if (dataset.varSort.disease.sort === _constants.VAR_SORT.NAME) {
128
+ setSortedDiseaseVars(_lodash.default.orderBy(diseaseVars, "name", dataset.varSort.disease.sortOrder));
129
+ } else {
130
+ setSortedDiseaseVars(diseaseVars);
131
+ }
132
+ }, [dataset.varSort.disease.sort, dataset.varSort.disease.sortOrder, diseaseVars, varMeans.fetchedData, varMeans.isPending, varMeans.serverError]);
133
+ const diseaseVarList = _lodash.default.map(sortedDiseaseVars, v => {
134
+ return /*#__PURE__*/_react.default.createElement(_reactBootstrap.ListGroup.Item, {
135
+ key: v.gene_id
136
+ }, /*#__PURE__*/_react.default.createElement("div", {
137
+ className: "d-flex justify-content-between align-items-center w-100"
138
+ }, v.name, /*#__PURE__*/_react.default.createElement("div", {
139
+ className: "d-flex align-items-center gap-1"
140
+ }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Button, {
141
+ type: "button",
142
+ className: "m-0 p-0 px-1",
143
+ variant: "outline-secondary",
144
+ title: "Add to list",
145
+ onClick: () => {
146
+ handleSelect(dispatch, v);
147
+ }
148
+ }, /*#__PURE__*/_react.default.createElement(_reactFontawesome.FontAwesomeIcon, {
149
+ icon: _freeSolidSvgIcons.faPlus
150
+ })))));
151
+ });
152
+ const isPending = diseaseData.isPending || varMeans.isPending && dataset.varSort.disease.sort === _constants.VAR_SORT.MATRIX;
153
+ return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("h5", null, disease.disease_name), /*#__PURE__*/_react.default.createElement("h6", null, "Implicated genes"), isPending ? /*#__PURE__*/_react.default.createElement("p", null, "Loading...") : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
154
+ className: "d-flex justify-content-end mb-2"
155
+ }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Button, {
156
+ size: "sm",
157
+ title: "Add all as a set",
158
+ onClick: () => {
159
+ addVarSet(dispatch, {
160
+ name: disease.disease_name,
161
+ vars: _lodash.default.map(diseaseVars, v => {
162
+ return {
163
+ index: v.index,
164
+ name: v.name,
165
+ matrix_index: v.matrix_index
166
+ };
167
+ })
168
+ });
169
+ }
170
+ }, /*#__PURE__*/_react.default.createElement(_reactFontawesome.FontAwesomeIcon, {
171
+ icon: _freeSolidSvgIcons.faPlus
172
+ }), " Add all as a set")), /*#__PURE__*/_react.default.createElement(_reactBootstrap.ListGroup, {
173
+ className: "overflow-scroll"
174
+ }, diseaseVarList)));
175
+ }
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.DiseasesSearchResults = DiseasesSearchResults;
7
7
  exports.VarSearchResults = VarSearchResults;
8
8
  var _react = _interopRequireWildcard(require("react"));
9
+ var _freeSolidSvgIcons = require("@fortawesome/free-solid-svg-icons");
10
+ var _reactFontawesome = require("@fortawesome/react-fontawesome");
9
11
  var _lodash = _interopRequireDefault(require("lodash"));
10
12
  var _reactBootstrap = require("react-bootstrap");
11
13
  var _DatasetContext = require("../../context/DatasetContext");
@@ -17,8 +19,10 @@ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e;
17
19
  function VarSearchResults(_ref) {
18
20
  let {
19
21
  text,
20
- setShowSuggestions,
21
- handleSelect
22
+ handleSelect,
23
+ selectedResult,
24
+ setSelectedResult,
25
+ setResultsLength
22
26
  } = _ref;
23
27
  const [suggestions, setSuggestions] = (0, _react.useState)([]);
24
28
  const dispatch = (0, _DatasetContext.useDatasetDispatch)();
@@ -43,51 +47,68 @@ function VarSearchResults(_ref) {
43
47
  });
44
48
  } else {
45
49
  setSuggestions([]);
46
- setShowSuggestions(false);
47
50
  }
48
51
  };
49
52
  return _lodash.default.debounce(setData, 300);
50
- }, [setParams, setShowSuggestions]);
53
+ }, [setParams]);
51
54
  (0, _react.useEffect)(() => {
52
55
  updateParams(text);
53
56
  }, [text, updateParams]);
54
57
  (0, _react.useEffect)(() => {
55
58
  if (!isPending && !serverError) {
56
59
  setSuggestions(fetchedData);
57
- setShowSuggestions(true);
60
+ setResultsLength(fetchedData?.length);
58
61
  }
59
- }, [fetchedData, isPending, serverError, setShowSuggestions]);
62
+ }, [fetchedData, isPending, serverError, setResultsLength]);
60
63
  const getDataAtIndex = index => deferredData[index];
61
- const ItemComponent = item => /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown.Item, {
62
- key: item.name,
63
- as: "button",
64
+ const ItemComponent = item => /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
65
+ className: "virtualized-list-wrapper"
66
+ }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.ListGroup.Item, {
67
+ key: item,
68
+ onClick: () => {
69
+ setSelectedResult(item);
70
+ },
71
+ active: selectedResult?.index === item.index
72
+ }, /*#__PURE__*/_react.default.createElement("div", {
73
+ className: "d-flex justify-content-between align-items-center w-100"
74
+ }, /*#__PURE__*/_react.default.createElement("div", null, item.name), /*#__PURE__*/_react.default.createElement("div", {
75
+ className: "d-flex align-items-center gap-1"
76
+ }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Button, {
77
+ type: "button",
78
+ className: "m-0 p-0 px-1",
79
+ variant: "outline-secondary",
80
+ title: "Add to list",
64
81
  disabled: isStale,
65
82
  onClick: () => {
66
83
  handleSelect(dispatch, item);
67
- _lodash.default.delay(() => {
68
- setShowSuggestions(false);
69
- }, 150);
70
84
  }
71
- }, item.name);
72
- return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown.Header, null, "Features"), /*#__PURE__*/_react.default.createElement("div", {
85
+ }, /*#__PURE__*/_react.default.createElement(_reactFontawesome.FontAwesomeIcon, {
86
+ icon: _freeSolidSvgIcons.faPlus
87
+ })))))));
88
+ return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("div", {
73
89
  className: "search-results"
90
+ }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.ListGroup, {
91
+ variant: "flush",
92
+ className: "cherita-list"
74
93
  }, deferredData?.length ? /*#__PURE__*/_react.default.createElement(_VirtualizedList.VirtualizedList, {
75
94
  getDataAtIndex: getDataAtIndex,
76
95
  count: deferredData.length,
77
96
  ItemComponent: ItemComponent,
78
97
  overscan: 500,
79
- estimateSize: 32,
80
- maxHeight: "25vh"
81
- }) : /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown.Item, {
98
+ estimateSize: 42,
99
+ maxHeight: "70vh"
100
+ }) : /*#__PURE__*/_react.default.createElement(_reactBootstrap.ListGroup.Item, {
82
101
  key: "empty",
83
102
  as: "button",
84
103
  disabled: true
85
- }, !serverError ? isStale || isPending ? "Loading..." : "No items found" : "Failed to fetch data")));
104
+ }, !text.length ? "Search features" : !serverError ? isStale || isPending ? "Loading..." : "No items found" : "Failed to fetch data"))));
86
105
  }
87
106
  function DiseasesSearchResults(_ref2) {
88
107
  let {
89
108
  text,
90
- setShowSuggestions
109
+ selectedResult,
110
+ setSelectedResult,
111
+ setResultsLength
91
112
  } = _ref2;
92
113
  const [suggestions, setSuggestions] = (0, _react.useState)([]);
93
114
  const dispatch = (0, _DatasetContext.useDatasetDispatch)();
@@ -122,37 +143,41 @@ function DiseasesSearchResults(_ref2) {
122
143
  (0, _react.useEffect)(() => {
123
144
  if (!isPending && !serverError) {
124
145
  setSuggestions(fetchedData);
125
- setShowSuggestions(true);
146
+ setResultsLength(fetchedData?.length);
126
147
  }
127
- }, [fetchedData, isPending, serverError, setShowSuggestions]);
148
+ }, [fetchedData, isPending, serverError, setResultsLength]);
128
149
  const getDataAtIndex = index => deferredData[index];
129
- const ItemComponent = item => /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown.Item, {
150
+ const ItemComponent = item => /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
151
+ className: "virtualized-list-wrapper"
152
+ }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.ListGroup.Item, {
130
153
  key: item.name,
131
- as: "button",
132
- disabled: isStale,
133
154
  onClick: () => {
155
+ setSelectedResult(item);
134
156
  dispatch({
135
157
  type: "select.disease",
136
158
  id: item.disease_id,
137
159
  name: item.disease_name
138
160
  });
139
- _lodash.default.delay(() => {
140
- setShowSuggestions(false);
141
- }, 150);
142
- }
143
- }, item.disease_name);
144
- return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown.Header, null, "Diseases"), /*#__PURE__*/_react.default.createElement("div", {
161
+ },
162
+ active: selectedResult?.id === item.id
163
+ }, /*#__PURE__*/_react.default.createElement("div", {
164
+ className: "d-flex justify-content-between align-items-center w-100"
165
+ }, /*#__PURE__*/_react.default.createElement("div", null, item.disease_name)))));
166
+ return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("div", {
145
167
  className: "search-results"
168
+ }, /*#__PURE__*/_react.default.createElement(_reactBootstrap.ListGroup, {
169
+ variant: "flush",
170
+ className: "cherita-list"
146
171
  }, deferredData?.length ? /*#__PURE__*/_react.default.createElement(_VirtualizedList.VirtualizedList, {
147
172
  getDataAtIndex: getDataAtIndex,
148
173
  count: deferredData.length,
149
174
  ItemComponent: ItemComponent,
150
175
  overscan: 250,
151
176
  estimateSize: 32,
152
- maxHeight: "25vh"
153
- }) : /*#__PURE__*/_react.default.createElement(_reactBootstrap.Dropdown.Item, {
177
+ maxHeight: "70vh"
178
+ }) : /*#__PURE__*/_react.default.createElement(_reactBootstrap.ListGroup.Item, {
154
179
  key: "empty",
155
180
  as: "button",
156
181
  disabled: true
157
- }, !serverError ? isStale || isPending ? "Loading..." : "No items found" : "Failed to fetch data")));
182
+ }, !text.length ? "Search diseases" : !serverError ? isStale || isPending ? "Loading..." : "No items found" : "Failed to fetch data"))));
158
183
  }
@@ -3,7 +3,9 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ exports.SearchResultItem = SearchResultItem;
6
7
  exports.SingleSelectionItem = SingleSelectionItem;
8
+ exports.VarDiseaseInfo = VarDiseaseInfo;
7
9
  exports.VarItem = VarItem;
8
10
  var _react = _interopRequireWildcard(require("react"));
9
11
  var _freeSolidSvgIcons = require("@fortawesome/free-solid-svg-icons");
@@ -265,4 +267,72 @@ function VarItem(_ref5) {
265
267
  } else {
266
268
  return null;
267
269
  }
270
+ }
271
+ function SearchResultItem(_ref6) {
272
+ let {
273
+ item,
274
+ isActive,
275
+ selectVar,
276
+ removeVar,
277
+ isDiseaseGene = false,
278
+ showSetColorEncoding = true,
279
+ showRemove = true
280
+ } = _ref6;
281
+ const ENDPOINT = "disease/gene";
282
+ const [openInfo, setOpenInfo] = (0, _react.useState)(false);
283
+ const dataset = (0, _DatasetContext.useDataset)();
284
+ const params = {
285
+ geneName: item.name,
286
+ diseaseDatasets: dataset.diseaseDatasets
287
+ };
288
+ const isNotInData = item.matrix_index === -1;
289
+ const {
290
+ fetchedData,
291
+ isPending,
292
+ serverError
293
+ } = (0, _requests.useFetch)(ENDPOINT, params, {
294
+ refetchOnMount: false,
295
+ enabled: !!dataset.diseaseDatasets.length
296
+ });
297
+ const hasDiseaseInfo = !isPending && !serverError && !!fetchedData?.length;
298
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
299
+ className: `d-flex justify-content-between ${hasDiseaseInfo ? "cursor-pointer" : ""}`,
300
+ onClick: () => {
301
+ setOpenInfo(o => !o);
302
+ }
303
+ }, /*#__PURE__*/_react.default.createElement("div", {
304
+ className: "d-flex justify-content-between align-items-center w-100"
305
+ }, /*#__PURE__*/_react.default.createElement("div", null, item.name), /*#__PURE__*/_react.default.createElement("div", {
306
+ className: "d-flex align-items-center gap-1"
307
+ }, hasDiseaseInfo && /*#__PURE__*/_react.default.createElement(_iconsMaterial.MoreVert, null), showSetColorEncoding && /*#__PURE__*/_react.default.createElement(_reactBootstrap.Button, {
308
+ type: "button",
309
+ key: item.matrix_index,
310
+ variant: isActive ? "primary" : isNotInData ? "outline-secondary" : "outline-primary",
311
+ className: "m-0 p-0 px-1",
312
+ onClick: e => {
313
+ e.stopPropagation();
314
+ selectVar();
315
+ },
316
+ disabled: isNotInData,
317
+ title: isNotInData ? "Not present in data" : "Set as color encoding"
318
+ }, /*#__PURE__*/_react.default.createElement(_reactFontawesome.FontAwesomeIcon, {
319
+ icon: _freeSolidSvgIcons.faDroplet
320
+ })), (!isDiseaseGene || !showRemove) && /*#__PURE__*/_react.default.createElement(_reactBootstrap.Button, {
321
+ type: "button",
322
+ className: "m-0 p-0 px-1",
323
+ variant: "outline-secondary",
324
+ title: "Remove from list",
325
+ onClick: e => {
326
+ e.stopPropagation();
327
+ removeVar();
328
+ }
329
+ }, /*#__PURE__*/_react.default.createElement(_reactFontawesome.FontAwesomeIcon, {
330
+ icon: _freeSolidSvgIcons.faTrash
331
+ }))))), hasDiseaseInfo && /*#__PURE__*/_react.default.createElement(_reactBootstrap.Collapse, {
332
+ in: openInfo
333
+ }, /*#__PURE__*/_react.default.createElement("div", {
334
+ className: "mt-2 var-disease-info-collapse"
335
+ }, /*#__PURE__*/_react.default.createElement(VarDiseaseInfo, {
336
+ data: fetchedData
337
+ }))));
268
338
  }