import './jquery_world'; // for custom $.tooltip function import React, { Component } from 'react'; import _ from 'underscore'; import Sidebar from './sidebar'; import Hits from './hits'; import Circos from './circos'; 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). this.state = { user_warning: null, download_links: [], search_id: '', seqserv_version: '', program: '', program_version: '', submitted_at: '', results: [], queries: [], querydb: [], params: [], stats: [], alignment_blob_url: '', allQueriesLoaded: false, cloud_sharing_enabled: false, }; 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]; function poll() { fetch(path) .then(response => { // Handle HTTP status codes if (!response.ok) throw response; return response.text().then(data => { if (data) { data = parseJSON(data); }; return { status: response.status, data } }); }) .then(({ status, data }) => { switch (status) { case 202: var interval; if (intervals.length === 1) { interval = intervals[0]; } else { interval = intervals.shift(); } setTimeout(poll, interval); break; case 200: callback(data); break; } }) .catch(error => { if (error.text) { error.text().then(errData => { errData = parseJSON(errData); switch (error.status) { case 400: case 422: case 500: errCallback(errData); break; default: console.error("Unhandled error:", error.status); } }); } else { console.error("Network error:", error); } }); } function parseJSON(str) { let parsedJson = str; try { parsedJson = JSON.parse(str); } catch (e) { console.error("Error parsing JSON:", e); } return parsedJson; } poll(); } /** * Calls setState after any required modification to responseJSON. */ setStateFromJSON(responseJSON) { this.lastTimeStamp = Date.now(); // the callback prepares the download link for all alignments if (responseJSON.user_warning == 'LARGE_RESULT') { 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(); } /** * Called after all results have been rendered. */ componentFinishedUpdating() { if (this.state.allQueriesLoaded) return; this.shouldShowIndex() && this.setupScrollSpy(); this.setState({ allQueriesLoaded: true }); } /** * Returns loading message */ loadingJSX() { return (
This can take some time depending on the size of your query and
database(s). The page will update automatically when BLAST is done.
You can bookmark the page and come back to it later or share the
link with someone.
{ process.env.targetEnv === 'cloud' && If the job takes more than 10 minutes to complete, we will send you an email upon completion. }
The BLAST result might be too large to load in the browser. If you have a powerful machine you can try loading the results anyway. Otherwise, you can download the results and view them locally.
{this.state.download_links.map((link, index) => { return ( {link.name} ); })}
SequenceServer {this.state.seqserv_version} using{' '} {this.state.program_version} {this.state.submitted_at && `, query submitted on ${this.state.submitted_at}`}
Databases: {this.state.querydb .map((db) => { return db.title; }) .join(', ')}{' '} ({this.state.stats.nsequences} sequences, {this.state.stats.ncharacters} characters)
Parameters: {' '} {_.map(this.state.params, function (val, key) { return key + ' ' + val; }).join(', ')}
Please cite:{' '} https://doi.org/10.1093/molbev/msz185