diff --git a/user-interface/src/main/bundles/dev.bundle b/user-interface/src/main/bundles/dev.bundle
index bf4751e4e..9a6dd122a 100644
Binary files a/user-interface/src/main/bundles/dev.bundle and b/user-interface/src/main/bundles/dev.bundle differ
diff --git a/user-interface/src/main/java/life/qbic/datamanager/views/account/PersonalAccessTokenMain.java b/user-interface/src/main/java/life/qbic/datamanager/views/account/PersonalAccessTokenMain.java
index 9a835ad6f..4252d05d6 100644
--- a/user-interface/src/main/java/life/qbic/datamanager/views/account/PersonalAccessTokenMain.java
+++ b/user-interface/src/main/java/life/qbic/datamanager/views/account/PersonalAccessTokenMain.java
@@ -102,7 +102,7 @@ private void onAddTokenClicked(AddTokenEvent addTokenEvent) {
event.personalAccessTokenDTO()
.tokenDescription(), event.personalAccessTokenDTO().expirationDate());
personalAccessTokenComponent.showCreatedToken(createdToken);
- event.getSource().closeIgnoringListeners();
+ event.getSource().close();
Toast toast = messageSourceToastFactory.create("personal-access-token.created.success",
new Object[]{event.personalAccessTokenDTO().tokenDescription()}, getLocale());
toast.open();
diff --git a/user-interface/src/main/java/life/qbic/datamanager/views/account/UserProfileComponent.java b/user-interface/src/main/java/life/qbic/datamanager/views/account/UserProfileComponent.java
index 2ded9571a..07a3f62b2 100644
--- a/user-interface/src/main/java/life/qbic/datamanager/views/account/UserProfileComponent.java
+++ b/user-interface/src/main/java/life/qbic/datamanager/views/account/UserProfileComponent.java
@@ -227,7 +227,7 @@ private void openChangeUserDialog() {
private void onChangeUserDetailsDialogConfirmed(ConfirmEvent event) {
var response = identityService.requestUserNameChange(userInfo.id(), event.userName());
if (response.isSuccess()) {
- event.getSource().closeIgnoringListeners();
+ event.getSource().close();
// Trigger reload of UI reloading the username displayed in the datamanager menu
// and within this component
UI.getCurrent().getPage().reload();
diff --git a/user-interface/src/main/java/life/qbic/datamanager/views/general/QbicDialog.java b/user-interface/src/main/java/life/qbic/datamanager/views/general/QbicDialog.java
index 0a5b6f8f7..c955bb0e8 100644
--- a/user-interface/src/main/java/life/qbic/datamanager/views/general/QbicDialog.java
+++ b/user-interface/src/main/java/life/qbic/datamanager/views/general/QbicDialog.java
@@ -1,152 +1,21 @@
package life.qbic.datamanager.views.general;
-import com.vaadin.flow.component.ComponentEvent;
import com.vaadin.flow.component.Key;
import com.vaadin.flow.component.Shortcuts;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import life.qbic.datamanager.views.notifications.SupportsCloseConfirmation;
-import life.qbic.datamanager.views.notifications.WithCloseListener.CloseEvent;
/**
* A {@link com.vaadin.flow.component.dialog.Dialog} with additional functionality.
*
- * This class adds functionality to only close on user confirmation. For this simply call
- * {@link #requireCloseConfirmation()}.
*
* @see com.vaadin.flow.component.dialog.Dialog
* @since 1.4.0
*/
-public class QbicDialog extends com.vaadin.flow.component.dialog.Dialog implements
- SupportsCloseConfirmation> {
-
- private final List dialogCloseListeners = new ArrayList<>();
- private ListenerRegistration requireCloseConfirmationListener = null;
- private boolean ignoresModificationForCloseConfirmation = SupportsCloseConfirmation.super.ignoresCloseCheckIfUnmodified();
- private boolean modified = false;
+public class QbicDialog extends com.vaadin.flow.component.dialog.Dialog {
public QbicDialog() {
setCloseOnOutsideClick(false);
setCloseOnEsc(false);
- Shortcuts.addShortcutListener(this, this::close, Key.ESCAPE);
- }
-
- @Override
- public ListenerRegistration requireCloseConfirmation() {
- if (requireCloseConfirmationListener != null) {
- requireCloseConfirmationListener.listenerRemover().removeListener();
- }
- requireCloseConfirmationListener = SupportsCloseConfirmation.super.requireCloseConfirmation();
- return requireCloseConfirmationListener;
- }
-
- /**
- * Remove required close confirmation. Can be used to revert {@link #requireCloseConfirmation()}
- *
- * @since 1.4.0
- */
- public void allowCloseWithoutConfirmation() {
- if (Objects.nonNull(requireCloseConfirmationListener)) {
- requireCloseConfirmationListener.listenerRemover().removeListener();
- }
- }
-
- /**
- * Add a listener that controls whether the dialog closes or not. The listener is informed when
- * the dialog is requested to close. Then you can decide whether to close or to keep opened the
- * dialog. It means that dialog won't closed unless you call the {@link #closeIgnoringListeners()}
- * method explicitly in the listener implementation.
- *
- * NOTE:
- * Adding this listener changes behavior of the dialog.
- *
- * If there are no close listeners present, the {@link #close()} method closes the dialog.
- * Otherwise, the existing close listeners will prevent {@link #close()} from closing the dialog.
- * The listeners should call the {@link #closeIgnoringListeners()} method to close the dialog
- * instead.
- *
- * @param listener the listener to add
- * @return the resulting
- * {@link life.qbic.datamanager.views.notifications.WithCloseListener.ListenerRegistration}
- */
- @Override
- public ListenerRegistration addCloseListener(
- DialogCloseListener> listener) {
- com.vaadin.flow.shared.Registration registration = addListener(DialogCloseEvent.class,
- listener::onClose);
-
- ListenerRegistration listenerRegistration = new ListenerRegistration(listener,
- registration::remove);
- dialogCloseListeners.add(listenerRegistration);
- return listenerRegistration;
- }
-
- @Override
- public boolean ignoresCloseCheckIfUnmodified() {
- return this.ignoresModificationForCloseConfirmation;
- }
-
- /**
- * Sets whether unmodified dialogs require close confirmation.
- *
- * @param ignore should missing modification ignore the close check?
- * @param the class from which the method is called.
- * @return the modified dialog
- */
- public S setIgnoreCloseCheckIfUnmodified(boolean ignore) {
- this.ignoresModificationForCloseConfirmation = ignore;
- return (S) this;
- }
-
- @Override
- public boolean wasModified() {
- return modified;
- }
-
- @Override
- public void setModified(boolean modified) {
- this.modified = modified;
- }
-
- /**
- * @see #close()
- */
- @Override
- public void closeIgnoringListeners() {
- super.close();
- }
-
- /**
- * Closes the dialog if no close listeners are present.
- *
- *
- * If there are close listeners, instead of closing the dialog, a {@link DialogCloseEvent} is
- * fired.
- */
- @Override
- public void close() {
- if (dialogCloseListeners.isEmpty()) {
- closeIgnoringListeners();
- return;
- }
- fireEvent(new DialogCloseEvent(this, false));
- }
-
- public static class DialogCloseEvent extends ComponentEvent implements
- CloseEvent {
-
- /**
- * Creates a new event using the given source and indicator whether the event originated from
- * the client side or the server side.
- *
- * @param source the source component
- * @param fromClient true
if the event originated from the client
- * side, false
otherwise
- */
- public DialogCloseEvent(QbicDialog source, boolean fromClient) {
- super(source, fromClient);
- }
-
+ Shortcuts.addShortcutListener(this, this::close,
+ Key.ESCAPE); //overwrite to point to close method instead
}
}
diff --git a/user-interface/src/main/java/life/qbic/datamanager/views/general/WizardDialogWindow.java b/user-interface/src/main/java/life/qbic/datamanager/views/general/WizardDialogWindow.java
index efe28959c..bc1a9e708 100644
--- a/user-interface/src/main/java/life/qbic/datamanager/views/general/WizardDialogWindow.java
+++ b/user-interface/src/main/java/life/qbic/datamanager/views/general/WizardDialogWindow.java
@@ -38,7 +38,7 @@ protected WizardDialogWindow() {
* @since 1.0.0
*/
protected void onFinishClicked(ClickEvent clickEvent) {
- this.closeIgnoringListeners();
+ close();
}
/**
diff --git a/user-interface/src/main/java/life/qbic/datamanager/views/navigation/ProjectSideNavigationComponent.java b/user-interface/src/main/java/life/qbic/datamanager/views/navigation/ProjectSideNavigationComponent.java
index 38f173beb..c130c1ea2 100644
--- a/user-interface/src/main/java/life/qbic/datamanager/views/navigation/ProjectSideNavigationComponent.java
+++ b/user-interface/src/main/java/life/qbic/datamanager/views/navigation/ProjectSideNavigationComponent.java
@@ -328,7 +328,7 @@ private void showAddExperimentDialog() {
private void onExperimentAddEvent(ExperimentAddEvent event) {
ProjectId projectId = context.projectId().orElseThrow();
ExperimentId createdExperiment = createExperiment(projectId, event.getExperimentDraft());
- event.getSource().closeIgnoringListeners();
+ event.getSource().close();
displayExperimentCreationSuccess(event.getExperimentDraft().getExperimentName());
routeToExperiment(createdExperiment);
}
diff --git a/user-interface/src/main/java/life/qbic/datamanager/views/notifications/CancelConfirmationDialogFactory.java b/user-interface/src/main/java/life/qbic/datamanager/views/notifications/CancelConfirmationDialogFactory.java
new file mode 100644
index 000000000..b85938a5a
--- /dev/null
+++ b/user-interface/src/main/java/life/qbic/datamanager/views/notifications/CancelConfirmationDialogFactory.java
@@ -0,0 +1,98 @@
+package life.qbic.datamanager.views.notifications;
+
+import com.vaadin.flow.component.Html;
+import com.vaadin.flow.component.button.Button;
+import com.vaadin.flow.component.confirmdialog.ConfirmDialog.ConfirmEvent;
+import com.vaadin.flow.component.html.Span;
+import java.util.Locale;
+import java.util.function.Consumer;
+import life.qbic.logging.api.Logger;
+import life.qbic.logging.service.LoggerFactory;
+import org.springframework.context.MessageSource;
+import org.springframework.context.NoSuchMessageException;
+import org.springframework.stereotype.Component;
+
+@Component
+public class CancelConfirmationDialogFactory {
+
+ private static final MessageType DEFAULT_MESSAGE_TYPE = MessageType.HTML; //set to html as text works with it too
+ private static final String DEFAULT_TITLE = "Discard Changes?";
+ private static final String DEFAULT_CONTENT = "By aborting the editing process and closing the dialog, you will loose all information entered.";
+ private static final String DEFAULT_CONFIRM_TEXT = "Discard Changes";
+ private static final Object[] EMPTY_PARAMETERS = new Object[]{};
+ private final MessageSource messageSource;
+
+ private static final Logger log = LoggerFactory.logger(CancelConfirmationDialogFactory.class);
+
+
+ public CancelConfirmationDialogFactory(MessageSource messageSource) {
+ this.messageSource = messageSource;
+ }
+
+ public NotificationDialog cancelConfirmationDialog(Consumer onCancelConfirmed,
+ String key, Locale locale) {
+ String title = parseTitle(key, locale);
+ MessageType contentType = parseMessageType(key, locale);
+ String contentText = parseMessageText(key, locale);
+ String confirmText = parseConfirmText(key, locale);
+ var content = createContentComponent(contentType, contentText);
+
+ NotificationDialog confirmCancelDialog = NotificationDialog.warningDialog()
+ .withTitle(title)
+ .withContent(content);
+ confirmCancelDialog.setCancelable(true);
+ confirmCancelDialog.setCancelText("Continue Editing");
+ Button redButton = new Button(confirmText);
+ redButton.addClassName("danger");
+ confirmCancelDialog.setConfirmButton(redButton);
+
+ confirmCancelDialog.addCancelListener(event -> event.getSource().close());
+
+ confirmCancelDialog.addConfirmListener(event -> {
+ event.getSource().close();
+ onCancelConfirmed.accept(event);
+ });
+ return confirmCancelDialog;
+
+ }
+
+ private static com.vaadin.flow.component.Component createContentComponent(MessageType contentType,
+ String contentText) {
+ return switch (contentType) {
+ case HTML -> new Html("%s
".formatted(contentText));
+ case TEXT -> new Span(contentText);
+ };
+ }
+
+ private String parseConfirmText(String key, Locale locale) {
+ return messageSource.getMessage("%s.cancel-confirmation.confirm-text".formatted(key),
+ new Object[]{}, DEFAULT_CONFIRM_TEXT, locale);
+ }
+
+ private String parseMessageText(String key, Locale locale) {
+ return messageSource.getMessage("%s.cancel-confirmation.message.text".formatted(key),
+ new Object[]{}, DEFAULT_CONTENT, locale);
+ }
+
+ private String parseTitle(String key, Locale locale) {
+ return messageSource.getMessage("%s.cancel-confirmation.title".formatted(key),
+ new Object[]{}, DEFAULT_TITLE, locale);
+ }
+
+ private MessageType parseMessageType(String key, Locale locale) {
+ try {
+ String messageType = messageSource.getMessage(
+ "%s.cancel-confirmation.message.type".formatted(key),
+ EMPTY_PARAMETERS, locale).strip().toUpperCase();
+ return MessageType.valueOf(messageType);
+ } catch (NoSuchMessageException e) {
+ log.error("No message type specified for %s." + key, e);
+ return DEFAULT_MESSAGE_TYPE;
+ }
+ }
+
+ private enum MessageType {
+ HTML,
+ TEXT
+ }
+}
diff --git a/user-interface/src/main/java/life/qbic/datamanager/views/notifications/CloseableWithoutListeners.java b/user-interface/src/main/java/life/qbic/datamanager/views/notifications/CloseableWithoutListeners.java
deleted file mode 100644
index 6024dd4f7..000000000
--- a/user-interface/src/main/java/life/qbic/datamanager/views/notifications/CloseableWithoutListeners.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package life.qbic.datamanager.views.notifications;
-
-/**
- * Can close without triggering any close listeners.
- *
- * Intended to be used together with {@link WithCloseListener}.
- */
-public interface CloseableWithoutListeners {
-
- /**
- * Close this without triggering
- * {@link life.qbic.datamanager.views.notifications.WithCloseListener.DialogCloseListener}s.
- */
- void closeIgnoringListeners();
-
-}
diff --git a/user-interface/src/main/java/life/qbic/datamanager/views/notifications/SupportsCloseConfirmation.java b/user-interface/src/main/java/life/qbic/datamanager/views/notifications/SupportsCloseConfirmation.java
deleted file mode 100644
index b0b799cd7..000000000
--- a/user-interface/src/main/java/life/qbic/datamanager/views/notifications/SupportsCloseConfirmation.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package life.qbic.datamanager.views.notifications;
-
-import com.vaadin.flow.component.ComponentEventListener;
-import com.vaadin.flow.component.button.Button;
-import com.vaadin.flow.component.confirmdialog.ConfirmDialog;
-import com.vaadin.flow.component.html.Span;
-import life.qbic.datamanager.views.notifications.WithCloseListener.CloseEvent;
-
-/**
- * Supports close only after confirmation
- *
- * This interface adds functionality to ask for confirmation after a close event is fired.
- * Implementing classes can modify the behaviour by providing their own implementation of
- *
- * {@link #getCloseConfirmationDialog()} - change the confirm dialog shown to ask for confirmation.
- * {@link #ignoresCloseCheckIfUnmodified()} - if {@code true} only asks for user confirmation if {@link TracksModification#wasModified()} is true
- * {@link #requireCloseConfirmation()} - needs to be called to require the close confirmation
- * {@link #onCloseActionConfirmed()} - defines what needs to be done after user confirmation of the close action
- *
- *
- * @since 1.4.0
- */
-
-public interface SupportsCloseConfirmation> extends
- WithCloseListener, CloseableWithoutListeners, TracksModification {
-
- /**
- * The dialog used to confirm close actions. It does not need
- * {@link ConfirmDialog#addConfirmListener(ComponentEventListener)}.
- *
- * @return a {@link ConfirmDialog} used to confirm closing.
- * @since 1.4.0
- */
- default ConfirmDialog getCloseConfirmationDialog() {
- return getDefaultCloseConfirmationDialog();
- }
-
- private ConfirmDialog getDefaultCloseConfirmationDialog() {
- NotificationDialog dialog = NotificationDialog.warningDialog().withTitle("Discard Changes?")
- .withContent(new Span(
- "By aborting the editing process and closing the dialog, you will loose all information entered."));
- dialog.setCancelable(true);
- dialog.setCancelText("Continue Editing");
- Button redButton = new Button("Discard Changes");
- redButton.addClassName("danger");
- dialog.setConfirmButton(redButton);
-
- return dialog;
- }
-
- /**
- * Should the user be asked to confirm closing even if {@link #wasModified()} is false?
- *
- * @return true if {@link #requireCloseConfirmation()} should not trigger if
- * {@link #wasModified()} is false; returns false if {@link #wasModified()} should be ignored for
- * user confirmation.
- * @since 1.4.0
- */
- default boolean ignoresCloseCheckIfUnmodified() {
- return false;
- }
-
- /**
- * Registers a close listener and asks for close confirmation.
- *
- * @return the
- * {@link life.qbic.datamanager.views.notifications.WithCloseListener.ListenerRegistration} of the
- * close listener that can be used to remove the listener again.
- * @since 1.4.0
- */
- default ListenerRegistration requireCloseConfirmation() {
- return this.addCloseListener(closeEvent -> askForConfirmation());
- }
-
-
- /**
- * Asks for close confirmation using the {@link #getCloseConfirmationDialog()} dialog. If the user
- * confirmed, executes {@link #onCloseActionConfirmed()}
- *
- * @since 1.4.0
- */
- private void askForConfirmation() {
-
- if (ignoresCloseCheckIfUnmodified() && !wasModified()) {
- onCloseActionConfirmed();
- return;
- }
-
- ConfirmDialog cancelConfirmationDialog = getCloseConfirmationDialog();
-
- cancelConfirmationDialog.addConfirmListener(confirmEvent -> onCloseActionConfirmed());
- cancelConfirmationDialog.open();
- }
-
- /**
- * Executed upon user confirmation of close action. Should probably continue the close.
- *
- * @since 1.4.0
- */
- default void onCloseActionConfirmed() {
- closeIgnoringListeners();
- }
-}
diff --git a/user-interface/src/main/java/life/qbic/datamanager/views/notifications/TracksModification.java b/user-interface/src/main/java/life/qbic/datamanager/views/notifications/TracksModification.java
deleted file mode 100644
index 2dc0734b4..000000000
--- a/user-interface/src/main/java/life/qbic/datamanager/views/notifications/TracksModification.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package life.qbic.datamanager.views.notifications;
-
-/**
- * This class tracks whether it was modified.
- */
-public interface TracksModification {
-
- /**
- * Was this instance modified?
- *
- * @return true if modified; false otherwise
- */
- boolean wasModified();
-
- /**
- * Set the modification state.
- *
- * @param modified was this instance modified?
- */
- void setModified(boolean modified);
-}
diff --git a/user-interface/src/main/java/life/qbic/datamanager/views/notifications/WithCloseListener.java b/user-interface/src/main/java/life/qbic/datamanager/views/notifications/WithCloseListener.java
deleted file mode 100644
index 3f475266e..000000000
--- a/user-interface/src/main/java/life/qbic/datamanager/views/notifications/WithCloseListener.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package life.qbic.datamanager.views.notifications;
-
-import com.vaadin.flow.component.dialog.Dialog;
-import java.io.Serializable;
-import life.qbic.datamanager.views.notifications.WithCloseListener.CloseEvent;
-
-/**
- * Listens for close events
- *
- * This interface can be used as replacement for
- * {@link com.vaadin.flow.component.dialog.Dialog.DialogCloseActionEvent}. In contrast to the
- * component listener based solution provided by vaadin, implementing classes are free to implement
- * and fire the close event any way they want.
- *
- * The vaadin solution does not cover all instances of closing a dialog. If a dialog is closed based
- * on a call to {@link Dialog#close()}, then no
- * {@link com.vaadin.flow.component.dialog.Dialog.DialogCloseActionEvent} is fired. This interface
- * thus acts as an addition filling this gap if a dialog close event is fired in the close method.
- *
- * @since 1.4.0
- */
-public interface WithCloseListener> {
-
- /**
- * Add a listener that is informed when something is deemed to be closed.
- *
- * In combination with the {@link CloseableWithoutListeners} interface and some custom logic in
- * implementing classes, the listener can be used to catch close events. The listener is informed
- * when the dialog is requested to close. Then you can decide whether to close or to keep opened
- * the dialog. It means that dialog won't close unless you call the
- * {@link CloseableWithoutListeners#closeIgnoringListeners()} method explicitly in the listener
- * implementation.
- *
- * @param listener the listener to add
- * @return the resulting
- * {@link life.qbic.datamanager.views.notifications.WithCloseListener.ListenerRegistration}
- */
- ListenerRegistration addCloseListener(DialogCloseListener listener);
-
- /**
- * A listener for close events.
- *
- * @param the component acting as source of the close event.
- * @param the close event to listen to.
- * @since 1.4.0
- */
- @FunctionalInterface
- interface DialogCloseListener> {
-
- /**
- * Action performed whenever the listener is triggered.
- *
- * @param closeEvent the event to consume.
- * @since 1.4.0
- */
- void onClose(T closeEvent);
-
- }
-
- /**
- * Adds functionality to remove an added listener.
- *
- * @since 1.4.0
- */
- @FunctionalInterface
- interface ListenerRemover {
-
- /**
- * An action that should remove the listener.
- *
- * @since 1.4.0
- */
- void removeListener();
- }
-
- /**
- * A listener registration. Contains the registered listener as well as a way to remove the
- * listener again.
- *
- * @param listener the registered listener
- * @param listenerRemover an action removing the listener
- */
- record ListenerRegistration(DialogCloseListener, ?> listener,
- ListenerRemover listenerRemover) implements
- Serializable {
-
- }
-
- /**
- * An event fired when some close action occurs.
- *
- * @param the source component class
- * @since 1.4.0
- */
- interface CloseEvent {
-
- C getSource();
-
- boolean isFromClient();
- }
-}
diff --git a/user-interface/src/main/java/life/qbic/datamanager/views/projects/create/AddProjectDialog.java b/user-interface/src/main/java/life/qbic/datamanager/views/projects/create/AddProjectDialog.java
index f81a8539d..6a28c6e3c 100644
--- a/user-interface/src/main/java/life/qbic/datamanager/views/projects/create/AddProjectDialog.java
+++ b/user-interface/src/main/java/life/qbic/datamanager/views/projects/create/AddProjectDialog.java
@@ -26,6 +26,8 @@
import life.qbic.datamanager.views.general.Stepper.StepIndicator;
import life.qbic.datamanager.views.general.contact.Contact;
import life.qbic.datamanager.views.general.funding.FundingEntry;
+import life.qbic.datamanager.views.notifications.CancelConfirmationDialogFactory;
+import life.qbic.datamanager.views.notifications.NotificationDialog;
import life.qbic.datamanager.views.projects.create.CollaboratorsLayout.ProjectCollaborators;
import life.qbic.datamanager.views.projects.create.ExperimentalInformationLayout.ExperimentalInformation;
import life.qbic.datamanager.views.projects.create.ProjectDesignLayout.ProjectDesign;
@@ -61,7 +63,7 @@ public class AddProjectDialog extends QbicDialog {
private final Button nextButton;
private final Map stepContent;
- private final TerminologyService terminologyService;
+ private final CancelConfirmationDialogFactory cancelConfirmationDialogFactory;
private StepIndicator addStep(Stepper stepper, String label, Component layout) {
@@ -72,16 +74,17 @@ private StepIndicator addStep(Stepper stepper, String label, Component layout) {
public AddProjectDialog(ProjectInformationService projectInformationService,
FinanceService financeService,
SpeciesLookupService speciesLookupService,
- ContactRepository contactRepository, TerminologyService terminologyService) {
+ ContactRepository contactRepository, TerminologyService terminologyService,
+ CancelConfirmationDialogFactory cancelConfirmationDialogFactory) {
super();
- requireCloseConfirmation();
- setIgnoreCloseCheckIfUnmodified(false);
addClassName("add-project-dialog");
requireNonNull(projectInformationService, "project information service must not be null");
requireNonNull(financeService, "financeService must not be null");
requireNonNull(speciesLookupService,
"ontologyTermInformationService must not be null");
+ this.cancelConfirmationDialogFactory = requireNonNull(cancelConfirmationDialogFactory,
+ "cancelConfirmationDialogFactory must not be null");
this.projectDesignLayout = new ProjectDesignLayout(projectInformationService, financeService);
this.fundingInformationLayout = new FundingInformationLayout();
this.collaboratorsLayout = new CollaboratorsLayout();
@@ -145,7 +148,6 @@ public AddProjectDialog(ProjectInformationService projectInformationService,
rightButtons.add(cancelButton, nextButton, confirmButton);
footer.add(backButton, rightButtons);
adaptFooterButtons(stepper.getFirstStep());
- this.terminologyService = terminologyService;
}
/**
@@ -156,7 +158,9 @@ public void enableOfferSearch() {
}
private void onCancelClicked(ClickEvent clickEvent) {
- close();
+ NotificationDialog cancelConfirmationDialog = cancelConfirmationDialogFactory.cancelConfirmationDialog(
+ it -> close(), "create-project", getLocale());
+ cancelConfirmationDialog.open();
}
private void onConfirmClicked(ClickEvent event) {
diff --git a/user-interface/src/main/java/life/qbic/datamanager/views/projects/overview/ProjectOverviewMain.java b/user-interface/src/main/java/life/qbic/datamanager/views/projects/overview/ProjectOverviewMain.java
index 79b90610d..d59ca3a21 100644
--- a/user-interface/src/main/java/life/qbic/datamanager/views/projects/overview/ProjectOverviewMain.java
+++ b/user-interface/src/main/java/life/qbic/datamanager/views/projects/overview/ProjectOverviewMain.java
@@ -20,6 +20,7 @@
import life.qbic.datamanager.views.UserMainLayout;
import life.qbic.datamanager.views.general.Main;
import life.qbic.datamanager.views.general.contact.Contact;
+import life.qbic.datamanager.views.notifications.CancelConfirmationDialogFactory;
import life.qbic.datamanager.views.notifications.StyledNotification;
import life.qbic.datamanager.views.notifications.SuccessMessage;
import life.qbic.datamanager.views.projects.create.AddProjectDialog;
@@ -63,7 +64,6 @@ public class ProjectOverviewMain extends Main {
private final transient ContactRepository contactRepository;
private final transient UserInformationService userInformationService;
private final transient AuthenticationToUserIdTranslationService userIdTranslator;
- private final TerminologyService terminologyService;
public ProjectOverviewMain(@Autowired ProjectCollectionComponent projectCollectionComponent,
ProjectCreationService projectCreationService, FinanceService financeService,
@@ -73,7 +73,8 @@ public ProjectOverviewMain(@Autowired ProjectCollectionComponent projectCollecti
UserInformationService userInformationService,
ContactRepository contactRepository,
AuthenticationToUserIdTranslationService userIdTranslator,
- TerminologyService terminologyService) {
+ TerminologyService terminologyService,
+ CancelConfirmationDialogFactory cancelConfirmationDialogFactory) {
this.projectCollectionComponent = requireNonNull(projectCollectionComponent,
"project collection component can not be null");
this.projectCreationService = requireNonNull(projectCreationService,
@@ -90,14 +91,17 @@ public ProjectOverviewMain(@Autowired ProjectCollectionComponent projectCollecti
this.userInformationService = requireNonNull(userInformationService,
"user information service can not be null");
this.userIdTranslator = requireNonNull(userIdTranslator, "userIdTranslator must not be null");
- this.terminologyService = requireNonNull(terminologyService);
+ requireNonNull(terminologyService, "terminologyService must not be null");
+ requireNonNull(cancelConfirmationDialogFactory,
+ "cancelConfirmationDialogFactory must not be null");
addTitleAndDescription();
add(projectCollectionComponent);
this.projectCollectionComponent.addCreateClickedListener(projectCreationClickedEvent -> {
AddProjectDialog addProjectDialog = new AddProjectDialog(this.projectInformationService,
this.financeService,
- this.ontologyTermInformationService, this.contactRepository, terminologyService);
+ this.ontologyTermInformationService, this.contactRepository, terminologyService,
+ cancelConfirmationDialogFactory);
if (isOfferSearchAllowed()) {
addProjectDialog.enableOfferSearch();
}
@@ -179,7 +183,8 @@ private void createProject(ConfirmEvent confirmEvent) {
private void onProjectCreated(ConfirmEvent confirmEvent) {
displaySuccessfulProjectCreationNotification();
- confirmEvent.getSource().closeIgnoringListeners();
+ confirmEvent.getSource().close();
+
projectCollectionComponent.refresh();
projectCollectionComponent.resetSearch();
}
diff --git a/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/access/ProjectAccessComponent.java b/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/access/ProjectAccessComponent.java
index 153f6c8aa..4dcb045d5 100644
--- a/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/access/ProjectAccessComponent.java
+++ b/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/access/ProjectAccessComponent.java
@@ -334,7 +334,7 @@ private void onAddCollaboratorConfirmed(ConfirmEvent event) {
event.projectCollaborator()
.userId(), event.projectCollaborator().projectRole());
refreshProjectUserGrid();
- event.getSource().closeIgnoringListeners();
+ event.getSource().close();
}
private void displayError(String title, String description) {
diff --git a/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/experiments/experiment/ExperimentDetailsComponent.java b/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/experiments/experiment/ExperimentDetailsComponent.java
index 108ad1a46..723bef87f 100644
--- a/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/experiments/experiment/ExperimentDetailsComponent.java
+++ b/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/experiments/experiment/ExperimentDetailsComponent.java
@@ -269,7 +269,7 @@ private void onExperimentUpdateEvent(ExperimentUpdateEvent event) {
experimentDraft.getSpeciesIcon().getLabel(),
experimentDraft.getSpecimenIcon().getLabel());
reloadExperimentInfo(experimentId);
- event.getSource().closeIgnoringListeners();
+ event.getSource().close();
}
private void listenForExperimentalVariablesComponentEvents() {
@@ -305,7 +305,7 @@ private void openExperimentalVariablesAddDialog() {
private void onExperimentalVariablesAddConfirmed(
ExperimentalVariablesDialog.ConfirmEvent confirmEvent) {
addExperimentalVariables(confirmEvent.getSource().definedVariables());
- confirmEvent.getSource().closeIgnoringListeners();
+ confirmEvent.getSource().close();
reloadExperimentInfo(context.experimentId().orElseThrow());
if (hasExperimentalGroups()) {
showSampleRegistrationPossibleNotification();
@@ -329,7 +329,7 @@ private void onExperimentalVariablesEditConfirmed(
ExperimentalVariablesDialog.ConfirmEvent confirmEvent) {
deleteExistingExperimentalVariables();
addExperimentalVariables(confirmEvent.getSource().definedVariables());
- confirmEvent.getSource().closeIgnoringListeners();
+ confirmEvent.getSource().close();
reloadExperimentInfo(context.experimentId().orElseThrow());
}
@@ -475,7 +475,7 @@ private void onExperimentalGroupAddConfirmed(
addExperimentalGroups(groupContents);
reloadExperimentalGroups();
- dialog.closeIgnoringListeners();
+ dialog.close();
}
}
@@ -508,7 +508,7 @@ private void onExperimentalGroupEditConfirmed(
experimentInformationService.updateExperimentalGroupsOfExperiment(
context.projectId().orElseThrow().value(), experimentId, groupDTOs);
reloadExperimentalGroups();
- confirmEvent.getSource().closeIgnoringListeners();
+ confirmEvent.getSource().close();
}
}
diff --git a/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/experiments/experiment/components/ExperimentalGroupsDialog.java b/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/experiments/experiment/components/ExperimentalGroupsDialog.java
index 5ebd5879b..e35406383 100644
--- a/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/experiments/experiment/components/ExperimentalGroupsDialog.java
+++ b/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/experiments/experiment/components/ExperimentalGroupsDialog.java
@@ -39,7 +39,6 @@ private ExperimentalGroupsDialog(Collection experimentalVariableL
this.editMode = editMode;
this.experimentalVariableLevels = Objects.requireNonNull(experimentalVariableLevels);
layoutComponent();
- requireCloseConfirmation();
}
private ExperimentalGroupsDialog(Collection experimentalVariableLevels,
diff --git a/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/experiments/experiment/components/ExperimentalVariablesDialog.java b/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/experiments/experiment/components/ExperimentalVariablesDialog.java
index 17ec65805..49b6335d3 100644
--- a/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/experiments/experiment/components/ExperimentalVariablesDialog.java
+++ b/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/experiments/experiment/components/ExperimentalVariablesDialog.java
@@ -208,12 +208,6 @@ public List definedVariables() {
.toList();
}
- @Override
- public void closeIgnoringListeners() {
- reset();
- super.closeIgnoringListeners();
- }
-
@DomEvent("confirm")
public static class ConfirmEvent extends
diff --git a/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/experiments/experiment/create/AddExperimentDialog.java b/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/experiments/experiment/create/AddExperimentDialog.java
index a90818b0e..01890fe91 100644
--- a/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/experiments/experiment/create/AddExperimentDialog.java
+++ b/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/experiments/experiment/create/AddExperimentDialog.java
@@ -138,12 +138,6 @@ public void setExperiment(ExperimentDraft experiment) {
binder.setBean(experiment);
}
- @Override
- public void closeIgnoringListeners() {
- super.closeIgnoringListeners();
- reset();
- }
-
public void reset() {
binder.setBean(new ExperimentDraft());
}
diff --git a/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/experiments/experiment/update/EditExperimentDialog.java b/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/experiments/experiment/update/EditExperimentDialog.java
index 9102aef80..4d8c1ddb1 100644
--- a/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/experiments/experiment/update/EditExperimentDialog.java
+++ b/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/experiments/experiment/update/EditExperimentDialog.java
@@ -176,18 +176,18 @@ protected void onCancelClicked(ClickEvent clickEvent) {
close();
}
+ @Override
+ public void close() {
+ super.close();
+ reset();
+ }
+
public void setExperiment(ExperimentDraft experiment,
Map> usedTerms) {
this.usedSampleOrigins = usedTerms;
binder.setBean(experiment);
}
- @Override
- public void closeIgnoringListeners() {
- super.closeIgnoringListeners();
- reset();
- }
-
public void reset() {
binder.setBean(new ExperimentDraft());
}
diff --git a/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/info/ProjectDetailsComponent.java b/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/info/ProjectDetailsComponent.java
index 380a70a10..047be68ba 100644
--- a/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/info/ProjectDetailsComponent.java
+++ b/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/info/ProjectDetailsComponent.java
@@ -270,7 +270,7 @@ private void onProjectUpdateEvent(ProjectUpdateEvent projectUpdateEvent) {
ProjectId projectId = context.projectId().orElseThrow();
fireEvent(new ProjectEditEvent(this, projectId, projectUpdateEvent.isFromClient()));
}
- projectUpdateEvent.getSource().closeIgnoringListeners();
+ projectUpdateEvent.getSource().close();
}
private void updateProjectInformation(ProjectInformation projectInformationContent) {
diff --git a/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/info/ProjectInformationMain.java b/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/info/ProjectInformationMain.java
index 3ab7c7f08..861479176 100644
--- a/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/info/ProjectInformationMain.java
+++ b/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/info/ProjectInformationMain.java
@@ -23,7 +23,6 @@
import life.qbic.datamanager.views.general.download.QualityControlDownload;
import life.qbic.datamanager.views.notifications.toasts.MessageSourceToastFactory;
import life.qbic.datamanager.views.notifications.toasts.Toast;
-import life.qbic.datamanager.views.notifications.toasts.MessageSourceToastFactory;
import life.qbic.datamanager.views.projects.project.ProjectMainLayout;
import life.qbic.datamanager.views.projects.project.experiments.ExperimentInformationMain;
import life.qbic.datamanager.views.projects.project.experiments.ExperimentListComponent;
@@ -213,7 +212,7 @@ private void onUploadOfferClicked(UploadOfferClickEvent uploadOfferClickEvent,
.toList();
projectPurchaseService.addPurchases(projectId, offerDTOs);
refreshOffers(projectPurchaseService, projectId, uploadOfferClickEvent.getSource());
- confirmEvent.getSource().closeIgnoringListeners();
+ confirmEvent.getSource().close();
});
dialog.addCancelListener(cancelEvent -> cancelEvent.getSource().close());
dialog.open();
@@ -260,7 +259,7 @@ private void onUploadQualityControlClicked() {
qualityControlService.addQualityControls(context.projectId().orElseThrow().toString(),
qualityControlReports);
refreshQualityControls();
- confirmEvent.getSource().closeIgnoringListeners();
+ confirmEvent.getSource().close();
});
dialog.addCancelListener(cancelEvent -> cancelEvent.getSource().close());
dialog.open();
@@ -307,7 +306,7 @@ private void setContext(Context context) {
private void onExperimentAddEvent(ExperimentAddEvent event) {
ProjectId projectId = context.projectId().orElseThrow();
ExperimentId createdExperiment = createExperiment(projectId, event.getExperimentDraft());
- event.getSource().closeIgnoringListeners();
+ event.getSource().close();
displayExperimentCreationSuccess(event.getExperimentDraft().getExperimentName());
routeToExperiment(createdExperiment);
}
diff --git a/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/samples/SampleInformationMain.java b/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/samples/SampleInformationMain.java
index fc05e0efb..8eda33fd3 100644
--- a/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/samples/SampleInformationMain.java
+++ b/user-interface/src/main/java/life/qbic/datamanager/views/projects/project/samples/SampleInformationMain.java
@@ -229,7 +229,7 @@ private void registerBatch(ConfirmEvent confirmEvent) {
context.projectId().orElseThrow())
.onError(responseCode -> displayRegistrationFailure())
.onValue(ignored -> fireEvent(new BatchRegisteredEvent(this, false)))
- .onValue(ignored -> confirmEvent.getSource().closeIgnoringListeners())
+ .onValue(ignored -> confirmEvent.getSource().close())
.onValue(batchId -> displayRegistrationSuccess())
.onValue(ignored -> setBatchAndSampleInformation());
}
@@ -375,7 +375,7 @@ private void editBatch(EditBatchDialog.ConfirmEvent confirmEvent) {
var result = batchRegistrationService.editBatch(confirmEvent.getData().batchId(),
confirmEvent.getData().batchName(), isPilot, createdSamples, editedSamples,
deletedSamples, context.projectId().orElseThrow());
- result.onValue(ignored -> confirmEvent.getSource().closeIgnoringListeners());
+ result.onValue(ignored -> confirmEvent.getSource().close());
result.onValue(batchId -> displayUpdateSuccess());
result.onValue(ignored -> setBatchAndSampleInformation());
}
diff --git a/user-interface/src/main/resources/application.properties b/user-interface/src/main/resources/application.properties
index ca4173d4d..b352f6da4 100644
--- a/user-interface/src/main/resources/application.properties
+++ b/user-interface/src/main/resources/application.properties
@@ -171,7 +171,7 @@ terminology.service.tib.endpoint.search=${TIB_SERVICE_API_SEARCH_ENDPOINT:/ts4ti
spring.messages.encoding=UTF-8
spring.messages.cache-duration=1s
spring.messages.fallback-to-system-locale=true
-spring.messages.basename=messages.error-messages, messages.toast-notifications
+spring.messages.basename=messages.error-messages, messages.toast-notifications, messages.dialog-messages
# you always have to escape single quotes by another single quote ' -> ''
# https://www.mscharhag.com/java/resource-bundle-single-quote-escaping for reference
spring.messages.always-use-message-format=true
diff --git a/user-interface/src/main/resources/messages/dialog-messages.properties b/user-interface/src/main/resources/messages/dialog-messages.properties
new file mode 100644
index 000000000..aa73dd134
--- /dev/null
+++ b/user-interface/src/main/resources/messages/dialog-messages.properties
@@ -0,0 +1,11 @@
+############### Configuration of dialog text ###############
+### Cancel Confirmation
+# Sometimes you want to support cancel confirmation for dialogs. You can choose to customize the
+# text shown in the cancel confirmation dialog.
+## (dialog-key).cancel-confirmation.message.type -> can be text or html. MUST BE PROVIDED
+## (dialog-key).cancel-confirmation.message.text -> the text or html to display
+## (dialog-key).cancel-confirmation.confirm-text -> the text on the button that confirms the cancel operation
+create-project.cancel-confirmation.title=Discard new project creation?
+create-project.cancel-confirmation.message.type=text
+create-project.cancel-confirmation.message.text=You will lose all the information entered for this project.
+create-project.cancel-confirmation.confirm-text=Discard project creation
diff --git a/user-interface/src/main/resources/messages/toast-notifications.properties b/user-interface/src/main/resources/messages/toast-notifications.properties
index c02ffe37f..b053318f2 100644
--- a/user-interface/src/main/resources/messages/toast-notifications.properties
+++ b/user-interface/src/main/resources/messages/toast-notifications.properties
@@ -10,8 +10,6 @@
## (.routing.link.text) The text to show as link
# foo.bar.routing.link.text=Go to Samples
############### Optional properties
-## (.closeable) Whether the notification should be closeable
-# foo.bar.closeable=true
## (.duration) Duration on how long to keep the notification open. Specified in ISO-8601 format
# foo.bar.duration=PT1m # for one minute
# foo.bar.duration=PT1s # for one second