@haniffalab/cherita-react 1.1.1 → 1.2.0-dev.2025-04-09.382ade7b
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/obs-list/ObsItem.js +22 -96
- package/dist/cjs/components/obs-list/ObsList.js +19 -56
- package/dist/cjs/components/var-list/VarItem.js +14 -10
- package/dist/cjs/utils/VirtualizedList.js +1 -1
- package/dist/css/cherita.css +36 -17
- package/dist/css/cherita.css.map +1 -1
- package/dist/esm/components/obs-list/ObsItem.js +23 -97
- package/dist/esm/components/obs-list/ObsList.js +19 -57
- package/dist/esm/components/var-list/VarItem.js +14 -10
- package/dist/esm/utils/VirtualizedList.js +1 -1
- package/package.json +4 -3
- package/scss/cherita.scss +10 -8
- package/scss/components/accordions.scss +5 -0
- package/scss/components/lists.scss +15 -3
|
@@ -9,14 +9,11 @@ import { Alert } from "react-bootstrap";
|
|
|
9
9
|
import Accordion from "react-bootstrap/Accordion";
|
|
10
10
|
import { useAccordionButton } from "react-bootstrap/AccordionButton";
|
|
11
11
|
import AccordionContext from "react-bootstrap/AccordionContext";
|
|
12
|
+
import { CategoricalObs, ContinuousObs } from "./ObsItem";
|
|
12
13
|
import { COLOR_ENCODINGS, DEFAULT_OBS_GROUP, OBS_TYPES } from "../../constants/constants";
|
|
13
14
|
import { useDataset, useDatasetDispatch } from "../../context/DatasetContext";
|
|
14
15
|
import { LoadingSpinner } from "../../utils/LoadingIndicators";
|
|
15
16
|
import { useFetch } from "../../utils/requests";
|
|
16
|
-
import { CategoricalObs, ContinuousObs } from "./ObsItem";
|
|
17
|
-
|
|
18
|
-
// @TODO: integrate ObsAccordionToggle with ObsColsList active, expandedItems, etc. to avoid duplication
|
|
19
|
-
|
|
20
17
|
const ObsAccordionToggle = _ref => {
|
|
21
18
|
let {
|
|
22
19
|
children,
|
|
@@ -26,10 +23,10 @@ const ObsAccordionToggle = _ref => {
|
|
|
26
23
|
const {
|
|
27
24
|
activeEventKey
|
|
28
25
|
} = useContext(AccordionContext);
|
|
26
|
+
const isCurrentEventKey = (activeEventKey || []).includes(eventKey);
|
|
29
27
|
const decoratedOnClick = useAccordionButton(eventKey, () => {
|
|
30
|
-
handleAccordionToggle(eventKey);
|
|
28
|
+
handleAccordionToggle(eventKey, isCurrentEventKey);
|
|
31
29
|
});
|
|
32
|
-
const isCurrentEventKey = Array.isArray(activeEventKey) ? activeEventKey.includes(eventKey) : activeEventKey === eventKey;
|
|
33
30
|
return /*#__PURE__*/React.createElement("div", {
|
|
34
31
|
className: `obs-accordion-header ${isCurrentEventKey ? "active" : ""}`,
|
|
35
32
|
onClick: decoratedOnClick
|
|
@@ -51,8 +48,7 @@ export function ObsColsList(_ref2) {
|
|
|
51
48
|
const dispatch = useDatasetDispatch();
|
|
52
49
|
const [enableGroups, setEnableGroups] = useState(enableObsGroups);
|
|
53
50
|
const [obsCols, setObsCols] = useState(null);
|
|
54
|
-
const [active, setActive] = useState(dataset.selectedObs?.name);
|
|
55
|
-
const [expandedItems, setExpandedItems] = useState({});
|
|
51
|
+
const [active, setActive] = useState([...[dataset.selectedObs?.name]]);
|
|
56
52
|
const [params, setParams] = useState({
|
|
57
53
|
url: dataset.url
|
|
58
54
|
});
|
|
@@ -105,26 +101,10 @@ export function ObsColsList(_ref2) {
|
|
|
105
101
|
}), "name"));
|
|
106
102
|
}
|
|
107
103
|
}, [fetchedData, isPending, obsGroups, serverError, enableGroups]);
|
|
108
|
-
useEffect(() => {
|
|
109
|
-
if (obsCols && Object.keys(expandedItems).length === 0) {
|
|
110
|
-
const initialExpanded = Object.keys(obsCols).reduce((acc, key) => {
|
|
111
|
-
acc[key] = false;
|
|
112
|
-
return acc;
|
|
113
|
-
}, {});
|
|
114
|
-
if (active && obsCols[active]) {
|
|
115
|
-
initialExpanded[active] = true;
|
|
116
|
-
}
|
|
117
|
-
setExpandedItems(initialExpanded);
|
|
118
|
-
}
|
|
119
|
-
}, [obsCols, expandedItems, active]);
|
|
120
|
-
|
|
121
|
-
// @TODO: fix re-rendering performance issue
|
|
122
104
|
useEffect(() => {
|
|
123
105
|
if (obsCols) {
|
|
124
|
-
if (obsCols[dataset.selectedObs?.name]) {
|
|
125
|
-
setActive(
|
|
126
|
-
} else {
|
|
127
|
-
setActive(null);
|
|
106
|
+
if (!obsCols[dataset.selectedObs?.name]) {
|
|
107
|
+
setActive([]);
|
|
128
108
|
dispatch({
|
|
129
109
|
type: "select.obs",
|
|
130
110
|
obs: null
|
|
@@ -132,25 +112,12 @@ export function ObsColsList(_ref2) {
|
|
|
132
112
|
}
|
|
133
113
|
}
|
|
134
114
|
}, [dataset.selectedObs, dispatch, obsCols]);
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
});
|
|
142
|
-
};
|
|
143
|
-
const handleAccordionToggle = itemName => {
|
|
144
|
-
_.delay(
|
|
145
|
-
// to avoid contents of accordion disappearing while closing
|
|
146
|
-
() => {
|
|
147
|
-
setExpandedItems(prev => {
|
|
148
|
-
return {
|
|
149
|
-
...prev,
|
|
150
|
-
[itemName]: !prev[itemName]
|
|
151
|
-
};
|
|
152
|
-
});
|
|
153
|
-
}, expandedItems[itemName] ? 250 : 0);
|
|
115
|
+
const handleAccordionToggle = (itemName, isCurrentEventKey) => {
|
|
116
|
+
if (isCurrentEventKey) {
|
|
117
|
+
_.delay(() => setActive(prev => _.without(prev, itemName)), 250);
|
|
118
|
+
} else {
|
|
119
|
+
setActive(prev => [...prev, itemName]);
|
|
120
|
+
}
|
|
154
121
|
};
|
|
155
122
|
const toggleAll = item => {
|
|
156
123
|
const omit = item.omit.length ? [] : _.map(item.values, v => item.codes[v]);
|
|
@@ -163,7 +130,7 @@ export function ObsColsList(_ref2) {
|
|
|
163
130
|
}
|
|
164
131
|
};
|
|
165
132
|
});
|
|
166
|
-
if (
|
|
133
|
+
if (dataset.selectedObs?.name === item.name) {
|
|
167
134
|
dispatch({
|
|
168
135
|
type: "select.obs",
|
|
169
136
|
obs: {
|
|
@@ -223,7 +190,7 @@ export function ObsColsList(_ref2) {
|
|
|
223
190
|
}
|
|
224
191
|
};
|
|
225
192
|
});
|
|
226
|
-
if (
|
|
193
|
+
if (dataset.selectedObs?.name === item.name) {
|
|
227
194
|
dispatch({
|
|
228
195
|
type: "select.obs",
|
|
229
196
|
obs: {
|
|
@@ -274,20 +241,18 @@ export function ObsColsList(_ref2) {
|
|
|
274
241
|
eventKey: item.name
|
|
275
242
|
}, /*#__PURE__*/React.createElement("div", {
|
|
276
243
|
className: "obs-accordion-body"
|
|
277
|
-
},
|
|
244
|
+
}, active.includes(item.name) && (item.type === OBS_TYPES.CATEGORICAL || item.type === OBS_TYPES.BOOLEAN ? /*#__PURE__*/React.createElement(CategoricalObs, {
|
|
278
245
|
key: item.name,
|
|
279
246
|
obs: item,
|
|
280
|
-
updateObs: updateObs,
|
|
281
247
|
toggleAll: () => toggleAll(item),
|
|
282
248
|
toggleObs: value => toggleObs(item, value),
|
|
283
249
|
toggleLabel: () => toggleLabel(item),
|
|
284
250
|
toggleSlice: () => toggleSlice(item),
|
|
285
251
|
toggleColor: () => toggleColor(item),
|
|
286
|
-
showColor: showColor
|
|
252
|
+
showColor: showColor && isColorEncoding
|
|
287
253
|
}) : /*#__PURE__*/React.createElement(ContinuousObs, {
|
|
288
254
|
key: item.name,
|
|
289
255
|
obs: item,
|
|
290
|
-
updateObs: updateObs,
|
|
291
256
|
toggleAll: () => toggleAll(item),
|
|
292
257
|
toggleObs: value => toggleObs(item, value),
|
|
293
258
|
toggleLabel: () => toggleLabel(item),
|
|
@@ -314,11 +279,8 @@ export function ObsColsList(_ref2) {
|
|
|
314
279
|
}, groupItems));
|
|
315
280
|
}
|
|
316
281
|
});
|
|
317
|
-
const obsList = enableGroups ? /*#__PURE__*/React.createElement(
|
|
318
|
-
|
|
319
|
-
flush: true,
|
|
320
|
-
alwaysOpen: true
|
|
321
|
-
}, groupList) : _.map(_.sortBy(obsCols, o => _.lowerCase(o.name)), item => obsItem(item));
|
|
282
|
+
const obsList = enableGroups ? /*#__PURE__*/React.createElement(React.Fragment, null, groupList) : _.map(_.sortBy(obsCols, o => _.lowerCase(o.name)), item => obsItem(item));
|
|
283
|
+
const defaultActiveGroup = enableGroups ? `group-${_.findKey(obsGroups, g => g.includes(active?.[0]))}` : null;
|
|
322
284
|
if (!serverError) {
|
|
323
285
|
return /*#__PURE__*/React.createElement("div", {
|
|
324
286
|
className: "position-relative h-100"
|
|
@@ -326,7 +288,7 @@ export function ObsColsList(_ref2) {
|
|
|
326
288
|
variant: "danger"
|
|
327
289
|
}, "No observations found.") : /*#__PURE__*/React.createElement(Accordion, {
|
|
328
290
|
flush: true,
|
|
329
|
-
defaultActiveKey: [active],
|
|
291
|
+
defaultActiveKey: [...active, ...[defaultActiveGroup]],
|
|
330
292
|
alwaysOpen: true,
|
|
331
293
|
className: "obs-accordion"
|
|
332
294
|
}, obsList));
|
|
@@ -51,11 +51,11 @@ function VarHistogram(_ref) {
|
|
|
51
51
|
function VarDiseaseInfoItem(item) {
|
|
52
52
|
const dispatch = useDatasetDispatch();
|
|
53
53
|
return /*#__PURE__*/React.createElement(ListGroup.Item, {
|
|
54
|
-
key: item.
|
|
54
|
+
key: item.disease_id,
|
|
55
55
|
className: "feature-disease-info"
|
|
56
|
-
}, /*#__PURE__*/React.createElement("
|
|
56
|
+
}, /*#__PURE__*/React.createElement("button", {
|
|
57
57
|
type: "button",
|
|
58
|
-
className: "btn btn-link",
|
|
58
|
+
className: "btn btn-link disease-link",
|
|
59
59
|
onClick: () => {
|
|
60
60
|
dispatch({
|
|
61
61
|
type: "select.disease",
|
|
@@ -63,25 +63,29 @@ function VarDiseaseInfoItem(item) {
|
|
|
63
63
|
name: item.disease_name
|
|
64
64
|
});
|
|
65
65
|
}
|
|
66
|
-
}, item.disease_name), /*#__PURE__*/React.createElement(
|
|
67
|
-
striped: true
|
|
66
|
+
}, item.disease_name), /*#__PURE__*/React.createElement(Table, {
|
|
67
|
+
striped: true,
|
|
68
|
+
size: "sm",
|
|
69
|
+
responsive: true
|
|
68
70
|
}, /*#__PURE__*/React.createElement("tbody", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "Confidence"), /*#__PURE__*/React.createElement("td", null, item.confidence || "unknown")), /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "Organ", item.organs.length > 1 ? "s" : ""), /*#__PURE__*/React.createElement("td", null, item.organs.map(o => o.name).join(", "))), !_.isEmpty(item.metadata) && _.map(item.metadata, (value, key) => {
|
|
69
71
|
if (value !== null && value !== undefined) {
|
|
70
|
-
return /*#__PURE__*/React.createElement("tr",
|
|
72
|
+
return /*#__PURE__*/React.createElement("tr", {
|
|
73
|
+
key: key
|
|
74
|
+
}, /*#__PURE__*/React.createElement("td", null, _.upperFirst(key)), /*#__PURE__*/React.createElement("td", null, value));
|
|
71
75
|
}
|
|
72
|
-
}))))
|
|
76
|
+
}))));
|
|
73
77
|
}
|
|
74
78
|
function VarDiseaseInfo(_ref2) {
|
|
75
79
|
let {
|
|
76
80
|
data
|
|
77
81
|
} = _ref2;
|
|
78
|
-
return /*#__PURE__*/React.createElement(
|
|
82
|
+
return /*#__PURE__*/React.createElement(VirtualizedList, {
|
|
79
83
|
getDataAtIndex: index => data[index],
|
|
80
84
|
count: data.length,
|
|
81
85
|
estimateSize: 140,
|
|
82
|
-
maxHeight: "
|
|
86
|
+
maxHeight: "40vh",
|
|
83
87
|
ItemComponent: VarDiseaseInfoItem
|
|
84
|
-
})
|
|
88
|
+
});
|
|
85
89
|
}
|
|
86
90
|
export function SingleSelectionItem(_ref3) {
|
|
87
91
|
let {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@haniffalab/cherita-react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0-dev.2025-04-09.382ade7b",
|
|
4
4
|
"author": "Haniffa Lab",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -123,5 +123,6 @@
|
|
|
123
123
|
"bugs": {
|
|
124
124
|
"url": "https://github.com/haniffalab/cherita-react/issues"
|
|
125
125
|
},
|
|
126
|
-
"homepage": "https://github.com/haniffalab/cherita-react#readme"
|
|
127
|
-
|
|
126
|
+
"homepage": "https://github.com/haniffalab/cherita-react#readme",
|
|
127
|
+
"prereleaseSha": "382ade7b92504de6a200b2f68f7942912a0271b8"
|
|
128
|
+
}
|
package/scss/cherita.scss
CHANGED
|
@@ -249,15 +249,22 @@ $gauge-padding: 0.15rem;
|
|
|
249
249
|
}
|
|
250
250
|
|
|
251
251
|
.feature-disease-info {
|
|
252
|
-
font-weight:
|
|
252
|
+
font-weight: 300;
|
|
253
|
+
padding-left: 0 !important;
|
|
253
254
|
border-top: 1px solid var(list-group-border-color);
|
|
254
255
|
border-right: 0;
|
|
255
256
|
border-left: 0;
|
|
256
257
|
border-bottom: 0;
|
|
257
258
|
}
|
|
258
259
|
|
|
259
|
-
.
|
|
260
|
-
|
|
260
|
+
.disease-link {
|
|
261
|
+
padding: 0;
|
|
262
|
+
white-space: normal;
|
|
263
|
+
text-align: left;
|
|
264
|
+
width: 100%;
|
|
265
|
+
position: sticky;
|
|
266
|
+
top: 0;
|
|
267
|
+
background-color: var(--#{$prefix}body-bg) !important;
|
|
261
268
|
}
|
|
262
269
|
|
|
263
270
|
.cherita-app-plot {
|
|
@@ -316,11 +323,6 @@ $gauge-padding: 0.15rem;
|
|
|
316
323
|
border-bottom: 1px solid #dee2e6; /* Adjust the color and width as needed */
|
|
317
324
|
}
|
|
318
325
|
|
|
319
|
-
.var-disease-info-collapse {
|
|
320
|
-
max-height: 40vh;
|
|
321
|
-
overflow-y: auto;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
326
|
.cherita-scatterplot #deckgl-wrapper {
|
|
325
327
|
z-index: 1 !important;
|
|
326
328
|
}
|
|
@@ -1,14 +1,26 @@
|
|
|
1
|
-
.list-group
|
|
2
|
-
.
|
|
1
|
+
.list-group.cherita-list {
|
|
2
|
+
.virtualized-list-wrapper {
|
|
3
|
+
padding: 0 0.25rem 0.25rem 0.25rem;
|
|
4
|
+
}
|
|
5
|
+
.list-group-item.unstyled {
|
|
3
6
|
background-color: transparent;
|
|
7
|
+
padding-left: 1rem;
|
|
4
8
|
}
|
|
5
9
|
.list-group-item {
|
|
6
10
|
border: 0;
|
|
7
11
|
padding: 0.375rem 0.75rem;
|
|
8
|
-
margin-bottom: 0.215rem;
|
|
9
12
|
line-height: 1.5;
|
|
10
13
|
color: var(--#{$prefix}body-color);
|
|
11
14
|
background-color: var(--#{$prefix}tertiary-bg);
|
|
12
15
|
border-radius: var(--#{$prefix}border-radius);
|
|
13
16
|
}
|
|
14
17
|
}
|
|
18
|
+
.obs-statistics {
|
|
19
|
+
border: 0;
|
|
20
|
+
margin: 0 0.25rem 0.25rem 0.25rem;
|
|
21
|
+
padding: 0.375rem 0.75rem;
|
|
22
|
+
line-height: 1.5;
|
|
23
|
+
color: var(--#{$prefix}body-color);
|
|
24
|
+
background-color: var(--#{$prefix}tertiary-bg);
|
|
25
|
+
border-radius: var(--#{$prefix}border-radius);
|
|
26
|
+
}
|