From c2bf9222b7d4029c30c5c9f41db7eb913f088b61 Mon Sep 17 00:00:00 2001 From: Asharani Date: Thu, 19 May 2016 10:51:12 +0530 Subject: [PATCH] Signed-off-by: Asharani --- .../ui/artifacts/event/UploadStatusEvent.java | 2 +- .../ui/artifacts/upload/UploadHandler.java | 53 ++++++++++-- .../ui/artifacts/upload/UploadLayout.java | 5 +- .../upload/UploadStatusInfoWindow.java | 83 ++++++++++++++----- .../src/main/resources/messages.properties | 4 + .../src/main/resources/messages_de.properties | 6 +- .../src/main/resources/messages_en.properties | 5 +- 7 files changed, 123 insertions(+), 35 deletions(-) diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/UploadStatusEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/UploadStatusEvent.java index 96513a52a..8a4da9f6d 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/UploadStatusEvent.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/UploadStatusEvent.java @@ -15,7 +15,7 @@ package org.eclipse.hawkbit.ui.artifacts.event; public class UploadStatusEvent { public enum UploadStatusEventType { - UPLOAD_FAILED, UPLOAD_IN_PROGRESS, UPLOAD_STARTED, UPLOAD_FINISHED, UPLOAD_SUCCESSFUL, UPLOAD_STREAMING_FAILED, UPLOAD_STREAMING_FINISHED + UPLOAD_FAILED, UPLOAD_IN_PROGRESS, UPLOAD_STARTED, UPLOAD_FINISHED, UPLOAD_SUCCESSFUL, UPLOAD_STREAMING_FAILED, UPLOAD_STREAMING_FINISHED, ABORT_UPLOAD } private UploadStatusEventType uploadProgressEventType; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadHandler.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadHandler.java index 848fa2da5..45a55d138 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadHandler.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadHandler.java @@ -15,7 +15,6 @@ import javax.annotation.PreDestroy; import org.eclipse.hawkbit.repository.exception.ArtifactUploadFailedException; import org.eclipse.hawkbit.repository.model.SoftwareModule; -import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent; import org.eclipse.hawkbit.ui.artifacts.event.UploadFileStatus; import org.eclipse.hawkbit.ui.artifacts.event.UploadStatusEvent; import org.eclipse.hawkbit.ui.artifacts.event.UploadStatusEvent.UploadStatusEventType; @@ -29,7 +28,6 @@ import org.vaadin.spring.events.EventScope; import org.vaadin.spring.events.annotation.EventBusListenerMethod; import com.vaadin.server.StreamVariable; -import com.vaadin.ui.UI; import com.vaadin.ui.Upload; import com.vaadin.ui.Upload.FailedEvent; import com.vaadin.ui.Upload.FailedListener; @@ -66,6 +64,7 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene private volatile String mimeType = null; private volatile boolean streamingInterrupted = false; private volatile boolean uploadInterrupted = false; + private volatile boolean aborted = false; private String failureReason; private final I18N i18n; @@ -77,6 +76,7 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene UploadHandler(final String fileName, final long fileSize, final UploadLayout view, final long maxSize, final Upload upload, final String mimeType, SoftwareModule selectedSw) { super(); + this.aborted = false; this.fileName = fileName; this.fileSize = fileSize; this.view = view; @@ -87,6 +87,23 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene this.i18n = SpringContextHelper.getBean(I18N.class); this.eventBus = SpringContextHelper.getBean(EventBus.SessionEventBus.class); this.artifactUploadState = SpringContextHelper.getBean(ArtifactUploadState.class); + eventBus.subscribe(this); + } + + @PreDestroy + void destroy() { + /* + * It's good manners to do this, even though vaadin-spring will + * automatically unsubscribe when this UI is garbage collected. + */ + eventBus.unsubscribe(this); + } + + @EventBusListenerMethod(scope = EventScope.SESSION) + void onEvent(final UploadStatusEventType event) { + if (event == UploadStatusEventType.ABORT_UPLOAD) { + aborted = true; + } } /** @@ -98,6 +115,7 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene public final OutputStream getOutputStream() { try { streamingInterrupted = false; + failureReason = null; return view.saveUploadedFileDetails(fileName, fileSize, mimeType, selectedSw); } catch (final ArtifactUploadFailedException e) { LOG.error("Atifact upload failed {} ", e); @@ -116,6 +134,8 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene @Override public OutputStream receiveUpload(final String fileName, final String mimeType) { uploadInterrupted = false; + aborted = false; + failureReason = null; this.fileName = fileName; this.mimeType = mimeType; // reset has directory flag before upload @@ -232,10 +252,13 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene if (readBytes > maxSize || contentLength > maxSize) { LOG.error("User tried to upload more than was allowed ({}).", maxSize); failureReason = i18n.get("message.uploadedfile.size.exceeded", maxSize); - eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_FAILED, new UploadFileStatus( - fileName, failureReason, selectedSwForUpload))); - upload.interruptUpload(); - uploadInterrupted = true; + interruptFileUpload(); + return; + } + if (aborted) { + LOG.error("User aborted file upload"); + failureReason = i18n.get("message.uploadedfile.aborted"); + interruptFileUpload(); return; } eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_IN_PROGRESS, @@ -254,9 +277,13 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene if (event.getBytesReceived() > maxSize || event.getContentLength() > maxSize) { LOG.error("User tried to upload more than was allowed ({}).", maxSize); failureReason = i18n.get("message.uploadedfile.size.exceeded", maxSize); - eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_FAILED, new UploadFileStatus( - fileName, failureReason, selectedSw))); - streamingInterrupted = true; + interruptFileStreaming(); + return; + } + if (aborted) { + LOG.error("User aborted the upload"); + failureReason = i18n.get("message.uploadedfile.aborted"); + interruptFileStreaming(); return; } eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_IN_PROGRESS, new UploadFileStatus( @@ -345,4 +372,12 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene return true; } + private void interruptFileStreaming() { + streamingInterrupted = true; + } + + private void interruptFileUpload() { + upload.interruptUpload(); + uploadInterrupted = true; + } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadLayout.java index cbf766da8..4eaa61096 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadLayout.java @@ -532,8 +532,7 @@ public class UploadLayout extends VerticalLayout { */ boolean enableProcessBtn() { if (artifactUploadState.getNumberOfFilesActuallyUpload().intValue() >= artifactUploadState - .getNumberOfFileUploadsExpected().intValue() - && artifactUploadState.getNumberOfFilesActuallyUpload().get() != 0) { + .getNumberOfFileUploadsExpected().intValue() && !getFileSelected().isEmpty()) { processBtn.setEnabled(true); artifactUploadState.getNumberOfFilesActuallyUpload().set(0); artifactUploadState.getNumberOfFileUploadsExpected().set(0); @@ -729,7 +728,7 @@ public class UploadLayout extends VerticalLayout { private boolean isUploadComplete() { int uploadedCount = artifactUploadState.getNumberOfFilesActuallyUpload().intValue(); int expectedUploadsCount = artifactUploadState.getNumberOfFileUploadsExpected().intValue(); - return uploadedCount == expectedUploadsCount; + return uploadedCount == expectedUploadsCount; } private void onUploadFailure(final UploadStatusEvent event) { diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadStatusInfoWindow.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadStatusInfoWindow.java index e2a486e6c..351d625c9 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadStatusInfoWindow.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadStatusInfoWindow.java @@ -18,8 +18,10 @@ import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent; import org.eclipse.hawkbit.ui.artifacts.event.UploadStatusEvent; import org.eclipse.hawkbit.ui.artifacts.event.UploadStatusEvent.UploadStatusEventType; import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState; +import org.eclipse.hawkbit.ui.common.ConfirmationDialog; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder; +import org.eclipse.hawkbit.ui.utils.I18N; import org.eclipse.hawkbit.ui.utils.SPUIComponetIdProvider; import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions; import org.springframework.beans.factory.annotation.Autowired; @@ -66,6 +68,9 @@ public class UploadStatusInfoWindow extends Window { @Autowired private ArtifactUploadState artifactUploadState; + @Autowired + private I18N i18n; + private static final String PROGRESS = "Progress"; private static final String FILE_NAME = "File name"; @@ -82,6 +87,8 @@ public class UploadStatusInfoWindow extends Window { private volatile boolean errorOccured = false; + private volatile boolean uploadAborted = false; + private Button minimizeButton; private VerticalLayout mainLayout; @@ -91,9 +98,10 @@ public class UploadStatusInfoWindow extends Window { private Button closeButton; private Button resizeButton; - - private UI ui; + private UI ui; + + private ConfirmationDialog confirmDialog; /** * Default Constructor. @@ -118,10 +126,10 @@ public class UploadStatusInfoWindow extends Window { setContent(mainLayout); eventBus.subscribe(this); ui = UI.getCurrent(); - + + createConfirmDialog(); } - @EventBusListenerMethod(scope = EventScope.SESSION) void onEvent(final UploadStatusEvent event) { if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_IN_PROGRESS) { @@ -139,13 +147,12 @@ public class UploadStatusInfoWindow extends Window { ui.access(() -> uploadSucceeded(event.getUploadStatus().getFileName())); } } - + private void onStartOfUpload(UploadStatusEvent event) { uploadSessionStarted(); uploadStarted(event.getUploadStatus().getFileName()); } - @PreDestroy void destroy() { /* @@ -154,7 +161,7 @@ public class UploadStatusInfoWindow extends Window { */ eventBus.unsubscribe(this); } - + private void restoreState() { Indexed container = grid.getContainerDataSource(); if (container.getItemIds().isEmpty()) { @@ -246,7 +253,7 @@ public class UploadStatusInfoWindow extends Window { @Override public JsonValue encode(final String value) { - String result ; + String result; switch (value) { case "Finished": result = "
" + FontAwesome.CHECK_CIRCLE.getHtml() + "
"; @@ -266,20 +273,28 @@ public class UploadStatusInfoWindow extends Window { * Automatically close if not error has occured. */ void uploadSessionFinished() { - if (!errorOccured) { - close(); + uploadAborted = false; + if (!errorOccured && !artifactUploadState.isStatusPopupMinimized()) { + clearWindow(); } artifactUploadState.setUploadCompleted(true); minimizeButton.setEnabled(false); + closeButton.setEnabled(true); + confirmDialog.getWindow().close(); + UI.getCurrent().removeWindow(confirmDialog.getWindow()); } void uploadSessionStarted() { - if (!artifactUploadState.isStatusPopupMinimized()) { - close(); + if (artifactUploadState.getNumberOfFilesActuallyUpload().intValue() == 0 + && artifactUploadState.getNumberOfFileUploadsFailed().intValue() == 0 + && !artifactUploadState.isStatusPopupMinimized()) { openWindow(); } - minimizeButton.setEnabled(true); - artifactUploadState.setUploadCompleted(false); + if (!uploadAborted) { + minimizeButton.setEnabled(true); + closeButton.setEnabled(true); + artifactUploadState.setUploadCompleted(false); + } } void openWindow() { @@ -304,11 +319,11 @@ public class UploadStatusInfoWindow extends Window { } void updateProgress(final String filename, final long readBytes, final long contentLength) { - final Item item = uploads.getItem(filename); + final Item item = uploads.getItem(filename); if (item != null) { double progress = (double) readBytes / (double) contentLength; item.getItemProperty(PROGRESS).setValue(progress); - List uploadStatusObjectList = (List) artifactUploadState + List uploadStatusObjectList = (List) artifactUploadState .getUploadedFileStatusList().stream().filter(e -> e.getFilename().equals(filename)) .collect(Collectors.toList()); if (!uploadStatusObjectList.isEmpty()) { @@ -340,9 +355,7 @@ public class UploadStatusInfoWindow extends Window { } void uploadFailed(final String filename, final String errorReason) { - if (!errorOccured) { - errorOccured = true; - } + errorOccured = true; String status = "Failed"; final Item item = uploads.getItem(filename); if (item != null) { @@ -363,6 +376,9 @@ public class UploadStatusInfoWindow extends Window { errorOccured = false; uploads.removeAllItems(); setWindowMode(WindowMode.NORMAL); + setColumnWidth(); + setPopupSizeInMinMode(); + resizeButton.setIcon(FontAwesome.EXPAND); this.close(); artifactUploadState.getUploadedFileStatusList().clear(); artifactUploadState.getNumberOfFileUploadsFailed().set(0); @@ -421,7 +437,34 @@ public class UploadStatusInfoWindow extends Window { SPUIComponetIdProvider.UPLOAD_STATUS_POPUP_CLOSE_BUTTON_ID, "", "", "", true, FontAwesome.TIMES, SPUIButtonStyleSmallNoBorder.class); closeBtn.addStyleName(ValoTheme.BUTTON_BORDERLESS); - closeBtn.addClickListener(event -> clearWindow()); + closeBtn.addClickListener(event -> onClose()); return closeBtn; } + + private void onClose() { + if (!artifactUploadState.isUploadCompleted()) { + confirmAbortAction(); + } else { + clearWindow(); + } + } + + private void confirmAbortAction() { + UI.getCurrent().addWindow(confirmDialog.getWindow()); + confirmDialog.getWindow().bringToFront(); + } + + private void createConfirmDialog() { + confirmDialog = new ConfirmationDialog(i18n.get("caption.cancel.action.confirmbox"), + i18n.get("message.abort.upload"), i18n.get("button.ok"), i18n.get("button.cancel"), ok -> { + if (ok) { + eventBus.publish(this, UploadStatusEventType.ABORT_UPLOAD); + uploadAborted = true; + errorOccured = true; + minimizeButton.setEnabled(false); + closeButton.setEnabled(false); + } + }); + } + } diff --git a/hawkbit-ui/src/main/resources/messages.properties b/hawkbit-ui/src/main/resources/messages.properties index 25dabd354..7efc6e16d 100644 --- a/hawkbit-ui/src/main/resources/messages.properties +++ b/hawkbit-ui/src/main/resources/messages.properties @@ -86,6 +86,7 @@ caption.cancel.action.confirmbox = Confirm action cancel caption.forcequit.action.confirmbox = Confirm force quit action caption.forced.datefield = Force update at time caption.force.action.confirmbox = Confirm Force Active Action +caption.confirm.abort.action = Confirm abort action caption.filter.delete.confirmbox = Confirm Filter Delete Action @@ -321,8 +322,11 @@ message.duplicate.filename = Duplicate file name message.swModule.deleted = {0} Software module(s) deleted message.upload.failed = Streaming Failed message.uploadedfile.size.exceeded = File size exceeded .Allowed size {0} bytes +message.uploadedfile.aborted = File upload aborted message.file.not.found = File not found message.artifact.deleted =Artifact with file {0} deleted successfully +message.abort.upload = Are you sure that you want to abort the upload? + upload.swModuleTable.header = Software module diff --git a/hawkbit-ui/src/main/resources/messages_de.properties b/hawkbit-ui/src/main/resources/messages_de.properties index 39661e3c9..6a1e25222 100644 --- a/hawkbit-ui/src/main/resources/messages_de.properties +++ b/hawkbit-ui/src/main/resources/messages_de.properties @@ -85,8 +85,9 @@ caption.forced.datefield = Force update at time caption.force.action.confirmbox = Confirm Force Active Action caption.filter.simple = Simple Filter caption.filter.custom = Custom Filter - caption.filter.delete.confirmbox = Confirm Filter Delete Action +caption.confirm.abort.action = Confirm abort action + # Labels prefix with - label label.dist.details.type = Type : @@ -319,8 +320,11 @@ message.swModule.deleted = {0} Software module(s) deleted message.error.missing.tagname = Please select tag name message.upload.failed = Streaming Failed message.uploadedfile.size.exceeded = File size exceeded .Allowed size {0} bytes +message.uploadedfile.aborted = File upload aborted message.file.not.found = File not found message.artifact.deleted =Artifact with file {0} deleted successfully +message.abort.upload = Are you sure that you want to abort the upload? + upload.swModuleTable.header = Software module diff --git a/hawkbit-ui/src/main/resources/messages_en.properties b/hawkbit-ui/src/main/resources/messages_en.properties index 23df35ad2..d512b9b97 100644 --- a/hawkbit-ui/src/main/resources/messages_en.properties +++ b/hawkbit-ui/src/main/resources/messages_en.properties @@ -85,8 +85,8 @@ caption.soft.delete.confirmbox = Confirm Software Module Delete Action caption.cancel.action.confirmbox = Confirm action cancellation caption.forced.datefield = Force update at time caption.force.action.confirmbox = Confirm Force Active Action - caption.filter.delete.confirmbox = Confirm Filter Delete Action +caption.confirm.abort.action = Confirm abort action # Labels prefix with - label label.dist.details.type = Type : @@ -313,7 +313,10 @@ message.duplicate.filename = Duplicate file name message.swModule.deleted = {0} Software module(s) deleted message.upload.failed = Streaming Failed message.uploadedfile.size.exceeded = File size exceeded .Allowed size {0} bytes +message.uploadedfile.aborted = File upload aborted message.file.not.found = File not found +message.abort.upload = Are you sure that you want to abort the upload? + upload.swModuleTable.header = Software module upload.selectedfile.name = file selected for upload