Adds basic "loading topologies" indicator for initial load.

Which can take a while sometimes.
This commit is contained in:
Simon Howe
2016-05-12 09:15:08 +02:00
parent 1ffdafdf8c
commit 9a0feb3eb0
7 changed files with 62 additions and 17 deletions

View File

@@ -1,14 +1,15 @@
import React from 'react';
import classnames from 'classnames';
export default function NodesError({children, faIconClass, hidden}) {
let classNames = 'nodes-chart-error';
if (hidden) {
classNames += ' hide';
}
export default function NodesError({children, faIconClass, hidden,
mainClassName = 'nodes-chart-error'}) {
const className = classnames(mainClassName, {
hide: hidden
});
const iconClassName = `fa ${faIconClass}`;
return (
<div className={classNames}>
<div className={className}>
<div className="nodes-chart-error-icon">
<span className={iconClassName} />
</div>

View File

@@ -9,6 +9,7 @@ import { fromJS } from 'immutable';
import debug from 'debug';
const log = debug('scope:debug-panel');
import ActionTypes from '../constants/action-types';
import { receiveNodesDelta } from '../actions/app-actions';
import { getNodeColor, getNodeColorDark, text2degree } from '../utils/color-utils';
@@ -111,11 +112,13 @@ function stopPerf() {
Perf.printWasted(measurements);
}
function startPerf(delay) {
Perf.start();
setTimeout(stopPerf, delay * 1000);
}
export function showingDebugToolbar() {
return (('debugToolbar' in localStorage && JSON.parse(localStorage.debugToolbar))
|| location.pathname.indexOf('debug') > -1);
@@ -134,11 +137,23 @@ function enableLog(ns) {
window.location.reload();
}
function disableLog() {
debug.disable();
window.location.reload();
}
function setAppState(fn) {
return (dispatch) => {
dispatch({
type: ActionTypes.DEBUG_TOOLBAR_INTERFERING,
fn
});
};
}
class DebugToolbar extends React.Component {
constructor(props, context) {
@@ -162,6 +177,10 @@ class DebugToolbar extends React.Component {
});
}
setLoading(loading) {
this.props.setAppState(state => state.set('topologiesLoaded', !loading));
}
addNodes(n, prefix = 'zing') {
const ns = this.props.nodes;
const nodeNames = ns.keySeq().toJS();
@@ -243,6 +262,12 @@ class DebugToolbar extends React.Component {
</table>
))}
<div>
<label>state</label>
<button onClick={() => this.setLoading(true)}>Set doing initial load</button>
<button onClick={() => this.setLoading(false)}>Stop</button>
</div>
<div>
<label>Measure React perf for </label>
<button onClick={() => startPerf(2)}>2s</button>
@@ -254,6 +279,7 @@ class DebugToolbar extends React.Component {
}
}
function mapStateToProps(state) {
return {
nodes: state.get('nodes'),
@@ -261,6 +287,8 @@ function mapStateToProps(state) {
};
}
export default connect(
mapStateToProps
mapStateToProps,
{setAppState}
)(DebugToolbar);

View File

@@ -62,15 +62,24 @@ class Nodes extends React.Component {
);
}
renderLoading(show) {
return (
<NodesError mainClassName="nodes-chart-loading" faIconClass="fa-circle-thin" hidden={!show}>
<div className="heading">Loading Topologies</div>
</NodesError>
);
}
render() {
const { nodes, selectedNodeId, topologyEmpty } = this.props;
const { nodes, selectedNodeId, topologyEmpty, topologiesLoaded } = this.props;
const layoutPrecision = getLayoutPrecision(nodes.size);
const hasSelectedNode = selectedNodeId && nodes.has(selectedNodeId);
const errorEmpty = this.renderEmptyTopologyError(topologyEmpty);
return (
<div className="nodes-wrapper">
{topologyEmpty && errorEmpty}
{!topologiesLoaded ?
this.renderLoading(!topologiesLoaded) :
(topologyEmpty && this.renderEmptyTopologyError(topologyEmpty))}
<NodesChart {...this.state}
detailsWidth={detailsWidth}
layoutPrecision={layoutPrecision}
@@ -97,6 +106,7 @@ function mapStateToProps(state) {
nodes: state.get('nodes'),
selectedNodeId: state.get('selectedNodeId'),
topologyEmpty: isTopologyEmpty(state),
topologiesLoaded: state.get('topologiesLoaded')
};
}

View File

@@ -3,8 +3,7 @@ import { connect } from 'react-redux';
class Status extends React.Component {
render() {
const {errorUrl, filteredNodeCount, topologiesLoaded, topology,
websocketClosed} = this.props;
const {errorUrl, filteredNodeCount, topology, websocketClosed} = this.props;
let title = '';
let text = 'Trying to reconnect...';
@@ -15,10 +14,6 @@ class Status extends React.Component {
title = `Cannot reach Scope. Make sure the following URL is reachable: ${errorUrl}`;
classNames += ' status-loading';
showWarningIcon = true;
} else if (!topologiesLoaded) {
text = 'Connecting to Scope...';
classNames += ' status-loading';
showWarningIcon = true;
} else if (websocketClosed) {
classNames += ' status-loading';
showWarningIcon = true;

View File

@@ -17,6 +17,7 @@ const ACTION_TYPES = [
'CLICK_TERMINAL',
'CLICK_TOPOLOGY',
'CLOSE_WEBSOCKET',
'DEBUG_TOOLBAR_INTERFERING',
'DESELECT_NODE',
'DO_CONTROL',
'DO_CONTROL_ERROR',

View File

@@ -656,6 +656,10 @@ export function rootReducer(state = initialState, action) {
return applyPinnedSearches(state);
}
case ActionTypes.DEBUG_TOOLBAR_INTERFERING: {
return action.fn(state);
}
default: {
return state;
}

View File

@@ -296,7 +296,7 @@ h2 {
.nodes-chart {
&-error {
&-error, &-loading {
.hideable;
position: absolute;
left: 50%;
@@ -304,6 +304,7 @@ h2 {
transform: translate(-50%, -50%);
color: @text-secondary-color;
width: 33%;
height: 550px;
.heading {
font-size: 125%;
@@ -316,6 +317,11 @@ h2 {
}
}
&-loading {
animation: blinking 2s infinite @base-ease;
text-align: center;
}
svg {
.hideable;
position: absolute;