mirror of
https://github.com/portainer/portainer.git
synced 2025-07-22 23:09:41 +02:00
Add actions to show upstream and downstream dependencies of a container for easy visualization.
Additionally updated angular-vis to use version 0.0.4 which already includes the changes of https://github.com/visjs/angular-visjs/pull/22.
This commit is contained in:
parent
9e713b7b81
commit
edd6a41d6e
4 changed files with 102 additions and 30 deletions
|
@ -41,7 +41,7 @@ DockerUI listens on port 9000 by default. If you run DockerUI inside a container
|
||||||
* [Gritter](https://github.com/jboesch/Gritter)
|
* [Gritter](https://github.com/jboesch/Gritter)
|
||||||
* [Spin.js](https://github.com/fgnass/spin.js/)
|
* [Spin.js](https://github.com/fgnass/spin.js/)
|
||||||
* [Golang](https://golang.org/)
|
* [Golang](https://golang.org/)
|
||||||
* [Vis.js](http://visjs.org/) - We are using a [patched version](https://github.com/visjs/angular-visjs/pull/22)
|
* [Vis.js](http://visjs.org/)
|
||||||
|
|
||||||
|
|
||||||
### Todo:
|
### Todo:
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
<button class="btn btn-warning" ng-click="network.hideSelected()">Hide Selected</button>
|
<button class="btn btn-warning" ng-click="network.hideSelected()">Hide Selected</button>
|
||||||
|
<button class="btn btn-info" ng-click="network.showSelectedDownstream()">Show Selected Downstream</button>
|
||||||
|
<button class="btn btn-info" ng-click="network.showSelectedUpstream()">Show Selected Upstream</button>
|
||||||
<button class="btn btn-success" ng-click="network.showAll()">Show All</button>
|
<button class="btn btn-success" ng-click="network.showAll()">Show All</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,7 +8,7 @@ angular.module('containersNetwork', ['ngVis'])
|
||||||
this.Image = data.Config.Image;
|
this.Image = data.Config.Image;
|
||||||
var dataLinks = data.HostConfig.Links;
|
var dataLinks = data.HostConfig.Links;
|
||||||
if (dataLinks != null) {
|
if (dataLinks != null) {
|
||||||
this.Links = [];
|
this.Links = {};
|
||||||
for (var i = 0; i < dataLinks.length; i++) {
|
for (var i = 0; i < dataLinks.length; i++) {
|
||||||
// links have the following format: /TargetContainerName:/SourceContainerName/LinkAlias
|
// links have the following format: /TargetContainerName:/SourceContainerName/LinkAlias
|
||||||
var link = dataLinks[i].split(":");
|
var link = dataLinks[i].split(":");
|
||||||
|
@ -23,7 +23,7 @@ angular.module('containersNetwork', ['ngVis'])
|
||||||
var dataVolumes = data.HostConfig.VolumesFrom;
|
var dataVolumes = data.HostConfig.VolumesFrom;
|
||||||
//converting array into properties for simpler and faster access
|
//converting array into properties for simpler and faster access
|
||||||
if (dataVolumes != null) {
|
if (dataVolumes != null) {
|
||||||
this.VolumesFrom = [];
|
this.VolumesFrom = {};
|
||||||
for (var j = 0; j < dataVolumes.length; j++) {
|
for (var j = 0; j < dataVolumes.length; j++) {
|
||||||
this.VolumesFrom[dataVolumes[j]] = true;
|
this.VolumesFrom[dataVolumes[j]] = true;
|
||||||
}
|
}
|
||||||
|
@ -69,12 +69,12 @@ angular.module('containersNetwork', ['ngVis'])
|
||||||
|
|
||||||
function ContainersNetwork() {
|
function ContainersNetwork() {
|
||||||
this.data = new ContainersNetworkData();
|
this.data = new ContainersNetworkData();
|
||||||
this.containers = [];
|
this.containers = {};
|
||||||
this.selectedContainers = [];
|
this.selectedContainersIds = [];
|
||||||
this.shownContainers = [];
|
this.shownContainersIds = [];
|
||||||
this.events = {
|
this.events = {
|
||||||
select : function(event) {
|
select : function(event) {
|
||||||
$scope.network.selectedContainers = event.nodes;
|
$scope.network.selectedContainersIds = event.nodes;
|
||||||
$scope.$apply( function() {
|
$scope.$apply( function() {
|
||||||
$scope.query = '';
|
$scope.query = '';
|
||||||
});
|
});
|
||||||
|
@ -104,11 +104,11 @@ angular.module('containersNetwork', ['ngVis'])
|
||||||
|
|
||||||
this.addContainer = function(data) {
|
this.addContainer = function(data) {
|
||||||
var container = new ContainerNode(data);
|
var container = new ContainerNode(data);
|
||||||
this.containers.push(container);
|
this.containers[container.Id] = container;
|
||||||
this.shownContainers.push(container);
|
this.shownContainersIds.push(container.Id);
|
||||||
this.data.addContainerNode(container);
|
this.data.addContainerNode(container);
|
||||||
for (var i = 0; i < this.containers.length; i++) {
|
for (var otherContainerId in this.containers) {
|
||||||
var otherContainer = this.containers[i];
|
var otherContainer = this.containers[otherContainerId];
|
||||||
this.data.addLinkEdgeIfExists(container, otherContainer);
|
this.data.addLinkEdgeIfExists(container, otherContainer);
|
||||||
this.data.addLinkEdgeIfExists(otherContainer, container);
|
this.data.addLinkEdgeIfExists(otherContainer, container);
|
||||||
this.data.addVolumeEdgeIfExists(container, otherContainer);
|
this.data.addVolumeEdgeIfExists(container, otherContainer);
|
||||||
|
@ -118,8 +118,8 @@ angular.module('containersNetwork', ['ngVis'])
|
||||||
|
|
||||||
this.selectContainers = function(query) {
|
this.selectContainers = function(query) {
|
||||||
if (this.component != null) {
|
if (this.component != null) {
|
||||||
this.selectedContainers = this.searchContainers(query);
|
this.selectedContainersIds = this.searchContainers(query);
|
||||||
this.component.selectNodes(this.selectedContainers);
|
this.component.selectNodes(this.selectedContainersIds);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -127,38 +127,103 @@ angular.module('containersNetwork', ['ngVis'])
|
||||||
if (query.trim() === "") {
|
if (query.trim() === "") {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
var selectedContainers = [];
|
var selectedContainersIds = [];
|
||||||
for (var i=0; i < this.shownContainers.length; i++) {
|
for (var i=0; i < this.shownContainersIds.length; i++) {
|
||||||
var container = this.shownContainers[i];
|
var container = this.containers[this.shownContainersIds[i]];
|
||||||
if (container.Name.indexOf(query) > -1 ||
|
if (container.Name.indexOf(query) > -1 ||
|
||||||
container.Image.indexOf(query) > -1 ||
|
container.Image.indexOf(query) > -1 ||
|
||||||
container.Id.indexOf(query) > -1) {
|
container.Id.indexOf(query) > -1) {
|
||||||
selectedContainers.push(container.Id);
|
selectedContainersIds.push(container.Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return selectedContainers;
|
return selectedContainersIds;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.hideSelected = function() {
|
this.hideSelected = function() {
|
||||||
var i=0;
|
var i=0;
|
||||||
while ( i < this.shownContainers.length ) {
|
while ( i < this.shownContainersIds.length ) {
|
||||||
if (this.selectedContainers.indexOf(this.shownContainers[i].Id) > -1) {
|
if (this.selectedContainersIds.indexOf(this.shownContainersIds[i]) > -1) {
|
||||||
this.shownContainers.splice(i, 1);
|
this.shownContainersIds.splice(i, 1);
|
||||||
} else {
|
} else {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.data.removeContainersNodes(this.selectedContainers);
|
this.data.removeContainersNodes(this.selectedContainersIds);
|
||||||
$scope.query = '';
|
$scope.query = '';
|
||||||
this.selectedContainers = [];
|
this.selectedContainersIds = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
this.searchDownstream = function(containerId, downstreamContainersIds) {
|
||||||
|
if (downstreamContainersIds.indexOf(containerId) > -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
downstreamContainersIds.push(containerId);
|
||||||
|
var container = this.containers[containerId];
|
||||||
|
if (container.Links == null && container.VolumesFrom == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (var otherContainerId in this.containers) {
|
||||||
|
var otherContainer = this.containers[otherContainerId];
|
||||||
|
if (container.Links != null && container.Links[otherContainer.Name] != null) {
|
||||||
|
this.searchDownstream(otherContainer.Id, downstreamContainersIds);
|
||||||
|
} else if (container.VolumesFrom != null &&
|
||||||
|
container.VolumesFrom[otherContainer.Id] != null) {
|
||||||
|
this.searchDownstream(otherContainer.Id, downstreamContainersIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.updateShownContainers = function(newShownContainersIds) {
|
||||||
|
for (var containerId in this.containers) {
|
||||||
|
if (newShownContainersIds.indexOf(containerId) > -1 &&
|
||||||
|
this.shownContainersIds.indexOf(containerId) === -1) {
|
||||||
|
this.data.addContainerNode(this.containers[containerId]);
|
||||||
|
} else if (newShownContainersIds.indexOf(containerId) === -1 &&
|
||||||
|
this.shownContainersIds.indexOf(containerId) > -1) {
|
||||||
|
this.data.removeContainersNodes(containerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.shownContainersIds = newShownContainersIds;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.showSelectedDownstream = function() {
|
||||||
|
var downstreamContainersIds = [];
|
||||||
|
for (var i=0; i < this.selectedContainersIds.length; i++) {
|
||||||
|
this.searchDownstream(this.selectedContainersIds[i], downstreamContainersIds);
|
||||||
|
}
|
||||||
|
this.updateShownContainers(downstreamContainersIds);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.searchUpstream = function(containerId, upstreamContainersIds) {
|
||||||
|
if (upstreamContainersIds.indexOf(containerId) > -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
upstreamContainersIds.push(containerId);
|
||||||
|
var container = this.containers[containerId];
|
||||||
|
for (var otherContainerId in this.containers) {
|
||||||
|
var otherContainer = this.containers[otherContainerId];
|
||||||
|
if (otherContainer.Links != null && otherContainer.Links[container.Name] != null) {
|
||||||
|
this.searchUpstream(otherContainer.Id, upstreamContainersIds);
|
||||||
|
} else if (otherContainer.VolumesFrom != null &&
|
||||||
|
otherContainer.VolumesFrom[container.Id] != null) {
|
||||||
|
this.searchUpstream(otherContainer.Id, upstreamContainersIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.showSelectedUpstream = function() {
|
||||||
|
var upstreamContainersIds = [];
|
||||||
|
for (var i=0; i < this.selectedContainersIds.length; i++) {
|
||||||
|
this.searchUpstream(this.selectedContainersIds[i], upstreamContainersIds);
|
||||||
|
}
|
||||||
|
this.updateShownContainers(upstreamContainersIds);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.showAll = function() {
|
this.showAll = function() {
|
||||||
for (var i=0; i < this.containers.length; i++) {
|
for (var containerId in this.containers) {
|
||||||
var container = this.containers[i];
|
if (this.shownContainersIds.indexOf(containerId) === -1) {
|
||||||
if (this.shownContainers.indexOf(container) === -1) {
|
this.data.addContainerNode(this.containers[containerId]);
|
||||||
this.data.addContainerNode(container);
|
this.shownContainersIds.push(containerId);
|
||||||
this.shownContainers.push(container);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
9
assets/js/angular-vis.js
vendored
9
assets/js/angular-vis.js
vendored
|
@ -19,7 +19,8 @@ angular.module('ngVis', [])
|
||||||
scope: {
|
scope: {
|
||||||
data: '=',
|
data: '=',
|
||||||
options: '=',
|
options: '=',
|
||||||
events: '='
|
events: '=',
|
||||||
|
component: '='
|
||||||
},
|
},
|
||||||
link: function (scope, element, attr) {
|
link: function (scope, element, attr) {
|
||||||
var timelineEvents = [
|
var timelineEvents = [
|
||||||
|
@ -46,6 +47,7 @@ angular.module('ngVis', [])
|
||||||
|
|
||||||
// Create the timeline object
|
// Create the timeline object
|
||||||
timeline = new vis.Timeline(element[0]);
|
timeline = new vis.Timeline(element[0]);
|
||||||
|
scope.component = timeline;
|
||||||
|
|
||||||
// Attach an event handler if defined
|
// Attach an event handler if defined
|
||||||
angular.forEach(scope.events, function (callback, event) {
|
angular.forEach(scope.events, function (callback, event) {
|
||||||
|
@ -169,7 +171,8 @@ angular.module('ngVis', [])
|
||||||
scope: {
|
scope: {
|
||||||
data: '=',
|
data: '=',
|
||||||
options: '=',
|
options: '=',
|
||||||
events: '='
|
events: '=',
|
||||||
|
component: '='
|
||||||
},
|
},
|
||||||
link: function (scope, element, attr) {
|
link: function (scope, element, attr) {
|
||||||
var graphEvents = [
|
var graphEvents = [
|
||||||
|
@ -181,6 +184,7 @@ angular.module('ngVis', [])
|
||||||
|
|
||||||
// Create the chart
|
// Create the chart
|
||||||
var graph = new vis.Graph2d(element[0]);
|
var graph = new vis.Graph2d(element[0]);
|
||||||
|
scope.component = graph;
|
||||||
|
|
||||||
scope.$watch('data', function () {
|
scope.$watch('data', function () {
|
||||||
// Sanity check
|
// Sanity check
|
||||||
|
@ -196,6 +200,7 @@ angular.module('ngVis', [])
|
||||||
|
|
||||||
// Create the graph2d object
|
// Create the graph2d object
|
||||||
graph = new vis.Graph2d(element[0]);
|
graph = new vis.Graph2d(element[0]);
|
||||||
|
scope.component = graph;
|
||||||
|
|
||||||
// Attach an event handler if defined
|
// Attach an event handler if defined
|
||||||
angular.forEach(scope.events, function (callback, event) {
|
angular.forEach(scope.events, function (callback, event) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue