Skip to content

Commit

Permalink
Merge pull request #729 from plotly/async-components
Browse files Browse the repository at this point in the history
Make FornaContainer component async
  • Loading branch information
LiamConnors authored Feb 24, 2023
2 parents 2b16035 + e7a6feb commit 2954dfe
Show file tree
Hide file tree
Showing 18 changed files with 152 additions and 116 deletions.
12 changes: 12 additions & 0 deletions R/internal.R
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ all_files = FALSE, async = TRUE), class = "html_dependency"),
`dash_bio` = structure(list(name = "dash_bio",
version = "1.0.2", src = list(href = NULL,
file = "deps"), meta = NULL,
script = 'async-fornacontainer.js',
stylesheet = NULL, head = NULL, attachment = NULL, package = "dashBio",
all_files = FALSE, async = TRUE), class = "html_dependency"),
`dash_bio` = structure(list(name = "dash_bio",
version = "1.0.2", src = list(href = NULL,
file = "deps"), meta = NULL,
script = 'async-ideogram.js',
stylesheet = NULL, head = NULL, attachment = NULL, package = "dashBio",
all_files = FALSE, async = TRUE), class = "html_dependency"),
Expand Down Expand Up @@ -92,6 +98,12 @@ all_files = FALSE, dynamic = TRUE), class = "html_dependency"),
`dash_bio` = structure(list(name = "dash_bio",
version = "1.0.2", src = list(href = NULL,
file = "deps"), meta = NULL,
script = 'async-fornacontainer.js.map',
stylesheet = NULL, head = NULL, attachment = NULL, package = "dashBio",
all_files = FALSE, dynamic = TRUE), class = "html_dependency"),
`dash_bio` = structure(list(name = "dash_bio",
version = "1.0.2", src = list(href = NULL,
file = "deps"), meta = NULL,
script = 'async-ideogram.js.map',
stylesheet = NULL, head = NULL, attachment = NULL, package = "dashBio",
all_files = FALSE, dynamic = TRUE), class = "html_dependency"),
Expand Down
1 change: 1 addition & 0 deletions dash_bio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
async_resources = [
'alignment',
'circos',
'fornacontainer',
'ideogram',
'igv',
'pileup',
Expand Down
2 changes: 2 additions & 0 deletions dash_bio/async-fornacontainer.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions dash_bio/async-fornacontainer.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dash_bio/bundle.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dash_bio/bundle.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dash_bio/dash_bio-shared.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dash_bio/dash_bio-shared.js.map

Large diffs are not rendered by default.

10 changes: 1 addition & 9 deletions dash_bio/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -807,15 +807,7 @@
"src/lib/components/FornaContainer.react.js": {
"description": "FornaContainer is a force-directed graph that is used to visualize\nthe secondary structure of biomolecules. It is based on the fornac\nlibrary (https://github.com/ViennaRNA/fornac).",
"displayName": "FornaContainer",
"methods": [
{
"name": "renderNewSequences",
"docblock": null,
"modifiers": [],
"params": [],
"returns": null
}
],
"methods": [],
"props": {
"id": {
"type": {
Expand Down
2 changes: 2 additions & 0 deletions inst/deps/async-fornacontainer.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions inst/deps/async-fornacontainer.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion inst/deps/bundle.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion inst/deps/bundle.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion inst/deps/dash_bio-shared.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion inst/deps/dash_bio-shared.js.map

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions src/lib/LazyLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ export default {
),
circos: () =>
import(/* webpackChunkName: "circos" */ './fragments/Circos.react'),
fornacontainer: () =>
import(
/* webpackChunkName: "fornacontainer" */ './fragments/FornaContainer.react'
),
ideogram: () =>
import(/* webpackChunkName: "ideogram" */ './fragments/Ideogram.react'),
igv: () => import(/* webpackChunkName: "igv" */ './fragments/Igv.react'),
Expand Down
109 changes: 10 additions & 99 deletions src/lib/components/FornaContainer.react.js
Original file line number Diff line number Diff line change
@@ -1,112 +1,20 @@
import React, {Component} from 'react';
import React, {Component, lazy, Suspense} from 'react';
import PropTypes from 'prop-types';
import {FornaContainer as PreFornaContainer} from 'fornac';
import * as R from 'ramda';
import LazyLoader from '../LazyLoader';

const RealFornaContainer = lazy(LazyLoader.fornacontainer);

/**
* FornaContainer is a force-directed graph that is used to visualize
* the secondary structure of biomolecules. It is based on the fornac
* library (https://github.com/ViennaRNA/fornac).
*/
export default class FornaContainer extends Component {
constructor(props) {
super(props);
this.renderNewSequences = this.renderNewSequences.bind(this);
this.containerRef = React.createRef();
}

componentDidMount() {
const {
height,
width,
nodeFillColor,
colorScheme,
customColors,
allowPanningAndZooming,
hoverPattern,
} = this.props;

this._fornaContainer = new PreFornaContainer(
this.containerRef.current,
{
initialSize: [width, height],
allowPanningAndZooming: allowPanningAndZooming,
hoverPattern: hoverPattern,
}
);
// initialize the correct colors
this._fornaContainer.addCustomColors(customColors);
this._fornaContainer.changeColorScheme(colorScheme);

this.renderNewSequences();

if (nodeFillColor !== undefined) {
this._fornaContainer.setOutlineColor(nodeFillColor);
}
}

componentDidUpdate() {
this.renderNewSequences();
}

renderNewSequences() {
const {sequences} = this.props;

if (this._fornaContainer) {
this._fornaContainer.clearNodes();

sequences.forEach((seq) => {
const unpackedOptions = Object.assign({}, seq.options, {
sequence: seq.sequence,
structure: seq.structure,
});
this._fornaContainer.addRNA(seq.structure, unpackedOptions);
});
}
}

shouldComponentUpdate(nextProps) {
const {sequences, colorScheme, hoverPattern, loading_state} =
this.props;

if (!R.equals(sequences, nextProps.sequences)) {
return true;
}

if (nextProps.hoverPattern !== hoverPattern) {
this._fornaContainer.setHoverPattern(nextProps.hoverPattern);
return true;
}

this._fornaContainer.addCustomColors(nextProps.customColors);
this._fornaContainer.changeColorScheme(colorScheme);

if (nextProps.nodeFillColor !== undefined) {
this._fornaContainer.setOutlineColor(nextProps.nodeFillColor);
}

if (
JSON.stringify(loading_state) !==
JSON.stringify(nextProps.loading_state)
) {
return true;
}

return false;
}

render() {
return (
<div
id={this.props.id}
ref={this.containerRef}
style={{outline: 'none'}}
data-dash-is-loading={
(this.props.loading_state &&
this.props.loading_state.is_loading) ||
undefined
}
/>
<Suspense fallback={null}>
<RealFornaContainer {...this.props} />
</Suspense>
);
}
}
Expand Down Expand Up @@ -303,3 +211,6 @@ FornaContainer.defaultProps = {
allowPanningAndZooming: true,
colorScheme: 'sequence',
};

export const defaultProps = FornaContainer.defaultProps;
export const propTypes = FornaContainer.propTypes;
110 changes: 110 additions & 0 deletions src/lib/fragments/FornaContainer.react.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import React, {Component} from 'react';
import {FornaContainer as PreFornaContainer} from 'fornac';
import * as R from 'ramda';
import {propTypes, defaultProps} from '../components/FornaContainer.react';

export default class FornaContainer extends Component {
constructor(props) {
super(props);
this.renderNewSequences = this.renderNewSequences.bind(this);
this.containerRef = React.createRef();
}

componentDidMount() {
const {
height,
width,
nodeFillColor,
colorScheme,
customColors,
allowPanningAndZooming,
hoverPattern,
} = this.props;

this._fornaContainer = new PreFornaContainer(
this.containerRef.current,
{
initialSize: [width, height],
allowPanningAndZooming: allowPanningAndZooming,
hoverPattern: hoverPattern,
}
);
// initialize the correct colors
this._fornaContainer.addCustomColors(customColors);
this._fornaContainer.changeColorScheme(colorScheme);

this.renderNewSequences();

if (nodeFillColor !== undefined) {
this._fornaContainer.setOutlineColor(nodeFillColor);
}
}

componentDidUpdate() {
this.renderNewSequences();
}

renderNewSequences() {
const {sequences} = this.props;

if (this._fornaContainer) {
this._fornaContainer.clearNodes();

sequences.forEach((seq) => {
const unpackedOptions = Object.assign({}, seq.options, {
sequence: seq.sequence,
structure: seq.structure,
});
this._fornaContainer.addRNA(seq.structure, unpackedOptions);
});
}
}

shouldComponentUpdate(nextProps) {
const {sequences, colorScheme, hoverPattern, loading_state} =
this.props;

if (!R.equals(sequences, nextProps.sequences)) {
return true;
}

if (nextProps.hoverPattern !== hoverPattern) {
this._fornaContainer.setHoverPattern(nextProps.hoverPattern);
return true;
}

this._fornaContainer.addCustomColors(nextProps.customColors);
this._fornaContainer.changeColorScheme(colorScheme);

if (nextProps.nodeFillColor !== undefined) {
this._fornaContainer.setOutlineColor(nextProps.nodeFillColor);
}

if (
JSON.stringify(loading_state) !==
JSON.stringify(nextProps.loading_state)
) {
return true;
}

return false;
}

render() {
return (
<div
id={this.props.id}
ref={this.containerRef}
style={{outline: 'none'}}
data-dash-is-loading={
(this.props.loading_state &&
this.props.loading_state.is_loading) ||
undefined
}
/>
);
}
}

FornaContainer.defaultProps = defaultProps;
FornaContainer.propTypes = propTypes;

0 comments on commit 2954dfe

Please sign in to comment.