Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(image): add the ability to force remove an image (#497) #562

Merged
merged 7 commits into from
Feb 15, 2017

Conversation

Filirom1
Copy link
Contributor

@Filirom1 Filirom1 commented Feb 4, 2017

Hello,

This MR implements #497

image

This is my first contribution on this project, I am volonteer to continue on #354, if this one is OK for you.

Cheers
Romain

Close #497

@deviantony
Copy link
Member

@ncresswell do we still want to add the ability to force remove an image?

@ncresswell
Copy link
Member

ncresswell commented Feb 11, 2017 via email

@deviantony
Copy link
Member

@Filirom1 would you be able to implement that information ? I'm not a great fond of popups as I've think they're bad for UX but nonetheless I agree with Neil that some confirmation should be asked.

@ncresswell
Copy link
Member

ncresswell commented Feb 12, 2017 via email

@Filirom1
Copy link
Contributor Author

Filirom1 commented Feb 13, 2017

Hi @ncresswell

I don't see what you are asking for. If you have examples it could help me.

Otherwize, with html5 dialog we could have something like this easily:

image

Pressing the ESC on the keyboard also cancel the dialog.

As for I as know, docker rmi -f doesn't break running container, it only removes tags on the image, but docker rmi -f is needed to remove an image with several tags.

@ncresswell
Copy link
Member

ncresswell commented Feb 13, 2017 via email

@deviantony
Copy link
Member

IMO, message needs to be udpated as a user could select multiple images and trigger the force remove.
I'll give a try to the HTML5 box to see if it fits well with Portainer design.

@Filirom1
Copy link
Contributor Author

Ok, I will push my commits once I get back home.

And we will iterate on it to have something great :-)

@deviantony
Copy link
Member

Perfect ! Thanks a lot @Filirom1 👍

@deviantony
Copy link
Member

Looks like something went wrong ;)

You should just pull/merge develop instead of doing a rebase.

@Filirom1
Copy link
Contributor Author

Yes, I rebase on master. Bad idea 😢

@deviantony
Copy link
Member

That's better ! I'll have a look at it today.

@Filirom1
Copy link
Contributor Author

HTML 5.1 dialog are not well supported by browsers.
Finally I switched to bootstrap modals.

force-remove

Are you OK with the usage of the bootbox library ? It eases modal usage.

@deviantony
Copy link
Member

Even if I despise popups, I do not see any alternative here. I'm OK for the bootbox library.

IMO, the message should be updated to "Forcing the removal of the image will remove the image even if it has multiple tags or if it is used by stopped containers".

@Filirom1
Copy link
Contributor Author

I like your message, I commit it 👯‍♂️

Copy link
Member

@deviantony deviantony left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have a look at my comments for a few changes.

Also, please run grunt lint and fix linting issues.

Oh and one more thing, would it be possible to have the modal centered on the screen instead of it opening in the top part of the screen ?

$scope.confirmRemovalAction = function (force) {
bootbox.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",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add an extra '.' at the end of the sentence?

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: 'Force',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace the label with 'Remove the image'

@@ -59,7 +59,28 @@ function ($scope, $state, Config, Image, ImageHelper, Messages, Pagination) {
});
};

$scope.removeAction = function () {
$scope.confirmRemovalAction = function (force) {
bootbox.confirm({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think you could isolate the bootbox call inside a specific service ? Like ModalService ? This way if we want to get rid of bootbox later, we'll just have to change the implementation there.

Copy link
Contributor Author

@Filirom1 Filirom1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@Filirom1
Copy link
Contributor Author

About the linter, I fixed my code, but the linter is still displaying a lot of errors elsewhere in the code.

Are you aware of it ?

$ grunt lint |grep ERROR
Linting gruntfile.js...ERROR
Linting app/app.js...ERROR
Linting app/components/createNetwork/createNetworkController.js...ERROR
Linting app/components/createService/createServiceController.js...ERROR
Linting app/components/images/imagesController.js...ERROR
Linting app/components/networks/networksController.js...ERROR
Linting app/components/stats/statsController.js...ERROR
Linting app/components/templates/templatesController.js...ERROR
Linting app/models/event.js...ERROR
Linting app/rest/container.js...ERROR
Linting app/rest/event.js...ERROR
Linting app/rest/exec.js...ERROR
Linting app/rest/image.js...ERROR
Linting app/rest/response/handlers.js...ERROR
Linting app/rest/version.js...ERROR
Linting app/rest/volume.js...ERROR
Linting app/services/containerService.js...ERROR
Linting app/services/imageService.js...ERROR
Linting app/services/templateService.js...ERROR
Linting app/services/volumeService.js...ERROR

@deviantony
Copy link
Member

Please run npm install again to ensure that you have the latest version of the linter installed. I do not have these issues.

Copy link
Member

@deviantony deviantony left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An update is required in the ModalService.

@@ -59,7 +59,28 @@ function ($scope, $state, Config, Image, ImageHelper, Messages, Pagination) {
});
};

$scope.removeAction = function () {
$scope.confirmRemovalAction = function (force) {
ModalService.confirm({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd go farther when isolating the bootbox inside the ModalService. ModalService methods should be pretty abstract and should not know about the required fields. It should only expose a confirmationModal method with the things that can change inside a confimation modal (e.g. title, message, confirmLabel, cancelLabel and the success callback).

Something like ModalService.confirmModal('Are you sure?', Forcing the removal of the image will remove the image even if it has multiple tags or if it is used by stopped containers.', 'Remove the image', 'Cancel', function () { ... })

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi,

I understand your point, but passing such parameters as arguments will make this module hard to evolve.

I would prefer passing parameters as an object:

ModalService.confirmModal({
   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.',
  confirm: {
    label: 'Remove the image'
  },
  cancel: {
    label: 'cancel'
  }
})

To make my point clear, in our situation, the className of the confirm button is red for danger.
This may not be the case, if later, for example, we want to use this service to confirm a password change.

Passing an object will make it simpler to extend with additional parameters.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I offer you this new solution in a5944dc, based on object passing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, this is OK for me.

@@ -135,6 +139,23 @@ input[type="radio"] {
line-height: 1.42857143;
border-radius: 4px;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this code is related to the centering of the modal. Have you tried to do it in the service directly ? See bootboxjs/bootbox#166 (comment)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point.

Copy link
Member

@deviantony deviantony left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@deviantony
Copy link
Member

Thanks @Filirom1 👍

Also, please update your local dev dependencies as there is still a small linting issue:

Running "jshint:files" (jshint) task

   app/services/modalService.js
     26 |  }
            ^ Missing semicolon.

>> 1 error in 94 files

I'll merge it and fix the linting issue.

@deviantony deviantony merged commit 64ef743 into portainer:develop Feb 15, 2017
chiptus pushed a commit that referenced this pull request Aug 13, 2021
Co-authored-by: Simon Meng <simon.meng@portainer.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants