sequenceserver 2.0.0.beta4 → 2.0.0.rc1
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.
Potentially problematic release.
This version of sequenceserver might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.travis.yml +7 -4
- data/AppImage/sequenceserver.sh +5 -0
- data/lib/sequenceserver.rb +9 -5
- data/lib/sequenceserver/blast/job.rb +7 -24
- data/lib/sequenceserver/blast/report.rb +66 -33
- data/lib/sequenceserver/routes.rb +28 -2
- data/lib/sequenceserver/version.rb +1 -1
- data/public/SequenceServer_logo.png +0 -0
- data/public/css/grapher.css +8 -15
- data/public/css/sequenceserver.css +115 -55
- data/public/css/sequenceserver.min.css +3 -3
- data/public/js/circos.js +1 -1
- data/public/js/download_fasta.js +17 -0
- data/public/js/grapher.js +7 -9
- data/public/js/hit.js +217 -0
- data/public/js/hits_overview.js +12 -13
- data/public/js/hsp.js +104 -84
- data/public/js/{sequenceserver.js → jquery_world.js} +1 -18
- data/public/js/kablammo.js +337 -334
- data/public/js/length_distribution.js +1 -1
- data/public/js/query.js +147 -0
- data/public/js/report.js +203 -830
- data/public/js/search.js +176 -169
- data/public/js/sequence_modal.js +167 -0
- data/public/js/sidebar.js +210 -0
- data/public/js/utils.js +2 -19
- data/public/js/visualisation_helpers.js +2 -2
- data/public/sequenceserver-report.min.js +19 -19
- data/public/sequenceserver-search.min.js +11 -11
- data/public/vendor/github/twbs/bootstrap@3.3.5/js/bootstrap.js +2 -2
- data/spec/blast_versions/blast_2.2.30/import_spec_capybara_local_2.2.30.rb +5 -5
- data/spec/blast_versions/blast_2.2.31/import_spec_capybara_local_2.2.31.rb +5 -5
- data/spec/blast_versions/blast_2.3.0/import_spec_capybara_local_2.3.0.rb +5 -5
- data/spec/blast_versions/blast_2.4.0/import_spec_capybara_local_2.4.0.rb +5 -5
- data/spec/blast_versions/blast_2.5.0/import_spec_capybara_local_2.5.0.rb +5 -5
- data/spec/blast_versions/blast_2.6.0/import_spec_capybara_local_2.6.0.rb +5 -5
- data/spec/blast_versions/blast_2.7.1/import_spec_capybara_local_2.7.1.rb +5 -5
- data/spec/blast_versions/blast_2.8.1/import_spec_capybara_local_2.8.1.rb +5 -5
- data/spec/blast_versions/blast_2.9.0/import_spec_capybara_local_2.9.0.rb +5 -5
- data/spec/blast_versions/diamond_0.9.24/import_spec_capybara_local_0.9.24.rb +2 -2
- data/spec/capybara_spec.rb +1 -1
- data/views/layout.erb +1 -1
- metadata +9 -3
data/public/js/search.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
import
|
2
|
-
import _ from 'underscore';
|
1
|
+
import './jquery_world';
|
3
2
|
import React from 'react';
|
3
|
+
import _ from 'underscore';
|
4
4
|
|
5
5
|
/**
|
6
6
|
* Load necessary polyfills.
|
@@ -20,7 +20,7 @@ var Page = React.createClass({
|
|
20
20
|
componentDidMount: function () {
|
21
21
|
this.refs.dnd.setState({
|
22
22
|
query: this.refs.form.refs.query
|
23
|
-
})
|
23
|
+
});
|
24
24
|
}
|
25
25
|
});
|
26
26
|
|
@@ -31,14 +31,14 @@ var DnD = React.createClass({
|
|
31
31
|
getInitialState: function () {
|
32
32
|
return {
|
33
33
|
query: null
|
34
|
-
}
|
34
|
+
};
|
35
35
|
},
|
36
36
|
|
37
37
|
render: function () {
|
38
38
|
return (
|
39
39
|
<div
|
40
40
|
className="dnd-overlay"
|
41
|
-
style={{display:
|
41
|
+
style={{display: 'none'}}>
|
42
42
|
<div
|
43
43
|
className="container dnd-overlay-container">
|
44
44
|
<div
|
@@ -47,15 +47,15 @@ var DnD = React.createClass({
|
|
47
47
|
className="col-md-offset-2 col-md-10">
|
48
48
|
<p
|
49
49
|
className="dnd-overlay-drop"
|
50
|
-
style={{display:
|
50
|
+
style={{display: 'none'}}>
|
51
51
|
<i className="fa fa-2x fa-file-o"></i>
|
52
52
|
Drop query sequence file here
|
53
53
|
</p>
|
54
54
|
<p
|
55
55
|
className="dnd-overlay-overwrite"
|
56
|
-
style={{display:
|
56
|
+
style={{display: 'none'}}>
|
57
57
|
<i className="fa fa-2x fa-file-o"></i>
|
58
|
-
<span style={{color:
|
58
|
+
<span style={{color: 'red'}}>Overwrite</span> query sequence file
|
59
59
|
</p>
|
60
60
|
|
61
61
|
<div
|
@@ -63,7 +63,7 @@ var DnD = React.createClass({
|
|
63
63
|
<div
|
64
64
|
className="dnd-error row"
|
65
65
|
id="dnd-multi-notification"
|
66
|
-
style={{display:
|
66
|
+
style={{display: 'none'}}>
|
67
67
|
<div
|
68
68
|
className="col-md-6 col-md-offset-3">
|
69
69
|
One file at a time please.
|
@@ -73,7 +73,7 @@ var DnD = React.createClass({
|
|
73
73
|
<div
|
74
74
|
className="dnd-error row"
|
75
75
|
id="dnd-large-file-notification"
|
76
|
-
style={{display:
|
76
|
+
style={{display: 'none'}}>
|
77
77
|
<div
|
78
78
|
className="col-md-6 col-md-offset-3">
|
79
79
|
Too big a file. Can only do less than 10 MB. >_<
|
@@ -83,7 +83,7 @@ var DnD = React.createClass({
|
|
83
83
|
<div
|
84
84
|
className="dnd-error row"
|
85
85
|
id="dnd-format-notification"
|
86
|
-
style={{display:
|
86
|
+
style={{display: 'none'}}>
|
87
87
|
<div
|
88
88
|
className="col-md-6 col-md-offset-3">
|
89
89
|
Only FASTA files please.
|
@@ -99,6 +99,7 @@ var DnD = React.createClass({
|
|
99
99
|
|
100
100
|
componentDidMount: function () {
|
101
101
|
var self = this;
|
102
|
+
var FASTA_FORMAT = /^>/;
|
102
103
|
|
103
104
|
$(document).ready(function(){
|
104
105
|
var tgtMarker = $('.dnd-overlay');
|
@@ -110,80 +111,80 @@ var DnD = React.createClass({
|
|
110
111
|
};
|
111
112
|
|
112
113
|
$(document)
|
113
|
-
|
114
|
+
.on('dragenter', function (evt) {
|
114
115
|
// Do not activate DnD if a modal is active.
|
115
|
-
|
116
|
+
if ($.modalActive()) return;
|
116
117
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
118
|
+
// Based on http://stackoverflow.com/a/8494918/1205465.
|
119
|
+
// Contrary to what the above link says, the snippet below can't
|
120
|
+
// distinguish directories from files. We handle that on drop.
|
121
|
+
var dt = evt.originalEvent.dataTransfer;
|
122
|
+
var isFile = dt.types && ((dt.types.indexOf && // Chrome and Safari
|
122
123
|
dt.types.indexOf('Files') != -1) ||
|
123
124
|
(dt.types.contains && // Firefox
|
124
125
|
dt.types.contains('application/x-moz-file')));
|
125
126
|
|
126
|
-
|
127
|
+
if (!isFile) { return; }
|
127
128
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
129
|
+
$('.dnd-error').hide();
|
130
|
+
tgtMarker.stop(true, true);
|
131
|
+
tgtMarker.show();
|
132
|
+
dt.effectAllowed = 'copy';
|
133
|
+
if (self.state.query.isEmpty()) {
|
134
|
+
$('.dnd-overlay-overwrite').hide();
|
135
|
+
$('.dnd-overlay-drop').show('drop', {direction: 'down'}, 'fast');
|
136
|
+
}
|
137
|
+
else {
|
138
|
+
$('.dnd-overlay-drop').hide();
|
139
|
+
$('.dnd-overlay-overwrite').show('drop', {direction: 'down'}, 'fast');
|
140
|
+
}
|
141
|
+
})
|
142
|
+
.on('dragleave', '.dnd-overlay', function (evt) {
|
143
|
+
tgtMarker.hide();
|
137
144
|
$('.dnd-overlay-drop').hide();
|
138
|
-
$('.dnd-overlay-overwrite').
|
139
|
-
}
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
var files = evt.originalEvent.dataTransfer.files;
|
158
|
-
if (files.length > 1) {
|
159
|
-
dndError('dnd-multi');
|
160
|
-
return;
|
161
|
-
}
|
145
|
+
$('.dnd-overlay-overwrite').hide();
|
146
|
+
})
|
147
|
+
.on('dragover', '.dnd-overlay', function (evt) {
|
148
|
+
evt.originalEvent.dataTransfer.dropEffect = 'copy';
|
149
|
+
evt.preventDefault();
|
150
|
+
})
|
151
|
+
.on('drop', '.dnd-overlay', function (evt) {
|
152
|
+
evt.preventDefault();
|
153
|
+
evt.stopPropagation();
|
154
|
+
|
155
|
+
var indicator = $('#sequence-file');
|
156
|
+
self.state.query.focus();
|
157
|
+
|
158
|
+
var files = evt.originalEvent.dataTransfer.files;
|
159
|
+
if (files.length > 1) {
|
160
|
+
dndError('dnd-multi');
|
161
|
+
return;
|
162
|
+
}
|
162
163
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
164
|
+
var file = files[0];
|
165
|
+
if (file.size > 10 * 1048576) {
|
166
|
+
dndError('dnd-large-file');
|
167
|
+
return;
|
168
|
+
}
|
168
169
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
170
|
+
var reader = new FileReader();
|
171
|
+
reader.onload = function (e) {
|
172
|
+
var content = e.target.result;
|
173
|
+
if (FASTA_FORMAT.test(content)) {
|
174
|
+
indicator.text(file.name + ' ');
|
175
|
+
self.state.query.value(content);
|
176
|
+
tgtMarker.hide();
|
177
|
+
} else {
|
177
178
|
// apparently not FASTA
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
179
|
+
dndError('dnd-format');
|
180
|
+
}
|
181
|
+
};
|
182
|
+
reader.onerror = function (e) {
|
182
183
|
// Couldn't read. Means dropped stuff wasn't FASTA file.
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
184
|
+
dndError('dnd-format');
|
185
|
+
};
|
186
|
+
reader.readAsText(file);
|
187
|
+
});
|
187
188
|
});
|
188
189
|
}
|
189
190
|
});
|
@@ -203,32 +204,39 @@ var Form = React.createClass({
|
|
203
204
|
componentDidMount: function () {
|
204
205
|
/* Fetch data to initialise the search interface from the server. These
|
205
206
|
* include list of databases to search against, advanced options to
|
206
|
-
* apply when an algorithm is selected, and a query
|
207
|
+
* apply when an algorithm is selected, and a query sequence that
|
207
208
|
* the user may want to search in the databases.
|
208
209
|
*/
|
209
|
-
|
210
|
+
var search = location.search.split(/\?|&/).filter(Boolean);
|
211
|
+
var job_id = sessionStorage.getItem('job_id');
|
212
|
+
if (job_id) {
|
213
|
+
search.unshift(`job_id=${job_id}`);
|
214
|
+
}
|
215
|
+
$.getJSON(`searchdata.json?${search.join('&')}`, function(data) {
|
210
216
|
/* Update form state (i.e., list of databases and predefined
|
211
217
|
* advanced options.
|
212
218
|
*/
|
213
219
|
this.setState({
|
214
|
-
databases: data[
|
220
|
+
databases: data['database'],
|
221
|
+
preSelectedDbs: data['preSelectedDbs'],
|
222
|
+
preDefinedOpts: data['options']
|
215
223
|
});
|
216
224
|
|
217
225
|
/* Pre-populate the form with server sent query sequences
|
218
226
|
* (if any).
|
219
227
|
*/
|
220
|
-
if (data[
|
221
|
-
this.refs.query.value(data[
|
228
|
+
if (data['query']) {
|
229
|
+
this.refs.query.value(data['query']);
|
222
230
|
}
|
223
231
|
}.bind(this));
|
224
232
|
|
225
233
|
/* Enable submitting form on Cmd+Enter */
|
226
|
-
|
227
|
-
|
234
|
+
$(document).bind('keydown', _.bind(function (e) {
|
235
|
+
if (e.ctrlKey && e.keyCode === 13 &&
|
228
236
|
!$('#method').is(':disabled')) {
|
229
|
-
|
230
|
-
|
231
|
-
|
237
|
+
$(this.getDOMNode()).trigger('submit');
|
238
|
+
}
|
239
|
+
}, this));
|
232
240
|
},
|
233
241
|
|
234
242
|
determineBlastMethod: function () {
|
@@ -241,26 +249,26 @@ var Form = React.createClass({
|
|
241
249
|
|
242
250
|
//database type is always known
|
243
251
|
switch (database_type) {
|
252
|
+
case 'protein':
|
253
|
+
switch (sequence_type) {
|
254
|
+
case undefined:
|
255
|
+
return ['blastp', 'blastx'];
|
244
256
|
case 'protein':
|
245
|
-
|
246
|
-
case undefined:
|
247
|
-
return ['blastp', 'blastx'];
|
248
|
-
case 'protein':
|
249
|
-
return ['blastp'];
|
250
|
-
case 'nucleotide':
|
251
|
-
return ['blastx'];
|
252
|
-
}
|
253
|
-
break;
|
257
|
+
return ['blastp'];
|
254
258
|
case 'nucleotide':
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
259
|
+
return ['blastx'];
|
260
|
+
}
|
261
|
+
break;
|
262
|
+
case 'nucleotide':
|
263
|
+
switch (sequence_type) {
|
264
|
+
case undefined:
|
265
|
+
return ['tblastn', 'blastn', 'tblastx'];
|
266
|
+
case 'protein':
|
267
|
+
return ['tblastn'];
|
268
|
+
case 'nucleotide':
|
269
|
+
return ['blastn', 'tblastx'];
|
270
|
+
}
|
271
|
+
break;
|
264
272
|
}
|
265
273
|
|
266
274
|
return [];
|
@@ -285,35 +293,32 @@ var Form = React.createClass({
|
|
285
293
|
},
|
286
294
|
|
287
295
|
handleAlgoChanged: function (algo) {
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
+
if (this.state.preDefinedOpts.hasOwnProperty(algo)) {
|
297
|
+
this.refs.opts.setState({
|
298
|
+
preOpts: this.state.preDefinedOpts[algo].join(' ')
|
299
|
+
});
|
300
|
+
}
|
301
|
+
else {
|
302
|
+
this.refs.opts.setState({preOpts: ''});
|
303
|
+
}
|
296
304
|
},
|
297
305
|
|
298
306
|
render: function () {
|
299
307
|
return (
|
300
|
-
<div
|
301
|
-
className="
|
302
|
-
|
303
|
-
id="blast" method="post" className="form-horizontal">
|
304
|
-
<div
|
305
|
-
className="form-group query-container">
|
308
|
+
<div className="container">
|
309
|
+
<form id="blast" method="post" className="form-horizontal">
|
310
|
+
<div className="form-group query-container">
|
306
311
|
<Query ref="query" onSequenceTypeChanged={this.handleSequenceTypeChanged}/>
|
307
312
|
</div>
|
308
|
-
<div
|
309
|
-
className="notifications" id="notifications">
|
313
|
+
<div className="notifications" id="notifications">
|
310
314
|
<NucleotideNotification/>
|
311
315
|
<ProteinNotification/>
|
312
316
|
<MixedNotification/>
|
313
317
|
</div>
|
314
|
-
<Databases ref="databases"
|
315
|
-
|
316
|
-
|
318
|
+
<Databases ref="databases" databases={this.state.databases}
|
319
|
+
preSelectedDbs={this.state.preSelectedDbs}
|
320
|
+
onDatabaseTypeChanged={this.handleDatabaseTypeChanaged} />
|
321
|
+
<div className="form-group">
|
317
322
|
<Options ref="opts"/>
|
318
323
|
<SearchButton ref="button" onAlgoChanged={this.handleAlgoChanged}/>
|
319
324
|
</div>
|
@@ -346,7 +351,7 @@ var Query = React.createClass({
|
|
346
351
|
else {
|
347
352
|
this.setState({
|
348
353
|
value: val
|
349
|
-
})
|
354
|
+
});
|
350
355
|
return this;
|
351
356
|
}
|
352
357
|
},
|
@@ -451,12 +456,12 @@ var Query = React.createClass({
|
|
451
456
|
if (!tmp) { continue; }
|
452
457
|
|
453
458
|
if (!type) {
|
454
|
-
|
455
|
-
|
459
|
+
// successfully guessed the type of atleast one sequence
|
460
|
+
type = tmp;
|
456
461
|
}
|
457
462
|
else if (tmp !== type) {
|
458
|
-
|
459
|
-
|
463
|
+
// user has mixed different type of sequences
|
464
|
+
return 'mixed';
|
460
465
|
}
|
461
466
|
}
|
462
467
|
|
@@ -511,7 +516,7 @@ var Query = React.createClass({
|
|
511
516
|
// Lifecycle methods. //
|
512
517
|
|
513
518
|
getInitialState: function () {
|
514
|
-
var input_sequence = $(
|
519
|
+
var input_sequence = $('input#input_sequence').val() || '';
|
515
520
|
return {
|
516
521
|
value: input_sequence
|
517
522
|
};
|
@@ -619,10 +624,7 @@ var MixedNotification = React.createClass({
|
|
619
624
|
|
620
625
|
var Databases = React.createClass({
|
621
626
|
getInitialState: function () {
|
622
|
-
return {
|
623
|
-
type: '',
|
624
|
-
databases: []
|
625
|
-
}
|
627
|
+
return { type: '' };
|
626
628
|
},
|
627
629
|
|
628
630
|
databases: function (category) {
|
@@ -631,9 +633,9 @@ var Databases = React.createClass({
|
|
631
633
|
}
|
632
634
|
|
633
635
|
return _.select(this.props.databases,
|
634
|
-
|
635
|
-
|
636
|
-
|
636
|
+
function (database) {
|
637
|
+
return database.type === category;
|
638
|
+
});
|
637
639
|
},
|
638
640
|
|
639
641
|
nselected: function () {
|
@@ -642,7 +644,7 @@ var Databases = React.createClass({
|
|
642
644
|
|
643
645
|
categories: function () {
|
644
646
|
return _.uniq(_.map(this.props.databases,
|
645
|
-
|
647
|
+
_.iteratee('type'))).sort();
|
646
648
|
},
|
647
649
|
|
648
650
|
handleClick: function (database) {
|
@@ -652,12 +654,12 @@ var Databases = React.createClass({
|
|
652
654
|
|
653
655
|
handleToggle: function (toggleState, type) {
|
654
656
|
switch (toggleState) {
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
657
|
+
case '[Select all]':
|
658
|
+
$(`.${type} .database input:not(:checked)`).click();
|
659
|
+
break;
|
660
|
+
case '[Deselect all]':
|
661
|
+
$(`.${type} .database input:checked`).click();
|
662
|
+
break;
|
661
663
|
}
|
662
664
|
},
|
663
665
|
|
@@ -672,13 +674,13 @@ var Databases = React.createClass({
|
|
672
674
|
renderDatabases: function (category) {
|
673
675
|
// Panel name and column width.
|
674
676
|
var panelTitle = category[0].toUpperCase() +
|
675
|
-
category.substring(1).toLowerCase() +
|
677
|
+
category.substring(1).toLowerCase() + ' databases';
|
676
678
|
var columnClass = this.categories().length === 1 ? 'col-md-12' :
|
677
679
|
'col-md-6';
|
678
680
|
|
679
681
|
// Toggle button.
|
680
682
|
var toggleState = '[Select all]';
|
681
|
-
var toggleClass = 'btn
|
683
|
+
var toggleClass = 'btn-link';
|
682
684
|
var toggleShown = this.databases(category).length > 1 ;
|
683
685
|
var toggleDisabled = this.state.type && this.state.type !== category;
|
684
686
|
if (toggleShown && toggleDisabled) toggleClass += ' disabled';
|
@@ -689,20 +691,20 @@ var Databases = React.createClass({
|
|
689
691
|
|
690
692
|
// JSX.
|
691
693
|
return (
|
692
|
-
<div className={columnClass} key={
|
694
|
+
<div className={columnClass} key={'DB_'+category}>
|
693
695
|
<div className="panel panel-default">
|
694
696
|
<div className="panel-heading">
|
695
|
-
<h4 style={{display:
|
697
|
+
<h4 style={{display: 'inline'}}>{panelTitle}</h4>
|
696
698
|
<button type="button" className={toggleClass} disabled={toggleDisabled}
|
697
|
-
onClick={ function () { this.handleToggle(toggleState, category) }.bind(this) }>
|
699
|
+
onClick={ function () { this.handleToggle(toggleState, category); }.bind(this) }>
|
698
700
|
{toggleState}
|
699
701
|
</button>
|
700
702
|
</div>
|
701
|
-
<ul className={
|
703
|
+
<ul className={'list-group databases ' + category}>
|
702
704
|
{
|
703
705
|
_.map(this.databases(category), _.bind(function (database,index) {
|
704
706
|
return (
|
705
|
-
<li className="list-group-item" key={
|
707
|
+
<li className="list-group-item" key={'DB_'+category+index}>
|
706
708
|
{ this.renderDatabase(database) }
|
707
709
|
</li>
|
708
710
|
);
|
@@ -724,18 +726,18 @@ var Databases = React.createClass({
|
|
724
726
|
type="checkbox" name="databases[]" value={database.id}
|
725
727
|
data-type={database.type} disabled={disabled}
|
726
728
|
onChange=
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
{
|
729
|
+
{
|
730
|
+
_.bind(function () {
|
731
|
+
this.handleClick(database);
|
732
|
+
}, this)
|
733
|
+
}/>
|
734
|
+
{' ' + (database.title || database.name)}
|
733
735
|
</label>
|
734
736
|
);
|
735
737
|
},
|
736
738
|
|
737
739
|
//shouldComponentUpdate: function (props, state) {
|
738
|
-
|
740
|
+
//return !(state.type && state.type === this.state.type);
|
739
741
|
//},
|
740
742
|
|
741
743
|
componentDidUpdate: function () {
|
@@ -744,6 +746,11 @@ var Databases = React.createClass({
|
|
744
746
|
this.handleClick(this.databases()[0]);
|
745
747
|
}
|
746
748
|
|
749
|
+
if (this.props.preSelectedDbs) {
|
750
|
+
var selectors = this.props.preSelectedDbs.map(db => `input[value=${db.id}]`);
|
751
|
+
$(...selectors).prop('checked',true);
|
752
|
+
setTimeout(() => this.handleClick(this.props.preSelectedDbs[0]));
|
753
|
+
}
|
747
754
|
this.props.onDatabaseTypeChanged(this.state.type);
|
748
755
|
}
|
749
756
|
});
|
@@ -751,15 +758,15 @@ var Databases = React.createClass({
|
|
751
758
|
var Options = React.createClass({
|
752
759
|
|
753
760
|
updateBox: function (evt) {
|
754
|
-
|
755
|
-
|
756
|
-
|
761
|
+
this.setState({
|
762
|
+
preOpts: evt.target.value
|
763
|
+
});
|
757
764
|
},
|
758
765
|
|
759
766
|
getInitialState: function () {
|
760
|
-
|
761
|
-
|
762
|
-
|
767
|
+
return {
|
768
|
+
preOpts: ''
|
769
|
+
};
|
763
770
|
},
|
764
771
|
|
765
772
|
render: function () {
|
@@ -784,7 +791,7 @@ var Options = React.createClass({
|
|
784
791
|
placeholder="eg: -evalue 1.0e-5 -num_alignments 100"
|
785
792
|
value={this.state.preOpts}
|
786
793
|
onChange={this.updateBox}
|
787
|
-
|
794
|
+
/>
|
788
795
|
<div
|
789
796
|
className="input-group-addon cursor-pointer"
|
790
797
|
data-toggle="modal" data-target="#help">
|
@@ -827,23 +834,23 @@ var SearchButton = React.createClass({
|
|
827
834
|
trigger: 'manual',
|
828
835
|
title: _.bind(function () {
|
829
836
|
if (!this.state.hasQuery && !this.state.hasDatabases) {
|
830
|
-
return
|
837
|
+
return 'You must enter a query sequence and select one or more databases above before you can run a search!';
|
831
838
|
}
|
832
839
|
else if (this.state.hasQuery && !this.state.hasDatabases) {
|
833
|
-
return
|
840
|
+
return 'You must select one or more databases above before you can run a search!';
|
834
841
|
}
|
835
842
|
else if (!this.state.hasQuery && this.state.hasDatabases) {
|
836
|
-
return
|
843
|
+
return 'You must enter a query sequence above before you can run a search!';
|
837
844
|
}
|
838
845
|
}, this)
|
839
846
|
});
|
840
847
|
|
841
848
|
this.submitButton().tooltip({
|
842
849
|
title: _.bind(function () {
|
843
|
-
var title =
|
850
|
+
var title = 'Click to BLAST or press Ctrl+Enter.';
|
844
851
|
if (this.state.methods.length > 1) {
|
845
|
-
title +=
|
846
|
-
|
852
|
+
title += ' Click dropdown button on the right for other' +
|
853
|
+
' BLAST algorithms that can be used.';
|
847
854
|
}
|
848
855
|
return title;
|
849
856
|
}, this)
|
@@ -902,7 +909,7 @@ var SearchButton = React.createClass({
|
|
902
909
|
methods: [],
|
903
910
|
hasQuery: false,
|
904
911
|
hasDatabases: false
|
905
|
-
}
|
912
|
+
};
|
906
913
|
},
|
907
914
|
|
908
915
|
render: function () {
|
@@ -970,7 +977,7 @@ var SearchButton = React.createClass({
|
|
970
977
|
this.props.onAlgoChanged(this.state.methods[0]);
|
971
978
|
}
|
972
979
|
else {
|
973
|
-
this.props.onAlgoChanged(
|
980
|
+
this.props.onAlgoChanged('');
|
974
981
|
}
|
975
982
|
}
|
976
983
|
});
|