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 (
+
+ {message}
+
+ );
+ }
+
+}
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 (
-
- {message}
-
- );
- }
-
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
+};