public/js/report.js in sequenceserver-2.2.0 vs public/js/report.js in sequenceserver-3.0
- old
+ new
@@ -6,19 +6,18 @@
import Circos from './circos';
import { ReportQuery } from './query';
import Hit from './hit';
import HSP from './hsp';
import AlignmentExporter from './alignment_exporter';
+import ReportPlugins from 'report_plugins';
-
-
-
/**
* Renders entire report.
*
* Composed of Query and Sidebar components.
*/
+
class Report extends Component {
constructor(props) {
super(props);
// Properties below are internal state used to render results in small
// slices (see updateState).
@@ -45,19 +44,25 @@
cloud_sharing_enabled: false,
};
this.prepareAlignmentOfSelectedHits = this.prepareAlignmentOfSelectedHits.bind(this);
this.prepareAlignmentOfAllHits = this.prepareAlignmentOfAllHits.bind(this);
this.setStateFromJSON = this.setStateFromJSON.bind(this);
+ this.plugins = new ReportPlugins(this);
}
+
/**
* Fetch results.
*/
fetchResults() {
+ const path = location.pathname + '.json' + location.search;
+ this.pollPeriodically(path, this.setStateFromJSON, this.props.showErrorModal);
+ }
+
+ pollPeriodically(path, callback, errCallback) {
var intervals = [200, 400, 800, 1200, 2000, 3000, 5000];
- var component = this;
function poll() {
- $.getJSON(location.pathname + '.json' + location.search).complete(function (jqXHR) {
+ $.getJSON(path).complete(function (jqXHR) {
switch (jqXHR.status) {
case 202:
var interval;
if (intervals.length === 1) {
interval = intervals[0];
@@ -65,16 +70,16 @@
interval = intervals.shift();
}
setTimeout(poll, interval);
break;
case 200:
- component.setStateFromJSON(jqXHR.responseJSON);
+ callback(jqXHR.responseJSON);
break;
- case 404:
case 400:
+ case 422:
case 500:
- component.props.showErrorModal(jqXHR.responseJSON);
+ errCallback(jqXHR.responseJSON);
break;
}
});
}
@@ -91,17 +96,19 @@
this.setState({user_warning: responseJSON.user_warning, download_links: responseJSON.download_links});
} else {
this.setState(responseJSON, this.prepareAlignmentOfAllHits);
}
}
+
/**
* Called as soon as the page has loaded and the user sees the loading spinner.
* We use this opportunity to setup services that make use of delegated events
* bound to the window, document, or body.
*/
componentDidMount() {
this.fetchResults();
+ this.plugins.init();
// This sets up an event handler which enables users to select text from
// hit header without collapsing the hit.
this.preventCollapseOnSelection();
this.toggleTable();
}
@@ -110,11 +117,11 @@
* Called for the first time after as BLAST results have been retrieved from
* the server and added to this.state by fetchResults. Only summary overview
* and circos would have been rendered at this point. At this stage we kick
* start iteratively adding 1 HSP to the page every 25 milli-seconds.
*/
- componentDidUpdate() {
+ componentDidUpdate(prevProps, prevState) {
// Log to console how long the last update take?
// console.log((Date.now() - this.lastTimeStamp) / 1000);
// Lock sidebar in its position on the first update.
if (this.nextQuery == 0 && this.nextHit == 0 && this.nextHSP == 0) {
@@ -128,36 +135,41 @@
// to user interactions.
setTimeout(() => this.updateState(), 25);
} else {
this.componentFinishedUpdating();
}
+
+ this.plugins.componentDidUpdate(prevProps, prevState);
}
/**
* Push next slice of results to React for rendering.
*/
updateState() {
var results = [];
var numHSPsProcessed = 0;
while (this.nextQuery < this.state.queries.length) {
var query = this.state.queries[this.nextQuery];
+
// We may see a query multiple times during rendering because only
- // 3 hsps or are rendered in each cycle, but we want to create the
+ // 3 hsps are rendered in each cycle, but we want to create the
// corresponding Query component only the first time we see it.
if (this.nextHit == 0 && this.nextHSP == 0) {
results.push(
<ReportQuery
- key={'Query_' + query.number}
+ key={'Query_' + query.id}
query={query}
program={this.state.program}
querydb={this.state.querydb}
showQueryCrumbs={this.state.queries.length > 1}
non_parse_seqids={this.state.non_parse_seqids}
imported_xml={this.state.imported_xml}
veryBig={this.state.veryBig}
/>
);
+
+ results.push(...this.plugins.queryResults(query));
}
while (this.nextHit < query.hits.length) {
var hit = query.hits[this.nextHit];
// We may see a hit multiple times during rendering because only
@@ -188,15 +200,15 @@
var hsp = hit.hsps[this.nextHSP++];
results.push(
<HSP
key={
'Query_' +
- query.number +
- '_Hit_' +
- hit.number +
- '_HSP_' +
- hsp.number
+ query.number +
+ '_Hit_' +
+ hit.number +
+ '_HSP_' +
+ hsp.number
}
query={query}
hit={hit}
hsp={hsp}
algorithm={this.state.program}
@@ -259,10 +271,13 @@
database(s). The page will update automatically when BLAST is done.
<br />
<br />
You can bookmark the page and come back to it later or share the
link with someone.
+ <br />
+ <br />
+ { process.env.targetEnv === 'cloud' && <b>If the job takes more than 10 minutes to complete, we will send you an email upon completion.</b> }
</p>
</div>
</div>
);
}
@@ -449,11 +464,11 @@
/* Handling the fa icon when Hit Table is collapsed */
toggleTable() {
$('body').on(
'mousedown',
- '.resultn > .section-content > .table-hit-overview > .caption',
+ '.resultn .caption[data-toggle="collapse"]',
function (event) {
var $this = $(this);
$this.on('mouseup mousemove', function handler(event) {
$this.find('i').toggleClass('fa-minus-square-o fa-plus-square-o');
$this.off('mouseup mousemove', handler);
@@ -507,9 +522,10 @@
$('.download-fasta-of-selected').enable();
$('.download-alignment-of-selected').enable();
} else {
$hit.removeClass('glow');
$hit.next('.hsp').removeClass('glow');
+ $('.download-fasta-of-selected').attr('href', '#').removeAttr('download');
}
var $a = $('.download-fasta-of-selected');
var $b = $('.download-alignment-of-selected');