Artifact upload : on discard action interupt the ongoing upload

Signed-off-by: Asharani <asharani.murugesh@in.bosch.com>
This commit is contained in:
Asharani
2016-05-16 14:56:23 +05:30
parent 8fc1f74f80
commit cb81c78b69
8 changed files with 171 additions and 56 deletions

View File

@@ -15,6 +15,5 @@ package org.eclipse.hawkbit.ui.artifacts.event;
*
*/
public enum UploadArtifactUIEvent {
SHOW_DROP_HINTS, HIDE_DROP_HINTS, SOFTWARE_DRAG_START, SOFTWARE_TYPE_DRAG_START, UPDATE_UPLOAD_COUNT, ENABLE_PROCESS_BUTTON, HIDE_FILTER_BY_TYPE, SHOW_FILTER_BY_TYPE, DISCARD_DELETE_SOFTWARE, DISCARD_ALL_DELETE_SOFTWARE, DELETED_ALL_SOFWARE, DISABLE_PROCESS_BUTTON, DISCARD_DELETE_SOFTWARE_TYPE, DISCARD_ALL_DELETE_SOFTWARE_TYPE, DELETED_ALL_SOFWARE_TYPE,MINIMIZED_STATUS_POPUP,MAXIMIZED_STATUS_POPUP, UPLOAD_IN_PROGESS
SHOW_DROP_HINTS, HIDE_DROP_HINTS, SOFTWARE_DRAG_START, SOFTWARE_TYPE_DRAG_START, UPDATE_UPLOAD_COUNT, HIDE_FILTER_BY_TYPE, SHOW_FILTER_BY_TYPE, DISCARD_DELETE_SOFTWARE, DISCARD_ALL_DELETE_SOFTWARE, DELETED_ALL_SOFWARE, DISCARD_DELETE_SOFTWARE_TYPE, DISCARD_ALL_DELETE_SOFTWARE_TYPE, DELETED_ALL_SOFWARE_TYPE, MINIMIZED_STATUS_POPUP, MAXIMIZED_STATUS_POPUP, UPLOAD_IN_PROGESS, DISCARD_UPLOAD, ARTIFACT_RESULT_POPUP_CLOSED
}

View File

@@ -73,6 +73,12 @@ public class ArtifactUploadState implements ManagmentEntityState<Long>, Serializ
private final AtomicInteger numberOfFilesActuallyUpload = new AtomicInteger();
private final AtomicInteger numberOfFileUploadsFailed = new AtomicInteger();
public AtomicInteger getNumberOfFileUploadsFailed() {
return numberOfFileUploadsFailed;
}
public AtomicInteger getNumberOfFilesActuallyUpload() {
return numberOfFilesActuallyUpload;
}

View File

@@ -544,7 +544,7 @@ public class UploadConfirmationwindow implements Button.ClickListener {
if (event.getComponent().getId().equals(SPUIComponetIdProvider.UPLOAD_ARTIFACT_DETAILS_CLOSE)) {
uploadConfrimationWindow.close();
} else if (event.getComponent().getId().equals(SPUIComponetIdProvider.UPLOAD_DISCARD_DETAILS_BUTTON)) {
uploadLayout.removeUploadedFileDetails();
uploadLayout.clearUploadedFileDetails();
uploadConfrimationWindow.close();
} else if (event.getComponent().getId().equals(SPUIComponetIdProvider.UPLOAD_BUTTON)) {
processArtifactUpload();
@@ -568,10 +568,10 @@ public class UploadConfirmationwindow implements Button.ClickListener {
uploadDetailsTable.removeItem(((Button) event.getComponent()).getData());
uploadLayout.getFileSelected().remove(customFile);
uploadLayout.updateActionCount();
uploadLayout.updateUploadCounts();
if (uploadDetailsTable.getItemIds().isEmpty()) {
uploadLayout.clearFileList();
uploadConfrimationWindow.close();
uploadLayout.clearUploadedFileDetails();
}
}

View File

@@ -11,6 +11,8 @@ package org.eclipse.hawkbit.ui.artifacts.upload;
import java.io.IOException;
import java.io.OutputStream;
import javax.annotation.PreDestroy;
import org.eclipse.hawkbit.repository.exception.ArtifactUploadFailedException;
import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent;
import org.eclipse.hawkbit.ui.artifacts.event.UploadFileStatus;
@@ -21,8 +23,11 @@ import org.eclipse.hawkbit.ui.utils.SpringContextHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.vaadin.spring.events.EventBus;
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;
@@ -83,6 +88,24 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
this.mimeType = mimeType;
this.i18n = SpringContextHelper.getBean(I18N.class);
this.eventBus = SpringContextHelper.getBean(EventBus.SessionEventBus.class);
eventBus.subscribe(this);
}
@EventBusListenerMethod(scope = EventScope.SESSION)
void onEvent(final UploadArtifactUIEvent event) {
if (event == UploadArtifactUIEvent.DISCARD_UPLOAD) {
UI.getCurrent().access(() ->intreruptUploadOnDiscard());
}
}
//
@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);
}
/**
@@ -93,6 +116,7 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
@Override
public final OutputStream getOutputStream() {
try {
streamingInterrupted = false;
return view.saveUploadedFileDetails(fileName, fileSize, mimeType);
} catch (final ArtifactUploadFailedException e) {
LOG.error("Atifact upload failed {} ", e);
@@ -110,18 +134,15 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
*/
@Override
public OutputStream receiveUpload(final String fileName, final String mimeType) {
uploadInterrupted = false;
this.fileName = fileName;
this.mimeType = mimeType;
// reset has directory flag before upload
view.setHasDirectory(false);
try {
if (view.checkIfSoftwareModuleIsSelected()) {
if (view.checkForDuplicate(fileName)) {
view.showDuplicateMessage();
} else {
view.increaseNumberOfFileUploadsExpected();
return view.saveUploadedFileDetails(fileName, 0, mimeType);
}
if (view.checkIfSoftwareModuleIsSelected() && !view.checkForDuplicate(fileName)) {
view.increaseNumberOfFileUploadsExpected();
return view.saveUploadedFileDetails(fileName, 0, mimeType);
}
} catch (final ArtifactUploadFailedException e) {
LOG.error("Atifact upload failed {} ", e);
@@ -350,5 +371,13 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
}
return true;
}
protected void intreruptUploadOnDiscard(){
if(upload!=null && upload.isUploading()){
upload.interruptUpload();
uploadInterrupted = true;
}
streamingInterrupted = true;
}
}

View File

@@ -118,6 +118,8 @@ public class UploadLayout extends VerticalLayout {
private Button uploadStatusButton;
private Boolean changesDiscarded = Boolean.FALSE;
/**
* Initialize the upload layout.
*/
@@ -129,7 +131,6 @@ public class UploadLayout extends VerticalLayout {
eventBus.subscribe(this);
ui = UI.getCurrent();
}
@EventBusListenerMethod(scope = EventScope.SESSION)
void onEvent(final UploadArtifactUIEvent event) {
@@ -139,14 +140,17 @@ public class UploadLayout extends VerticalLayout {
ui.access(() -> showUploadStatusButton());
} else if (event == UploadArtifactUIEvent.MAXIMIZED_STATUS_POPUP) {
ui.access(() -> maximizeStatusPopup());
}
}
else if(event == UploadArtifactUIEvent.ARTIFACT_RESULT_POPUP_CLOSED){
ui.access(() -> closeUploadStatusPopup());
}
}
@EventBusListenerMethod(scope = EventScope.SESSION)
void onEvent(final UploadStatusEvent event) {
if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_STARTED) {
ui.access(() -> setUploadStatusButtonIconToInProgress());
}
else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_FAILED) {
ui.access(() -> onStartOfUpload());
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_FAILED) {
ui.access(() -> onUploadFailure(event));
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_FINISHED) {
ui.access(() -> onUploadCompletion());
@@ -155,7 +159,7 @@ public class UploadLayout extends VerticalLayout {
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_STREAMING_FAILED) {
ui.access(() -> onUploadStreamingFailure(event));
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_STREAMING_FINISHED) {
ui.access(() -> onUploadStreamingSuccess(event));
ui.access(() -> onUploadStreamingSuccess());
}
}
@@ -211,6 +215,7 @@ public class UploadLayout extends VerticalLayout {
private void restoreState() {
updateActionCount();
if (!artifactUploadState.getFileSelected().isEmpty() && artifactUploadState.isUploadCompleted()) {
processBtn.setEnabled(true);
}
@@ -237,6 +242,7 @@ public class UploadLayout extends VerticalLayout {
@Override
public void drop(final DragAndDropEvent event) {
changesDiscarded = Boolean.FALSE;
if (validate(event)) {
final Html5File[] files = ((WrapperTransferable) event.getTransferable()).getFiles();
// reset the flag
@@ -342,15 +348,6 @@ public class UploadLayout extends VerticalLayout {
return isDuplicate;
}
@EventBusListenerMethod(scope = EventScope.SESSION)
void toggleProcessButton(final UploadArtifactUIEvent event) {
if (event == UploadArtifactUIEvent.ENABLE_PROCESS_BUTTON) {
processBtn.setEnabled(true);
} else if (event == UploadArtifactUIEvent.DISABLE_PROCESS_BUTTON) {
processBtn.setEnabled(false);
}
}
/**
* Save uploaded file details.
*
@@ -387,15 +384,14 @@ public class UploadLayout extends VerticalLayout {
artifactUploadState.getBaseSwModuleList().put(currentBaseSoftwareModuleKey, selectedSoftwareModule);
}
return out;
}
catch (final FileNotFoundException e) {
} catch (final FileNotFoundException e) {
LOG.error("Upload failed {}", e);
throw new ArtifactUploadFailedException(i18n.get("message.file.not.found"));
} catch (final IOException e) {
LOG.error("Upload failed {}", e);
throw new ArtifactUploadFailedException(i18n.get("message.upload.failed"));
}
}
Boolean validate(final DragAndDropEvent event) {
@@ -491,8 +487,10 @@ public class UploadLayout extends VerticalLayout {
void displayDuplicateValidationMessage() {
// check if streaming of all dropped files are completed
if (artifactUploadState.getNumberOfFilesActuallyUpload().intValue() == artifactUploadState.getNumberOfFileUploadsExpected().intValue()) {
if (artifactUploadState.getNumberOfFilesActuallyUpload().intValue() == artifactUploadState
.getNumberOfFileUploadsExpected().intValue()) {
displayCompositeMessage();
duplicateFileNamesList.clear();
}
}
@@ -537,6 +535,10 @@ public class UploadLayout extends VerticalLayout {
artifactUploadState.getNumberOfFilesActuallyUpload().incrementAndGet();
}
void increaseNumberOfFileUploadsFailed() {
artifactUploadState.getNumberOfFileUploadsFailed().incrementAndGet();
}
/**
* Enable process button once upload is completed.
*/
@@ -561,15 +563,22 @@ public class UploadLayout extends VerticalLayout {
if (artifactUploadState.getFileSelected().isEmpty()) {
uiNotification.displayValidationError(i18n.get("message.error.noFileSelected"));
} else {
removeUploadedFileDetails();
clearUploadedFileDetails();
}
}
}
protected void removeUploadedFileDetails() {
protected void clearUploadedFileDetails() {
eventBus.publish(this, UploadArtifactUIEvent.DISCARD_UPLOAD);
changesDiscarded = Boolean.TRUE;
clearFileList();
closeUploadStatusPopup();
}
private void closeUploadStatusPopup() {
uploadInfoWindow.clearWindow();
hideUploadStatusButton();
artifactUploadState.setStatusPopupMinimized(false);
}
/**
@@ -589,6 +598,7 @@ public class UploadLayout extends VerticalLayout {
processBtn.setEnabled(false);
artifactUploadState.getNumberOfFilesActuallyUpload().set(0);
artifactUploadState.getNumberOfFileUploadsExpected().set(0);
artifactUploadState.getNumberOfFileUploadsFailed().set(0);
duplicateFileNamesList.clear();
}
@@ -664,10 +674,17 @@ public class UploadLayout extends VerticalLayout {
return dropAreaLayout;
}
private void onStartOfUpload() {
changesDiscarded = Boolean.FALSE;
setUploadStatusButtonIconToInProgress();
if (artifactUploadState.isStatusPopupMinimized()) {
updateStatusButtonCount();
}
}
private void onUploadStreamingSuccess(UploadStatusEvent event) {
private void onUploadStreamingSuccess() {
increaseNumberOfFilesActuallyUpload();
updateActionCount();
updateUploadCounts();
enableProcessBtn();
if (isUploadComplete()) {
uploadInfoWindow.uploadSessionFinished();
@@ -675,19 +692,35 @@ public class UploadLayout extends VerticalLayout {
}
// display the duplicate message after streaming all files
displayDuplicateValidationMessage();
duplicateFileNamesList.clear();
}
private void onUploadStreamingFailure(UploadStatusEvent event) {
onUploadFailure(event);
updateActionCount();
enableProcessBtn();
// check if we are finished
if (isUploadComplete()) {
uploadInfoWindow.uploadSessionFinished();
setUploadStatusButtonIconToFinished();
if (!changesDiscarded) {
/**
* If upload interrupted because of duplicate file,do not remove the
* file already in upload list
**/
if (getDuplicateFileNamesList().isEmpty()
|| !getDuplicateFileNamesList().contains(event.getUploadStatus().getFileName())) {
final SoftwareModule sw = getSoftwareModuleSelected();
getFileSelected().remove(
new CustomFile(event.getUploadStatus().getFileName(), sw.getName(), sw.getVersion()));
// failed reason to be updated only if there is error other than
// duplicate file error
uploadInfoWindow.uploadFailed(event.getUploadStatus().getFileName(), event.getUploadStatus()
.getFailureReason());
increaseNumberOfFileUploadsFailed();
}
decreaseNumberOfFileUploadsExpected();
updateUploadCounts();
enableProcessBtn();
// check if we are finished
if (isUploadComplete()) {
uploadInfoWindow.uploadSessionFinished();
setUploadStatusButtonIconToFinished();
}
displayDuplicateValidationMessage();
}
displayDuplicateValidationMessage();
}
private void onUploadSuccess(UploadStatusEvent event) {
@@ -701,12 +734,14 @@ public class UploadLayout extends VerticalLayout {
if (isUploadComplete()) {
uploadInfoWindow.uploadSessionFinished();
setUploadStatusButtonIconToFinished();
displayDuplicateValidationMessage();
}
updateActionCount();
updateUploadCounts();
enableProcessBtn();
duplicateFileNamesList.clear();
}
private boolean isUploadComplete() {
int uploadedCount = artifactUploadState.getNumberOfFilesActuallyUpload().intValue();
int expectedUploadsCount = artifactUploadState.getNumberOfFileUploadsExpected().intValue();
@@ -714,19 +749,22 @@ public class UploadLayout extends VerticalLayout {
}
private void onUploadFailure(final UploadStatusEvent event) {
decreaseNumberOfFileUploadsExpected();
/**
* If upload interrupted because of duplicate file,do not remove the
* file already in upload list
**/
if (getDuplicateFileNamesList().isEmpty()
|| !getDuplicateFileNamesList().contains(event.getUploadStatus().getFileName())) {
if ((getDuplicateFileNamesList().isEmpty() || !getDuplicateFileNamesList().contains(
event.getUploadStatus().getFileName()))
&& !changesDiscarded) {
final SoftwareModule sw = getSoftwareModuleSelected();
getFileSelected().remove(
new CustomFile(event.getUploadStatus().getFileName(), sw.getName(), sw.getVersion()));
//failed reason to be updated only if there is error other than duplicate file error
// failed reason to be updated only if there is error other than
// duplicate file error
uploadInfoWindow.uploadFailed(event.getUploadStatus().getFileName(), event.getUploadStatus()
.getFailureReason());
increaseNumberOfFileUploadsFailed();
decreaseNumberOfFileUploadsExpected();
}
}
@@ -777,6 +815,24 @@ public class UploadLayout extends VerticalLayout {
uploadStatusButton.setVisible(false);
}
void updateStatusButtonCount() {
int uploadsPending = artifactUploadState.getNumberOfFileUploadsExpected().get()
- artifactUploadState.getNumberOfFilesActuallyUpload().get();
int uploadsFailed = artifactUploadState.getNumberOfFileUploadsFailed().get();
StringBuilder builder = new StringBuilder("");
if (uploadsFailed != 0) {
if (uploadsPending != 0) {
builder.append("<div class='error-count error-count-color'>" + uploadsFailed + "</div>");
} else {
builder.append("<div class='unread error-count-color'>" + uploadsFailed + "</div>");
}
}
if (uploadsPending != 0) {
builder.append("<div class='unread'>" + uploadsPending + "</div>");
}
uploadStatusButton.setCaption(builder.toString());
}
private void onClickOfUploadStatusButton() {
artifactUploadState.setStatusPopupMinimized(false);
eventBus.publish(this, UploadArtifactUIEvent.MAXIMIZED_STATUS_POPUP);
@@ -787,6 +843,7 @@ public class UploadLayout extends VerticalLayout {
return;
}
uploadStatusButton.setVisible(true);
updateStatusButtonCount();
}
protected void hideUploadStatusButton() {
@@ -816,5 +873,10 @@ public class UploadLayout extends VerticalLayout {
uploadStatusButton.addStyleName(SPUIStyleDefinitions.UPLOAD_PROGRESS_INDICATOR_STYLE);
uploadStatusButton.setIcon(null);
}
protected void updateUploadCounts() {
updateActionCount();
updateStatusButtonCount();
}
}

View File

@@ -11,6 +11,7 @@ package org.eclipse.hawkbit.ui.artifacts.upload;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleTiny;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
@@ -19,6 +20,8 @@ import org.eclipse.hawkbit.ui.utils.SPUIComponetIdProvider;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.SpringContextHelper;
import org.vaadin.spring.events.EventBus;
import com.vaadin.data.Item;
import com.vaadin.data.util.IndexedContainer;
@@ -63,6 +66,9 @@ public class UploadResultWindow implements Button.ClickListener {
private static final String UPLOAD_RESULT = "uploadResult";
private static final String REASON = "reason";
private transient EventBus.SessionEventBus eventBus;
/**
* Initialize upload status popup.
@@ -75,6 +81,7 @@ public class UploadResultWindow implements Button.ClickListener {
public UploadResultWindow(final List<UploadStatus> uploadResultList, final I18N i18n) {
this.uploadResultList = uploadResultList;
this.i18n = i18n;
eventBus = SpringContextHelper.getBean( EventBus.SessionEventBus.class);
createComponents();
createLayout();
}
@@ -183,6 +190,8 @@ public class UploadResultWindow implements Button.ClickListener {
if (event.getComponent().getId().equals(SPUIComponetIdProvider.UPLOAD_ARTIFACT_RESULT_CLOSE)
|| event.getComponent().getId().equals(SPUIComponetIdProvider.UPLOAD_ARTIFACT_RESULT_POPUP_CLOSE)) {
uploadResultsWindow.close();
//close upload status popup if open
eventBus.publish(this, UploadArtifactUIEvent.ARTIFACT_RESULT_POPUP_CLOSED);
}
}

View File

@@ -166,7 +166,6 @@ public class UploadStatusInfoWindow extends Window {
item.getItemProperty(PROGRESS).setValue(statusObject.getProgress());
item.getItemProperty(FILE_NAME).setValue(statusObject.getFilename());
}
// artifactUploadState.setUploadCompleted(true);
if (artifactUploadState.isUploadCompleted()) {
minimizeButton.setEnabled(false);
}
@@ -294,7 +293,9 @@ public class UploadStatusInfoWindow extends Window {
void uploadStarted(final String filename) {
final Item item = uploads.addItem(filename);
item.getItemProperty(FILE_NAME).setValue(filename);
if (item != null) {
item.getItemProperty(FILE_NAME).setValue(filename);
}
grid.scrollToEnd();
UploadStatusObject uploadStatus = new UploadStatusObject(filename);
uploadStatus.setStatus("Active");
@@ -302,11 +303,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<UploadStatusObject> uploadStatusObjectList = (List<UploadStatusObject>) artifactUploadState
List<UploadStatusObject> uploadStatusObjectList = (List<UploadStatusObject>) artifactUploadState
.getUploadedFileStatusList().stream().filter(e -> e.getFilename().equals(filename))
.collect(Collectors.toList());
if (!uploadStatusObjectList.isEmpty()) {
@@ -363,6 +364,7 @@ public class UploadStatusInfoWindow extends Window {
setWindowMode(WindowMode.NORMAL);
this.close();
artifactUploadState.getUploadedFileStatusList().clear();
artifactUploadState.getNumberOfFileUploadsFailed().set(0);
}
private void setPopupSizeInMinMode() {
@@ -421,5 +423,4 @@ public class UploadStatusInfoWindow extends Window {
closeBtn.addClickListener(event -> clearWindow());
return closeBtn;
}
}

View File

@@ -10,7 +10,7 @@
@mixin others {
//Style to display the pending action count
.unread {
.unread, .error-count {
@include valo-badge-style;
position: absolute;
pointer-events: none;
@@ -21,6 +21,15 @@
border-radius: $v-border-radius;
color: $widget-bg;
}
.error-count {
top: round($v-unit-size / -5);
right: round($v-unit-size / 1.9);
}
.error-count-color{
@include valo-gradient($color: $red-color);
}
//Deployment view - Style of count message
.v-caption-count-msg-box {