diff --git a/app/components/container/containerController.js b/app/components/container/containerController.js index a79419cfe..66b3b25cc 100644 --- a/app/components/container/containerController.js +++ b/app/components/container/containerController.js @@ -119,22 +119,26 @@ function ($scope, $state, $stateParams, $filter, Container, ContainerCommit, Ima }; $scope.confirmRemove = function () { + var title = 'You are about to remove a container.'; if ($scope.container.State.Running) { - ModalService.confirmDeletion( - 'You are about to remove a running container.', - function (confirmed) { - if(!confirmed) { return; } - $scope.remove(); - } - ); - } else { - $scope.remove(); + title = 'You are about to remove a running container.'; } + ModalService.confirmContainerDeletion( + title, + function (result) { + if(!result) { return; } + var cleanAssociatedVolumes = false; + if (result[0]) { + cleanAssociatedVolumes = true; + } + $scope.remove(cleanAssociatedVolumes); + } + ); }; - $scope.remove = function() { + $scope.remove = function(cleanAssociatedVolumes) { $('#loadingViewSpinner').show(); - Container.remove({id: $stateParams.id, force: true}, function (d) { + Container.remove({id: $stateParams.id, v: (cleanAssociatedVolumes) ? 1 : 0, force: true}, function (d) { if (d.message) { $('#loadingViewSpinner').hide(); Notifications.error("Failure", d, "Unable to remove container"); diff --git a/app/components/containers/containersController.js b/app/components/containers/containersController.js index 656d0c111..25eb90d25 100644 --- a/app/components/containers/containersController.js +++ b/app/components/containers/containersController.js @@ -17,6 +17,8 @@ angular.module('containers', []) Pagination.setPaginationCount('containers', $scope.state.pagination_count); }; + $scope.cleanAssociatedVolumes = false; + function removeContainerResourceControl(container) { volumeResourceControlQueries = []; angular.forEach(container.Mounts, function (volume) { @@ -128,7 +130,7 @@ angular.module('containers', []) }); } else if (action === Container.remove) { - action({id: c.Id, force: true}, function (d) { + action({id: c.Id, v: ($scope.cleanAssociatedVolumes) ? 1 : 0, force: true}, function (d) { if (d.message) { Notifications.error("Error", d, "Unable to remove container"); } @@ -239,17 +241,21 @@ angular.module('containers', []) return; } }); + var title = 'You are about to remove one or more container.'; if (isOneContainerRunning) { - ModalService.confirmDeletion( - 'You are about to remove one or more running containers.', - function (confirmed) { - if(!confirmed) { return; } - $scope.removeAction(); - } - ); - } else { - $scope.removeAction(); + title = 'You are about to remove one or more running containers.'; } + ModalService.confirmContainerDeletion( + title, + function (result) { + if(!result) { return; } + $scope.cleanAssociatedVolumes = false; + if (result[0]) { + $scope.cleanAssociatedVolumes = true; + } + $scope.removeAction(); + } + ); }; function retrieveSwarmHostsInfo(data) { diff --git a/app/rest/container.js b/app/rest/container.js index fa16d9d3b..b53b49264 100644 --- a/app/rest/container.js +++ b/app/rest/container.js @@ -23,7 +23,7 @@ angular.module('portainer.rest') transformResponse: genericHandler }, remove: { - method: 'DELETE', params: {id: '@id', v: 0, force: '@force'}, + method: 'DELETE', params: {id: '@id', v: '@v', force: '@force'}, transformResponse: genericHandler }, rename: { diff --git a/app/services/modalService.js b/app/services/modalService.js index f6667fe5e..c70704935 100644 --- a/app/services/modalService.js +++ b/app/services/modalService.js @@ -3,21 +3,7 @@ angular.module('portainer.services') '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: options.buttons.confirm.className - }, - cancel: { - label: options.buttons.cancel && options.buttons.cancel.label ? options.buttons.cancel.label : 'Cancel' - } - }, - callback: options.callback - }); + var applyBoxCSS = function(box) { box.css({ 'top': '50%', 'margin-top': function () { @@ -26,6 +12,40 @@ angular.module('portainer.services') }); }; + var confirmButtons = function(options) { + var buttons = { + confirm: { + label: options.buttons.confirm.label, + className: options.buttons.confirm.className + }, + cancel: { + label: options.buttons.cancel && options.buttons.cancel.label ? options.buttons.cancel.label : 'Cancel' + } + }; + return buttons; + }; + + service.confirm = function(options){ + var box = bootbox.confirm({ + title: options.title, + message: options.message, + buttons: confirmButtons(options), + callback: options.callback + }); + applyBoxCSS(box); + }; + + service.prompt = function(options){ + var box = bootbox.prompt({ + title: options.title, + inputType: options.inputType, + inputOptions: options.inputOptions, + buttons: confirmButtons(options), + callback: options.callback + }); + applyBoxCSS(box); + }; + service.confirmOwnershipChange = function(callback, msg) { service.confirm({ title: 'Are you sure ?', @@ -82,5 +102,26 @@ angular.module('portainer.services') callback: callback, }); }; + + service.confirmContainerDeletion = function(title, callback) { + service.prompt({ + title: title, + inputType: 'checkbox', + inputOptions: [ + { + text: 'Automatically remove non-persistent volumes', + value: '1' + } + ], + buttons: { + confirm: { + label: 'Remove', + className: 'btn-danger' + } + }, + callback: callback + }); + }; + return service; }]); diff --git a/assets/css/app.css b/assets/css/app.css index 5d05de383..d0d1cd0f5 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -371,11 +371,23 @@ ul.sidebar .sidebar-list .sidebar-sublist a.active { float: none !important; } +.bootbox-form .bootbox-input-checkbox { + display: none +} + +.bootbox-form label { + padding-left: 0; +} + .switch input { display: none; } -.switch i { +.bootbox-form .checkbox i { + margin-left: 21px; +} + +.switch i, .bootbox-form .checkbox i { display: inline-block; vertical-align: middle; cursor: pointer; @@ -386,7 +398,7 @@ ul.sidebar .sidebar-list .sidebar-sublist a.active { box-shadow: inset 0 0 1px 1px rgba(0,0,0,.5); } -.switch i:before { +.switch i:before, .bootbox-form .checkbox i:before { display: block; content: ''; width: 24px; @@ -396,7 +408,7 @@ ul.sidebar .sidebar-list .sidebar-sublist a.active { box-shadow: 0 0 1px 1px rgba(0,0,0,.5); } -.switch :checked + i { +.switch :checked + i, .bootbox-form .checkbox :checked ~ i { padding-right: 0; padding-left: 24px; -webkit-box-shadow: inset 0 0 1px rgba(0,0,0,.5), inset 0 0 40px #337ab7;