Skip to content

Commit

Permalink
Add cancel confirmation dialog to most dialog winows (#655)
Browse files Browse the repository at this point in the history
* add notifications before canceling project/experiment creation or editing

* clean up imports

* remove unused Action

* reuse code, add cancel notification to more dialogs

* some css changes

* Hacky solution for footer items in confirm dialog

* review changes

---------

Co-authored-by: Sven F <[email protected]>
Co-authored-by: Steffengreiner <[email protected]>
  • Loading branch information
3 people authored Jul 8, 2024
1 parent e028e64 commit 739c989
Show file tree
Hide file tree
Showing 15 changed files with 245 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ vaadin-button.primary {
min-width: calc(var(--lumo-button-size) * 2.5);
}

vaadin-button.danger {
background-color: var(--lumo-error-color, var(--lumo-error-color));
color: var(--lumo-button-primary-color, var(--lumo-primary-contrast-color));
}

vaadin-button.danger[focus-ring] {
box-shadow: none !important;
}

/* Styles recreated from vaadin lumo theme */
vaadin-button[disabled] {
background-color: var(--lumo-contrast-30pct);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ vaadin-dialog-overlay::part(title) {
margin: 0;
}

/*Vaadin currently does not allow to style the flex items within the footer.
Since we want to remove the spacing between the cancel and confirm button we replace the flex setting with a grid layout*/
.notification-dialog::part(footer) {
display: grid;
grid-template-columns: 0 15% 15%;
}

/* icon in header */
.notification-dialog > [slot="header"] vaadin-icon {
width: 1.83rem;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package life.qbic.datamanager.views;

import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
import life.qbic.datamanager.views.notifications.NotificationDialog;

/**
* Warns the user that they are about to cancel a dialog and lose input data
* <p>
* This dialog is to be shown when a dialog is canceled via the Esc key or the Cancel button
*/
public class CancelConfirmationNotificationDialog extends NotificationDialog {

public CancelConfirmationNotificationDialog() {
customizeHeader();
setCancelable(true);
Button redButton = new Button("Discard");
redButton.addClassName("danger");
setConfirmButton(redButton);
Button cancelButton = new Button("Continue");
setCancelButton(cancelButton);
}

public CancelConfirmationNotificationDialog withBodyText(String mainText) {
content.removeAll();
content.add(new Span(mainText));
return this;
}

public CancelConfirmationNotificationDialog withConfirmText(String confirmText) {
setConfirmText(confirmText);
return this;
}

public CancelConfirmationNotificationDialog withTitle(String headerText) {
setTitle(headerText);
return this;
}

private void customizeHeader() {
Icon errorIcon = new Icon(VaadinIcon.WARNING);
errorIcon.setClassName("warning-icon");
setHeaderIcon(errorIcon);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ public static class ChangeUserDetailsDialog extends DialogWindow {

public ChangeUserDetailsDialog(String currentUserName) {
super();

setHeaderTitle("Change username");
add(platformUserNameField);
setConfirmButtonLabel("Save");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package life.qbic.datamanager.views.general;

import com.vaadin.flow.component.ClickEvent;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.Key;
import com.vaadin.flow.component.Shortcuts;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.dialog.Dialog;
import com.vaadin.flow.server.Command;

/**
* <b>Dialog to create something</b>
Expand All @@ -29,6 +33,13 @@ protected DialogWindow() {
confirmButton.addClickListener(this::onConfirmClicked);
}

protected void specifyCancelShortcuts(Command onCreationCanceled) {
setCloseOnOutsideClick(false);
setCloseOnEsc(false);
Shortcuts.addShortcutListener(this,
onCreationCanceled, Key.ESCAPE);
}

/**
* Overwrite to change what happens on confirm button clicked
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import com.vaadin.flow.component.ComponentEvent;
import com.vaadin.flow.component.ComponentEventListener;
import com.vaadin.flow.component.HasValidation;
import com.vaadin.flow.component.Key;
import com.vaadin.flow.component.Shortcuts;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.dialog.Dialog;
import com.vaadin.flow.component.html.Div;
Expand All @@ -21,6 +23,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import life.qbic.datamanager.views.CancelConfirmationNotificationDialog;
import life.qbic.datamanager.views.general.HasBinderValidation;
import life.qbic.datamanager.views.general.Stepper;
import life.qbic.datamanager.views.general.Stepper.StepIndicator;
Expand Down Expand Up @@ -72,6 +75,9 @@ public AddProjectDialog(ProjectInformationService projectInformationService,
OntologyLookupService ontologyLookupService,
ContactRepository contactRepository) {
super();

initCancelShortcuts();

addClassName("add-project-dialog");
requireNonNull(projectInformationService, "project information service must not be null");
requireNonNull(financeService, "financeService must not be null");
Expand Down Expand Up @@ -142,6 +148,27 @@ public AddProjectDialog(ProjectInformationService projectInformationService,
adaptFooterButtons(stepper.getFirstStep());
}

private void initCancelShortcuts() {
setCloseOnOutsideClick(false);
setCloseOnEsc(false);
Shortcuts.addShortcutListener(this,
this::onCreationCanceled, Key.ESCAPE);
}

private void onCreationCanceled() {
CancelConfirmationNotificationDialog cancelDialog = new CancelConfirmationNotificationDialog()
.withBodyText("You will lose all the information entered for this project.")
.withConfirmText("Discard project creation")
.withTitle("Discard new project creation?");
cancelDialog.open();
cancelDialog.addConfirmListener(event -> {
cancelDialog.close();
fireEvent(new CancelEvent(this, true));
});
cancelDialog.addCancelListener(
event -> cancelDialog.close());
}

/**
* Allows user to search the offer database to prefill some project information
*/
Expand All @@ -150,7 +177,7 @@ public void enableOfferSearch() {
}

private void onCancelClicked(ClickEvent<Button> clickEvent) {
fireEvent(new CancelEvent(this, clickEvent.isFromClient()));
onCreationCanceled();
}

private void onConfirmClicked(ClickEvent<Button> event) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import java.util.Objects;
import java.util.Optional;
import java.util.StringJoiner;
import life.qbic.datamanager.views.CancelConfirmationNotificationDialog;
import life.qbic.datamanager.views.general.DialogWindow;
import life.qbic.datamanager.views.general.contact.Contact;
import life.qbic.datamanager.views.general.funding.FundingEntry;
Expand Down Expand Up @@ -44,6 +45,8 @@ public class EditProjectInformationDialog extends DialogWindow {
public EditProjectInformationDialog(ContactRepository contactRepository) {
super();

specifyCancelShortcuts(this::onEditCanceled);

addClassName("edit-project-dialog");
setHeaderTitle("Project Information");
setConfirmButtonLabel("Save");
Expand All @@ -64,7 +67,6 @@ public EditProjectInformationDialog(ContactRepository contactRepository) {

// Calls the reset method for all possible closure methods of the dialogue window:
addDialogCloseActionListener(closeActionEvent -> close());
cancelButton.addClickListener(buttonClickEvent -> close());

add(formLayout);
}
Expand Down Expand Up @@ -93,13 +95,25 @@ protected void onConfirmClicked(ClickEvent<Button> clickEvent) {
}
}

private void onEditCanceled() {
CancelConfirmationNotificationDialog cancelDialog = new CancelConfirmationNotificationDialog()
.withBodyText("You will lose all the changes made to this project.")
.withConfirmText("Discard changes")
.withTitle("Discard project changes?");
cancelDialog.open();
cancelDialog.addConfirmListener(event -> {
cancelDialog.close();
fireEvent(new CancelEvent(this, true));
});
cancelDialog.addCancelListener(
event -> cancelDialog.close());
}

@Override
protected void onCancelClicked(ClickEvent<Button> clickEvent) {
fireEvent(new CancelEvent(this, clickEvent.isFromClient()));
close();
onEditCanceled();
}


public void addProjectUpdateEventListener(ComponentEventListener<ProjectUpdateEvent> listener) {
addListener(ProjectUpdateEvent.class, listener);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import life.qbic.datamanager.views.CancelConfirmationNotificationDialog;
import life.qbic.datamanager.views.general.DialogWindow;
import life.qbic.datamanager.views.projects.project.experiments.experiment.ExperimentalGroupInput;
import life.qbic.projectmanagement.application.VariableValueFormatter;
Expand Down Expand Up @@ -41,6 +42,7 @@ public class ExperimentalGroupsDialog extends DialogWindow {
private ExperimentalGroupsDialog(Collection<VariableLevel> experimentalVariableLevels,
boolean editMode) {
super();
specifyCancelShortcuts(this::onCanceled);
this.editMode = editMode;
this.experimentalVariableLevels = Objects.requireNonNull(experimentalVariableLevels);
layoutComponent();
Expand Down Expand Up @@ -114,9 +116,23 @@ protected void onConfirmClicked(ClickEvent<Button> clickEvent) {
fireEvent(new ConfirmEvent(this, clickEvent.isFromClient()));
}

private void onCanceled() {
CancelConfirmationNotificationDialog cancelDialog = new CancelConfirmationNotificationDialog()
.withBodyText("You will lose any changes you made to experimental groups.")
.withConfirmText("Discard changes")
.withTitle("Discard experimental group changes?");
cancelDialog.open();
cancelDialog.addConfirmListener(event -> {
cancelDialog.close();
fireEvent(new CancelEvent(this, true));
});
cancelDialog.addCancelListener(
event -> cancelDialog.close());
}

@Override
protected void onCancelClicked(ClickEvent<Button> clickEvent) {
fireEvent(new CancelEvent(this, clickEvent.isFromClient()));
onCanceled();
}

public void addCancelEventListener(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import life.qbic.datamanager.views.CancelConfirmationNotificationDialog;
import life.qbic.datamanager.views.general.DialogWindow;
import life.qbic.projectmanagement.domain.model.experiment.ExperimentalVariable;

Expand Down Expand Up @@ -45,6 +46,7 @@ private ExperimentalVariablesDialog(boolean editMode) {
super();
mode = editMode ? MODE.EDIT : MODE.ADD;
setConfirmButtonLabel(confirmActionLabel());
specifyCancelShortcuts(this::onCanceled);
setCancelButtonLabel("Cancel");
addClassName("experiment-variable-dialog");
layoutComponent();
Expand Down Expand Up @@ -93,9 +95,23 @@ protected void onConfirmClicked(ClickEvent<Button> clickEvent) {

}

private void onCanceled() {
CancelConfirmationNotificationDialog cancelDialog = new CancelConfirmationNotificationDialog()
.withBodyText("You will lose any changes you made to variables.")
.withConfirmText("Discard changes")
.withTitle("Discard variable changes?");
cancelDialog.open();
cancelDialog.addConfirmListener(event -> {
cancelDialog.close();
fireEvent(new CancelEvent(this, true));
});
cancelDialog.addCancelListener(
event -> cancelDialog.close());
}

@Override
protected void onCancelClicked(ClickEvent<Button> clickEvent) {
fireEvent(new CancelEvent(this, clickEvent.isFromClient()));
onCanceled();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import life.qbic.datamanager.views.CancelConfirmationNotificationDialog;
import life.qbic.datamanager.views.events.UserCancelEvent;
import life.qbic.datamanager.views.general.DialogWindow;
import life.qbic.datamanager.views.projects.create.BioIconComboboxFactory;
Expand Down Expand Up @@ -52,6 +53,8 @@ public AddExperimentDialog(
ontologyTermInformationService);
final BioIconComboboxFactory bioIconComboboxFactory = new BioIconComboboxFactory();

specifyCancelShortcuts(this::onCreationCanceled);

Span experimentHeader = new Span("Experiment");
experimentHeader.addClassName("header");

Expand Down Expand Up @@ -128,9 +131,23 @@ protected void onConfirmClicked(ClickEvent<Button> clickEvent) {
}
}

private void onCreationCanceled() {
CancelConfirmationNotificationDialog cancelDialog = new CancelConfirmationNotificationDialog()
.withBodyText("You will lose all the information entered for this experiment.")
.withConfirmText("Discard experiment creation")
.withTitle("Discard new experiment creation?");
cancelDialog.open();
cancelDialog.addConfirmListener(event -> {
cancelDialog.close();
fireEvent(new CancelEvent(this, true));
});
cancelDialog.addCancelListener(
event -> cancelDialog.close());
}

@Override
protected void onCancelClicked(ClickEvent<Button> clickEvent) {
fireEvent(new CancelEvent(this, clickEvent.isFromClient()));
onCreationCanceled();
}

public void setExperiment(ExperimentDraft experiment) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import life.qbic.datamanager.views.CancelConfirmationNotificationDialog;
import life.qbic.datamanager.views.events.UserCancelEvent;
import life.qbic.datamanager.views.general.DialogWindow;
import life.qbic.datamanager.views.projects.create.BioIconComboboxFactory;
Expand Down Expand Up @@ -47,6 +48,8 @@ public EditExperimentDialog(OntologyLookupService ontologyTermInformationService
ontologyTermInformationService);
final BioIconComboboxFactory bioIconComboboxFactory = new BioIconComboboxFactory();

specifyCancelShortcuts(this::onEditCanceled);

Span experimentHeader = new Span("Experiment");
experimentHeader.addClassName("header");

Expand Down Expand Up @@ -124,9 +127,23 @@ protected void onConfirmClicked(ClickEvent<Button> clickEvent) {
}
}

private void onEditCanceled() {
CancelConfirmationNotificationDialog cancelDialog = new CancelConfirmationNotificationDialog()
.withBodyText("You will lose all the changes made to this experiment.")
.withConfirmText("Discard changes")
.withTitle("Discard experiment changes?");
cancelDialog.open();
cancelDialog.addConfirmListener(event -> {
cancelDialog.close();
fireEvent(new CancelEvent(this, true));
});
cancelDialog.addCancelListener(
event -> cancelDialog.close());
}

@Override
protected void onCancelClicked(ClickEvent<Button> clickEvent) {
fireEvent(new CancelEvent(this, clickEvent.isFromClient()));
onEditCanceled();
}

public void setExperiment(ExperimentDraft experiment) {
Expand Down
Loading

0 comments on commit 739c989

Please sign in to comment.