diff --git a/client/app/scripts/actions/app-actions.js b/client/app/scripts/actions/app-actions.js index 58f8ff9ce6..ac82b7984f 100644 --- a/client/app/scripts/actions/app-actions.js +++ b/client/app/scripts/actions/app-actions.js @@ -9,6 +9,15 @@ module.exports = { RouterUtils.updateRoute(); }, + clickGrouping: function(grouping) { + AppDispatcher.dispatch({ + type: ActionTypes.CLICK_GROUPING, + grouping: grouping + }); + RouterUtils.updateRoute(); + WebapiUtils.getNodesDelta(AppStore.getUrlForTopology(AppStore.getCurrentTopology())); + }, + clickNode: function(nodeId) { AppDispatcher.dispatch({ type: ActionTypes.CLICK_NODE, @@ -27,15 +36,6 @@ module.exports = { WebapiUtils.getNodesDelta(AppStore.getUrlForTopology(AppStore.getCurrentTopology())); }, - clickTopologyMode: function(mode) { - AppDispatcher.dispatch({ - type: ActionTypes.CLICK_TOPOLOGY_MODE, - mode: mode - }); - RouterUtils.updateRoute(); - WebapiUtils.getNodesDelta(AppStore.getUrlForTopology(AppStore.getCurrentTopology())); - }, - hitEsc: function() { AppDispatcher.dispatch({ type: ActionTypes.HIT_ESC_KEY diff --git a/client/app/scripts/charts/nodes-chart.js b/client/app/scripts/charts/nodes-chart.js index fce55f2337..8b43528dac 100644 --- a/client/app/scripts/charts/nodes-chart.js +++ b/client/app/scripts/charts/nodes-chart.js @@ -7,7 +7,7 @@ var Node = require('./node'); var MAX_NODES = 100; var MARGINS = { - top: 120, + top: 130, left: 40, right: 40, bottom: 0 @@ -151,7 +151,7 @@ var NodesChart = React.createClass({ var zoomFactor = Math.min(xFactor, yFactor); var zoomScale = this.state.scale; - if(this.zoom && !this.state.hasZoomed && zoomFactor < 1) { + if(this.zoom && !this.state.hasZoomed && zoomFactor > 0 && zoomFactor < 1) { zoomScale = zoomFactor; // saving in d3's behavior cache this.zoom.scale(zoomFactor); diff --git a/client/app/scripts/components/app.js b/client/app/scripts/components/app.js index bf2dfedeeb..128006cf99 100644 --- a/client/app/scripts/components/app.js +++ b/client/app/scripts/components/app.js @@ -6,6 +6,7 @@ var _ = require('lodash'); var Logo = require('./logo'); var SearchBar = require('./search-bar.js'); var AppStore = require('../stores/app-store'); +var Groupings = require('./groupings.js'); var Topologies = require('./topologies.js'); var TopologyStore = require('../stores/topology-store'); var WebapiUtils = require('../utils/web-api-utils'); @@ -20,12 +21,12 @@ var ESC_KEY_CODE = 27; function getStateFromStores() { return { + activeTopology: AppStore.getCurrentTopology(), + currentGrouping: AppStore.getCurrentGrouping(), selectedNodeId: AppStore.getSelectedNodeId(), nodeDetails: AppStore.getNodeDetails(), nodes: TopologyStore.getNodes(), - topologies: AppStore.getTopologies(), - activeTopology: AppStore.getCurrentTopology(), - activeTopologyMode: AppStore.getCurrentTopologyMode() + topologies: AppStore.getTopologies() } } @@ -68,6 +69,7 @@ var App = React.createClass({
+
diff --git a/client/app/scripts/components/groupings.js b/client/app/scripts/components/groupings.js new file mode 100644 index 0000000000..97d976e440 --- /dev/null +++ b/client/app/scripts/components/groupings.js @@ -0,0 +1,48 @@ +/** @jsx React.DOM */ + +var React = require('react'); +var _ = require('lodash'); + +var AppActions = require('../actions/app-actions'); +var AppStore = require('../stores/app-store'); + +var GROUPINGS = [{ + id: 'none', + iconClass: 'fa fa-th' +}, { + id: 'grouped', + iconClass: 'fa fa-th-large' +}]; + +var Groupings = React.createClass({ + + onGroupingClick: function(ev) { + ev.preventDefault(); + AppActions.clickGrouping(ev.currentTarget.getAttribute('rel')); + }, + + renderGrouping: function(grouping, active) { + var className = grouping.id === active ? "groupings-item groupings-item-active" : "groupings-item"; + + return ( +
+ +
+ ); + }, + + render: function() { + var activeGrouping = this.props.active; + + return ( +
+ {GROUPINGS.map(function(grouping) { + return this.renderGrouping(grouping, activeGrouping); + }, this)} +
+ ); + } + +}); + +module.exports = Groupings; diff --git a/client/app/scripts/components/topologies.js b/client/app/scripts/components/topologies.js index a36164f999..8c93e8c44d 100644 --- a/client/app/scripts/components/topologies.js +++ b/client/app/scripts/components/topologies.js @@ -39,7 +39,6 @@ var Topologies = React.createClass({ return (
- {topologies.map(function(topology) { return this.renderTopology(topology, activeTopologyId); }, this)} diff --git a/client/app/scripts/constants/action-types.js b/client/app/scripts/constants/action-types.js index 214c8c10b6..e25f6e99c8 100644 --- a/client/app/scripts/constants/action-types.js +++ b/client/app/scripts/constants/action-types.js @@ -2,9 +2,9 @@ var keymirror = require('keymirror'); module.exports = keymirror({ CLICK_CLOSE_DETAILS: null, + CLICK_GROUPING: null, CLICK_NODE: null, CLICK_TOPOLOGY: null, - CLICK_TOPOLOGY_MODE: null, ENTER_NODE: null, HIT_ESC_KEY: null, LEAVE_NODE: null, diff --git a/client/app/scripts/stores/app-store.js b/client/app/scripts/stores/app-store.js index 6c099b78e7..0d21d63645 100644 --- a/client/app/scripts/stores/app-store.js +++ b/client/app/scripts/stores/app-store.js @@ -11,8 +11,8 @@ var TopologyStore = require('./topology-store'); // Initial values +var currentGrouping = 'none'; var currentTopology = 'applications'; -var currentTopologyMode = 'individual'; var nodeDetails = null; var selectedNodeId = null; var topologies = []; @@ -26,7 +26,7 @@ var AppStore = assign({}, EventEmitter.prototype, { getAppState: function() { return { currentTopology: this.getCurrentTopology(), - currentTopologyMode: this.getCurrentTopologyMode(), + currentGrouping: this.getCurrentGrouping(), selectedNodeId: this.getSelectedNodeId() }; }, @@ -35,8 +35,8 @@ var AppStore = assign({}, EventEmitter.prototype, { return currentTopology; }, - getCurrentTopologyMode: function() { - return currentTopologyMode; + getCurrentGrouping: function() { + return currentGrouping; }, getNodeDetails: function() { @@ -61,7 +61,7 @@ var AppStore = assign({}, EventEmitter.prototype, { }, this); if (topology) { - return topology.grouped_url && currentTopologyMode == 'class' ? topology.grouped_url : topology.url; + return topology.grouped_url && currentGrouping == 'grouped' ? topology.grouped_url : topology.url; } }, @@ -81,6 +81,12 @@ AppStore.dispatchToken = AppDispatcher.register(function(payload) { AppStore.emit(AppStore.CHANGE_EVENT); break; + case ActionTypes.CLICK_GROUPING: + currentGrouping = payload.grouping; + AppDispatcher.waitFor([TopologyStore.dispatchToken]); + AppStore.emit(AppStore.CHANGE_EVENT); + break; + case ActionTypes.CLICK_NODE: selectedNodeId = payload.nodeId; AppStore.emit(AppStore.CHANGE_EVENT); @@ -92,12 +98,6 @@ AppStore.dispatchToken = AppDispatcher.register(function(payload) { AppStore.emit(AppStore.CHANGE_EVENT); break; - case ActionTypes.CLICK_TOPOLOGY_MODE: - currentTopologyMode = payload.mode; - AppDispatcher.waitFor([TopologyStore.dispatchToken]); - AppStore.emit(AppStore.CHANGE_EVENT); - break; - case ActionTypes.HIT_ESC_KEY: nodeDetails = null; selectedNodeId = null; @@ -116,7 +116,7 @@ AppStore.dispatchToken = AppDispatcher.register(function(payload) { case ActionTypes.ROUTE_TOPOLOGY: currentTopology = payload.state.currentTopology; - currentTopologyMode = payload.state.currentTopologyMode; + currentGrouping = payload.state.currentGrouping; selectedNodeId = payload.state.selectedNodeId; AppDispatcher.waitFor([TopologyStore.dispatchToken]); AppStore.emit(AppStore.CHANGE_EVENT); diff --git a/client/app/scripts/stores/topology-store.js b/client/app/scripts/stores/topology-store.js index 5443f92c4b..e3422d986f 100644 --- a/client/app/scripts/stores/topology-store.js +++ b/client/app/scripts/stores/topology-store.js @@ -29,12 +29,12 @@ var TopologyStore = assign({}, EventEmitter.prototype, { TopologyStore.dispatchToken = AppDispatcher.register(function(payload) { switch (payload.type) { - case ActionTypes.CLICK_TOPOLOGY: + case ActionTypes.CLICK_GROUPING: nodes = {}; TopologyStore.emit(TopologyStore.CHANGE_EVENT); break; - case ActionTypes.CLICK_TOPOLOGY_MODE: + case ActionTypes.CLICK_TOPOLOGY: nodes = {}; TopologyStore.emit(TopologyStore.CHANGE_EVENT); break; diff --git a/client/app/styles/main.less b/client/app/styles/main.less index 37954a0cab..b1bf753532 100644 --- a/client/app/styles/main.less +++ b/client/app/styles/main.less @@ -22,7 +22,7 @@ @background-secondary-color: lighten(@background-color, 8%); @text-color: lighten(@primary-color, 10%); @text-secondary-color: lighten(@primary-color, 33%); -@text-pale-color: lighten(@primary-color, 50%); +@text-tertiary-color: lighten(@primary-color, 50%); @text-darker-color: @primary-color; @white: @background-secondary-color; @@ -46,14 +46,13 @@ body { .header { position: absolute; top: 32px; - // border-bottom: 1px solid @text-pale-color; width: 100%; height: 80px; z-index: 20; } .logo { - margin: 0 64px 0 64px; + margin: -8px 64px 0 64px; height: 64px; width: 250px; float: left; @@ -63,7 +62,7 @@ body { float: left; position: relative; margin-top: 7px; - margin-left: 64px; + margin-left: 128px; &-icon { font-size: 12px; @@ -74,29 +73,10 @@ body { } .topologies-item { - margin-top: 16px; - margin-bottom: 16px; - margin-left: 16px; - margin-right: 16px; + margin: 8px 16px 6px 0; cursor: pointer; display: inline-block; - &-frame { - display: inline-block; - width: 64px; - height: 64px; - padding-top: 4px; - } - - &-nodes, - &-edges, - &-divider { - display: block; - line-height: 28px; - font-size: 24px; - color: @text-secondary-color; - } - &-label { color: @text-secondary-color; font-size: 16px; @@ -106,13 +86,29 @@ body { &-active, &:hover { .topologies-item-label { color: @text-color; - //border-bottom: 2px solid @primary-color; } } } - } +.groupings { + float: left; + position: relative; + margin-top: 7px; + margin-left: 128px; + + &-item { + font-size: 16px; + margin: 8px 12px 6px 0; + cursor: pointer; + display: inline-block; + color: @text-tertiary-color; + + &-active, &:hover { + color: @text-color; + } + } +} #stats {