diff --git a/README.md b/README.md
index 7b1b693a3..178451b16 100644
--- a/README.md
+++ b/README.md
@@ -41,7 +41,7 @@ DockerUI listens on port 9000 by default. If you run DockerUI inside a container
* [Gritter](https://github.com/jboesch/Gritter)
* [Spin.js](https://github.com/fgnass/spin.js/)
* [Golang](https://golang.org/)
-* [Vis.js](http://visjs.org/)
+* [Vis.js](http://visjs.org/) - We are using a [patched version](https://github.com/visjs/angular-visjs/pull/22)
### Todo:
diff --git a/app/components/containersNetwork/containersNetwork.html b/app/components/containersNetwork/containersNetwork.html
index 67fe230bf..fe2eea40f 100644
--- a/app/components/containersNetwork/containersNetwork.html
+++ b/app/components/containersNetwork/containersNetwork.html
@@ -1,7 +1,21 @@
Containers Network
-
-
+
+
+
+ Hide Selected
+ Show All
+
+
+
+
diff --git a/app/components/containersNetwork/containersNetworkController.js b/app/components/containersNetwork/containersNetworkController.js
index b015488f9..d2537dc7b 100644
--- a/app/components/containersNetwork/containersNetworkController.js
+++ b/app/components/containersNetwork/containersNetworkController.js
@@ -1,26 +1,11 @@
angular.module('containersNetwork', ['ngVis'])
.controller('ContainersNetworkController', ['$scope', '$location', 'Container', 'Messages', 'VisDataSet', function($scope, $location, Container, Messages, VisDataSet) {
- $scope.options = {
- navigation: true,
- keyboard: true,
- height: '500px', width: '700px',
- nodes: {
- shape: 'box'
- },
- edges: {
- style: 'arrow'
- },
- physics: {
- barnesHut : {
- springLength: 200
- }
- }
- };
function ContainerNode(data) {
this.Id = data.Id;
// names have the following format: /Name
this.Name = data.Name.substring(1);
+ this.Image = data.Config.Image;
var dataLinks = data.HostConfig.Links;
if (dataLinks != null) {
this.Links = [];
@@ -45,57 +30,155 @@ angular.module('containersNetwork', ['ngVis'])
}
}
- function ContainersNetwork() {
- this.containers = [];
+ function ContainersNetworkData() {
this.nodes = new VisDataSet();
this.edges = new VisDataSet();
- this.add = function(data) {
- var container = new ContainerNode(data);
- this.containers.push(container);
- this.nodes.add({id: container.Id, label: container.Name});
- for (var i = 0; i < this.containers.length; i++) {
- var otherContainer = this.containers[i];
- this.addLinkEdgeIfExists(container, otherContainer);
- this.addLinkEdgeIfExists(otherContainer, container);
- this.addVolumeEdgeIfExists(container, otherContainer);
- this.addVolumeEdgeIfExists(otherContainer, container);
- }
+ this.addContainerNode = function(container) {
+ this.nodes.add({
+ id: container.Id,
+ label: container.Name,
+ title: "
" +
+ "ID: " + container.Id + " " +
+ "Image: " + container.Image + " " +
+ " "});
};
this.addLinkEdgeIfExists = function(from, to) {
if (from.Links != null && from.Links[to.Name] != null) {
- this.edges.add({ from: from.Id, to: to.Id, label: from.Links[to.Name] });
+ this.edges.add({
+ from: from.Id,
+ to: to.Id,
+ label: from.Links[to.Name] });
}
};
this.addVolumeEdgeIfExists = function(from, to) {
if (from.VolumesFrom != null && from.VolumesFrom[to.Id] != null) {
- this.edges.add({ from: from.Id, to: to.Id, color: { color: '#A0A0A0', highlight: '#A0A0A0', hover: '#848484'}});
+ this.edges.add({
+ from: from.Id,
+ to: to.Id,
+ color: { color: '#A0A0A0', highlight: '#A0A0A0', hover: '#848484'}});
}
};
+
+ this.removeContainersNodes = function(containersIds) {
+ this.nodes.remove(containersIds);
+ };
}
- $scope.data = new ContainersNetwork();
- $scope.events = {
- doubleClick : function(event) {
- $scope.$apply( function() {
- $location.path('/containers/' + event.nodes[0]);
- });
- }
- };
+ function ContainersNetwork() {
+ this.data = new ContainersNetworkData();
+ this.containers = [];
+ this.selectedContainers = [];
+ this.shownContainers = [];
+ this.events = {
+ select : function(event) {
+ $scope.network.selectedContainers = event.nodes;
+ $scope.$apply( function() {
+ $scope.query = '';
+ });
+ },
+ doubleClick : function(event) {
+ $scope.$apply( function() {
+ $location.path('/containers/' + event.nodes[0]);
+ });
+ }
+ };
+ this.options = {
+ navigation: true,
+ keyboard: true,
+ height: '500px', width: '700px',
+ nodes: {
+ shape: 'box'
+ },
+ edges: {
+ style: 'arrow'
+ },
+ physics: {
+ barnesHut : {
+ springLength: 200
+ }
+ }
+ };
+
+ this.addContainer = function(data) {
+ var container = new ContainerNode(data);
+ this.containers.push(container);
+ this.shownContainers.push(container);
+ this.data.addContainerNode(container);
+ for (var i = 0; i < this.containers.length; i++) {
+ var otherContainer = this.containers[i];
+ this.data.addLinkEdgeIfExists(container, otherContainer);
+ this.data.addLinkEdgeIfExists(otherContainer, container);
+ this.data.addVolumeEdgeIfExists(container, otherContainer);
+ this.data.addVolumeEdgeIfExists(otherContainer, container);
+ }
+ };
+
+ this.selectContainers = function(query) {
+ if (this.component != null) {
+ this.selectedContainers = this.searchContainers(query);
+ this.component.selectNodes(this.selectedContainers);
+ }
+ };
+
+ this.searchContainers = function(query) {
+ if (query.trim() === "") {
+ return [];
+ }
+ var selectedContainers = [];
+ for (var i=0; i < this.shownContainers.length; i++) {
+ var container = this.shownContainers[i];
+ if (container.Name.indexOf(query) > -1 ||
+ container.Image.indexOf(query) > -1 ||
+ container.Id.indexOf(query) > -1) {
+ selectedContainers.push(container.Id);
+ }
+ }
+ return selectedContainers;
+ };
+
+ this.hideSelected = function() {
+ var i=0;
+ while ( i < this.shownContainers.length ) {
+ if (this.selectedContainers.indexOf(this.shownContainers[i].Id) > -1) {
+ this.shownContainers.splice(i, 1);
+ } else {
+ i++;
+ }
+ }
+ this.data.removeContainersNodes(this.selectedContainers);
+ $scope.query = '';
+ this.selectedContainers = [];
+ };
+
+ this.showAll = function() {
+ for (var i=0; i < this.containers.length; i++) {
+ var container = this.containers[i];
+ if (this.shownContainers.indexOf(container) === -1) {
+ this.data.addContainerNode(container);
+ this.shownContainers.push(container);
+ }
+ }
+ };
+
+ }
+
+ $scope.network = new ContainersNetwork();
var showFailure = function (event) {
- Messages.error('Failure', e.data);
+ Messages.error('Failure', e.data);
};
var addContainer = function (container) {
- $scope.data.add(container);
+ $scope.network.addContainer(container);
};
Container.query({all: 0}, function(d) {
for (var i = 0; i < d.length; i++) {
Container.get({id: d[i].Id}, addContainer, showFailure);
}
- });
+ });
+
}]);
diff --git a/assets/font/glyphicons-halflings-regular.eot b/assets/fonts/glyphicons-halflings-regular.eot
similarity index 100%
rename from assets/font/glyphicons-halflings-regular.eot
rename to assets/fonts/glyphicons-halflings-regular.eot
diff --git a/assets/font/glyphicons-halflings-regular.svg b/assets/fonts/glyphicons-halflings-regular.svg
similarity index 100%
rename from assets/font/glyphicons-halflings-regular.svg
rename to assets/fonts/glyphicons-halflings-regular.svg
diff --git a/assets/font/glyphicons-halflings-regular.ttf b/assets/fonts/glyphicons-halflings-regular.ttf
similarity index 100%
rename from assets/font/glyphicons-halflings-regular.ttf
rename to assets/fonts/glyphicons-halflings-regular.ttf
diff --git a/assets/font/glyphicons-halflings-regular.woff b/assets/fonts/glyphicons-halflings-regular.woff
similarity index 100%
rename from assets/font/glyphicons-halflings-regular.woff
rename to assets/fonts/glyphicons-halflings-regular.woff
diff --git a/assets/js/angular-vis.js b/assets/js/angular-vis.js
index 71b967867..a0347fb5d 100755
--- a/assets/js/angular-vis.js
+++ b/assets/js/angular-vis.js
@@ -92,7 +92,8 @@ angular.module('ngVis', [])
scope: {
data: '=',
options: '=',
- events: '='
+ events: '=',
+ component: '='
},
link: function (scope, element, attr) {
var networkEvents = [
@@ -103,6 +104,7 @@ angular.module('ngVis', [])
];
var network = new vis.Network(element[0], scope.data, scope.options);
+ scope.component = network;
scope.$watch('data', function () {
// Sanity check
@@ -118,6 +120,7 @@ angular.module('ngVis', [])
// Create the graph2d object
network = new vis.Network(element[0]);
+ scope.component = network;
// Attach an event handler if defined
angular.forEach(scope.events, function (callback, event) {