mirror of https://github.com/portainer/portainer
parent
813c14d93c
commit
66ae15b4fb
|
@ -33,10 +33,17 @@
|
||||||
</rd-widget-taskbar>
|
</rd-widget-taskbar>
|
||||||
<rd-widget-body classes="no-padding">
|
<rd-widget-body classes="no-padding">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table">
|
<table class="table table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th><label><input type="checkbox" ng-model="state.toggle" ng-change="toggleSelectAll()" /> Select</label></th>
|
<th></th>
|
||||||
|
<th>
|
||||||
|
<a ui-sref="containers" ng-click="order('State')">
|
||||||
|
State
|
||||||
|
<span ng-show="sortType == 'State' && !sortReverse" class="glyphicon glyphicon-chevron-down"></span>
|
||||||
|
<span ng-show="sortType == 'State' && sortReverse" class="glyphicon glyphicon-chevron-up"></span>
|
||||||
|
</a>
|
||||||
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<a ui-sref="containers" ng-click="order('Names')">
|
<a ui-sref="containers" ng-click="order('Names')">
|
||||||
Name
|
Name
|
||||||
|
@ -44,6 +51,20 @@
|
||||||
<span ng-show="sortType == 'Names' && sortReverse" class="glyphicon glyphicon-chevron-up"></span>
|
<span ng-show="sortType == 'Names' && sortReverse" class="glyphicon glyphicon-chevron-up"></span>
|
||||||
</a>
|
</a>
|
||||||
</th>
|
</th>
|
||||||
|
<th>
|
||||||
|
<a ui-sref="containers" ng-click="order('IP')">
|
||||||
|
IP Address
|
||||||
|
<span ng-show="sortType == 'IP' && !sortReverse" class="glyphicon glyphicon-chevron-down"></span>
|
||||||
|
<span ng-show="sortType == 'IP' && sortReverse" class="glyphicon glyphicon-chevron-up"></span>
|
||||||
|
</a>
|
||||||
|
</th>
|
||||||
|
<th ng-if="swarm">
|
||||||
|
<a ui-sref="containers" ng-click="order('Host')">
|
||||||
|
Host
|
||||||
|
<span ng-show="sortType == 'Host' && !sortReverse" class="glyphicon glyphicon-chevron-down"></span>
|
||||||
|
<span ng-show="sortType == 'Host' && sortReverse" class="glyphicon glyphicon-chevron-up"></span>
|
||||||
|
</a>
|
||||||
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<a ui-sref="containers" ng-click="order('Image')">
|
<a ui-sref="containers" ng-click="order('Image')">
|
||||||
Image
|
Image
|
||||||
|
@ -58,30 +79,18 @@
|
||||||
<span ng-show="sortType == 'Command' && sortReverse" class="glyphicon glyphicon-chevron-up"></span>
|
<span ng-show="sortType == 'Command' && sortReverse" class="glyphicon glyphicon-chevron-up"></span>
|
||||||
</a>
|
</a>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
|
||||||
<a ui-sref="containers" ng-click="order('Created')">
|
|
||||||
Created
|
|
||||||
<span ng-show="sortType == 'Created' && !sortReverse" class="glyphicon glyphicon-chevron-down"></span>
|
|
||||||
<span ng-show="sortType == 'Created' && sortReverse" class="glyphicon glyphicon-chevron-up"></span>
|
|
||||||
</a>
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
<a ui-sref="containers" ng-click="order('Status')">
|
|
||||||
Status
|
|
||||||
<span ng-show="sortType == 'Status' && !sortReverse" class="glyphicon glyphicon-chevron-down"></span>
|
|
||||||
<span ng-show="sortType == 'Status' && sortReverse" class="glyphicon glyphicon-chevron-up"></span>
|
|
||||||
</a>
|
|
||||||
</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr ng-repeat="container in (state.filteredContainers = ( containers | filter:state.filter | orderBy:sortType:sortReverse))">
|
<tr ng-repeat="container in (state.filteredContainers = ( containers | filter:state.filter | orderBy:sortType:sortReverse))">
|
||||||
<td><input type="checkbox" ng-model="container.Checked" ng-change="selectItem(container)"/></td>
|
<td><input type="checkbox" ng-model="container.Checked" ng-change="selectItem(container)"/></td>
|
||||||
<td><a ui-sref="container({id: container.Id})">{{ container|containername}}</a></td>
|
<td><span class="label label-{{ container.State|containerstatusbadge }}">{{ container.State }}</span></td>
|
||||||
|
<td ng-if="swarm"><a ui-sref="container({id: container.Id})">{{ container|swarmcontainername}}</a></td>
|
||||||
|
<td ng-if="!swarm"><a ui-sref="container({id: container.Id})">{{ container|containername}}</a></td>
|
||||||
|
<td>{{ container.IP ? container.IP : '-' }}</td>
|
||||||
|
<td ng-if="swarm">{{ container|swarmhostname}}</td>
|
||||||
<td><a ui-sref="image({id: container.Image})">{{ container.Image }}</a></td>
|
<td><a ui-sref="image({id: container.Image})">{{ container.Image }}</a></td>
|
||||||
<td>{{ container.Command|truncate:40 }}</td>
|
<td>{{ container.Command|truncate:60 }}</td>
|
||||||
<td>{{ container.Created|getdate }}</td>
|
|
||||||
<td><span class="label label-{{ container.Status|statusbadge }}">{{ container.Status }}</span></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -4,9 +4,8 @@ function ($scope, Container, Settings, Messages, ViewSpinner, Config) {
|
||||||
|
|
||||||
$scope.state = {};
|
$scope.state = {};
|
||||||
$scope.state.displayAll = Settings.displayAll;
|
$scope.state.displayAll = Settings.displayAll;
|
||||||
$scope.sortType = 'Created';
|
$scope.sortType = 'State';
|
||||||
$scope.sortReverse = true;
|
$scope.sortReverse = true;
|
||||||
$scope.state.toggle = false;
|
|
||||||
$scope.state.selectedItemCount = 0;
|
$scope.state.selectedItemCount = 0;
|
||||||
|
|
||||||
$scope.order = function (sortType) {
|
$scope.order = function (sortType) {
|
||||||
|
@ -91,18 +90,6 @@ function ($scope, Container, Settings, Messages, ViewSpinner, Config) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.toggleSelectAll = function () {
|
|
||||||
$scope.state.selectedItem = $scope.state.toggle;
|
|
||||||
angular.forEach($scope.state.filteredContainers, function (i) {
|
|
||||||
i.Checked = $scope.state.toggle;
|
|
||||||
});
|
|
||||||
if ($scope.state.toggle) {
|
|
||||||
$scope.state.selectedItemCount = $scope.state.filteredContainers.length;
|
|
||||||
} else {
|
|
||||||
$scope.state.selectedItemCount = 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.toggleGetAll = function () {
|
$scope.toggleGetAll = function () {
|
||||||
Settings.displayAll = $scope.state.displayAll;
|
Settings.displayAll = $scope.state.displayAll;
|
||||||
update({all: Settings.displayAll ? 1 : 0});
|
update({all: Settings.displayAll ? 1 : 0});
|
||||||
|
@ -151,9 +138,10 @@ function ($scope, Container, Settings, Messages, ViewSpinner, Config) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var hiddenLabels;
|
$scope.swarm = false;
|
||||||
Config.$promise.then(function (c) {
|
Config.$promise.then(function (c) {
|
||||||
hiddenLabels = c.hiddenLabels;
|
hiddenLabels = c.hiddenLabels;
|
||||||
|
$scope.swarm = c.swarm;
|
||||||
update({all: Settings.displayAll ? 1 : 0});
|
update({all: Settings.displayAll ? 1 : 0});
|
||||||
});
|
});
|
||||||
}]);
|
}]);
|
||||||
|
|
|
@ -137,7 +137,7 @@
|
||||||
<td>{{ node.ip }}</td>
|
<td>{{ node.ip }}</td>
|
||||||
<td>{{ node.containers }}</td>
|
<td>{{ node.containers }}</td>
|
||||||
<td>{{ node.version }}</td>
|
<td>{{ node.version }}</td>
|
||||||
<td><span class="label label-{{ node.status|statusbadge }}">{{ node.status }}</span></td>
|
<td><span class="label label-{{ node.status|nodestatusbadge }}">{{ node.status }}</span></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -1,128 +1,149 @@
|
||||||
angular.module('dockerui.filters', [])
|
angular.module('dockerui.filters', [])
|
||||||
.filter('truncate', function () {
|
.filter('truncate', function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
return function (text, length, end) {
|
return function (text, length, end) {
|
||||||
if (isNaN(length)) {
|
if (isNaN(length)) {
|
||||||
length = 10;
|
length = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (end === undefined) {
|
if (end === undefined) {
|
||||||
end = '...';
|
end = '...';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (text.length <= length || text.length - end.length <= length) {
|
if (text.length <= length || text.length - end.length <= length) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return String(text).substring(0, length - end.length) + end;
|
return String(text).substring(0, length - end.length) + end;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter('statusbadge', function () {
|
.filter('containerstatusbadge', function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
return function (text) {
|
return function (text) {
|
||||||
if (text === 'Ghost') {
|
if (text === 'paused') {
|
||||||
return 'important';
|
return 'warning';
|
||||||
} else if (text === 'Unhealthy') {
|
} else if (text === 'created') {
|
||||||
return 'danger';
|
return 'info';
|
||||||
} else if (text.indexOf('Exit') !== -1 && text !== 'Exit 0') {
|
} else if (text === 'exited') {
|
||||||
return 'warning';
|
return 'danger';
|
||||||
}
|
}
|
||||||
return 'success';
|
return 'success';
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter('trimcontainername', function () {
|
.filter('nodestatusbadge', function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
return function (name) {
|
return function (text) {
|
||||||
if (name) {
|
if (text === 'Unhealthy') {
|
||||||
return (name.indexOf('/') === 0 ? name.replace('/','') : name);
|
return 'danger';
|
||||||
}
|
}
|
||||||
return '';
|
return 'success';
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter('getstatetext', function () {
|
.filter('trimcontainername', function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
return function (state) {
|
return function (name) {
|
||||||
if (state === undefined) {
|
if (name) {
|
||||||
return '';
|
return (name.indexOf('/') === 0 ? name.replace('/','') : name);
|
||||||
}
|
}
|
||||||
if (state.Ghost && state.Running) {
|
return '';
|
||||||
return 'Ghost';
|
};
|
||||||
}
|
})
|
||||||
if (state.Running && state.Paused) {
|
.filter('getstatetext', function () {
|
||||||
return 'Running (Paused)';
|
'use strict';
|
||||||
}
|
return function (state) {
|
||||||
if (state.Running) {
|
if (state === undefined) {
|
||||||
return 'Running';
|
return '';
|
||||||
}
|
}
|
||||||
return 'Stopped';
|
if (state.Ghost && state.Running) {
|
||||||
};
|
return 'Ghost';
|
||||||
})
|
}
|
||||||
.filter('getstatelabel', function () {
|
if (state.Running && state.Paused) {
|
||||||
'use strict';
|
return 'Running (Paused)';
|
||||||
return function (state) {
|
}
|
||||||
if (state === undefined) {
|
if (state.Running) {
|
||||||
return 'label-default';
|
return 'Running';
|
||||||
}
|
}
|
||||||
|
return 'Stopped';
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.filter('getstatelabel', function () {
|
||||||
|
'use strict';
|
||||||
|
return function (state) {
|
||||||
|
if (state === undefined) {
|
||||||
|
return 'label-default';
|
||||||
|
}
|
||||||
|
|
||||||
if (state.Ghost && state.Running) {
|
if (state.Ghost && state.Running) {
|
||||||
return 'label-important';
|
return 'label-important';
|
||||||
}
|
}
|
||||||
if (state.Running) {
|
if (state.Running) {
|
||||||
return 'label-success';
|
return 'label-success';
|
||||||
}
|
}
|
||||||
return 'label-default';
|
return 'label-default';
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter('humansize', function () {
|
.filter('humansize', function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
return function (bytes) {
|
return function (bytes) {
|
||||||
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
||||||
if (bytes === 0) {
|
if (bytes === 0) {
|
||||||
return 'n/a';
|
return 'n/a';
|
||||||
}
|
}
|
||||||
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)), 10);
|
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)), 10);
|
||||||
var value = bytes / Math.pow(1024, i);
|
var value = bytes / Math.pow(1024, i);
|
||||||
var decimalPlaces = (i < 1) ? 0 : (i - 1);
|
var decimalPlaces = (i < 1) ? 0 : (i - 1);
|
||||||
return value.toFixed(decimalPlaces) + ' ' + sizes[[i]];
|
return value.toFixed(decimalPlaces) + ' ' + sizes[[i]];
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter('containername', function () {
|
.filter('containername', function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
return function (container) {
|
return function (container) {
|
||||||
var name = container.Names[0];
|
var name = container.Names[0];
|
||||||
return name.substring(1, name.length);
|
return name.substring(1, name.length);
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter('repotag', function () {
|
.filter('swarmcontainername', function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
return function (image) {
|
return function (container) {
|
||||||
if (image.RepoTags && image.RepoTags.length > 0) {
|
return _.split(container.Names[0], '/')[2];
|
||||||
var tag = image.RepoTags[0];
|
};
|
||||||
if (tag === '<none>:<none>') {
|
})
|
||||||
tag = '';
|
.filter('swarmhostname', function () {
|
||||||
}
|
'use strict';
|
||||||
return tag;
|
return function (container) {
|
||||||
}
|
return _.split(container.Names[0], '/')[1];
|
||||||
return '';
|
};
|
||||||
};
|
})
|
||||||
})
|
.filter('repotag', function () {
|
||||||
.filter('getdate', function () {
|
'use strict';
|
||||||
'use strict';
|
return function (image) {
|
||||||
return function (data) {
|
if (image.RepoTags && image.RepoTags.length > 0) {
|
||||||
//Multiply by 1000 for the unix format
|
var tag = image.RepoTags[0];
|
||||||
var date = new Date(data * 1000);
|
if (tag === '<none>:<none>') {
|
||||||
return date.toDateString();
|
tag = '';
|
||||||
};
|
}
|
||||||
})
|
return tag;
|
||||||
.filter('errorMsg', function () {
|
}
|
||||||
return function (object) {
|
return '';
|
||||||
var idx = 0;
|
};
|
||||||
var msg = '';
|
})
|
||||||
while (object[idx] && typeof(object[idx]) === 'string') {
|
.filter('getdate', function () {
|
||||||
msg += object[idx];
|
'use strict';
|
||||||
idx++;
|
return function (data) {
|
||||||
}
|
//Multiply by 1000 for the unix format
|
||||||
return msg;
|
var date = new Date(data * 1000);
|
||||||
};
|
return date.toDateString();
|
||||||
});
|
};
|
||||||
|
})
|
||||||
|
.filter('errorMsg', function () {
|
||||||
|
return function (object) {
|
||||||
|
var idx = 0;
|
||||||
|
var msg = '';
|
||||||
|
while (object[idx] && typeof(object[idx]) === 'string') {
|
||||||
|
msg += object[idx];
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
|
@ -10,11 +10,10 @@ function ImageViewModel(data) {
|
||||||
|
|
||||||
function ContainerViewModel(data) {
|
function ContainerViewModel(data) {
|
||||||
this.Id = data.Id;
|
this.Id = data.Id;
|
||||||
|
this.State = data.State;
|
||||||
|
this.Names = data.Names;
|
||||||
|
this.IP = data.NetworkSettings.Networks[Object.keys(data.NetworkSettings.Networks)[0]].IPAddress;
|
||||||
this.Image = data.Image;
|
this.Image = data.Image;
|
||||||
this.Command = data.Command;
|
this.Command = data.Command;
|
||||||
this.Created = data.Created;
|
|
||||||
this.SizeRw = data.SizeRw;
|
|
||||||
this.Status = data.Status;
|
|
||||||
this.Checked = false;
|
this.Checked = false;
|
||||||
this.Names = data.Names;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,20 +15,6 @@ describe('filters', function () {
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('statusbadge', function () {
|
|
||||||
it('should be "important" when input is "Ghost"', inject(function (statusbadgeFilter) {
|
|
||||||
expect(statusbadgeFilter('Ghost')).toBe('important');
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should be "success" when input is "Exit 0"', inject(function (statusbadgeFilter) {
|
|
||||||
expect(statusbadgeFilter('Exit 0')).toBe('success');
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should be "warning" when exit code is non-zero', inject(function (statusbadgeFilter) {
|
|
||||||
expect(statusbadgeFilter('Exit 1')).toBe('warning');
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('getstatetext', function () {
|
describe('getstatetext', function () {
|
||||||
|
|
||||||
it('should return an empty string when state is undefined', inject(function (getstatetextFilter) {
|
it('should return an empty string when state is undefined', inject(function (getstatetextFilter) {
|
||||||
|
@ -352,4 +338,4 @@ describe('filters', function () {
|
||||||
expect(errorMsgFilter(response)).toBe(message);
|
expect(errorMsgFilter(response)).toBe(message);
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue