Skip to content

Commit 3467111

Browse files
authored
Merge pull request #839 from CaitlinOCallaghan/inputErrorCheck
Functional Invalid Token Checking Enrichment #813 , #815
2 parents 733274d + 3385bb5 commit 3467111

File tree

6 files changed

+213
-56
lines changed

6 files changed

+213
-56
lines changed

package-lock.json

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
"react-router-dom": "^4.2.2",
7979
"react-table": "^6.7.4",
8080
"react-tabs": "^2.1.1",
81+
"react-textarea-autosize": "^6.1.0",
8182
"rethinkdb": "^2.3.3",
8283
"sbgnml-to-cytoscape": "^4.0.4",
8384
"serve-favicon": "^2.4.5",

src/client/common/components/base-network-view/base-network-view.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class BaseNetworkView extends React.Component {
7777
layout.run();
7878
}
7979

80+
8081
changeMenu(menu) {
8182
let resizeCyImmediate = () => this.state.cy.resize();
8283
let resizeCyDebounced = _.debounce( resizeCyImmediate, 500 );
@@ -187,7 +188,7 @@ class BaseNetworkView extends React.Component {
187188
// if 'titleContainer' exists from index file, unique title will render in 'div.title-container'
188189
// default: metadata pathway name and database
189190
const displayInfo = [
190-
(this.props.titleContainer ? this.props.titleContainer : metadataTitles)
191+
(this.props.titleContainer ? this.props.titleContainer() : metadataTitles)
191192
];
192193

193194

@@ -203,7 +204,7 @@ class BaseNetworkView extends React.Component {
203204
]),
204205
h('div.title-container', displayInfo)
205206
]),
206-
h('div.view-toolbar', toolBar)
207+
h('div.view-toolbar', {style: {display: this.props.closeToolBar == true ? 'none': 'inherit'}}, toolBar)
207208
]),
208209
h(Loader, {
209210
loaded: !this.state.networkLoading,
Lines changed: 65 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
const React = require('react');
22
const h = require('react-hyperscript');
3-
//const queryString = require('query-string');
43
const _ = require('lodash');
54
//const Loader = require('react-loader');
5+
//const queryString = require('query-string');
66

77
// const hideTooltips = require('../../common/cy/events/click').hideTooltips;
88
// const removeStyle= require('../../common/cy/manage-style').removeStyle;
9-
// const make_cytoscape = require('../../common/cy/');
9+
const make_cytoscape = require('../../common/cy/');
1010
// const interactionsStylesheet= require('../../common/cy/interactions-stylesheet');
11+
const TokenInput = require('./token-input');
1112
const { BaseNetworkView } = require('../../common/components');
12-
//const { getLayoutConfig } = require('../../common/cy/layout');
13+
const { getLayoutConfig } = require('../../common/cy/layout');
1314
//const downloadTypes = require('../../common/config').downloadTypes;
1415

1516
const enrichmentConfig={
@@ -20,61 +21,81 @@ const enrichmentConfig={
2021
useSearchBar: true
2122
};
2223

24+
//temporary empty network for development purposes
25+
const emptyNetwork = {
26+
graph: {
27+
edges: [],
28+
nodes: [],
29+
pathwayMetadata: {
30+
title: [],
31+
datasource: [],
32+
comments: []
33+
},
34+
layout: null
35+
}
36+
};
37+
const network = emptyNetwork;
38+
const layoutConfig = getLayoutConfig();
39+
2340
class Enrichment extends React.Component {
2441
constructor(props) {
2542
super(props);
2643
this.state = {
44+
cy: make_cytoscape({headless: true}),
2745
componentConfig: enrichmentConfig,
28-
networkMetadata: {
29-
name: '',
30-
datasource: '',
31-
comments: []
32-
},
33-
query: '',
34-
titleContainer: []
46+
layoutConfig: layoutConfig,
47+
networkJSON: network.graph,
48+
networkMetadata: network.graph.pathwayMetadata,
49+
50+
//temporarily set to false so loading spinner is disabled
51+
networkLoading: false,
52+
53+
closeToolBar: true,
54+
//all submitted tokens, includes valid and invalid tokens
55+
genes: [],
56+
unrecognized: [],
57+
inputs: ""
3558
};
59+
60+
this.handleInputs = this.handleInputs.bind(this);
61+
this.handleUnrecognized = this.handleUnrecognized.bind(this);
62+
this.handleGenes = this.handleGenes.bind(this);
63+
}
64+
65+
handleInputs( inputs ) {
66+
this.setState({ inputs });
3667
}
3768

38-
geneInputChange(e) {
39-
this.setState( {query: e.target.value});
69+
handleUnrecognized( unrecognized ) {
70+
this.setState({ unrecognized });
4071
}
4172

42-
geneInputSubmission(input){
43-
const geneArray = input.split(/\n/g);
44-
const inputObject = {genes: _.pull(geneArray,"")};
45-
//console.log(geneArray);
46-
//console.log(inputObject.genes);
47-
//console.log(ServerAPI.geneQuery(inputObject));
48-
return inputObject.genes;
73+
handleGenes( genes ) {
74+
this.setState( { genes } );console.log(genes);
4975
}
5076

5177
render() {
52-
const state = this.state;
53-
const baseView = h(BaseNetworkView.component, {
54-
componentConfig: state.componentConfig,
55-
//titles at top of toolbar
56-
networkMetadata: {},
57-
titleContainer: [
58-
h('h4', [
59-
h('span', 'Pathway Enrichment '),]),
60-
h('img', {
61-
src: '/img/humanIcon.png'
62-
}),
63-
h('textarea.gene-input', {
64-
placeholder: 'Enter one gene per line',
65-
onChange: e => this.geneInputChange(e),
66-
onKeyPress: e => this.geneInputChange(e)
67-
}),
68-
h('submit-container', {onClick: () => this.geneInputSubmission(this.state.query) },[
69-
h('button.submit', 'Submit'),
70-
])
71-
]
78+
let { cy, componentConfig, layoutConfig, networkJSON, networkMetadata, networkLoading } = this.state;
79+
let retrieveTokenInput = () => h(TokenInput,{
80+
inputs: this.state.inputs,
81+
handleInputs: this.handleInputs,
82+
handleUnrecognized: this.handleUnrecognized,
83+
unrecognized: this.state.unrecognized,
84+
handleGenes: this.handleGenes
85+
});
86+
87+
return h(BaseNetworkView.component, {
88+
cy,
89+
componentConfig,
90+
layoutConfig,
91+
networkJSON,
92+
networkMetadata,
93+
networkLoading,
94+
titleContainer: () => h(retrieveTokenInput),
95+
//will use state to set to false to render the toolbar once analysis is run and graph is displayed
96+
closeToolBar: true
7297
});
73-
//console.log(this.state.query);
74-
return h('div.main', [baseView]);
7598
}
7699
}
77-
module.exports = Enrichment;
78100

79-
//NOTE: CURRENTLY ONLY RENDERS ON PAGE WHEN base-network-view.js function 'componentDidMount(){}'
80-
// IS COMMENTED OUT
101+
module.exports = Enrichment;
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
const React = require('react');
2+
const h = require('react-hyperscript');
3+
const _ = require('lodash');
4+
const { ServerAPI } = require('../../services/');
5+
let Textarea = require('react-textarea-autosize').default;
6+
7+
class TokenInput extends React.Component {
8+
9+
constructor(props) {
10+
super(props);
11+
// Note on input contents: Set the initial value here from parent
12+
// in order to maintain contents on re-render.
13+
this.state = {
14+
inputBoxContents: this.props.inputs
15+
};
16+
}
17+
//store 'gene-input-box' contents on state
18+
handleChange(e) {
19+
this.setState({inputBoxContents: e.target.value});
20+
}
21+
22+
//call validation service API to retrieve validation result in the form of []
23+
retrieveValidationAPIResult(){
24+
let tokenList = _.pull(this.state.inputBoxContents.split(/\s/g), "");
25+
ServerAPI.enrichmentAPI({
26+
genes: tokenList,
27+
targetDb: "HGNCSYMBOL"
28+
}, "validation")
29+
.then( result => {
30+
const aliases = result.geneInfo.map( value => {
31+
return value.convertedAlias;
32+
});
33+
this.props.handleGenes( aliases );
34+
this.props.handleUnrecognized( result.unrecognized );
35+
this.props.handleInputs( this.state.inputBoxContents );
36+
})
37+
.catch(
38+
error => error
39+
);
40+
}
41+
42+
render() {
43+
44+
const unrecognized = this.props.unrecognized;
45+
46+
return h('div.enrichmentInput', [
47+
h('h4', [
48+
h('span', 'Pathway Enrichment ')
49+
]),
50+
h('img', {
51+
src: '/img/humanIcon.png'
52+
}),
53+
h('div.gene-input-container', [
54+
h(Textarea, {
55+
className: 'gene-input-box',
56+
placeholder: 'Enter one gene per line',
57+
value: this.state.inputBoxContents,
58+
onChange: (e) => this.handleChange(e)
59+
})
60+
]),
61+
h('submit-container', {
62+
onClick: () => { this.retrieveValidationAPIResult();} },
63+
[h('button.submit', 'Submit')]
64+
),
65+
h('div.unrecognized-token-container',[
66+
h(Textarea, {
67+
className:'unrecognized-tokens-feedback',
68+
value: "Unrecognized Tokens: \n" + unrecognized.join("\n"),
69+
readOnly: true,
70+
//if unrecognizedTokens is its default value (ie no tokens have been added), feedback box not displayed
71+
style: {display: _.isEmpty( unrecognized ) ? 'none' : 'block' }
72+
})
73+
])
74+
]);
75+
}
76+
}
77+
78+
module.exports = TokenInput;
79+
80+

src/styles/features/view/menuBar.css

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,16 @@
5555
margin: 0;
5656
margin-top: 5px;
5757
}
58-
/* css for human icon */
59-
& img {
60-
margin-top: 2px;
61-
height: var(--icon-size);
62-
width: auto;
63-
}
58+
/* css for human icon */
59+
& img {
60+
margin-top: 2px;
61+
height: var(--icon-size);
62+
width: auto;
63+
}
64+
}
65+
66+
.enrichmentInput {
67+
display: flex;
6468
}
6569

6670
.sidebar-tool-button-container {
@@ -148,18 +152,60 @@ _::-webkit-full-page-media, _:future, :root .view-toolbar{
148152
padding: 0 0 1px 0 !important;
149153
border-width: 0px !important;
150154
}
151-
152-
.gene-input{
155+
.gene-input-container{
153156
height: 1.85em;
154157
width: 200px;
158+
}
159+
160+
.gene-input-box{
161+
min-height: 1.85em;
162+
max-height: 80%;
163+
width: 200px;
155164
background-color: white;
156165
padding: 0em 0.5em;
157166
box-sizing: border-box;
158167
border: 1px solid var(--light-base-colour-dark);
159-
border-right: none;
160-
vertical-align: middle;
168+
border-radius: 0 !important;
161169
font-weight: normal;
170+
position: fixed;
171+
vertical-align: middle;
172+
z-index: 1;
173+
overflow-y:scroll;
174+
line-height: 1.8;
175+
resize: none;
176+
}
177+
178+
.gene-input-box:empty:not(:focus):before {
179+
content: attr(placeholder);
180+
}
181+
182+
.unrecognized-token-container{
183+
@extend %flex-center;
184+
185+
min-width: 200px;
186+
position: absolute;
187+
top: 100%;
188+
left: -1px;
189+
}
190+
191+
.unrecognized-tokens-feedback{
192+
min-height: 1.85em;
193+
max-height: 628px;
194+
width: 200px;
195+
background-color: white;
196+
padding: 0em 0.5em;
197+
border: 1px solid var(--light-base-colour-dark);
162198
border-radius: 0 !important;
199+
font-weight: normal;
200+
vertical-align: middle;
201+
z-index: 1;
202+
overflow-y:scroll;
203+
line-height: 1.8;
204+
resize: none;
205+
}
206+
207+
.unrecognized-tokens-feedback:empty{
208+
display:none;
163209
}
164210

165211
/* submit button for gene input */

0 commit comments

Comments
 (0)