From 38fa82dee46974ff6b28d665e5012509d07de640 Mon Sep 17 00:00:00 2001 From: David Kaltschmidt Date: Tue, 15 Sep 2015 16:38:31 +0200 Subject: [PATCH] animate status bar, add Loading text --- client/app/scripts/components/app.js | 2 ++ client/app/scripts/components/status.js | 47 ++++++++++++++----------- client/app/scripts/stores/app-store.js | 6 ++++ client/app/styles/main.less | 16 +++++++-- 4 files changed, 48 insertions(+), 23 deletions(-) diff --git a/client/app/scripts/components/app.js b/client/app/scripts/components/app.js index 89f7b52d2..8f23c3b30 100644 --- a/client/app/scripts/components/app.js +++ b/client/app/scripts/components/app.js @@ -30,6 +30,7 @@ function getStateFromStores() { nodeDetails: AppStore.getNodeDetails(), nodes: AppStore.getNodes(), topologies: AppStore.getTopologies(), + topologiesLoaded: AppStore.isTopologiesLoaded(), version: AppStore.getVersion(), websocketClosed: AppStore.isWebsocketClosed() }; @@ -94,6 +95,7 @@ const App = React.createClass({ diff --git a/client/app/scripts/components/status.js b/client/app/scripts/components/status.js index cea0dc382..43a698d6b 100644 --- a/client/app/scripts/components/status.js +++ b/client/app/scripts/components/status.js @@ -2,29 +2,34 @@ const React = require('react'); const Status = React.createClass({ - renderConnectionState: function(errorUrl, websocketClosed) { - if (errorUrl || websocketClosed) { - const title = errorUrl ? 'Cannot reach Scope. Make sure the following URL is reachable: ' + errorUrl : ''; - return ( -
- - Trying to reconnect... -
- ); - } - }, - - renderTopologyStats: function(stats) { - const statsText = `${stats.node_count} nodes, ${stats.edge_count} connections`; - return
{statsText}
; - }, - render: function() { - const showStats = this.props.topology && !this.props.errorUrl && !this.props.websocketClosed; + let title = ''; + let text = 'Trying to reconnect...'; + let showWarningIcon = false; + let classNames = 'status sidebar-item'; + + if (this.props.errorUrl) { + title = `Cannot reach Scope. Make sure the following URL is reachable: ${this.props.errorUrl}`; + classNames += ' status-loading'; + showWarningIcon = true; + } else if (!this.props.topologiesLoaded) { + text = 'Loading topologies...'; + classNames += ' status-loading'; + showWarningIcon = false; + } else if (this.props.websocketClosed) { + classNames += ' status-loading'; + showWarningIcon = true; + } else if (this.props.topology) { + const stats = this.props.topology.stats; + text = `${stats.node_count} nodes, ${stats.edge_count} connections`; + classNames += ' status-stats'; + showWarningIcon = false; + } + return ( -
- {showStats && this.renderTopologyStats(this.props.topology.stats)} - {!showStats && this.renderConnectionState(this.props.errorUrl, this.props.websocketClosed)} +
+ {showWarningIcon && } + {text}
); } diff --git a/client/app/scripts/stores/app-store.js b/client/app/scripts/stores/app-store.js index 09aa0aac4..aa689c7cd 100644 --- a/client/app/scripts/stores/app-store.js +++ b/client/app/scripts/stores/app-store.js @@ -56,6 +56,7 @@ let nodes = makeOrderedMap(); let nodeDetails = null; let selectedNodeId = null; let topologies = []; +let topologiesLoaded = false; let websocketClosed = true; function setTopology(topologyId) { @@ -192,6 +193,10 @@ const AppStore = assign({}, EventEmitter.prototype, { return version; }, + isTopologiesLoaded: function() { + return topologiesLoaded; + }, + isWebsocketClosed: function() { return websocketClosed; } @@ -316,6 +321,7 @@ AppStore.registeredCallback = function(payload) { case ActionTypes.RECEIVE_TOPOLOGIES: errorUrl = null; + topologiesLoaded = true; topologies = payload.topologies; if (!currentTopology) { setTopology(currentTopologyId); diff --git a/client/app/styles/main.less b/client/app/styles/main.less index 84078d9d2..f7d843f60 100644 --- a/client/app/styles/main.less +++ b/client/app/styles/main.less @@ -167,7 +167,6 @@ h2 { font-size: 16px; position: relative; top: 1px; - color: @text-secondary-color; } &-label { @@ -389,7 +388,7 @@ h2 { .sidebar { position: fixed; bottom: 16px; - left: 24px; + left: 20px; width: 18em; font-size: 85%; @@ -404,6 +403,9 @@ h2 { background-color: darken(@background-color, 4%); color: @text-secondary-color; } + &.status-loading { + animation: status-loading 2.0s infinite ease-in-out; + } &-action { float: right; @@ -415,3 +417,13 @@ h2 { } } } + +@keyframes status-loading { + 0%, 100% { + background-color: darken(@background-color, 4%); + color: @text-secondary-color; + } 50% { + background-color: darken(@background-color, 8%); + color: @text-color; + } +}