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

mgr/dashboard: Adds reusable deletion dialog #20899

Merged
merged 5 commits into from Apr 24, 2018

Conversation

Devp00l
Copy link

@Devp00l Devp00l commented Mar 14, 2018

You can now simply use a deletion dialog without having to import a lot
of different things from ngx-bootstrap. Its easy to extend the dialog
by a detail description.

Signed-off-by: Stephan Müller smueller@suse.com

This commit is based on two commits from @tspmelo.

To see a working example look here


The updated example on how to use the different deletion methods can be found here

@Devp00l Devp00l changed the title mgr/dashboard_v2: Adds reusable deletion dialog [DNM] mgr/dashboard_v2: Adds reusable deletion dialog Mar 14, 2018
@Devp00l
Copy link
Author

Devp00l commented Mar 14, 2018

deletion-dialog-example

This animation was created using the other branch named "deletion-dialog-example".

@LenzGr LenzGr changed the title [DNM] mgr/dashboard_v2: Adds reusable deletion dialog [DNM] mgr/dashboard: Adds reusable deletion dialog Mar 16, 2018
@votdev
Copy link
Member

votdev commented Mar 23, 2018

Could you please rebase this PR.

Copy link
Contributor

@ricardoasmarques ricardoasmarques left a comment

Choose a reason for hiding this comment

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

Shouldn't we wait for #21011 ?

export class DeletionModalComponent implements OnInit {
@Input() metaType: string;
@Input() pattern: string;
@Input() btnClasses = 'btn btn-primary';
Copy link
Contributor

Choose a reason for hiding this comment

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

Should be 'btn btn-sm btn-primary' (dashboard buttons are small).

Copy link
Member

Choose a reason for hiding this comment

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

This is correct, but the button still does not fit in a btn-group. I think we need to duplicate the btn-group CSS for cd-deletion-modal.
bildschirmfoto vom 2018-03-26 09-44-41

Copy link
Author

Choose a reason for hiding this comment

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

fixed

</ng-container>

<ng-container class="modal-footer">
<button type="button"
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't we use a "cd-submit-button" here (after #21011 is merged)?

With a "cd-submit-button" you will have auto focus on invalid field.

Copy link
Author

Choose a reason for hiding this comment

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

fixed

</ng-template>

<ng-template #deletionButtonLabel>
<i class="fa fa-fw fa-trash-o"></i>
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm sure we should use an icon on the "first" button, but IMO we don't need this icon on the modal "submit" button because we don't use icons on any other form submission (e.g. Pool creation, RBD creation).

Copy link
Author

Choose a reason for hiding this comment

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

fixed

@votdev
Copy link
Member

votdev commented Mar 26, 2018

I do not like that the component does not take care about showing a progress spinner somewhere until the deletion is done. The current implementation forces the developer to do this on its own.

import { BsModalRef, BsModalService } from 'ngx-bootstrap';

@Component({
selector: 'cd-deletion-modal',
Copy link
Member

Choose a reason for hiding this comment

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

Maybe consider to rename it to something like cd-deletion-button.

Copy link
Author

@Devp00l Devp00l Apr 6, 2018

Choose a reason for hiding this comment

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

done

}
}

openModal(template: TemplateRef<any>) {
Copy link
Member

Choose a reason for hiding this comment

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

I think we should name this method showModal.

Copy link
Author

Choose a reason for hiding this comment

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

renamed


constructor(private modalService: BsModalService) {}

openModal(template: TemplateRef<any>) {
Copy link
Member

Choose a reason for hiding this comment

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

Consider renaming this method to showModal.

Copy link
Author

Choose a reason for hiding this comment

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

done

@Devp00l Devp00l force-pushed the deletion-dialog branch 2 times, most recently from 430f5d9 to 3819dbf Compare April 6, 2018 14:34
@Devp00l Devp00l changed the title [DNM] mgr/dashboard: Adds reusable deletion dialog mgr/dashboard: Adds reusable deletion dialog Apr 6, 2018
@ricardoasmarques
Copy link
Contributor

Delete confirmation dialog does not close automatically after submit, is this something we should do manually? If yes, how should we implement it?

screenshot from 2018-04-09 13-16-36

@Devp00l
Copy link
Author

Devp00l commented Apr 9, 2018

@ricardoasmarques it closes automatically if you provide a delete method that is a observable - If you don't you have to close it manually - You can see how each way can be done in this example.

The problem is if the delete function is only triggered though emit the modal won't know when the deletion is done and therefore should not close itself.

@ricardoasmarques
Copy link
Contributor

@Devp00l The required validation message is not displayed when I click on Delete button before I type anything on the input (I mean, if input is not dirty). Is this something that can be fixed?


constructor(private modalService: BsModalService) {}

openModal(template: TemplateRef<any>) {
Copy link
Member

Choose a reason for hiding this comment

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

This method is not used in this PR, so it can be removed, right?

</cd-modal>
</ng-template>

<ng-template #deletionButtonLabel>
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not being used.

<ng-container *ngTemplateOutlet="deletionHeading"></ng-container>
</ng-template>

<ng-template #dialogDeleteButton>
Copy link
Contributor

Choose a reason for hiding this comment

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

I would suggest we don't create a template for elements that are only used once.
cdSubmitButton can be inserted directly in the the modal-footer element.

Copy link
Author

Choose a reason for hiding this comment

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

It's only possible to use the submit button with the right scope in the modal if its a template.

{{ metaType }}
</ng-template>

<ng-template #deletionDescription>
Copy link
Contributor

Choose a reason for hiding this comment

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

Same situation as cdSubmitButton.

Copy link
Author

Choose a reason for hiding this comment

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

Same here

export class DeletionButtonComponent implements OnInit {
@ViewChild(SubmitButtonComponent) submitButton: SubmitButtonComponent;
@Input() metaType: string;
@Input() pattern: string;
Copy link
Member

Choose a reason for hiding this comment

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

Does it make sense to set a default value here?

Copy link
Author

Choose a reason for hiding this comment

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

removed it

}

invalidControl (control: FormControl, error?: string) {
return control.dirty && control.invalid && (error ? control.errors[error] : true);
Copy link
Contributor

Choose a reason for hiding this comment

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

We should also check if the form is in the submitted state. something like (formDir.submitted || control.dirty) && ..

Copy link
Author

Choose a reason for hiding this comment

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

Included

@Devp00l Devp00l force-pushed the deletion-dialog branch 2 times, most recently from a79fc33 to 91f1112 Compare April 16, 2018 09:20
@Devp00l
Copy link
Author

Devp00l commented Apr 16, 2018

Changed the button into a link - now you can use it everywhere :)

<ng-container i18n>
Delete
</ng-container>
{{ metaType }}
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't this be translated?

</span>
<span class="help-block"
*ngIf="invalidControl(formDir.submitted, 'pattern')">
'{{ confirmation.value }}'
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't this be translated?

<ng-container i18n>
To confirm the deletion, enter
</ng-container>
<kbd>{{ pattern }}</kbd>
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't this be translated?

@votdev
Copy link
Member

votdev commented Apr 16, 2018

Dropdown looks now like
fireshot capture 19 - ceph - http___localhost_4200_ _rgw_user

@ricardoasmarques
Copy link
Contributor

Per our discussion today, this PR should only include a component that represents the modal, and each developer is responsible for opening and closing that modal.

After RBD management PR is merged, you should addapt your code based on mgr/dashboard: Add 'delete-confirmation-modal' component commit -
https://github.com/ricardoasmarques/ceph/commits/wip-list-all-rbds

@Devp00l Devp00l force-pushed the deletion-dialog branch 2 times, most recently from f4dcc08 to cb58f23 Compare April 18, 2018 15:25
@ricardoasmarques
Copy link
Contributor

'Cancel' is not working for the deletion modal.

When I try to cancel the deletion modal, a validation error is displayes instead of closing the moda:

screenshot from 2018-04-19 15-39-23

@Devp00l
Copy link
Author

Devp00l commented Apr 20, 2018

Addressed all commits, added a setup method that check that everything needed is set. Also I now mocked show form modalService to prevent detached modals on the chrome output.

@ricardoasmarques
Copy link
Contributor

If we receive an error from server, the Delete button should be re-enabled

screenshot from 2018-04-23 10-51-10

Doing something like this.deletionForm.setErrors({'cdSubmitButton': true}); should fix the problem.

} from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';

import { BsModalRef, BsModalService } from 'ngx-bootstrap';
Copy link
Member

Choose a reason for hiding this comment

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

BsModalService can be removed because it is not used.

@Devp00l
Copy link
Author

Devp00l commented Apr 23, 2018

@ricardoasmarques Added the error to the stopLoadingSpinner method which you have to call manually if you don't use an observable deletion method.

@votdev removed the unused import

@ricardoasmarques
Copy link
Contributor

@Devp00l can you please apply the following patch to guarantee that we stop the spinner button on RBD dialogs:

diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.ts
index ee4b58e9c0..6ac2fbb02a 100644
--- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.ts
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.ts
@@ -235,6 +235,7 @@ export class RbdListComponent implements OnInit, OnDestroy {
         this.modalRef.hide();
         this.loadImages(null);
       }).catch((resp) => {
+        this.modalRef.content.stopLoadingSpinner();
         finishedTask.success = false;
         finishedTask.exception = resp.error;
         this.notificationService.notifyTask(finishedTask);
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.ts
index 52752febf4..270822bee1 100644
--- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.ts
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-snapshot-list/rbd-snapshot-list.component.ts
@@ -207,7 +207,7 @@ export class RbdSnapshotListComponent implements OnInit, OnChanges {
           });
       })
       .catch((resp) => {
-        this.modalRef.hide();
+        this.modalRef.content.stopLoadingSpinner();
         finishedTask.success = false;
         finishedTask.exception = resp.error;
         this.notificationService.notifyTask(finishedTask);
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rollback-confirmation-modal/rollback-confimation-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rollback-confirmation-modal/rollback-confimation-modal.component.ts
index 596c6e9427..b95d7e4704 100644
--- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rollback-confirmation-modal/rollback-confimation-modal.component.ts
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rollback-confirmation-modal/rollback-confimation-modal.component.ts
@@ -32,4 +32,8 @@ export class RollbackConfirmationModalComponent implements OnInit {
   submit() {
     this.onSubmit.next(this.snapName);
   }
+
+  stopLoadingSpinner() {
+    this.rollbackForm.setErrors({'cdSubmitButton': true});
+  }
 }

Tiago Melo and others added 4 commits April 24, 2018 13:57
This component should be used each time you define a new modal.
This will allows us to keep all modals with the same visual aspect.

Signed-off-by: Tiago Melo <tmelo@suse.com>
Signed-off-by: Stephan Müller <smueller@suse.com>
You can now simply use a deletion dialog without having to import a lot
of different things from ngx-bootstrap. Its easy to extend the dialog
by a detail description.

Signed-off-by: Tiago Melo <tmelo@suse.com>
Signed-off-by: Stephan Müller <smueller@suse.com>
This change was made because a link can be placed anywhere instead of a
button element.

Signed-off-by: Stephan Müller <smueller@suse.com>
Due to CSS problems the link solution wasn't the best way, now it will
represent only the modal content. The downside of this solution is that
it put's the burden on the developer to use it the right way and import
a view things to get it working. But on the upside CSS styles will work
as expected.

The unit test example was updated accordingly this way it should be easy
to understand how it can be implemented the right way.

Signed-off-by: Stephan Müller <smueller@suse.com>
@Devp00l
Copy link
Author

Devp00l commented Apr 24, 2018

@ricardoasmarques implemented your requested changes with unit tests

@ricardoasmarques
Copy link
Contributor

ricardoasmarques commented Apr 24, 2018

@Devp00l this PR has a javascript error because you haven't applied all my patch, you missed this part:

diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rollback-confirmation-modal/rollback-confimation-modal.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rollback-confirmation-modal/rollback-confimation-modal.component.ts
index 596c6e9427..b95d7e4704 100644
--- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rollback-confirmation-modal/rollback-confimation-modal.component.ts
+++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rollback-confirmation-modal/rollback-confimation-modal.component.ts
@@ -32,4 +32,8 @@ export class RollbackConfirmationModalComponent implements OnInit {
   submit() {
     this.onSubmit.next(this.snapName);
   }
+
+  stopLoadingSpinner() {
+    this.rollbackForm.setErrors({'cdSubmitButton': true});
+  }
 }

FYI, this is the error, when trying to rollback an RBD snapshot:

ERROR Error: Uncaught (in promise): TypeError: _this.modalRef.content.stopLoadingSpinner is not a function
TypeError: _this.modalRef.content.stopLoadingSpinner is not a function
    at eval (rbd-snapshot-list.component.ts:210)

This replaces usage of "delete-confirmation-modal" with the use of
"delete-modal".

Signed-off-by: Stephan Müller <smueller@suse.com>
@Devp00l
Copy link
Author

Devp00l commented Apr 24, 2018

@ricardoasmarques addressed your comment

Copy link
Contributor

@ricardoasmarques ricardoasmarques left a comment

Choose a reason for hiding this comment

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

Thanks, approved!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants