gramene-search 1.6.21 → 1.6.23
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/.parcel-cache/83e7562660f7cc15-BundleGraph +0 -0
- package/.parcel-cache/9a0d07555444f4da-AssetGraph +0 -0
- package/.parcel-cache/d3a1b9507cb44047-AssetGraph +0 -0
- package/.parcel-cache/data.mdb +0 -0
- package/.parcel-cache/dc1da35000e13623-RequestGraph +0 -0
- package/.parcel-cache/lock.mdb +0 -0
- package/.parcel-cache/snapshot-dc1da35000e13623.txt +2 -2
- package/dist/index.js +180 -36
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/bundles/api.js +2 -1
- package/src/components/results/UserGeneLists.js +68 -13
- package/src/components/results/details/Expression.js +63 -14
- package/src/components/results/details/VEP.js +5 -2
- package/src/demo.js +3 -3
- package/src/maize.html +7 -0
- package/src/static/atlasWidget.html +6 -5
package/package.json
CHANGED
package/src/bundles/api.js
CHANGED
|
@@ -64,7 +64,8 @@ grameneSuggestions.selectGrameneSuggestionsStatus = createSelector(
|
|
|
64
64
|
if (!queryString) return '';
|
|
65
65
|
if (shouldUpdate) return 'update needed';
|
|
66
66
|
if (isLoading) return 'loading';
|
|
67
|
-
if (suggestionsRaw) return suggestionsRaw.data.grouped.category.matches + ' terms';
|
|
67
|
+
if (suggestionsRaw.data) return suggestionsRaw.data.grouped.category.matches + ' terms';
|
|
68
|
+
console.error(suggestionsRaw)
|
|
68
69
|
return 'error';
|
|
69
70
|
}
|
|
70
71
|
);
|
|
@@ -9,20 +9,44 @@ const auth = getAuth(firebaseApp);
|
|
|
9
9
|
const MAX_GENE_IDS = 1000; // Define the maximum number of gene IDs allowed
|
|
10
10
|
|
|
11
11
|
const GeneListDisplayComponent = props => {
|
|
12
|
-
const [
|
|
12
|
+
const [publicGeneLists, setPublicGeneLists] = useState([]);
|
|
13
|
+
const [privateGeneLists, setPrivateGeneLists] = useState([]);
|
|
13
14
|
const [error, setError] = useState(null);
|
|
14
15
|
const [user, setUser] = useState({});
|
|
15
16
|
onAuthStateChanged(auth, (user) => setUser(user));
|
|
16
17
|
|
|
18
|
+
const fetchPrivateGeneLists = async () => {
|
|
19
|
+
try {
|
|
20
|
+
const token = await user.getIdToken();
|
|
21
|
+
// Replace this with actual fetch from your backend or storage
|
|
22
|
+
const response = await fetch(`${props.api}/gene_lists?site=${props.site}&isPublic=false`, {
|
|
23
|
+
method: 'GET',
|
|
24
|
+
headers: {
|
|
25
|
+
"Content-Type": "application/json",
|
|
26
|
+
"Authorization": `Bearer ${token}`
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
const result = await response.json();
|
|
30
|
+
|
|
31
|
+
if (response.ok) {
|
|
32
|
+
setError(null);
|
|
33
|
+
setPrivateGeneLists(result); // array of saved gene lists
|
|
34
|
+
} else {
|
|
35
|
+
setError('Error fetching gene lists.');
|
|
36
|
+
}
|
|
37
|
+
} catch (err) {
|
|
38
|
+
setError('Failed to fetch private gene lists. Please try again later.');
|
|
39
|
+
}
|
|
40
|
+
};
|
|
17
41
|
// Fetch saved gene lists from a backend or local storage
|
|
18
|
-
const
|
|
42
|
+
const fetchPublicGeneLists = async () => {
|
|
19
43
|
try {
|
|
20
44
|
// Replace this with actual fetch from your backend or storage
|
|
21
|
-
const response = await fetch(`${props.api}/
|
|
45
|
+
const response = await fetch(`${props.api}/gene_lists?site=${props.site}&isPublic=true`);
|
|
22
46
|
const result = await response.json();
|
|
23
47
|
|
|
24
48
|
if (response.ok) {
|
|
25
|
-
|
|
49
|
+
setPublicGeneLists(result); // array of saved gene lists
|
|
26
50
|
} else {
|
|
27
51
|
setError('Error fetching gene lists.');
|
|
28
52
|
}
|
|
@@ -33,8 +57,11 @@ const GeneListDisplayComponent = props => {
|
|
|
33
57
|
|
|
34
58
|
// Fetch data when the component is mounted
|
|
35
59
|
useEffect(() => {
|
|
36
|
-
|
|
60
|
+
fetchPublicGeneLists();
|
|
37
61
|
}, []);
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
fetchPrivateGeneLists();
|
|
64
|
+
}, [user]);
|
|
38
65
|
|
|
39
66
|
return (
|
|
40
67
|
<div className="gene-list-display-component">
|
|
@@ -46,7 +73,35 @@ const GeneListDisplayComponent = props => {
|
|
|
46
73
|
</Alert>
|
|
47
74
|
)}
|
|
48
75
|
|
|
49
|
-
{
|
|
76
|
+
{privateGeneLists.length > 0 && (
|
|
77
|
+
<Table striped bordered hover className="mt-4">
|
|
78
|
+
<thead>
|
|
79
|
+
<tr>
|
|
80
|
+
<th>List Name</th>
|
|
81
|
+
<th>Number of Genes</th>
|
|
82
|
+
<th>Actions</th>
|
|
83
|
+
</tr>
|
|
84
|
+
</thead>
|
|
85
|
+
<tbody>
|
|
86
|
+
{privateGeneLists.map((list, index) => (
|
|
87
|
+
<tr key={index}>
|
|
88
|
+
<td>{list.label}</td>
|
|
89
|
+
<td>{list.hash}</td>
|
|
90
|
+
<td>
|
|
91
|
+
<Button variant="info" onClick={() => viewGeneList(list)}>
|
|
92
|
+
View
|
|
93
|
+
</Button>
|
|
94
|
+
<Button variant="danger" onClick={() => deleteGeneList(props.api, list._id)} className="ml-2">
|
|
95
|
+
Delete
|
|
96
|
+
</Button>
|
|
97
|
+
</td>
|
|
98
|
+
</tr>
|
|
99
|
+
))}
|
|
100
|
+
</tbody>
|
|
101
|
+
</Table>
|
|
102
|
+
)}
|
|
103
|
+
|
|
104
|
+
{publicGeneLists.length > 0 ? (
|
|
50
105
|
<Table striped bordered hover className="mt-4">
|
|
51
106
|
<thead>
|
|
52
107
|
<tr>
|
|
@@ -56,15 +111,15 @@ const GeneListDisplayComponent = props => {
|
|
|
56
111
|
</tr>
|
|
57
112
|
</thead>
|
|
58
113
|
<tbody>
|
|
59
|
-
{
|
|
114
|
+
{publicGeneLists.map((list, index) => (
|
|
60
115
|
<tr key={index}>
|
|
61
|
-
<td>{list.
|
|
62
|
-
<td>{list.
|
|
116
|
+
<td>{list.label}</td>
|
|
117
|
+
<td>{list.hash}</td>
|
|
63
118
|
<td>
|
|
64
119
|
<Button variant="info" onClick={() => viewGeneList(list)}>
|
|
65
120
|
View
|
|
66
121
|
</Button>
|
|
67
|
-
<Button variant="danger" onClick={() => deleteGeneList(props.api, list.
|
|
122
|
+
<Button variant="danger" onClick={() => deleteGeneList(props.api, list._id)} className="ml-2">
|
|
68
123
|
Delete
|
|
69
124
|
</Button>
|
|
70
125
|
</td>
|
|
@@ -90,7 +145,7 @@ const deleteGeneList = async (api,listId) => {
|
|
|
90
145
|
if (window.confirm('Are you sure you want to delete this gene list?')) {
|
|
91
146
|
// Replace with the actual delete request
|
|
92
147
|
try {
|
|
93
|
-
await fetch(`${api}/
|
|
148
|
+
await fetch(`${api}/gene_lists/${listId}`, {
|
|
94
149
|
method: 'DELETE',
|
|
95
150
|
});
|
|
96
151
|
alert('Gene list deleted!');
|
|
@@ -149,7 +204,7 @@ const GeneListComponent = props => {
|
|
|
149
204
|
headers: {
|
|
150
205
|
'Content-Type': 'application/json',
|
|
151
206
|
},
|
|
152
|
-
body: JSON.stringify(
|
|
207
|
+
body: JSON.stringify(geneArray),
|
|
153
208
|
});
|
|
154
209
|
|
|
155
210
|
const result = await response.json();
|
|
@@ -181,7 +236,7 @@ const GeneListComponent = props => {
|
|
|
181
236
|
|
|
182
237
|
const token = await user.getIdToken();
|
|
183
238
|
try {
|
|
184
|
-
const response = await fetch(`${props.api}/
|
|
239
|
+
const response = await fetch(`${props.api}/gene_lists?${queryString}`, {
|
|
185
240
|
method: 'POST',
|
|
186
241
|
headers: {
|
|
187
242
|
"Content-Type": "application/json",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import React, { useRef, useEffect } from 'react'
|
|
1
|
+
import React, { useRef, useEffect, useState } from 'react'
|
|
2
2
|
import {connect} from "redux-bundler-react";
|
|
3
|
-
import {Tabs, Tab} from 'react-bootstrap';
|
|
3
|
+
import {Tabs, Tab, Form, Row, Col} from 'react-bootstrap';
|
|
4
4
|
import BAR, {haveBAR} from "gramene-efp-browser";
|
|
5
5
|
|
|
6
6
|
function DynamicIframe(props) {
|
|
@@ -61,33 +61,82 @@ function DynamicIframe(props) {
|
|
|
61
61
|
|
|
62
62
|
const Detail = props => {
|
|
63
63
|
const gene = props.geneDocs[props.searchResult.id];
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
const [atlasExperiment, setAtlasExperiment] = useState(null);
|
|
65
|
+
const [atlasExperimentList, setAtlasExperimentList] = useState([]);
|
|
66
|
+
const [isLocal, setIsLocal] = useState(false);
|
|
67
|
+
|
|
68
|
+
const handleLocalAPIChange = (event) => {
|
|
69
|
+
setIsLocal(event.target.checked);
|
|
70
|
+
};
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
const tid = Math.floor(gene.taxon_id / 1000);
|
|
73
|
+
if (props.expressionStudies[tid]) {
|
|
74
|
+
let eList = props.expressionStudies[tid].filter(e => e.type === "Baseline");
|
|
75
|
+
setAtlasExperimentList(eList);
|
|
66
76
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
77
|
+
let refExp = eList.filter(e => e.isRef);
|
|
78
|
+
if (refExp.length === 1) {
|
|
79
|
+
setAtlasExperiment(refExp[0]._id);
|
|
80
|
+
} else {
|
|
81
|
+
// no reference experiment - choose first
|
|
82
|
+
setAtlasExperiment(eList[0]._id);
|
|
83
|
+
}
|
|
71
84
|
}
|
|
85
|
+
}, [props.expressionStudies]);
|
|
86
|
+
|
|
87
|
+
let paralogs_url;
|
|
88
|
+
let gene_url = `/static/atlasWidget.html?genes=${gene.atlas_id || gene._id}&localAPI=${isLocal}`;
|
|
89
|
+
let paralogs = [];
|
|
90
|
+
if (gene.homology && gene.homology.homologous_genes && gene.homology.homologous_genes.within_species_paralog) {
|
|
91
|
+
paralogs = gene.homology.homologous_genes.within_species_paralog;
|
|
72
92
|
}
|
|
73
|
-
|
|
74
|
-
|
|
93
|
+
if (paralogs.length > 1 && atlasExperiment) {
|
|
94
|
+
paralogs_url= `/static/atlasWidget.html?genes=${paralogs.join(' ')}&experiment=${atlasExperiment}&localAPI=${isLocal}`;
|
|
75
95
|
}
|
|
76
96
|
return <Tabs>
|
|
77
97
|
{paralogs_url &&
|
|
78
|
-
<Tab tabClassName="gxa" eventKey="paralogs" title=
|
|
98
|
+
<Tab tabClassName="gxa" eventKey="paralogs" title={`Paralogs`} key="gxaparalogs">
|
|
99
|
+
<Form>
|
|
100
|
+
<Form.Check
|
|
101
|
+
type="switch"
|
|
102
|
+
id="localAPI"
|
|
103
|
+
label="Local API"
|
|
104
|
+
checked={isLocal}
|
|
105
|
+
onChange={handleLocalAPIChange}
|
|
106
|
+
/>
|
|
107
|
+
<Form.Group as={Row} className="mb-3" controlId="formGroupExperiment">
|
|
108
|
+
<Form.Label column sm={1}>Experiment</Form.Label>
|
|
109
|
+
<Col sm={5}>
|
|
110
|
+
<Form.Select defaultValue={atlasExperiment} onChange={(e) => setAtlasExperiment(e.target.value)}>
|
|
111
|
+
{atlasExperimentList.map((experiment, index) => (
|
|
112
|
+
<option key={index} value={experiment._id}>{experiment.name}</option>
|
|
113
|
+
))}
|
|
114
|
+
</Form.Select>
|
|
115
|
+
</Col>
|
|
116
|
+
</Form.Group>
|
|
117
|
+
</Form>
|
|
79
118
|
<DynamicIframe url={paralogs_url}/>
|
|
80
119
|
</Tab>
|
|
81
120
|
}
|
|
82
|
-
<Tab tabClassName="gxa" eventKey="gene" title="All Studies"
|
|
121
|
+
<Tab tabClassName="gxa" eventKey="gene" title="All Studies" key="gxa">
|
|
122
|
+
<Form.Check
|
|
123
|
+
type="switch"
|
|
124
|
+
id="localAPI"
|
|
125
|
+
label="Local API"
|
|
126
|
+
checked={isLocal}
|
|
127
|
+
onChange={handleLocalAPIChange}
|
|
128
|
+
/>
|
|
129
|
+
<DynamicIframe url={gene_url}/>
|
|
130
|
+
</Tab>
|
|
83
131
|
{haveBAR(gene) &&
|
|
84
|
-
<Tab tabClassName="eFP" eventKey="eFP" title="eFP Browser"><BAR gene={gene}/></Tab>
|
|
132
|
+
<Tab tabClassName="eFP" eventKey="eFP" title="eFP Browser" key="bar"><BAR gene={gene}/></Tab>
|
|
85
133
|
}
|
|
86
134
|
</Tabs>
|
|
87
135
|
};
|
|
88
136
|
|
|
89
137
|
export default connect(
|
|
90
|
-
'selectParalogExpression',
|
|
138
|
+
// 'selectParalogExpression',
|
|
139
|
+
'selectExpressionStudies',
|
|
91
140
|
'doRequestParalogExpression',
|
|
92
141
|
Detail
|
|
93
142
|
);
|
|
@@ -12,7 +12,8 @@ const ggURL = {
|
|
|
12
12
|
IRRI: 'https://gringlobal.irri.org/gringlobal/accessiondetail?id=',
|
|
13
13
|
ARS: 'https://npgsweb.ars-grin.gov/gringlobal/accessiondetail.aspx?id=',
|
|
14
14
|
ICRISAT: 'https://genebank.icrisat.org/IND/PassportSummary?ID=',
|
|
15
|
-
sorbmutdb: 'https://www.depts.ttu.edu/igcast/sorbmutdb.php'
|
|
15
|
+
sorbmutdb: 'https://www.depts.ttu.edu/igcast/sorbmutdb.php',
|
|
16
|
+
maizeGDB: 'https://wgs.maizegdb.org/'
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
const rice_studies = {'1': {label: 'Rice 3K', type: 'NAT'}};
|
|
@@ -62,6 +63,9 @@ const AccessionLink = ({germplasm, gene_id}) => {
|
|
|
62
63
|
</form>
|
|
63
64
|
);
|
|
64
65
|
}
|
|
66
|
+
if (germplasm.pop_id === '15' && germplasm.stock_center === 'NOT FOUND') {
|
|
67
|
+
return <a target="_blank" href={ggURL['maizeGDB']}>SNPVersity 2.0</a>
|
|
68
|
+
}
|
|
65
69
|
return <span>{germplasm.pub_id}</span>
|
|
66
70
|
}
|
|
67
71
|
function group_germplasm(gene, germplasmLUT, vep_obj) {
|
|
@@ -206,7 +210,6 @@ const GridWithGroups = ({groups,gene_id}) => {
|
|
|
206
210
|
}
|
|
207
211
|
},
|
|
208
212
|
{ field: 'synonym', headerName: 'Synonym', filter:false, sortable:false, flex: 1, cellRenderer: (params) => {
|
|
209
|
-
console.log(params.data);
|
|
210
213
|
if (params.data.accession) {
|
|
211
214
|
return params.data.accession.germplasm.ens_id
|
|
212
215
|
}
|
package/src/demo.js
CHANGED
|
@@ -137,11 +137,11 @@ const panSites = [
|
|
|
137
137
|
ensemblURL: 'https://ensembl-dev.sorghumbase.org',
|
|
138
138
|
ensemblSite: 'https://ensembl-dev.sorghumbase.org',
|
|
139
139
|
ensemblRest: 'https://data.gramene.org/pansite-ensembl-108',
|
|
140
|
-
grameneData: 'https://data.sorghumbase.org/
|
|
140
|
+
grameneData: 'https://data.sorghumbase.org/auth_testing',
|
|
141
141
|
ga: 'G-L5KXDCCZ16',
|
|
142
142
|
targetTaxonId: 4558003,
|
|
143
143
|
alertText: 'Click the search icon in the menu bar or type /',
|
|
144
|
-
showViews:
|
|
144
|
+
showViews: true,
|
|
145
145
|
details: {
|
|
146
146
|
sequences: true,
|
|
147
147
|
VEP: true,
|
|
@@ -315,7 +315,7 @@ const SearchViewsCmp = props => (
|
|
|
315
315
|
<Status/>
|
|
316
316
|
<Filters/>
|
|
317
317
|
{props.configuration.showViews && <Views/>}
|
|
318
|
-
|
|
318
|
+
<Auth/>
|
|
319
319
|
</div>
|
|
320
320
|
</div>
|
|
321
321
|
<div style={{width:"calc(100% - 250px", left:250, position:'relative'}}>
|
package/src/maize.html
CHANGED
|
@@ -10,6 +10,13 @@
|
|
|
10
10
|
<script async src="./static/gramene-dalliance/dalliance-all.js"></script>
|
|
11
11
|
<script async src="https://plantreactome.gramene.org/DiagramJs/diagram/diagram.nocache.js"></script>
|
|
12
12
|
|
|
13
|
+
<link rel="stylesheet" type="text/css"
|
|
14
|
+
href="//www.ebi.ac.uk/gxa/resources/css/alt-customized-bootstrap-3.3.5.css"/>
|
|
15
|
+
<script language="JavaScript" type="text/javascript"
|
|
16
|
+
src="https://www.ebi.ac.uk/gxa/resources/js-bundles/vendorCommons.bundle.js"></script>
|
|
17
|
+
<script language="JavaScript" type="text/javascript"
|
|
18
|
+
src="https://www.ebi.ac.uk/gxa/resources/js-bundles/expressionAtlasHeatmapHighcharts.bundle.js"></script>
|
|
19
|
+
|
|
13
20
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no"/>
|
|
14
21
|
<link rel="stylesheet" type="text/css" href="static/style.css">
|
|
15
22
|
<!-- Global site tag (gtag.js) - Google Analytics -->
|
|
@@ -13,14 +13,15 @@
|
|
|
13
13
|
const queryString = location.search;
|
|
14
14
|
const urlParams = new URLSearchParams(queryString);
|
|
15
15
|
const genes = urlParams.get('genes');
|
|
16
|
-
const experiment = urlParams.get('
|
|
16
|
+
const experiment = urlParams.get('experiment');
|
|
17
|
+
const localAPI = urlParams.get('localAPI');
|
|
17
18
|
const options = {
|
|
18
19
|
target: "heatmapContainer",
|
|
19
|
-
query: { gene: genes }
|
|
20
|
+
query: { gene: genes },
|
|
21
|
+
disableGoogleAnalytics: true,
|
|
22
|
+
experiment: experiment || false,
|
|
23
|
+
atlasUrl: localAPI ? "https://data.sorghumbase.org/auth_testing/gxa/" : "https://www.ebi.ac.uk/gxa/"
|
|
20
24
|
};
|
|
21
|
-
if (+experiment === 1) {
|
|
22
|
-
options["experiment"] = "reference"
|
|
23
|
-
}
|
|
24
25
|
expressionAtlasHeatmapHighcharts.render(options);
|
|
25
26
|
</script>
|
|
26
27
|
</body>
|