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 {