+
+
+
+ {topology.sub_topologies && topology.sub_topologies.map(this.renderSubTopology)}
+
);
},
render: function() {
const topologies = _.sortBy(this.props.topologies, function(topology) {
- return topology.name;
- });
+ return topology.name;
+ });
return (
diff --git a/client/app/scripts/stores/__tests__/app-store-test.js b/client/app/scripts/stores/__tests__/app-store-test.js
index bcca13750..7ca3c6668 100644
--- a/client/app/scripts/stores/__tests__/app-store-test.js
+++ b/client/app/scripts/stores/__tests__/app-store-test.js
@@ -16,6 +16,11 @@ describe('AppStore', function() {
nodeId: 'n1'
};
+ const ClickSubTopologyAction = {
+ type: ActionTypes.CLICK_TOPOLOGY,
+ topologyId: 'topo1-grouped'
+ };
+
const ClickTopologyAction = {
type: ActionTypes.CLICK_TOPOLOGY,
topologyId: 'topo1'
@@ -45,8 +50,11 @@ describe('AppStore', function() {
type: ActionTypes.RECEIVE_TOPOLOGIES,
topologies: [{
url: '/topo1',
- grouped_url: '/topo1grouped',
- name: 'Topo1'
+ name: 'Topo1',
+ sub_topologies: [{
+ url: '/topo1-grouped',
+ name: 'topo 1 grouped'
+ }]
}]
};
@@ -77,14 +85,13 @@ describe('AppStore', function() {
expect(AppStore.getCurrentTopologyUrl()).toBe('/topo1');
});
- it('get grouped topology', function() {
- registeredCallback(ClickTopologyAction);
+ it('get sub-topology', function() {
registeredCallback(ReceiveTopologiesAction);
- registeredCallback(ClickGroupingAction);
+ registeredCallback(ClickSubTopologyAction);
expect(AppStore.getTopologies().length).toBe(1);
- expect(AppStore.getCurrentTopology().name).toBe('Topo1');
- expect(AppStore.getCurrentTopologyUrl()).toBe('/topo1grouped');
+ expect(AppStore.getCurrentTopology().name).toBe('topo 1 grouped');
+ expect(AppStore.getCurrentTopologyUrl()).toBe('/topo1-grouped');
});
// browsing
@@ -110,14 +117,14 @@ describe('AppStore', function() {
registeredCallback(ReceiveNodesDeltaAction);
// TODO clear AppStore cache
expect(AppStore.getAppState())
- .toEqual({"topologyId":"topo1","grouping":"grouped","selectedNodeId": null});
+ .toEqual({"topologyId":"topo1-grouped","grouping":"none","selectedNodeId": null});
registeredCallback(ClickNodeAction);
expect(AppStore.getAppState())
- .toEqual({"topologyId":"topo1","grouping":"grouped","selectedNodeId": 'n1'});
+ .toEqual({"topologyId":"topo1-grouped","grouping":"none","selectedNodeId": 'n1'});
// go back in browsing
- RouteAction.state = {"topologyId":"topo1","grouping":"grouped","selectedNodeId": null};
+ RouteAction.state = {"topologyId":"topo1-grouped","grouping":"none","selectedNodeId": null};
registeredCallback(RouteAction);
expect(AppStore.getSelectedNodeId()).toBe(null);
expect(AppStore.getNodes()).toEqual(NODE_SET);
diff --git a/client/app/scripts/stores/app-store.js b/client/app/scripts/stores/app-store.js
index 4670b823d..8db061b74 100644
--- a/client/app/scripts/stores/app-store.js
+++ b/client/app/scripts/stores/app-store.js
@@ -9,8 +9,22 @@ const Naming = require('../constants/naming');
// Helpers
-function isUrlForTopologyId(url, topologyId) {
- return _.endsWith(url, topologyId);
+function findCurrentTopology(subTree, topologyId) {
+ let foundTopology;
+
+ _.each(subTree, function(topology) {
+ if (_.endsWith(topology.url, topologyId)) {
+ foundTopology = topology;
+ }
+ if (!foundTopology) {
+ foundTopology = findCurrentTopology(topology.sub_topologies, topologyId);
+ }
+ if (foundTopology) {
+ return false;
+ }
+ });
+
+ return foundTopology;
}
// Initial values
@@ -45,16 +59,14 @@ const AppStore = assign({}, EventEmitter.prototype, {
},
getCurrentTopology: function() {
- return _.find(topologies, function(topology) {
- return isUrlForTopologyId(topology.url, currentTopologyId);
- });
+ return findCurrentTopology(topologies, currentTopologyId);
},
getCurrentTopologyUrl: function() {
const topology = this.getCurrentTopology();
if (topology) {
- return topology.grouped_url && currentGrouping === 'grouped' ? topology.grouped_url : topology.url;
+ return topology.url;
}
},
diff --git a/client/app/scripts/utils/web-api-utils.js b/client/app/scripts/utils/web-api-utils.js
index dce7160c3..b5d37e851 100644
--- a/client/app/scripts/utils/web-api-utils.js
+++ b/client/app/scripts/utils/web-api-utils.js
@@ -39,10 +39,50 @@ function createWebsocket(topologyUrl) {
currentUrl = topologyUrl;
}
+
+const TOPOLOGIES = [
+ {
+ 'name': 'Applications',
+ 'url': '/api/topology/applications',
+ 'stats': {
+ 'node_count': 12,
+ 'nonpseudo_node_count': 10,
+ 'edge_count': 13
+ },
+ 'sub_topologies': [
+ {
+ 'name': 'by name',
+ 'url': '/api/topology/applications-grouped'
+ }
+ ]
+ },
+ {
+ 'name': 'Containers',
+ 'url': '/api/topology/containers',
+ 'grouped_url': '/api/topology/containers-grouped',
+ 'stats': {
+ 'node_count': 2,
+ 'nonpseudo_node_count': 1,
+ 'edge_count': 2
+ }
+ },
+ {
+ 'name': 'Hosts',
+ 'url': '/api/topology/hosts',
+ 'stats': {
+ 'node_count': 2,
+ 'nonpseudo_node_count': 1,
+ 'edge_count': 2
+ }
+ }
+];
+
+
function getTopologies() {
clearTimeout(topologyTimer);
- reqwest('/api/topology', function(res) {
- AppActions.receiveTopologies(res);
+ reqwest('/api/topology', function() {
+ // injecting static topos
+ AppActions.receiveTopologies(TOPOLOGIES);
topologyTimer = setTimeout(getTopologies, 10000);
});
}
diff --git a/client/app/styles/main.less b/client/app/styles/main.less
index b4df69bf9..fb3f342cd 100644
--- a/client/app/styles/main.less
+++ b/client/app/styles/main.less
@@ -81,59 +81,47 @@ body {
float: left;
}
-.topologies,
-.groupings {
- float: left;
- margin-top: 7px;
- margin-left: 48px;
-}
-
.topologies {
- &-icon {
- font-size: 12px;
- color: @text-secondary-color;
- margin-right: 16px;
- position: relative;
- top: -1px;
- }
+ float: left;
+ margin: 4px 64px;
.topologies-item {
- margin: 8px 16px 6px 0;
- cursor: pointer;
- display: inline-block;
+ margin: 0px 16px;
+ float: left;
&-label {
color: @text-secondary-color;
- font-size: 15px;
+ font-size: 16px;
text-transform: uppercase;
}
+ }
+
+ .topologies-sub {
+ margin-top: 4px;
+
+ &-item {
+ &-label {
+ color: @text-secondary-color;
+ font-size: 12px;
+ text-transform: uppercase;
+ }
+ }
+ }
+
+ .topologies-item-main,
+ .topologies-sub-item {
+ cursor: pointer;
+
&-active, &:hover {
+ .topologies-sub-item-label,
.topologies-item-label {
color: @text-color;
}
}
+
}
-}
-.groupings {
- &-item {
- font-size: 15px;
- margin: 8px 12px 6px 0;
- cursor: pointer;
- display: inline-block;
- color: @text-tertiary-color;
-
- &-disabled {
- color: @text-tertiary-color;
- cursor: default;
- }
-
- &-default:hover,
- &-active {
- color: @text-color;
- }
- }
}
.status {