-
+
+
+
+
+
diff --git a/app/components/images/imagesController.js b/app/components/images/imagesController.js
index 7000cddaa..e3bf84066 100644
--- a/app/components/images/imagesController.js
+++ b/app/components/images/imagesController.js
@@ -1,6 +1,6 @@
angular.module('images', [])
-.controller('ImagesController', ['$scope', '$state', 'Config', 'Image', 'ImageHelper', 'Messages', 'Pagination',
-function ($scope, $state, Config, Image, ImageHelper, Messages, Pagination) {
+.controller('ImagesController', ['$scope', '$state', 'Config', 'Image', 'ImageHelper', 'Messages', 'Pagination', 'ModalService',
+function ($scope, $state, Config, Image, ImageHelper, Messages, Pagination, ModalService) {
$scope.state = {};
$scope.state.pagination_count = Pagination.getPaginationCount('images');
$scope.sortType = 'RepoTags';
@@ -59,7 +59,27 @@ function ($scope, $state, Config, Image, ImageHelper, Messages, Pagination) {
});
};
- $scope.removeAction = function () {
+ $scope.confirmRemovalAction = function (force) {
+ ModalService.confirm({
+ title: "Are you sure?",
+ message: "Forcing the removal of the image will remove the image even if it has multiple tags or if it is used by stopped containers.",
+ buttons: {
+ confirm: {
+ label: 'Remove the image',
+ },
+ cancel: {
+ label: 'Cancel'
+ }
+ },
+ callback: function (confirmed) {
+ if(!confirmed) { return; }
+ $scope.removeAction(force);
+ }
+ });
+ };
+
+ $scope.removeAction = function (force) {
+ force = !!force;
$('#loadImagesSpinner').show();
var counter = 0;
var complete = function () {
@@ -71,7 +91,7 @@ function ($scope, $state, Config, Image, ImageHelper, Messages, Pagination) {
angular.forEach($scope.images, function (i) {
if (i.Checked) {
counter = counter + 1;
- Image.remove({id: i.Id}, function (d) {
+ Image.remove({id: i.Id, force: force}, function (d) {
if (d[0].message) {
$('#loadImagesSpinner').hide();
Messages.error("Unable to remove image", {}, d[0].message);
diff --git a/app/rest/image.js b/app/rest/image.js
index 9361136fc..8a436b45a 100644
--- a/app/rest/image.js
+++ b/app/rest/image.js
@@ -18,7 +18,7 @@ angular.module('portainer.rest')
isArray: true, transformResponse: jsonObjectsToArrayHandler
},
remove: {
- method: 'DELETE', params: {id: '@id'},
+ method: 'DELETE', params: {id: '@id', force: '@force'},
isArray: true, transformResponse: deleteImageHandler
}
});
diff --git a/app/services/modalService.js b/app/services/modalService.js
new file mode 100644
index 000000000..0e1d9729b
--- /dev/null
+++ b/app/services/modalService.js
@@ -0,0 +1,28 @@
+angular.module('portainer.services')
+.factory('ModalService', [function ModalServiceFactory() {
+ 'use strict';
+ var service = {};
+ service.confirm = function(options){
+ var box = bootbox.confirm({
+ title: options.title,
+ message: options.message,
+ buttons: {
+ confirm: {
+ label: options.buttons.confirm.label,
+ className: 'btn-danger'
+ },
+ cancel: {
+ label: options.buttons.cancel.label
+ }
+ },
+ callback: options.callback
+ });
+ box.css({
+ 'top': '50%',
+ 'margin-top': function () {
+ return -(box.height() / 2);
+ }
+ });
+ }
+ return service;
+}]);
diff --git a/assets/css/app.css b/assets/css/app.css
index cce7e440b..09a7b23b6 100644
--- a/assets/css/app.css
+++ b/assets/css/app.css
@@ -72,6 +72,10 @@ input[type="radio"] {
vertical-align: middle;
}
+a[ng-click]{
+ cursor: pointer;
+}
+
.space-right {
margin-right: 5px;
}
diff --git a/bower.json b/bower.json
index 37054c119..2627f8495 100644
--- a/bower.json
+++ b/bower.json
@@ -47,7 +47,8 @@
"xterm.js": "~2.0.1",
"font-awesome": "~4.7.0",
"ng-file-upload": "~12.2.13",
- "splitargs": "~0.2.0"
+ "splitargs": "~0.2.0",
+ "bootbox.js": "bootbox#^4.4.0"
},
"resolutions": {
"angular": "1.5.5"
diff --git a/gruntfile.js b/gruntfile.js
index b053ca3ae..4abb9f753 100644
--- a/gruntfile.js
+++ b/gruntfile.js
@@ -139,6 +139,7 @@ module.exports = function (grunt) {
'bower_components/filesize/lib/filesize.min.js',
'bower_components/moment/min/moment.min.js',
'bower_components/xterm.js/dist/xterm.js',
+ 'bower_components/bootbox.js/bootbox.js',
'assets/js/jquery.gritter.js', // Using custom version to fix error in minified build due to "use strict"
'assets/js/legend.js' // Not a bower package
],