From b6b579d55d20a21775fb07ed68fd9088e7814e3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Kov=C3=A1cs?= Date: Sat, 8 Jul 2017 08:59:32 +0200 Subject: [PATCH] feat(image-details): simple image history (#425) --- app/components/image/image.html | 39 +++++++++++++++++++++++++ app/components/image/imageController.js | 18 ++++++++++++ app/filters/filters.js | 6 ++++ app/models/imageLayer.js | 8 +++++ app/services/docker/imageService.js | 20 +++++++++++++ assets/css/app.css | 16 +++++----- 6 files changed, 99 insertions(+), 8 deletions(-) create mode 100644 app/models/imageLayer.js diff --git a/app/components/image/image.html b/app/components/image/image.html index 799dd2386..e8a780cb7 100644 --- a/app/components/image/image.html +++ b/app/components/image/image.html @@ -167,3 +167,42 @@ + +
+
+ + + + + + + + + + + + + + + + +
SizeLayer
{{layer.Size|humansize}} +
+ + + {{layer.CreatedBy|createdby|limitTo:100}}{{layer.CreatedBy.length > 100 ? '...' : ''}} + +
+
+ + {{layer.CreatedBy|createdby}} + +
+
+
+
+
+
+
diff --git a/app/components/image/imageController.js b/app/components/image/imageController.js index fa2925b07..0e4552532 100644 --- a/app/components/image/imageController.js +++ b/app/components/image/imageController.js @@ -6,6 +6,12 @@ function ($scope, $stateParams, $state, $timeout, ImageService, RegistryService, Registry: '' }; + $scope.toggleLayerCommand = function(layerId) { + $('#layer-command-expander'+layerId+' span').toggleClass('glyphicon-plus-sign glyphicon-minus-sign'); + $('#layer-command-'+layerId+'-short').toggle(); + $('#layer-command-'+layerId+'-full').toggle(); + }; + $scope.tagImage = function() { $('#loadingViewSpinner').show(); var image = $scope.formValues.Image; @@ -108,6 +114,18 @@ function ($scope, $stateParams, $state, $timeout, ImageService, RegistryService, .finally(function final() { $('#loadingViewSpinner').hide(); }); + + $('#loadingViewSpinner').show(); + ImageService.history($stateParams.id) + .then(function success(data) { + $scope.history = data; + }) + .catch(function error(err) { + Notifications.error('Failure', err, 'Unable to retrieve image history'); + }) + .finally(function final() { + $('#loadingViewSpinner').hide(); + }); } retrieveImageDetails(); diff --git a/app/filters/filters.js b/app/filters/filters.js index 5f0569cd4..57096d633 100644 --- a/app/filters/filters.js +++ b/app/filters/filters.js @@ -271,4 +271,10 @@ angular.module('portainer.filters', []) } return ''; }; +}) +.filter('createdby', function () { + 'use strict'; + return function (createdBy) { + return createdBy.replace('/bin/sh -c #(nop) ','').replace('/bin/sh -c ', 'RUN '); + }; }); diff --git a/app/models/imageLayer.js b/app/models/imageLayer.js new file mode 100644 index 000000000..59889d290 --- /dev/null +++ b/app/models/imageLayer.js @@ -0,0 +1,8 @@ +function ImageLayerViewModel(data) { + this.Id = data.Id; + this.Created = data.Created; + this.CreatedBy = data.CreatedBy; + this.Size = data.Size; + this.Comment = data.Comment; + this.Tags = data.Tags; +} diff --git a/app/services/docker/imageService.js b/app/services/docker/imageService.js index c3dbebb1e..2966abdaf 100644 --- a/app/services/docker/imageService.js +++ b/app/services/docker/imageService.js @@ -35,6 +35,26 @@ angular.module('portainer.services') return deferred.promise; }; + service.history = function(imageId) { + var deferred = $q.defer(); + Image.history({id: imageId}).$promise + .then(function success(data) { + if (data.message) { + deferred.reject({ msg: data.message }); + } else { + var layers = []; + angular.forEach(data, function(imageLayer) { + layers.push(new ImageLayerViewModel(imageLayer)); + }); + deferred.resolve(layers); + } + }) + .catch(function error(err) { + deferred.reject({ msg: 'Unable to retrieve image details', err: err }); + }); + return deferred.promise; + }; + service.pushImage = function(tag, registry) { var deferred = $q.defer(); diff --git a/assets/css/app.css b/assets/css/app.css index adbfa66a7..7be1a7fbb 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -281,14 +281,6 @@ a[ng-click]{ margin: 0 auto; } -ul.sidebar { - bottom: 40px; -} - -ul.sidebar .sidebar-title { - height: auto; -} - ul.sidebar .sidebar-list a.active { color: #fff; text-indent: 22px; @@ -296,6 +288,14 @@ ul.sidebar .sidebar-list a.active { background: #2d3e63; } +#image-layers .btn{ + padding: 0; +} + +#image-layers .expand{ + padding-right: 0; +} + ul.sidebar .sidebar-list .sidebar-sublist a { text-indent: 35px; font-size: 12px;