@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.
- package/dist/cjs/components/search-bar/SearchBar.js +152 -57
- package/dist/cjs/components/search-bar/SearchInfo.js +175 -0
- package/dist/cjs/components/search-bar/SearchResults.js +58 -33
- package/dist/cjs/components/var-list/VarItem.js +70 -0
- package/dist/cjs/components/var-list/VarList.js +7 -91
- package/dist/cjs/components/var-list/VarSet.js +42 -16
- package/dist/css/cherita.css +20 -0
- package/dist/css/cherita.css.map +1 -1
- package/dist/esm/components/search-bar/SearchBar.js +153 -59
- package/dist/esm/components/search-bar/SearchInfo.js +165 -0
- package/dist/esm/components/search-bar/SearchResults.js +60 -35
- package/dist/esm/components/var-list/VarItem.js +70 -2
- package/dist/esm/components/var-list/VarList.js +7 -91
- package/dist/esm/components/var-list/VarSet.js +44 -18
- package/package.json +2 -2
- package/scss/cherita.scss +6 -0
- package/scss/components/layouts.scss +5 -0
- package/scss/components/lists.scss +11 -0
|
@@ -4,13 +4,13 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
|
4
4
|
import _ from "lodash";
|
|
5
5
|
import { Alert, Button, ListGroup } from "react-bootstrap";
|
|
6
6
|
import ButtonGroup from "react-bootstrap/ButtonGroup";
|
|
7
|
+
import { VarItem } from "./VarItem";
|
|
8
|
+
import { VarListToolbar } from "./VarListToolbar";
|
|
9
|
+
import { VarSet } from "./VarSet";
|
|
7
10
|
import { SELECTION_MODES, VAR_SORT } from "../../constants/constants";
|
|
8
11
|
import { useDataset, useDatasetDispatch } from "../../context/DatasetContext";
|
|
9
12
|
import { LoadingSpinner } from "../../utils/LoadingIndicators";
|
|
10
13
|
import { useFetch } from "../../utils/requests";
|
|
11
|
-
import { VarItem } from "./VarItem";
|
|
12
|
-
import { VarListToolbar } from "./VarListToolbar";
|
|
13
|
-
import { VarSet } from "./VarSet";
|
|
14
14
|
const useVarMean = function (varKeys) {
|
|
15
15
|
let enabled = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
16
16
|
const ENDPOINT = "matrix/mean";
|
|
@@ -45,93 +45,11 @@ const useVarMean = function (varKeys) {
|
|
|
45
45
|
const sortMeans = (i, means) => {
|
|
46
46
|
return means[i.name] || _.min(_.values(means)) - 1;
|
|
47
47
|
};
|
|
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) {
|
|
48
|
+
export function VarNamesList(_ref) {
|
|
130
49
|
let {
|
|
131
50
|
mode = SELECTION_MODES.SINGLE,
|
|
132
|
-
displayName = "genes"
|
|
133
|
-
|
|
134
|
-
} = _ref2;
|
|
51
|
+
displayName = "genes"
|
|
52
|
+
} = _ref;
|
|
135
53
|
const dataset = useDataset();
|
|
136
54
|
const dispatch = useDatasetDispatch();
|
|
137
55
|
const [varButtons, setVarButtons] = useState(mode === SELECTION_MODES.SINGLE ? dataset.selectedVar ? _.unionWith([dataset.selectedVar], dataset.varSets, _.isEqual) : [...dataset.varSets] : [...dataset.selectedMultiVar, ...dataset.varSets]);
|
|
@@ -285,7 +203,5 @@ export function VarNamesList(_ref2) {
|
|
|
285
203
|
}, isPending && /*#__PURE__*/React.createElement(LoadingSpinner, null), /*#__PURE__*/React.createElement(ListGroup, {
|
|
286
204
|
variant: "flush",
|
|
287
205
|
className: "cherita-list"
|
|
288
|
-
}, varList))))
|
|
289
|
-
makeListItem: makeListItem
|
|
290
|
-
}))));
|
|
206
|
+
}, varList))))));
|
|
291
207
|
}
|
|
@@ -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 { SingleSelectionItem } from "./VarItem";
|
|
7
7
|
import { COLOR_ENCODINGS, SELECTION_MODES } from "../../constants/constants";
|
|
8
8
|
import { useDataset, useDatasetDispatch } from "../../context/DatasetContext";
|
|
9
|
-
import {
|
|
10
|
-
import { SingleSelectionItem } from "./VarItem";
|
|
9
|
+
import { SearchModal } from "../search-bar/SearchBar";
|
|
11
10
|
|
|
12
11
|
// @TODO: add button to score genes and plot
|
|
13
12
|
|
|
@@ -24,10 +23,11 @@ function SingleSelectionSet(_ref) {
|
|
|
24
23
|
isActive,
|
|
25
24
|
selectSet,
|
|
26
25
|
removeSet,
|
|
27
|
-
removeSetVar
|
|
28
|
-
showSearchBar = true
|
|
26
|
+
removeSetVar
|
|
29
27
|
} = _ref;
|
|
30
28
|
const [openSet, setOpenSet] = useState(false);
|
|
29
|
+
const [showModal, setShowModal] = useState(false);
|
|
30
|
+
const [searchText, setSearchText] = useState("");
|
|
31
31
|
const varList = set.vars.length ? _.map(set.vars, v => {
|
|
32
32
|
return /*#__PURE__*/React.createElement(ListGroup.Item, {
|
|
33
33
|
key: v.name
|
|
@@ -46,16 +46,38 @@ function SingleSelectionSet(_ref) {
|
|
|
46
46
|
}
|
|
47
47
|
}, /*#__PURE__*/React.createElement("div", {
|
|
48
48
|
className: "d-flex justify-content-between align-items-center w-100"
|
|
49
|
-
}, /*#__PURE__*/React.createElement("div",
|
|
49
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
50
|
+
className: "ellipsis-text",
|
|
51
|
+
title: set.name
|
|
52
|
+
}, set.name), /*#__PURE__*/React.createElement("div", {
|
|
50
53
|
className: "d-flex align-items-center gap-1"
|
|
51
54
|
}, /*#__PURE__*/React.createElement(OverlayTrigger, {
|
|
52
55
|
placement: "top",
|
|
53
56
|
overlay: /*#__PURE__*/React.createElement(Tooltip, null, "This set represents the mean value of its features")
|
|
54
57
|
}, /*#__PURE__*/React.createElement(FontAwesomeIcon, {
|
|
55
58
|
icon: faCircleInfo
|
|
56
|
-
})), /*#__PURE__*/React.createElement(
|
|
59
|
+
})), /*#__PURE__*/React.createElement(Button, {
|
|
60
|
+
type: "button",
|
|
61
|
+
variant: "outline-primary",
|
|
62
|
+
className: "m-0 p-0 px-1",
|
|
63
|
+
disabled: !set.vars.length,
|
|
64
|
+
title: "Open set"
|
|
65
|
+
}, /*#__PURE__*/React.createElement(FontAwesomeIcon, {
|
|
66
|
+
icon: openSet ? faChevronUp : faChevronDown
|
|
67
|
+
})), /*#__PURE__*/React.createElement(Button, {
|
|
68
|
+
type: "button",
|
|
69
|
+
variant: "outline-primary",
|
|
70
|
+
className: "m-0 p-0 px-1",
|
|
71
|
+
onClick: e => {
|
|
72
|
+
e.stopPropagation();
|
|
73
|
+
setShowModal(true);
|
|
74
|
+
},
|
|
75
|
+
disabled: !set.vars.length,
|
|
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 => {
|
|
@@ -81,17 +103,21 @@ function SingleSelectionSet(_ref) {
|
|
|
81
103
|
in: openSet
|
|
82
104
|
}, /*#__PURE__*/React.createElement("div", {
|
|
83
105
|
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
106
|
}, /*#__PURE__*/React.createElement(ListGroup, {
|
|
92
107
|
variant: "flush",
|
|
93
|
-
className: "cherita-list"
|
|
94
|
-
}, varList)))
|
|
108
|
+
className: "cherita-list var-set-list"
|
|
109
|
+
}, varList))), /*#__PURE__*/React.createElement(SearchModal, {
|
|
110
|
+
show: showModal,
|
|
111
|
+
handleClose: () => setShowModal(false),
|
|
112
|
+
text: searchText,
|
|
113
|
+
setText: setSearchText,
|
|
114
|
+
displayText: "features",
|
|
115
|
+
handleSelect: (d, i) => {
|
|
116
|
+
addVarToSet(d, set, i);
|
|
117
|
+
},
|
|
118
|
+
searchVar: true,
|
|
119
|
+
searchDiseases: false
|
|
120
|
+
}));
|
|
95
121
|
}
|
|
96
122
|
function MultipleSelectionSet(_ref2) {
|
|
97
123
|
let {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@haniffalab/cherita-react",
|
|
3
|
-
"version": "1.2.0-dev.2025-
|
|
3
|
+
"version": "1.2.0-dev.2025-05-16.4367ee63",
|
|
4
4
|
"author": "Haniffa Lab",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -124,5 +124,5 @@
|
|
|
124
124
|
"url": "https://github.com/haniffalab/cherita-react/issues"
|
|
125
125
|
},
|
|
126
126
|
"homepage": "https://github.com/haniffalab/cherita-react#readme",
|
|
127
|
-
"prereleaseSha": "
|
|
127
|
+
"prereleaseSha": "4367ee63df5209cda070f21e714ac5c6ccaa1e2c"
|
|
128
128
|
}
|
package/scss/cherita.scss
CHANGED
|
@@ -13,6 +13,10 @@
|
|
|
13
13
|
color: var(--#{$prefix}body-color);
|
|
14
14
|
background-color: var(--#{$prefix}tertiary-bg);
|
|
15
15
|
border-radius: var(--#{$prefix}border-radius);
|
|
16
|
+
cursor: pointer;
|
|
17
|
+
}
|
|
18
|
+
.list-group-item.active {
|
|
19
|
+
background-color: var(--#{$prefix}secondary-bg);
|
|
16
20
|
}
|
|
17
21
|
}
|
|
18
22
|
.obs-statistics {
|
|
@@ -24,3 +28,10 @@
|
|
|
24
28
|
background-color: var(--#{$prefix}tertiary-bg);
|
|
25
29
|
border-radius: var(--#{$prefix}border-radius);
|
|
26
30
|
}
|
|
31
|
+
|
|
32
|
+
.cherita-list.var-set-list {
|
|
33
|
+
.list-group-item {
|
|
34
|
+
padding-right: 0;
|
|
35
|
+
padding-left: 0.35rem;
|
|
36
|
+
}
|
|
37
|
+
}
|