diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/UploadArtifactView.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/UploadArtifactView.java index af2b8ca08..92911e6b1 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/UploadArtifactView.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/UploadArtifactView.java @@ -8,6 +8,8 @@ */ package org.eclipse.hawkbit.ui.artifacts; +import static org.eclipse.hawkbit.ui.artifacts.upload.FileUploadProgress.FileUploadStatus.UPLOAD_STARTED; + import java.util.EnumMap; import java.util.Map; @@ -24,7 +26,9 @@ import org.eclipse.hawkbit.ui.SpPermissionChecker; import org.eclipse.hawkbit.ui.artifacts.details.ArtifactDetailsGridLayout; import org.eclipse.hawkbit.ui.artifacts.smtable.SoftwareModuleGridLayout; import org.eclipse.hawkbit.ui.artifacts.smtype.filter.SMTypeFilterLayout; +import org.eclipse.hawkbit.ui.artifacts.upload.FileUploadProgress; import org.eclipse.hawkbit.ui.common.CommonUiDependencies; +import org.eclipse.hawkbit.ui.common.ConfirmationDialog; import org.eclipse.hawkbit.ui.common.event.EventLayout; import org.eclipse.hawkbit.ui.common.event.EventView; import org.eclipse.hawkbit.ui.common.event.EventViewAware; @@ -32,19 +36,26 @@ import org.eclipse.hawkbit.ui.common.layout.listener.LayoutResizeListener; import org.eclipse.hawkbit.ui.common.layout.listener.LayoutResizeListener.ResizeHandler; import org.eclipse.hawkbit.ui.common.layout.listener.LayoutVisibilityListener; import org.eclipse.hawkbit.ui.common.layout.listener.LayoutVisibilityListener.VisibilityHandler; +import org.eclipse.hawkbit.ui.menu.DashboardEvent; +import org.eclipse.hawkbit.ui.menu.DashboardMenu; +import org.eclipse.hawkbit.ui.menu.DashboardMenuItem; import org.eclipse.hawkbit.ui.utils.SPUIDefinitions; +import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider; +import org.eclipse.hawkbit.ui.utils.UIMessageIdProvider; import org.eclipse.hawkbit.ui.utils.UINotification; import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; import org.springframework.beans.factory.annotation.Autowired; import org.vaadin.spring.events.EventBus.UIEventBus; import com.vaadin.navigator.View; +import com.vaadin.navigator.ViewBeforeLeaveEvent; import com.vaadin.server.Page; import com.vaadin.server.Page.BrowserWindowResizeEvent; import com.vaadin.server.Page.BrowserWindowResizeListener; import com.vaadin.spring.annotation.SpringView; import com.vaadin.spring.annotation.UIScope; import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.UI; import com.vaadin.ui.VerticalLayout; /** @@ -63,6 +74,8 @@ public class UploadArtifactView extends VerticalLayout implements View, BrowserW private final SMTypeFilterLayout smTypeFilterLayout; private final SoftwareModuleGridLayout smGridLayout; private final ArtifactDetailsGridLayout artifactDetailsGridLayout; + private final VaadinMessageSource i18n; + private final DashboardMenu dashboardMenu; private HorizontalLayout mainLayout; @@ -74,12 +87,15 @@ public class UploadArtifactView extends VerticalLayout implements View, BrowserW final UINotification uiNotification, final ArtifactUploadState artifactUploadState, final EntityFactory entityFactory, final SoftwareModuleManagement softwareModuleManagement, final SoftwareModuleTypeManagement softwareModuleTypeManagement, - final MultipartConfigElement multipartConfigElement, final ArtifactManagement artifactManagement) { + final MultipartConfigElement multipartConfigElement, final ArtifactManagement artifactManagement, + final DashboardMenu dashboardMenu) { this.permChecker = permChecker; this.artifactUploadState = artifactUploadState; + this.i18n = i18n; + this.dashboardMenu = dashboardMenu; - final CommonUiDependencies uiDependencies = new CommonUiDependencies(i18n, entityFactory, eventBus, uiNotification, - permChecker); + final CommonUiDependencies uiDependencies = new CommonUiDependencies(i18n, entityFactory, eventBus, + uiNotification, permChecker); if (permChecker.hasReadRepositoryPermission()) { this.smTypeFilterLayout = new SMTypeFilterLayout(uiDependencies, softwareModuleTypeManagement, @@ -260,4 +276,35 @@ public class UploadArtifactView extends VerticalLayout implements View, BrowserW artifactDetailsGridLayout.unsubscribeListener(); } } + + @Override + public void beforeLeave(final ViewBeforeLeaveEvent event) { + if (isAnyUploadInUploadQueue()) { + final ConfirmationDialog confirmDeleteDialog = new ConfirmationDialog(i18n, + i18n.getMessage(UIMessageIdProvider.CAPTION_CLEAR_FILE_UPLOAD_QUEUE), + i18n.getMessage(UIMessageIdProvider.MESSAGE_CLEAR_FILE_UPLOAD_QUEUE), ok -> { + if (Boolean.TRUE.equals(ok)) { + // Clear all queued file uploads + artifactUploadState.clearFileStates(); + event.navigate(); + } else { + // Send a PostViewChangeEvent to the DashboardMenu as if the navigation actually + // happened to prevent the DashboardMenu navigation from getting stuck + final DashboardMenuItem dashboardMenuItem = dashboardMenu.getByViewName(VIEW_NAME); + dashboardMenu.postViewChange(DashboardEvent.createPostViewChangeEvent(dashboardMenuItem)); + } + }, UIComponentIdProvider.UPLOAD_QUEUE_CLEAR_CONFIRMATION_DIALOG); + UI.getCurrent().addWindow(confirmDeleteDialog.getWindow()); + confirmDeleteDialog.getWindow().bringToFront(); + } else { + event.navigate(); + } + } + + private boolean isAnyUploadInUploadQueue() { + return artifactUploadState.getAllFileUploadProgressValuesFromOverallUploadProcessList().stream() + .map(FileUploadProgress::getFileUploadStatus) + .anyMatch(fileUploadStatus -> fileUploadStatus == UPLOAD_STARTED); + } + } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/FileTransferHandlerStreamVariable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/FileTransferHandlerStreamVariable.java index 87b73e844..3556f3b08 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/FileTransferHandlerStreamVariable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/FileTransferHandlerStreamVariable.java @@ -60,7 +60,7 @@ public class FileTransferHandlerStreamVariable extends AbstractFileTransferHandl } /** - * Checks for duplication and invalid file name during feil upload process + * Checks for duplication and invalid file name during file upload process * * @param event * StreamingStartEvent diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIComponentIdProvider.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIComponentIdProvider.java index 1cbaa1487..778c7244c 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIComponentIdProvider.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIComponentIdProvider.java @@ -1498,6 +1498,11 @@ public final class UIComponentIdProvider { */ public static final String DISTRIBUTION_SET_TYPE_ID_PREFIXS = "dist.set.type"; + /** + * Id of the file upload cancel confirmation window + */ + public static final String UPLOAD_QUEUE_CLEAR_CONFIRMATION_DIALOG = "upload.queue.clear.confirmation.window"; + /** * /* Private Constructor. */ diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIMessageIdProvider.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIMessageIdProvider.java index 05e78ab42..1028aa6c9 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIMessageIdProvider.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIMessageIdProvider.java @@ -227,6 +227,8 @@ public final class UIMessageIdProvider { public static final String CAPTION_ARTIFACT_FILENAME = "artifact.filename.caption"; + public static final String CAPTION_CLEAR_FILE_UPLOAD_QUEUE = "caption.clear.file.upload.queue"; + public static final String CAPTION_ARTIFACT_FILESIZE_BYTES = "artifact.filesize.bytes.caption"; public static final String CAPTION_SOFTWARE_MODULE = "caption.software.module"; @@ -235,6 +237,8 @@ public final class UIMessageIdProvider { public static final String MESSAGE_TARGET_BULKUPLOAD_RESULT_FAIL = "message.bulk.upload.result.fail"; + public static final String MESSAGE_CLEAR_FILE_UPLOAD_QUEUE = "message.clear.file.upload.queue.confirm"; + public static final String VAADIN_SYSTEM_SESSIONEXPIRED_CAPTION = "vaadin.system.sessionexpired.caption"; public static final String VAADIN_SYSTEM_SESSIONEXPIRED_MESSAGE = "vaadin.system.sessionexpired.message"; diff --git a/hawkbit-ui/src/main/resources/messages.properties b/hawkbit-ui/src/main/resources/messages.properties index a707619ac..ea70577d9 100644 --- a/hawkbit-ui/src/main/resources/messages.properties +++ b/hawkbit-ui/src/main/resources/messages.properties @@ -161,6 +161,8 @@ caption.maintenancewindow.schedule = Schedule caption.maintenancewindow.duration = Duration caption.maintenancewindow.timezone = Time Zone (from GMT) +caption.clear.file.upload.queue = Clear file upload queue + # Labels prefix with - label label.create.filter = Create Filter label.edit.filter = Edit Filter @@ -497,6 +499,7 @@ message.key.deleted.or.notAllowed = {0} with key {0} was deleted or you are not message.forcedTime.cannotBeEmpty = Forced time can not be empty message.forcedTime.missing = Force time is not specified for the time-forced assignment message.scheduledTime.cannotBeEmpty = Scheduled time can not be empty +message.clear.file.upload.queue.confirm = There is still at least one queued file upload pending. By leaving this view the upload queue will be cleared. \nAre you sure you want to leave this view? # action info action.target.table.selectall = Select all (Ctrl+A)