Skip to content

Commit 27b1c9f

Browse files
Merge pull request #124 from ctrlaltaf/go-exploration
Fix interaction in ancestor/descendant selectors
2 parents 6b5eddc + da0337a commit 27b1c9f

File tree

4 files changed

+178
-114
lines changed

4 files changed

+178
-114
lines changed

client/src/components/AncestorSelector.jsx

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
import React, { useEffect, useState } from 'react';
1+
import React, { useEffect, useState } from "react";
22
import { FaInfoCircle } from "react-icons/fa";
33

44
export default function AncestorSelector({
55
parentGoTerms,
6-
storeGoTermValue
6+
storeGoTermValue,
7+
handleInputChangeAncestor,
8+
inputValueAncestor,
79
}) {
810
const [isEmpty, setIsEmpty] = useState(false);
911
const [showTooltip, setShowTooltip] = useState(false);
@@ -20,7 +22,7 @@ export default function AncestorSelector({
2022
} else {
2123
setIsEmpty(false);
2224
// Iterate through the array and create options
23-
array.forEach(optionText => {
25+
array.forEach((optionText) => {
2426
const option = document.createElement("option");
2527
option.value = optionText;
2628
datalist.appendChild(option);
@@ -33,6 +35,12 @@ export default function AncestorSelector({
3335
}, [parentGoTerms]);
3436
// Call the function to populate the datalist
3537

38+
const onChange = (e) => {
39+
const inputText = e.currentTarget.value;
40+
handleInputChangeAncestor(inputText);
41+
storeGoTermValue(e);
42+
};
43+
3644
return (
3745
<div className="ancestor-input">
3846
<div className="hierarchy-input-container">
@@ -44,20 +52,24 @@ export default function AncestorSelector({
4452
onMouseLeave={() => setShowTooltip(false)}
4553
>
4654
<FaInfoCircle className="info-icon" />
47-
{showTooltip && <div className="hierarchy-warning">You have reached the most general GO term.</div>}
55+
{showTooltip && (
56+
<div className="hierarchy-warning">
57+
You have reached the most general GO term.
58+
</div>
59+
)}
4860
</div>
4961
)}
5062
{/* normal input display */}
5163
<input
5264
list="parent-go-terms"
5365
id="ancestor-selector"
5466
name="ancestor-selector"
55-
onChange={storeGoTermValue}
56-
placeholder='Parent GO Terms'
67+
onChange={onChange}
68+
placeholder="Parent GO Terms"
69+
value={inputValueAncestor}
5770
/>
58-
5971
</div>
6072
<datalist id="parent-go-terms"></datalist>
6173
</div>
62-
)
74+
);
6375
}

client/src/components/DescendantSelector.jsx

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
import React, { useEffect, useState } from 'react';
1+
import React, { useEffect, useState } from "react";
22
import { FaInfoCircle } from "react-icons/fa";
33

44
export default function DescendantSelector({
55
childrenGoTerms,
6-
storeGoTermValue
6+
storeGoTermValue,
7+
handleInputChangeDescendant,
8+
inputValueDescendant,
79
}) {
810
const [isEmpty, setIsEmpty] = useState(false);
911
const [showTooltip, setShowTooltip] = useState(false);
@@ -20,7 +22,7 @@ export default function DescendantSelector({
2022
} else {
2123
setIsEmpty(false);
2224
// Iterate through the array and create options
23-
array.forEach(optionText => {
25+
array.forEach((optionText) => {
2426
const option = document.createElement("option");
2527
option.value = optionText;
2628
datalist.appendChild(option);
@@ -33,6 +35,12 @@ export default function DescendantSelector({
3335
populateDatalistWithOptions(childrenGoTerms);
3436
}, [childrenGoTerms]);
3537

38+
const onChange = (e) => {
39+
const inputText = e.currentTarget.value;
40+
handleInputChangeDescendant(inputText);
41+
storeGoTermValue(e);
42+
};
43+
3644
return (
3745
<div className="descendant-input">
3846
<div className="hierarchy-input-container">
@@ -44,19 +52,24 @@ export default function DescendantSelector({
4452
onMouseLeave={() => setShowTooltip(false)}
4553
>
4654
<FaInfoCircle className="info-icon" />
47-
{showTooltip && <div className="hierarchy-warning">You have reached the most specific GO term.</div>}
55+
{showTooltip && (
56+
<div className="hierarchy-warning">
57+
You have reached the most specific GO term.
58+
</div>
59+
)}
4860
</div>
4961
)}
5062
{/* normal input display */}
5163
<input
5264
list="child-go-terms"
5365
id="descendant-selector"
5466
name="descendant-selector"
55-
onChange={storeGoTermValue}
56-
placeholder='Child GO Terms'
67+
onChange={onChange}
68+
placeholder="Child GO Terms"
69+
value={inputValueDescendant}
5770
/>
5871
</div>
5972
<datalist id="child-go-terms"></datalist>
6073
</div>
61-
)
74+
);
6275
}

client/src/components/GraphExploration.jsx

Lines changed: 124 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ export default function GraphExploration({
1919
handleGoTermChange,
2020
}) {
2121
const [proteinCount, setProteinCount] = useState(0);
22+
const [inputValueAncestor, setInputValueAncestor] = useState("");
23+
const [inputValueDescendant, setInputValueDescendant] = useState("");
24+
const [goButtonClassname, setGoButtonClassname] = useState(
25+
"new-go-term-button-disabled"
26+
);
27+
const [sourceNodeButton, setSourceNodeButton] = useState(
28+
"new-source-disabled"
29+
);
2230

2331
// Keep track of the proteins in the query
2432
useEffect(() => {
@@ -33,7 +41,6 @@ export default function GraphExploration({
3341
}
3442
}, [currentNode]);
3543

36-
3744
// Keep track of the queries
3845
useEffect(() => {
3946
if (query) {
@@ -45,110 +52,128 @@ export default function GraphExploration({
4552
handleLog(newQuery);
4653
}
4754
}, [searchExecuted]);
48-
if (currentNode) {
49-
// If a protein is selected, allow the user to set as source node
50-
return (
51-
<div>
52-
<h4 className="graph-exploration-title">Graph Exploration Tools</h4>
53-
<div className="graph-exploration">
54-
{/* New Source Node Button */}
55-
<div className="new-source-container">
55+
56+
const handleInputChangeAncestor = (value) => {
57+
setInputValueAncestor(value);
58+
};
59+
60+
const handleInputChangeDescendant = (value) => {
61+
setInputValueDescendant(value);
62+
};
63+
64+
useEffect(() => {
65+
if (inputValueAncestor == "" && inputValueDescendant == "") {
66+
setGoButtonClassname("new-go-term-button-disabled");
67+
} else if (inputValueAncestor != "" || inputValueDescendant != "") {
68+
setGoButtonClassname("new-go-term-button");
69+
}
70+
}, [inputValueAncestor, inputValueDescendant]);
71+
72+
useEffect(() => {
73+
if (inputValueAncestor != "") {
74+
setInputValueDescendant("");
75+
} else {
76+
setInputValueAncestor("");
77+
}
78+
}, [inputValueAncestor]);
79+
80+
useEffect(() => {
81+
if (inputValueDescendant != "") {
82+
setInputValueAncestor("");
83+
} else {
84+
setInputValueDescendant("");
85+
}
86+
}, [inputValueDescendant]);
87+
88+
const handleNewGoButton = () => {
89+
setInputValueAncestor("");
90+
setInputValueDescendant("");
91+
handleGoTermChange();
92+
};
93+
94+
useEffect(() => {
95+
if (currentNode) {
96+
setSourceNodeButton("new-source");
97+
} else {
98+
setSourceNodeButton("new-source-disabled");
99+
}
100+
}, [currentNode]);
101+
return (
102+
<div>
103+
<h4 className="graph-exploration-title">Graph Exploration Tools</h4>
104+
<div className="graph-exploration">
105+
{/* New Source Node Button */}
106+
<div className="new-source-container">
107+
{currentNode && (
56108
<h5>Selected protein: {currentNode.label}</h5>
57-
<form method="post" onSubmit={handleSubmit}>
58-
<button
59-
className="new-source"
60-
onClick={handleSourceNode}
61-
new-source-node={currentNode.label}
62-
>
63-
Set as New Source Node
64-
</button>
65-
</form>
66-
</div>
67-
{/* GO Term Selection */}
68-
<div className="go-container">
69-
<h5>Change queried GO Term:</h5>
70-
<div className="go-selector-container">
71-
<AncestorSelector
72-
parentGoTerms={parentGoTerms}
73-
storeGoTermValue={storeGoTermValue}
74-
/>
75-
<DescendantSelector
76-
childrenGoTerms={childrenGoTerms}
77-
storeGoTermValue={storeGoTermValue}
78-
/>
79-
<form method="post" onSubmit={handleSubmit} className="new-go-form">
80-
<button
81-
className="new-go-term-button"
82-
onClick={handleGoTermChange}
83-
>
84-
Set as New GO Term
85-
</button>
86-
</form>
87-
</div>
88-
</div>
89-
</div>
90-
{/* Export Logs/PNG */}
91-
<div className="exports-container">
92-
<h5>Export logs or PNG of current network:</h5>
93-
<ExportLogJSON log={logs} />
94-
<a className="export" onClick={exportPNG}>
95-
Export Graph to PNG
96-
</a>
97-
</div>
98-
</div>
109+
)}
110+
{!currentNode && <h5>Selected protein:</h5>}
99111

100-
)
101-
} else {
102-
// If no protein is selected, do not allow the user to set as source node
103-
return (
104-
<div>
105-
<h4 className="graph-exploration-title">Graph Exploration Tools</h4>
106-
<div className="graph-exploration">
107-
{/* New Source Node Button */}
108-
<div className="new-source-container">
109-
<h5>Select a protein: </h5>
110-
<form method="post" onSubmit={handleSubmit}>
112+
<form method="post" onSubmit={handleSubmit}>
113+
<button
114+
className={sourceNodeButton}
115+
onClick={handleSourceNode}
116+
new-source-node={
117+
currentNode && currentNode.label
118+
? currentNode.label
119+
: ""
120+
}
121+
disabled={
122+
sourceNodeButton ==
123+
"new-go-term-button-disabled"
124+
}
125+
>
126+
Set as New Source Node
127+
</button>
128+
</form>
129+
</div>
130+
{/* GO Term Selection */}
131+
<div className="go-container">
132+
<h5>Change queried GO Term:</h5>
133+
<div className="go-selector-container">
134+
<AncestorSelector
135+
parentGoTerms={parentGoTerms}
136+
storeGoTermValue={storeGoTermValue}
137+
handleInputChangeAncestor={
138+
handleInputChangeAncestor
139+
}
140+
inputValueAncestor={inputValueAncestor}
141+
/>
142+
<DescendantSelector
143+
childrenGoTerms={childrenGoTerms}
144+
storeGoTermValue={storeGoTermValue}
145+
handleInputChangeDescendant={
146+
handleInputChangeDescendant
147+
}
148+
inputValueDescendant={inputValueDescendant}
149+
/>
150+
<form
151+
method="post"
152+
onSubmit={handleSubmit}
153+
className="new-go-form"
154+
>
111155
<button
112-
className="new-source-disabled"
113-
onClick={handleSourceNode}
114-
disabled={true}
156+
className={goButtonClassname}
157+
onClick={handleNewGoButton}
158+
disabled={
159+
goButtonClassname ==
160+
"new-go-term-button-disabled"
161+
}
115162
>
116-
Set as New Source Node
163+
Set as New GO Term
117164
</button>
118165
</form>
119166
</div>
120-
{/* GO Term Selection */}
121-
<div className="go-container">
122-
<h5>Change queried GO Term:</h5>
123-
<div className="go-selector-container">
124-
<AncestorSelector
125-
parentGoTerms={parentGoTerms}
126-
storeGoTermValue={storeGoTermValue}
127-
/>
128-
<DescendantSelector
129-
childrenGoTerms={childrenGoTerms}
130-
storeGoTermValue={storeGoTermValue}
131-
/>
132-
<form method="post" onSubmit={handleSubmit} className="new-go-form">
133-
<button
134-
className="new-go-term-button"
135-
onClick={handleGoTermChange}
136-
>
137-
Set as New GO Term
138-
</button>
139-
</form>
140-
</div>
141-
</div>
142-
</div>
143-
{/* Export Logs/PNG */}
144-
<div className="exports-container">
145-
<h5>Export logs or PNG of current network:</h5>
146-
<ExportLogJSON log={logs} />
147-
<a className="export" onClick={exportPNG}>
148-
Export Graph to PNG
149-
</a>
150167
</div>
151168
</div>
152-
)
153-
}
154-
}
169+
{/* Export Logs/PNG */}
170+
<div className="exports-container">
171+
<h5>Export logs or PNG of current network:</h5>
172+
<ExportLogJSON log={logs} />
173+
<a className="export" onClick={exportPNG}>
174+
Export Graph to PNG
175+
</a>
176+
</div>
177+
</div>
178+
);
179+
}

0 commit comments

Comments
 (0)