UNPKG

@jbrowse/plugin-linear-genome-view

Version:

JBrowse 2 linear genome view

224 lines (223 loc) 7.74 kB
import { readConfObject } from '@jbrowse/core/configuration'; import { assembleLocString, getContainingDisplay, getContainingTrack, getSession, getViewParams, makeAbortableReaction, } from '@jbrowse/core/util'; import { stopStopToken } from '@jbrowse/core/util/stopToken'; import { getRpcSessionId, getTrackAssemblyNames, } from '@jbrowse/core/util/tracks'; import { isRetryException } from '@jbrowse/core/util/types'; import { cast, getParent, isAlive, types } from 'mobx-state-tree'; import ServerSideRenderedBlockContent from '../components/ServerSideRenderedBlockContent'; const blockState = types .model('BlockState', { key: types.string, region: types.frozen(), reloadFlag: 0, isLeftEndOfDisplayedRegion: false, isRightEndOfDisplayedRegion: false, }) .volatile(() => ({ stopToken: undefined, filled: false, reactElement: undefined, features: undefined, layout: undefined, status: '', error: undefined, message: undefined, maxHeightReached: false, ReactComponent: ServerSideRenderedBlockContent, renderProps: undefined, })) .actions(self => ({ doReload() { self.reloadFlag = self.reloadFlag + 1; }, afterAttach() { const display = getContainingDisplay(self); setTimeout(() => { if (isAlive(self)) { makeAbortableReaction(self, renderBlockData, renderBlockEffect, { name: `${display.id}/${assembleLocString(self.region)} rendering`, delay: display.renderDelay, fireImmediately: true, }, this.setLoading, this.setRendered, this.setError); } }, display.renderDelay); }, setStatus(message) { self.status = message; }, setLoading(newStopToken) { if (self.stopToken !== undefined) { stopStopToken(self.stopToken); } self.filled = false; self.message = undefined; self.reactElement = undefined; self.features = undefined; self.layout = undefined; self.error = undefined; self.maxHeightReached = false; self.renderProps = undefined; self.stopToken = newStopToken; }, setMessage(messageText) { if (self.stopToken !== undefined) { stopStopToken(self.stopToken); } self.filled = false; self.message = messageText; self.reactElement = undefined; self.features = undefined; self.layout = undefined; self.error = undefined; self.maxHeightReached = false; self.renderProps = undefined; self.stopToken = undefined; }, setRendered(props) { if (!props) { return; } const { reactElement, features, layout, maxHeightReached, renderProps } = props; self.filled = true; self.message = undefined; self.reactElement = reactElement; self.features = features; self.layout = layout; self.error = undefined; self.maxHeightReached = maxHeightReached; self.renderProps = renderProps; self.stopToken = undefined; }, setError(error) { console.error(error); if (self.stopToken !== undefined) { stopStopToken(self.stopToken); } self.filled = false; self.message = undefined; self.reactElement = undefined; self.features = undefined; self.layout = undefined; self.maxHeightReached = false; self.error = error; self.renderProps = undefined; self.stopToken = undefined; if (isRetryException(error)) { this.reload(); } }, reload() { self.stopToken = undefined; self.filled = false; self.reactElement = undefined; self.features = undefined; self.layout = undefined; self.error = undefined; self.message = undefined; self.maxHeightReached = false; self.ReactComponent = ServerSideRenderedBlockContent; self.renderProps = undefined; getParent(self, 2).reload(); }, beforeDestroy() { ; (async () => { try { if (self.stopToken !== undefined) { stopStopToken(self.stopToken); } const display = getContainingDisplay(self); const { rpcManager } = getSession(self); const { rendererType } = display; const { renderArgs } = renderBlockData(cast(self)); if (renderArgs) { await rendererType.freeResourcesInClient(rpcManager, JSON.parse(JSON.stringify(renderArgs))); } } catch (e) { console.error('Error while destroying block', e); } })(); }, })); export default blockState; export function renderBlockData(self, optDisplay) { try { const display = optDisplay || getContainingDisplay(self); const { assemblyManager, rpcManager } = getSession(display); const { adapterConfig, rendererType, error, parentTrack } = display; const assemblyNames = getTrackAssemblyNames(parentTrack); const regionAsm = self.region.assemblyName; if (!assemblyNames.includes(regionAsm) && !assemblyNames.some(name => { var _a; return (_a = assemblyManager.get(name)) === null || _a === void 0 ? void 0 : _a.hasName(regionAsm); })) { throw new Error(`region assembly (${regionAsm}) does not match track assemblies (${assemblyNames})`); } const renderProps = display.renderProps(); const { config } = renderProps; readConfObject(config); const sessionId = getRpcSessionId(display); const layoutId = getContainingTrack(display).id; const cannotBeRenderedReason = display.regionCannotBeRendered(self.region); return { rendererType, rpcManager, renderProps, cannotBeRenderedReason, displayError: error, renderArgs: { statusCallback: (message) => { if (isAlive(self)) { self.setStatus(message); } }, assemblyName: self.region.assemblyName, regions: [self.region], adapterConfig, rendererType: rendererType.name, sessionId, layoutId, blockKey: self.key, reloadFlag: self.reloadFlag, timeout: 1000000, }, }; } catch (e) { return { displayError: e }; } } async function renderBlockEffect(props, stopToken, self) { if (!props) { return; } const { rendererType, renderProps, rpcManager, renderArgs, cannotBeRenderedReason, displayError, } = props; if (!isAlive(self)) { return undefined; } else if (displayError) { self.setError(displayError); return undefined; } else if (cannotBeRenderedReason) { self.setMessage(cannotBeRenderedReason); return undefined; } else if (renderProps.notReady) { return undefined; } else { const { reactElement, features, layout, maxHeightReached } = await rendererType.renderInClient(rpcManager, { ...renderArgs, ...renderProps, viewParams: getViewParams(self), stopToken, }); return { reactElement, features, layout, maxHeightReached, renderProps, }; } }