diff --git a/client/app/scripts/components/loading.js b/client/app/scripts/components/loading.js new file mode 100644 index 000000000..afd21b940 --- /dev/null +++ b/client/app/scripts/components/loading.js @@ -0,0 +1,59 @@ +import React from 'react'; +import _ from 'lodash'; + +import { findTopologyById } from '../utils/topology-utils'; +import NodesError from '../charts/nodes-error'; + + +const LOADING_TEMPLATES = [ + 'Loading THINGS', + 'Verifying THINGS', + 'Fetching THINGS', + 'Processing THINGS', + 'Reticulating THINGS', + 'Locating THINGS', + 'Optimizing THINGS', + 'Transporting THINGS', + 'Double checking THINGS', +]; + + +export function getNodeType(topology, topologies) { + if (!topology || topologies.size === 0) { + return ''; + } + let name = topology.get('name'); + if (topology.get('parentId')) { + const parentTopology = findTopologyById(topologies, topology.get('parentId')); + name = parentTopology.get('name'); + } + return name.toLowerCase(); +} + + +function renderTemplate(nodeType, template) { + return template.replace('THINGS', nodeType); +} + + +export class Loading extends React.Component { + + constructor(props, context) { + super(props, context); + + this.state = { + template: _.sample(LOADING_TEMPLATES) + }; + } + + render() { + const { itemType, show } = this.props; + const message = renderTemplate(itemType, this.state.template); + return ( + + ); + } + +} diff --git a/client/app/scripts/components/nodes.js b/client/app/scripts/components/nodes.js index 355629411..92db420dd 100644 --- a/client/app/scripts/components/nodes.js +++ b/client/app/scripts/components/nodes.js @@ -1,34 +1,17 @@ import React from 'react'; -import _ from 'lodash'; import { connect } from 'react-redux'; import NodesChart from '../charts/nodes-chart'; import NodesError from '../charts/nodes-error'; -import { findTopologyById, isTopologyEmpty } from '../utils/topology-utils'; +import { DelayedShow } from '../utils/delayed-show'; +import { Loading, getNodeType } from './loading'; +import { isTopologyEmpty } from '../utils/topology-utils'; const navbarHeight = 160; const marginTop = 0; const detailsWidth = 450; -const LOADING_TEMPLATES = [ - 'Loading THINGS', - 'Verifying THINGS', - 'Fetching THINGS', - 'Processing THINGS', - 'Reticulating THINGS', - 'Locating THINGS', - 'Optimizing THINGS', - 'Transporting THINGS', - 'Double checking THINGS', -]; - - -function renderTemplate(nodeType, template) { - return template.replace('THINGS', nodeType); -} - - /** * dynamic coords precision based on topology size */ @@ -47,29 +30,14 @@ function getLayoutPrecision(nodesCount) { return precision; } -function getNodeType(topology, topologies) { - if (!topology || topologies.size === 0) { - return ''; - } - let name = topology.get('name'); - if (topology.get('parentId')) { - const parentTopology = findTopologyById(topologies, topology.get('parentId')); - name = parentTopology.get('name'); - } - return name.toLowerCase(); -} - class Nodes extends React.Component { constructor(props, context) { super(props, context); this.handleResize = this.handleResize.bind(this); - const [topologiesLoadingTemplate, nodeLoadingTemplate] = _.sampleSize(LOADING_TEMPLATES, 2); this.state = { width: window.innerWidth, height: window.innerHeight - navbarHeight - marginTop, - topologiesLoadingTemplate, - nodeLoadingTemplate, }; } @@ -97,28 +65,20 @@ class Nodes extends React.Component { ); } - renderLoading(message, show) { - return ( - - ); - } - render() { const { nodes, selectedNodeId, topologyEmpty, topologiesLoaded, nodesLoaded, topologies, topology } = this.props; const layoutPrecision = getLayoutPrecision(nodes.size); const hasSelectedNode = selectedNodeId && nodes.has(selectedNodeId); - const topologyLoadingMessage = renderTemplate('topologies', - this.state.topologiesLoadingTemplate); - const nodeLoadingMessage = renderTemplate(getNodeType(topology, topologies), - this.state.nodeLoadingTemplate); return (
- {this.renderLoading(topologyLoadingMessage, !topologiesLoaded)} - {this.renderLoading(nodeLoadingMessage, topologiesLoaded && !nodesLoaded)} + + + + {this.renderEmptyTopologyError(topologiesLoaded && nodesLoaded && topologyEmpty)} this.setState({ show: true }), this.props.delay); + } + + cancelShow() { + clearTimeout(this.showTimeout); + } + + componentWillReceiveProps(nextProps) { + if (nextProps.show === this.props.show) { + return; + } + + if (nextProps.show) { + this.scheduleShow(); + } else { + this.cancelShow(); + this.setState({ show: false }); + } + } + + render() { + const { children } = this.props; + const { show } = this.state; + const style = { + opacity: show ? 1 : 0, + transition: 'opacity 0.5s ease-in-out', + }; + return ( +
+ {children} +
+ ); + } +} + + +DelayedShow.defaultProps = { + delay: 1000 +};