diff --git a/app/components/containers/containers.html b/app/components/containers/containers.html index 5849e8ac2..39a754168 100644 --- a/app/components/containers/containers.html +++ b/app/components/containers/containers.html @@ -105,7 +105,7 @@
{{ service.Running }}
+ /
+ {{ service.Replicas }}
- {{ service.Replicas }}
Scale
diff --git a/app/components/services/servicesController.js b/app/components/services/servicesController.js
index 850d5009f..13f63fff6 100644
--- a/app/components/services/servicesController.js
+++ b/app/components/services/servicesController.js
@@ -1,6 +1,6 @@
angular.module('services', [])
-.controller('ServicesController', ['$q', '$scope', '$stateParams', '$state', 'Service', 'ServiceHelper', 'Messages', 'Pagination', 'Authentication', 'UserService', 'ModalService', 'ResourceControlService',
-function ($q, $scope, $stateParams, $state, Service, ServiceHelper, Messages, Pagination, Authentication, UserService, ModalService, ResourceControlService) {
+.controller('ServicesController', ['$q', '$scope', '$stateParams', '$state', 'Service', 'ServiceHelper', 'Messages', 'Pagination', 'Task', 'Node', 'Authentication', 'UserService', 'ModalService', 'ResourceControlService',
+function ($q, $scope, $stateParams, $state, Service, ServiceHelper, Messages, Pagination, Task, Node, Authentication, UserService, ModalService, ResourceControlService) {
$scope.state = {};
$scope.state.selectedItemCount = 0;
$scope.state.pagination_count = Pagination.getPaginationCount('services');
@@ -127,30 +127,41 @@ function ($q, $scope, $stateParams, $state, Service, ServiceHelper, Messages, Pa
function fetchServices() {
$('#loadServicesSpinner').show();
+
var userDetails = Authentication.getUserDetails();
$scope.user = userDetails;
- Service.query({}, function (d) {
- $scope.services = d.map(function (service) {
- return new ServiceViewModel(service);
+ $q.all({
+ services: Service.query({}).$promise,
+ tasks: Task.query({filters: {'desired-state': ['running']}}).$promise,
+ nodes: Node.query({}).$promise,
+ })
+ .then(function success(data) {
+ $scope.services = data.services.map(function (service) {
+ var serviceTasks = data.tasks.filter(function (task) {
+ return task.ServiceID === service.ID;
+ });
+ var taskNodes = data.nodes.filter(function (node) {
+ return node.Spec.Availability === 'active' && node.Status.State === 'ready';
+ });
+ return new ServiceViewModel(service, serviceTasks, taskNodes);
});
if (userDetails.role === 1) {
UserService.users()
.then(function success(data) {
mapUsersToServices(data);
})
- .catch(function error(err) {
- Messages.error("Failure", err, "Unable to retrieve users");
- })
.finally(function final() {
$('#loadServicesSpinner').hide();
});
}
- $('#loadServicesSpinner').hide();
- }, function(e) {
- $('#loadServicesSpinner').hide();
- Messages.error("Failure", e, "Unable to retrieve services");
+ })
+ .catch(function error(err) {
$scope.services = [];
+ Messages.error("Failure", err, "Unable to retrieve services");
+ })
+ .finally(function final() {
+ $('#loadServicesSpinner').hide();
});
}
diff --git a/app/filters/filters.js b/app/filters/filters.js
index ddfda05f1..075fa5902 100644
--- a/app/filters/filters.js
+++ b/app/filters/filters.js
@@ -228,4 +228,13 @@ angular.module('portainer.filters', [])
}
return '';
};
+})
+.filter('hideshasum', function () {
+ 'use strict';
+ return function (imageName) {
+ if (imageName) {
+ return imageName.split('@sha')[0];
+ }
+ return '';
+ };
});
diff --git a/app/models/service.js b/app/models/service.js
index b312e2d2c..156faefef 100644
--- a/app/models/service.js
+++ b/app/models/service.js
@@ -1,4 +1,4 @@
-function ServiceViewModel(data) {
+function ServiceViewModel(data, runningTasks, nodes) {
this.Model = data;
this.Id = data.ID;
this.Name = data.Spec.Name;
@@ -9,6 +9,12 @@ function ServiceViewModel(data) {
this.Replicas = data.Spec.Mode.Replicated.Replicas;
} else {
this.Mode = 'global';
+ if (nodes) {
+ this.Replicas = nodes.length;
+ }
+ }
+ if (runningTasks) {
+ this.Running = runningTasks.length;
}
this.Labels = data.Spec.Labels;
if (data.Spec.TaskTemplate.ContainerSpec) {