mirror of
https://github.com/weaveworks/scope.git
synced 2026-03-03 18:20:27 +00:00
Adds basic "loading topologies" indicator for initial load.
Which can take a while sometimes.
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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')
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -17,6 +17,7 @@ const ACTION_TYPES = [
|
||||
'CLICK_TERMINAL',
|
||||
'CLICK_TOPOLOGY',
|
||||
'CLOSE_WEBSOCKET',
|
||||
'DEBUG_TOOLBAR_INTERFERING',
|
||||
'DESELECT_NODE',
|
||||
'DO_CONTROL',
|
||||
'DO_CONTROL_ERROR',
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user