From 8a976cabadba6d454718daf05e8ef6948a5c7d5c Mon Sep 17 00:00:00 2001 From: Asharani Date: Thu, 5 May 2016 16:28:12 +0530 Subject: [PATCH] Minimize/Maximize upload status popup intial commit Signed-off-by: Asharani --- .../event/UploadArtifactUIEvent.java | 2 +- .../artifacts/state/ArtifactUploadState.java | 39 ++- .../ui/artifacts/upload/UploadHandler.java | 27 +- .../ui/artifacts/upload/UploadLayout.java | 125 ++++++-- .../upload/UploadStatusInfoWindow.java | 272 ++++++++++++++---- .../artifacts/upload/UploadStatusObject.java | 71 +++++ .../footer/AbstractDeleteActionsLayout.java | 8 +- .../ui/common/grid/AbstractGridLayout.java | 3 +- .../FilterManagementView.java | 3 +- .../ui/utils/SPUIComponetIdProvider.java | 21 ++ .../ui/utils/SPUIStyleDefinitions.java | 9 +- 11 files changed, 480 insertions(+), 100 deletions(-) create mode 100644 hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadStatusObject.java diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/UploadArtifactUIEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/UploadArtifactUIEvent.java index 3d75b67a7..de8f5867b 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/UploadArtifactUIEvent.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/UploadArtifactUIEvent.java @@ -16,5 +16,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 + 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_FINISHED,UPLOAD_STARTED, UPLOAD_STREAMINING_FINISHED } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/state/ArtifactUploadState.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/state/ArtifactUploadState.java index f82ce9ccf..ae6a5860e 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/state/ArtifactUploadState.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/state/ArtifactUploadState.java @@ -9,14 +9,17 @@ package org.eclipse.hawkbit.ui.artifacts.state; import java.io.Serializable; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import org.eclipse.hawkbit.repository.model.SoftwareModule; +import org.eclipse.hawkbit.ui.artifacts.upload.UploadStatusObject; import org.eclipse.hawkbit.ui.common.ManagmentEntityState; import org.springframework.beans.factory.annotation.Autowired; @@ -58,8 +61,42 @@ public class ArtifactUploadState implements ManagmentEntityState, Serializ private final Set selectedDeleteSWModuleTypes = new HashSet<>(); private boolean noDataAvilableSoftwareModule = Boolean.FALSE; + + private boolean isStatusPopupMinimized = Boolean.FALSE; + + private boolean isUploadCompleted = Boolean.FALSE; + + private List uploadedFileStatusList = new ArrayList<>(); + + public List getUploadedFileStatusList() { + return uploadedFileStatusList; + } + + public void setUploadedFileStatusList(List uploadedFileStatusList) { + this.uploadedFileStatusList = uploadedFileStatusList; + } + + public boolean isUploadCompleted() { + return isUploadCompleted; + } + + public void setUploadCompleted(boolean isUploadCompleted) { + this.isUploadCompleted = isUploadCompleted; + } - /** + + public void setStatusPopupMinimized(boolean isStatusPopupMinimized) { + this.isStatusPopupMinimized = isStatusPopupMinimized; + } + + public boolean isStatusPopupMinimized() { + return isStatusPopupMinimized; + } + + + + + /** * Set software. * * @return 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 8c1feeb33..976d5ac27 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 @@ -13,11 +13,13 @@ import java.io.OutputStream; 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.state.CustomFile; import org.eclipse.hawkbit.ui.utils.I18N; import org.eclipse.hawkbit.ui.utils.SpringContextHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.vaadin.spring.events.EventBus; import com.vaadin.server.StreamVariable; import com.vaadin.ui.Upload; @@ -66,6 +68,8 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene private volatile boolean interrupted = false; private String failureReason; private final I18N i18n; + private transient EventBus.SessionEventBus eventBus; + UploadHandler(final String fileName, final long fileSize, final UploadLayout view, final UploadStatusInfoWindow infoWindow, final long maxSize, final Upload upload, final String mimeType) { @@ -78,7 +82,7 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene this.upload = upload; this.mimeType = mimeType; this.i18n = SpringContextHelper.getBean(I18N.class); - + this.eventBus = SpringContextHelper.getBean(EventBus.SessionEventBus.class); } /** @@ -166,7 +170,7 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene if (view.enableProcessBtn()) { infoWindow.uploadSessionFinished(); } - view.updateActionCount(); + eventBus.publish(this, UploadArtifactUIEvent.UPLOAD_STREAMINING_FINISHED); // display the duplicate message after streaming all files view.displayDuplicateValidationMessage(); @@ -237,10 +241,12 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene public void updateProgress(final long readBytes, final long contentLength) { if (readBytes > maxSize || contentLength > maxSize) { LOG.error("User tried to upload more than was allowed ({}).", maxSize); + view.decreaseNumberOfFileUploadsExpected(); final SoftwareModule sw = view.getSoftwareModuleSelected(); view.getFileSelected().remove(new CustomFile(fileName, sw.getName(), sw.getVersion())); view.updateActionCount(); + failureReason = i18n.get("message.uploadedfile.size.exceeded", maxSize); infoWindow.uploadFailed(fileName, failureReason); upload.interruptUpload(); @@ -261,10 +267,12 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene public void onProgress(final StreamingProgressEvent event) { if (event.getBytesReceived() > maxSize || event.getContentLength() > maxSize) { LOG.error("User tried to upload more than was allowed ({}).", maxSize); + view.decreaseNumberOfFileUploadsExpected(); final SoftwareModule sw = view.getSoftwareModuleSelected(); view.getFileSelected().remove(new CustomFile(fileName, sw.getName(), sw.getVersion())); - view.updateActionCount(); + eventBus.publish(this, UploadArtifactUIEvent.UPLOAD_STREAMINING_FINISHED); + failureReason = i18n.get("message.uploadedfile.size.exceeded", maxSize); infoWindow.uploadFailed(event.getFileName(), failureReason); interrupted = true; @@ -285,11 +293,19 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene @Override public void streamingFailed(final StreamingErrorEvent event) { LOG.info("Streaming failed for file :{}", event.getFileName()); + view.decreaseNumberOfFileUploadsExpected(); final SoftwareModule sw = view.getSoftwareModuleSelected(); view.getFileSelected().remove(new CustomFile(fileName, sw.getName(), sw.getVersion())); - view.updateActionCount(); - infoWindow.uploadFailed(event.getFileName(), failureReason); + eventBus.publish(this, UploadArtifactUIEvent.UPLOAD_STREAMINING_FINISHED); + + if (failureReason != null) { + // Display custom error message + infoWindow.uploadFailed(event.getFileName(), failureReason); + } else { + // internal upload error + infoWindow.uploadFailed(event.getFileName(), event.getException().getMessage()); + } // check if we are finished if (view.enableProcessBtn()) { infoWindow.uploadSessionFinished(); @@ -299,6 +315,7 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene LOG.info("Streaming failed due to :{}", event.getException()); } + /** * Upload failed for {@link Upload} variant. * 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 7376cce13..340f66287 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 @@ -103,7 +103,7 @@ public class UploadLayout extends VerticalLayout { private final List duplicateFileNamesList = new ArrayList<>(); - private Button processBtn; + private Button processBtn ; private Button discardBtn; @@ -119,6 +119,8 @@ public class UploadLayout extends VerticalLayout { private Boolean hasDirectory = Boolean.FALSE; + private Button uploadStatusButton; + /** * Initialize the upload layout. */ @@ -127,12 +129,13 @@ public class UploadLayout extends VerticalLayout { createComponents(); buildLayout(); updateActionCount(); + restoreState(); eventBus.subscribe(this); ui = UI.getCurrent(); } private void createComponents() { - + createUploadStatusButton(); createProcessButton(); createDiscardBtn(); } @@ -154,12 +157,15 @@ public class UploadLayout extends VerticalLayout { fileUploadLayout = new HorizontalLayout(); fileUploadLayout.setSpacing(true); + fileUploadLayout.addStyleName(SPUIStyleDefinitions.FOOTER_LAYOUT); fileUploadLayout.addComponent(upload); fileUploadLayout.setComponentAlignment(upload, Alignment.MIDDLE_LEFT); fileUploadLayout.addComponent(processBtn); fileUploadLayout.setComponentAlignment(processBtn, Alignment.MIDDLE_RIGHT); fileUploadLayout.addComponent(discardBtn); fileUploadLayout.setComponentAlignment(discardBtn, Alignment.MIDDLE_RIGHT); + fileUploadLayout.addComponent(uploadStatusButton); + fileUploadLayout.setComponentAlignment(uploadStatusButton, Alignment.MIDDLE_RIGHT); setMargin(false); /* create drag-drop wrapper for drop area */ @@ -167,7 +173,13 @@ public class UploadLayout extends VerticalLayout { dropAreaWrapper.setDropHandler(new DropAreahandler()); setSizeFull(); setSpacing(true); + } + private void restoreState() { + if (artifactUploadState.isStatusPopupMinimized()) { + showUploadStatusButton(); + setUploadStatusButtonIconToFinished(); + } } public DragAndDropWrapper getDropAreaWrapper() { @@ -324,8 +336,8 @@ public class UploadLayout extends VerticalLayout { final SoftwareModule selectedSoftwareModule = artifactUploadState.getSelectedBaseSoftwareModule().get(); - final String currentBaseSoftwareModuleKey = HawkbitCommonUtil - .getFormattedNameVersion(selectedSoftwareModule.getName(), selectedSoftwareModule.getVersion()); + final String currentBaseSoftwareModuleKey = HawkbitCommonUtil.getFormattedNameVersion( + selectedSoftwareModule.getName(), selectedSoftwareModule.getVersion()); final CustomFile customFile = new CustomFile(name, size, tempFile.getAbsolutePath(), selectedSoftwareModule.getName(), selectedSoftwareModule.getVersion(), mimeType); @@ -403,8 +415,8 @@ public class UploadLayout extends VerticalLayout { public Boolean checkIfFileIsDuplicate(final String name) { Boolean isDuplicate = false; final SoftwareModule selectedSoftwareModule = artifactUploadState.getSelectedBaseSoftwareModule().get(); - final String currentBaseSoftwareModuleKey = HawkbitCommonUtil - .getFormattedNameVersion(selectedSoftwareModule.getName(), selectedSoftwareModule.getVersion()); + final String currentBaseSoftwareModuleKey = HawkbitCommonUtil.getFormattedNameVersion( + selectedSoftwareModule.getName(), selectedSoftwareModule.getVersion()); for (final CustomFile customFile : artifactUploadState.getFileSelected()) { final String fileSoftwareModuleKey = HawkbitCommonUtil.getFormattedNameVersion( @@ -469,8 +481,8 @@ public class UploadLayout extends VerticalLayout { void updateFileSize(final String name, final long size) { final SoftwareModule selectedSoftwareModule = artifactUploadState.getSelectedBaseSoftwareModule().get(); - final String currentBaseSoftwareModuleKey = HawkbitCommonUtil - .getFormattedNameVersion(selectedSoftwareModule.getName(), selectedSoftwareModule.getVersion()); + final String currentBaseSoftwareModuleKey = HawkbitCommonUtil.getFormattedNameVersion( + selectedSoftwareModule.getName(), selectedSoftwareModule.getVersion()); for (final CustomFile customFile : artifactUploadState.getFileSelected()) { final String fileSoftwareModuleKey = HawkbitCommonUtil.getFormattedNameVersion( @@ -507,9 +519,10 @@ public class UploadLayout extends VerticalLayout { if (event.getButton().equals(discardBtn)) { if (artifactUploadState.getFileSelected().isEmpty()) { uiNotification.displayValidationError(i18n.get("message.error.noFileSelected")); - } else { clearFileList(); + uploadInfoWindow.clearWindow(); + hideUploadStatusButton(); } } } @@ -536,12 +549,12 @@ public class UploadLayout extends VerticalLayout { private void setConfirmationPopupHeightWidth(final float newWidth, final float newHeight) { if (currentUploadConfirmationwindow != null) { - currentUploadConfirmationwindow.getUploadArtifactDetails().setWidth(HawkbitCommonUtil - .getArtifactUploadPopupWidth(newWidth, SPUIDefinitions.MIN_UPLOAD_CONFIRMATION_POPUP_WIDTH), - Unit.PIXELS); - currentUploadConfirmationwindow.getUploadDetailsTable().setHeight(HawkbitCommonUtil - .getArtifactUploadPopupHeight(newHeight, SPUIDefinitions.MIN_UPLOAD_CONFIRMATION_POPUP_HEIGHT), - Unit.PIXELS); + currentUploadConfirmationwindow.getUploadArtifactDetails().setWidth( + HawkbitCommonUtil.getArtifactUploadPopupWidth(newWidth, + SPUIDefinitions.MIN_UPLOAD_CONFIRMATION_POPUP_WIDTH), Unit.PIXELS); + currentUploadConfirmationwindow.getUploadDetailsTable().setHeight( + HawkbitCommonUtil.getArtifactUploadPopupHeight(newHeight, + SPUIDefinitions.MIN_UPLOAD_CONFIRMATION_POPUP_HEIGHT), Unit.PIXELS); } } @@ -558,10 +571,12 @@ public class UploadLayout extends VerticalLayout { && currentUploadConfirmationwindow.getCurrentUploadResultWindow() != null) { final UploadResultWindow uploadResultWindow = currentUploadConfirmationwindow .getCurrentUploadResultWindow(); - uploadResultWindow.getUploadResultsWindow().setWidth(HawkbitCommonUtil.getArtifactUploadPopupWidth(newWidth, - SPUIDefinitions.MIN_UPLOAD_CONFIRMATION_POPUP_WIDTH), Unit.PIXELS); - uploadResultWindow.getUploadResultTable().setHeight(HawkbitCommonUtil.getArtifactUploadPopupHeight( - newHeight, SPUIDefinitions.MIN_UPLOAD_CONFIRMATION_POPUP_HEIGHT), Unit.PIXELS); + uploadResultWindow.getUploadResultsWindow().setWidth( + HawkbitCommonUtil.getArtifactUploadPopupWidth(newWidth, + SPUIDefinitions.MIN_UPLOAD_CONFIRMATION_POPUP_WIDTH), Unit.PIXELS); + uploadResultWindow.getUploadResultTable().setHeight( + HawkbitCommonUtil.getArtifactUploadPopupHeight(newHeight, + SPUIDefinitions.MIN_UPLOAD_CONFIRMATION_POPUP_HEIGHT), Unit.PIXELS); } } @@ -572,8 +587,8 @@ public class UploadLayout extends VerticalLayout { } else { currentUploadConfirmationwindow = new UploadConfirmationwindow(this, artifactUploadState); UI.getCurrent().addWindow(currentUploadConfirmationwindow.getUploadConfrimationWindow()); - setConfirmationPopupHeightWidth(Page.getCurrent().getBrowserWindowWidth(), - Page.getCurrent().getBrowserWindowHeight()); + setConfirmationPopupHeightWidth(Page.getCurrent().getBrowserWindowWidth(), Page.getCurrent() + .getBrowserWindowHeight()); } } } @@ -608,7 +623,20 @@ public class UploadLayout extends VerticalLayout { void onEvent(final UploadArtifactUIEvent event) { if (event == UploadArtifactUIEvent.DELETED_ALL_SOFWARE) { ui.access(() -> updateActionCount()); + } else if (event == UploadArtifactUIEvent.MINIMIZED_STATUS_POPUP) { + ui.access(() -> showUploadStatusButton()); + } else if (event == UploadArtifactUIEvent.MAXIMIZED_STATUS_POPUP) { + ui.access(() -> maximizeStatusPopup()); + } else if (event == UploadArtifactUIEvent.UPLOAD_FINISHED) { + ui.access(() -> setUploadStatusButtonIconToFinished()); + } else if (event == UploadArtifactUIEvent.UPLOAD_STARTED) { + ui.access(() -> setUploadStatusButtonIconToInProgress()); + }else if (event == UploadArtifactUIEvent.UPLOAD_STREAMINING_FINISHED) { + //TODO re-check + updateActionCount(); + enableProcessBtn(); } + } @PreDestroy @@ -637,8 +665,8 @@ public class UploadLayout extends VerticalLayout { * @param selectedBaseSoftwareModule */ public void refreshArtifactDetailsLayout(final SoftwareModule selectedBaseSoftwareModule) { - eventBus.publish(this, - new SoftwareModuleEvent(SoftwareModuleEventType.ARTIFACTS_CHANGED, selectedBaseSoftwareModule)); + eventBus.publish(this, new SoftwareModuleEvent(SoftwareModuleEventType.ARTIFACTS_CHANGED, + selectedBaseSoftwareModule)); } /** @@ -655,4 +683,55 @@ public class UploadLayout extends VerticalLayout { public void setHasDirectory(final Boolean hasDirectory) { this.hasDirectory = hasDirectory; } + + private void createUploadStatusButton() { + uploadStatusButton = SPUIComponentProvider.getButton(SPUIComponetIdProvider.UPLOAD_STATUS_BUTTON, "", "", "", + false, null, SPUIButtonStyleSmall.class); + uploadStatusButton.setStyleName(SPUIStyleDefinitions.ACTION_BUTTON); + uploadStatusButton.addStyleName(SPUIStyleDefinitions.UPLOAD_PROGRESS_INDICATOR_STYLE); + uploadStatusButton.setWidth("100px"); + uploadStatusButton.setHtmlContentAllowed(true); + uploadStatusButton.addClickListener(event -> onClickOfUploadStatusButton()); + uploadStatusButton.setVisible(false); + } + + private void onClickOfUploadStatusButton() { + artifactUploadState.setStatusPopupMinimized(false); + eventBus.publish(this, UploadArtifactUIEvent.MAXIMIZED_STATUS_POPUP); + } + + private void showUploadStatusButton() { + if (uploadStatusButton == null) { + return; + } + uploadStatusButton.setVisible(true); + } + + private void hideUploadStatusButton() { + if (uploadStatusButton == null) { + return; + } + uploadStatusButton.setVisible(false); + } + + private void maximizeStatusPopup() { + hideUploadStatusButton(); + uploadInfoWindow.maximizeStatusPopup(); + } + + private void setUploadStatusButtonIconToFinished() { + if (uploadStatusButton == null) { + return; + } + uploadStatusButton.removeStyleName(SPUIStyleDefinitions.UPLOAD_PROGRESS_INDICATOR_STYLE); + uploadStatusButton.setIcon(FontAwesome.UPLOAD); + } + + private void setUploadStatusButtonIconToInProgress() { + if (uploadStatusButton == null) { + return; + } + uploadStatusButton.addStyleName(SPUIStyleDefinitions.UPLOAD_PROGRESS_INDICATOR_STYLE); + uploadStatusButton.setIcon(null); + } } 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 8b36ef39e..4693ab3dc 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 @@ -8,20 +8,37 @@ */ package org.eclipse.hawkbit.ui.artifacts.upload; -import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions; +import java.util.List; +import java.util.stream.Collectors; +import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent; +import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState; +import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; +import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder; +import org.eclipse.hawkbit.ui.utils.SPUIComponetIdProvider; +import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions; +import org.springframework.beans.factory.annotation.Autowired; +import org.vaadin.spring.events.EventBus; + +import com.vaadin.data.Container.Indexed; import com.vaadin.data.Item; import com.vaadin.data.util.IndexedContainer; import com.vaadin.server.FontAwesome; import com.vaadin.shared.ui.window.WindowMode; import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.ViewScope; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Grid; import com.vaadin.ui.Grid.SelectionMode; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; import com.vaadin.ui.UI; +import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.Window; import com.vaadin.ui.renderers.HtmlRenderer; import com.vaadin.ui.renderers.ProgressBarRenderer; +import com.vaadin.ui.themes.ValoTheme; import elemental.json.JsonValue; @@ -34,7 +51,13 @@ import elemental.json.JsonValue; @ViewScope @SpringComponent -public class UploadStatusInfoWindow extends Window implements Window.CloseListener, Window.WindowModeChangeListener { +public class UploadStatusInfoWindow extends Window { + + @Autowired + private transient EventBus.SessionEventBus eventBus; + + @Autowired + private ArtifactUploadState artifactUploadState; private static final String PROGRESS = "Progress"; @@ -52,39 +75,105 @@ public class UploadStatusInfoWindow extends Window implements Window.CloseListen private volatile boolean errorOccured = false; + private Button minimizeButton; + + private VerticalLayout mainLayout; + + private Label windowCaption; + + private Button closeButton; + + private Button resizeButton; + /** * Default Constructor. */ UploadStatusInfoWindow() { - super("Upload Status"); + super(); - addStyleName(SPUIStyleDefinitions.UPLOAD_INFO); - center(); - setImmediate(true); - setResizable(true); - setDraggable(true); - setClosable(true); - uploads = new IndexedContainer(); - uploads.addContainerProperty(STATUS, String.class, "Active"); - uploads.addContainerProperty(FILE_NAME, String.class, null); - uploads.addContainerProperty(PROGRESS, Double.class, 0D); - uploads.addContainerProperty(REASON, String.class, ""); + setPopupProperties(); + createStatusPopupHeaderComponents(); - grid = new Grid(uploads); - grid.addStyleName(SPUIStyleDefinitions.UPLOAD_STATUS_GRID); - grid.setSelectionMode(SelectionMode.NONE); - grid.getColumn(STATUS).setRenderer(new StatusRenderer()); - grid.getColumn(PROGRESS).setRenderer(new ProgressBarRenderer()); - setColumnWidth(); - grid.setFrozenColumnCount(4); - grid.setColumnOrder(STATUS, PROGRESS, FILE_NAME, REASON); - grid.setHeaderVisible(true); - grid.setImmediate(true); + mainLayout = new VerticalLayout(); + mainLayout.setSpacing(Boolean.TRUE); + mainLayout.setSizeUndefined(); setPopupSizeInMinMode(); - setContent(grid); - addCloseListener(this); - addWindowModeChangeListener(this); + uploads = getGridContainer(); + grid = createGrid(); + setGridColumnProperties(); + + mainLayout.addComponents(getCaptionLayout(), grid); + mainLayout.setExpandRatio(grid, 1.0F); + setContent(mainLayout); + } + + private void restoreState() { + Indexed container = grid.getContainerDataSource(); + if (container.getItemIds().isEmpty()) { + container.removeAllItems(); + for (UploadStatusObject statusObject : artifactUploadState.getUploadedFileStatusList()) { + Item item = container.addItem(statusObject.getFilename()); + item.getItemProperty(REASON).setValue(statusObject.getReason() != null ? statusObject.getReason() : ""); + item.getItemProperty(STATUS).setValue(statusObject.getStatus()); + item.getItemProperty(PROGRESS).setValue(statusObject.getProgress()); + item.getItemProperty(FILE_NAME).setValue(statusObject.getFilename()); + } + artifactUploadState.setUploadCompleted(true); + minimizeButton.setEnabled(false); + } + } + + private void setPopupProperties() { + addStyleName(SPUIStyleDefinitions.UPLOAD_INFO); + setImmediate(true); + setResizable(false); + setDraggable(true); + setClosable(false); + } + + private void setGridColumnProperties() { + grid.getColumn(STATUS).setRenderer(new StatusRenderer()); + grid.getColumn(PROGRESS).setRenderer(new ProgressBarRenderer()); + grid.setColumnOrder(STATUS, PROGRESS, FILE_NAME, REASON); + setColumnWidth(); + grid.setFrozenColumnCount(4); + } + + private Grid createGrid() { + Grid statusGrid = new Grid(uploads); + statusGrid.addStyleName(SPUIStyleDefinitions.UPLOAD_STATUS_GRID); + statusGrid.setSelectionMode(SelectionMode.NONE); + statusGrid.setHeaderVisible(true); + statusGrid.setImmediate(true); + statusGrid.setSizeFull(); + return statusGrid; + } + + private IndexedContainer getGridContainer() { + IndexedContainer uploadContainer = new IndexedContainer(); + uploadContainer.addContainerProperty(STATUS, String.class, "Active"); + uploadContainer.addContainerProperty(FILE_NAME, String.class, null); + uploadContainer.addContainerProperty(PROGRESS, Double.class, 0D); + uploadContainer.addContainerProperty(REASON, String.class, ""); + return uploadContainer; + } + + private HorizontalLayout getCaptionLayout() { + final HorizontalLayout captionLayout = new HorizontalLayout(); + captionLayout.setSizeFull(); + captionLayout.setHeight("36px"); + captionLayout.addComponents(windowCaption, minimizeButton, resizeButton, closeButton); + captionLayout.setExpandRatio(windowCaption, 1.0F); + captionLayout.addStyleName("v-window-header"); + return captionLayout; + } + + private void createStatusPopupHeaderComponents() { + minimizeButton = getMinimizeButton(); + windowCaption = new Label("Upload status"); + closeButton = getCloseButton(); + resizeButton = getResizeButton(); } private void setColumnWidth() { @@ -99,15 +188,13 @@ public class UploadStatusInfoWindow extends Window implements Window.CloseListen grid.getColumn(PROGRESS).setWidthUndefined(); grid.getColumn(FILE_NAME).setWidthUndefined(); grid.getColumn(REASON).setWidthUndefined(); - } private static class StatusRenderer extends HtmlRenderer { @Override public JsonValue encode(final String value) { - - String result = ""; + String result ; switch (value) { case "Finished": result = "
" + FontAwesome.CHECK_CIRCLE.getHtml() + "
"; @@ -129,28 +216,52 @@ public class UploadStatusInfoWindow extends Window implements Window.CloseListen void uploadSessionFinished() { if (!errorOccured) { close(); + eventBus.publish(this, UploadArtifactUIEvent.UPLOAD_FINISHED); + artifactUploadState.setUploadCompleted(true); + minimizeButton.setEnabled(false); } } void uploadSessionStarted() { close(); + openWindow(); + minimizeButton.setEnabled(true); + eventBus.publish(this, UploadArtifactUIEvent.UPLOAD_STARTED); + artifactUploadState.setUploadCompleted(false); + } + + void openWindow() { UI.getCurrent().addWindow(this); center(); } + void maximizeStatusPopup() { + openWindow(); + restoreState(); + } + void uploadStarted(final String filename) { final Item item = uploads.addItem(filename); item.getItemProperty(FILE_NAME).setValue(filename); grid.scrollToEnd(); - + UploadStatusObject uploadStatus = new UploadStatusObject(filename); + uploadStatus.setStatus("Active"); + artifactUploadState.getUploadedFileStatusList().add(uploadStatus); } void updateProgress(final String filename, final long readBytes, final long contentLength) { final Item item = uploads.getItem(filename); if (item != null) { - item.getItemProperty(PROGRESS).setValue((double) readBytes / (double) contentLength); - + double progress = (double) readBytes / (double) contentLength; + item.getItemProperty(PROGRESS).setValue(progress); + List uploadStatusObjectList = (List) artifactUploadState + .getUploadedFileStatusList().stream().filter(e -> e.getFilename().equals(filename)) + .collect(Collectors.toList()); + if (!uploadStatusObjectList.isEmpty()) { + UploadStatusObject uploadStatusObject = uploadStatusObjectList.get(0); + uploadStatusObject.setProgress(progress); + } } } @@ -163,8 +274,15 @@ public class UploadStatusInfoWindow extends Window implements Window.CloseListen public void uploadSucceeded(final String filename) { final Item item = uploads.getItem(filename); if (item != null) { - item.getItemProperty(STATUS).setValue("Finished"); - + String status = "Finished"; + item.getItemProperty(STATUS).setValue(status); + List uploadStatusObjectList = (List) artifactUploadState + .getUploadedFileStatusList().stream().filter(e -> e.getFilename().equals(filename)) + .collect(Collectors.toList()); + if (!uploadStatusObjectList.isEmpty()) { + UploadStatusObject uploadStatusObject = uploadStatusObjectList.get(0); + uploadStatusObject.setStatus(status); + } } } @@ -175,51 +293,81 @@ public class UploadStatusInfoWindow extends Window implements Window.CloseListen errorOccured = true; } item.getItemProperty(REASON).setValue(errorReason); - item.getItemProperty(STATUS).setValue("Failed"); - + String status = "Failed"; + item.getItemProperty(STATUS).setValue(status); + List uploadStatusObjectList = (List) artifactUploadState + .getUploadedFileStatusList().stream().filter(e -> e.getFilename().equals(filename)) + .collect(Collectors.toList()); + if (!uploadStatusObjectList.isEmpty()) { + UploadStatusObject uploadStatusObject = uploadStatusObjectList.get(0); + uploadStatusObject.setStatus(status); + uploadStatusObject.setReason(errorReason); + } } } - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Window.CloseListener#windowClose(com.vaadin.ui.Window. - * CloseEvent) - */ - @Override - public void windowClose(final CloseEvent e) { - clearWindow(); - } - - private void clearWindow() { + protected void clearWindow() { errorOccured = false; uploads.removeAllItems(); setWindowMode(WindowMode.NORMAL); + this.close(); + artifactUploadState.getUploadedFileStatusList().clear(); } - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.Window.WindowModeChangeListener#windowModeChanged(com. - * vaadin.ui.Window. WindowModeChangeEvent) - */ - @Override - public void windowModeChanged(final WindowModeChangeEvent event) { - if (event.getWindow().getWindowMode() == WindowMode.MAXIMIZED) { + private void setPopupSizeInMinMode() { + mainLayout.setWidth(800, Unit.PIXELS); + mainLayout.setHeight(510, Unit.PIXELS); + } + + private Button getMinimizeButton() { + final Button minimizeBtn = SPUIComponentProvider.getButton( + SPUIComponetIdProvider.UPLOAD_STATUS_POPUP_MINIMIZE_BUTTON_ID, "", "", "", true, FontAwesome.MINUS, + SPUIButtonStyleSmallNoBorder.class); + minimizeBtn.addStyleName(ValoTheme.BUTTON_BORDERLESS); + minimizeBtn.addClickListener(event -> minimizeWindow()); + minimizeBtn.setEnabled(true); + return minimizeBtn; + } + + private Button getResizeButton() { + final Button resizeBtn = SPUIComponentProvider.getButton( + SPUIComponetIdProvider.UPLOAD_STATUS_POPUP_RESIZE_BUTTON_ID, "", "", "", true, FontAwesome.EXPAND, + SPUIButtonStyleSmallNoBorder.class); + resizeBtn.addStyleName(ValoTheme.BUTTON_BORDERLESS); + resizeBtn.addClickListener(event -> resizeWindow(event)); + return resizeBtn; + } + + private void resizeWindow(ClickEvent event) { + if (event.getButton().getIcon() == FontAwesome.EXPAND) { + event.getButton().setIcon(FontAwesome.COMPRESS); + setWindowMode(WindowMode.MAXIMIZED); resetColumnWidth(); grid.getColumn(STATUS).setExpandRatio(0); grid.getColumn(PROGRESS).setExpandRatio(1); grid.getColumn(FILE_NAME).setExpandRatio(2); grid.getColumn(REASON).setExpandRatio(3); - grid.setSizeFull(); + mainLayout.setSizeFull(); } else { + event.getButton().setIcon(FontAwesome.EXPAND); + setWindowMode(WindowMode.NORMAL); setColumnWidth(); setPopupSizeInMinMode(); } } - private void setPopupSizeInMinMode() { - grid.setWidth(800, Unit.PIXELS); - grid.setHeight(510, Unit.PIXELS); + private void minimizeWindow() { + this.close(); + artifactUploadState.setStatusPopupMinimized(true); + eventBus.publish(this, UploadArtifactUIEvent.MINIMIZED_STATUS_POPUP); + } + + private Button getCloseButton() { + final Button closeBtn = SPUIComponentProvider.getButton( + SPUIComponetIdProvider.UPLOAD_STATUS_POPUP_CLOSE_BUTTON_ID, "", "", "", true, FontAwesome.TIMES, + SPUIButtonStyleSmallNoBorder.class); + closeBtn.addStyleName(ValoTheme.BUTTON_BORDERLESS); + closeBtn.addClickListener(event -> clearWindow()); + return closeBtn; } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadStatusObject.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadStatusObject.java new file mode 100644 index 000000000..80c71fe7b --- /dev/null +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadStatusObject.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2015 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.ui.artifacts.upload; + +public class UploadStatusObject { + private String status; + private Double progress; + private String filename; + private String reason; + + public UploadStatusObject(String status, Double progress, String fileName, String reason) { + this(fileName); + this.status = status; + this.progress = progress; + this.reason = reason; + } + + public UploadStatusObject(String fileName) { + this.filename = fileName; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public Double getProgress() { + return progress; + } + + public void setProgress(Double progress) { + this.progress = progress; + } + + public String getFilename() { + return filename; + } + + public void setFilename(String filename) { + this.filename = filename; + } + + public String getReason() { + return reason; + } + + public void setReason(String reason) { + this.reason = reason; + } + + @Override + public boolean equals(Object obj) { + if (this == null || obj == null) { + return false; + } + if (obj instanceof UploadStatusObject && this.getFilename() == ((UploadStatusObject) obj).getFilename()) { + return true; + } + return false; + } + +} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/footer/AbstractDeleteActionsLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/footer/AbstractDeleteActionsLayout.java index 75bd43447..09ab92cee 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/footer/AbstractDeleteActionsLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/footer/AbstractDeleteActionsLayout.java @@ -130,7 +130,7 @@ public abstract class AbstractDeleteActionsLayout extends VerticalLayout impleme addComponent(hLayout); setComponentAlignment(hLayout, Alignment.BOTTOM_CENTER); } - setStyleName("footer-layout"); + setStyleName(SPUIStyleDefinitions.FOOTER_LAYOUT); setWidth("100%"); } @@ -168,7 +168,7 @@ public abstract class AbstractDeleteActionsLayout extends VerticalLayout impleme final Button button = SPUIComponentProvider.getButton(SPUIComponetIdProvider.BULK_UPLOAD_STATUS_BUTTON, "", "", "", false, null, SPUIButtonStyleSmall.class); button.setStyleName(SPUIStyleDefinitions.ACTION_BUTTON); - button.addStyleName(SPUIStyleDefinitions.BULK_UPLOAD_PROGRESS_INDICATOR_STYLE); + button.addStyleName(SPUIStyleDefinitions.UPLOAD_PROGRESS_INDICATOR_STYLE); button.setWidth("100px"); button.setHtmlContentAllowed(true); button.addClickListener(event -> onClickBulkUploadNotificationButton()); @@ -199,7 +199,7 @@ public abstract class AbstractDeleteActionsLayout extends VerticalLayout impleme if (bulkUploadStatusButton == null) { return; } - bulkUploadStatusButton.removeStyleName(SPUIStyleDefinitions.BULK_UPLOAD_PROGRESS_INDICATOR_STYLE); + bulkUploadStatusButton.removeStyleName(SPUIStyleDefinitions.UPLOAD_PROGRESS_INDICATOR_STYLE); bulkUploadStatusButton.setIcon(FontAwesome.UPLOAD); } @@ -207,7 +207,7 @@ public abstract class AbstractDeleteActionsLayout extends VerticalLayout impleme if (bulkUploadStatusButton == null) { return; } - bulkUploadStatusButton.addStyleName(SPUIStyleDefinitions.BULK_UPLOAD_PROGRESS_INDICATOR_STYLE); + bulkUploadStatusButton.addStyleName(SPUIStyleDefinitions.UPLOAD_PROGRESS_INDICATOR_STYLE); bulkUploadStatusButton.setIcon(null); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/grid/AbstractGridLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/grid/AbstractGridLayout.java index 98c14e698..308bbeec4 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/grid/AbstractGridLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/grid/AbstractGridLayout.java @@ -9,6 +9,7 @@ package org.eclipse.hawkbit.ui.common.grid; import org.eclipse.hawkbit.ui.utils.SPUIComponetIdProvider; +import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions; import com.vaadin.ui.Alignment; import com.vaadin.ui.HorizontalLayout; @@ -72,7 +73,7 @@ public abstract class AbstractGridLayout extends VerticalLayout { final Label countMessageLabel = getCountMessageLabel(); countMessageLabel.setId(SPUIComponetIdProvider.ROLLOUT_GROUP_TARGET_LABEL); rolloutGroupTargetsCountLayout.addComponent(getCountMessageLabel()); - rolloutGroupTargetsCountLayout.setStyleName("footer-layout"); + rolloutGroupTargetsCountLayout.setStyleName(SPUIStyleDefinitions.FOOTER_LAYOUT); rolloutGroupTargetsCountLayout.setWidth("100%"); return rolloutGroupTargetsCountLayout; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/FilterManagementView.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/FilterManagementView.java index 06cbe4d69..99c586070 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/FilterManagementView.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/FilterManagementView.java @@ -14,6 +14,7 @@ import org.eclipse.hawkbit.ui.HawkbitUI; import org.eclipse.hawkbit.ui.filtermanagement.event.CustomFilterUIEvent; import org.eclipse.hawkbit.ui.filtermanagement.footer.TargetFilterCountMessageLabel; import org.eclipse.hawkbit.ui.filtermanagement.state.FilterManagementUIState; +import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions; import org.springframework.beans.factory.annotation.Autowired; import org.vaadin.spring.events.EventBus; import org.vaadin.spring.events.EventScope; @@ -151,7 +152,7 @@ public class FilterManagementView extends VerticalLayout implements View { private HorizontalLayout addTargetFilterMessageLabel() { final HorizontalLayout messageLabelLayout = new HorizontalLayout(); messageLabelLayout.addComponent(targetFilterCountMessageLabel); - messageLabelLayout.addStyleName("footer-layout"); + messageLabelLayout.addStyleName(SPUIStyleDefinitions.FOOTER_LAYOUT); return messageLabelLayout; } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIComponetIdProvider.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIComponetIdProvider.java index 48e501e1d..7c25bf90a 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIComponetIdProvider.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIComponetIdProvider.java @@ -883,6 +883,27 @@ public final class SPUIComponetIdProvider { */ public static final String VALIDATION_STATUS_ICON_ID = "validation.status.icon"; + /** + * Artifact upload status popup - minimize button id. + */ + public static final String UPLOAD_STATUS_POPUP_MINIMIZE_BUTTON_ID = "artifact.upload.minimize.button.id"; + + /** + * Artifact upload status popup - close button id. + */ + public static final String UPLOAD_STATUS_POPUP_CLOSE_BUTTON_ID = "artifact.upload.close.button.id"; + + /** + * Artifact upload status popup - resize button id. + */ + public static final String UPLOAD_STATUS_POPUP_RESIZE_BUTTON_ID = "artifact.upload.resize.button.id"; + + /** + * Artifact upload view - upload status button id. + */ + public static final String UPLOAD_STATUS_BUTTON = "artficat.upload.status.button.id"; + + /** * /* Private Constructor. */ diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIStyleDefinitions.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIStyleDefinitions.java index c50135251..ac713a07c 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIStyleDefinitions.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIStyleDefinitions.java @@ -240,9 +240,9 @@ public final class SPUIStyleDefinitions { public static final String DISABLE_ACTION_TYPE_LAYOUT = "disable-action-type-layout"; /** - * Bulk upload progress indicator style. + * Upload progress indicator style. */ - public static final String BULK_UPLOAD_PROGRESS_INDICATOR_STYLE = "app-loading"; + public static final String UPLOAD_PROGRESS_INDICATOR_STYLE = "app-loading"; /** * Target filter search progress indicator style. @@ -293,6 +293,11 @@ public final class SPUIStyleDefinitions { * Status pending icon. */ public static final String STATUS_ICON_PENDING = "statusIconPending"; + + /** + * Footer layout style. + */ + public static final String FOOTER_LAYOUT = "footer-layout"; /** * Constructor.