Remove footer, expand layout and move functions to other elements (#689)

* Remove process and discard upload buttons; change upload process to only have one upload status window that is displayed immediately when an upload is triggered.
* Separation of FileTransferHandler: FileTransferHandler was split into 3 parts. One common part remains in the abstract super class. The other pieces were moved to the upload-specific and the streaming-specific subclasses.
* Fix upload process: Fix status visualization in progress window. Move repository transfer to the file upload handler so it can report if the complete upload process succeeded or failed.
* Prevent file upload if no software module or more than one is selected.
* Added Unit Tests and fixed Sonar findings.
* Move upload button from the buttom to the right side of the drag and drop area.
* Remove minimize and resize buttons in progress dialog. Remove unused code.
* Code cleanup and layout adaptions: Remove unnecessary code and fix layout problems when showing the upload button on the right side of the drag and drop area.
* Removed abort functionality for user because of Vaadin bug https://github.com/vaadin/framework/issues/10545
* Fixed Vaadin upload bug by subclassing Upload and overriding necessary methods.
* Disable drag-and-drop area in case no OR more than one software module selected.
* Enhance /adapt unit tests
* Enhance /adapt UI tests

Signed-off-by: Markus Block <markus.block@bosch-si.com>

* First draw, insert delete button in entity tables
* Add shortcuts to cancel/confirm buttons in confirmation dialog
* First draw, target/distribution assignment
* Entity assignments for tables
* Fix table row mark correctly when assigning entities
* Mark the right entity in table when deleting an entity
* Refactor code for distribution tags on deployment view
* Target Tags can be managed with Menu Bar
* Refactor classes for managing tags and types for all entities
* Disable fields correctly when updating/deleting tags and types
* Remove delete and action buttons in the bottom
* Delete Metadata column in tables
* Redesign tables for tags and types. Show action icon for update/delete
* Correct CSS for menubar for tag/type actions
* Add confirmation window when deleting tag or type
* Remove unused code. Fix style for target tag config menu bar
* New abstract classes for target/ds tags
* Reorganize package structure tags, set ids for tags
* Add total targets count in target table, add close icon for menubar
* Add total target label and remove footer styles
* MenuBar is displayed when update/delete action is cancelled, finished, or update/delete modus is left
* Insert EventHandling for show menuBar/CancelButton
* Delete drag & drop criteria where not needed anymore
* Fix mandatory field check in DistributionTypeLayout
* Fix notification message
* Move upload button into drop area
* Enhance /adapt unit tests
* Enhance /adapt UI tests

Signed-off-by: Melanie Retter <melanie.retter@bosch-si.com>
This commit is contained in:
Melanie Retter
2018-07-02 09:09:13 +02:00
committed by Stefan Behl
parent bafce18db6
commit f5f51bfc2c
190 changed files with 8520 additions and 10691 deletions

View File

@@ -202,10 +202,10 @@ public interface TargetManagement {
void delete(@NotEmpty Collection<Long> targetIDs);
/**
* Deletes target with the given IDs.
* Deletes target with the given controller ID.
*
* @param controllerID
* the ID of the targets to be deleted
* the controller ID of the target to be deleted
*
* @throws EntityNotFoundException
* if target with given ID does not exist

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType">
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="false"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_DISABLED_BUILDER" value="org.eclipse.m2e.core.maven2Builder"/>
<mapAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
</launchConfiguration>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType">
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="false"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_DISABLED_BUILDER" value="org.sonarlint.eclipse.core.sonarlintBuilder"/>
<mapAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
</launchConfiguration>

View File

@@ -10,7 +10,7 @@ package org.eclipse.hawkbit.ui;
import org.eclipse.hawkbit.ui.menu.DashboardMenu;
import org.eclipse.hawkbit.ui.menu.DashboardMenuItem;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.springframework.beans.factory.annotation.Autowired;
@@ -64,7 +64,7 @@ public class ErrorView extends VerticalLayout implements View {
final Notification nt = new Notification("Access denied",
i18n.getMessage("message.accessdenied.view", new Object[] { event.getViewName() }),
Type.ERROR_MESSAGE, false);
nt.setStyleName(SPUILabelDefinitions.SP_NOTIFICATION_ERROR_MESSAGE_STYLE);
nt.setStyleName(SPUIStyleDefinitions.SP_NOTIFICATION_ERROR_MESSAGE_STYLE);
nt.setPosition(Position.BOTTOM_RIGHT);
nt.show(UI.getCurrent().getPage());
message.setValue(i18n.getMessage("message.accessdenied.view", new Object[] { event.getViewName() }));

View File

@@ -21,11 +21,11 @@ import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.artifacts.details.ArtifactDetailsLayout;
import org.eclipse.hawkbit.ui.artifacts.event.ArtifactDetailsEvent;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent;
import org.eclipse.hawkbit.ui.artifacts.footer.SMDeleteActionsLayout;
import org.eclipse.hawkbit.ui.artifacts.smtable.SoftwareModuleTableLayout;
import org.eclipse.hawkbit.ui.artifacts.smtype.SMTypeFilterLayout;
import org.eclipse.hawkbit.ui.artifacts.smtype.filter.SMTypeFilterButtons;
import org.eclipse.hawkbit.ui.artifacts.smtype.filter.SMTypeFilterLayout;
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
import org.eclipse.hawkbit.ui.artifacts.upload.UploadLayout;
import org.eclipse.hawkbit.ui.artifacts.upload.UploadDropAreaLayout;
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.dd.criteria.UploadViewClientCriterion;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
@@ -45,9 +45,7 @@ import com.vaadin.server.Page.BrowserWindowResizeListener;
import com.vaadin.spring.annotation.SpringView;
import com.vaadin.spring.annotation.UIScope;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.DragAndDropWrapper;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.VerticalLayout;
/**
@@ -77,18 +75,12 @@ public class UploadArtifactView extends VerticalLayout implements View, BrowserW
private final ArtifactDetailsLayout artifactDetailsLayout;
private final UploadLayout uploadLayout;
private final SMDeleteActionsLayout deleteActionsLayout;
private final UploadDropAreaLayout dropAreaLayout;
private VerticalLayout detailAndUploadLayout;
private HorizontalLayout uplaodButtonsLayout;
private GridLayout mainLayout;
private DragAndDropWrapper dadw;
@Autowired
UploadArtifactView(final UIEventBus eventBus, final SpPermissionChecker permChecker, final VaadinMessageSource i18n,
final UINotification uiNotification, final ArtifactUploadState artifactUploadState,
@@ -101,17 +93,18 @@ public class UploadArtifactView extends VerticalLayout implements View, BrowserW
this.i18n = i18n;
this.uiNotification = uiNotification;
this.artifactUploadState = artifactUploadState;
this.filterByTypeLayout = new SMTypeFilterLayout(artifactUploadState, i18n, permChecker, eventBus,
entityFactory, uiNotification, softwareModuleTypeManagement, uploadViewClientCriterion);
this.smTableLayout = new SoftwareModuleTableLayout(i18n, permChecker, artifactUploadState, uiNotification,
eventBus, softwareModuleManagement, softwareModuleTypeManagement, entityFactory,
uploadViewClientCriterion);
this.artifactDetailsLayout = new ArtifactDetailsLayout(i18n, eventBus, artifactUploadState, uiNotification,
artifactManagement, softwareModuleManagement);
this.uploadLayout = new UploadLayout(i18n, uiNotification, eventBus, artifactUploadState,
multipartConfigElement, artifactManagement, softwareModuleManagement);
this.deleteActionsLayout = new SMDeleteActionsLayout(i18n, permChecker, eventBus, uiNotification,
artifactUploadState, softwareModuleManagement, softwareModuleTypeManagement, uploadViewClientCriterion);
final SMTypeFilterButtons smTypeFilterButtons = new SMTypeFilterButtons(eventBus, artifactUploadState,
uploadViewClientCriterion, softwareModuleTypeManagement, i18n, entityFactory, permChecker,
uiNotification);
this.filterByTypeLayout = new SMTypeFilterLayout(artifactUploadState, i18n, permChecker, eventBus,
entityFactory, uiNotification, softwareModuleTypeManagement, smTypeFilterButtons);
this.dropAreaLayout = new UploadDropAreaLayout(i18n, eventBus, uiNotification, artifactUploadState,
multipartConfigElement, softwareModuleManagement, artifactManagement);
}
@PostConstruct
@@ -168,15 +161,13 @@ public class UploadArtifactView extends VerticalLayout implements View, BrowserW
private VerticalLayout createDetailsAndUploadLayout() {
detailAndUploadLayout = new VerticalLayout();
detailAndUploadLayout.addComponent(artifactDetailsLayout);
detailAndUploadLayout.setComponentAlignment(artifactDetailsLayout, Alignment.MIDDLE_CENTER);
detailAndUploadLayout.setComponentAlignment(artifactDetailsLayout, Alignment.TOP_CENTER);
detailAndUploadLayout.setExpandRatio(artifactDetailsLayout, 1.0F);
if (permChecker.hasCreateRepositoryPermission()) {
dadw = uploadLayout.getDropAreaWrapper();
detailAndUploadLayout.addComponent(dadw);
detailAndUploadLayout.setComponentAlignment(dadw, Alignment.MIDDLE_CENTER);
detailAndUploadLayout.addComponent(dropAreaLayout.getDropAreaWrapper());
}
detailAndUploadLayout.setExpandRatio(artifactDetailsLayout, 1.0F);
detailAndUploadLayout.setSizeFull();
detailAndUploadLayout.addStyleName("group");
detailAndUploadLayout.setSpacing(true);
@@ -185,28 +176,19 @@ public class UploadArtifactView extends VerticalLayout implements View, BrowserW
private GridLayout createMainLayout() {
createDetailsAndUploadLayout();
createUploadButtonLayout();
mainLayout = new GridLayout(3, 2);
mainLayout = new GridLayout(3, 1);
mainLayout.setSizeFull();
mainLayout.setSpacing(true);
mainLayout.setStyleName("fullSize");
mainLayout.addComponent(filterByTypeLayout, 0, 0);
mainLayout.addComponent(smTableLayout, 1, 0);
mainLayout.addComponent(detailAndUploadLayout, 2, 0);
mainLayout.addComponent(deleteActionsLayout, 1, 1);
mainLayout.addComponent(uplaodButtonsLayout, 2, 1);
mainLayout.setRowExpandRatio(0, 1.0F);
mainLayout.setColumnExpandRatio(1, 0.5F);
mainLayout.setColumnExpandRatio(2, 0.5F);
mainLayout.setComponentAlignment(deleteActionsLayout, Alignment.BOTTOM_CENTER);
mainLayout.setComponentAlignment(uplaodButtonsLayout, Alignment.BOTTOM_CENTER);
return mainLayout;
}
private void createUploadButtonLayout() {
uplaodButtonsLayout = new HorizontalLayout();
if (permChecker.hasCreateRepositoryPermission()) {
uplaodButtonsLayout = uploadLayout.getFileUploadLayout();
}
return mainLayout;
}
private void minimizeSwTable() {
@@ -216,14 +198,13 @@ public class UploadArtifactView extends VerticalLayout implements View, BrowserW
private void maximizeSwTable() {
mainLayout.removeComponent(detailAndUploadLayout);
removeOtherComponents();
mainLayout.setColumnExpandRatio(1, 1F);
mainLayout.setColumnExpandRatio(2, 0F);
}
private void minimizeArtifactoryDetails() {
mainLayout.setSpacing(true);
detailAndUploadLayout.addComponent(dadw);
detailAndUploadLayout.addComponent(dropAreaLayout.getDropAreaWrapper());
mainLayout.addComponent(filterByTypeLayout, 0, 0);
mainLayout.addComponent(smTableLayout, 1, 0);
addOtherComponents();
@@ -233,24 +214,14 @@ public class UploadArtifactView extends VerticalLayout implements View, BrowserW
mainLayout.setSpacing(false);
mainLayout.removeComponent(filterByTypeLayout);
mainLayout.removeComponent(smTableLayout);
detailAndUploadLayout.removeComponent(dadw);
removeOtherComponents();
detailAndUploadLayout.removeComponent(dropAreaLayout.getDropAreaWrapper());
mainLayout.setColumnExpandRatio(1, 0F);
mainLayout.setColumnExpandRatio(2, 1F);
}
private void addOtherComponents() {
mainLayout.addComponent(deleteActionsLayout, 1, 1);
mainLayout.addComponent(uplaodButtonsLayout, 2, 1);
mainLayout.setColumnExpandRatio(1, 0.5F);
mainLayout.setColumnExpandRatio(2, 0.5F);
mainLayout.setComponentAlignment(deleteActionsLayout, Alignment.BOTTOM_CENTER);
mainLayout.setComponentAlignment(uplaodButtonsLayout, Alignment.BOTTOM_CENTER);
}
private void removeOtherComponents() {
mainLayout.removeComponent(deleteActionsLayout);
mainLayout.removeComponent(uplaodButtonsLayout);
}
private void checkNoDataAvaialble() {
@@ -278,6 +249,7 @@ public class UploadArtifactView extends VerticalLayout implements View, BrowserW
public void enter(final ViewChangeEvent event) {
smTableLayout.getSoftwareModuleTable()
.selectEntity(artifactUploadState.getSelectedBaseSwModuleId().orElse(null));
dropAreaLayout.getUploadButtonLayout().restoreState();
}
}

View File

@@ -9,6 +9,7 @@
package org.eclipse.hawkbit.ui.artifacts.details;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
@@ -27,7 +28,7 @@ import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.components.SPUIButton;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleNoBorder;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
@@ -180,10 +181,9 @@ public class ArtifactDetailsLayout extends VerticalLayout {
private SPUIButton createMaxMinButton() {
final SPUIButton button = (SPUIButton) SPUIComponentProvider.getButton(SPUIDefinitions.EXPAND_ACTION_HISTORY,
"", "", null, true, FontAwesome.EXPAND, SPUIButtonStyleSmallNoBorder.class);
"", "", null, true, FontAwesome.EXPAND, SPUIButtonStyleNoBorder.class);
button.addClickListener(event -> maxArtifactDetails());
return button;
}
private void buildLayout() {
@@ -267,31 +267,24 @@ public class ArtifactDetailsLayout extends VerticalLayout {
final Button deleteIcon = SPUIComponentProvider.getButton(
fileName + "-" + UIComponentIdProvider.UPLOAD_FILE_DELETE_ICON, "",
SPUILabelDefinitions.DISCARD, ValoTheme.BUTTON_TINY + " " + "blueicon", true,
FontAwesome.TRASH_O, SPUIButtonStyleSmallNoBorder.class);
FontAwesome.TRASH_O, SPUIButtonStyleNoBorder.class);
deleteIcon.setData(itemId);
deleteIcon.addClickListener(event -> confirmAndDeleteArtifact((Long) itemId, fileName));
return deleteIcon;
}
});
}
private void confirmAndDeleteArtifact(final Long id, final String fileName) {
final ConfirmationDialog confirmDialog = new ConfirmationDialog(
i18n.getMessage("caption.delete.artifact.confirmbox"),
i18n.getMessage("message.delete.artifact", new Object[] { fileName }), i18n.getMessage("button.ok"),
i18n.getMessage("button.cancel"), ok -> {
i18n.getMessage("message.delete.artifact", new Object[] { fileName }),
i18n.getMessage(SPUIDefinitions.BUTTON_OK), i18n.getMessage(SPUIDefinitions.BUTTON_CANCEL), ok -> {
if (ok) {
artifactManagement.delete(id);
uINotification.displaySuccess(i18n.getMessage("message.artifact.deleted", fileName));
final Optional<SoftwareModule> softwareModule = findSelectedSoftwareModule();
if (softwareModule.isPresent()) {
populateArtifactDetails(softwareModule.get().getId(),
HawkbitCommonUtil.getFormattedNameVersion(softwareModule.get().getName(),
softwareModule.get().getVersion()));
} else {
populateArtifactDetails(null, null);
}
populateArtifactDetails(softwareModule.orElse(null));
}
});
UI.getCurrent().addWindow(confirmDialog.getWindow());
@@ -299,7 +292,6 @@ public class ArtifactDetailsLayout extends VerticalLayout {
}
private void setTableColumnDetails(final Table table) {
table.setColumnHeader(PROVIDED_FILE_NAME, i18n.getMessage("upload.file.name"));
table.setColumnHeader(SIZE, i18n.getMessage("upload.size"));
if (fullWindowMode) {
@@ -359,15 +351,13 @@ public class ArtifactDetailsLayout extends VerticalLayout {
private void maxArtifactDetails() {
final Boolean flag = (Boolean) maxMinButton.getData();
if (flag == null || Boolean.FALSE.equals(flag)) {
// Clicked on max Button
maximizedArtifactDetailsView();
} else {
// Clicked on min Button
minimizeArtifactDetailsView();
minimizedArtifactDetailsView();
}
}
private void minimizeArtifactDetailsView() {
private void minimizedArtifactDetailsView() {
fullWindowMode = Boolean.FALSE;
showMaxIcon();
setTableColumnDetails(artifactDetailsTable);
@@ -380,7 +370,6 @@ public class ArtifactDetailsLayout extends VerticalLayout {
showMinIcon();
setTableColumnDetails(artifactDetailsTable);
createArtifactDetailsMaxView();
}
/**
@@ -398,7 +387,6 @@ public class ArtifactDetailsLayout extends VerticalLayout {
}
private void createArtifactDetailsMaxView() {
artifactDetailsTable.setValue(null);
artifactDetailsTable.setSelectable(false);
artifactDetailsTable.setMultiSelect(false);
@@ -417,12 +405,19 @@ public class ArtifactDetailsLayout extends VerticalLayout {
/**
* Populate artifact details.
*
* @param baseSwModuleId
* software module id
* @param swModuleName
* software module name
* @param softwareModule
* software module
*/
public void populateArtifactDetails(final Long baseSwModuleId, final String swModuleName) {
public void populateArtifactDetails(final SoftwareModule softwareModule) {
if (softwareModule == null) {
populateArtifactDetails(null, null);
} else {
populateArtifactDetails(softwareModule.getId(),
HawkbitCommonUtil.getFormattedNameVersion(softwareModule.getName(), softwareModule.getVersion()));
}
}
private void populateArtifactDetails(final Long baseSwModuleId, final String swModuleName) {
if (!readOnly) {
if (StringUtils.isEmpty(swModuleName)) {
setTitleOfLayoutHeader();
@@ -456,18 +451,35 @@ public class ArtifactDetailsLayout extends VerticalLayout {
@EventBusListenerMethod(scope = EventScope.UI)
void onEvent(final SoftwareModuleEvent softwareModuleEvent) {
if (softwareModuleEvent.getEventType() == BaseEntityEventType.SELECTED_ENTITY
|| softwareModuleEvent.getSoftwareModuleEventType() == SoftwareModuleEventType.ARTIFACTS_CHANGED) {
if (softwareModuleEvent.getEventType() == BaseEntityEventType.SELECTED_ENTITY) {
UI.getCurrent().access(() -> {
if (softwareModuleEvent.getEntity() != null) {
populateArtifactDetails(softwareModuleEvent.getEntity().getId(),
HawkbitCommonUtil.getFormattedNameVersion(softwareModuleEvent.getEntity().getName(),
softwareModuleEvent.getEntity().getVersion()));
populateArtifactDetails(softwareModuleEvent.getEntity());
} else {
populateArtifactDetails(null, null);
}
});
}
if (isArtifactChangedEvent(softwareModuleEvent) && areEntityIdsNotEmpty(softwareModuleEvent)) {
UI.getCurrent().access(() -> findSelectedSoftwareModule().ifPresent(selectedSoftwareModule -> {
if (hasSelectedSoftwareModuleChanged(softwareModuleEvent.getEntityIds(), selectedSoftwareModule)) {
populateArtifactDetails(selectedSoftwareModule);
}
}));
}
}
private static boolean areEntityIdsNotEmpty(final SoftwareModuleEvent softwareModuleEvent) {
return softwareModuleEvent.getEntityIds() != null && !softwareModuleEvent.getEntityIds().isEmpty();
}
private static boolean isArtifactChangedEvent(final SoftwareModuleEvent softwareModuleEvent) {
return softwareModuleEvent.getSoftwareModuleEventType() == SoftwareModuleEventType.ARTIFACTS_CHANGED;
}
private static boolean hasSelectedSoftwareModuleChanged(final Collection<Long> changedSoftwareModuleIds,
final SoftwareModule selectedSoftwareModule) {
return changedSoftwareModuleIds.stream().anyMatch(smId -> selectedSoftwareModule.getId().equals(smId));
}
public Table getArtifactDetailsTable() {

View File

@@ -8,6 +8,7 @@
*/
package org.eclipse.hawkbit.ui.artifacts.event;
import java.util.Arrays;
import java.util.Collection;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
@@ -78,6 +79,19 @@ public class SoftwareModuleEvent extends BaseUIEntityEvent<SoftwareModule> {
this.softwareModuleEventType = softwareModuleEventType;
}
/**
* Creates software module event.
*
* @param softwareModuleEventType
* the event type
* @param softwareModuleId
* the id of the {@link SoftwareModule}
*/
public SoftwareModuleEvent(final SoftwareModuleEventType softwareModuleEventType, final long softwareModuleId) {
super(null, Arrays.asList(softwareModuleId), SoftwareModule.class);
this.softwareModuleEventType = softwareModuleEventType;
}
public SoftwareModuleEventType getSoftwareModuleEventType() {
return softwareModuleEventType;
}

View File

@@ -19,7 +19,7 @@ public class SoftwareModuleTypeEvent {
* Software module type events in the Upload UI.
*/
public enum SoftwareModuleTypeEnum {
ADD_SOFTWARE_MODULE_TYPE, DELETE_SOFTWARE_MODULE_TYPE, UPDATE_SOFTWARE_MODULE_TYPE
ADD_SOFTWARE_MODULE_TYPE, UPDATE_SOFTWARE_MODULE_TYPE
}
private SoftwareModuleType softwareModuleType;

View File

@@ -15,5 +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, 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, ARTIFACT_RESULT_POPUP_CLOSED
HIDE_DROP_HINTS, HIDE_FILTER_BY_TYPE, SHOW_FILTER_BY_TYPE, DISCARD_DELETE_SOFTWARE, DISCARD_ALL_DELETE_SOFTWARE, DELETED_ALL_SOFTWARE, DISCARD_DELETE_SOFTWARE_TYPE, DISCARD_ALL_DELETE_SOFTWARE_TYPE, DELETED_ALL_SOFTWARE_TYPE
}

View File

@@ -1,99 +0,0 @@
/**
* 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.event;
import java.io.Serializable;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
/**
*
* Holds file and upload status details.Meta data sent with upload events.
*
*/
public class UploadFileStatus implements Serializable {
private static final long serialVersionUID = -3599629192216760811L;
private final String fileName;
private long contentLength;
private long bytesRead;
private String failureReason;
private SoftwareModule softwareModule;
/**
* constructor for UploadFileStatus
*
* @param fileName
* name of the file to be uploaded
*/
public UploadFileStatus(final String fileName) {
this.fileName = fileName;
}
/**
* constructor for UploadFileStatus
*
* @param fileName
* name of the file to be uploaded
* @param bytesRead
* number of bytes
* @param contentLength
* length of the content (stream)
* @param softwareModule
* softwareModule
*/
public UploadFileStatus(final String fileName, final long bytesRead, final long contentLength,
final SoftwareModule softwareModule) {
this.fileName = fileName;
this.contentLength = contentLength;
this.bytesRead = bytesRead;
this.softwareModule = softwareModule;
}
/**
* constructor for UploadFileStatus
*
* @param fileName
* name of the file to be uploaded
* @param failureReason
* reason of failure
* @param selectedSw
* the selected softwareModule
*/
public UploadFileStatus(final String fileName, final String failureReason, final SoftwareModule selectedSw) {
this.failureReason = failureReason;
this.fileName = fileName;
this.softwareModule = selectedSw;
}
public String getFileName() {
return fileName;
}
public long getContentLength() {
return contentLength;
}
public long getBytesRead() {
return bytesRead;
}
public String getFailureReason() {
return failureReason;
}
public SoftwareModule getSoftwareModule() {
return softwareModule;
}
}

View File

@@ -1,55 +0,0 @@
/**
* 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.event;
/**
*
* Holds the upload file status.
*
*/
public class UploadStatusEvent {
/**
* TenantAwareEvent type definition of events during the artifact upload
* life-cycle from receiving the upload until the process end.
*/
public enum UploadStatusEventType {
RECEIVE_UPLOAD, UPLOAD_FAILED, UPLOAD_IN_PROGRESS, UPLOAD_STARTED, UPLOAD_FINISHED, UPLOAD_SUCCESSFUL, UPLOAD_STREAMING_FAILED, UPLOAD_STREAMING_FINISHED, ABORT_UPLOAD
}
private final UploadStatusEventType uploadProgressEventType;
private UploadFileStatus uploadStatus;
/**
* Constructor.
*
* @param eventType
* the type of the event
* @param uploadStatus
* the upload status of this event
*/
public UploadStatusEvent(final UploadStatusEventType eventType, final UploadFileStatus uploadStatus) {
this.uploadProgressEventType = eventType;
this.uploadStatus = uploadStatus;
}
public UploadFileStatus getUploadStatus() {
return uploadStatus;
}
public void setUploadStatus(final UploadFileStatus uploadStatus) {
this.uploadStatus = uploadStatus;
}
public UploadStatusEventType getUploadProgressEventType() {
return uploadProgressEventType;
}
}

View File

@@ -1,193 +0,0 @@
/**
* 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.footer;
import java.util.Set;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent;
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
import org.eclipse.hawkbit.ui.common.footer.AbstractDeleteActionsLayout;
import org.eclipse.hawkbit.ui.common.table.AbstractTable;
import org.eclipse.hawkbit.ui.dd.criteria.UploadViewClientCriterion;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.spring.events.EventBus.UIEventBus;
import org.vaadin.spring.events.EventScope;
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
import com.vaadin.ui.Component;
import com.vaadin.ui.Table;
import com.vaadin.ui.Table.TableTransferable;
import com.vaadin.ui.UI;
/**
* Upload view footer layout implementation.
*/
public class SMDeleteActionsLayout extends AbstractDeleteActionsLayout {
private static final long serialVersionUID = -3273982053389866299L;
private final ArtifactUploadState artifactUploadState;
private final UploadViewConfirmationWindowLayout uploadViewConfirmationWindowLayout;
private final UploadViewClientCriterion uploadViewClientCriterion;
public SMDeleteActionsLayout(final VaadinMessageSource i18n, final SpPermissionChecker permChecker,
final UIEventBus eventBus, final UINotification notification, final ArtifactUploadState artifactUploadState,
final SoftwareModuleManagement softwareModuleManagement,
final SoftwareModuleTypeManagement softwareModuleTypeManagement,
final UploadViewClientCriterion uploadViewClientCriterion) {
super(i18n, permChecker, eventBus, notification);
this.artifactUploadState = artifactUploadState;
this.uploadViewConfirmationWindowLayout = new UploadViewConfirmationWindowLayout(i18n, eventBus,
softwareModuleManagement, softwareModuleTypeManagement, artifactUploadState);
this.uploadViewClientCriterion = uploadViewClientCriterion;
init();
}
@EventBusListenerMethod(scope = EventScope.UI)
void onEvent(final UploadArtifactUIEvent event) {
if (isSoftwareEvent(event) || isSoftwareTypeEvent(event)) {
UI.getCurrent().access(() -> {
if (!hasUnsavedActions()) {
closeUnsavedActionsWindow();
final String message = uploadViewConfirmationWindowLayout.getConsolidatedMessage();
if (message != null && message.length() > 0) {
notification.displaySuccess(message);
}
}
updateSWActionCount();
});
}
}
private boolean isSoftwareEvent(final UploadArtifactUIEvent event) {
return event == UploadArtifactUIEvent.DISCARD_ALL_DELETE_SOFTWARE
|| event == UploadArtifactUIEvent.DELETED_ALL_SOFWARE
|| event == UploadArtifactUIEvent.DISCARD_DELETE_SOFTWARE;
}
private boolean isSoftwareTypeEvent(final UploadArtifactUIEvent event) {
return event == UploadArtifactUIEvent.DISCARD_ALL_DELETE_SOFTWARE_TYPE
|| event == UploadArtifactUIEvent.DELETED_ALL_SOFWARE_TYPE
|| event == UploadArtifactUIEvent.DISCARD_DELETE_SOFTWARE_TYPE;
}
@Override
protected boolean hasDeletePermission() {
return permChecker.hasDeleteRepositoryPermission();
}
@Override
protected boolean hasUpdatePermission() {
/**
* Footer layout should be displayed only when software modeule has
* delete permission.So update permission need not be checked in this
* case.
*/
return false;
}
@Override
protected String getDeleteAreaLabel() {
return i18n.getMessage("label.software.module.drop.area");
}
@Override
protected String getDeleteAreaId() {
return UIComponentIdProvider.DELETE_BUTTON_WRAPPER_ID;
}
@Override
protected AcceptCriterion getDeleteLayoutAcceptCriteria() {
return uploadViewClientCriterion;
}
@Override
protected void processDroppedComponent(final DragAndDropEvent event) {
final Component sourceComponent = event.getTransferable().getSourceComponent();
if (sourceComponent instanceof Table) {
final Table sourceTable = (Table) event.getTransferable().getSourceComponent();
addToDeleteList(sourceTable, (TableTransferable) event.getTransferable());
updateSWActionCount();
}
if (sourceComponent.getId().startsWith(UIComponentIdProvider.UPLOAD_TYPE_BUTTON_PREFIX)) {
final String swModuleTypeName = sourceComponent.getId()
.replace(UIComponentIdProvider.UPLOAD_TYPE_BUTTON_PREFIX, "");
if (artifactUploadState.getSoftwareModuleFilters().getSoftwareModuleType()
.map(type -> type.getName().equalsIgnoreCase(swModuleTypeName)).orElse(false)) {
notification.displayValidationError(
i18n.getMessage("message.swmodule.type.check.delete", new Object[] { swModuleTypeName }));
} else {
deleteSWModuleType(swModuleTypeName);
updateSWActionCount();
}
}
}
private void deleteSWModuleType(final String swModuleTypeName) {
artifactUploadState.getSelectedDeleteSWModuleTypes().add(swModuleTypeName);
}
private void addToDeleteList(final Table sourceTable, final TableTransferable transferable) {
final AbstractTable<?> swTable = (AbstractTable<?>) sourceTable;
final Set<Long> swModuleIdNameSet = swTable.getDeletedEntityByTransferable(transferable);
swModuleIdNameSet.forEach(id -> {
final String swModuleName = (String) sourceTable.getContainerDataSource().getItem(id)
.getItemProperty(SPUILabelDefinitions.NAME_VERSION).getValue();
artifactUploadState.getDeleteSofwareModules().put(id, swModuleName);
});
}
private void updateSWActionCount() {
final int count = artifactUploadState.getDeleteSofwareModules().size()
+ artifactUploadState.getSelectedDeleteSWModuleTypes().size();
updateActionsCount(count);
}
@Override
protected void restoreActionCount() {
updateSWActionCount();
}
@Override
protected void unsavedActionsWindowClosed() {
final String message = uploadViewConfirmationWindowLayout.getConsolidatedMessage();
if (message != null && message.length() > 0) {
notification.displaySuccess(message);
}
}
@Override
protected Component getUnsavedActionsWindowContent() {
uploadViewConfirmationWindowLayout.initialize();
return uploadViewConfirmationWindowLayout;
}
@Override
protected boolean hasUnsavedActions() {
return !artifactUploadState.getDeleteSofwareModules().isEmpty()
|| !artifactUploadState.getSelectedDeleteSWModuleTypes().isEmpty();
}
}

View File

@@ -1,270 +0,0 @@
/**
* 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.footer;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent;
import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent;
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
import org.eclipse.hawkbit.ui.artifacts.state.CustomFile;
import org.eclipse.hawkbit.ui.common.confirmwindow.layout.AbstractConfirmationWindowLayout;
import org.eclipse.hawkbit.ui.common.confirmwindow.layout.ConfirmationTab;
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.spring.events.EventBus.UIEventBus;
import com.google.common.collect.Maps;
import com.vaadin.data.Container;
import com.vaadin.data.Item;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.server.FontAwesome;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Table.Align;
/**
* Layout of confirm actions window on the Upload View.
*/
public class UploadViewConfirmationWindowLayout extends AbstractConfirmationWindowLayout {
private static final long serialVersionUID = 1L;
private static final String SW_MODULE_NAME_MSG = "SW MOdule Name";
private static final String SW_DISCARD_CHGS = "DiscardChanges";
private static final String SW_MODULE_TYPE_NAME = "SoftwareModuleTypeName";
private static final String DISCARD = "Discard";
private final transient SoftwareModuleTypeManagement softwareModuleTypeManagement;
private final transient SoftwareModuleManagement softwareModuleManagement;
private final ArtifactUploadState artifactUploadState;
UploadViewConfirmationWindowLayout(final VaadinMessageSource i18n, final UIEventBus eventBus,
final SoftwareModuleManagement softwareModuleManagement,
final SoftwareModuleTypeManagement softwareModuleTypeManagement,
final ArtifactUploadState artifactUploadState) {
super(i18n, eventBus);
this.softwareModuleTypeManagement = softwareModuleTypeManagement;
this.softwareModuleManagement = softwareModuleManagement;
this.artifactUploadState = artifactUploadState;
}
@Override
protected Map<String, ConfirmationTab> getConfirmationTabs() {
final Map<String, ConfirmationTab> tabs = Maps.newHashMapWithExpectedSize(2);
if (!artifactUploadState.getDeleteSofwareModules().isEmpty()) {
tabs.put(i18n.getMessage("caption.delete.swmodule.accordion.tab"), createSMDeleteConfirmationTab());
}
if (!artifactUploadState.getSelectedDeleteSWModuleTypes().isEmpty()) {
tabs.put(i18n.getMessage("caption.delete.sw.module.type.accordion.tab"),
createSMtypeDeleteConfirmationTab());
}
return tabs;
}
private ConfirmationTab createSMDeleteConfirmationTab() {
final ConfirmationTab tab = new ConfirmationTab();
tab.getConfirmAll().setId(UIComponentIdProvider.SW_DELETE_ALL);
tab.getConfirmAll().setIcon(FontAwesome.TRASH_O);
tab.getConfirmAll().setCaption(i18n.getMessage("button.delete.all"));
tab.getConfirmAll().addClickListener(event -> deleteSMAll(tab));
tab.getDiscardAll().setCaption(i18n.getMessage("button.discard.all"));
tab.getDiscardAll().addClickListener(event -> discardSMAll(tab));
// Add items container to the table.
tab.getTable().setContainerDataSource(getSWModuleTableContainer());
// Add the discard action column
tab.getTable().addGeneratedColumn(SW_DISCARD_CHGS, (source, itemId, columnId) -> {
final ClickListener clickListener = event -> discardSoftwareDelete(event, itemId, tab);
return createDiscardButton(itemId, clickListener);
});
tab.getTable().setVisibleColumns(SW_MODULE_NAME_MSG, SW_DISCARD_CHGS);
tab.getTable().setColumnHeaders(i18n.getMessage("upload.swModuleTable.header"),
i18n.getMessage("header.second.deletetarget.table"));
tab.getTable().setColumnExpandRatio(SW_MODULE_NAME_MSG, SPUIDefinitions.TARGET_DISTRIBUTION_COLUMN_WIDTH);
tab.getTable().setColumnExpandRatio(SW_DISCARD_CHGS, SPUIDefinitions.DISCARD_COLUMN_WIDTH);
tab.getTable().setColumnAlignment(SW_DISCARD_CHGS, Align.CENTER);
return tab;
}
/**
* Get SWModule table container.
*
* @return IndexedContainer
*/
@SuppressWarnings("unchecked")
private IndexedContainer getSWModuleTableContainer() {
final IndexedContainer swcontactContainer = new IndexedContainer();
swcontactContainer.addContainerProperty("SWModuleId", String.class, "");
swcontactContainer.addContainerProperty(SW_MODULE_NAME_MSG, String.class, "");
for (final Long swModuleID : artifactUploadState.getDeleteSofwareModules().keySet()) {
final Item item = swcontactContainer.addItem(swModuleID);
item.getItemProperty("SWModuleId").setValue(swModuleID.toString());
item.getItemProperty(SW_MODULE_NAME_MSG)
.setValue(artifactUploadState.getDeleteSofwareModules().get(swModuleID));
}
return swcontactContainer;
}
private void discardSoftwareDelete(final Button.ClickEvent event, final Object itemId, final ConfirmationTab tab) {
final Long swmoduleId = (Long) ((Button) event.getComponent()).getData();
if (null != artifactUploadState.getDeleteSofwareModules()
&& !artifactUploadState.getDeleteSofwareModules().isEmpty()
&& artifactUploadState.getDeleteSofwareModules().containsKey(swmoduleId)) {
artifactUploadState.getDeleteSofwareModules().remove(swmoduleId);
}
tab.getTable().getContainerDataSource().removeItem(itemId);
final int deleteCount = tab.getTable().size();
if (0 == deleteCount) {
removeCurrentTab(tab);
eventBus.publish(this, UploadArtifactUIEvent.DISCARD_ALL_DELETE_SOFTWARE);
} else {
eventBus.publish(this, UploadArtifactUIEvent.DISCARD_DELETE_SOFTWARE);
}
}
private void deleteSMAll(final ConfirmationTab tab) {
final Set<Long> swmoduleIds = artifactUploadState.getDeleteSofwareModules().keySet();
softwareModuleManagement.delete(swmoduleIds);
eventBus.publish(this, new SoftwareModuleEvent(BaseEntityEventType.REMOVE_ENTITY, swmoduleIds));
addToConsolitatedMsg(FontAwesome.TRASH_O.getHtml() + SPUILabelDefinitions.HTML_SPACE
+ i18n.getMessage("message.swModule.deleted", artifactUploadState.getDeleteSofwareModules().size()));
/*
* Check if any information / files pending to upload for the deleted
* software modules. If so, then delete the files from the upload list.
*/
final List<CustomFile> tobeRemoved = new ArrayList<>();
for (final Long id : swmoduleIds) {
final String deleteSoftwareNameVersion = artifactUploadState.getDeleteSofwareModules().get(id);
for (final CustomFile customFile : artifactUploadState.getFileSelected()) {
final String swNameVersion = HawkbitCommonUtil.getFormattedNameVersion(
customFile.getBaseSoftwareModuleName(), customFile.getBaseSoftwareModuleVersion());
if (deleteSoftwareNameVersion != null && deleteSoftwareNameVersion.equals(swNameVersion)) {
tobeRemoved.add(customFile);
}
}
}
if (!tobeRemoved.isEmpty()) {
artifactUploadState.getFileSelected().removeAll(tobeRemoved);
}
artifactUploadState.getDeleteSofwareModules().clear();
removeCurrentTab(tab);
setActionMessage(i18n.getMessage("message.software.delete.success"));
eventBus.publish(this, UploadArtifactUIEvent.DELETED_ALL_SOFWARE);
}
private void discardSMAll(final ConfirmationTab tab) {
removeCurrentTab(tab);
artifactUploadState.getDeleteSofwareModules().clear();
setActionMessage(i18n.getMessage("message.software.discard.success"));
eventBus.publish(this, UploadArtifactUIEvent.DISCARD_ALL_DELETE_SOFTWARE);
}
private ConfirmationTab createSMtypeDeleteConfirmationTab() {
final ConfirmationTab tab = new ConfirmationTab();
tab.getConfirmAll().setId(UIComponentIdProvider.SAVE_DELETE_SW_MODULE_TYPE);
tab.getConfirmAll().setIcon(FontAwesome.TRASH_O);
tab.getConfirmAll().setCaption(i18n.getMessage("button.delete.all"));
tab.getConfirmAll().addClickListener(event -> deleteSMtypeAll(tab));
tab.getDiscardAll().setCaption(i18n.getMessage("button.discard.all"));
tab.getDiscardAll().addClickListener(event -> discardSMtypeAll(tab));
// Add items container to the table.
tab.getTable().setContainerDataSource(getSWModuleTypeTableContainer());
// Add the discard action column
tab.getTable().addGeneratedColumn(DISCARD, (source, itemId, columnId) -> {
final ClickListener clickListener = event -> discardSoftwareTypeDelete(
(String) ((Button) event.getComponent()).getData(), itemId, tab);
return createDiscardButton(itemId, clickListener);
});
tab.getTable().setVisibleColumns(SW_MODULE_TYPE_NAME, DISCARD);
tab.getTable().setColumnHeaders(i18n.getMessage("header.first.delete.swmodule.type.table"),
i18n.getMessage("header.second.delete.swmodule.type.table"));
tab.getTable().setColumnExpandRatio(SW_MODULE_TYPE_NAME, 2);
tab.getTable().setColumnExpandRatio(SW_DISCARD_CHGS, SPUIDefinitions.DISCARD_COLUMN_WIDTH);
tab.getTable().setColumnAlignment(SW_DISCARD_CHGS, Align.CENTER);
return tab;
}
private Container getSWModuleTypeTableContainer() {
final IndexedContainer contactContainer = new IndexedContainer();
contactContainer.addContainerProperty(SW_MODULE_TYPE_NAME, String.class, "");
for (final String swModuleTypeName : artifactUploadState.getSelectedDeleteSWModuleTypes()) {
final Item saveTblitem = contactContainer.addItem(swModuleTypeName);
saveTblitem.getItemProperty(SW_MODULE_TYPE_NAME).setValue(swModuleTypeName);
}
return contactContainer;
}
private void discardSoftwareTypeDelete(final String discardSWModuleType, final Object itemId,
final ConfirmationTab tab) {
if (null != artifactUploadState.getSelectedDeleteSWModuleTypes()
&& !artifactUploadState.getSelectedDeleteSWModuleTypes().isEmpty()
&& artifactUploadState.getSelectedDeleteSWModuleTypes().contains(discardSWModuleType)) {
artifactUploadState.getSelectedDeleteSWModuleTypes().remove(discardSWModuleType);
}
tab.getTable().getContainerDataSource().removeItem(itemId);
final int deleteCount = tab.getTable().size();
if (0 == deleteCount) {
removeCurrentTab(tab);
eventBus.publish(this, UploadArtifactUIEvent.DISCARD_ALL_DELETE_SOFTWARE_TYPE);
} else {
eventBus.publish(this, UploadArtifactUIEvent.DISCARD_DELETE_SOFTWARE_TYPE);
}
}
private void deleteSMtypeAll(final ConfirmationTab tab) {
final int deleteSWModuleTypeCount = artifactUploadState.getSelectedDeleteSWModuleTypes().size();
for (final String swModuleTypeName : artifactUploadState.getSelectedDeleteSWModuleTypes()) {
softwareModuleTypeManagement.getByName(swModuleTypeName).map(SoftwareModuleType::getId)
.ifPresent(softwareModuleTypeManagement::delete);
}
addToConsolitatedMsg(FontAwesome.TASKS.getHtml() + SPUILabelDefinitions.HTML_SPACE
+ i18n.getMessage("message.sw.module.type.delete", new Object[] { deleteSWModuleTypeCount }));
artifactUploadState.getSelectedDeleteSWModuleTypes().clear();
removeCurrentTab(tab);
setActionMessage(i18n.getMessage("message.software.type.delete.success"));
eventBus.publish(this, UploadArtifactUIEvent.DELETED_ALL_SOFWARE_TYPE);
}
private void discardSMtypeAll(final ConfirmationTab tab) {
removeCurrentTab(tab);
artifactUploadState.getSelectedDeleteSWModuleTypes().clear();
setActionMessage(i18n.getMessage("message.software.type.discard.success"));
eventBus.publish(this, UploadArtifactUIEvent.DISCARD_ALL_DELETE_SOFTWARE_TYPE);
}
}

View File

@@ -21,6 +21,7 @@ import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow.SaveDialogCloseListener;
import org.eclipse.hawkbit.ui.common.SoftwareModuleTypeBeanQuery;
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
import org.eclipse.hawkbit.ui.common.builder.TextAreaBuilder;
import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder;
import org.eclipse.hawkbit.ui.common.builder.WindowBuilder;
@@ -83,6 +84,8 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent {
private final AbstractTable<SoftwareModule> softwareModuleTable;
private Label softwareModuleType;
/**
* Constructor for SoftwareModuleAddUpdateWindow
*
@@ -248,7 +251,9 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent {
nameTextField.clear();
versionTextField.clear();
descTextArea.clear();
typeComboBox.clear();
if (!editSwModule) {
typeComboBox.clear();
}
editSwModule = Boolean.FALSE;
}
@@ -261,7 +266,13 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent {
formLayout = new FormLayout();
formLayout.setCaption(null);
formLayout.addComponent(typeComboBox);
if (editSwModule) {
formLayout.addComponent(softwareModuleType);
} else {
formLayout.addComponent(typeComboBox);
typeComboBox.focus();
}
formLayout.addComponent(nameTextField);
formLayout.addComponent(versionTextField);
formLayout.addComponent(vendorTextField);
@@ -270,12 +281,11 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent {
setCompositionRoot(formLayout);
final CommonDialogWindow window = new WindowBuilder(SPUIDefinitions.CREATE_UPDATE_WINDOW)
.caption(i18n.getMessage("upload.caption.add.new.swmodule")).content(this).layout(formLayout).i18n(i18n)
.saveDialogCloseListener(new SaveOnDialogCloseListener()).buildCommonDialogWindow();
.caption(i18n.getMessage("caption.create.new", i18n.getMessage("caption.software.module"))).id(UIComponentIdProvider.SW_MODULE_CREATE_DIALOG)
.content(this).layout(formLayout).i18n(i18n).saveDialogCloseListener(new SaveOnDialogCloseListener())
.buildCommonDialogWindow();
nameTextField.setEnabled(!editSwModule);
versionTextField.setEnabled(!editSwModule);
typeComboBox.setEnabled(!editSwModule);
typeComboBox.focus();
return window;
}
@@ -293,11 +303,7 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent {
versionTextField.setValue(swModule.getVersion());
vendorTextField.setValue(swModule.getVendor());
descTextArea.setValue(swModule.getDescription());
if (swModule.getType().isDeleted()) {
typeComboBox.addItem(swModule.getType().getName());
}
typeComboBox.setValue(swModule.getType().getName());
softwareModuleType = new LabelBuilder().name(swModule.getType().getName()).caption("Type").buildLabel();
});
}

View File

@@ -12,24 +12,22 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.artifacts.event.RefreshSoftwareModuleByFilterEvent;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent;
import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent;
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
import org.eclipse.hawkbit.ui.common.table.AbstractNamedVersionTable;
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.dd.criteria.UploadViewClientCriterion;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.distributions.smtable.SwMetadataPopupLayout;
import org.eclipse.hawkbit.ui.push.SoftwareModuleUpdatedEventContainer;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
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.TableColumn;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.UINotification;
@@ -47,9 +45,6 @@ import com.vaadin.data.Container;
import com.vaadin.data.Item;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
import com.vaadin.server.FontAwesome;
import com.vaadin.ui.Button;
import com.vaadin.ui.Table;
import com.vaadin.ui.UI;
/**
@@ -65,17 +60,13 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable<SoftwareModul
private final UploadViewClientCriterion uploadViewClientCriterion;
private final SwMetadataPopupLayout swMetadataPopupLayout;
SoftwareModuleTable(final UIEventBus eventBus, final VaadinMessageSource i18n, final UINotification uiNotification,
final ArtifactUploadState artifactUploadState, final SoftwareModuleManagement softwareManagement,
final UploadViewClientCriterion uploadViewClientCriterion,
final SwMetadataPopupLayout swMetadataPopupLayout) {
super(eventBus, i18n, uiNotification);
final UploadViewClientCriterion uploadViewClientCriterion, final SpPermissionChecker permChecker) {
super(eventBus, i18n, uiNotification, permChecker);
this.artifactUploadState = artifactUploadState;
this.softwareModuleManagement = softwareManagement;
this.uploadViewClientCriterion = uploadViewClientCriterion;
this.swMetadataPopupLayout = swMetadataPopupLayout;
addNewContainerDS();
setColumnProperties();
@@ -99,17 +90,16 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable<SoftwareModul
final BeanQueryFactory<BaseSwModuleBeanQuery> swQF = new BeanQueryFactory<>(BaseSwModuleBeanQuery.class);
swQF.setQueryConfiguration(queryConfiguration);
return new LazyQueryContainer(new LazyQueryDefinition(true, SPUIDefinitions.PAGE_SIZE, "swId"), swQF);
return new LazyQueryContainer(
new LazyQueryDefinition(true, SPUIDefinitions.PAGE_SIZE, SPUILabelDefinitions.VAR_SWM_ID), swQF);
}
private Map<String, Object> prepareQueryConfigFilters() {
final Map<String, Object> queryConfig = Maps.newHashMapWithExpectedSize(2);
artifactUploadState.getSoftwareModuleFilters().getSearchText()
.ifPresent(value -> queryConfig.put(SPUIDefinitions.FILTER_BY_TEXT, value));
artifactUploadState.getSoftwareModuleFilters().getSoftwareModuleType()
.ifPresent(type -> queryConfig.put(SPUIDefinitions.BY_SOFTWARE_MODULE_TYPE, type));
return queryConfig;
}
@@ -128,11 +118,6 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable<SoftwareModul
lqc.addContainerProperty(SPUILabelDefinitions.VAR_LAST_MODIFIED_DATE, String.class, null, false, true);
}
@Override
protected boolean isFirstRowSelectedOnLoad() {
return artifactUploadState.getSelectedSoftwareModules().isEmpty();
}
@Override
protected Object getItemIdToSelect() {
return artifactUploadState.getSelectedSoftwareModules().isEmpty() ? null
@@ -156,7 +141,7 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable<SoftwareModul
@Override
protected void publishSelectedEntityEvent(final SoftwareModule lastSoftwareModule) {
eventBus.publish(this, new SoftwareModuleEvent(BaseEntityEventType.SELECTED_ENTITY, lastSoftwareModule));
getEventBus().publish(this, new SoftwareModuleEvent(BaseEntityEventType.SELECTED_ENTITY, lastSoftwareModule));
}
@EventBusListenerMethod(scope = EventScope.UI)
@@ -166,7 +151,7 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable<SoftwareModul
@EventBusListenerMethod(scope = EventScope.UI)
void onEvent(final UploadArtifactUIEvent event) {
if (event == UploadArtifactUIEvent.DELETED_ALL_SOFWARE) {
if (event == UploadArtifactUIEvent.DELETED_ALL_SOFTWARE) {
UI.getCurrent().access(this::refreshFilter);
}
}
@@ -176,8 +161,7 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable<SoftwareModul
@SuppressWarnings("unchecked")
final List<Long> visibleItemIds = (List<Long>) getVisibleItemIds();
eventContainer.getEvents().stream().filter(event -> visibleItemIds.contains(event.getEntityId()))
.filter(Objects::nonNull)
.forEach(event -> updateSoftwareModuleInTable(event.getEntity()));
.filter(Objects::nonNull).forEach(event -> updateSoftwareModuleInTable(event.getEntity()));
}
private void updateSoftwareModuleInTable(final SoftwareModule editedSm) {
@@ -196,30 +180,13 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable<SoftwareModul
super.updateEntity(baseEntity, item);
}
@Override
protected void addCustomGeneratedColumns() {
addGeneratedColumn(SPUILabelDefinitions.METADATA_ICON, new ColumnGenerator() {
private static final long serialVersionUID = 1L;
@Override
public Object generateCell(final Table source, final Object itemId, final Object columnId) {
final String nameVersionStr = getNameAndVerion(itemId);
final Button manageMetaDataBtn = createManageMetadataButton(nameVersionStr);
manageMetaDataBtn.addClickListener(event -> showMetadataDetails((Long) itemId));
return manageMetaDataBtn;
}
});
}
@Override
protected List<TableColumn> getTableVisibleColumns() {
final List<TableColumn> columnList = super.getTableVisibleColumns();
if (!isMaximized()) {
columnList.add(new TableColumn(SPUILabelDefinitions.METADATA_ICON, "", 0.1F));
return columnList;
if (isMaximized()) {
columnList
.add(new TableColumn(SPUILabelDefinitions.VAR_VENDOR, getI18n().getMessage("header.vendor"), 0.1F));
}
columnList.add(new TableColumn(SPUILabelDefinitions.VAR_VENDOR, i18n.getMessage("header.vendor"), 0.1F));
return columnList;
}
@@ -238,25 +205,54 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable<SoftwareModul
artifactUploadState.setNoDataAvilableSoftwareModule(!available);
}
private Button createManageMetadataButton(final String nameVersionStr) {
final Button manageMetadataBtn = SPUIComponentProvider.getButton(
UIComponentIdProvider.SW_TABLE_MANAGE_METADATA_ID + "." + nameVersionStr, "", "", null, false,
FontAwesome.LIST_ALT, SPUIButtonStyleSmallNoBorder.class);
manageMetadataBtn.addStyleName(SPUIStyleDefinitions.ARTIFACT_DTLS_ICON);
manageMetadataBtn.setDescription(i18n.getMessage("tooltip.metadata.icon"));
return manageMetadataBtn;
@Override
protected void handleOkDelete(final List<Long> entitiesToDelete) {
if (isUploadInProgressForSoftwareModule(entitiesToDelete)) {
getNotification().displayValidationError(getI18n().getMessage("message.error.swModule.notDeleted"));
return;
}
softwareModuleManagement.delete(entitiesToDelete);
getEventBus().publish(this, new SoftwareModuleEvent(BaseEntityEventType.REMOVE_ENTITY, entitiesToDelete));
getNotification().displaySuccess(getI18n().getMessage("message.delete.success",
entitiesToDelete.size() + " " + getI18n().getMessage("caption.software.module") + "(s)"));
artifactUploadState.getSelectedSoftwareModules().clear();
getEventBus().publish(this, UploadArtifactUIEvent.DELETED_ALL_SOFTWARE);
}
private String getNameAndVerion(final Object itemId) {
final Item item = getItem(itemId);
final String name = (String) item.getItemProperty(SPUILabelDefinitions.VAR_NAME).getValue();
final String version = (String) item.getItemProperty(SPUILabelDefinitions.VAR_VERSION).getValue();
return name + "." + version;
private boolean isUploadInProgressForSoftwareModule(final List<Long> entitiesToDelete) {
for (final Long id : entitiesToDelete) {
if (artifactUploadState.isUploadInProgressForSelectedSoftwareModule(id)) {
return true;
}
}
return false;
}
private void showMetadataDetails(final Long itemId) {
softwareModuleManagement.get(itemId)
.ifPresent(swmodule -> UI.getCurrent().addWindow(swMetadataPopupLayout.getWindow(swmodule, null)));
@Override
protected String getEntityType() {
return getI18n().getMessage("upload.swModuleTable.header");
}
@Override
protected Set<Long> getSelectedEntities() {
return artifactUploadState.getSelectedSoftwareModules();
}
@Override
protected String getEntityId(final Object itemId) {
final String entityId = String.valueOf(
getContainerDataSource().getItem(itemId).getItemProperty(SPUILabelDefinitions.VAR_SWM_ID).getValue());
return "softwareModule." + entityId;
}
@Override
protected String getDeletedEntityName(final Long entityId) {
final Optional<SoftwareModule> softwareModule = softwareModuleManagement.get(entityId);
if (softwareModule.isPresent()) {
return softwareModule.get().getName() + ":" + softwareModule.get().getVersion();
}
return "";
}
}

View File

@@ -38,7 +38,7 @@ public class SoftwareModuleTableLayout extends AbstractTableLayout<SoftwareModul
final SwMetadataPopupLayout swMetadataPopupLayout = new SwMetadataPopupLayout(i18n, uiNotification, eventBus,
softwareModuleManagement, entityFactory, permChecker);
this.softwareModuleTable = new SoftwareModuleTable(eventBus, i18n, uiNotification, artifactUploadState,
softwareModuleManagement, uploadViewClientCriterion, swMetadataPopupLayout);
softwareModuleManagement, uploadViewClientCriterion, permChecker);
final SoftwareModuleAddUpdateWindow softwareModuleAddUpdateWindow = new SoftwareModuleAddUpdateWindow(i18n,
uiNotification, eventBus, softwareModuleManagement, softwareModuleTypeManagement, entityFactory,

View File

@@ -0,0 +1,196 @@
/**
* 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.smtype;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
import org.eclipse.hawkbit.ui.layouts.AbstractTypeLayout;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.spring.events.EventBus.UIEventBus;
import com.vaadin.ui.Label;
import com.vaadin.ui.OptionGroup;
import com.vaadin.ui.themes.ValoTheme;
/**
* General Layout for the software module types pop-up window which is provided
* on the Distribution and Upload view when creating, updating or deleting a
* software module type
*
*/
public abstract class AbstractSoftwareModuleTypeLayout extends AbstractTypeLayout<SoftwareModuleType> {
private static final long serialVersionUID = 1L;
private final transient SoftwareModuleTypeManagement softwareModuleTypeManagement;
private String singleAssignStr;
private String multiAssignStr;
private Label singleAssign;
private Label multiAssign;
private OptionGroup assignOptiongroup;
/**
* Constructor
*
* @param i18n
* VaadinMessageSource
* @param entityFactory
* EntityFactory
* @param eventBus
* UIEventBus
* @param permChecker
* SpPermissionChecker
* @param uiNotification
* UINotification
* @param softwareModuleTypeManagement
* SoftwareModuleTypeManagement
*/
public AbstractSoftwareModuleTypeLayout(final VaadinMessageSource i18n, final EntityFactory entityFactory,
final UIEventBus eventBus, final SpPermissionChecker permChecker, final UINotification uiNotification,
final SoftwareModuleTypeManagement softwareModuleTypeManagement) {
super(i18n, entityFactory, eventBus, permChecker, uiNotification);
this.softwareModuleTypeManagement = softwareModuleTypeManagement;
}
@Override
protected int getTagNameSize() {
return SoftwareModuleType.NAME_MAX_SIZE;
}
@Override
protected int getTagDescSize() {
return SoftwareModuleType.DESCRIPTION_MAX_SIZE;
}
@Override
protected int getTypeKeySize() {
return SoftwareModuleType.KEY_MAX_SIZE;
}
@Override
protected String getTagNameId() {
return UIComponentIdProvider.NEW_SOFTWARE_TYPE_NAME;
}
@Override
protected String getTagDescId() {
return UIComponentIdProvider.NEW_SOFTWARE_TYPE_DESC;
}
@Override
protected String getTypeKeyId() {
return UIComponentIdProvider.NEW_SOFTWARE_TYPE_KEY;
}
@Override
protected void createRequiredComponents() {
super.createRequiredComponents();
singleAssignStr = getI18n().getMessage("label.singleAssign.type");
multiAssignStr = getI18n().getMessage("label.multiAssign.type");
singleAssign = new LabelBuilder().name(singleAssignStr).buildLabel();
multiAssign = new LabelBuilder().name(multiAssignStr).buildLabel();
singleMultiOptionGroup();
}
@Override
protected void buildLayout() {
super.buildLayout();
getFormLayout().addComponent(assignOptiongroup);
}
@Override
protected Optional<SoftwareModuleType> findEntityByKey() {
return softwareModuleTypeManagement.getByKey(getTypeKey().getValue());
}
@Override
protected Optional<SoftwareModuleType> findEntityByName() {
return softwareModuleTypeManagement.getByName(getTagName().getValue());
}
@Override
protected String getDuplicateKeyErrorMessage(final SoftwareModuleType existingType) {
return getI18n().getMessage("message.type.key.swmodule.duplicate.check", existingType.getKey());
}
public SoftwareModuleTypeManagement getSoftwareModuleTypeManagement() {
return softwareModuleTypeManagement;
}
public String getSingleAssignStr() {
return singleAssignStr;
}
public void setSingleAssignStr(final String singleAssignStr) {
this.singleAssignStr = singleAssignStr;
}
public String getMultiAssignStr() {
return multiAssignStr;
}
public void setMultiAssignStr(final String multiAssignStr) {
this.multiAssignStr = multiAssignStr;
}
public Label getSingleAssign() {
return singleAssign;
}
public void setSingleAssign(final Label singleAssign) {
this.singleAssign = singleAssign;
}
public Label getMultiAssign() {
return multiAssign;
}
public void setMultiAssign(final Label multiAssign) {
this.multiAssign = multiAssign;
}
public OptionGroup getAssignOptiongroup() {
return assignOptiongroup;
}
public void setAssignOptiongroup(final OptionGroup assignOptiongroup) {
this.assignOptiongroup = assignOptiongroup;
}
private void singleMultiOptionGroup() {
final List<String> optionValues = new ArrayList<>();
optionValues.add(singleAssign.getValue());
optionValues.add(multiAssign.getValue());
assignOptionGroupByValues(optionValues);
}
private void assignOptionGroupByValues(final List<String> tagOptions) {
assignOptiongroup = new OptionGroup("", tagOptions);
assignOptiongroup.setStyleName(ValoTheme.OPTIONGROUP_SMALL);
assignOptiongroup.addStyleName("custom-option-group");
assignOptiongroup.setNullSelectionAllowed(false);
assignOptiongroup.setId(UIComponentIdProvider.ASSIGN_OPTION_GROUP_SOFTWARE_MODULE_TYPE_ID);
assignOptiongroup.select(tagOptions.get(0));
}
}

View File

@@ -0,0 +1,92 @@
/**
* 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.smtype;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent.SoftwareModuleTypeEnum;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.spring.events.EventBus.UIEventBus;
/**
* Layout for the pop-up window which is created when creating a software module
* type on the Upload or Distribution View.
*/
public class CreateSoftwareModuleTypeLayout extends AbstractSoftwareModuleTypeLayout {
private static final long serialVersionUID = 1L;
/**
* Constructor for CreateUpdateSoftwareTypeLayout
*
* @param i18n
* I18N
* @param entityFactory
* EntityFactory
* @param eventBus
* UIEventBus
* @param permChecker
* SpPermissionChecker
* @param uiNotification
* UINotification
* @param softwareModuleTypeManagement
* management for {@link SoftwareModuleType}s
*/
public CreateSoftwareModuleTypeLayout(final VaadinMessageSource i18n, final EntityFactory entityFactory,
final UIEventBus eventBus, final SpPermissionChecker permChecker, final UINotification uiNotification,
final SoftwareModuleTypeManagement softwareModuleTypeManagement) {
super(i18n, entityFactory, eventBus, permChecker, uiNotification, softwareModuleTypeManagement);
}
@Override
protected String getWindowCaption() {
return getI18n().getMessage("caption.create.new", getI18n().getMessage("caption.type"));
}
@Override
protected void saveEntity() {
createNewSWModuleType();
}
private void createNewSWModuleType() {
int assignNumber = 0;
final String colorPicked = ColorPickerHelper.getColorPickedString(getColorPickerLayout().getSelPreview());
final String typeNameValue = getTagName().getValue();
final String typeKeyValue = getTypeKey().getValue();
final String typeDescValue = getTagDesc().getValue();
final String assignValue = (String) getAssignOptiongroup().getValue();
if (assignValue != null && assignValue.equalsIgnoreCase(getSingleAssignStr())) {
assignNumber = 1;
} else if (assignValue != null && assignValue.equalsIgnoreCase(getMultiAssignStr())) {
assignNumber = Integer.MAX_VALUE;
}
if (typeNameValue != null && typeKeyValue != null) {
final SoftwareModuleType newSWType = getSoftwareModuleTypeManagement()
.create(getEntityFactory().softwareModuleType().create().key(typeKeyValue).name(typeNameValue)
.description(typeDescValue).colour(colorPicked).maxAssignments(assignNumber));
getUiNotification().displaySuccess(getI18n().getMessage("message.save.success", newSWType.getName()));
getEventBus().publish(this,
new SoftwareModuleTypeEvent(SoftwareModuleTypeEnum.ADD_SOFTWARE_MODULE_TYPE, newSWType));
} else {
getUiNotification().displayValidationError(getI18n().getMessage("message.error.missing.typenameorkey"));
}
}
@Override
protected boolean isUpdateAction() {
return false;
}
}

View File

@@ -1,310 +0,0 @@
/**
* 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.smtype;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent.SoftwareModuleTypeEnum;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerConstants;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper;
import org.eclipse.hawkbit.ui.common.SoftwareModuleTypeBeanQuery;
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
import org.eclipse.hawkbit.ui.common.builder.TextAreaBuilder;
import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder;
import org.eclipse.hawkbit.ui.layouts.CreateUpdateTypeLayout;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory;
import org.vaadin.spring.events.EventBus.UIEventBus;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.shared.ui.colorpicker.Color;
import com.vaadin.ui.Label;
import com.vaadin.ui.OptionGroup;
import com.vaadin.ui.TextField;
import com.vaadin.ui.components.colorpicker.ColorChangeListener;
import com.vaadin.ui.themes.ValoTheme;
/**
* Layout for the create or update software module type.
*
*/
public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout<SoftwareModuleType> {
private static final long serialVersionUID = 1L;
private static final Logger LOG = LoggerFactory.getLogger(CreateUpdateSoftwareTypeLayout.class);
private final transient SoftwareModuleTypeManagement softwareModuleTypeManagement;
private String singleAssignStr;
private String multiAssignStr;
private Label singleAssign;
private Label multiAssign;
private OptionGroup assignOptiongroup;
/**
* Constructor for CreateUpdateSoftwareTypeLayout
*
* @param i18n
* I18N
* @param entityFactory
* EntityFactory
* @param eventBus
* UIEventBus
* @param permChecker
* SpPermissionChecker
* @param uiNotification
* UINotification
* @param softwareModuleTypeManagement
* management for {@link SoftwareModuleType}s
*/
public CreateUpdateSoftwareTypeLayout(final VaadinMessageSource i18n, final EntityFactory entityFactory,
final UIEventBus eventBus, final SpPermissionChecker permChecker, final UINotification uiNotification,
final SoftwareModuleTypeManagement softwareModuleTypeManagement) {
super(i18n, entityFactory, eventBus, permChecker, uiNotification);
this.softwareModuleTypeManagement = softwareModuleTypeManagement;
}
@Override
protected void addListeners() {
super.addListeners();
optiongroup.addValueChangeListener(this::optionValueChanged);
}
@Override
protected void createRequiredComponents() {
super.createRequiredComponents();
singleAssignStr = i18n.getMessage("label.singleAssign.type");
multiAssignStr = i18n.getMessage("label.multiAssign.type");
singleAssign = new LabelBuilder().name(singleAssignStr).buildLabel();
multiAssign = new LabelBuilder().name(multiAssignStr).buildLabel();
tagName = createTextField("textfield.name", SPUIDefinitions.TYPE_NAME, SPUIDefinitions.NEW_SOFTWARE_TYPE_NAME,
SoftwareModuleType.NAME_MAX_SIZE);
typeKey = createTextField("textfield.key", SPUIDefinitions.TYPE_KEY, SPUIDefinitions.NEW_SOFTWARE_TYPE_KEY,
SoftwareModuleType.KEY_MAX_SIZE);
tagDesc = new TextAreaBuilder(SoftwareModuleType.DESCRIPTION_MAX_SIZE)
.caption(i18n.getMessage("textfield.description"))
.styleName(ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TYPE_DESC)
.id(SPUIDefinitions.NEW_SOFTWARE_TYPE_DESC).buildTextComponent();
singleMultiOptionGroup();
}
@Override
protected Color getColorForColorPicker() {
final Optional<SoftwareModuleType> typeSelected = softwareModuleTypeManagement
.getByName(tagNameComboBox.getValue().toString());
if (typeSelected.isPresent()) {
return typeSelected.get().getColour() != null
? ColorPickerHelper.rgbToColorConverter(typeSelected.get().getColour())
: ColorPickerHelper.rgbToColorConverter(ColorPickerConstants.DEFAULT_COLOR);
}
return ColorPickerHelper.rgbToColorConverter(ColorPickerConstants.DEFAULT_COLOR);
}
private TextField createTextField(final String in18Key, final String styleName, final String id,
final int maxLength) {
return new TextFieldBuilder(maxLength).caption(i18n.getMessage(in18Key))
.styleName(ValoTheme.TEXTFIELD_TINY + " " + styleName).required(true, i18n).id(id).buildTextComponent();
}
@Override
protected void buildLayout() {
super.buildLayout();
ColorPickerHelper.setRgbSliderValues(colorPickerLayout);
getFormLayout().addComponent(typeKey, 4);
getFormLayout().addComponent(assignOptiongroup);
}
@Override
protected String getWindowCaption() {
return i18n.getMessage("caption.add.type");
}
/**
* Listener for option group - Create tag/Update.
*
* @param event
* ValueChangeEvent
*/
@Override
protected void optionValueChanged(final ValueChangeEvent event) {
super.optionValueChanged(event);
if (updateTagStr.equals(event.getProperty().getValue())) {
assignOptiongroup.setEnabled(false);
} else {
assignOptiongroup.setEnabled(true);
}
assignOptiongroup.select(singleAssignStr);
}
/**
* reset the components.
*/
@Override
protected void reset() {
super.reset();
assignOptiongroup.select(singleAssignStr);
}
@Override
protected void resetTagNameField() {
super.resetTagNameField();
typeKey.clear();
tagDesc.clear();
assignOptiongroup.select(singleAssignStr);
}
/**
* Select tag & set tag name & tag desc values corresponding to selected
* tag.
*
* @param targetTagSelected
* as the selected tag from combo
*/
@Override
protected void setTagDetails(final String targetTagSelected) {
tagName.setValue(targetTagSelected);
softwareModuleTypeManagement.getByName(targetTagSelected).ifPresent(selectedTypeTag -> {
tagDesc.setValue(selectedTypeTag.getDescription());
typeKey.setValue(selectedTypeTag.getKey());
if (selectedTypeTag.getMaxAssignments() == 1) {
assignOptiongroup.setValue(singleAssignStr);
} else {
assignOptiongroup.setValue(multiAssignStr);
}
setColorPickerComponentsColor(selectedTypeTag.getColour());
});
}
private void singleMultiOptionGroup() {
final List<String> optionValues = new ArrayList<>();
optionValues.add(singleAssign.getValue());
optionValues.add(multiAssign.getValue());
assignOptionGroupByValues(optionValues);
}
private void assignOptionGroupByValues(final List<String> tagOptions) {
assignOptiongroup = new OptionGroup("", tagOptions);
assignOptiongroup.setStyleName(ValoTheme.OPTIONGROUP_SMALL);
assignOptiongroup.addStyleName("custom-option-group");
assignOptiongroup.setNullSelectionAllowed(false);
assignOptiongroup.setId(SPUIDefinitions.ASSIGN_OPTION_GROUP_SOFTWARE_MODULE_TYPE_ID);
assignOptiongroup.select(tagOptions.get(0));
}
@Override
protected void createEntity() {
createNewSWModuleType();
}
@Override
protected void updateEntity(final SoftwareModuleType entity) {
updateSWModuleType(entity);
}
@Override
protected Optional<SoftwareModuleType> findEntityByKey() {
return softwareModuleTypeManagement.getByKey(typeKey.getValue());
}
@Override
protected Optional<SoftwareModuleType> findEntityByName() {
return softwareModuleTypeManagement.getByName(tagName.getValue());
}
@Override
protected String getDuplicateKeyErrorMessage(final SoftwareModuleType existingType) {
return i18n.getMessage("message.type.key.swmodule.duplicate.check", new Object[] { existingType.getKey() });
}
private void createNewSWModuleType() {
int assignNumber = 0;
final String colorPicked = ColorPickerHelper.getColorPickedString(getColorPickerLayout().getSelPreview());
final String typeNameValue = tagName.getValue();
final String typeKeyValue = typeKey.getValue();
final String typeDescValue = tagDesc.getValue();
final String assignValue = (String) assignOptiongroup.getValue();
if (assignValue != null && assignValue.equalsIgnoreCase(singleAssignStr)) {
assignNumber = 1;
} else if (assignValue != null && assignValue.equalsIgnoreCase(multiAssignStr)) {
assignNumber = Integer.MAX_VALUE;
}
if (typeNameValue != null && typeKeyValue != null) {
final SoftwareModuleType newSWType = softwareModuleTypeManagement
.create(entityFactory.softwareModuleType().create().key(typeKeyValue).name(typeNameValue)
.description(typeDescValue).colour(colorPicked).maxAssignments(assignNumber));
uiNotification
.displaySuccess(i18n.getMessage("message.save.success", new Object[] { newSWType.getName() }));
eventBus.publish(this,
new SoftwareModuleTypeEvent(SoftwareModuleTypeEnum.ADD_SOFTWARE_MODULE_TYPE, newSWType));
} else {
uiNotification.displayValidationError(i18n.getMessage("message.error.missing.typenameorkey"));
}
}
private void updateSWModuleType(final SoftwareModuleType existingType) {
softwareModuleTypeManagement
.update(entityFactory.softwareModuleType().update(existingType.getId()).description(tagDesc.getValue())
.colour(ColorPickerHelper.getColorPickedString(getColorPickerLayout().getSelPreview())));
uiNotification
.displaySuccess(i18n.getMessage("message.update.success", new Object[] { existingType.getName() }));
eventBus.publish(this,
new SoftwareModuleTypeEvent(SoftwareModuleTypeEnum.UPDATE_SOFTWARE_MODULE_TYPE, existingType));
}
@Override
public void addColorChangeListener(final ColorChangeListener listener) {
LOG.debug("inside addColorChangeListener");
}
@Override
public void removeColorChangeListener(final ColorChangeListener listener) {
LOG.debug("inside removeColorChangeListener");
}
@Override
public Color getColor() {
return null;
}
@Override
protected void populateTagNameCombo() {
tagNameComboBox.setContainerDataSource(
HawkbitCommonUtil.createLazyQueryContainer(new BeanQueryFactory<>(SoftwareModuleTypeBeanQuery.class)));
tagNameComboBox.setItemCaptionPropertyId(SPUILabelDefinitions.VAR_NAME);
}
}

View File

@@ -1,117 +0,0 @@
/**
* 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.smtype;
import java.util.EnumSet;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent.SoftwareModuleTypeEnum;
import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent;
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
import org.eclipse.hawkbit.ui.common.SoftwareModuleTypeBeanQuery;
import org.eclipse.hawkbit.ui.common.filterlayout.AbstractFilterButtons;
import org.eclipse.hawkbit.ui.dd.criteria.UploadViewClientCriterion;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory;
import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer;
import org.vaadin.spring.events.EventBus.UIEventBus;
import org.vaadin.spring.events.EventScope;
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
/**
* Software module type filter buttons.
*
*/
public class SMTypeFilterButtons extends AbstractFilterButtons {
private static final long serialVersionUID = 169198312654380358L;
private final ArtifactUploadState artifactUploadState;
private final UploadViewClientCriterion uploadViewClientCriterion;
SMTypeFilterButtons(final UIEventBus eventBus, final ArtifactUploadState artifactUploadState,
final UploadViewClientCriterion uploadViewClientCriterion,
final SoftwareModuleTypeManagement softwareModuleTypeManagement) {
super(eventBus, new SMTypeFilterButtonClick(eventBus, artifactUploadState, softwareModuleTypeManagement));
this.artifactUploadState = artifactUploadState;
this.uploadViewClientCriterion = uploadViewClientCriterion;
}
@EventBusListenerMethod(scope = EventScope.UI)
void onEvent(final SoftwareModuleTypeEvent event) {
if (event.getSoftwareModuleType() != null
&& EnumSet.allOf(SoftwareModuleTypeEnum.class).contains(event.getSoftwareModuleTypeEnum())) {
refreshTable();
}
}
@EventBusListenerMethod(scope = EventScope.UI)
void onEvent(final UploadArtifactUIEvent event) {
if (event == UploadArtifactUIEvent.DELETED_ALL_SOFWARE_TYPE) {
refreshTable();
}
}
@Override
protected String getButtonsTableId() {
return UIComponentIdProvider.SW_MODULE_TYPE_TABLE_ID;
}
@Override
protected LazyQueryContainer createButtonsLazyQueryContainer() {
return HawkbitCommonUtil.createLazyQueryContainer(new BeanQueryFactory<>(SoftwareModuleTypeBeanQuery.class));
}
@Override
protected boolean isClickedByDefault(final String typeName) {
return artifactUploadState.getSoftwareModuleFilters().getSoftwareModuleType()
.map(type -> type.getName().equals(typeName)).orElse(false);
}
@Override
protected String createButtonId(final String name) {
return UIComponentIdProvider.SM_TYPE_FILTER_BTN_ID + name;
}
@Override
protected DropHandler getFilterButtonDropHandler() {
return new DropHandler() {
private static final long serialVersionUID = 1L;
@Override
public AcceptCriterion getAcceptCriterion() {
return uploadViewClientCriterion;
}
@Override
public void drop(final DragAndDropEvent event) {
/* Not required */
}
};
}
@Override
protected String getButttonWrapperIdPrefix() {
return UIComponentIdProvider.UPLOAD_TYPE_BUTTON_PREFIX;
}
@Override
protected String getButtonWrapperData() {
return null;
}
}

View File

@@ -1,93 +0,0 @@
/**
* 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.smtype;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent;
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
import org.eclipse.hawkbit.ui.common.filterlayout.AbstractFilterHeader;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.spring.events.EventBus.UIEventBus;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.UI;
import com.vaadin.ui.Window;
/**
* Software module type filter buttons header.
*/
public class SMTypeFilterHeader extends AbstractFilterHeader {
private static final long serialVersionUID = -4855810338059032342L;
private final ArtifactUploadState artifactUploadState;
private final CreateUpdateSoftwareTypeLayout createUpdateSWTypeLayout;
SMTypeFilterHeader(final VaadinMessageSource i18n, final SpPermissionChecker permChecker, final UIEventBus eventBus,
final ArtifactUploadState artifactUploadState, final EntityFactory entityFactory,
final UINotification uiNotification, final SoftwareModuleTypeManagement softwareModuletypeManagement) {
super(permChecker, eventBus, i18n);
this.artifactUploadState = artifactUploadState;
this.createUpdateSWTypeLayout = new CreateUpdateSoftwareTypeLayout(i18n, entityFactory, eventBus, permChecker,
uiNotification, softwareModuletypeManagement);
if (permChecker.hasCreateRepositoryPermission() || permChecker.hasUpdateRepositoryPermission()) {
createUpdateSWTypeLayout.init();
}
}
@Override
protected boolean hasCreateUpdatePermission() {
return permChecker.hasCreateRepositoryPermission() || permChecker.hasUpdateRepositoryPermission();
}
@Override
protected String getTitle() {
return SPUILabelDefinitions.TYPE;
}
@Override
protected void settingsIconClicked(final ClickEvent event) {
final Window addUpdateWindow = createUpdateSWTypeLayout.getWindow();
UI.getCurrent().addWindow(addUpdateWindow);
addUpdateWindow.setVisible(Boolean.TRUE);
}
@Override
protected boolean dropHitsRequired() {
return false;
}
@Override
protected void hideFilterButtonLayout() {
artifactUploadState.setSwTypeFilterClosed(true);
eventBus.publish(this, UploadArtifactUIEvent.HIDE_FILTER_BY_TYPE);
}
@Override
protected String getConfigureFilterButtonId() {
return SPUIDefinitions.ADD_SOFTWARE_MODULE_TYPE;
}
@Override
protected String getHideButtonId() {
return UIComponentIdProvider.SM_SHOW_FILTER_BUTTON_ID;
}
@Override
protected boolean isAddTagRequired() {
return true;
}
}

View File

@@ -0,0 +1,132 @@
/**
* 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.smtype;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent.SoftwareModuleTypeEnum;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper;
import org.eclipse.hawkbit.ui.layouts.UpdateTag;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.spring.events.EventBus.UIEventBus;
import com.vaadin.ui.Window.CloseListener;
/**
* Layout for the pop-up window which is created when updating a Software Module
* Type on the Upload View.
*
*/
public class UpdateSoftwareModuleTypeLayout extends AbstractSoftwareModuleTypeLayout implements UpdateTag {
private static final long serialVersionUID = 1L;
private final String selectedTypeName;
private final CloseListener closeListener;
/**
* Constructor for initializing the pop-up window for updating a software
* module type. The form fields are filled with the current data of the
* selected software module type.
*
* @param i18n
* VaadinMessageSource
* @param entityFactory
* EntityFactory
* @param eventBus
* UIEventBus
* @param permChecker
* SpPermissionChecker
* @param uiNotification
* UINotification
* @param softwareModuleTypeManagement
* SoftwareModuleTypeManagement
* @param selectedTypeName
* The name of the selected software module type to update
* @param closeListener
* CloseListener which describes the action to do when closing
* the window
*/
public UpdateSoftwareModuleTypeLayout(final VaadinMessageSource i18n, final EntityFactory entityFactory,
final UIEventBus eventBus, final SpPermissionChecker permChecker, final UINotification uiNotification,
final SoftwareModuleTypeManagement softwareModuleTypeManagement, final String selectedTypeName,
final CloseListener closeListener) {
super(i18n, entityFactory, eventBus, permChecker, uiNotification, softwareModuleTypeManagement);
this.selectedTypeName = selectedTypeName;
this.closeListener = closeListener;
initUpdatePopup();
}
private void initUpdatePopup() {
setTagDetails(selectedTypeName);
getWindow().addCloseListener(closeListener);
}
@Override
protected String getWindowCaption() {
return getI18n().getMessage("caption.update", getI18n().getMessage("caption.type"));
}
@Override
protected void saveEntity() {
updateSWModuleType(findEntityByName()
.orElseThrow(() -> new EntityNotFoundException(DistributionSetType.class, getTagName().getValue())));
}
@Override
protected void buildLayout() {
super.buildLayout();
disableFields();
}
@Override
protected void disableFields() {
getTagName().setEnabled(false);
getTypeKey().setEnabled(false);
getAssignOptiongroup().setEnabled(false);
}
@Override
public void setTagDetails(final String selectedEntity) {
getSoftwareModuleTypeManagement().getByName(selectedEntity).ifPresent(selectedTypeTag -> {
getTagName().setValue(selectedTypeTag.getName());
getTagDesc().setValue(selectedTypeTag.getDescription());
getTypeKey().setValue(selectedTypeTag.getKey());
if (selectedTypeTag.getMaxAssignments() == 1) {
getAssignOptiongroup().setValue(getSingleAssignStr());
} else {
getAssignOptiongroup().setValue(getMultiAssignStr());
}
setColorPickerComponentsColor(selectedTypeTag.getColour());
});
disableFields();
}
private void updateSWModuleType(final SoftwareModuleType existingType) {
getSoftwareModuleTypeManagement().update(getEntityFactory().softwareModuleType().update(existingType.getId())
.description(getTagDesc().getValue())
.colour(ColorPickerHelper.getColorPickedString(getColorPickerLayout().getSelPreview())));
getUiNotification().displaySuccess(getI18n().getMessage("message.update.success", existingType.getName()));
getEventBus().publish(this,
new SoftwareModuleTypeEvent(SoftwareModuleTypeEnum.UPDATE_SOFTWARE_MODULE_TYPE, existingType));
}
@Override
protected boolean isUpdateAction() {
return true;
}
}

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.ui.artifacts.smtype;
package org.eclipse.hawkbit.ui.artifacts.smtype.filter;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.ui.artifacts.event.RefreshSoftwareModuleByFilterEvent;

View File

@@ -0,0 +1,197 @@
/**
* 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.smtype.filter;
import java.util.EnumSet;
import java.util.Optional;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent.SoftwareModuleTypeEnum;
import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent;
import org.eclipse.hawkbit.ui.artifacts.smtype.UpdateSoftwareModuleTypeLayout;
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
import org.eclipse.hawkbit.ui.common.SoftwareModuleTypeBeanQuery;
import org.eclipse.hawkbit.ui.common.event.FilterHeaderEvent.FilterHeaderEnum;
import org.eclipse.hawkbit.ui.common.event.SoftwareModuleTypeFilterHeaderEvent;
import org.eclipse.hawkbit.ui.common.filterlayout.AbstractFilterButtons;
import org.eclipse.hawkbit.ui.dd.criteria.UploadViewClientCriterion;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory;
import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer;
import org.vaadin.spring.events.EventBus.UIEventBus;
import org.vaadin.spring.events.EventScope;
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
import com.vaadin.ui.Button.ClickEvent;
/**
* Software module type filter buttons.
*
*/
public class SMTypeFilterButtons extends AbstractFilterButtons {
private static final long serialVersionUID = 1L;
private final ArtifactUploadState artifactUploadState;
private final UploadViewClientCriterion uploadViewClientCriterion;
private final transient SoftwareModuleTypeManagement softwareModuleTypeManagement;
private final transient EntityFactory entityFactory;
private final SpPermissionChecker permChecker;
private final UINotification uiNotification;
/**
* Constructor
*
* @param eventBus
* UIEventBus
* @param artifactUploadState
* ArtifactUploadState
* @param uploadViewClientCriterion
* UploadViewClientCriterion
* @param softwareModuleTypeManagement
* SoftwareModuleTypeManagement
* @param i18n
* VaadinMessageSource
* @param entityFactory
* EntityFactory
* @param permChecker
* SpPermissionChecker
* @param uiNotification
* UINotification
*/
public SMTypeFilterButtons(final UIEventBus eventBus, final ArtifactUploadState artifactUploadState,
final UploadViewClientCriterion uploadViewClientCriterion,
final SoftwareModuleTypeManagement softwareModuleTypeManagement, final VaadinMessageSource i18n,
final EntityFactory entityFactory, final SpPermissionChecker permChecker,
final UINotification uiNotification) {
super(eventBus, new SMTypeFilterButtonClick(eventBus, artifactUploadState, softwareModuleTypeManagement), i18n);
this.artifactUploadState = artifactUploadState;
this.uploadViewClientCriterion = uploadViewClientCriterion;
this.softwareModuleTypeManagement = softwareModuleTypeManagement;
this.entityFactory = entityFactory;
this.permChecker = permChecker;
this.uiNotification = uiNotification;
}
@EventBusListenerMethod(scope = EventScope.UI)
void onEvent(final SoftwareModuleTypeEvent event) {
if (event.getSoftwareModuleType() != null
&& EnumSet.allOf(SoftwareModuleTypeEnum.class).contains(event.getSoftwareModuleTypeEnum())) {
refreshTable();
}
if (isUpdate(event)) {
getEventBus().publish(this, new SoftwareModuleTypeFilterHeaderEvent(FilterHeaderEnum.SHOW_MENUBAR));
}
}
private static boolean isUpdate(final SoftwareModuleTypeEvent event) {
return event.getSoftwareModuleTypeEnum() == SoftwareModuleTypeEnum.UPDATE_SOFTWARE_MODULE_TYPE;
}
@EventBusListenerMethod(scope = EventScope.UI)
void onEvent(final UploadArtifactUIEvent event) {
if (event == UploadArtifactUIEvent.DELETED_ALL_SOFTWARE_TYPE) {
refreshTable();
}
}
@Override
protected String getButtonsTableId() {
return UIComponentIdProvider.SW_MODULE_TYPE_TABLE_ID;
}
@Override
protected LazyQueryContainer createButtonsLazyQueryContainer() {
return HawkbitCommonUtil.createLazyQueryContainer(new BeanQueryFactory<>(SoftwareModuleTypeBeanQuery.class));
}
@Override
protected boolean isClickedByDefault(final String typeName) {
return artifactUploadState.getSoftwareModuleFilters().getSoftwareModuleType()
.map(type -> type.getName().equals(typeName)).orElse(false);
}
@Override
protected String createButtonId(final String name) {
return UIComponentIdProvider.SM_TYPE_FILTER_BTN_ID + name;
}
@Override
protected DropHandler getFilterButtonDropHandler() {
return new DropHandler() {
private static final long serialVersionUID = 1L;
@Override
public AcceptCriterion getAcceptCriterion() {
return uploadViewClientCriterion;
}
@Override
public void drop(final DragAndDropEvent event) {
/* Not required */
}
};
}
@Override
protected String getButttonWrapperIdPrefix() {
return UIComponentIdProvider.UPLOAD_TYPE_BUTTON_PREFIX;
}
@Override
protected String getButtonWrapperData() {
return null;
}
@Override
protected void addEditButtonClickListener(final ClickEvent event) {
new UpdateSoftwareModuleTypeLayout(getI18n(), entityFactory, getEventBus(), permChecker, uiNotification,
softwareModuleTypeManagement, getEntityId(event), getCloseListenerForEditAndDeleteTag(
new SoftwareModuleTypeFilterHeaderEvent(FilterHeaderEnum.SHOW_MENUBAR)));
}
@Override
protected void addDeleteButtonClickListener(final ClickEvent event) {
openConfirmationWindowForDeletion(getEntityId(event),
getI18n().getMessage("caption.entity.software.module.type"),
new SoftwareModuleTypeFilterHeaderEvent(FilterHeaderEnum.SHOW_MENUBAR));
}
@Override
protected void deleteEntity(final String entityToDelete) {
final Optional<SoftwareModuleType> swmTypeToDelete = softwareModuleTypeManagement.getByName(entityToDelete);
swmTypeToDelete.ifPresent(tag -> {
if (artifactUploadState.getSoftwareModuleFilters().getSoftwareModuleType().equals(swmTypeToDelete)) {
uiNotification.displayValidationError(getI18n().getMessage("message.tag.delete", entityToDelete));
removeUpdateAndDeleteColumn();
} else {
softwareModuleTypeManagement.delete(swmTypeToDelete.get().getId());
getEventBus().publish(this, UploadArtifactUIEvent.DELETED_ALL_SOFTWARE_TYPE);
uiNotification.displaySuccess(getI18n().getMessage("message.delete.success", entityToDelete));
}
});
}
}

View File

@@ -0,0 +1,129 @@
/**
* 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.smtype.filter;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent;
import org.eclipse.hawkbit.ui.artifacts.smtype.CreateSoftwareModuleTypeLayout;
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
import org.eclipse.hawkbit.ui.common.event.FilterHeaderEvent.FilterHeaderEnum;
import org.eclipse.hawkbit.ui.common.event.SoftwareModuleTypeFilterHeaderEvent;
import org.eclipse.hawkbit.ui.common.filterlayout.AbstractFilterHeader;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.spring.events.EventBus.UIEventBus;
import org.vaadin.spring.events.EventScope;
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.MenuBar.Command;
/**
* Software module type filter buttons header.
*/
public class SMTypeFilterHeader extends AbstractFilterHeader {
private static final long serialVersionUID = 1L;
private final ArtifactUploadState artifactUploadState;
private final transient EntityFactory entityFactory;
private final UINotification uiNotification;
private final transient SoftwareModuleTypeManagement softwareModuleTypeManagement;
private final SMTypeFilterButtons smTypeFilterButtons;
SMTypeFilterHeader(final VaadinMessageSource i18n, final SpPermissionChecker permChecker, final UIEventBus eventBus,
final ArtifactUploadState artifactUploadState, final EntityFactory entityFactory,
final UINotification uiNotification, final SoftwareModuleTypeManagement softwareModuleTypeManagement,
final SMTypeFilterButtons smTypeFilterButtons) {
super(permChecker, eventBus, i18n);
this.artifactUploadState = artifactUploadState;
this.entityFactory = entityFactory;
this.uiNotification = uiNotification;
this.softwareModuleTypeManagement = softwareModuleTypeManagement;
this.smTypeFilterButtons = smTypeFilterButtons;
}
@Override
protected String getTitle() {
return SPUILabelDefinitions.TYPE;
}
@Override
protected boolean dropHitsRequired() {
return false;
}
@Override
protected void hideFilterButtonLayout() {
artifactUploadState.setSwTypeFilterClosed(true);
getEventBus().publish(this, UploadArtifactUIEvent.HIDE_FILTER_BY_TYPE);
}
@Override
protected String getConfigureFilterButtonId() {
return UIComponentIdProvider.ADD_SOFTWARE_MODULE_TYPE;
}
@Override
protected String getHideButtonId() {
return UIComponentIdProvider.SM_SHOW_FILTER_BUTTON_ID;
}
@Override
protected boolean isAddTagRequired() {
return true;
}
@Override
protected Command getAddButtonCommand() {
return command -> new CreateSoftwareModuleTypeLayout(getI18n(), entityFactory, getEventBus(), getPermChecker(),
uiNotification, softwareModuleTypeManagement);
}
@Override
protected Command getDeleteButtonCommand() {
return command -> {
smTypeFilterButtons.addDeleteColumn();
getEventBus().publish(this, new SoftwareModuleTypeFilterHeaderEvent(FilterHeaderEnum.SHOW_CANCEL_BUTTON));
};
}
@Override
protected Command getUpdateButtonCommand() {
return command -> {
smTypeFilterButtons.addUpdateColumn();
getEventBus().publish(this, new SoftwareModuleTypeFilterHeaderEvent(FilterHeaderEnum.SHOW_CANCEL_BUTTON));
};
}
@Override
protected void cancelUpdateOrDeleteTag(final ClickEvent event) {
super.cancelUpdateOrDeleteTag(event);
smTypeFilterButtons.removeUpdateAndDeleteColumn();
}
@EventBusListenerMethod(scope = EventScope.UI)
private void onEvent(final SoftwareModuleTypeFilterHeaderEvent event) {
processFilterHeaderEvent(event);
}
@Override
protected String getMenuBarId() {
return UIComponentIdProvider.SOFT_MODULE_TYPE_MENU_BAR_ID;
}
}

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.ui.artifacts.smtype;
package org.eclipse.hawkbit.ui.artifacts.smtype.filter;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
@@ -14,7 +14,6 @@ import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent;
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
import org.eclipse.hawkbit.ui.common.filterlayout.AbstractFilterLayout;
import org.eclipse.hawkbit.ui.dd.criteria.UploadViewClientCriterion;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.spring.events.EventBus.UIEventBus;
@@ -26,23 +25,38 @@ import org.vaadin.spring.events.annotation.EventBusListenerMethod;
*/
public class SMTypeFilterLayout extends AbstractFilterLayout {
private static final long serialVersionUID = 1581066345157393665L;
private static final long serialVersionUID = 1L;
private final ArtifactUploadState artifactUploadState;
/**
* Constructor
*
* @param artifactUploadState
* ArtifactUploadState
* @param i18n
* VaadinMessageSource
* @param permChecker
* SpPermissionChecker
* @param eventBus
* UIEventBus
* @param entityFactory
* EntityFactory
* @param uiNotification
* UINotification
* @param softwareModuleTypeManagement
* SoftwareModuleTypeManagement
* @param sMTypeFilterButtons
* SMTypeFilterButtons
*/
public SMTypeFilterLayout(final ArtifactUploadState artifactUploadState, final VaadinMessageSource i18n,
final SpPermissionChecker permChecker, final UIEventBus eventBus, final EntityFactory entityFactory,
final UINotification uiNotification, final SoftwareModuleTypeManagement softwareModuleTypeManagement,
final UploadViewClientCriterion uploadViewClientCriterion) {
final SMTypeFilterButtons sMTypeFilterButtons) {
super(new SMTypeFilterHeader(i18n, permChecker, eventBus, artifactUploadState, entityFactory, uiNotification,
softwareModuleTypeManagement),
new SMTypeFilterButtons(eventBus, artifactUploadState, uploadViewClientCriterion,
softwareModuleTypeManagement));
softwareModuleTypeManagement, sMTypeFilterButtons), sMTypeFilterButtons, eventBus);
this.artifactUploadState = artifactUploadState;
restoreState();
eventBus.subscribe(this);
}
@EventBusListenerMethod(scope = EventScope.UI)

View File

@@ -8,22 +8,29 @@
*/
package org.eclipse.hawkbit.ui.artifacts.state;
import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
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 java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.ui.artifacts.upload.UploadStatusObject;
import org.eclipse.hawkbit.ui.artifacts.upload.FileUploadId;
import org.eclipse.hawkbit.ui.artifacts.upload.FileUploadProgress;
import org.eclipse.hawkbit.ui.artifacts.upload.FileUploadProgress.FileUploadStatus;
import org.eclipse.hawkbit.ui.common.ManagementEntityState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.VaadinSessionScope;
@@ -36,16 +43,14 @@ public class ArtifactUploadState implements ManagementEntityState, Serializable
private static final long serialVersionUID = 1L;
private static final Logger LOG = LoggerFactory.getLogger(ArtifactUploadState.class);
private final SoftwareModuleFilters softwareModuleFilters;
private final Map<Long, String> deleteSofwareModules = new HashMap<>();
private final Set<CustomFile> fileSelected = new HashSet<>();
private transient Optional<Long> selectedBaseSwModuleId = Optional.empty();
private final Map<String, SoftwareModule> baseSwModuleList = new HashMap<>();
private Set<Long> selectedSoftwareModules = Collections.emptySet();
private boolean swTypeFilterClosed;
@@ -60,49 +65,17 @@ public class ArtifactUploadState implements ManagementEntityState, Serializable
private boolean statusPopupMinimized;
private boolean uploadCompleted;
private List<UploadStatusObject> uploadedFileStatusList = new ArrayList<>();
private final AtomicInteger numberOfFileUploadsExpected = new AtomicInteger();
private final AtomicInteger numberOfFilesActuallyUpload = new AtomicInteger();
private final AtomicInteger numberOfFileUploadsFailed = new AtomicInteger();
/**
* Map that holds all files that were selected for upload. They remain in
* the list even if upload fails, succeeds or is aborted by the user.
*/
private Map<FileUploadId, FileUploadProgress> overallFilesInUploadProcess;
@Autowired
ArtifactUploadState(final SoftwareModuleFilters softwareModuleFilters) {
this.softwareModuleFilters = softwareModuleFilters;
}
public AtomicInteger getNumberOfFileUploadsFailed() {
return numberOfFileUploadsFailed;
}
public AtomicInteger getNumberOfFilesActuallyUpload() {
return numberOfFilesActuallyUpload;
}
public AtomicInteger getNumberOfFileUploadsExpected() {
return numberOfFileUploadsExpected;
}
public List<UploadStatusObject> getUploadedFileStatusList() {
return uploadedFileStatusList;
}
public void setUploadedFileStatusList(final List<UploadStatusObject> uploadedFileStatusList) {
this.uploadedFileStatusList = uploadedFileStatusList;
}
public boolean isUploadCompleted() {
return uploadCompleted;
}
public void setUploadCompleted(final boolean uploadCompleted) {
this.uploadCompleted = uploadCompleted;
}
public void setStatusPopupMinimized(final boolean statusPopupMinimized) {
this.statusPopupMinimized = statusPopupMinimized;
}
@@ -115,22 +88,14 @@ public class ArtifactUploadState implements ManagementEntityState, Serializable
return softwareModuleFilters;
}
public Map<Long, String> getDeleteSofwareModules() {
public Map<Long, String> getDeleteSoftwareModules() {
return deleteSofwareModules;
}
public Set<CustomFile> getFileSelected() {
return fileSelected;
}
public Optional<Long> getSelectedBaseSwModuleId() {
return selectedBaseSwModuleId;
}
public Map<String, SoftwareModule> getBaseSwModuleList() {
return baseSwModuleList;
}
public Set<Long> getSelectedSoftwareModules() {
return selectedSoftwareModules;
}
@@ -180,4 +145,150 @@ public class ArtifactUploadState implements ManagementEntityState, Serializable
public void setNoDataAvilableSoftwareModule(final boolean noDataAvilableSoftwareModule) {
this.noDataAvilableSoftwareModule = noDataAvilableSoftwareModule;
}
public boolean isMoreThanOneSoftwareModulesSelected() {
return getSelectedSoftwareModules().size() > 1;
}
public boolean isNoSoftwareModuleSelected() {
return !getSelectedBaseSwModuleId().isPresent();
}
public void removeFilesFromOverallUploadProcessList(final Collection<FileUploadId> filesToRemove) {
getOverallFilesInUploadProcessMap().keySet().removeAll(filesToRemove);
}
public Set<FileUploadId> getAllFileUploadIdsFromOverallUploadProcessList() {
return Collections.unmodifiableSet(getOverallFilesInUploadProcessMap().keySet());
}
public Collection<FileUploadProgress> getAllFileUploadProgressValuesFromOverallUploadProcessList() {
return Collections.unmodifiableCollection(getOverallFilesInUploadProcessMap().values());
}
public Set<FileUploadId> getFilesInFailedState() {
return Collections.unmodifiableSet(getFailedUploads());
}
public FileUploadProgress getFileUploadProgress(final FileUploadId fileUploadId) {
return getOverallFilesInUploadProcessMap().get(fileUploadId);
}
public void updateFileUploadProgress(final FileUploadId fileUploadId, final FileUploadProgress fileUploadProgress) {
getOverallFilesInUploadProcessMap().put(fileUploadId, fileUploadProgress);
}
public boolean isFileInUploadState(final FileUploadId fileUploadId) {
return getOverallFilesInUploadProcessMap().containsKey(fileUploadId);
}
public boolean isFileInUploadState(final String filename, final SoftwareModule softwareModule) {
return isFileInUploadState(new FileUploadId(filename, softwareModule));
}
public boolean isAtLeastOneUploadInProgress() {
return getInProgressCount() > 0;
}
public boolean areAllUploadsFinished() {
return getInProgressCount() == 0;
}
private int getInProgressCount() {
final int succeededUploadCount = getSucceededUploads().size();
final int failedUploadCount = getFailedUploads().size();
final int overallUploadCount = getOverallFilesInUploadProcessMap().size();
final int inProgressCount = overallUploadCount - failedUploadCount - succeededUploadCount;
assertFileStateConsistency(inProgressCount, overallUploadCount, succeededUploadCount, failedUploadCount);
return inProgressCount;
}
private static void assertFileStateConsistency(final int inProgressCount, final int overallUploadCount,
final int succeededUploadCount, final int failedUploadCount) {
if (inProgressCount < 0) {
LOG.error("IllegalState: \n{}",
getStateListLogMessage(overallUploadCount, succeededUploadCount, failedUploadCount));
}
}
private static String getStateListLogMessage(final int overallUploadCount, final int succeededUploadCount,
final int failedUploadCount) {
final StringBuilder buffer = new StringBuilder();
buffer.append("Overall uploads: " + overallUploadCount);
buffer.append("| succeeded uploads: " + succeededUploadCount);
buffer.append("| Failed Uploads: " + failedUploadCount);
return buffer.toString();
}
void clearFileStates() {
getOverallFilesInUploadProcessMap().clear();
}
/**
* Clears all temp data collected while uploading files.
*/
public void clearUploadTempData() {
LOG.debug("Cleaning up temp data...");
// delete file system zombies
for (final FileUploadProgress fileUploadProgress : getAllFileUploadProgressValuesFromOverallUploadProcessList()) {
if (!StringUtils.isBlank(fileUploadProgress.getFilePath())) {
final boolean deleted = FileUtils.deleteQuietly(new File(fileUploadProgress.getFilePath()));
if (!deleted) {
LOG.warn("TempFile was not deleted: " + fileUploadProgress.getFilePath());
}
}
}
clearFileStates();
}
/**
* Checks if an upload is in progress for the given Software Module
*
* @param softwareModuleId
* id of the software module
* @return boolean
*/
public boolean isUploadInProgressForSelectedSoftwareModule(final Long softwareModuleId) {
for (final FileUploadId fileUploadId : getAllFileUploadIdsFromOverallUploadProcessList()) {
if (fileUploadId.getSoftwareModuleId().equals(softwareModuleId)) {
return true;
}
}
return false;
}
private Map<FileUploadId, FileUploadProgress> getOverallFilesInUploadProcessMap() {
if (overallFilesInUploadProcess == null) {
overallFilesInUploadProcess = Maps.newConcurrentMap();
}
return overallFilesInUploadProcess;
}
private Set<FileUploadId> getFailedUploads() {
final Collection<FileUploadProgress> allFileUploadProgressObjects = getOverallFilesInUploadProcessMap()
.values();
final Set<FileUploadId> failedFileUploads = Sets.newHashSet();
for (final FileUploadProgress fileUploadProgress : allFileUploadProgressObjects) {
if (fileUploadProgress.getFileUploadStatus() == FileUploadStatus.UPLOAD_FAILED) {
failedFileUploads.add(fileUploadProgress.getFileUploadId());
}
}
return failedFileUploads;
}
private Set<FileUploadId> getSucceededUploads() {
final Collection<FileUploadProgress> allFileUploadProgressObjects = getOverallFilesInUploadProcessMap()
.values();
final Set<FileUploadId> succeededFileUploads = Sets.newHashSet();
for (final FileUploadProgress fileUploadProgress : allFileUploadProgressObjects) {
if (fileUploadProgress.getFileUploadStatus() == FileUploadStatus.UPLOAD_SUCCESSFUL) {
succeededFileUploads.add(fileUploadProgress.getFileUploadId());
}
}
return succeededFileUploads;
}
}

View File

@@ -1,205 +0,0 @@
/**
* 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.state;
import java.io.Serializable;
/**
* Custom file to hold details of uploaded file.
*
*
*
*/
public class CustomFile implements Serializable {
private static final long serialVersionUID = -5902321650745311767L;
private final String fileName;
private long fileSize;
private String filePath;
private String baseSoftwareModuleName;
private String baseSoftwareModuleVersion;
private String mimeType;
/**
* Used to specify if the file is uploaded successfully.
*/
private Boolean isValid = Boolean.TRUE;
/**
* Reason if upload fails.
*/
private String failureReason;
/**
* Initialize details.
*
* @param fileName
* uploaded file name
* @param fileSize
* uploaded file size
* @param filePath
* uploaded file path
* @param baseSoftwareModuleName
* software module name
* @param baseSoftwareModuleVersion
* software module version
* @param mimeType
* the mimeType of the file
*/
public CustomFile(final String fileName, final long fileSize, final String filePath,
final String baseSoftwareModuleName, final String baseSoftwareModuleVersion, final String mimeType) {
this.fileName = fileName;
this.fileSize = fileSize;
this.filePath = filePath;
this.baseSoftwareModuleName = baseSoftwareModuleName;
this.baseSoftwareModuleVersion = baseSoftwareModuleVersion;
this.mimeType = mimeType;
}
/**
* Initialize details.
*
* @param fileName
* uploaded file name
* @param baseSoftwareModuleName
* software module name
* @param baseSoftwareModuleVersion
* software module version
*/
public CustomFile(final String fileName, final String baseSoftwareModuleName,
final String baseSoftwareModuleVersion) {
this.fileName = fileName;
this.baseSoftwareModuleName = baseSoftwareModuleName;
this.baseSoftwareModuleVersion = baseSoftwareModuleVersion;
}
public String getBaseSoftwareModuleName() {
return baseSoftwareModuleName;
}
public void setBaseSoftwareModuleName(final String baseSoftwareModuleName) {
this.baseSoftwareModuleName = baseSoftwareModuleName;
}
public String getBaseSoftwareModuleVersion() {
return baseSoftwareModuleVersion;
}
public void setBaseSoftwareModuleVersion(final String baseSoftwareModuleVersion) {
this.baseSoftwareModuleVersion = baseSoftwareModuleVersion;
}
public String getFileName() {
return fileName;
}
public long getFileSize() {
return fileSize;
}
public void setFileSize(final long fileSize) {
this.fileSize = fileSize;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(final String filePath) {
this.filePath = filePath;
}
public String getMimeType() {
return mimeType;
}
/**
*
* @return the isValid
*/
public Boolean getIsValid() {
return isValid;
}
/**
* @param isValid
* the isValid to set
*/
public void setIsValid(final Boolean isValid) {
this.isValid = isValid;
}
/**
* @param mimeType
* the mimeType to set
*/
public void setMimeType(final String mimeType) {
this.mimeType = mimeType;
}
/**
* @return the failureReason
*/
public String getFailureReason() {
return failureReason;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((baseSoftwareModuleName == null) ? 0 : baseSoftwareModuleName.hashCode());
result = prime * result + ((baseSoftwareModuleVersion == null) ? 0 : baseSoftwareModuleVersion.hashCode());
result = prime * result + ((fileName == null) ? 0 : fileName.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final CustomFile other = (CustomFile) obj;
if (baseSoftwareModuleName == null) {
if (other.baseSoftwareModuleName != null) {
return false;
}
} else if (!baseSoftwareModuleName.equals(other.baseSoftwareModuleName)) {
return false;
}
if (baseSoftwareModuleVersion == null) {
if (other.baseSoftwareModuleVersion != null) {
return false;
}
} else if (!baseSoftwareModuleVersion.equals(other.baseSoftwareModuleVersion)) {
return false;
}
if (fileName == null) {
if (other.fileName != null) {
return false;
}
} else if (!fileName.equals(other.fileName)) {
return false;
}
return true;
}
}

View File

@@ -17,7 +17,7 @@ import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.VaadinSessionScope;
/**
* Softwrae module filters.
* Software module filters.
*
*
*/

View File

@@ -0,0 +1,238 @@
/**
* 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;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.hawkbit.repository.ArtifactManagement;
import org.eclipse.hawkbit.repository.exception.ArtifactUploadFailedException;
import org.eclipse.hawkbit.repository.exception.InvalidMD5HashException;
import org.eclipse.hawkbit.repository.exception.InvalidSHA1HashException;
import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent.SoftwareModuleEventType;
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
import org.eclipse.hawkbit.ui.artifacts.upload.FileUploadProgress.FileUploadStatus;
import org.eclipse.hawkbit.ui.utils.SpringContextHelper;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.vaadin.spring.events.EventBus;
import org.vaadin.spring.events.EventBus.UIEventBus;
import com.google.common.io.ByteStreams;
/**
* Abstract base class for transferring files from the browser to the
* repository.
*/
public abstract class AbstractFileTransferHandler implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger LOG = LoggerFactory.getLogger(AbstractFileTransferHandler.class);
private volatile boolean duplicateFile;
private volatile boolean uploadInterrupted;
private volatile String tempFilePath;
private volatile String failureReason;
private final ArtifactUploadState artifactUploadState;
private final transient UIEventBus eventBus;
private final transient ArtifactManagement artifactManagement;
private final VaadinMessageSource i18n;
AbstractFileTransferHandler(final ArtifactManagement artifactManagement, final VaadinMessageSource i18n) {
this.artifactManagement = artifactManagement;
this.i18n = i18n;
this.eventBus = SpringContextHelper.getBean(EventBus.UIEventBus.class);
this.artifactUploadState = SpringContextHelper.getBean(ArtifactUploadState.class);
}
protected boolean isDuplicateFile() {
return duplicateFile;
}
protected void setDuplicateFile() {
uploadInterrupted = true;
duplicateFile = true;
}
protected void setUploadInterrupted() {
uploadInterrupted = true;
}
protected boolean isUploadInterrupted() {
return uploadInterrupted;
}
protected void resetState() {
duplicateFile = false;
uploadInterrupted = false;
failureReason = null;
}
protected ArtifactUploadState getUploadState() {
return artifactUploadState;
}
protected VaadinMessageSource getI18n() {
return i18n;
}
private void setFailureReason(final String failureReason) {
this.failureReason = failureReason;
}
protected void setFailureReasonUploadFailed() {
setFailureReason(i18n.getMessage("message.upload.failed"));
}
protected void setFailureReasonFileSizeExceeded(final long maxSize) {
setFailureReason(i18n.getMessage("message.uploadedfile.size.exceeded", maxSize));
}
protected boolean isFileAlreadyContainedInSoftwareModule(final FileUploadId newFileUploadId,
final SoftwareModule softwareModule) {
for (final Artifact artifact : softwareModule.getArtifacts()) {
final FileUploadId existingId = new FileUploadId(artifact.getFilename(), softwareModule);
if (existingId.equals(newFileUploadId)) {
return true;
}
}
return false;
}
protected void publishUploadStarted(final FileUploadId fileUploadId) {
LOG.info("Upload started for file {}", fileUploadId);
final FileUploadProgress fileUploadProgress = new FileUploadProgress(fileUploadId, FileUploadStatus.UPLOAD_STARTED);
artifactUploadState.updateFileUploadProgress(fileUploadId, fileUploadProgress);
eventBus.publish(this, fileUploadProgress);
}
protected void publishUploadProgressEvent(final FileUploadId fileUploadId, final long bytesReceived,
final long fileSize, final String tempFilePath) {
if (LOG.isTraceEnabled()) {
LOG.trace("Upload in progress for file {} - {}%", fileUploadId,
String.format("%.0f", (double) bytesReceived / (double) fileSize * 100));
}
final FileUploadProgress fileUploadProgress = new FileUploadProgress(fileUploadId,
FileUploadStatus.UPLOAD_IN_PROGRESS, bytesReceived, fileSize, tempFilePath);
artifactUploadState.updateFileUploadProgress(fileUploadId, fileUploadProgress);
eventBus.publish(this, fileUploadProgress);
}
private void publishUploadSucceeded(final FileUploadId fileUploadId, final long fileSize,
final String tempFilePath) {
LOG.info("Upload succeeded for file {}", fileUploadId);
final FileUploadProgress fileUploadProgress = new FileUploadProgress(fileUploadId,
FileUploadStatus.UPLOAD_SUCCESSFUL, fileSize, fileSize, tempFilePath);
artifactUploadState.updateFileUploadProgress(fileUploadId, fileUploadProgress);
eventBus.publish(this, fileUploadProgress);
}
protected void publishUploadFinishedEvent(final FileUploadId fileUploadId) {
LOG.info("Upload finished for file {}", fileUploadId);
final FileUploadProgress fileUploadProgress = new FileUploadProgress(fileUploadId,
FileUploadStatus.UPLOAD_FINISHED);
eventBus.publish(this, fileUploadProgress);
}
protected void publishUploadFailedEvent(final FileUploadId fileUploadId, final String failureReason,
final Exception uploadException) {
LOG.info("Upload failed for file {} due to {}", fileUploadId,
StringUtils.isBlank(failureReason) ? uploadException.getMessage() : failureReason);
final FileUploadProgress fileUploadProgress = new FileUploadProgress(fileUploadId,
FileUploadStatus.UPLOAD_FAILED,
StringUtils.isBlank(failureReason) ? uploadException.getMessage() : failureReason);
artifactUploadState.updateFileUploadProgress(fileUploadId, fileUploadProgress);
eventBus.publish(this, fileUploadProgress);
}
protected void publishUploadFailedEvent(final FileUploadId fileUploadId, final Exception uploadException) {
publishUploadFailedEvent(fileUploadId, failureReason, uploadException);
}
protected void assertStateConsistency(final FileUploadId fileUploadId, final String filenameExtractedFromEvent) {
if (!filenameExtractedFromEvent.equals(fileUploadId.getFilename())) {
throw new IllegalStateException("Event filename " + filenameExtractedFromEvent + " but stored filename "
+ fileUploadId.getFilename());
}
}
protected OutputStream createOutputStreamForTempFile() throws IOException {
if (isUploadInterrupted()) {
return ByteStreams.nullOutputStream();
}
final File tempFile = File.createTempFile("spUiArtifactUpload", null);
// we return the outputstream so we cannot close it here
@SuppressWarnings("squid:S2095")
final OutputStream out = new FileOutputStream(tempFile);
tempFilePath = tempFile.getAbsolutePath();
return out;
}
protected String getTempFilePath() {
return tempFilePath;
}
// Exception squid:S3655 - Optional access is checked in
// checkIfArtifactDetailsDispalyed subroutine
@SuppressWarnings("squid:S3655")
protected void transferArtifactToRepository(final FileUploadId fileUploadId, final long fileSize,
final String mimeType, final String tempFilePath) {
final File newFile = new File(tempFilePath);
final String filename = fileUploadId.getFilename();
LOG.info("Transfering tempfile {} - {} to repository", filename, tempFilePath);
try (FileInputStream fis = new FileInputStream(newFile)) {
artifactManagement.create(fis, fileUploadId.getSoftwareModuleId(), filename, null, null, true, mimeType,
fileSize);
publishUploadSucceeded(fileUploadId, fileSize, tempFilePath);
eventBus.publish(this, new SoftwareModuleEvent(SoftwareModuleEventType.ARTIFACTS_CHANGED,
fileUploadId.getSoftwareModuleId()));
} catch (final ArtifactUploadFailedException | InvalidSHA1HashException | InvalidMD5HashException
| IOException e) {
publishUploadFailedEvent(fileUploadId, i18n.getMessage("message.upload.failed"), e);
LOG.error("Failed to transfer file to repository", e);
} finally {
LOG.debug("Deleting tempfile {} - {}", filename, newFile.getAbsolutePath());
if (newFile.exists() && !newFile.delete()) {
LOG.error("Could not delete temporary file: {}", newFile.getAbsolutePath());
}
}
publishUploadFinishedEvent(fileUploadId);
}
}

View File

@@ -0,0 +1,167 @@
/**
* 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;
import java.io.IOException;
import java.io.OutputStream;
import org.eclipse.hawkbit.repository.ArtifactManagement;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.ui.artifacts.upload.FileUploadProgress.FileUploadStatus;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.io.ByteStreams;
import com.vaadin.server.StreamVariable;
import com.vaadin.ui.Upload.FinishedEvent;
import com.vaadin.ui.Upload.SucceededEvent;
/**
* {@link StreamVariable} implementation to read and upload a file. One instance
* per file stream is used.
*
* The handler manages the output to the user and at the same time ensures that
* the upload does not exceed the configured max file size.
*
*/
public class FileTransferHandlerStreamVariable extends AbstractFileTransferHandler implements StreamVariable {
private static final long serialVersionUID = 1L;
private static final Logger LOG = LoggerFactory.getLogger(FileTransferHandlerStreamVariable.class);
private final long maxSize;
private final long fileSize;
private final String mimeType;
private final FileUploadId fileUploadId;
private final SoftwareModule selectedSoftwareModule;
FileTransferHandlerStreamVariable(final String fileName, final long fileSize, final long maxSize,
final String mimeType, final SoftwareModule selectedSw, final ArtifactManagement artifactManagement,
final VaadinMessageSource i18n) {
super(artifactManagement, i18n);
this.fileSize = fileSize;
this.maxSize = maxSize;
this.mimeType = mimeType;
this.selectedSoftwareModule = selectedSw;
this.fileUploadId = new FileUploadId(fileName, selectedSw);
publishUploadStarted(fileUploadId);
}
@Override
public void streamingStarted(final StreamingStartEvent event) {
assertStateConsistency(fileUploadId, event.getFileName());
if (isFileAlreadyContainedInSoftwareModule(fileUploadId, selectedSoftwareModule)) {
LOG.info("File {} already contained in Software Module {}", fileUploadId.getFilename(),
selectedSoftwareModule);
getUploadState().updateFileUploadProgress(fileUploadId,
new FileUploadProgress(fileUploadId, FileUploadStatus.UPLOAD_FAILED));
setDuplicateFile();
}
}
@Override
public final OutputStream getOutputStream() {
// we return the outputstream so we cannot close it here
@SuppressWarnings("squid:S2095")
OutputStream outputStream = ByteStreams.nullOutputStream();
try {
outputStream = createOutputStreamForTempFile();
publishUploadProgressEvent(fileUploadId, 0, fileSize, getTempFilePath());
} catch (final IOException e) {
LOG.error("Creating temp file for upload failed {}.", e);
try {
outputStream.close();
} catch (final IOException e1) {
LOG.error("Closing output stream caused an exception {}", e1);
}
setFailureReasonUploadFailed();
setUploadInterrupted();
}
return outputStream;
}
/**
* listen progress.
*
* @return boolean
*/
@Override
public boolean listenProgress() {
return true;
}
/**
* Reports progress in {@link StreamVariable} variant. Interrupts
*
* @see com.vaadin.server.StreamVariable#onProgress(com.vaadin.server.StreamVariable.StreamingProgressEvent)
*/
@Override
public void onProgress(final StreamingProgressEvent event) {
assertStateConsistency(fileUploadId, event.getFileName());
if (event.getBytesReceived() > maxSize || event.getContentLength() > maxSize) {
LOG.error("User tried to upload more than was allowed ({}).", maxSize);
setFailureReasonFileSizeExceeded(maxSize);
setUploadInterrupted();
return;
}
if (isUploadInterrupted()) {
return;
}
publishUploadProgressEvent(fileUploadId, event.getBytesReceived(), event.getContentLength(), getTempFilePath());
}
/**
* Upload finished for {@link StreamVariable} variant. Called only in good
* case. So a combination of {@link #uploadSucceeded(SucceededEvent)} and
* {@link #uploadFinished(FinishedEvent)}.
*
* @see com.vaadin.server.StreamVariable#streamingFinished(com.vaadin.server.StreamVariable.StreamingEndEvent)
*/
@Override
public void streamingFinished(final StreamingEndEvent event) {
assertStateConsistency(fileUploadId, event.getFileName());
transferArtifactToRepository(fileUploadId, event.getContentLength(), mimeType, getTempFilePath());
}
/**
* Upload failed for{@link StreamVariable} variant.
*
* @param event
* StreamingEndEvent
*/
@Override
public void streamingFailed(final StreamingErrorEvent event) {
assertStateConsistency(fileUploadId, event.getFileName());
if (isDuplicateFile()) {
publishUploadFailedEvent(fileUploadId, getI18n().getMessage("message.no.duplicateFiles"),
event.getException());
} else {
publishUploadFailedEvent(fileUploadId, event.getException());
}
publishUploadFinishedEvent(fileUploadId);
}
@Override
public boolean isInterrupted() {
return isUploadInterrupted();
}
}

View File

@@ -0,0 +1,226 @@
/**
* 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;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Optional;
import org.eclipse.hawkbit.repository.ArtifactManagement;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.ui.artifacts.upload.FileUploadProgress.FileUploadStatus;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.io.ByteStreams;
import com.vaadin.ui.Upload;
import com.vaadin.ui.Upload.FailedEvent;
import com.vaadin.ui.Upload.FailedListener;
import com.vaadin.ui.Upload.FinishedEvent;
import com.vaadin.ui.Upload.FinishedListener;
import com.vaadin.ui.Upload.ProgressListener;
import com.vaadin.ui.Upload.Receiver;
import com.vaadin.ui.Upload.StartedEvent;
import com.vaadin.ui.Upload.StartedListener;
import com.vaadin.ui.Upload.SucceededEvent;
import com.vaadin.ui.Upload.SucceededListener;
/**
* Vaadin Upload implementation to read and upload a file. One instance is used
* to handle all the uploads.
*
* The handler manages the output to the user and at the same time ensures that
* the upload does not exceed the configured max file size.
*
*/
public class FileTransferHandlerVaadinUpload extends AbstractFileTransferHandler
implements Receiver, SucceededListener, FailedListener, FinishedListener, ProgressListener, StartedListener {
private static final long serialVersionUID = 1L;
private static final Logger LOG = LoggerFactory.getLogger(FileTransferHandlerVaadinUpload.class);
private final transient SoftwareModuleManagement softwareModuleManagement;
private final long maxSize;
private volatile String mimeType;
private volatile FileUploadId fileUploadId;
FileTransferHandlerVaadinUpload(final long maxSize, final SoftwareModuleManagement softwareManagement,
final ArtifactManagement artifactManagement, final VaadinMessageSource i18n) {
super(artifactManagement, i18n);
this.maxSize = maxSize;
this.softwareModuleManagement = softwareManagement;
}
/**
* Upload started for {@link Upload} variant.
*
* @see com.vaadin.ui.Upload.StartedListener#uploadStarted(com.vaadin.ui.Upload.StartedEvent)
*/
@Override
public void uploadStarted(final StartedEvent event) {
// reset internal state here because instance is reused for next upload!
resetState();
this.mimeType = null;
this.fileUploadId = null;
assertThatOneSoftwareModuleIsSelected();
// selected software module at the time of this callback is considered
SoftwareModule softwareModule = null;
final Optional<Long> selectedSoftwareModuleId = getUploadState().getSelectedBaseSwModuleId();
final Long softwareModuleId = selectedSoftwareModuleId.orElse(null);
if (softwareModuleId != null) {
softwareModule = softwareModuleManagement.get(softwareModuleId).orElse(null);
}
this.fileUploadId = new FileUploadId(event.getFilename(), softwareModule);
this.mimeType = event.getMIMEType();
if (getUploadState().isFileInUploadState(this.fileUploadId)) {
setFailureReasonUploadFailed();
// actual interrupt will happen a bit late so setting the below
// flag
setDuplicateFile();
event.getUpload().interruptUpload();
} else {
LOG.info("Uploading file {}", fileUploadId);
publishUploadStarted(fileUploadId);
if (isFileAlreadyContainedInSoftwareModule(fileUploadId, softwareModule)) {
LOG.info("File {} already contained in Software Module {}", fileUploadId.getFilename(), softwareModule);
getUploadState().updateFileUploadProgress(fileUploadId,
new FileUploadProgress(fileUploadId, FileUploadStatus.UPLOAD_FAILED));
setDuplicateFile();
event.getUpload().interruptUpload();
}
}
}
private void assertThatOneSoftwareModuleIsSelected() {
// FileUpload button should be disabled if no SoftwareModul or more
// than one is selected!
if (getUploadState().isNoSoftwareModuleSelected()) {
throw new IllegalStateException("No SoftwareModul selected");
} else if (getUploadState().isMoreThanOneSoftwareModulesSelected()) {
throw new IllegalStateException("More than one SoftwareModul selected but only one is allowed");
}
}
/**
* Create stream for {@link Upload} variant.
*
* @see com.vaadin.ui.Upload.Receiver#receiveUpload(java.lang.String,
* java.lang.String)
*/
@Override
public OutputStream receiveUpload(final String fileName, final String mimeType) {
if (isUploadInterrupted()) {
return ByteStreams.nullOutputStream();
}
// we return the outputstream so we cannot close it here
@SuppressWarnings("squid:S2095")
OutputStream outputStream = ByteStreams.nullOutputStream();
try {
outputStream = createOutputStreamForTempFile();
this.mimeType = mimeType;
publishUploadProgressEvent(fileUploadId, 0, 0, getTempFilePath());
} catch (final IOException e) {
LOG.error("Creating temp file for upload failed {}.", e);
if (outputStream != null) {
try {
outputStream.close();
} catch (final IOException e1) {
LOG.error("Closing output stream caused an exception {}", e1);
}
}
setFailureReasonUploadFailed();
setUploadInterrupted();
}
return outputStream;
}
/**
* Reports progress in {@link Upload} variant.
*
* @see com.vaadin.ui.Upload.ProgressListener#updateProgress(long, long)
*/
@Override
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);
setFailureReasonFileSizeExceeded(maxSize);
setUploadInterrupted();
return;
}
if (isUploadInterrupted()) {
// Upload interruption is delayed maybe another event is fired
// before
return;
}
publishUploadProgressEvent(fileUploadId, readBytes, contentLength, getTempFilePath());
}
/**
*
* Upload sucessfull for {@link Upload} variant.
*
* @see com.vaadin.ui.Upload.SucceededListener#uploadSucceeded(com.vaadin.ui.Upload.SucceededEvent)
*/
@Override
public void uploadSucceeded(final SucceededEvent event) {
if (isUploadInterrupted()) {
// Upload interruption is delayed maybe another event is fired
// before
return;
}
assertStateConsistency(fileUploadId, event.getFilename());
transferArtifactToRepository(fileUploadId, event.getLength(), mimeType, getTempFilePath());
}
/**
* Upload finished for {@link Upload} variant. Both for good and error
* variant.
*
* @see com.vaadin.ui.Upload.FinishedListener#uploadFinished(com.vaadin.ui.Upload.FinishedEvent)
*/
@Override
public void uploadFinished(final FinishedEvent event) {
// ignore this event
}
/**
* Upload failed for {@link Upload} variant.
*
* @see com.vaadin.ui.Upload.FailedListener#uploadFailed(com.vaadin.ui.Upload.FailedEvent)
*/
@Override
public void uploadFailed(final FailedEvent event) {
assertStateConsistency(fileUploadId, event.getFilename());
if (isDuplicateFile()) {
publishUploadFailedEvent(fileUploadId, getI18n().getMessage("message.no.duplicateFiles"),
event.getReason());
} else {
publishUploadFailedEvent(fileUploadId, event.getReason());
}
publishUploadFinishedEvent(fileUploadId);
}
}

View File

@@ -0,0 +1,120 @@
/**
* 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;
import java.io.Serializable;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
/**
* The {@link FileUploadId} identifies a file that is uploaded for a
* {@link SoftwareModule}.
*
*/
public class FileUploadId implements Serializable {
private static final long serialVersionUID = 1L;
private final String filename;
private final String softwareModuleName;
private final String softwareModuleVersion;
private Long softwareModuleId;
private final String id;
/**
* Creates a new {@link FileUploadId} instance.
*
* @param filename
* the name of the file
* @param softwareModule
* the {@link SoftwareModule} for which the file is uploaded
*/
public FileUploadId(final String filename, final SoftwareModule softwareModule) {
this.filename = filename;
this.softwareModuleName = softwareModule.getName();
this.softwareModuleVersion = softwareModule.getVersion();
this.softwareModuleId = softwareModule.getId();
this.id = createFileUploadIdString(filename, softwareModuleName, softwareModuleVersion);
}
/**
* Creates a new {@link FileUploadId} instance.
*
* @param filename
* the name of the file
* @param softwareModuleName
* the name of a {@link SoftwareModule} for which the file is
* uploaded
* @param softwareModuleVersion
* the version of a {@link SoftwareModule} for which the file is
* uploaded
*/
public FileUploadId(final String filename, final String softwareModuleName, final String softwareModuleVersion) {
this.filename = filename;
this.softwareModuleName = softwareModuleName;
this.softwareModuleVersion = softwareModuleVersion;
this.id = createFileUploadIdString(filename, softwareModuleName, softwareModuleVersion);
}
private static String createFileUploadIdString(final String filename, final String softwareModuleName,
final String softwareModuleVersion) {
return new StringBuilder(filename).append(":")
.append(HawkbitCommonUtil.getFormattedNameVersion(softwareModuleName, softwareModuleVersion))
.toString();
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final FileUploadId other = (FileUploadId) obj;
return new EqualsBuilder().append(id, other.id).isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder().append(id).toHashCode();
}
@Override
public String toString() {
return id;
}
public String getFilename() {
return filename;
}
public String getSoftwareModuleName() {
return softwareModuleName;
}
public String getSoftwareModuleVersion() {
return softwareModuleVersion;
}
public Long getSoftwareModuleId() {
return softwareModuleId;
}
}

View File

@@ -0,0 +1,144 @@
/**
* 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;
import java.io.Serializable;
/**
* Holds file and upload progress details.
*/
public class FileUploadProgress implements Serializable {
/**
* Status of a file upload.
*/
public enum FileUploadStatus {
/**
* An upload for a file has been started.
*/
UPLOAD_STARTED,
/**
* Progress changed for one file upload.
*/
UPLOAD_IN_PROGRESS,
/**
* Upload of one file failed.
*/
UPLOAD_FAILED,
/**
* One file upload succeeded.
*/
UPLOAD_SUCCESSFUL,
/**
* One file upload finished ()
*/
UPLOAD_FINISHED
}
private static final long serialVersionUID = 1L;
private final FileUploadId fileUploadId;
private long contentLength;
private long bytesRead;
private String failureReason;
private String filePath;
private final FileUploadStatus fileUploadStatus;
/**
* Creates a new {@link FileUploadProgress} instance.
*
* @param fileUploadId
* the {@link FileUploadId} to which this progress information
* belongs.
* @param fileUploadStatus
* the {@link FileUploadStatus} of this progress
*/
public FileUploadProgress(final FileUploadId fileUploadId, final FileUploadStatus fileUploadStatus) {
this.fileUploadId = fileUploadId;
this.fileUploadStatus = fileUploadStatus;
}
/**
* Creates a new {@link FileUploadProgress} instance.
*
* @param fileUploadId
* the {@link FileUploadId} to which this progress information
* belongs.
* @param fileUploadStatus
* the {@link FileUploadStatus} of this progress
* @param bytesRead
* number of bytes read
* @param contentLength
* size of the file in bytes
* @param filePath
* the path of the file
*/
FileUploadProgress(final FileUploadId fileUploadId, final FileUploadStatus fileUploadStatus,
final long bytesRead, final long contentLength,
final String filePath) {
this.fileUploadId = fileUploadId;
this.fileUploadStatus = fileUploadStatus;
this.contentLength = contentLength;
this.bytesRead = bytesRead;
this.filePath = filePath;
}
/**
* Creates a new {@link FileUploadProgress} instance.
*
* @param fileUploadId
* the {@link FileUploadId} to which this progress information
* belongs.
* @param fileUploadStatus
* the {@link FileUploadStatus} of this progress
* @param failureReason
* the reason of the failed upload
*/
FileUploadProgress(final FileUploadId fileUploadId, final FileUploadStatus fileUploadStatus,
final String failureReason) {
this.fileUploadId = fileUploadId;
this.fileUploadStatus = fileUploadStatus;
this.failureReason = failureReason;
}
public FileUploadId getFileUploadId() {
return fileUploadId;
}
public long getContentLength() {
return contentLength;
}
public long getBytesRead() {
return bytesRead;
}
public String getFailureReason() {
return failureReason;
}
public String getFilePath() {
return filePath;
}
public FileUploadStatus getFileUploadStatus() {
return fileUploadStatus;
}
}

View File

@@ -1,687 +0,0 @@
/**
* 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;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.eclipse.hawkbit.repository.ArtifactManagement;
import org.eclipse.hawkbit.repository.exception.ArtifactUploadFailedException;
import org.eclipse.hawkbit.repository.exception.InvalidMD5HashException;
import org.eclipse.hawkbit.repository.exception.InvalidSHA1HashException;
import org.eclipse.hawkbit.repository.exception.QuotaExceededException;
import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
import org.eclipse.hawkbit.ui.artifacts.state.CustomFile;
import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleTiny;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
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.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.vaadin.spring.events.EventBus.UIEventBus;
import com.vaadin.data.Item;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.event.FieldEvents.TextChangeEvent;
import com.vaadin.server.FontAwesome;
import com.vaadin.server.Page;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
import com.vaadin.ui.themes.ValoTheme;
/**
* Artifact upload confirmation popup.
*
*/
public class UploadConfirmationWindow implements Button.ClickListener {
private static final long serialVersionUID = 1L;
private static final Logger LOG = LoggerFactory.getLogger(UploadConfirmationWindow.class);
private static final String MD5_CHECKSUM = "md5Checksum";
private static final String SHA1_CHECKSUM = "sha1Checksum";
private static final String FILE_NAME = "fileName";
private static final String SW_MODULE_NAME = "swModuleName";
private static final String SIZE = "size";
private static final String ACTION = "action";
private static final String BASE_SOFTWARE_ID = "softwareModuleId";
private static final String FILE_NAME_LAYOUT = "fileNameLayout";
private static final String WARNING_ICON = "warningIcon";
private static final String CUSTOM_FILE = "customFile";
private static final String ARTIFACT_UPLOAD_EXCEPTION = "Artifact upload exception:";
private static final String ALREADY_EXISTS_MSG = "upload.artifact.alreadyExists";
private final VaadinMessageSource i18n;
private Window window;
private Button uploadBtn;
private Button cancelBtn;
private Table uploadDetailsTable;
private final UploadLayout uploadLayout;
private IndexedContainer tableContainer;
private final List<UploadStatus> uploadResultList = new ArrayList<>();
private VerticalLayout uploadArtifactDetails;
private UploadResultWindow currentUploadResultWindow;
private int redErrorLabelCount;
private final ArtifactUploadState artifactUploadState;
private final transient UIEventBus eventBus;
private final transient ArtifactManagement artifactManagement;
/**
* Initialize the upload confirmation window.
*
* @param artifactUploadView
* reference of upload layout.
* @param artifactUploadState
* reference of session variable {@link ArtifactUploadState}.
*/
UploadConfirmationWindow(final UploadLayout artifactUploadView, final ArtifactUploadState artifactUploadState,
final UIEventBus eventBus, final ArtifactManagement artifactManagement) {
this.uploadLayout = artifactUploadView;
this.artifactUploadState = artifactUploadState;
this.eventBus = eventBus;
this.artifactManagement = artifactManagement;
i18n = artifactUploadView.getI18n();
createRequiredComponents();
buildLayout();
}
private boolean checkIfArtifactDetailsDisplayed(final Long bSoftwareModuleId) {
return artifactUploadState.getSelectedBaseSwModuleId().map(moduleId -> moduleId.equals(bSoftwareModuleId))
.orElse(false);
}
private Boolean preUploadValidation(final List<String> itemIds) {
Boolean validationSuccess = true;
for (final String itemId : itemIds) {
final Item item = tableContainer.getItem(itemId);
final String providedFileName = (String) item.getItemProperty(FILE_NAME).getValue();
if (!StringUtils.hasText(providedFileName)) {
validationSuccess = false;
break;
}
}
return validationSuccess;
}
private void createRequiredComponents() {
uploadBtn = SPUIComponentProvider.getButton(UIComponentIdProvider.UPLOAD_BUTTON, SPUILabelDefinitions.SUBMIT,
SPUILabelDefinitions.SUBMIT, ValoTheme.BUTTON_PRIMARY, false, null, SPUIButtonStyleTiny.class);
uploadBtn.addClickListener(this);
cancelBtn = SPUIComponentProvider.getButton(UIComponentIdProvider.UPLOAD_DISCARD_DETAILS_BUTTON,
SPUILabelDefinitions.DISCARD, SPUILabelDefinitions.DISCARD, null, false, null,
SPUIButtonStyleTiny.class);
cancelBtn.addClickListener(this);
uploadDetailsTable = new Table();
uploadDetailsTable.addStyleName("artifact-table");
uploadDetailsTable.setSizeFull();
uploadDetailsTable.setId(UIComponentIdProvider.UPLOAD_ARTIFACT_DETAILS_TABLE);
uploadDetailsTable.addStyleName(ValoTheme.TABLE_BORDERLESS);
uploadDetailsTable.addStyleName(ValoTheme.TABLE_NO_VERTICAL_LINES);
uploadDetailsTable.addStyleName(ValoTheme.TABLE_SMALL);
setTableContainer();
populateUploadDetailsTable();
}
/**
* Warning icon is displayed, if an artifact exists with same provided file
* name. Error icon is displayed, if file name entered is duplicate.
*
* @param warningIconLabel
* warning/error label
* @param fileName
* provided file name
* @param itemId
* item id of the current row
*/
private void setWarningIcon(final Label warningIconLabel, final String fileName, final Object itemId) {
final Item item = uploadDetailsTable.getItem(itemId);
if (StringUtils.hasText(fileName)) {
final String fileNameTrimmed = StringUtils.trimWhitespace(fileName);
final Long baseSwId = (Long) item.getItemProperty(BASE_SOFTWARE_ID).getValue();
final Optional<Artifact> artifact = artifactManagement.getByFilenameAndSoftwareModule(fileNameTrimmed,
baseSwId);
if (artifact.isPresent()) {
warningIconLabel.setVisible(true);
if (isErrorIcon(warningIconLabel)) {
warningIconLabel.removeStyleName(SPUIStyleDefinitions.ERROR_LABEL);
redErrorLabelCount--;
}
warningIconLabel.setDescription(i18n.getMessage(ALREADY_EXISTS_MSG));
if (checkForDuplicate(fileNameTrimmed, itemId, baseSwId)) {
warningIconLabel.setDescription(i18n.getMessage("message.duplicate.filename"));
warningIconLabel.addStyleName(SPUIStyleDefinitions.ERROR_LABEL);
redErrorLabelCount++;
}
} else {
warningIconLabel.setVisible(false);
if (warningIconLabel.getStyleName().contains(SPUIStyleDefinitions.ERROR_LABEL)) {
warningIconLabel.removeStyleName(SPUIStyleDefinitions.ERROR_LABEL);
warningIconLabel.setDescription(i18n.getMessage(ALREADY_EXISTS_MSG));
redErrorLabelCount--;
}
}
}
}
private Boolean checkForDuplicate(final String fileName, final Object itemId, final Long currentBaseSwId) {
for (final Object newItemId : tableContainer.getItemIds()) {
final Item newItem = tableContainer.getItem(newItemId);
final Long newBaseSwId = (Long) newItem.getItemProperty(BASE_SOFTWARE_ID).getValue();
final String newFileName = (String) newItem.getItemProperty(FILE_NAME).getValue();
if (!newItemId.equals(itemId) && newBaseSwId.equals(currentBaseSwId) && newFileName.equals(fileName)) {
return true;
}
}
return false;
}
private void populateUploadDetailsTable() {
for (final CustomFile customFile : uploadLayout.getFileSelected()) {
final String swNameVersion = HawkbitCommonUtil.getFormattedNameVersion(
customFile.getBaseSoftwareModuleName(), customFile.getBaseSoftwareModuleVersion());
final String itemId = swNameVersion + "/" + customFile.getFileName();
final Item newItem = tableContainer.addItem(itemId);
final SoftwareModule bSoftwareModule = artifactUploadState.getBaseSwModuleList().get(swNameVersion);
newItem.getItemProperty(BASE_SOFTWARE_ID).setValue(bSoftwareModule.getId());
addFileNameLayout(newItem, swNameVersion, customFile.getFileName(), itemId);
newItem.getItemProperty(SW_MODULE_NAME).setValue(HawkbitCommonUtil.getFormatedLabel(swNameVersion));
newItem.getItemProperty(SIZE).setValue(customFile.getFileSize());
final Button deleteIcon = SPUIComponentProvider.getButton(
UIComponentIdProvider.UPLOAD_DELETE_ICON + "-" + itemId, "", SPUILabelDefinitions.DISCARD,
ValoTheme.BUTTON_TINY + " " + "blueicon", true, FontAwesome.TRASH_O,
SPUIButtonStyleSmallNoBorder.class);
deleteIcon.addClickListener(this);
deleteIcon.setData(itemId);
newItem.getItemProperty(ACTION).setValue(deleteIcon);
final TextField sha1 = createTextField(swNameVersion + "/" + customFile.getFileName() + "/sha1");
final TextField md5 = createTextField(swNameVersion + "/" + customFile.getFileName() + "/md5");
createTextField(swNameVersion + "/" + customFile.getFileName() + "/customFileName");
newItem.getItemProperty(SHA1_CHECKSUM).setValue(sha1);
newItem.getItemProperty(MD5_CHECKSUM).setValue(md5);
newItem.getItemProperty(CUSTOM_FILE).setValue(customFile);
}
}
private static TextField createTextField(final String id) {
return new TextFieldBuilder(64).id(id).buildTextComponent();
}
private void addFileNameLayout(final Item newItem, final String baseSoftwareModuleNameVersion,
final String customFileName, final String itemId) {
final HorizontalLayout horizontalLayout = new HorizontalLayout();
final TextField fileNameTextField = createTextField(
baseSoftwareModuleNameVersion + "/" + customFileName + "/customFileName");
fileNameTextField.setData(baseSoftwareModuleNameVersion + "/" + customFileName);
fileNameTextField.setValue(customFileName);
newItem.getItemProperty(FILE_NAME).setValue(fileNameTextField.getValue());
final Label warningIconLabel = getWarningLabel();
warningIconLabel.setId(baseSoftwareModuleNameVersion + "/" + customFileName + "/icon");
setWarningIcon(warningIconLabel, fileNameTextField.getValue(), itemId);
newItem.getItemProperty(WARNING_ICON).setValue(warningIconLabel);
horizontalLayout.addComponent(fileNameTextField);
horizontalLayout.setComponentAlignment(fileNameTextField, Alignment.MIDDLE_LEFT);
horizontalLayout.addComponent(warningIconLabel);
horizontalLayout.setComponentAlignment(warningIconLabel, Alignment.MIDDLE_RIGHT);
newItem.getItemProperty(FILE_NAME_LAYOUT).setValue(horizontalLayout);
fileNameTextField.addTextChangeListener(event -> onFileNameChange(event, warningIconLabel, newItem));
}
private void onFileNameChange(final TextChangeEvent event, final Label warningIconLabel, final Item newItem) {
final String itemId = (String) ((TextField) event.getComponent()).getData();
final String fileName = event.getText();
final Boolean isWarningIconDisplayed = isWarningIcon(warningIconLabel);
setWarningIcon(warningIconLabel, fileName, itemId);
final Long currentSwId = (Long) newItem.getItemProperty(BASE_SOFTWARE_ID).getValue();
final String oldFileName = (String) newItem.getItemProperty(FILE_NAME).getValue();
newItem.getItemProperty(FILE_NAME).setValue(event.getText());
// if warning was displayed prior and not displayed currently
if (isWarningIconDisplayed && !warningIconLabel.isVisible()) {
modifyIconOfSameSwId(itemId, currentSwId, oldFileName);
}
checkDuplicateEntry(itemId, currentSwId, event.getText(), oldFileName);
enableOrDisableUploadBtn();
}
private void enableOrDisableUploadBtn() {
if (redErrorLabelCount == 0) {
uploadBtn.setEnabled(true);
} else {
uploadBtn.setEnabled(false);
}
}
/**
* If warning was displayed prior and not displayed currently ,the update
* other warning labels accordingly.
*
* @param itemId
* id of row which is deleted/whose file name modified.
* @param oldSwId
* software module id
* @param oldFileName
* file name before modification
*/
private void modifyIconOfSameSwId(final Object itemId, final Long oldSwId, final String oldFileName) {
for (final Object rowId : tableContainer.getItemIds()) {
final Item newItem = tableContainer.getItem(rowId);
final Long newBaseSwId = (Long) newItem.getItemProperty(BASE_SOFTWARE_ID).getValue();
final String newFileName = (String) newItem.getItemProperty(FILE_NAME).getValue();
if (!rowId.equals(itemId) && newBaseSwId.equals(oldSwId) && newFileName.equals(oldFileName)) {
final HorizontalLayout layout = (HorizontalLayout) newItem.getItemProperty(FILE_NAME_LAYOUT).getValue();
final Label warningLabel = (Label) layout.getComponent(1);
if (warningLabel.isVisible()) {
warningLabel.removeStyleName(SPUIStyleDefinitions.ERROR_LABEL);
warningLabel.setDescription(i18n.getMessage(ALREADY_EXISTS_MSG));
newItem.getItemProperty(WARNING_ICON).setValue(warningLabel);
redErrorLabelCount--;
break;
}
}
}
}
/**
* Check if icon is warning icon and visible.
*
* @param icon
* label
* @return Boolean
*/
private static boolean isWarningIcon(final Label icon) {
return !isErrorIcon(icon);
}
/**
* Check if icon is error icon and visible.
*
* @param icon
* label
* @return Boolean
*/
private static boolean isErrorIcon(final Label icon) {
return icon.isVisible() && icon.getStyleName().contains(SPUIStyleDefinitions.ERROR_LABEL);
}
private static Label getWarningLabel() {
final Label warningIconLabel = new Label();
warningIconLabel.addStyleName(ValoTheme.LABEL_SMALL);
warningIconLabel.setHeightUndefined();
warningIconLabel.setContentMode(ContentMode.HTML);
warningIconLabel.setValue(FontAwesome.WARNING.getHtml());
warningIconLabel.addStyleName("warningLabel");
warningIconLabel.setVisible(false);
return warningIconLabel;
}
private void newFileNameIsDuplicate(final Object itemId, final Long currentSwId, final String currentChangedText) {
for (final Object rowId : tableContainer.getItemIds()) {
final Item currentItem = tableContainer.getItem(itemId);
final Item newItem = tableContainer.getItem(rowId);
final Long newBaseSwId = (Long) newItem.getItemProperty(BASE_SOFTWARE_ID).getValue();
final String fileName = (String) newItem.getItemProperty(FILE_NAME).getValue();
if (!rowId.equals(itemId) && newBaseSwId.equals(currentSwId) && fileName.equals(currentChangedText)) {
final HorizontalLayout layout = (HorizontalLayout) currentItem.getItemProperty(FILE_NAME_LAYOUT)
.getValue();
final Label iconLabel = (Label) layout.getComponent(1);
if (!iconLabel.getStyleName().contains(SPUIStyleDefinitions.ERROR_LABEL)) {
iconLabel.setVisible(true);
iconLabel.setDescription(i18n.getMessage("message.duplicate.filename"));
iconLabel.addStyleName(SPUIStyleDefinitions.ERROR_LABEL);
redErrorLabelCount++;
}
break;
}
}
}
private void reValidateOtherFileNamesOfSameBaseSw(final Object itemId, final Long currentSwId,
final String oldFileName) {
Label warningLabel = null;
Label errorLabel = null;
int errorLabelCount = 0;
int duplicateCount = 0;
for (final Object rowId : tableContainer.getItemIds()) {
final Item newItem = tableContainer.getItem(rowId);
final Long newBaseSwId = (Long) newItem.getItemProperty(BASE_SOFTWARE_ID).getValue();
final String newFileName = (String) newItem.getItemProperty(FILE_NAME).getValue();
if (!rowId.equals(itemId) && newBaseSwId.equals(currentSwId) && newFileName.equals(oldFileName)) {
final HorizontalLayout layout = (HorizontalLayout) newItem.getItemProperty(FILE_NAME_LAYOUT).getValue();
final Label icon = (Label) layout.getComponent(1);
duplicateCount++;
if (icon.isVisible()) {
if (!icon.getStyleName().contains(SPUIStyleDefinitions.ERROR_LABEL)) {
warningLabel = icon;
break;
}
errorLabel = icon;
errorLabelCount++;
}
}
}
hideErrorIcon(warningLabel, errorLabelCount, duplicateCount, errorLabel, oldFileName, currentSwId);
}
private void hideErrorIcon(final Label warningLabel, final int errorLabelCount, final int duplicateCount,
final Label errorLabel, final String oldFileName, final Long currentSwId) {
if (warningLabel == null && (errorLabelCount > 1 || (duplicateCount == 1 && errorLabelCount == 1))) {
final Optional<Artifact> artifactList = artifactManagement.getByFilenameAndSoftwareModule(oldFileName,
currentSwId);
if (errorLabel == null) {
return;
}
errorLabel.removeStyleName(SPUIStyleDefinitions.ERROR_LABEL);
errorLabel.setDescription(i18n.getMessage(ALREADY_EXISTS_MSG));
if (!artifactList.isPresent()) {
errorLabel.setVisible(false);
}
redErrorLabelCount--;
}
}
private void checkDuplicateEntry(final Object itemId, final Long currentSwId, final String newChangedText,
final String oldFileName) {
/**
* Check if newly entered file name is a duplicate.
*/
newFileNameIsDuplicate(itemId, currentSwId, newChangedText);
/**
* After the current changed file name is validated ,other files of same
* software module as has be revalidated. And icons are updated
* accordingly.
*/
reValidateOtherFileNamesOfSameBaseSw(itemId, currentSwId, oldFileName);
}
private void setTableContainer() {
tableContainer = new IndexedContainer();
tableContainer.addContainerProperty(FILE_NAME_LAYOUT, HorizontalLayout.class, null);
tableContainer.addContainerProperty(SW_MODULE_NAME, Label.class, null);
tableContainer.addContainerProperty(SHA1_CHECKSUM, TextField.class, null);
tableContainer.addContainerProperty(MD5_CHECKSUM, TextField.class, null);
tableContainer.addContainerProperty(SIZE, Long.class, null);
tableContainer.addContainerProperty(ACTION, Button.class, "");
tableContainer.addContainerProperty(FILE_NAME, String.class, null);
tableContainer.addContainerProperty(BASE_SOFTWARE_ID, Long.class, null);
tableContainer.addContainerProperty(WARNING_ICON, Label.class, null);
tableContainer.addContainerProperty(CUSTOM_FILE, CustomFile.class, null);
uploadDetailsTable.setContainerDataSource(tableContainer);
uploadDetailsTable.setPageLength(10);
uploadDetailsTable.setColumnHeader(FILE_NAME_LAYOUT, i18n.getMessage("upload.file.name"));
uploadDetailsTable.setColumnHeader(SW_MODULE_NAME, i18n.getMessage("upload.swModuleTable.header"));
uploadDetailsTable.setColumnHeader(SHA1_CHECKSUM, i18n.getMessage("upload.sha1"));
uploadDetailsTable.setColumnHeader(MD5_CHECKSUM, i18n.getMessage("upload.md5"));
uploadDetailsTable.setColumnHeader(SIZE, i18n.getMessage("upload.size"));
uploadDetailsTable.setColumnHeader(ACTION, i18n.getMessage("upload.action"));
uploadDetailsTable.setColumnExpandRatio(FILE_NAME_LAYOUT, 0.25F);
uploadDetailsTable.setColumnExpandRatio(SW_MODULE_NAME, 0.17F);
uploadDetailsTable.setColumnExpandRatio(SHA1_CHECKSUM, 0.2F);
uploadDetailsTable.setColumnExpandRatio(MD5_CHECKSUM, 0.2F);
uploadDetailsTable.setColumnExpandRatio(SIZE, 0.12F);
uploadDetailsTable.setColumnExpandRatio(ACTION, 0.06F);
final Object[] visibileColumn = { FILE_NAME_LAYOUT, SW_MODULE_NAME, SHA1_CHECKSUM, MD5_CHECKSUM, SIZE, ACTION };
uploadDetailsTable.setVisibleColumns(visibileColumn);
}
private void buildLayout() {
final HorizontalLayout footer = getFooterLayout();
uploadArtifactDetails = new VerticalLayout();
uploadArtifactDetails.setWidth(SPUIDefinitions.MIN_UPLOAD_CONFIRMATION_POPUP_WIDTH + "px");
uploadArtifactDetails.addStyleName("confirmation-popup");
uploadArtifactDetails.addComponent(uploadDetailsTable);
uploadArtifactDetails.setComponentAlignment(uploadDetailsTable, Alignment.MIDDLE_CENTER);
uploadArtifactDetails.addComponent(footer);
uploadArtifactDetails.setComponentAlignment(footer, Alignment.MIDDLE_CENTER);
window = new Window();
window.setContent(uploadArtifactDetails);
window.setResizable(Boolean.FALSE);
window.setClosable(Boolean.TRUE);
window.setDraggable(Boolean.TRUE);
window.setModal(true);
window.addCloseListener(event -> onPopupClose());
window.setCaption(i18n.getMessage("header.caption.upload.details"));
window.addStyleName(SPUIStyleDefinitions.CONFIRMATION_WINDOW_CAPTION);
}
private void onPopupClose() {
uploadLayout.setCurrentUploadConfirmationwindow(null);
}
private HorizontalLayout getFooterLayout() {
final HorizontalLayout footer = new HorizontalLayout();
footer.setSizeUndefined();
footer.addStyleName("confirmation-window-footer");
footer.setSpacing(true);
footer.setMargin(false);
footer.addComponents(uploadBtn, cancelBtn);
footer.setComponentAlignment(uploadBtn, Alignment.TOP_LEFT);
footer.setComponentAlignment(cancelBtn, Alignment.TOP_RIGHT);
return footer;
}
public Window getUploadConfirmationWindow() {
return window;
}
@Override
public void buttonClick(final ClickEvent event) {
if (event.getComponent().getId().equals(UIComponentIdProvider.UPLOAD_ARTIFACT_DETAILS_CLOSE)) {
window.close();
} else if (event.getComponent().getId().equals(UIComponentIdProvider.UPLOAD_DISCARD_DETAILS_BUTTON)) {
uploadLayout.clearUploadedFileDetails();
window.close();
} else if (event.getComponent().getId().equals(UIComponentIdProvider.UPLOAD_BUTTON)) {
processArtifactUpload();
} else if (event.getComponent().getId().startsWith(UIComponentIdProvider.UPLOAD_DELETE_ICON)) {
final String itemId = ((Button) event.getComponent()).getData().toString();
final Item item = uploadDetailsTable.getItem(((Button) event.getComponent()).getData());
final Long swId = (Long) item.getItemProperty(BASE_SOFTWARE_ID).getValue();
final CustomFile customFile = (CustomFile) item.getItemProperty(CUSTOM_FILE).getValue();
final String fileName = (String) item.getItemProperty(FILE_NAME).getValue();
final Label warningIconLabel = (Label) item.getItemProperty(WARNING_ICON).getValue();
final Boolean isWarningIconDisplayed = isWarningIcon(warningIconLabel);
if (isWarningIconDisplayed) {
modifyIconOfSameSwId(itemId, swId, fileName);
} else if (isErrorIcon(warningIconLabel)) {
redErrorLabelCount--;
}
reValidateOtherFileNamesOfSameBaseSw(((Button) event.getComponent()).getData(), swId, fileName);
enableOrDisableUploadBtn();
uploadDetailsTable.removeItem(((Button) event.getComponent()).getData());
uploadLayout.getFileSelected().remove(customFile);
uploadLayout.updateUploadCounts();
if (uploadDetailsTable.getItemIds().isEmpty()) {
window.close();
uploadLayout.clearUploadedFileDetails();
}
}
}
// Exception squid:S3655 - Optional access is checked in
// checkIfArtifactDetailsDispalyed subroutine
@SuppressWarnings("squid:S3655")
private void processArtifactUpload() {
final List<String> itemIds = (List<String>) uploadDetailsTable.getItemIds();
if (preUploadValidation(itemIds)) {
Boolean refreshArtifactDetailsLayout = false;
for (final String itemId : itemIds) {
final String[] itemDet = itemId.split("/");
final String baseSoftwareModuleNameVersion = itemDet[0];
final String fileName = itemDet[1];
final SoftwareModule bSoftwareModule = artifactUploadState.getBaseSwModuleList()
.get(baseSoftwareModuleNameVersion);
for (final CustomFile customFile : uploadLayout.getFileSelected()) {
final String baseSwModuleNameVersion = HawkbitCommonUtil.getFormattedNameVersion(
customFile.getBaseSoftwareModuleName(), customFile.getBaseSoftwareModuleVersion());
if (customFile.getFileName().equals(fileName)
&& baseSwModuleNameVersion.equals(baseSoftwareModuleNameVersion)) {
createArtifact(itemId, customFile.getFilePath(), customFile.getFileSize(), artifactManagement,
bSoftwareModule);
}
}
refreshArtifactDetailsLayout = checkIfArtifactDetailsDisplayed(bSoftwareModule.getId());
}
if (refreshArtifactDetailsLayout) {
uploadLayout.refreshArtifactDetailsLayout(artifactUploadState.getSelectedBaseSwModuleId().get());
}
uploadLayout.clearFileList();
window.close();
// call upload result window
currentUploadResultWindow = new UploadResultWindow(uploadResultList, i18n, eventBus);
UI.getCurrent().addWindow(currentUploadResultWindow.getUploadResultsWindow());
currentUploadResultWindow.getUploadResultsWindow().addCloseListener(event -> onResultDetailsPopupClose());
uploadLayout.setResultPopupHeightWidth(Page.getCurrent().getBrowserWindowWidth(),
Page.getCurrent().getBrowserWindowHeight());
} else {
uploadLayout.getUINotification()
.displayValidationError(uploadLayout.getI18n().getMessage("message.error.noProvidedName"));
}
}
private void onResultDetailsPopupClose() {
currentUploadResultWindow = null;
}
private void createArtifact(final String itemId, final String filePath, final long fileSize,
final ArtifactManagement artifactManagement, final SoftwareModule baseSw) {
final File newFile = new File(filePath);
final Item item = tableContainer.getItem(itemId);
// We have to make sure that null is assigned to sha1Checksum and
// md5Checksum if no alphanumeric value is provided. Empty String will
// fail
final String sha1Checksum = HawkbitCommonUtil
.trimAndNullIfEmpty(((TextField) item.getItemProperty(SHA1_CHECKSUM).getValue()).getValue());
final String md5Checksum = HawkbitCommonUtil
.trimAndNullIfEmpty(((TextField) item.getItemProperty(MD5_CHECKSUM).getValue()).getValue());
final String providedFileName = (String) item.getItemProperty(FILE_NAME).getValue();
final CustomFile customFile = (CustomFile) item.getItemProperty(CUSTOM_FILE).getValue();
final String[] itemDet = itemId.split("/");
final String swModuleNameVersion = itemDet[0];
try (FileInputStream fis = new FileInputStream(newFile)) {
artifactManagement.create(fis, baseSw.getId(), providedFileName, md5Checksum, sha1Checksum, true,
customFile.getMimeType(), fileSize);
saveUploadStatus(providedFileName, swModuleNameVersion, SPUILabelDefinitions.SUCCESS, "");
} catch (final ArtifactUploadFailedException | InvalidSHA1HashException | InvalidMD5HashException
| FileNotFoundException | QuotaExceededException e) {
saveUploadStatus(providedFileName, swModuleNameVersion, SPUILabelDefinitions.FAILED, e.getMessage());
LOG.error(ARTIFACT_UPLOAD_EXCEPTION, e);
} catch (final IOException ex) {
LOG.error(ARTIFACT_UPLOAD_EXCEPTION, ex);
} finally {
if (newFile.exists() && !newFile.delete()) {
LOG.error("Could not delete temporary file: {}", newFile);
}
}
}
private void saveUploadStatus(final String fileName, final String baseSwModuleName, final String status,
final String message) {
final UploadStatus result = new UploadStatus();
result.setFileName(fileName);
result.setBaseSwModuleName(baseSwModuleName);
result.setUploadResult(status);
result.setReason(message);
uploadResultList.add(result);
}
public Table getUploadDetailsTable() {
return uploadDetailsTable;
}
public VerticalLayout getUploadArtifactDetails() {
return uploadArtifactDetails;
}
public UploadResultWindow getCurrentUploadResultWindow() {
return currentUploadResultWindow;
}
public void setCurrentUploadResultWindow(final UploadResultWindow currentUploadResultWindow) {
this.currentUploadResultWindow = currentUploadResultWindow;
}
}

View File

@@ -0,0 +1,244 @@
/**
* 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;
import javax.servlet.MultipartConfigElement;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.hawkbit.repository.ArtifactManagement;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent;
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.dd.criteria.ServerItemIdClientCriterion;
import org.eclipse.hawkbit.ui.dd.criteria.ServerItemIdClientCriterion.Mode;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.spring.events.EventBus;
import org.vaadin.spring.events.EventBus.UIEventBus;
import org.vaadin.spring.events.EventScope;
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
import com.vaadin.event.dd.acceptcriteria.Not;
import com.vaadin.server.FontAwesome;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.DragAndDropWrapper;
import com.vaadin.ui.DragAndDropWrapper.WrapperTransferable;
import com.vaadin.ui.Html5File;
import com.vaadin.ui.Label;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
/**
* Container for drag and drop area in the upload view.
*/
public class UploadDropAreaLayout extends AbstractComponent {
private static final long serialVersionUID = 1L;
private static AcceptCriterion acceptAllExceptBlacklisted = new Not(new ServerItemIdClientCriterion(Mode.PREFIX,
UIComponentIdProvider.UPLOAD_SOFTWARE_MODULE_TABLE, UIComponentIdProvider.UPLOAD_TYPE_BUTTON_PREFIX));
private DragAndDropWrapper dropAreaWrapper;
private final VaadinMessageSource i18n;
private final UINotification uiNotification;
private final ArtifactUploadState artifactUploadState;
private final transient MultipartConfigElement multipartConfigElement;
private final transient SoftwareModuleManagement softwareManagement;
private final transient ArtifactManagement artifactManagement;
private final UploadProgressButtonLayout uploadButtonLayout;
/**
* Creates a new {@link UploadDropAreaLayout} instance.
*
* @param i18n
* the {@link VaadinMessageSource}
* @param eventBus
* the {@link EventBus} used to send/retrieve events
* @param uiNotification
* {@link UINotification} for showing notifications
* @param artifactUploadState
* the {@link ArtifactUploadState} for state information
* @param multipartConfigElement
* the {@link MultipartConfigElement}
* @param softwareManagement
* the {@link SoftwareModuleManagement} for retrieving the
* {@link SoftwareModule}
* @param artifactManagement
* the {@link ArtifactManagement} for storing the uploaded
* artifacts
*/
public UploadDropAreaLayout(final VaadinMessageSource i18n, final UIEventBus eventBus,
final UINotification uiNotification, final ArtifactUploadState artifactUploadState,
final MultipartConfigElement multipartConfigElement, final SoftwareModuleManagement softwareManagement,
final ArtifactManagement artifactManagement) {
this.i18n = i18n;
this.uiNotification = uiNotification;
this.artifactUploadState = artifactUploadState;
this.multipartConfigElement = multipartConfigElement;
this.softwareManagement = softwareManagement;
this.artifactManagement = artifactManagement;
this.uploadButtonLayout = new UploadProgressButtonLayout(i18n, eventBus, artifactUploadState,
multipartConfigElement, artifactManagement, softwareManagement);
buildLayout();
eventBus.subscribe(this);
}
@EventBusListenerMethod(scope = EventScope.UI)
void onEvent(final SoftwareModuleEvent event) {
final BaseEntityEventType eventType = event.getEventType();
if (eventType == BaseEntityEventType.SELECTED_ENTITY) {
UI.getCurrent().access(() -> {
if (artifactUploadState.isNoSoftwareModuleSelected()
|| artifactUploadState.isMoreThanOneSoftwareModulesSelected()) {
dropAreaWrapper.setEnabled(false);
} else if (artifactUploadState.areAllUploadsFinished()) {
dropAreaWrapper.setEnabled(true);
}
});
}
}
private void buildLayout() {
dropAreaWrapper = new DragAndDropWrapper(createDropAreaLayout());
dropAreaWrapper.setDropHandler(new DropAreaHandler());
}
private VerticalLayout createDropAreaLayout() {
final VerticalLayout dropAreaLayout = new VerticalLayout();
final Label dropHereLabel = new Label("Drop Files to upload");
dropHereLabel.setWidth(null);
final Label dropIcon = new Label(FontAwesome.ARROW_DOWN.getHtml(), ContentMode.HTML);
dropIcon.addStyleName("drop-icon");
dropIcon.setWidth(null);
dropAreaLayout.addComponent(dropIcon);
dropAreaLayout.setComponentAlignment(dropIcon, Alignment.TOP_CENTER);
dropAreaLayout.addComponent(dropHereLabel);
dropAreaLayout.setComponentAlignment(dropHereLabel, Alignment.TOP_CENTER);
uploadButtonLayout.setWidth(null);
uploadButtonLayout.addStyleName("upload-button");
dropAreaLayout.addComponent(uploadButtonLayout);
dropAreaLayout.setComponentAlignment(uploadButtonLayout, Alignment.BOTTOM_CENTER);
dropAreaLayout.setSizeFull();
dropAreaLayout.setStyleName("upload-drop-area-layout-info");
dropAreaLayout.setSpacing(false);
return dropAreaLayout;
}
public DragAndDropWrapper getDropAreaWrapper() {
return dropAreaWrapper;
}
private class DropAreaHandler implements DropHandler {
private static final long serialVersionUID = 1L;
@Override
public AcceptCriterion getAcceptCriterion() {
return acceptAllExceptBlacklisted;
}
@Override
public void drop(final DragAndDropEvent event) {
if (validate(event)) {
final Html5File[] files = ((WrapperTransferable) event.getTransferable()).getFiles();
// selected software module at the time of file drop is
// considered for upload
artifactUploadState.getSelectedBaseSwModuleId()
.ifPresent(selectedSwId -> uploadFilesForSoftwareModule(files, selectedSwId));
}
}
private void uploadFilesForSoftwareModule(final Html5File[] files, final Long softwareModuleId) {
final SoftwareModule softwareModule = softwareManagement.get(softwareModuleId).orElse(null);
boolean isDirectory = false;
boolean isDuplicate = false;
for (final Html5File file : files) {
isDirectory = isDirectory(file);
isDuplicate = artifactUploadState.isFileInUploadState(file.getFileName(), softwareModule);
if (!isDirectory && !isDuplicate) {
file.setStreamVariable(new FileTransferHandlerStreamVariable(file.getFileName(), file.getFileSize(),
multipartConfigElement.getMaxFileSize(), file.getType(), softwareModule, artifactManagement,
i18n));
}
}
if (isDirectory && isDuplicate) {
uiNotification.displayValidationError(i18n.getMessage("message.no.duplicateFiles") + "<br>"
+ i18n.getMessage("message.no.directory.upload"));
} else if (isDirectory) {
uiNotification.displayValidationError(i18n.getMessage("message.no.directory.upload"));
} else if (isDuplicate) {
uiNotification.displayValidationError(i18n.getMessage("message.no.duplicateFiles"));
}
}
private boolean isDirectory(final Html5File file) {
return StringUtils.isBlank(file.getType()) && file.getFileSize() % 4096 == 0;
}
private boolean validate(final DragAndDropEvent event) {
// check if drop is valid.If valid ,check if software module is
// selected.
if (!isFilesDropped(event)) {
uiNotification.displayValidationError(i18n.getMessage("message.action.not.allowed"));
return false;
}
return validateSoftwareModuleSelection();
}
private boolean isFilesDropped(final DragAndDropEvent event) {
if (event.getTransferable() instanceof WrapperTransferable) {
final Html5File[] files = ((WrapperTransferable) event.getTransferable()).getFiles();
return files != null;
}
return false;
}
private boolean validateSoftwareModuleSelection() {
if (artifactUploadState.isNoSoftwareModuleSelected()) {
uiNotification.displayValidationError(i18n.getMessage("message.error.noSwModuleSelected"));
return false;
}
if (artifactUploadState.isMoreThanOneSoftwareModulesSelected()) {
uiNotification.displayValidationError(i18n.getMessage("message.error.multiSwModuleSelected"));
return false;
}
return true;
}
}
public UploadProgressButtonLayout getUploadButtonLayout() {
return uploadButtonLayout;
}
}

View File

@@ -0,0 +1,87 @@
/**
* 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;
import java.io.OutputStream;
import com.vaadin.server.StreamVariable;
import com.vaadin.ui.Upload;
/**
* The {@link Upload} class has a bug.The lifecycle methods of the registered
* handler
* com.vaadin.ui.Upload.StartedListener#uploadStarted(com.vaadin.ui.Upload.StartedEvent)
* etc are called even the upload was interrupted. This bug is fixed in this
* class.
*
*/
public class UploadFixed extends Upload {
private static final long serialVersionUID = 1L;
private boolean uploadInterrupted;
@Override
public void interruptUpload() {
super.interruptUpload();
uploadInterrupted = true;
}
@Override
protected StreamVariable getStreamVariable() {
return new StreamVariableFixed(super.getStreamVariable());
}
private class StreamVariableFixed implements StreamVariable {
private static final long serialVersionUID = 1L;
private final StreamVariable originalStreamVariable;
public StreamVariableFixed(final StreamVariable originalStreamVariable) {
this.originalStreamVariable = originalStreamVariable;
}
@Override
public boolean listenProgress() {
// this fixes the vaadin bug
return originalStreamVariable.listenProgress() && !uploadInterrupted;
}
@Override
public void onProgress(final StreamingProgressEvent event) {
originalStreamVariable.onProgress(event);
}
@Override
public boolean isInterrupted() {
return uploadInterrupted;
}
@Override
public OutputStream getOutputStream() {
return originalStreamVariable.getOutputStream();
}
@Override
public void streamingStarted(final StreamingStartEvent event) {
originalStreamVariable.streamingStarted(event);
}
@Override
public void streamingFinished(final StreamingEndEvent event) {
originalStreamVariable.streamingFinished(event);
}
@Override
public void streamingFailed(final StreamingErrorEvent event) {
originalStreamVariable.streamingFailed(event);
uploadInterrupted = false;
}
}
}

View File

@@ -1,403 +0,0 @@
/**
* 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;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Optional;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.exception.ArtifactUploadFailedException;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
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;
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
import org.eclipse.hawkbit.ui.utils.SpringContextHelper;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
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.Upload;
import com.vaadin.ui.Upload.FailedEvent;
import com.vaadin.ui.Upload.FailedListener;
import com.vaadin.ui.Upload.FinishedEvent;
import com.vaadin.ui.Upload.FinishedListener;
import com.vaadin.ui.Upload.ProgressListener;
import com.vaadin.ui.Upload.Receiver;
import com.vaadin.ui.Upload.StartedEvent;
import com.vaadin.ui.Upload.StartedListener;
import com.vaadin.ui.Upload.SucceededEvent;
import com.vaadin.ui.Upload.SucceededListener;
/**
* Implementation to read file selected for upload. both for {@link Upload} and
* {@link StreamVariable} upload variants.
*
* The handler manages the output to the user and at the same time ensures that
* the upload does not exceed the configured max file size.
*
*/
public class UploadHandler implements StreamVariable, Receiver, SucceededListener, FailedListener, FinishedListener,
ProgressListener, StartedListener {
private static final long serialVersionUID = 1L;
private static final Logger LOG = LoggerFactory.getLogger(UploadHandler.class);
private final long fileSize;
private final UploadLayout view;
private final long maxSize;
private final Upload upload;
private volatile String fileName;
private volatile String mimeType;
private volatile boolean streamingInterrupted;
private volatile boolean uploadInterrupted;
private volatile boolean aborted;
private String failureReason;
private final VaadinMessageSource i18n;
private transient EventBus.UIEventBus eventBus;
private final SoftwareModule selectedSw;
private SoftwareModule selectedSwForUpload;
private final ArtifactUploadState artifactUploadState;
private final transient SoftwareModuleManagement softwareModuleManagement;
UploadHandler(final String fileName, final long fileSize, final UploadLayout view, final long maxSize,
final Upload upload, final String mimeType, final SoftwareModule selectedSw,
final SoftwareModuleManagement softwareManagement) {
this.aborted = false;
this.fileName = fileName;
this.fileSize = fileSize;
this.view = view;
this.maxSize = maxSize;
this.upload = upload;
this.mimeType = mimeType;
this.selectedSw = selectedSw;
this.i18n = SpringContextHelper.getBean(VaadinMessageSource.class);
this.eventBus = SpringContextHelper.getBean(EventBus.UIEventBus.class);
this.artifactUploadState = SpringContextHelper.getBean(ArtifactUploadState.class);
this.softwareModuleManagement = softwareManagement;
eventBus.subscribe(this);
}
@EventBusListenerMethod(scope = EventScope.UI)
void onEvent(final UploadStatusEventType event) {
if (event == UploadStatusEventType.ABORT_UPLOAD) {
aborted = true;
}
}
/**
* Create stream for {@link StreamVariable} variant.
*
* @see com.vaadin.server.StreamVariable#getOutputStream()
*/
@Override
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);
failureReason = e.getMessage();
streamingInterrupted = true;
return new NullOutputStream();
}
}
/**
* Create stream for {@link Upload} variant.
*
* @see com.vaadin.ui.Upload.Receiver#receiveUpload(java.lang.String,
* java.lang.String)
*/
@Override
public OutputStream receiveUpload(final String fileName, final String mimeType) {
aborted = false;
failureReason = null;
this.fileName = fileName;
this.mimeType = mimeType;
// reset has directory flag before upload
view.setHasDirectory(false);
try {
if (view.checkIfSoftwareModuleIsSelected() && !view.checkForDuplicate(fileName, selectedSwForUpload)) {
view.increaseNumberOfFileUploadsExpected();
final OutputStream saveUploadedFileDetails = view.saveUploadedFileDetails(fileName, 0, mimeType,
selectedSwForUpload);
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.RECEIVE_UPLOAD,
new UploadFileStatus(fileName, 0, -1, selectedSwForUpload)));
return saveUploadedFileDetails;
}
} catch (final ArtifactUploadFailedException e) {
LOG.error("Atifact upload failed {} ", e);
failureReason = e.getMessage();
upload.interruptUpload();
uploadInterrupted = true;
}
// if final validation fails ,final no upload ,return NullOutputStream
return new NullOutputStream();
}
/**
*
* Upload sucessfull for {@link Upload} variant.
*
* @see com.vaadin.ui.Upload.SucceededListener#uploadSucceeded(com.vaadin.ui.Upload.SucceededEvent)
*/
@Override
public void uploadSucceeded(final SucceededEvent event) {
LOG.debug("Streaming finished for file :{}", event.getFilename());
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_SUCCESSFUL,
new UploadFileStatus(event.getFilename(), 0, event.getLength(), selectedSwForUpload)));
}
/**
* Upload finished for {@link StreamVariable} variant. Called only in good
* case. So a combination of {@link #uploadSucceeded(SucceededEvent)} and
* {@link #uploadFinished(FinishedEvent)}.
*
* @see com.vaadin.server.StreamVariable#streamingFinished(com.vaadin.server.StreamVariable.StreamingEndEvent)
*/
@Override
public void streamingFinished(final StreamingEndEvent event) {
LOG.debug("Streaming finished for file :{}", event.getFileName());
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_STREAMING_FINISHED,
new UploadFileStatus(event.getFileName(), 0, event.getContentLength(), selectedSw)));
}
/**
* Upload finished for {@link Upload} variant. Both for good and error
* variant.
*
* @see com.vaadin.ui.Upload.FinishedListener#uploadFinished(com.vaadin.ui.Upload.FinishedEvent)
*/
@Override
public void uploadFinished(final FinishedEvent event) {
LOG.debug("Upload finished for file :{}", event.getFilename());
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_FINISHED,
new UploadFileStatus(event.getFilename())));
}
/**
* Upload started for {@link StreamVariable} variant.
*
* @see com.vaadin.server.StreamVariable#streamingStarted(com.vaadin.server.StreamVariable.StreamingStartEvent)
*/
@Override
public void streamingStarted(final StreamingStartEvent event) {
LOG.debug("Streaming started for file :{}", fileName);
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_STARTED,
new UploadFileStatus(fileName, 0, 0, selectedSw)));
}
/**
* Upload started for {@link Upload} variant.
*
* @see com.vaadin.ui.Upload.StartedListener#uploadStarted(com.vaadin.ui.Upload.StartedEvent)
*/
@Override
public void uploadStarted(final StartedEvent event) {
uploadInterrupted = false;
selectedSwForUpload = null;
final Optional<Long> selectedBaseSwModuleId = artifactUploadState.getSelectedBaseSwModuleId();
if (selectedBaseSwModuleId.isPresent()) {
selectedSwForUpload = softwareModuleManagement.get(selectedBaseSwModuleId.get()).orElse(null);
}
if (selectedSwForUpload != null && view.checkIfSoftwareModuleIsSelected()
&& !view.checkIfFileIsDuplicate(event.getFilename(), selectedSwForUpload)) {
LOG.debug("Upload started for file :{}", event.getFilename());
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_STARTED,
new UploadFileStatus(event.getFilename(), 0, 0, selectedSwForUpload)));
} else {
failureReason = i18n.getMessage("message.upload.failed");
upload.interruptUpload();
// actual interrupt will happen a bit late so setting the below
// flag
uploadInterrupted = true;
}
}
/**
* listen progress.
*
* @return boolean
*/
@Override
public boolean listenProgress() {
return true;
}
/**
* Reports progress in {@link Upload} variant.
*
* @see com.vaadin.ui.Upload.ProgressListener#updateProgress(long, long)
*/
@Override
public void updateProgress(final long readBytes, final long contentLength) {
// Update progress is called event after upload interrupted in
// uploadStarted method
if (!uploadInterrupted) {
if (aborted) {
LOG.info("User aborted file upload for file : {}", fileName);
failureReason = i18n.getMessage("message.uploadedfile.aborted");
interruptFileUpload();
return;
}
if (readBytes > maxSize || contentLength > maxSize) {
LOG.error("User tried to upload more than was allowed ({}).", maxSize);
failureReason = i18n.getMessage("message.uploadedfile.size.exceeded", maxSize);
interruptFileUpload();
return;
}
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_IN_PROGRESS,
new UploadFileStatus(fileName, readBytes, contentLength, selectedSwForUpload)));
LOG.info("Update progress - {} : {}", fileName, (double) readBytes / (double) contentLength);
}
}
/**
* Reports progress in {@link StreamVariable} variant. Interrupts
*
* @see com.vaadin.server.StreamVariable#onProgress(com.vaadin.server.StreamVariable.StreamingProgressEvent)
*/
@Override
public void onProgress(final StreamingProgressEvent event) {
if (aborted) {
LOG.info("User aborted the upload for file : {}", event.getFileName());
failureReason = i18n.getMessage("message.uploadedfile.aborted");
interruptFileStreaming();
return;
}
if (event.getBytesReceived() > maxSize || event.getContentLength() > maxSize) {
LOG.error("User tried to upload more than was allowed ({}).", maxSize);
failureReason = i18n.getMessage("message.uploadedfile.size.exceeded", maxSize);
interruptFileStreaming();
return;
}
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_IN_PROGRESS,
new UploadFileStatus(fileName, event.getBytesReceived(), event.getContentLength(), selectedSw)));
// Logging to solve sonar issue
LOG.trace("Streaming in progress for file :{}", event.getFileName());
}
/**
* Upload failed for{@link StreamVariable} variant.
*
* @param event
* StreamingEndEvent
*/
@Override
public void streamingFailed(final StreamingErrorEvent event) {
if (failureReason == null) {
failureReason = event.getException().getMessage();
}
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_STREAMING_FAILED,
new UploadFileStatus(fileName, failureReason, selectedSw)));
if (!aborted) {
LOG.info("Streaming failed for file :{}", event.getFileName());
LOG.info("Streaming failed due to :{}", event.getException());
}
}
/**
* Upload failed for {@link Upload} variant.
*
* @see com.vaadin.ui.Upload.FailedListener#uploadFailed(com.vaadin.ui.Upload.FailedEvent)
*/
@Override
public void uploadFailed(final FailedEvent event) {
/**
* If upload failed due to no selected software UPLOAD_FAILED event need
* not be published.
*/
if (selectedSwForUpload != null) {
if (failureReason == null) {
failureReason = event.getReason().getMessage();
}
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_FAILED,
new UploadFileStatus(fileName, failureReason, selectedSwForUpload)));
if (!aborted) {
LOG.info("Upload failed for file :{}", event.getFilename());
LOG.info("Upload failed for file :{}", event.getReason());
}
}
}
/**
* to check if upload is interrupted.
*/
@Override
public boolean isInterrupted() {
return streamingInterrupted;
}
private static class NullOutputStream extends OutputStream {
/**
* null output stream.
*
* @param i
* byte
*/
@Override
public void write(final int i) throws IOException {
// do nothing
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((fileName == null) ? 0 : fileName.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final UploadHandler other = (UploadHandler) obj;
if (fileName == null) {
if (other.fileName != null) {
return false;
}
} else if (!fileName.equals(other.fileName)) {
return false;
}
return true;
}
private void interruptFileStreaming() {
streamingInterrupted = true;
}
private void interruptFileUpload() {
upload.interruptUpload();
uploadInterrupted = true;
}
}

View File

@@ -1,824 +0,0 @@
/**
* 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;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.servlet.MultipartConfigElement;
import org.apache.commons.io.FileUtils;
import org.eclipse.hawkbit.repository.ArtifactManagement;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.exception.ArtifactUploadFailedException;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent.SoftwareModuleEventType;
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;
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
import org.eclipse.hawkbit.ui.artifacts.state.CustomFile;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.dd.criteria.ServerItemIdClientCriterion;
import org.eclipse.hawkbit.ui.dd.criteria.ServerItemIdClientCriterion.Mode;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmall;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
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.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.vaadin.spring.events.EventBus;
import org.vaadin.spring.events.EventBus.UIEventBus;
import org.vaadin.spring.events.EventScope;
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
import com.vaadin.event.dd.acceptcriteria.Not;
import com.vaadin.server.FontAwesome;
import com.vaadin.server.Page;
import com.vaadin.server.StreamVariable;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.DragAndDropWrapper;
import com.vaadin.ui.DragAndDropWrapper.WrapperTransferable;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Html5File;
import com.vaadin.ui.Label;
import com.vaadin.ui.UI;
import com.vaadin.ui.Upload;
import com.vaadin.ui.VerticalLayout;
/**
* Upload files layout.
*/
public class UploadLayout extends VerticalLayout {
private static final long serialVersionUID = 1L;
private static final String HTML_DIV = "</div>";
private static final Logger LOG = LoggerFactory.getLogger(UploadLayout.class);
private final UploadStatusInfoWindow uploadInfoWindow;
private final VaadinMessageSource i18n;
private final UINotification uiNotification;
private final transient EventBus.UIEventBus eventBus;
private final ArtifactUploadState artifactUploadState;
private final transient MultipartConfigElement multipartConfigElement;
private final List<String> duplicateFileNamesList = new ArrayList<>();
private Button processBtn;
private Button discardBtn;
private UploadConfirmationWindow currentUploadConfirmationwindow;
private final UI ui;
private HorizontalLayout fileUploadLayout;
private DragAndDropWrapper dropAreaWrapper;
private boolean hasDirectory;
private Button uploadStatusButton;
private final transient SoftwareModuleManagement softwareModuleManagement;
private static AcceptCriterion acceptAllExceptBlacklisted = new Not(new ServerItemIdClientCriterion(Mode.PREFIX,
UIComponentIdProvider.UPLOAD_SOFTWARE_MODULE_TABLE, UIComponentIdProvider.UPLOAD_TYPE_BUTTON_PREFIX));
private final transient ArtifactManagement artifactManagement;
public UploadLayout(final VaadinMessageSource i18n, final UINotification uiNotification, final UIEventBus eventBus,
final ArtifactUploadState artifactUploadState, final MultipartConfigElement multipartConfigElement,
final ArtifactManagement artifactManagement, final SoftwareModuleManagement softwareManagement) {
this.uploadInfoWindow = new UploadStatusInfoWindow(eventBus, artifactUploadState, i18n);
this.i18n = i18n;
this.uiNotification = uiNotification;
this.eventBus = eventBus;
this.artifactUploadState = artifactUploadState;
this.multipartConfigElement = multipartConfigElement;
this.artifactManagement = artifactManagement;
this.softwareModuleManagement = softwareManagement;
createComponents();
buildLayout();
restoreState();
eventBus.subscribe(this);
ui = UI.getCurrent();
}
@EventBusListenerMethod(scope = EventScope.UI)
void onEvent(final UploadArtifactUIEvent event) {
if (event == UploadArtifactUIEvent.DELETED_ALL_SOFWARE) {
ui.access(this::updateActionCount);
} else if (event == UploadArtifactUIEvent.MINIMIZED_STATUS_POPUP) {
ui.access(this::showUploadStatusButton);
} else if (event == UploadArtifactUIEvent.MAXIMIZED_STATUS_POPUP) {
ui.access(this::maximizeStatusPopup);
} else if (event == UploadArtifactUIEvent.ARTIFACT_RESULT_POPUP_CLOSED) {
ui.access(this::closeUploadStatusPopup);
}
}
@EventBusListenerMethod(scope = EventScope.UI)
void onEvent(final UploadStatusEvent event) {
if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_STARTED) {
ui.access(this::onStartOfUpload);
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_FAILED) {
ui.access(() -> onUploadFailure(event));
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_FINISHED) {
ui.access(this::onUploadCompletion);
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_SUCCESSFUL) {
ui.access(() -> onUploadSuccess(event));
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_STREAMING_FAILED) {
ui.access(() -> onUploadStreamingFailure(event));
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_STREAMING_FINISHED) {
ui.access(this::onUploadStreamingSuccess);
}
}
private void createComponents() {
createUploadStatusButton();
createProcessButton();
createDiscardBtn();
}
private void buildLayout() {
final Upload upload = new Upload();
final UploadHandler uploadHandler = new UploadHandler(null, 0, this, multipartConfigElement.getMaxFileSize(),
upload, null, null, softwareModuleManagement);
upload.setButtonCaption(i18n.getMessage("upload.file"));
upload.setImmediate(true);
upload.setReceiver(uploadHandler);
upload.addSucceededListener(uploadHandler);
upload.addFailedListener(uploadHandler);
upload.addFinishedListener(uploadHandler);
upload.addProgressListener(uploadHandler);
upload.addStartedListener(uploadHandler);
upload.addStyleName(SPUIStyleDefinitions.ACTION_BUTTON);
upload.addStyleName("no-border");
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 */
dropAreaWrapper = new DragAndDropWrapper(createDropAreaLayout());
dropAreaWrapper.setDropHandler(new DropAreahandler());
setSizeFull();
setSpacing(true);
}
private void restoreState() {
updateActionCount();
if (!artifactUploadState.getFileSelected().isEmpty() && artifactUploadState.isUploadCompleted()) {
processBtn.setEnabled(true);
}
if (artifactUploadState.isStatusPopupMinimized()) {
showUploadStatusButton();
if (artifactUploadState.isUploadCompleted()) {
setUploadStatusButtonIconToFinished();
}
}
if (artifactUploadState.isUploadCompleted()) {
artifactUploadState.getNumberOfFilesActuallyUpload().set(0);
artifactUploadState.getNumberOfFileUploadsExpected().set(0);
artifactUploadState.getNumberOfFileUploadsFailed().set(0);
}
}
public DragAndDropWrapper getDropAreaWrapper() {
return dropAreaWrapper;
}
private class DropAreahandler implements DropHandler {
private static final long serialVersionUID = 1L;
@Override
public AcceptCriterion getAcceptCriterion() {
return acceptAllExceptBlacklisted;
}
@Override
public void drop(final DragAndDropEvent event) {
if (validate(event)) {
final Html5File[] files = ((WrapperTransferable) event.getTransferable()).getFiles();
// selected software module at the time of file drop is
// considered for upload
artifactUploadState.getSelectedBaseSwModuleId().ifPresent(selectedSwId -> {
// reset the flag
hasDirectory = false;
final SoftwareModule softwareModule = softwareModuleManagement.get(selectedSwId)
.orElse(null);
for (final Html5File file : files) {
processFile(file, softwareModule);
}
if (artifactUploadState.getNumberOfFileUploadsExpected().get() > 0) {
processBtn.setEnabled(false);
} else {
// If the upload is not started, it signifies all
// dropped files as either duplicate or directory.So
// display message accordingly
displayCompositeMessage();
}
});
}
}
private boolean validate(final DragAndDropEvent event) {
// check if drop is valid.If valid ,check if software module is
// selected.
if (!isFilesDropped(event)) {
uiNotification.displayValidationError(i18n.getMessage("message.action.not.allowed"));
return false;
}
return checkIfSoftwareModuleIsSelected();
}
private boolean isFilesDropped(final DragAndDropEvent event) {
if (event.getTransferable() instanceof WrapperTransferable) {
final Html5File[] files = ((WrapperTransferable) event.getTransferable()).getFiles();
return files != null;
}
return false;
}
private void processFile(final Html5File file, final SoftwareModule selectedSw) {
if (!isDirectory(file)) {
if (!checkForDuplicate(file.getFileName(), selectedSw)) {
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.RECEIVE_UPLOAD,
new UploadFileStatus(file.getFileName(), 0, -1, selectedSw)));
artifactUploadState.getNumberOfFileUploadsExpected().incrementAndGet();
file.setStreamVariable(createStreamVariable(file, selectedSw));
}
} else {
hasDirectory = Boolean.TRUE;
}
}
private StreamVariable createStreamVariable(final Html5File file, final SoftwareModule selectedSw) {
return new UploadHandler(file.getFileName(), file.getFileSize(), UploadLayout.this,
multipartConfigElement.getMaxFileSize(), null, file.getType(), selectedSw, softwareModuleManagement);
}
private boolean isDirectory(final Html5File file) {
return StringUtils.isEmpty(file.getType()) && file.getFileSize() % 4096 == 0;
}
}
private void displayCompositeMessage() {
final String duplicateMessage = getDuplicateFileValidationMessage();
final StringBuilder compositeMessage = new StringBuilder();
if (!StringUtils.isEmpty(duplicateMessage)) {
compositeMessage.append(duplicateMessage);
}
if (hasDirectory) {
if (compositeMessage.length() > 0) {
compositeMessage.append("<br>");
}
compositeMessage.append(i18n.getMessage("message.no.directory.upload"));
}
if (!compositeMessage.toString().isEmpty()) {
uiNotification.displayValidationError(compositeMessage.toString());
}
}
private static VerticalLayout createDropAreaLayout() {
final VerticalLayout dropAreaLayout = new VerticalLayout();
final Label dropHereLabel = new Label("Drop files to upload");
dropHereLabel.setWidth(null);
final Label dropIcon = new Label(FontAwesome.ARROW_DOWN.getHtml(), ContentMode.HTML);
dropIcon.addStyleName("drop-icon");
dropIcon.setWidth(null);
dropAreaLayout.addComponent(dropIcon);
dropAreaLayout.setComponentAlignment(dropIcon, Alignment.BOTTOM_CENTER);
dropAreaLayout.addComponent(dropHereLabel);
dropAreaLayout.setComponentAlignment(dropHereLabel, Alignment.TOP_CENTER);
dropAreaLayout.setSizeFull();
dropAreaLayout.setStyleName("upload-drop-area-layout-info");
dropAreaLayout.setSpacing(false);
return dropAreaLayout;
}
private void createProcessButton() {
processBtn = SPUIComponentProvider.getButton(UIComponentIdProvider.UPLOAD_PROCESS_BUTTON,
SPUILabelDefinitions.PROCESS, SPUILabelDefinitions.PROCESS, null, false, null,
SPUIButtonStyleSmall.class);
processBtn.setIcon(FontAwesome.BELL);
processBtn.addStyleName(SPUIStyleDefinitions.ACTION_BUTTON);
processBtn.addClickListener(this::displayConfirmWindow);
processBtn.setHtmlContentAllowed(true);
processBtn.setEnabled(false);
}
private void createDiscardBtn() {
discardBtn = SPUIComponentProvider.getButton(UIComponentIdProvider.UPLOAD_DISCARD_BUTTON,
SPUILabelDefinitions.DISCARD, SPUILabelDefinitions.DISCARD, null, false, null,
SPUIButtonStyleSmall.class);
discardBtn.setIcon(FontAwesome.TRASH_O);
discardBtn.addStyleName(SPUIStyleDefinitions.ACTION_BUTTON);
discardBtn.addClickListener(this::discardUploadData);
}
boolean checkForDuplicate(final String filename, final SoftwareModule selectedSw) {
final Boolean isDuplicate = checkIfFileIsDuplicate(filename, selectedSw);
if (isDuplicate) {
getDuplicateFileNamesList().add(filename);
}
return isDuplicate;
}
/**
* Save uploaded file details.
*
* @param stream
* read from uploaded file
* @param name
* file name
* @param size
* file size
* @param mimeType
* the mimeType of the file
* @param selectedSw
* @throws IOException
* in case of upload errors
*/
OutputStream saveUploadedFileDetails(final String name, final long size, final String mimeType,
final SoftwareModule selectedSw) {
File tempFile = null;
try {
tempFile = File.createTempFile("spUiArtifactUpload", null);
// we return the outputstream so we cannot close it here
@SuppressWarnings("squid:S2095")
final OutputStream out = new FileOutputStream(tempFile);
final String currentBaseSoftwareModuleKey = HawkbitCommonUtil.getFormattedNameVersion(selectedSw.getName(),
selectedSw.getVersion());
final CustomFile customFile = new CustomFile(name, size, tempFile.getAbsolutePath(), selectedSw.getName(),
selectedSw.getVersion(), mimeType);
artifactUploadState.getFileSelected().add(customFile);
processBtn.setEnabled(false);
if (!artifactUploadState.getBaseSwModuleList().keySet().contains(currentBaseSoftwareModuleKey)) {
artifactUploadState.getBaseSwModuleList().put(currentBaseSoftwareModuleKey, selectedSw);
}
return out;
} catch (final FileNotFoundException e) {
LOG.error("Upload failed {}", e);
throw new ArtifactUploadFailedException(i18n.getMessage("message.file.not.found"));
} catch (final IOException e) {
LOG.error("Upload failed {}", e);
throw new ArtifactUploadFailedException(i18n.getMessage("message.upload.failed"));
}
}
boolean checkIfSoftwareModuleIsSelected() {
if (!artifactUploadState.getSelectedBaseSwModuleId().isPresent()) {
uiNotification.displayValidationError(i18n.getMessage("message.error.noSwModuleSelected"));
return false;
}
return true;
}
/**
* Check if the selected file is duplicate. i.e. already selected for upload
* for same software module.
*
* @param name
* file name
* @param selectedSoftwareModule
* the current selected software module
* @return Boolean
*/
Boolean checkIfFileIsDuplicate(final String name, final SoftwareModule selectedSoftwareModule) {
Boolean isDuplicate = false;
final String currentBaseSoftwareModuleKey = HawkbitCommonUtil
.getFormattedNameVersion(selectedSoftwareModule.getName(), selectedSoftwareModule.getVersion());
for (final CustomFile customFile : artifactUploadState.getFileSelected()) {
final String fileSoftwareModuleKey = HawkbitCommonUtil.getFormattedNameVersion(
customFile.getBaseSoftwareModuleName(), customFile.getBaseSoftwareModuleVersion());
if (customFile.getFileName().equals(name) && currentBaseSoftwareModuleKey.equals(fileSoftwareModuleKey)) {
isDuplicate = true;
break;
}
}
return isDuplicate;
}
private void decreaseNumberOfFileUploadsExpected() {
artifactUploadState.getNumberOfFileUploadsExpected().decrementAndGet();
}
private List<String> getDuplicateFileNamesList() {
return duplicateFileNamesList;
}
/**
* Update pending action count.
*/
private void updateActionCount() {
if (!artifactUploadState.getFileSelected().isEmpty()) {
processBtn.setCaption(SPUILabelDefinitions.PROCESS + "<div class='unread'>"
+ artifactUploadState.getFileSelected().size() + HTML_DIV);
} else {
processBtn.setCaption(SPUILabelDefinitions.PROCESS);
}
}
private void displayDuplicateValidationMessage() {
// check if streaming of all dropped files are completed
if (artifactUploadState.getNumberOfFilesActuallyUpload().intValue() == artifactUploadState
.getNumberOfFileUploadsExpected().intValue()) {
displayCompositeMessage();
duplicateFileNamesList.clear();
}
}
private String getDuplicateFileValidationMessage() {
final StringBuilder message = new StringBuilder();
if (!duplicateFileNamesList.isEmpty()) {
final String fileNames = StringUtils.collectionToCommaDelimitedString(duplicateFileNamesList);
if (duplicateFileNamesList.size() == 1) {
message.append(i18n.getMessage("message.no.duplicateFile") + fileNames);
} else if (duplicateFileNamesList.size() > 1) {
message.append(i18n.getMessage("message.no.duplicateFiles"));
}
}
return message.toString();
}
void increaseNumberOfFileUploadsExpected() {
artifactUploadState.getNumberOfFileUploadsExpected().incrementAndGet();
}
private void updateFileSize(final String name, final long size, final SoftwareModule selectedSoftwareModule) {
final String currentBaseSoftwareModuleKey = HawkbitCommonUtil
.getFormattedNameVersion(selectedSoftwareModule.getName(), selectedSoftwareModule.getVersion());
for (final CustomFile customFile : artifactUploadState.getFileSelected()) {
final String fileSoftwareModuleKey = HawkbitCommonUtil.getFormattedNameVersion(
customFile.getBaseSoftwareModuleName(), customFile.getBaseSoftwareModuleVersion());
if (customFile.getFileName().equals(name) && currentBaseSoftwareModuleKey.equals(fileSoftwareModuleKey)) {
customFile.setFileSize(size);
break;
}
}
}
private void increaseNumberOfFilesActuallyUpload() {
artifactUploadState.getNumberOfFilesActuallyUpload().incrementAndGet();
}
private void increaseNumberOfFileUploadsFailed() {
artifactUploadState.getNumberOfFileUploadsFailed().incrementAndGet();
}
/**
* Enable process button once upload is completed.
*/
private boolean enableProcessBtn() {
if (artifactUploadState.getNumberOfFilesActuallyUpload().intValue() >= artifactUploadState
.getNumberOfFileUploadsExpected().intValue() && !getFileSelected().isEmpty()) {
processBtn.setEnabled(true);
artifactUploadState.getNumberOfFilesActuallyUpload().set(0);
artifactUploadState.getNumberOfFileUploadsExpected().set(0);
return true;
}
return false;
}
Set<CustomFile> getFileSelected() {
return artifactUploadState.getFileSelected();
}
private void discardUploadData(final Button.ClickEvent event) {
if (event.getButton().equals(discardBtn)) {
if (artifactUploadState.getFileSelected().isEmpty()) {
uiNotification.displayValidationError(i18n.getMessage("message.error.noFileSelected"));
} else {
clearUploadedFileDetails();
}
}
}
protected void clearUploadedFileDetails() {
clearFileList();
closeUploadStatusPopup();
}
private void closeUploadStatusPopup() {
uploadInfoWindow.clearWindow();
hideUploadStatusButton();
artifactUploadState.setStatusPopupMinimized(false);
}
/**
* Clear details.
*/
void clearFileList() {
// delete file system zombies
artifactUploadState.getFileSelected()
.forEach(customFile -> FileUtils.deleteQuietly(new File(customFile.getFilePath())));
artifactUploadState.getFileSelected().clear();
artifactUploadState.getBaseSwModuleList().clear();
processBtn.setCaption(SPUILabelDefinitions.PROCESS);
/* disable when there is no files to upload. */
processBtn.setEnabled(false);
artifactUploadState.getNumberOfFilesActuallyUpload().set(0);
artifactUploadState.getNumberOfFileUploadsExpected().set(0);
artifactUploadState.getNumberOfFileUploadsFailed().set(0);
duplicateFileNamesList.clear();
}
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);
}
}
/**
* Set artifact upload result pop up size changes.
*
* @param newWidth
* new width of result pop up
* @param newHeight
* new height of result pop up
*/
void setResultPopupHeightWidth(final float newWidth, final float newHeight) {
if (currentUploadConfirmationwindow != null
&& 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);
}
}
private void displayConfirmWindow(final Button.ClickEvent event) {
if (event.getComponent().getId().equals(UIComponentIdProvider.UPLOAD_PROCESS_BUTTON)) {
if (artifactUploadState.getFileSelected().isEmpty()) {
uiNotification.displayValidationError(i18n.getMessage("message.error.noFileSelected"));
} else {
currentUploadConfirmationwindow = new UploadConfirmationWindow(this, artifactUploadState, eventBus,
artifactManagement);
UI.getCurrent().addWindow(currentUploadConfirmationwindow.getUploadConfirmationWindow());
setConfirmationPopupHeightWidth(Page.getCurrent().getBrowserWindowWidth(),
Page.getCurrent().getBrowserWindowHeight());
}
}
}
VaadinMessageSource getI18n() {
return i18n;
}
void setCurrentUploadConfirmationwindow(final UploadConfirmationWindow currentUploadConfirmationwindow) {
this.currentUploadConfirmationwindow = currentUploadConfirmationwindow;
}
private void onStartOfUpload() {
setUploadStatusButtonIconToInProgress();
if (artifactUploadState.isStatusPopupMinimized()) {
updateStatusButtonCount();
}
}
private void onUploadStreamingSuccess() {
increaseNumberOfFilesActuallyUpload();
updateUploadCounts();
enableProcessBtn();
if (isUploadComplete()) {
uploadInfoWindow.uploadSessionFinished();
setUploadStatusButtonIconToFinished();
}
// display the duplicate message after streaming all files
displayDuplicateValidationMessage();
}
private void onUploadStreamingFailure(final UploadStatusEvent event) {
/**
* 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 = event.getUploadStatus().getSoftwareModule();
if (sw != null) {
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(), event.getUploadStatus().getSoftwareModule());
increaseNumberOfFileUploadsFailed();
}
decreaseNumberOfFileUploadsExpected();
updateUploadCounts();
enableProcessBtn();
// check if we are finished
if (isUploadComplete()) {
uploadInfoWindow.uploadSessionFinished();
setUploadStatusButtonIconToFinished();
}
displayDuplicateValidationMessage();
}
private void onUploadSuccess(final UploadStatusEvent event) {
updateFileSize(event.getUploadStatus().getFileName(), event.getUploadStatus().getContentLength(),
event.getUploadStatus().getSoftwareModule());
// recorded that we now one more uploaded
increaseNumberOfFilesActuallyUpload();
}
private void onUploadCompletion() {
// check if we are finished
if (isUploadComplete()) {
uploadInfoWindow.uploadSessionFinished();
setUploadStatusButtonIconToFinished();
displayDuplicateValidationMessage();
}
updateUploadCounts();
enableProcessBtn();
}
private boolean isUploadComplete() {
final int uploadedCount = artifactUploadState.getNumberOfFilesActuallyUpload().intValue();
final int expectedUploadsCount = artifactUploadState.getNumberOfFileUploadsExpected().intValue();
return uploadedCount == expectedUploadsCount;
}
private void onUploadFailure(final UploadStatusEvent event) {
/**
* 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 = event.getUploadStatus().getSoftwareModule();
if (sw != null) {
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(), event.getUploadStatus().getSoftwareModule());
increaseNumberOfFileUploadsFailed();
decreaseNumberOfFileUploadsExpected();
}
}
void refreshArtifactDetailsLayout(final Long selectedBaseSoftwareModuleId) {
final SoftwareModule softwareModule = softwareModuleManagement.get(selectedBaseSoftwareModuleId)
.orElse(null);
eventBus.publish(this, new SoftwareModuleEvent(SoftwareModuleEventType.ARTIFACTS_CHANGED, softwareModule));
}
public HorizontalLayout getFileUploadLayout() {
return fileUploadLayout;
}
public UINotification getUINotification() {
return uiNotification;
}
public void setHasDirectory(final Boolean hasDirectory) {
this.hasDirectory = hasDirectory;
}
private void createUploadStatusButton() {
uploadStatusButton = SPUIComponentProvider.getButton(UIComponentIdProvider.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 updateStatusButtonCount() {
final int uploadsPending = artifactUploadState.getNumberOfFileUploadsExpected().get()
- artifactUploadState.getNumberOfFilesActuallyUpload().get();
final int uploadsFailed = artifactUploadState.getNumberOfFileUploadsFailed().get();
final StringBuilder builder = new StringBuilder("");
if (uploadsFailed != 0) {
if (uploadsPending != 0) {
builder.append("<div class='error-count error-count-color'>" + uploadsFailed + HTML_DIV);
} else {
builder.append("<div class='unread error-count-color'>" + uploadsFailed + HTML_DIV);
}
}
if (uploadsPending != 0) {
builder.append("<div class='unread'>" + uploadsPending + HTML_DIV);
}
uploadStatusButton.setCaption(builder.toString());
}
private void onClickOfUploadStatusButton() {
artifactUploadState.setStatusPopupMinimized(false);
eventBus.publish(this, UploadArtifactUIEvent.MAXIMIZED_STATUS_POPUP);
}
private void showUploadStatusButton() {
if (uploadStatusButton == null) {
return;
}
uploadStatusButton.setVisible(true);
updateStatusButtonCount();
}
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);
}
protected void updateUploadCounts() {
updateActionCount();
updateStatusButtonCount();
}
}

View File

@@ -0,0 +1,203 @@
/**
* 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;
import javax.servlet.MultipartConfigElement;
import org.eclipse.hawkbit.repository.ArtifactManagement;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent;
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleNoBorder;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.spring.events.EventBus.UIEventBus;
import org.vaadin.spring.events.EventScope;
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
import com.vaadin.ui.Button;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
/**
* Container for upload and progress button.
*/
public class UploadProgressButtonLayout extends VerticalLayout {
private static final long serialVersionUID = 1L;
private final UploadProgressInfoWindow uploadInfoWindow;
private final VaadinMessageSource i18n;
private final transient MultipartConfigElement multipartConfigElement;
private final UI ui;
private Button uploadProgressButton;
private final transient SoftwareModuleManagement softwareModuleManagement;
private final UploadFixed upload;
private final transient ArtifactManagement artifactManagement;
private final ArtifactUploadState artifactUploadState;
/**
* Creates a new {@link UploadProgressButtonLayout} instance.
*
* @param i18n
* the {@link VaadinMessageSource}
* @param eventBus
* the {@link UIEventBus} for listening to ui events
* @param artifactUploadState
* the {@link ArtifactUploadState} for state information
* @param multipartConfigElement
* the {@link MultipartConfigElement}
* @param softwareManagement
* the {@link SoftwareModuleManagement} for retrieving the
* {@link SoftwareModule}
* @param artifactManagement
* the {@link ArtifactManagement} for storing the uploaded
* artifacts
*/
public UploadProgressButtonLayout(final VaadinMessageSource i18n, final UIEventBus eventBus,
final ArtifactUploadState artifactUploadState, final MultipartConfigElement multipartConfigElement,
final ArtifactManagement artifactManagement, final SoftwareModuleManagement softwareManagement) {
this.artifactUploadState = artifactUploadState;
this.artifactManagement = artifactManagement;
this.uploadInfoWindow = new UploadProgressInfoWindow(eventBus, artifactUploadState, i18n);
this.uploadInfoWindow.addCloseListener(event -> {
// ensure that the progress button is hidden when the progress
// window is closed and no more uploads running
if (artifactUploadState.areAllUploadsFinished()) {
hideUploadProgressButton();
}
});
this.i18n = i18n;
this.multipartConfigElement = multipartConfigElement;
this.softwareModuleManagement = softwareManagement;
this.upload = new UploadFixed();
createComponents();
buildLayout();
restoreState();
ui = UI.getCurrent();
eventBus.subscribe(this);
}
@EventBusListenerMethod(scope = EventScope.UI)
void onEvent(final FileUploadProgress fileUploadProgress) {
final FileUploadProgress.FileUploadStatus uploadProgressEventType = fileUploadProgress.getFileUploadStatus();
switch (uploadProgressEventType) {
case UPLOAD_STARTED:
ui.access(this::onStartOfUpload);
break;
case UPLOAD_FAILED:
case UPLOAD_SUCCESSFUL:
case UPLOAD_IN_PROGRESS:
break;
case UPLOAD_FINISHED:
ui.access(this::onUploadFinished);
break;
default:
throw new IllegalArgumentException("Enum " + FileUploadProgress.FileUploadStatus.class.getSimpleName()
+ " doesn't contain value " + uploadProgressEventType);
}
}
@EventBusListenerMethod(scope = EventScope.UI)
void onEvent(final SoftwareModuleEvent event) {
final BaseEntityEventType eventType = event.getEventType();
if (eventType == BaseEntityEventType.SELECTED_ENTITY) {
ui.access(() -> {
if (artifactUploadState.isNoSoftwareModuleSelected()
|| artifactUploadState.isMoreThanOneSoftwareModulesSelected()) {
upload.setEnabled(false);
} else if (artifactUploadState.areAllUploadsFinished()) {
upload.setEnabled(true);
}
});
}
}
private void createComponents() {
uploadProgressButton = SPUIComponentProvider.getButton(UIComponentIdProvider.UPLOAD_STATUS_BUTTON, "", "", "",
false, null, SPUIButtonStyleNoBorder.class);
uploadProgressButton.addStyleName(SPUIStyleDefinitions.UPLOAD_PROGRESS_INDICATOR_STYLE);
uploadProgressButton.setIcon(null);
uploadProgressButton.setHtmlContentAllowed(true);
uploadProgressButton.addClickListener(event -> onClickOfUploadProgressButton());
}
private void buildLayout() {
final FileTransferHandlerVaadinUpload uploadHandler = new FileTransferHandlerVaadinUpload(
multipartConfigElement.getMaxFileSize(), softwareModuleManagement, artifactManagement, i18n);
upload.setButtonCaption(i18n.getMessage("upload.file"));
upload.setImmediate(true);
upload.setReceiver(uploadHandler);
upload.addSucceededListener(uploadHandler);
upload.addFailedListener(uploadHandler);
upload.addFinishedListener(uploadHandler);
upload.addProgressListener(uploadHandler);
upload.addStartedListener(uploadHandler);
upload.setId(UIComponentIdProvider.UPLOAD_BUTTON);
addComponent(upload);
setSpacing(true);
}
/**
* Is called when view is shown to the user
*/
public void restoreState() {
if (artifactUploadState.areAllUploadsFinished()) {
artifactUploadState.clearUploadTempData();
hideUploadProgressButton();
upload.setEnabled(true);
} else if (artifactUploadState.isAtLeastOneUploadInProgress()) {
showUploadProgressButton();
}
}
private void onStartOfUpload() {
showUploadProgressButton();
}
/**
* Called for every finished (succeeded or failed) upload.
*/
private void onUploadFinished() {
if (artifactUploadState.areAllUploadsFinished()) {
hideUploadProgressButton();
upload.setEnabled(true);
artifactUploadState.clearUploadTempData();
}
}
private void onClickOfUploadProgressButton() {
uploadInfoWindow.maximizeWindow();
}
private void showUploadProgressButton() {
removeComponent(upload);
addComponent(uploadProgressButton);
}
private void hideUploadProgressButton() {
removeComponent(uploadProgressButton);
addComponent(upload);
}
}

View File

@@ -0,0 +1,343 @@
/**
* 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;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
import org.eclipse.hawkbit.ui.artifacts.upload.FileUploadProgress.FileUploadStatus;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleNoBorder;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.spring.events.EventBus.UIEventBus;
import org.vaadin.spring.events.EventScope;
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
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.ui.Button;
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;
/**
* Window that shows the progress of all uploads.
*/
public class UploadProgressInfoWindow extends Window {
private static final long serialVersionUID = 1L;
private static final String COLUMN_PROGRESS = "Progress";
private static final String COLUMN_FILE_NAME = "File name";
private static final String COLUMN_STATUS = "Status";
private static final String COLUMN_REASON = "Reason";
private static final String STATUS_INPROGRESS = "InProgress";
private static final String STATUS_FINISHED = "Finished";
private static final String STATUS_FAILED = "Failed";
private final ArtifactUploadState artifactUploadState;
private final VaadinMessageSource i18n;
private final Grid grid;
private final IndexedContainer uploads;
private final VerticalLayout mainLayout;
private final UI ui;
private Label windowCaption;
private Button closeButton;
UploadProgressInfoWindow(final UIEventBus eventBus, final ArtifactUploadState artifactUploadState,
final VaadinMessageSource i18n) {
this.artifactUploadState = artifactUploadState;
this.i18n = i18n;
setPopupProperties();
createStatusPopupHeaderComponents();
mainLayout = new VerticalLayout();
mainLayout.setSpacing(Boolean.TRUE);
mainLayout.setSizeUndefined();
setPopupSizeInMinMode();
uploads = getGridContainer();
grid = createGrid();
setGridColumnProperties();
mainLayout.addComponents(getCaptionLayout(), grid);
mainLayout.setExpandRatio(grid, 1.0F);
setContent(mainLayout);
eventBus.subscribe(this);
ui = UI.getCurrent();
}
@EventBusListenerMethod(scope = EventScope.UI)
void onEvent(final FileUploadProgress fileUploadProgress) {
switch (fileUploadProgress.getFileUploadStatus()) {
case UPLOAD_STARTED:
ui.access(() -> onUploadStarted(fileUploadProgress));
break;
case UPLOAD_IN_PROGRESS:
case UPLOAD_FAILED:
case UPLOAD_SUCCESSFUL:
ui.access(() -> updateUploadProgressInfoRowObject(fileUploadProgress));
break;
case UPLOAD_FINISHED:
ui.access(this::onUploadFinished);
break;
default:
break;
}
}
private void onUploadStarted(final FileUploadProgress fileUploadProgress) {
updateUploadProgressInfoRowObject(fileUploadProgress);
if (isWindowNotAlreadyAttached()) {
maximizeWindow();
}
grid.scrollTo(fileUploadProgress.getFileUploadId());
}
private boolean isWindowNotAlreadyAttached() {
return !UI.getCurrent().getWindows().contains(this);
}
private void restoreState() {
final Indexed container = grid.getContainerDataSource();
container.removeAllItems();
for (final FileUploadProgress fileUploadProgress : artifactUploadState
.getAllFileUploadProgressValuesFromOverallUploadProcessList()) {
updateUploadProgressInfoRowObject(fileUploadProgress);
}
}
private void setPopupProperties() {
setId(UIComponentIdProvider.UPLOAD_STATUS_POPUP_ID);
addStyleName(SPUIStyleDefinitions.UPLOAD_INFO);
setImmediate(true);
setResizable(false);
setDraggable(true);
setClosable(false);
setModal(true);
}
private void setGridColumnProperties() {
grid.getColumn(COLUMN_STATUS).setRenderer(new StatusRenderer());
grid.getColumn(COLUMN_PROGRESS).setRenderer(new ProgressBarRenderer());
grid.setColumnOrder(COLUMN_STATUS, COLUMN_PROGRESS, COLUMN_FILE_NAME, SPUILabelDefinitions.NAME_VERSION,
COLUMN_REASON);
setColumnWidth();
grid.getColumn(SPUILabelDefinitions.NAME_VERSION)
.setHeaderCaption(i18n.getMessage("upload.swModuleTable.header"));
grid.setFrozenColumnCount(5);
}
private Grid createGrid() {
final Grid statusGrid = new Grid(uploads);
statusGrid.addStyleName(SPUIStyleDefinitions.UPLOAD_STATUS_GRID);
statusGrid.setId(UIComponentIdProvider.UPLOAD_STATUS_POPUP_GRID);
statusGrid.setSelectionMode(SelectionMode.NONE);
statusGrid.setHeaderVisible(true);
statusGrid.setImmediate(true);
statusGrid.setSizeFull();
return statusGrid;
}
private static IndexedContainer getGridContainer() {
final IndexedContainer uploadContainer = new IndexedContainer();
uploadContainer.addContainerProperty(COLUMN_STATUS, String.class, "Active");
uploadContainer.addContainerProperty(COLUMN_FILE_NAME, String.class, null);
uploadContainer.addContainerProperty(COLUMN_PROGRESS, Double.class, 0D);
uploadContainer.addContainerProperty(COLUMN_REASON, String.class, "");
uploadContainer.addContainerProperty(SPUILabelDefinitions.NAME_VERSION, String.class, "");
return uploadContainer;
}
private HorizontalLayout getCaptionLayout() {
final HorizontalLayout captionLayout = new HorizontalLayout();
captionLayout.setSizeFull();
captionLayout.setHeight("36px");
captionLayout.addComponents(windowCaption, closeButton);
captionLayout.setExpandRatio(windowCaption, 1.0F);
captionLayout.addStyleName("v-window-header");
return captionLayout;
}
private void createStatusPopupHeaderComponents() {
windowCaption = new Label("Upload status");
closeButton = getCloseButton();
}
private void setColumnWidth() {
grid.getColumn(COLUMN_STATUS).setWidth(60);
grid.getColumn(COLUMN_PROGRESS).setWidth(150);
grid.getColumn(COLUMN_FILE_NAME).setWidth(200);
grid.getColumn(COLUMN_REASON).setWidth(290);
grid.getColumn(SPUILabelDefinitions.NAME_VERSION).setWidth(200);
}
private static class StatusRenderer extends HtmlRenderer {
private static final long serialVersionUID = 1L;
@Override
public JsonValue encode(final String value) {
if (value == null) {
return super.encode(getNullRepresentation());
}
final String result;
switch (value) {
case STATUS_FINISHED:
result = "<div class=\"statusIconGreen\">" + FontAwesome.CHECK_CIRCLE.getHtml() + "</div>";
break;
case STATUS_FAILED:
result = "<div class=\"statusIconRed\">" + FontAwesome.EXCLAMATION_CIRCLE.getHtml() + "</div>";
break;
case STATUS_INPROGRESS:
result = "<div class=\"statusIconActive\"></div>";
break;
default:
throw new IllegalArgumentException("Argument " + value + " wasn't expected.");
}
return super.encode(result);
}
}
private void openWindow() {
UI.getCurrent().addWindow(this);
center();
}
protected void maximizeWindow() {
openWindow();
restoreState();
artifactUploadState.setStatusPopupMinimized(false);
}
private void minimizeWindow() {
artifactUploadState.setStatusPopupMinimized(true);
closeWindow();
if (artifactUploadState.areAllUploadsFinished()) {
cleanupStates();
}
}
/**
* Called for every finished (succeeded or failed) upload.
*/
private void onUploadFinished() {
if (artifactUploadState.areAllUploadsFinished() && artifactUploadState.isStatusPopupMinimized()) {
if (artifactUploadState.getFilesInFailedState().isEmpty()) {
cleanupStates();
closeWindow();
} else {
maximizeWindow();
}
}
}
private void cleanupStates() {
uploads.removeAllItems();
artifactUploadState.clearUploadTempData();
}
private void setPopupSizeInMinMode() {
mainLayout.setWidth(900, Unit.PIXELS);
mainLayout.setHeight(510, Unit.PIXELS);
}
private Button getCloseButton() {
final Button closeBtn = SPUIComponentProvider.getButton(
UIComponentIdProvider.UPLOAD_STATUS_POPUP_CLOSE_BUTTON_ID, "", "", "", true, FontAwesome.TIMES,
SPUIButtonStyleNoBorder.class);
closeBtn.addStyleName(ValoTheme.BUTTON_BORDERLESS);
closeBtn.addClickListener(event -> onClose());
return closeBtn;
}
private void onClose() {
if (artifactUploadState.areAllUploadsFinished()) {
cleanupStates();
closeWindow();
} else {
minimizeWindow();
}
}
private void closeWindow() {
setWindowMode(WindowMode.NORMAL);
setColumnWidth();
setPopupSizeInMinMode();
this.close();
}
@SuppressWarnings("unchecked")
private void updateUploadProgressInfoRowObject(final FileUploadProgress fileUploadProgress) {
final FileUploadId fileUploadId = fileUploadProgress.getFileUploadId();
Item item = uploads.getItem(fileUploadId);
if (item == null) {
item = grid.getContainerDataSource().addItem(fileUploadId);
item.getItemProperty(COLUMN_FILE_NAME).setValue(fileUploadId.getFilename());
item.getItemProperty(SPUILabelDefinitions.NAME_VERSION).setValue(HawkbitCommonUtil.getFormattedNameVersion(
fileUploadId.getSoftwareModuleName(), fileUploadId.getSoftwareModuleVersion()));
}
final String status;
final FileUploadStatus uploadStatus = fileUploadProgress.getFileUploadStatus();
if (uploadStatus == FileUploadStatus.UPLOAD_FAILED) {
status = STATUS_FAILED;
} else if (uploadStatus == FileUploadStatus.UPLOAD_SUCCESSFUL) {
status = STATUS_FINISHED;
} else {
status = STATUS_INPROGRESS;
}
item.getItemProperty(COLUMN_STATUS).setValue(status);
final String failureReason = artifactUploadState.getFileUploadProgress(fileUploadId).getFailureReason();
if (StringUtils.isNotBlank(failureReason)) {
item.getItemProperty(COLUMN_REASON).setValue(failureReason);
}
final long bytesRead = fileUploadProgress.getBytesRead();
final long fileSize = fileUploadProgress.getContentLength();
if (bytesRead > 0 && fileSize > 0) {
item.getItemProperty(COLUMN_PROGRESS).setValue((double) bytesRead / (double) fileSize);
}
}
}

View File

@@ -1,200 +0,0 @@
/**
* 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;
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;
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.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.spring.events.EventBus;
import com.vaadin.data.Item;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Table;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
import com.vaadin.ui.themes.ValoTheme;
/**
* Upload status popup.
*/
public class UploadResultWindow implements Button.ClickListener {
private static final long serialVersionUID = 5205927189362269027L;
private List<UploadStatus> uploadResultList = new ArrayList<>();
private Button closeBtn;
private Table uploadResultTable;
private Window uploadResultsWindow;
private IndexedContainer tabelContainer;
private final VaadinMessageSource i18n;
private static final String FILE_NAME = "fileName";
private static final String BASE_SW_MODULE = "baseSwModuleName";
private static final String UPLOAD_RESULT = "uploadResult";
private static final String REASON = "reason";
private transient EventBus.UIEventBus eventBus;
/**
* Initialize upload status popup.
*
* @param uploadResultList
* upload status details
* @param i18n
* I18N
*/
UploadResultWindow(final List<UploadStatus> uploadResultList, final VaadinMessageSource i18n, final EventBus.UIEventBus eventBus) {
this.uploadResultList = uploadResultList;
this.i18n = i18n;
this.eventBus = eventBus;
createComponents();
createLayout();
}
private void createComponents() {
closeBtn = SPUIComponentProvider.getButton(UIComponentIdProvider.UPLOAD_ARTIFACT_RESULT_CLOSE,
SPUILabelDefinitions.CLOSE, SPUILabelDefinitions.CLOSE, ValoTheme.BUTTON_PRIMARY, false, null,
SPUIButtonStyleTiny.class);
closeBtn.addClickListener(this);
uploadResultTable = new Table();
uploadResultTable.addStyleName("artifact-table");
uploadResultTable.setSizeFull();
uploadResultTable.setImmediate(true);
uploadResultTable.setId(UIComponentIdProvider.UPLOAD_RESULT_TABLE);
uploadResultTable.addStyleName(ValoTheme.TABLE_BORDERLESS);
uploadResultTable.addStyleName(ValoTheme.TABLE_SMALL);
uploadResultTable.addStyleName(ValoTheme.TABLE_NO_VERTICAL_LINES);
uploadResultTable.addStyleName("accordion-tab-table-style");
populateUploadResultTable();
}
private void populateUploadResultTable() {
setTableContainer();
Label statusLabel;
Label reasonLabel;
for (final UploadStatus uploadResult : uploadResultList) {
final Item newItem = tabelContainer
.addItem(uploadResult.getBaseSwModuleName() + "/" + uploadResult.getFileName());
newItem.getItemProperty(FILE_NAME).setValue(HawkbitCommonUtil.getFormatedLabel(uploadResult.getFileName()));
newItem.getItemProperty(BASE_SW_MODULE)
.setValue(HawkbitCommonUtil.getFormatedLabel(uploadResult.getBaseSwModuleName()));
if (uploadResult.getUploadResult().equals(SPUILabelDefinitions.SUCCESS)) {
statusLabel = new Label(HawkbitCommonUtil.getFormatedLabel(i18n.getMessage("upload.success")));
statusLabel.addStyleName("validation-success");
newItem.getItemProperty(UPLOAD_RESULT).setValue(statusLabel);
} else {
statusLabel = new Label(HawkbitCommonUtil.getFormatedLabel(i18n.getMessage("upload.failed")));
statusLabel.addStyleName("validation-failed");
newItem.getItemProperty(UPLOAD_RESULT).setValue(statusLabel);
}
reasonLabel = HawkbitCommonUtil.getFormatedLabel(uploadResult.getReason());
reasonLabel.setDescription(uploadResult.getReason());
final String idStr = UIComponentIdProvider.UPLOAD_ERROR_REASON + uploadResult.getBaseSwModuleName() + "/"
+ uploadResult.getFileName();
reasonLabel.setId(idStr);
newItem.getItemProperty(REASON).setValue(reasonLabel);
}
}
private void setTableContainer() {
tabelContainer = new IndexedContainer();
tabelContainer.addContainerProperty(FILE_NAME, Label.class, null);
tabelContainer.addContainerProperty(BASE_SW_MODULE, Label.class, null);
tabelContainer.addContainerProperty(UPLOAD_RESULT, Label.class, null);
tabelContainer.addContainerProperty(REASON, Label.class, null);
uploadResultTable.setContainerDataSource(tabelContainer);
uploadResultTable.setPageLength(10);
uploadResultTable.setColumnHeader(FILE_NAME, i18n.getMessage("upload.file.name"));
uploadResultTable.setColumnHeader(BASE_SW_MODULE, i18n.getMessage("upload.swModuleTable.header"));
uploadResultTable.setColumnHeader(UPLOAD_RESULT, i18n.getMessage("upload.result.status"));
uploadResultTable.setColumnHeader(REASON, i18n.getMessage("upload.reason"));
uploadResultTable.setColumnExpandRatio(FILE_NAME, 0.2f);
uploadResultTable.setColumnExpandRatio(BASE_SW_MODULE, 0.2f);
uploadResultTable.setColumnExpandRatio(UPLOAD_RESULT, 0.12f);
uploadResultTable.setColumnExpandRatio(REASON, 0.48f);
final Object[] visibileColumn = { FILE_NAME, BASE_SW_MODULE, UPLOAD_RESULT, REASON };
uploadResultTable.setVisibleColumns(visibileColumn);
}
private void createLayout() {
final HorizontalLayout footer = new HorizontalLayout();
footer.setSizeUndefined();
footer.addStyleName("confirmation-window-footer");
footer.setSpacing(true);
footer.setMargin(false);
footer.addComponents(closeBtn);
footer.setComponentAlignment(closeBtn, Alignment.TOP_CENTER);
final VerticalLayout uploadResultDetails = new VerticalLayout();
uploadResultDetails.setWidth(SPUIDefinitions.MIN_UPLOAD_CONFIRMATION_POPUP_WIDTH + "px");
uploadResultDetails.addStyleName("confirmation-popup");
uploadResultDetails.addComponent(uploadResultTable);
uploadResultDetails.setComponentAlignment(uploadResultTable, Alignment.MIDDLE_CENTER);
uploadResultDetails.addComponent(footer);
uploadResultDetails.setComponentAlignment(footer, Alignment.MIDDLE_CENTER);
uploadResultsWindow = new Window();
uploadResultsWindow.setContent(uploadResultDetails);
uploadResultsWindow.setResizable(Boolean.FALSE);
uploadResultsWindow.setClosable(Boolean.FALSE);
uploadResultsWindow.setDraggable(Boolean.TRUE);
uploadResultsWindow.setModal(true);
uploadResultsWindow.setCaption(SPUILabelDefinitions.UPLOAD_RESULT);
uploadResultsWindow.addStyleName(SPUIStyleDefinitions.CONFIRMATION_WINDOW_CAPTION);
}
@Override
public void buttonClick(final ClickEvent event) {
if (event.getComponent().getId().equals(UIComponentIdProvider.UPLOAD_ARTIFACT_RESULT_CLOSE)
|| event.getComponent().getId().equals(UIComponentIdProvider.UPLOAD_ARTIFACT_RESULT_POPUP_CLOSE)) {
uploadResultsWindow.close();
// close upload status popup if open
eventBus.publish(this, UploadArtifactUIEvent.ARTIFACT_RESULT_POPUP_CLOSED);
}
}
public Window getUploadResultsWindow() {
return uploadResultsWindow;
}
public Table getUploadResultTable() {
return uploadResultTable;
}
}

View File

@@ -1,65 +0,0 @@
/**
* 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;
import java.io.Serializable;
/**
* Artifact upload status.
*
*
*
*
*
*/
public class UploadStatus implements Serializable {
private static final long serialVersionUID = 8500552533390925782L;
private String uploadResult;
private String reason;
private String fileName;
private String baseSwModuleName;
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getBaseSwModuleName() {
return baseSwModuleName;
}
public void setBaseSwModuleName(String baseSwModuleName) {
this.baseSwModuleName = baseSwModuleName;
}
public String getUploadResult() {
return uploadResult;
}
public void setUploadResult(String uploadResult) {
this.uploadResult = uploadResult;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
}

View File

@@ -1,486 +0,0 @@
/**
* 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;
import java.util.List;
import java.util.stream.Collectors;
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;
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.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.spring.events.EventBus;
import org.vaadin.spring.events.EventBus.UIEventBus;
import org.vaadin.spring.events.EventScope;
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
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.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;
/**
* Shows upload status during upload.
*/
public class UploadStatusInfoWindow extends Window {
private final transient EventBus.UIEventBus eventBus;
private final ArtifactUploadState artifactUploadState;
private final VaadinMessageSource i18n;
private static final String PROGRESS = "Progress";
private static final String FILE_NAME = "File name";
private static final String STATUS = "Status";
private static final String REASON = "Reason";
private static final long serialVersionUID = 1L;
private final Grid grid;
private final IndexedContainer uploads;
private volatile boolean errorOccured;
private volatile boolean uploadAborted;
private Button minimizeButton;
private final VerticalLayout mainLayout;
private Label windowCaption;
private Button closeButton;
private Button resizeButton;
private final UI ui;
private ConfirmationDialog confirmDialog;
UploadStatusInfoWindow(final UIEventBus eventBus, final ArtifactUploadState artifactUploadState, final VaadinMessageSource i18n) {
this.eventBus = eventBus;
this.artifactUploadState = artifactUploadState;
this.i18n = i18n;
setPopupProperties();
createStatusPopupHeaderComponents();
mainLayout = new VerticalLayout();
mainLayout.setSpacing(Boolean.TRUE);
mainLayout.setSizeUndefined();
setPopupSizeInMinMode();
uploads = getGridContainer();
grid = createGrid();
setGridColumnProperties();
mainLayout.addComponents(getCaptionLayout(), grid);
mainLayout.setExpandRatio(grid, 1.0F);
setContent(mainLayout);
eventBus.subscribe(this);
ui = UI.getCurrent();
createConfirmDialog();
}
@EventBusListenerMethod(scope = EventScope.UI)
void onEvent(final UploadStatusEvent event) {
final UploadFileStatus uploadStatus = event.getUploadStatus();
switch (event.getUploadProgressEventType()) {
case UPLOAD_IN_PROGRESS:
ui.access(() -> updateProgress(uploadStatus.getFileName(), uploadStatus.getBytesRead(),
uploadStatus.getContentLength(), uploadStatus.getSoftwareModule()));
break;
case UPLOAD_STARTED:
ui.access(() -> onStartOfUpload(event));
break;
case UPLOAD_STREAMING_FAILED:
ui.access(() -> uploadFailed(uploadStatus.getFileName(), uploadStatus.getFailureReason(),
uploadStatus.getSoftwareModule()));
break;
case UPLOAD_SUCCESSFUL:
// fall through here
case UPLOAD_STREAMING_FINISHED:
ui.access(() -> uploadSucceeded(uploadStatus.getFileName(), uploadStatus.getSoftwareModule()));
break;
case RECEIVE_UPLOAD:
uploadRecevied(uploadStatus.getFileName(), uploadStatus.getSoftwareModule());
break;
default:
break;
}
}
private void onStartOfUpload(final UploadStatusEvent event) {
uploadSessionStarted();
uploadStarted(event.getUploadStatus().getFileName(), event.getUploadStatus().getSoftwareModule());
}
private void restoreState() {
final Indexed container = grid.getContainerDataSource();
if (container.getItemIds().isEmpty()) {
container.removeAllItems();
for (final UploadStatusObject statusObject : artifactUploadState.getUploadedFileStatusList()) {
final Item item = container
.addItem(getItemid(statusObject.getFilename(), statusObject.getSelectedSoftwareModule()));
item.getItemProperty(REASON).setValue(statusObject.getReason() != null ? statusObject.getReason() : "");
if (statusObject.getStatus() != null) {
item.getItemProperty(STATUS).setValue(statusObject.getStatus());
}
if (statusObject.getProgress() != null) {
item.getItemProperty(PROGRESS).setValue(statusObject.getProgress());
}
item.getItemProperty(FILE_NAME).setValue(statusObject.getFilename());
final SoftwareModule sw = statusObject.getSelectedSoftwareModule();
item.getItemProperty(SPUILabelDefinitions.NAME_VERSION)
.setValue(HawkbitCommonUtil.getFormattedNameVersion(sw.getName(), sw.getVersion()));
}
if (artifactUploadState.isUploadCompleted()) {
minimizeButton.setEnabled(false);
}
}
}
private void setPopupProperties() {
setId(UIComponentIdProvider.UPLOAD_STATUS_POPUP_ID);
addStyleName(SPUIStyleDefinitions.UPLOAD_INFO);
setImmediate(true);
setResizable(false);
setDraggable(true);
setClosable(false);
setModal(true);
}
private void setGridColumnProperties() {
grid.getColumn(STATUS).setRenderer(new StatusRenderer());
grid.getColumn(PROGRESS).setRenderer(new ProgressBarRenderer());
grid.setColumnOrder(STATUS, PROGRESS, FILE_NAME, SPUILabelDefinitions.NAME_VERSION, REASON);
setColumnWidth();
grid.getColumn(SPUILabelDefinitions.NAME_VERSION).setHeaderCaption(i18n.getMessage("upload.swModuleTable.header"));
grid.setFrozenColumnCount(5);
}
private Grid createGrid() {
final 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() {
final 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, "");
uploadContainer.addContainerProperty(SPUILabelDefinitions.NAME_VERSION, 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() {
grid.getColumn(STATUS).setWidth(60);
grid.getColumn(PROGRESS).setWidth(150);
grid.getColumn(FILE_NAME).setWidth(200);
grid.getColumn(REASON).setWidth(290);
grid.getColumn(SPUILabelDefinitions.NAME_VERSION).setWidth(200);
}
private void resetColumnWidth() {
grid.getColumn(STATUS).setWidthUndefined();
grid.getColumn(PROGRESS).setWidthUndefined();
grid.getColumn(FILE_NAME).setWidthUndefined();
grid.getColumn(REASON).setWidthUndefined();
grid.getColumn(SPUILabelDefinitions.NAME_VERSION).setWidthUndefined();
}
private static class StatusRenderer extends HtmlRenderer {
private static final long serialVersionUID = -5365795450234970943L;
@Override
public JsonValue encode(final String value) {
String result;
switch (value) {
case "Finished":
result = "<div class=\"statusIconGreen\">" + FontAwesome.CHECK_CIRCLE.getHtml() + "</div>";
break;
case "Failed":
result = "<div class=\"statusIconRed\">" + FontAwesome.EXCLAMATION_CIRCLE.getHtml() + "</div>";
break;
default:
result = "<div class=\"statusIconActive\"></div>";
}
return super.encode(result);
}
}
/**
* Automatically close if not error has occured.
*/
void uploadSessionFinished() {
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.getNumberOfFilesActuallyUpload().intValue() == 0
&& artifactUploadState.getNumberOfFileUploadsFailed().intValue() == 0
&& !artifactUploadState.isStatusPopupMinimized()) {
openWindow();
}
if (!uploadAborted) {
minimizeButton.setEnabled(true);
closeButton.setEnabled(true);
artifactUploadState.setUploadCompleted(false);
}
}
void openWindow() {
UI.getCurrent().addWindow(this);
center();
}
void maximizeStatusPopup() {
openWindow();
restoreState();
}
@SuppressWarnings("unchecked")
private void uploadRecevied(final String filename, final SoftwareModule softwareModule) {
final Item item = uploads.addItem(getItemid(filename, softwareModule));
if (item != null) {
item.getItemProperty(FILE_NAME).setValue(filename);
item.getItemProperty(SPUILabelDefinitions.NAME_VERSION).setValue(
HawkbitCommonUtil.getFormattedNameVersion(softwareModule.getName(), softwareModule.getVersion()));
final UploadStatusObject uploadStatus = new UploadStatusObject(filename, softwareModule);
uploadStatus.setStatus("Active");
artifactUploadState.getUploadedFileStatusList().add(uploadStatus);
}
}
void uploadStarted(final String filename, final SoftwareModule softwareModule) {
grid.scrollTo(getItemid(filename, softwareModule));
}
void updateProgress(final String filename, final long readBytes, final long contentLength,
final SoftwareModule softwareModule) {
final Item item = uploads.getItem(getItemid(filename, softwareModule));
final double progress = (double) readBytes / (double) contentLength;
if (item != null) {
item.getItemProperty(PROGRESS).setValue(progress);
}
final List<UploadStatusObject> uploadStatusObjectList = artifactUploadState.getUploadedFileStatusList().stream()
.filter(e -> e.getFilename().equals(filename)).collect(Collectors.toList());
if (!uploadStatusObjectList.isEmpty()) {
final UploadStatusObject uploadStatusObject = uploadStatusObjectList.get(0);
uploadStatusObject.setProgress(progress);
}
}
/**
* Called when each file upload is success.
*
* @param filename
* of the uploaded file.
* @param softwareModule
* selected software module
*/
public void uploadSucceeded(final String filename, final SoftwareModule softwareModule) {
final Item item = uploads.getItem(getItemid(filename, softwareModule));
final String status = "Finished";
if (item != null) {
item.getItemProperty(STATUS).setValue(status);
}
final List<UploadStatusObject> uploadStatusObjectList = artifactUploadState.getUploadedFileStatusList().stream()
.filter(e -> e.getFilename().equals(filename)).collect(Collectors.toList());
if (!uploadStatusObjectList.isEmpty()) {
final UploadStatusObject uploadStatusObject = uploadStatusObjectList.get(0);
uploadStatusObject.setStatus(status);
uploadStatusObject.setProgress(1d);
}
}
void uploadFailed(final String filename, final String errorReason, final SoftwareModule softwareModule) {
errorOccured = true;
final String status = "Failed";
final Item item = uploads.getItem(getItemid(filename, softwareModule));
if (item != null) {
item.getItemProperty(REASON).setValue(errorReason);
item.getItemProperty(STATUS).setValue(status);
}
final List<UploadStatusObject> uploadStatusObjectList = artifactUploadState.getUploadedFileStatusList().stream()
.filter(e -> e.getFilename().equals(filename)).collect(Collectors.toList());
if (!uploadStatusObjectList.isEmpty()) {
final UploadStatusObject uploadStatusObject = uploadStatusObjectList.get(0);
uploadStatusObject.setStatus(status);
uploadStatusObject.setReason(errorReason);
}
}
protected void clearWindow() {
errorOccured = false;
uploads.removeAllItems();
setWindowMode(WindowMode.NORMAL);
setColumnWidth();
setPopupSizeInMinMode();
resizeButton.setIcon(FontAwesome.EXPAND);
this.close();
artifactUploadState.getUploadedFileStatusList().clear();
artifactUploadState.getNumberOfFileUploadsFailed().set(0);
}
private void setPopupSizeInMinMode() {
mainLayout.setWidth(900, Unit.PIXELS);
mainLayout.setHeight(510, Unit.PIXELS);
}
private Button getMinimizeButton() {
final Button minimizeBtn = SPUIComponentProvider.getButton(
UIComponentIdProvider.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(
UIComponentIdProvider.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(final ClickEvent event) {
if (FontAwesome.EXPAND.equals(event.getButton().getIcon())) {
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.getColumn(SPUILabelDefinitions.NAME_VERSION).setExpandRatio(4);
mainLayout.setSizeFull();
} else {
event.getButton().setIcon(FontAwesome.EXPAND);
setWindowMode(WindowMode.NORMAL);
setColumnWidth();
setPopupSizeInMinMode();
}
}
private void minimizeWindow() {
this.close();
artifactUploadState.setStatusPopupMinimized(true);
eventBus.publish(this, UploadArtifactUIEvent.MINIMIZED_STATUS_POPUP);
}
private Button getCloseButton() {
final Button closeBtn = SPUIComponentProvider.getButton(
UIComponentIdProvider.UPLOAD_STATUS_POPUP_CLOSE_BUTTON_ID, "", "", "", true, FontAwesome.TIMES,
SPUIButtonStyleSmallNoBorder.class);
closeBtn.addStyleName(ValoTheme.BUTTON_BORDERLESS);
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.getMessage("caption.confirm.abort.action"),
i18n.getMessage("message.abort.upload"), i18n.getMessage("button.ok"), i18n.getMessage("button.cancel"), ok -> {
if (ok) {
eventBus.publish(this, UploadStatusEventType.ABORT_UPLOAD);
uploadAborted = true;
errorOccured = true;
minimizeButton.setEnabled(false);
closeButton.setEnabled(false);
}
});
}
private String getItemid(final String filename, final SoftwareModule softwareModule) {
return new StringBuilder(filename).append(
HawkbitCommonUtil.getFormattedNameVersion(softwareModule.getName(), softwareModule.getVersion()))
.toString();
}
}

View File

@@ -1,101 +0,0 @@
/**
* 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;
import java.io.Serializable;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
/**
*
* Holds uploaded file status.Used to display the details in upload status
* popup.
*
*/
public class UploadStatusObject implements Serializable {
private static final long serialVersionUID = 1L;
private String status;
private Double progress;
private String filename;
private String reason;
private final SoftwareModule selectedSoftwareModule;
UploadStatusObject(final String fileName, final SoftwareModule selectedSoftwareModule) {
this.filename = fileName;
this.selectedSoftwareModule = selectedSoftwareModule;
}
public SoftwareModule getSelectedSoftwareModule() {
return selectedSoftwareModule;
}
public String getStatus() {
return status;
}
public void setStatus(final String status) {
this.status = status;
}
public Double getProgress() {
return progress;
}
public void setProgress(final Double progress) {
this.progress = progress;
}
public String getFilename() {
return filename;
}
public void setFilename(final String filename) {
this.filename = filename;
}
public String getReason() {
return reason;
}
public void setReason(final String reason) {
this.reason = reason;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((filename == null) ? 0 : filename.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final UploadStatusObject other = (UploadStatusObject) obj;
if (filename == null) {
if (other.filename != null) {
return false;
}
} else if (!filename.equals(other.filename)) {
return false;
}
return true;
}
}

View File

@@ -17,6 +17,7 @@ import com.vaadin.shared.ui.colorpicker.Color;
public final class ColorPickerConstants {
public static final String DEFAULT_COLOR = "rgb(44,151,32)";
public static final Color START_COLOR = new Color(0, 146, 58);
private ColorPickerConstants() {

View File

@@ -29,19 +29,23 @@ import com.vaadin.ui.components.colorpicker.ColorSelector;
*/
public class ColorPickerLayout extends GridLayout {
private static final long serialVersionUID = -7025970080613796692L;
private static final long serialVersionUID = 1L;
private SpColorPickerPreview selPreview;
private ColorPickerGradient colorSelect;
private Set<ColorSelector> selectors;
private Color selectedColor;
/** RGB color converter. */
private final Coordinates2Color rgbConverter = new CoordinatesToColor();
private Slider redSlider;
private Slider greenSlider;
private Slider blueSlider;
public ColorPickerLayout() {
@@ -80,7 +84,7 @@ public class ColorPickerLayout extends GridLayout {
selectors.add(colorSelect);
}
private Slider createRGBSlider(final String caption, final String styleName) {
private static Slider createRGBSlider(final String caption, final String styleName) {
final Slider slider = new Slider(caption, 0, 255);
slider.setImmediate(true);
slider.setWidth("150px");

View File

@@ -21,7 +21,7 @@ import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder;
import org.eclipse.hawkbit.ui.common.builder.WindowBuilder;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.customrenderers.renderers.HtmlButtonRenderer;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleNoBorder;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
@@ -280,9 +280,9 @@ public abstract class AbstractMetadataPopupLayout<E extends NamedVersionedEntity
final String key = (String) item.getItemProperty(KEY).getValue();
final ConfirmationDialog confirmDialog = new ConfirmationDialog(
i18n.getMessage("caption.metadata.delete.action.confirmbox"),
i18n.getMessage("message.confirm.delete.metadata", key), i18n.getMessage("button.ok"),
i18n.getMessage("button.cancel"), ok -> {
i18n.getMessage("caption.entity.delete.action.confirmbox"),
i18n.getMessage("message.confirm.delete.metadata", key), i18n.getMessage(SPUIDefinitions.BUTTON_OK),
i18n.getMessage(SPUIDefinitions.BUTTON_CANCEL), ok -> {
if (ok) {
handleOkDeleteMetadata(event, key);
}
@@ -322,8 +322,7 @@ public abstract class AbstractMetadataPopupLayout<E extends NamedVersionedEntity
private Button createAddIcon() {
addIcon = SPUIComponentProvider.getButton(UIComponentIdProvider.METADTA_ADD_ICON_ID,
i18n.getMessage("button.save"), null, null, false, FontAwesome.PLUS,
SPUIButtonStyleSmallNoBorder.class);
i18n.getMessage("button.save"), null, null, false, FontAwesome.PLUS, SPUIButtonStyleNoBorder.class);
addIcon.addClickListener(event -> onAdd());
return addIcon;
}

View File

@@ -22,7 +22,6 @@ import java.util.stream.Collectors;
import org.eclipse.hawkbit.ui.artifacts.smtable.SoftwareModuleAddUpdateWindow;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleNoBorderWithIcon;
import org.eclipse.hawkbit.ui.layouts.AbstractCreateUpdateTagLayout;
import org.eclipse.hawkbit.ui.management.targettable.TargetAddUpdateWindowLayout;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
@@ -88,8 +87,6 @@ public class CommonDialogWindow extends Window {
private HorizontalLayout buttonsLayout;
protected ValueChangeListener buttonEnableListener;
private final ClickListener cancelButtonClickListener;
private final ClickListener closeClickListener = this::onCloseEvent;
@@ -262,7 +259,11 @@ public class CommonDialogWindow extends Window {
cancelButton.addClickListener(closeClickListener);
}
protected void addComponentListeners() {
/**
* adds a listener to a component. Depending on the type of component a
* valueChange-, textChange- or itemSetChangeListener will be added.
*/
public void addComponentListeners() {
// avoid duplicate registration
removeListeners();
@@ -275,7 +276,6 @@ public class CommonDialogWindow extends Window {
((Table) field).addItemSetChangeListener(new ChangeListener(field));
}
field.addValueChangeListener(new ChangeListener(field));
}
}
@@ -438,8 +438,6 @@ public class CommonDialogWindow extends Window {
((TargetAddUpdateWindowLayout) content).getFormLayout().addComponent(mandatoryLabel);
} else if (content instanceof SoftwareModuleAddUpdateWindow) {
((SoftwareModuleAddUpdateWindow) content).getFormLayout().addComponent(mandatoryLabel);
} else if (content instanceof AbstractCreateUpdateTagLayout) {
((AbstractCreateUpdateTagLayout) content).getMainLayout().addComponent(mandatoryLabel);
}
mainLayout.addComponent(mandatoryLabel);

View File

@@ -8,12 +8,14 @@
*/
package org.eclipse.hawkbit.ui.common;
import org.eclipse.hawkbit.ui.common.confirmwindow.layout.ConfirmationTab;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleTiny;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.springframework.util.StringUtils;
import com.vaadin.event.ShortcutAction.KeyCode;
import com.vaadin.server.Resource;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.Alignment;
@@ -27,17 +29,44 @@ import com.vaadin.ui.Window;
import com.vaadin.ui.themes.ValoTheme;
/**
*
* module.
*
* Class for the confirmation dialog which pops up when deleting, assigning...
* entities.
*/
public class ConfirmationDialog implements Button.ClickListener {
private static final long serialVersionUID = 1L;
/** The confirmation callback. */
private transient ConfirmationDialogCallback callback;
private final Button okButton;
private final Window window;
/**
* Constructor for configuring confirmation dialog.
*
* @param caption
* the dialog caption.
* @param question
* the question.
* @param okLabel
* the Ok button label.
* @param cancelLabel
* the cancel button label.
* @param callback
* the callback.
* @param tab
* ConfirmationTab which contains more information about the
* action which has to be confirmed, e.g. maintenance window
* @param id
* the id of the confirmation window
*/
public ConfirmationDialog(final String caption, final String question, final String okLabel,
final String cancelLabel, final ConfirmationDialogCallback callback, final ConfirmationTab tab,
final String id) {
this(caption, question, okLabel, cancelLabel, callback, null, id, tab);
}
/**
* Constructor for configuring confirmation dialog.
*
@@ -54,7 +83,7 @@ public class ConfirmationDialog implements Button.ClickListener {
*/
public ConfirmationDialog(final String caption, final String question, final String okLabel,
final String cancelLabel, final ConfirmationDialogCallback callback) {
this(caption, question, okLabel, cancelLabel, callback, null, null);
this(caption, question, okLabel, cancelLabel, callback, null, null, null);
}
/**
@@ -75,7 +104,7 @@ public class ConfirmationDialog implements Button.ClickListener {
*/
public ConfirmationDialog(final String caption, final String question, final String okLabel,
final String cancelLabel, final ConfirmationDialogCallback callback, final String id) {
this(caption, question, okLabel, cancelLabel, callback, null, id);
this(caption, question, okLabel, cancelLabel, callback, null, id, null);
}
/**
@@ -96,7 +125,7 @@ public class ConfirmationDialog implements Button.ClickListener {
*/
public ConfirmationDialog(final String caption, final String question, final String okLabel,
final String cancelLabel, final ConfirmationDialogCallback callback, final Resource icon) {
this(caption, question, okLabel, cancelLabel, callback, icon, null);
this(caption, question, okLabel, cancelLabel, callback, icon, null, null);
}
/**
@@ -116,9 +145,13 @@ public class ConfirmationDialog implements Button.ClickListener {
* the icon of the dialog
* @param id
* the id of the confirmation dialog
* @param tab
* ConfirmationTab which contains more information about the
* action which has to be confirmed, e.g. maintenance window
*/
public ConfirmationDialog(final String caption, final String question, final String okLabel,
final String cancelLabel, final ConfirmationDialogCallback callback, final Resource icon, final String id) {
final String cancelLabel, final ConfirmationDialogCallback callback, final Resource icon, final String id,
final ConfirmationTab tab) {
window = new Window(caption);
if (!StringUtils.isEmpty(id)) {
window.setId(id);
@@ -129,29 +162,39 @@ public class ConfirmationDialog implements Button.ClickListener {
window.setIcon(icon);
}
okButton = SPUIComponentProvider.getButton(UIComponentIdProvider.OK_BUTTON, okLabel, "",
ValoTheme.BUTTON_PRIMARY, false, null, SPUIButtonStyleTiny.class);
okButton.addClickListener(this);
okButton = createOkButton(okLabel);
final Button cancelButton = SPUIComponentProvider.getButton(null, cancelLabel, "", null, false, null,
SPUIButtonStyleTiny.class);
cancelButton.addClickListener(this);
cancelButton.setId(UIComponentIdProvider.CANCEL_BUTTON);
final Button cancelButton = createCancelButton(cancelLabel);
window.setModal(true);
window.addStyleName(SPUIStyleDefinitions.CONFIRMBOX_WINDOW_SYLE);
window.addStyleName(SPUIStyleDefinitions.CONFIRMBOX_WINDOW_STYLE);
if (this.callback == null) {
this.callback = callback;
}
final VerticalLayout vLayout = new VerticalLayout();
if (question != null) {
final Label questionLbl = new Label(String.format("<p>%s</p>", question.replaceAll("\n", "<br/>")),
ContentMode.HTML);
questionLbl.addStyleName(SPUIStyleDefinitions.CONFIRMBOX_QUESTION_LABEL);
vLayout.addComponent(questionLbl);
vLayout.addComponent(createConfirmationQuestion(question));
}
if (tab != null) {
vLayout.addComponent(tab);
}
final HorizontalLayout hButtonLayout = createButtonLayout(cancelButton);
hButtonLayout.addStyleName("marginTop");
vLayout.addComponent(hButtonLayout);
vLayout.setComponentAlignment(hButtonLayout, Alignment.BOTTOM_CENTER);
window.setContent(vLayout);
window.setResizable(false);
}
private static Label createConfirmationQuestion(final String question) {
final Label questionLbl = new Label(String.format("<p>%s</p>", question.replaceAll("\n", "<br/>")),
ContentMode.HTML);
questionLbl.addStyleName(SPUIStyleDefinitions.CONFIRMBOX_QUESTION_LABEL);
return questionLbl;
}
private HorizontalLayout createButtonLayout(final Button cancelButton) {
final HorizontalLayout hButtonLayout = new HorizontalLayout();
hButtonLayout.setSpacing(true);
hButtonLayout.addComponent(okButton);
@@ -159,11 +202,23 @@ public class ConfirmationDialog implements Button.ClickListener {
hButtonLayout.setSizeUndefined();
hButtonLayout.setComponentAlignment(okButton, Alignment.TOP_CENTER);
hButtonLayout.setComponentAlignment(cancelButton, Alignment.TOP_CENTER);
return hButtonLayout;
}
vLayout.addComponent(hButtonLayout);
vLayout.setComponentAlignment(hButtonLayout, Alignment.BOTTOM_CENTER);
window.setContent(vLayout);
window.setResizable(false);
private Button createCancelButton(final String cancelLabel) {
final Button button = SPUIComponentProvider.getButton(UIComponentIdProvider.CANCEL_BUTTON, cancelLabel, "",
null, false, null, SPUIButtonStyleTiny.class);
button.addClickListener(this);
button.setClickShortcut(KeyCode.ESCAPE);
return button;
}
private Button createOkButton(final String okLabel) {
final Button button = SPUIComponentProvider.getButton(UIComponentIdProvider.OK_BUTTON, okLabel, "",
ValoTheme.BUTTON_PRIMARY, false, null, SPUIButtonStyleTiny.class);
button.addClickListener(this);
button.setClickShortcut(KeyCode.ENTER);
return button;
}
/**
@@ -180,11 +235,6 @@ public class ConfirmationDialog implements Button.ClickListener {
callback.response(event.getSource().equals(okButton));
}
/**
* Get the window which holds the confirmation dialog
*
* @return the window which holds the confirmation dialog
*/
public Window getWindow() {
return window;
}
@@ -203,4 +253,8 @@ public class ConfirmationDialog implements Button.ClickListener {
void response(boolean ok);
}
public Button getOkButton() {
return okButton;
}
}

View File

@@ -8,6 +8,8 @@
*/
package org.eclipse.hawkbit.ui.common.builder;
import org.springframework.util.StringUtils;
import com.vaadin.ui.Label;
import com.vaadin.ui.themes.ValoTheme;
@@ -17,6 +19,8 @@ import com.vaadin.ui.themes.ValoTheme;
*/
public class LabelBuilder {
private String caption;
private String name;
private String id;
@@ -25,7 +29,7 @@ public class LabelBuilder {
/**
* @param name
* the name to set
* the value to set
* @return builder
*/
public LabelBuilder name(final String name) {
@@ -33,6 +37,16 @@ public class LabelBuilder {
return this;
}
/**
* @param caption
* the caption to set
* @return builder
*/
public LabelBuilder caption(final String caption) {
this.caption = caption;
return this;
}
/**
* @param id
* the id to set
@@ -60,7 +74,6 @@ public class LabelBuilder {
*/
public Label buildCaptionLabel() {
final Label label = createLabel();
label.setValue(name);
label.addStyleName("header-caption");
return label;
}
@@ -75,6 +88,9 @@ public class LabelBuilder {
label.setImmediate(false);
label.setWidth("-1px");
label.setHeight("-1px");
if (StringUtils.hasText(caption)) {
label.setCaption(caption);
}
return label;
}

View File

@@ -1,153 +0,0 @@
/**
* 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.common.confirmwindow.layout;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.spring.events.EventBus;
import org.vaadin.spring.events.EventBus.UIEventBus;
import com.vaadin.server.FontAwesome;
import com.vaadin.ui.Accordion;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Label;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.ValoTheme;
/**
* Abstract layout of confirm actions window.
*
*/
public abstract class AbstractConfirmationWindowLayout extends VerticalLayout {
private static final long serialVersionUID = 1L;
private Label actionMessage;
private Accordion accordion;
private String consolidatedMessage;
protected VaadinMessageSource i18n;
protected transient EventBus.UIEventBus eventBus;
protected AbstractConfirmationWindowLayout(final VaadinMessageSource i18n, final UIEventBus eventBus) {
this.i18n = i18n;
this.eventBus = eventBus;
}
/**
* Initialize the confirmation window layout
*/
public void initialize() {
removeAllComponents();
consolidatedMessage = "";
createComponents();
buildLayout();
}
private void createComponents() {
createAccordian();
createActionMessgaeLabel();
}
private void createActionMessgaeLabel() {
actionMessage = new LabelBuilder().name("").id(UIComponentIdProvider.ACTION_LABEL).visible(false).buildLabel();
actionMessage.addStyleName(SPUIStyleDefinitions.CONFIRM_WINDOW_INFO_BOX);
}
private void createAccordian() {
accordion = new Accordion();
accordion.setSizeFull();
}
private void buildLayout() {
final Map<String, ConfirmationTab> confimrationTabs = getConfirmationTabs();
for (final Entry<String, ConfirmationTab> captionConfirmationTab : confimrationTabs.entrySet()) {
accordion.addTab(captionConfirmationTab.getValue(), captionConfirmationTab.getKey(), null);
}
final VerticalLayout confirmActionsLayout = new VerticalLayout();
confirmActionsLayout.addStyleName(SPUIStyleDefinitions.CONFIRM_WINDOW_ACCORDIAN);
confirmActionsLayout.setSpacing(false);
confirmActionsLayout.setMargin(false);
confirmActionsLayout.addComponent(actionMessage);
confirmActionsLayout.addComponent(accordion);
addComponent(confirmActionsLayout);
setComponentAlignment(confirmActionsLayout, Alignment.MIDDLE_CENTER);
setSpacing(false);
setMargin(false);
}
/**
* Add to the consolidated result message which will be displayed in the
* notification on closing the window. Each message that will be added in
* new line of previous messages using html <br>
*
* @param message
* to be added to the consolidated messages.
*/
public void addToConsolitatedMsg(final String message) {
if (consolidatedMessage != null && consolidatedMessage.length() > 0) {
consolidatedMessage = consolidatedMessage + "<br>";
}
consolidatedMessage = consolidatedMessage + message;
}
/**
* @param tab
*/
protected void removeCurrentTab(final ConfirmationTab tab) {
accordion.removeComponent(tab);
}
/**
*
* @param message
*/
protected void setActionMessage(final String message) {
actionMessage.setValue(message);
actionMessage.setVisible(true);
}
/**
* Get contents for each tab to be displayed in the accordian.
*
* @return map of caption and content for each tab.
*/
protected abstract Map<String, ConfirmationTab> getConfirmationTabs();
/**
* @return the consolidatedMessage
*/
public String getConsolidatedMessage() {
return consolidatedMessage;
}
protected Button createDiscardButton(final Object itemId, final ClickListener clickListener) {
final Button deletesDsIcon = SPUIComponentProvider.getButton("", "", SPUILabelDefinitions.DISCARD,
ValoTheme.BUTTON_TINY + " " + SPUIStyleDefinitions.REDICON, true, FontAwesome.REPLY,
SPUIButtonStyleSmallNoBorder.class);
deletesDsIcon.setData(itemId);
deletesDsIcon.setImmediate(true);
deletesDsIcon.addClickListener(clickListener);
return deletesDsIcon;
}
}

View File

@@ -8,144 +8,26 @@
*/
package org.eclipse.hawkbit.ui.common.confirmwindow.layout;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleTiny;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import com.vaadin.server.FontAwesome;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Table;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.ValoTheme;
/**
* Confirmation tab of confirmation window.
*/
public class ConfirmationTab extends VerticalLayout {
private static final long serialVersionUID = -5211351556595775554L;
private Table table;
private Button confirmAll;
private Button discardAll;
private static final long serialVersionUID = 1L;
/**
* Default constructor.
*/
public ConfirmationTab() {
createComponents();
buildLayout();
}
private void createComponents() {
// Create table
createTable();
// Create confirm all button
createConfirmAllButton();
// Create discard all button
createDiscardAllButton();
}
private void buildLayout() {
final HorizontalLayout btnLayout = new HorizontalLayout();
btnLayout.setSpacing(true);
btnLayout.addStyleName(SPUIStyleDefinitions.SP_ACCORDION_TAB_BTN);
btnLayout.addComponent(confirmAll);
btnLayout.setComponentAlignment(confirmAll, Alignment.MIDDLE_CENTER);
btnLayout.addComponent(discardAll);
btnLayout.setComponentAlignment(discardAll, Alignment.MIDDLE_CENTER);
setSizeFull();
setMargin(false);
setSpacing(false);
addComponent(table);
setComponentAlignment(table, Alignment.MIDDLE_CENTER);
addComponent(btnLayout);
setComponentAlignment(btnLayout, Alignment.MIDDLE_CENTER);
}
private void createDiscardAllButton() {
discardAll = SPUIComponentProvider.getButton(null, SPUILabelDefinitions.DISCARD_ALL, "", null, false, null,
SPUIButtonStyleTiny.class);
discardAll.setIcon(FontAwesome.REPLY);
}
private void createConfirmAllButton() {
confirmAll = SPUIComponentProvider.getButton(null, "", "", ValoTheme.BUTTON_PRIMARY, false, null,
SPUIButtonStyleTiny.class);
confirmAll.setIcon(FontAwesome.REPLY);
}
private void createTable() {
table = new Table();
table.setSizeFull();
table.setPageLength(SPUIDefinitions.ACCORDION_TAB_DETAILS_PAGE_LENGTH);
// Build Style
final StringBuilder style = new StringBuilder(ValoTheme.TABLE_COMPACT);
style.append(' ');
style.append(ValoTheme.TABLE_SMALL);
style.append(' ');
style.append(ValoTheme.TABLE_NO_VERTICAL_LINES);
// Set style
table.addStyleName(style.toString());
table.addStyleName("accordion-tab-table-style");
table.setImmediate(true);
}
/**
* @return the table
*/
public Table getTable() {
return table;
}
/**
* @param table
* the table to set
*/
public void setTable(final Table table) {
this.table = table;
}
/**
* @return the confirmAll
*/
public Button getConfirmAll() {
return confirmAll;
}
/**
* @param confirmAll
* the confirmAll to set
*/
public void setConfirmAll(final Button confirmAll) {
this.confirmAll = confirmAll;
}
/**
* @return the discardAll
*/
public Button getDiscardAll() {
return discardAll;
}
/**
* @param discardAll
* the discardAll to set
*/
public void setDiscardAll(final Button discardAll) {
this.discardAll = discardAll;
}
}

View File

@@ -103,6 +103,11 @@ public abstract class AbstractDistributionSetDetails
return UIComponentIdProvider.DS_EDIT_BUTTON;
}
@Override
protected String getMetadataButtonId() {
return UIComponentIdProvider.DS_METADATA_BUTTON;
}
@Override
protected boolean hasEditPermission() {
return getPermissionChecker().hasUpdateRepositoryPermission();

View File

@@ -10,7 +10,7 @@ package org.eclipse.hawkbit.ui.common.detailslayout;
import org.eclipse.hawkbit.repository.model.MetaData;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleNoBorder;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import com.vaadin.data.Item;
@@ -25,7 +25,9 @@ import com.vaadin.ui.themes.ValoTheme;
*/
public abstract class AbstractMetadataDetailsLayout extends Table {
protected static final String METADATA_KEY = "Key";
private static final long serialVersionUID = 1L;
private static final String METADATA_KEY = "Key";
protected static final int MAX_METADATA_QUERY = 500;
@@ -80,7 +82,7 @@ public abstract class AbstractMetadataDetailsLayout extends Table {
private Button customMetadataDetailButton(final String metadataKey) {
final Button viewIcon = SPUIComponentProvider.getButton(getDetailLinkId(metadataKey), metadataKey,
"View " + metadataKey + " Metadata details", null, false, null, SPUIButtonStyleSmallNoBorder.class);
"View " + metadataKey + " Metadata details", null, false, null, SPUIButtonStyleNoBorder.class);
viewIcon.setData(metadataKey);
viewIcon.addStyleName(ValoTheme.BUTTON_TINY + " " + ValoTheme.BUTTON_LINK + " " + "on-focus-no-border link"
+ " " + "text-style");

View File

@@ -34,4 +34,5 @@ public abstract class AbstractNamedVersionedEntityTableDetailsLayout<T extends N
return HawkbitCommonUtil.getFormattedNameVersion(getSelectedBaseEntity().getName(),
getSelectedBaseEntity().getVersion());
}
}

View File

@@ -81,7 +81,8 @@ public abstract class AbstractSoftwareModuleDetails
protected void onEdit(final ClickEvent event) {
final Window addSoftwareModule = softwareModuleAddUpdateWindow
.createUpdateSoftwareModuleWindow(getSelectedBaseEntityId());
addSoftwareModule.setCaption(getI18n().getMessage("upload.caption.update.swmodule"));
addSoftwareModule
.setCaption(getI18n().getMessage("caption.update", getI18n().getMessage("caption.software.module")));
UI.getCurrent().addWindow(addSoftwareModule);
addSoftwareModule.setVisible(Boolean.TRUE);
}
@@ -91,6 +92,11 @@ public abstract class AbstractSoftwareModuleDetails
return UIComponentIdProvider.UPLOAD_SW_MODULE_EDIT_BUTTON;
}
@Override
protected String getMetadataButtonId() {
return UIComponentIdProvider.UPLOAD_SW_MODULE_METADATA_BUTTON;
}
@Override
protected String getDefaultCaption() {
return getI18n().getMessage("upload.swModuleTable.header");

View File

@@ -17,7 +17,7 @@ import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.common.table.BaseUIEntityEvent;
import org.eclipse.hawkbit.ui.common.tagdetails.AbstractTagToken;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleNoBorder;
import org.eclipse.hawkbit.ui.management.state.ManagementUIState;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
@@ -71,6 +71,8 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
private final ManagementUIState managementUIState;
private HorizontalLayout nameEditLayout;
protected AbstractTableDetailsLayout(final VaadinMessageSource i18n, final UIEventBus eventBus,
final SpPermissionChecker permissionChecker, final ManagementUIState managementUIState) {
this.i18n = i18n;
@@ -227,21 +229,21 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
return managementUIState;
}
private void createComponents() {
protected void createComponents() {
caption = createHeaderCaption();
caption.setImmediate(true);
caption.setContentMode(ContentMode.HTML);
caption.setId(getDetailsHeaderCaptionId());
editButton = SPUIComponentProvider.getButton("", "", "", null, false, FontAwesome.PENCIL_SQUARE_O,
SPUIButtonStyleSmallNoBorder.class);
SPUIButtonStyleNoBorder.class);
editButton.setId(getEditButtonId());
editButton.addClickListener(this::onEdit);
editButton.setEnabled(false);
manageMetadataBtn = SPUIComponentProvider.getButton("", "", "", null, false, FontAwesome.LIST_ALT,
SPUIButtonStyleSmallNoBorder.class);
manageMetadataBtn.setId(getEditButtonId());
SPUIButtonStyleNoBorder.class);
manageMetadataBtn.setId(getMetadataButtonId());
manageMetadataBtn.setDescription(i18n.getMessage("tooltip.metadata.icon"));
manageMetadataBtn.addClickListener(this::showMetadata);
manageMetadataBtn.setEnabled(false);
@@ -254,8 +256,8 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
detailsTab.setId(getTabSheetId());
}
private void buildLayout() {
final HorizontalLayout nameEditLayout = new HorizontalLayout();
protected void buildLayout() {
nameEditLayout = new HorizontalLayout();
nameEditLayout.setWidth(100.0F, Unit.PERCENTAGE);
nameEditLayout.addComponent(caption);
nameEditLayout.setComponentAlignment(caption, Alignment.TOP_LEFT);
@@ -288,7 +290,7 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
* If there is no data in table (i.e. no row selected), then disable the
* edit button. If row is selected, enable edit button.
*/
private void populateData(final T selectedBaseEntity) {
protected void populateData(final T selectedBaseEntity) {
this.selectedBaseEntity = selectedBaseEntity;
editButton.setEnabled(selectedBaseEntity != null);
manageMetadataBtn.setEnabled(selectedBaseEntity != null);
@@ -335,6 +337,8 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
protected abstract String getEditButtonId();
protected abstract String getMetadataButtonId();
protected abstract boolean onLoadIsTableMaximized();
protected abstract String getTabSheetId();
@@ -349,4 +353,12 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
protected abstract void showMetadata(Button.ClickEvent event);
public HorizontalLayout getNameEditLayout() {
return nameEditLayout;
}
public Button getEditButton() {
return editButton;
}
}

View File

@@ -18,7 +18,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleNoBorder;
import org.eclipse.hawkbit.ui.distributions.event.DistributionsUIEvent;
import org.eclipse.hawkbit.ui.distributions.state.ManageDistUIState;
import org.eclipse.hawkbit.ui.management.event.DistributionTableEvent;
@@ -223,7 +223,7 @@ public class SoftwareModuleDetailsTable extends Table {
horizontalLayout.setSizeFull();
final Label softwareModule = HawkbitCommonUtil.getFormatedLabel("");
final Button reassignSoftModule = SPUIComponentProvider.getButton(sw.getName(), "", "", "", true,
FontAwesome.TIMES, SPUIButtonStyleSmallNoBorder.class);
FontAwesome.TIMES, SPUIButtonStyleNoBorder.class);
reassignSoftModule
.addClickListener(event -> unassignSW(event, distributionSet, alreadyAssignedSwModules));
final String softwareModNameVersion = HawkbitCommonUtil.getFormattedNameVersion(sw.getName(),

View File

@@ -0,0 +1,28 @@
/**
* 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.common.event;
/**
* Event which is thrown when menubar item in the filter header is chosen or
* modify modus is closed.
*
*/
public class DistributionSetTagFilterHeaderEvent extends FilterHeaderEvent {
/**
* Constructor
*
* @param filterHeaderEnum
* FilterHeaderEnum
*/
public DistributionSetTagFilterHeaderEvent(final FilterHeaderEnum filterHeaderEnum) {
super(filterHeaderEnum);
}
}

View File

@@ -0,0 +1,28 @@
/**
* 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.common.event;
/**
* Event which is thrown when menubar item in the filter header is chosen or
* modify modus is closed.
*
*/
public class DistributionSetTypeFilterHeaderEvent extends FilterHeaderEvent {
/**
* Constructor
*
* @param filterHeaderEnum
* FilterHeaderEnum
*/
public DistributionSetTypeFilterHeaderEvent(final FilterHeaderEnum filterHeaderEnum) {
super(filterHeaderEnum);
}
}

View File

@@ -0,0 +1,41 @@
/**
* 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.common.event;
/**
* Event class for the table header of the tags and types table. Event is fired
* when the edit or delete modus of a tag or type is closed by clicking on the
* cancel icon. The menubar for selecting a tag/type action is shown again.
*/
public class FilterHeaderEvent {
/**
* FilterHeaderEnum which describes the action to execute
*/
public enum FilterHeaderEnum {
SHOW_MENUBAR, SHOW_CANCEL_BUTTON
}
private final FilterHeaderEnum filterHeaderEnum;
/**
* Constructor
*
* @param filterHeaderEnum
* Enum which describes the action to execute
*/
public FilterHeaderEvent(final FilterHeaderEnum filterHeaderEnum) {
this.filterHeaderEnum = filterHeaderEnum;
}
public FilterHeaderEnum getFilterHeaderEnum() {
return filterHeaderEnum;
}
}

View File

@@ -0,0 +1,28 @@
/**
* 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.common.event;
/**
* Event which is thrown when menubar item in the filter header is chosen or
* modify modus is closed.
*
*/
public class SoftwareModuleTypeFilterHeaderEvent extends FilterHeaderEvent {
/**
* Constructor
*
* @param filterHeaderEnum
* FilterHeaderEnum
*/
public SoftwareModuleTypeFilterHeaderEvent(final FilterHeaderEnum filterHeaderEnum) {
super(filterHeaderEnum);
}
}

View File

@@ -0,0 +1,28 @@
/**
* 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.common.event;
/**
* Event which is thrown when menubar item in the filter header is chosen or
* modify modus is closed.
*
*/
public class TargetTagFilterHeaderEvent extends FilterHeaderEvent {
/**
* Constructor
*
* @param filterHeaderEnum
* FilterHeaderEnum
*/
public TargetTagFilterHeaderEvent(final FilterHeaderEnum filterHeaderEnum) {
super(filterHeaderEnum);
}
}

View File

@@ -11,13 +11,20 @@ package org.eclipse.hawkbit.ui.common.filterlayout;
import static org.eclipse.hawkbit.ui.utils.SPUIDefinitions.NO_TAG_BUTTON_ID;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.hawkbit.ui.common.ConfirmationDialog;
import org.eclipse.hawkbit.ui.common.event.FilterHeaderEvent;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleNoBorder;
import org.eclipse.hawkbit.ui.decorators.SPUITagButtonStyle;
import org.eclipse.hawkbit.ui.management.tag.TagIdName;
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.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.springframework.util.StringUtils;
import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer;
import org.vaadin.spring.events.EventBus;
@@ -27,9 +34,14 @@ import com.vaadin.data.Item;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.server.FontAwesome;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.DragAndDropWrapper;
import com.vaadin.ui.DragAndDropWrapper.DragStartMode;
import com.vaadin.ui.Table;
import com.vaadin.ui.UI;
import com.vaadin.ui.Window;
import com.vaadin.ui.Window.CloseEvent;
import com.vaadin.ui.Window.CloseListener;
import com.vaadin.ui.themes.ValoTheme;
/**
@@ -37,20 +49,22 @@ import com.vaadin.ui.themes.ValoTheme;
*/
public abstract class AbstractFilterButtons extends Table {
private static final long serialVersionUID = 7783305719009746375L;
private static final long serialVersionUID = 1L;
private static final String DEFAULT_GREEN = "rgb(44,151,32)";
protected static final String DEFAULT_GREEN = "rgb(44,151,32)";
protected static final String FILTER_BUTTON_COLUMN = "filterButton";
protected transient EventBus.UIEventBus eventBus;
private final transient EventBus.UIEventBus eventBus;
protected final AbstractFilterButtonClickBehaviour filterButtonClickBehaviour;
private final AbstractFilterButtonClickBehaviour filterButtonClickBehaviour;
private final VaadinMessageSource i18n;
protected AbstractFilterButtons(final UIEventBus eventBus,
final AbstractFilterButtonClickBehaviour filterButtonClickBehaviour) {
final AbstractFilterButtonClickBehaviour filterButtonClickBehaviour, final VaadinMessageSource i18n) {
this.eventBus = eventBus;
this.i18n = i18n;
this.filterButtonClickBehaviour = filterButtonClickBehaviour;
createTable();
if (doSubscribeToEventBus()) {
@@ -77,8 +91,8 @@ public abstract class AbstractFilterButtons extends Table {
addColumn();
setTableVisibleColumns();
setDragMode(TableDragMode.NONE);
setSelectable(false);
setSizeFull();
setSelectable(false);
}
private void setStyle() {
@@ -101,6 +115,95 @@ public abstract class AbstractFilterButtons extends Table {
addGeneratedColumn(FILTER_BUTTON_COLUMN, (source, itemId, columnId) -> addGeneratedCell(itemId));
}
/**
* Insert the update icons next to the filter tags in target, distribution
* and software module tags/types tables
*/
public void addUpdateColumn() {
if (alreadyContainsColumn(SPUIDefinitions.UPDATE_FILTER_BUTTON_COLUMN)) {
return;
}
deleteColumnIfVisible(SPUIDefinitions.DELETE_FILTER_BUTTON_COLUMN);
addGeneratedColumn(SPUIDefinitions.UPDATE_FILTER_BUTTON_COLUMN,
(source, itemId, columnId) -> addUpdateCell(itemId));
}
/**
* Insert the delete icons next to the filter tags in target, distribution
* and software module tags/types tables
*/
public void addDeleteColumn() {
if (alreadyContainsColumn(SPUIDefinitions.DELETE_FILTER_BUTTON_COLUMN)) {
return;
}
deleteColumnIfVisible(SPUIDefinitions.UPDATE_FILTER_BUTTON_COLUMN);
addGeneratedColumn(SPUIDefinitions.DELETE_FILTER_BUTTON_COLUMN,
(source, itemId, columnId) -> addDeleteCell(itemId));
}
/**
* Removes the edit and delete icon next to the filter tags in target,
* distribution and software module tags/types tables, when the edit/delete
* action is executed or cancelled
*/
public void removeUpdateAndDeleteColumn() {
removeGeneratedColumn(SPUIDefinitions.UPDATE_FILTER_BUTTON_COLUMN);
removeGeneratedColumn(SPUIDefinitions.DELETE_FILTER_BUTTON_COLUMN);
}
private List<Object> getVisibleColumnsAsList() {
return Arrays.asList(getVisibleColumns());
}
private void deleteColumnIfVisible(final String columnName) {
final List<Object> columns = getVisibleColumnsAsList();
if (columns.contains(columnName)) {
removeGeneratedColumn(columnName);
}
}
private boolean alreadyContainsColumn(final String columnName) {
return getVisibleColumnsAsList().contains(columnName);
}
private Object addDeleteCell(final Object itemId) {
if (itemId instanceof TagIdName && SPUIDefinitions.NO_TAG.equals(((TagIdName) itemId).getName())) {
return null;
}
final Button deleteButton = SPUIComponentProvider.getButton("", "", "", "", true, FontAwesome.TRASH_O,
SPUIButtonStyleNoBorder.class);
if (itemId instanceof TagIdName) {
deleteButton.setId(UIComponentIdProvider.DELETE_TAG_ID + ((TagIdName) itemId).getName());
} else {
deleteButton.setId(UIComponentIdProvider.DELETE_TAG_ID + itemId.toString());
}
deleteButton.setDescription(SPUIDefinitions.DELETE);
deleteButton.addClickListener(this::addDeleteButtonClickListener);
return deleteButton;
}
private Button addUpdateCell(final Object itemId) {
if (itemId instanceof TagIdName && SPUIDefinitions.NO_TAG.equals(((TagIdName) itemId).getName())) {
return null;
}
final Button editButton = SPUIComponentProvider.getButton("", "", "", "", true, FontAwesome.EDIT,
SPUIButtonStyleNoBorder.class);
if (itemId instanceof TagIdName) {
editButton.setId(UIComponentIdProvider.UPDATE_TAG_ID + ((TagIdName) itemId).getName());
} else {
editButton.setId(UIComponentIdProvider.UPDATE_TAG_ID + itemId.toString());
}
editButton.setDescription(SPUIDefinitions.EDIT);
editButton.addClickListener(this::addEditButtonClickListener);
return editButton;
}
protected abstract void addEditButtonClickListener(final ClickEvent event);
protected abstract void addDeleteButtonClickListener(final ClickEvent event);
private DragAndDropWrapper addGeneratedCell(final Object itemId) {
final Item item = getItem(itemId);
@@ -115,7 +218,6 @@ public abstract class AbstractFilterButtons extends Table {
if ((NO_TAG_BUTTON_ID.equals(typeButton.getData()) && isNoTagStateSelected())
|| (id != null && isClickedByDefault(name))) {
filterButtonClickBehaviour.setDefaultClickedButton(typeButton);
}
@@ -149,7 +251,7 @@ public abstract class AbstractFilterButtons extends Table {
columnIds.add(FILTER_BUTTON_COLUMN);
setVisibleColumns(columnIds.toArray());
setColumnHeaderMode(ColumnHeaderMode.HIDDEN);
setColumnWidth(FILTER_BUTTON_COLUMN, 137);
setColumnWidth(FILTER_BUTTON_COLUMN, 120);
}
private Button createFilterButton(final Long id, final String name, final String description, final String color,
@@ -187,10 +289,61 @@ public abstract class AbstractFilterButtons extends Table {
return caption.toString();
}
protected void refreshTable() {
setContainerDataSource(createButtonsLazyQueryContainer());
protected String getEntityId(final ClickEvent event) {
final String buttonId = event.getButton().getId();
if (!StringUtils.hasText(buttonId)) {
return "";
}
if (buttonId.startsWith(UIComponentIdProvider.UPDATE_TAG_ID)) {
return buttonId.substring(UIComponentIdProvider.UPDATE_TAG_ID.length());
}
if (buttonId.startsWith(UIComponentIdProvider.DELETE_TAG_ID)) {
return buttonId.substring(UIComponentIdProvider.DELETE_TAG_ID.length());
}
return "";
}
/**
* Refreshes the tags tables
*/
public void refreshTable() {
setContainerDataSource(createButtonsLazyQueryContainer());
removeUpdateAndDeleteColumn();
}
protected void openConfirmationWindowForDeletion(final String entityToDelete, final String entityName,
final FilterHeaderEvent event) {
final ConfirmationDialog confirmDialog = new ConfirmationDialog(
i18n.getMessage("caption.entity.delete.action.confirmbox"),
i18n.getMessage("message.confirm.delete.entity", entityName.toLowerCase(),
entityToDelete.substring(entityToDelete.indexOf('.') + 1), ""),
i18n.getMessage(SPUIDefinitions.BUTTON_OK), i18n.getMessage(SPUIDefinitions.BUTTON_CANCEL), ok -> {
if (ok) {
deleteEntity(entityToDelete);
} else {
removeUpdateAndDeleteColumn();
getEventBus().publish(this, event);
}
});
confirmDialog.getWindow().addCloseListener(getCloseListenerForEditAndDeleteTag(event));
UI.getCurrent().addWindow(confirmDialog.getWindow());
confirmDialog.getWindow().bringToFront();
}
protected CloseListener getCloseListenerForEditAndDeleteTag(final FilterHeaderEvent event) {
return new Window.CloseListener() {
private static final long serialVersionUID = 1L;
@Override
public void windowClose(final CloseEvent e) {
removeUpdateAndDeleteColumn();
getEventBus().publish(this, event);
}
};
}
protected abstract void deleteEntity(String entityToDelete);
/**
* Id of the buttons table to be used in test cases.
*
@@ -243,4 +396,17 @@ public abstract class AbstractFilterButtons extends Table {
* @return button wrapper info.
*/
protected abstract String getButtonWrapperData();
protected EventBus.UIEventBus getEventBus() {
return eventBus;
}
protected VaadinMessageSource getI18n() {
return i18n;
}
protected AbstractFilterButtonClickBehaviour getFilterButtonClickBehaviour() {
return filterButtonClickBehaviour;
}
}

View File

@@ -10,9 +10,13 @@ package org.eclipse.hawkbit.ui.common.filterlayout;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
import org.eclipse.hawkbit.ui.common.event.FilterHeaderEvent;
import org.eclipse.hawkbit.ui.common.event.FilterHeaderEvent.FilterHeaderEnum;
import org.eclipse.hawkbit.ui.components.ConfigMenuBar;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleNoBorder;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.spring.events.EventBus;
import org.vaadin.spring.events.EventBus.UIEventBus;
@@ -20,8 +24,10 @@ import org.vaadin.spring.events.EventBus.UIEventBus;
import com.vaadin.server.FontAwesome;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.MenuBar.Command;
import com.vaadin.ui.VerticalLayout;
/**
@@ -29,61 +35,130 @@ import com.vaadin.ui.VerticalLayout;
*/
public abstract class AbstractFilterHeader extends VerticalLayout {
private static final long serialVersionUID = -1388340600522323332L;
private static final long serialVersionUID = 1L;
protected SpPermissionChecker permChecker;
private final SpPermissionChecker permChecker;
protected transient EventBus.UIEventBus eventBus;
private final transient EventBus.UIEventBus eventBus;
private Label title;
private Button config;
private Button hideIcon;
protected final VaadinMessageSource i18n;
private ConfigMenuBar menu;
protected AbstractFilterHeader(final SpPermissionChecker permChecker, final UIEventBus eventBus, final VaadinMessageSource i18n) {
private final VaadinMessageSource i18n;
private HorizontalLayout typeHeaderLayout;
private Button cancelTagButton;
protected AbstractFilterHeader(final SpPermissionChecker permChecker, final UIEventBus eventBus,
final VaadinMessageSource i18n) {
this.permChecker = permChecker;
this.eventBus = eventBus;
this.i18n = i18n;
createComponents();
buildLayout();
if (doSubscribeToEventBus()) {
eventBus.subscribe(this);
}
}
/**
* Create required components.
* Subscribes the view to the eventBus. Method has to be overriden (return
* false) if the view does not contain any listener to avoid Vaadin blowing
* up our logs with warnings.
*/
protected boolean doSubscribeToEventBus() {
return true;
}
protected void removeMenuBarAndAddCancelButton() {
typeHeaderLayout.removeComponent(menu);
typeHeaderLayout.addComponent(createCancelButtonForUpdateOrDeleteTag(), 1);
}
private Button createCancelButtonForUpdateOrDeleteTag() {
cancelTagButton = SPUIComponentProvider.getButton(UIComponentIdProvider.CANCEL_UPDATE_TAG_ID, "", "", null,
false, FontAwesome.TIMES_CIRCLE, SPUIButtonStyleNoBorder.class);
cancelTagButton.addClickListener(this::cancelUpdateOrDeleteTag);
return cancelTagButton;
}
@SuppressWarnings("squid:S1172")
protected void cancelUpdateOrDeleteTag(final ClickEvent event) {
removeCancelButtonAndAddMenuBar();
}
private void createComponents() {
title = createHeaderCaption();
if (hasCreateUpdatePermission() && isAddTagRequired()) {
config = SPUIComponentProvider.getButton(getConfigureFilterButtonId(), "", "", "", true, FontAwesome.COG,
SPUIButtonStyleSmallNoBorder.class);
config.addClickListener(this::settingsIconClicked);
if (isAddTagRequired()) {
menu = new ConfigMenuBar(permChecker.hasCreateRepositoryPermission(),
permChecker.hasUpdateRepositoryPermission(), permChecker.hasDeleteRepositoryPermission(),
getAddButtonCommand(), getUpdateButtonCommand(), getDeleteButtonCommand(), getMenuBarId());
}
hideIcon = SPUIComponentProvider.getButton(getHideButtonId(), "", "", "", true, FontAwesome.TIMES,
SPUIButtonStyleSmallNoBorder.class);
SPUIButtonStyleNoBorder.class);
hideIcon.addClickListener(event -> hideFilterButtonLayout());
}
protected void processFilterHeaderEvent(final FilterHeaderEvent event) {
if (FilterHeaderEnum.SHOW_MENUBAR == event.getFilterHeaderEnum()
&& typeHeaderLayout.getComponent(1).equals(cancelTagButton)) {
removeCancelButtonAndAddMenuBar();
} else if (FilterHeaderEnum.SHOW_CANCEL_BUTTON == event.getFilterHeaderEnum()) {
removeMenuBarAndAddCancelButton();
}
}
/**
* Build layout.
* Returns the id for the menubar element for configuring tags and types
*
* @return String with id
*/
protected abstract String getMenuBarId();
/**
* Command which should be executed when clicking on the delete tag button
* in the menubar
*
* @return Command
*/
protected abstract Command getDeleteButtonCommand();
/**
* Command which should be executed when clicking on the update tag button
* in the menubar
*
* @return Command
*/
protected abstract Command getUpdateButtonCommand();
/**
* Command which should be executed when clicking on the create tag button
* in the menubar
*
* @return Command
*/
protected abstract Command getAddButtonCommand();
private void buildLayout() {
setStyleName("filter-btns-header-layout");
final HorizontalLayout typeHeaderLayout = new HorizontalLayout();
typeHeaderLayout.setWidth(100.0f, Unit.PERCENTAGE);
typeHeaderLayout = new HorizontalLayout();
typeHeaderLayout.setHeight(32, Unit.PIXELS);
typeHeaderLayout.setWidth(100.0F, Unit.PERCENTAGE);
typeHeaderLayout.addComponentAsFirst(title);
typeHeaderLayout.addStyleName(SPUIStyleDefinitions.WIDGET_TITLE);
typeHeaderLayout.setComponentAlignment(title, Alignment.TOP_LEFT);
if (config != null && hasCreateUpdatePermission()) {
typeHeaderLayout.addComponent(config);
typeHeaderLayout.setComponentAlignment(config, Alignment.TOP_RIGHT);
if (menu != null) {
typeHeaderLayout.addComponent(menu);
typeHeaderLayout.setComponentAlignment(menu, Alignment.TOP_RIGHT);
}
typeHeaderLayout.addComponent(hideIcon);
typeHeaderLayout.setComponentAlignment(hideIcon, Alignment.TOP_RIGHT);
typeHeaderLayout.setExpandRatio(title, 1.0f);
typeHeaderLayout.setExpandRatio(title, 1.0F);
addComponent(typeHeaderLayout);
}
@@ -91,18 +166,17 @@ public abstract class AbstractFilterHeader extends VerticalLayout {
return new LabelBuilder().name(getTitle()).buildCaptionLabel();
}
/**
*
* @return
*/
protected abstract String getHideButtonId();
protected void removeCancelButtonAndAddMenuBar() {
typeHeaderLayout.removeComponent(cancelTagButton);
typeHeaderLayout.addComponent(menu, 1);
}
/**
* Check if user is authorized for this action.
* Returns the id of the hide filter button
*
* @return true if user has permission otherwise false.
* @return String containing the id
*/
protected abstract boolean hasCreateUpdatePermission();
protected abstract String getHideButtonId();
/**
* Get the title to be displayed on the header of filter button layout.
@@ -111,14 +185,6 @@ public abstract class AbstractFilterHeader extends VerticalLayout {
*/
protected abstract String getTitle();
/**
* This method will be called when settings icon (or) clicked on the header.
*
* @param event
* reference of {@link Button.ClicEvent}.
*/
protected abstract void settingsIconClicked(final Button.ClickEvent event);
/**
* Space required to show drop hits in the filter layout header.
*
@@ -137,8 +203,27 @@ public abstract class AbstractFilterHeader extends VerticalLayout {
protected abstract String getConfigureFilterButtonId();
/**
* @return
* Returns the information if the icon for configuring tags should be
* visible
*
* @return boolean
*/
protected abstract boolean isAddTagRequired();
protected SpPermissionChecker getPermChecker() {
return permChecker;
}
protected EventBus.UIEventBus getEventBus() {
return eventBus;
}
protected VaadinMessageSource getI18n() {
return i18n;
}
protected HorizontalLayout getTypeHeaderLayout() {
return typeHeaderLayout;
}
}

View File

@@ -9,6 +9,7 @@
package org.eclipse.hawkbit.ui.common.filterlayout;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.vaadin.spring.events.EventBus.UIEventBus;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.VerticalLayout;
@@ -18,16 +19,21 @@ import com.vaadin.ui.VerticalLayout;
*/
public abstract class AbstractFilterLayout extends VerticalLayout {
private static final long serialVersionUID = 9190616426688385851L;
private static final long serialVersionUID = 1L;
private final AbstractFilterHeader filterHeader;
private final AbstractFilterButtons filterButtons;
protected AbstractFilterLayout(final AbstractFilterHeader filterHeader, final AbstractFilterButtons filterButtons) {
private final transient UIEventBus eventBus;
protected AbstractFilterLayout(final AbstractFilterHeader filterHeader, final AbstractFilterButtons filterButtons,
final UIEventBus eventBus) {
this.filterHeader = filterHeader;
this.filterButtons = filterButtons;
this.eventBus = eventBus;
buildLayout();
eventBus.subscribe(this);
}
private void buildLayout() {
@@ -65,4 +71,9 @@ public abstract class AbstractFilterLayout extends VerticalLayout {
* @return true if filter is cleaned before.
*/
public abstract Boolean onLoadIsTypeFilterIsClosed();
public UIEventBus getEventBus() {
return eventBus;
}
}

View File

@@ -1,397 +0,0 @@
/**
* 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.common.footer;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.common.builder.WindowBuilder;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmall;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.spring.events.EventBus;
import org.vaadin.spring.events.EventBus.UIEventBus;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
import com.vaadin.server.FontAwesome;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component;
import com.vaadin.ui.DragAndDropWrapper;
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.themes.ValoTheme;
/**
* Parent class for footer layout.
*/
public abstract class AbstractDeleteActionsLayout extends VerticalLayout implements DropHandler {
private static final long serialVersionUID = 1L;
protected VaadinMessageSource i18n;
protected SpPermissionChecker permChecker;
protected transient EventBus.UIEventBus eventBus;
protected UINotification notification;
private DragAndDropWrapper deleteWrapper;
private Button noActionBtn;
private Window unsavedActionsWindow;
private Button bulkUploadStatusButton;
protected AbstractDeleteActionsLayout(final VaadinMessageSource i18n, final SpPermissionChecker permChecker,
final UIEventBus eventBus, final UINotification notification) {
this.i18n = i18n;
this.permChecker = permChecker;
this.eventBus = eventBus;
this.notification = notification;
if (doSubscribeToEventBus()) {
eventBus.subscribe(this);
}
}
/**
* Subscribes the view to the eventBus. Method has to be overriden (return
* false) if the view does not contain any listener to avoid Vaadin blowing
* up our logs with warnings.
*/
protected boolean doSubscribeToEventBus() {
return true;
}
protected void init() {
if (hasCountMessage() || hasDeletePermission() || hasUpdatePermission() || hasBulkUploadPermission()) {
createComponents();
buildLayout();
reload();
}
}
protected void reload() {
restoreActionCount();
restoreBulkUploadStatusCount();
}
protected void createComponents() {
if (hasDeletePermission()) {
deleteWrapper = createDeleteWrapperLayout();
}
if (hasDeletePermission() || hasUpdatePermission()) {
noActionBtn = createActionsButton();
}
if (hasBulkUploadPermission()) {
bulkUploadStatusButton = createBulkUploadStatusButton();
}
}
protected void buildLayout() {
final HorizontalLayout dropHintLayout = new HorizontalLayout();
if (hasCountMessage()) {
dropHintLayout.addComponent(getCountMessageLabel());
}
final HorizontalLayout hLayout = new HorizontalLayout();
hLayout.setId(UIComponentIdProvider.ACTION_BUTTON_LAYOUT);
hLayout.setSpacing(true);
hLayout.setSizeUndefined();
if (deleteWrapper != null) {
hLayout.addComponent(deleteWrapper);
hLayout.setComponentAlignment(deleteWrapper, Alignment.BOTTOM_LEFT);
}
if (noActionBtn != null) {
hLayout.addComponent(noActionBtn);
hLayout.setComponentAlignment(noActionBtn, Alignment.BOTTOM_LEFT);
}
if (bulkUploadStatusButton != null) {
hLayout.addComponent(bulkUploadStatusButton);
hLayout.setComponentAlignment(bulkUploadStatusButton, Alignment.BOTTOM_LEFT);
}
if (dropHintLayout.getComponentCount() > 0) {
addComponent(dropHintLayout);
setComponentAlignment(dropHintLayout, Alignment.BOTTOM_CENTER);
}
if (hLayout.getComponentCount() > 0) {
addComponent(hLayout);
setComponentAlignment(hLayout, Alignment.BOTTOM_CENTER);
}
setStyleName(SPUIStyleDefinitions.FOOTER_LAYOUT);
setWidth("100%");
}
private DragAndDropWrapper createDeleteWrapperLayout() {
final Button dropToDelete = new Button(i18n.getMessage("label.components.drop.area"));
dropToDelete.setCaptionAsHtml(true);
dropToDelete.setIcon(FontAwesome.TRASH_O);
dropToDelete.addStyleName(ValoTheme.BUTTON_BORDERLESS);
dropToDelete.addStyleName("drop-to-delete-button");
dropToDelete.addStyleName(SPUIStyleDefinitions.ACTION_BUTTON);
dropToDelete.addStyleName(SPUIStyleDefinitions.DEL_ACTION_BUTTON);
dropToDelete.addStyleName("delete-icon");
final DragAndDropWrapper wrapper = new DragAndDropWrapper(dropToDelete);
wrapper.setStyleName(ValoTheme.BUTTON_PRIMARY);
wrapper.setId(getDeleteAreaId());
wrapper.setDropHandler(this);
wrapper.addStyleName("delete-button-border");
return wrapper;
}
private Button createActionsButton() {
final Button button = SPUIComponentProvider.getButton(UIComponentIdProvider.PENDING_ACTION_BUTTON,
getNoActionsButtonLabel(), "", "", false, FontAwesome.BELL, SPUIButtonStyleSmall.class);
button.setStyleName(SPUIStyleDefinitions.ACTION_BUTTON);
button.addStyleName(SPUIStyleDefinitions.DEL_ACTION_BUTTON);
button.addClickListener(event -> actionButtonClicked());
button.setHtmlContentAllowed(true);
return button;
}
private Button createBulkUploadStatusButton() {
final Button button = SPUIComponentProvider.getButton(UIComponentIdProvider.BULK_UPLOAD_STATUS_BUTTON, "", "",
"", false, null, SPUIButtonStyleSmall.class);
button.setStyleName(SPUIStyleDefinitions.ACTION_BUTTON);
button.addStyleName(SPUIStyleDefinitions.UPLOAD_PROGRESS_INDICATOR_STYLE);
button.setWidth("100px");
button.setHtmlContentAllowed(true);
button.addClickListener(event -> onClickBulkUploadNotificationButton());
button.setVisible(false);
return button;
}
private void onClickBulkUploadNotificationButton() {
hideBulkUploadStatusButton();
showBulkUploadWindow();
}
protected void setUploadStatusButtonCaption(final int count) {
if (bulkUploadStatusButton == null) {
return;
}
bulkUploadStatusButton.setCaption("<div class='unread'>" + count + "</div>");
}
protected void enableBulkUploadStatusButton() {
if (bulkUploadStatusButton == null) {
return;
}
bulkUploadStatusButton.setVisible(true);
}
protected void updateUploadBtnIconToComplete() {
if (bulkUploadStatusButton == null) {
return;
}
bulkUploadStatusButton.removeStyleName(SPUIStyleDefinitions.UPLOAD_PROGRESS_INDICATOR_STYLE);
bulkUploadStatusButton.setIcon(FontAwesome.UPLOAD);
}
protected void updateUploadBtnIconToProgressIndicator() {
if (bulkUploadStatusButton == null) {
return;
}
bulkUploadStatusButton.addStyleName(SPUIStyleDefinitions.UPLOAD_PROGRESS_INDICATOR_STYLE);
bulkUploadStatusButton.setIcon(null);
}
protected void actionButtonClicked() {
if (!hasUnsavedActions()) {
return;
}
unsavedActionsWindow = new WindowBuilder(SPUIDefinitions.CONFIRMATION_WINDOW)
.caption(getUnsavedActionsWindowCaption()).id(UIComponentIdProvider.CONFIRMATION_POPUP_ID)
.content(getUnsavedActionsWindowContent()).buildWindow();
unsavedActionsWindow.addCloseListener(event -> unsavedActionsWindowClosed());
UI.getCurrent().addWindow(unsavedActionsWindow);
}
/**
* It will close the unsaved actions window.
*/
protected void closeUnsavedActionsWindow() {
UI.getCurrent().removeWindow(unsavedActionsWindow);
}
@Override
public AcceptCriterion getAcceptCriterion() {
return getDeleteLayoutAcceptCriteria();
}
@Override
public void drop(final DragAndDropEvent event) {
processDroppedComponent(event);
}
/**
* Update the pending actions count.
*
* @param newCount
* new count value.
*/
protected void updateActionsCount(final int newCount) {
if (noActionBtn != null) {
if (newCount > 0) {
noActionBtn.setCaption(getActionsButtonLabel() + "<div class='unread'>" + newCount + "</div>");
} else {
noActionBtn.setCaption(getNoActionsButtonLabel());
}
}
}
protected void hideBulkUploadStatusButton() {
if (null != bulkUploadStatusButton) {
bulkUploadStatusButton.setCaption(null);
bulkUploadStatusButton.setVisible(false);
}
}
/**
*
* @return true if the count label is displayed; false is not displayed
*/
protected boolean hasCountMessage() {
return false;
}
/**
*
* @return the count message label
*/
protected Label getCountMessageLabel() {
return null;
}
/**
* @return true if bulk upload is allowed and has required create
* permissions.
*/
protected boolean hasBulkUploadPermission() {
// can be overriden
return false;
}
protected void showBulkUploadWindow() {
// can be overriden
}
/**
* restore the upload status count.
*/
protected void restoreBulkUploadStatusCount() {
// can be overriden
}
/**
* Check if user has delete permission.
*
* @return true if user has permission, otherwise return false.
*/
protected abstract boolean hasDeletePermission();
/**
* Check if user has update permission.
*
* @return true if user has permission, otherwise return false.
*/
protected abstract boolean hasUpdatePermission();
/**
* Get label for delete drop area.
*
* @return label of delete drop area.
*/
protected abstract String getDeleteAreaLabel();
/**
* Get Id of the delete drop area.
*
* @return Id of the delete drop area.
*/
protected abstract String getDeleteAreaId();
/**
* Get the accept criteria for the delete layout drop.
*
* @return reference of {@link AcceptCriteria}
*/
protected abstract AcceptCriterion getDeleteLayoutAcceptCriteria();
/**
* Process the dropped component.
*
* @param event
* reference of {@link DragAndDropEvent}
*/
protected abstract void processDroppedComponent(DragAndDropEvent event);
/**
* Get the no actions button label.
*
* @return the no actions label.
*/
protected String getNoActionsButtonLabel() {
return i18n.getMessage("button.no.actions");
}
/**
* Get the pending actions button label.
*
* @return the actions label.
*/
protected String getActionsButtonLabel() {
return i18n.getMessage("button.actions");
}
/**
* Get caption of unsaved actions window.
*
* @return caption of the window.
*/
protected String getUnsavedActionsWindowCaption() {
return i18n.getMessage("caption.save.window");
}
/**
* reload the count value.
*/
protected abstract void restoreActionCount();
/**
* This method will be called when unsaved actions window is closed.
*/
protected abstract void unsavedActionsWindowClosed();
/**
* Get the content to be displayed in unsaved actions window.
*
* @return reference of the component.
*/
protected abstract Component getUnsavedActionsWindowContent();
/**
* Check if any unsaved actions done by the user.
*
* @return 'true' if any unsaved actions available, otherwise return
* 'false'.
*/
protected abstract boolean hasUnsavedActions();
}

View File

@@ -8,7 +8,6 @@
*/
package org.eclipse.hawkbit.ui.common.grid;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.spring.events.EventBus;
import org.vaadin.spring.events.EventBus.UIEventBus;
@@ -193,7 +192,6 @@ public abstract class AbstractGridComponentLayout extends VerticalLayout {
private Layout createFooterMessageComponent() {
final HorizontalLayout footerLayout = new HorizontalLayout();
footerLayout.addComponent(getFooterMessageLabel());
footerLayout.setStyleName(SPUIStyleDefinitions.FOOTER_LAYOUT);
footerLayout.setWidth(100, Unit.PERCENTAGE);
return footerLayout;
}

View File

@@ -12,7 +12,7 @@ import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder;
import org.eclipse.hawkbit.ui.components.SPUIButton;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleNoBorder;
import org.eclipse.hawkbit.ui.rollout.state.RolloutUIState;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
@@ -116,7 +116,7 @@ public abstract class AbstractGridHeader extends VerticalLayout {
private SPUIButton createSearchResetIcon() {
final SPUIButton button = (SPUIButton) SPUIComponentProvider.getButton(getSearchRestIconId(), "", "", null,
false, FontAwesome.SEARCH, SPUIButtonStyleSmallNoBorder.class);
false, FontAwesome.SEARCH, SPUIButtonStyleNoBorder.class);
button.addClickListener(event -> onSearchResetClick());
button.setData(Boolean.FALSE);
return button;
@@ -124,14 +124,14 @@ public abstract class AbstractGridHeader extends VerticalLayout {
private Button createAddButton() {
final Button button = SPUIComponentProvider.getButton(getAddIconId(), "", "", null, false, FontAwesome.PLUS,
SPUIButtonStyleSmallNoBorder.class);
SPUIButtonStyleNoBorder.class);
button.addClickListener(this::addNewItem);
return button;
}
private Button createCloseButton() {
final Button button = SPUIComponentProvider.getButton(getCloseButtonId(), "", "", null, false,
FontAwesome.TIMES, SPUIButtonStyleSmallNoBorder.class);
FontAwesome.TIMES, SPUIButtonStyleNoBorder.class);
button.addClickListener(this::onClose);
return button;
}

View File

@@ -11,7 +11,7 @@ package org.eclipse.hawkbit.ui.common.grid;
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
import org.eclipse.hawkbit.ui.components.SPUIButton;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleNoBorder;
import org.eclipse.hawkbit.ui.management.state.ManagementUIState;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
@@ -218,7 +218,7 @@ public class DefaultGridHeader extends VerticalLayout {
*/
protected SPUIButton createMinMaxButton(final String buttonId) {
return (SPUIButton) SPUIComponentProvider.getButton(buttonId, "", "Maximize", null, true,
FontAwesome.EXPAND, SPUIButtonStyleSmallNoBorder.class);
FontAwesome.EXPAND, SPUIButtonStyleNoBorder.class);
}
/**

View File

@@ -12,6 +12,7 @@ import java.util.Collections;
import java.util.List;
import org.eclipse.hawkbit.repository.model.NamedVersionedEntity;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.TableColumn;
import org.eclipse.hawkbit.ui.utils.UINotification;
@@ -30,20 +31,18 @@ import com.vaadin.ui.DragAndDropWrapper;
*/
public abstract class AbstractNamedVersionTable<E extends NamedVersionedEntity> extends AbstractTable<E> {
private static final long serialVersionUID = 780050712209750719L;
private static final long serialVersionUID = 1L;
protected AbstractNamedVersionTable(final UIEventBus eventBus, final VaadinMessageSource i18n,
final UINotification notification) {
super(eventBus, i18n, notification);
setMultiSelect(true);
setSelectable(true);
final UINotification notification, final SpPermissionChecker permChecker) {
super(eventBus, i18n, notification, permChecker);
}
@Override
protected List<TableColumn> getTableVisibleColumns() {
final List<TableColumn> columnList = super.getTableVisibleColumns();
final float versionColumnSize = isMaximized() ? 0.1F : 0.2F;
columnList.add(new TableColumn(SPUILabelDefinitions.VAR_VERSION, i18n.getMessage("header.version"),
columnList.add(new TableColumn(SPUILabelDefinitions.VAR_VERSION, getI18n().getMessage("header.version"),
versionColumnSize));
return columnList;
}

View File

@@ -79,7 +79,7 @@ public abstract class AbstractSoftwareModuleTableHeader extends AbstractTableHea
@Override
protected void addNewItem(final ClickEvent event) {
final Window addSoftwareModule = softwareModuleAddUpdateWindow.createAddSoftwareModuleWindow();
addSoftwareModule.setCaption(i18n.getMessage("upload.caption.add.new.swmodule"));
addSoftwareModule.setCaption(i18n.getMessage("caption.create.new", i18n.getMessage("caption.software.module")));
UI.getCurrent().addWindow(addSoftwareModule);
addSoftwareModule.setVisible(Boolean.TRUE);
}

View File

@@ -18,10 +18,14 @@ import java.util.Set;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent;
import org.eclipse.hawkbit.ui.common.ConfirmationDialog;
import org.eclipse.hawkbit.ui.common.ManagementEntityState;
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
import org.eclipse.hawkbit.ui.components.RefreshableContainer;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleNoBorderWithIcon;
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
@@ -40,6 +44,9 @@ import com.vaadin.event.Transferable;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
import com.vaadin.server.FontAwesome;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Component;
import com.vaadin.ui.DragAndDropWrapper;
import com.vaadin.ui.Table;
@@ -56,21 +63,36 @@ public abstract class AbstractTable<E extends NamedEntity> extends Table impleme
private static final long serialVersionUID = 1L;
protected static final String MESSAGE_CONFIRM_DELETE_ENTITY = "message.confirm.delete.entity";
protected static final String DISTRIBUTIONSET_NOT_EXISTS = "distributionset.not.exists";
protected static final String TARGETS_NOT_EXISTS = "targets.not.exists";
protected static final String CAPTION_ENTITY_ASSIGN_ACTION_CONFIRMBOX = "caption.entity.assign.action.confirmbox";
protected static final String MESSAGE_CONFIRM_ASSIGN_ENTITY = "message.confirm.assign.entity";
protected static final String MESSAGE_CONFIRM_ASSIGN_MULTIPLE_ENTITIES = "message.confirm.assign.multiple.entities";
private static final float DEFAULT_COLUMN_NAME_MIN_SIZE = 0.8F;
protected static final String ACTION_NOT_ALLOWED_MSG = "message.action.not.allowed";
protected transient EventBus.UIEventBus eventBus;
private final transient EventBus.UIEventBus eventBus;
protected VaadinMessageSource i18n;
private final VaadinMessageSource i18n;
protected UINotification notification;
private final UINotification notification;
private final SpPermissionChecker permChecker;
protected AbstractTable(final UIEventBus eventBus, final VaadinMessageSource i18n,
final UINotification notification) {
final UINotification notification, final SpPermissionChecker permChecker) {
this.eventBus = eventBus;
this.i18n = i18n;
this.notification = notification;
this.permChecker = permChecker;
setStyleName("sp-table");
setSizeFull();
setImmediate(true);
@@ -80,6 +102,7 @@ public abstract class AbstractTable<E extends NamedEntity> extends Table impleme
setSortEnabled(false);
setId(getTableId());
addCustomGeneratedColumns();
addDeleteColumn();
setDefault();
addValueChangeListener(event -> onValueChange());
setPageLength(SPUIDefinitions.PAGE_SIZE);
@@ -97,6 +120,17 @@ public abstract class AbstractTable<E extends NamedEntity> extends Table impleme
return true;
}
// can be overriden
protected boolean hasDeletePermission() {
return permChecker.hasDeleteRepositoryPermission();
}
private void addDeleteColumn() {
if (hasDeletePermission()) {
addGeneratedColumn(SPUIDefinitions.DELETE_ENTITY, (source, itemId, columnId) -> createDeleteButton(itemId));
}
}
/**
* Gets the selected item id or in multiselect mode a set of selected ids.
*
@@ -156,11 +190,11 @@ public abstract class AbstractTable<E extends NamedEntity> extends Table impleme
protected void selectRow() {
if (!isMaximized()) {
if (isFirstRowSelectedOnLoad()) {
selectFirstRow();
} else {
setValue(getItemIdToSelect());
final Object itemIdToSelect = getItemIdToSelect();
if (itemIdToSelect == null) {
return;
}
setValue(itemIdToSelect);
}
}
@@ -176,6 +210,7 @@ public abstract class AbstractTable<E extends NamedEntity> extends Table impleme
protected void setColumnProperties() {
final List<TableColumn> columnList = getTableVisibleColumns();
addDeleteButtonToColumnList(columnList);
final List<Object> swColumnIds = new ArrayList<>();
for (final TableColumn column : columnList) {
setColumnHeader(column.getColumnPropertyId(), column.getColumnHeader());
@@ -185,11 +220,9 @@ public abstract class AbstractTable<E extends NamedEntity> extends Table impleme
setVisibleColumns(swColumnIds.toArray());
}
private void selectFirstRow() {
final Container container = getContainerDataSource();
final int size = container.size();
if (size > 0) {
select(firstItemId());
private void addDeleteButtonToColumnList(final List<TableColumn> columnList) {
if (hasDeletePermission()) {
columnList.add(new TableColumn(SPUIDefinitions.DELETE_ENTITY, "", 0.0F));
}
}
@@ -248,18 +281,18 @@ public abstract class AbstractTable<E extends NamedEntity> extends Table impleme
* the table transferable
* @return set of entities id which will deleted
*/
public Set<Long> getDeletedEntityByTransferable(final TableTransferable transferable) {
public Set<Long> getSelectedEntitiesByTransferable(final TableTransferable transferable) {
final Set<Long> selectedEntities = getTableValue(this);
final Set<Long> ids = new HashSet<>();
final Long tranferableData = (Long) transferable.getData(SPUIDefinitions.ITEMID);
if (tranferableData == null) {
final Long transferableData = (Long) transferable.getData(SPUIDefinitions.ITEMID);
if (transferableData == null) {
return ids;
}
if (!selectedEntities.contains(tranferableData)) {
ids.add(tranferableData);
} else {
if (entityToBeDeletedIsSelectedInTable(transferableData, selectedEntities)) {
ids.addAll(selectedEntities);
} else {
ids.add(transferableData);
}
return ids;
}
@@ -291,6 +324,9 @@ public abstract class AbstractTable<E extends NamedEntity> extends Table impleme
protected abstract void publishSelectedEntityEvent(final E selectedLastEntity);
protected void setLastSelectedEntityId(final Long selectedLastEntityId) {
if (selectedLastEntityId == null) {
return;
}
getManagementEntityState().setLastSelectedEntityId(selectedLastEntityId);
}
@@ -323,14 +359,97 @@ public abstract class AbstractTable<E extends NamedEntity> extends Table impleme
// can be overriden
}
/**
* Check if the first row should be selected by default on load. (if there
* is no other item selected)
*
* @return true if it should be selected otherwise return false, if there is
* a different item already selected.
*/
protected abstract boolean isFirstRowSelectedOnLoad();
private Object createDeleteButton(final Object itemId) {
final Button deleteButton = SPUIComponentProvider.getButton("", "", "", "", true, FontAwesome.TRASH_O,
SPUIButtonStyleNoBorderWithIcon.class);
final String id = getEntityId(itemId);
deleteButton.setId("delete.entity." + id);
deleteButton.setDescription(SPUIDefinitions.DELETE);
deleteButton.addClickListener(this::addDeleteButtonClickListener);
return deleteButton;
}
private void addDeleteButtonClickListener(final ClickEvent event) {
openConfirmationWindowDeleteAction(event);
}
private void openConfirmationWindowDeleteAction(final ClickEvent event) {
final List<Long> entitiesToBeDeleted = getEntitiesForDeletion(event);
final String confirmationQuestion = createConfirmationQuestionForDeletion(entitiesToBeDeleted);
final ConfirmationDialog confirmDialog = createConfirmationWindowForDeletion(entitiesToBeDeleted,
confirmationQuestion);
UI.getCurrent().addWindow(confirmDialog.getWindow());
confirmDialog.getWindow().bringToFront();
}
private List<Long> getEntitiesForDeletion(final ClickEvent event) {
List<Long> entitiesToBeDeleted;
final Long id = getDeleteButtonId(event);
final Set<Long> selectedEntities = getSelectedEntities();
if (entityToBeDeletedIsSelectedInTable(id, selectedEntities)) {
entitiesToBeDeleted = selectedEntities.stream().collect(Collectors.toList());
} else {
final Table table = getTable(event);
unselectSelectedEntitiesInTable(selectedEntities, table);
selectEntityToDeleteInTable(id, table);
entitiesToBeDeleted = new ArrayList<>();
entitiesToBeDeleted.add(id);
}
return entitiesToBeDeleted;
}
private ConfirmationDialog createConfirmationWindowForDeletion(final List<Long> entitiesToBeDeleted,
final String confirmationQuestion) {
return new ConfirmationDialog(i18n.getMessage("caption.entity.delete.action.confirmbox", getEntityType()),
confirmationQuestion, i18n.getMessage(SPUIDefinitions.BUTTON_OK),
i18n.getMessage(SPUIDefinitions.BUTTON_CANCEL), ok -> {
if (ok) {
handleOkDelete(entitiesToBeDeleted);
}
});
}
private String createConfirmationQuestionForDeletion(final List<Long> entitiesToBeDeleted) {
if (entitiesToBeDeleted.size() == 1) {
return i18n.getMessage(MESSAGE_CONFIRM_DELETE_ENTITY, getEntityType().toLowerCase(),
getDeletedEntityName(entitiesToBeDeleted.get(0)), "");
} else {
return i18n.getMessage(MESSAGE_CONFIRM_DELETE_ENTITY, entitiesToBeDeleted.size(),
getEntityType().toLowerCase(), "s");
}
}
private static boolean entityToBeDeletedIsSelectedInTable(final Long id, final Set<Long> selectedEntities) {
return selectedEntities.contains(id);
}
private static Table getTable(final ClickEvent event) {
final Button source = (Button) event.getSource();
return (Table) source.getParent();
}
private static void selectEntityToDeleteInTable(final Long id, final Table table) {
table.select(id);
}
private static void unselectSelectedEntitiesInTable(final Set<Long> selectedEntities, final Table table) {
selectedEntities.forEach(table::unselect);
}
private static long getDeleteButtonId(final ClickEvent event) {
final String id = event.getButton().getId();
return Long.parseLong(id.substring(id.lastIndexOf('.') + 1));
}
protected abstract String getDeletedEntityName(Long entityId);
protected abstract void handleOkDelete(List<Long> allEntities);
protected abstract String getEntityType();
protected abstract Set<Long> getSelectedEntities();
protected abstract String getEntityId(Object itemId);
/**
* Get Item Id which should be displayed as selected.
@@ -368,7 +487,6 @@ public abstract class AbstractTable<E extends NamedEntity> extends Table impleme
i18n.getMessage("header.modifiedDate"), 0.1F));
columnList.add(new TableColumn(SPUILabelDefinitions.VAR_DESC, i18n.getMessage("header.description"), 0.2F));
setItemDescriptionGenerator((source, itemId, propertyId) -> {
if (SPUILabelDefinitions.VAR_CREATED_BY.equals(propertyId)) {
return getItem(itemId).getItemProperty(SPUILabelDefinitions.VAR_CREATED_BY).getValue().toString();
}
@@ -377,7 +495,6 @@ public abstract class AbstractTable<E extends NamedEntity> extends Table impleme
}
return null;
});
return columnList;
}
@@ -416,17 +533,16 @@ public abstract class AbstractTable<E extends NamedEntity> extends Table impleme
final AbstractSelectTargetDetails dropData = (AbstractSelectTargetDetails) event.getTargetDetails();
final Long targetItemId = (Long) dropData.getItemIdOver();
if (!targetSelected.contains(targetItemId)) {
return Sets.newHashSet(targetItemId);
if (entityToBeDeletedIsSelectedInTable(targetItemId, targetSelected)) {
return targetSelected;
}
return targetSelected;
return Sets.newHashSet(targetItemId);
}
private Set<Long> getDraggedTargetList(final TableTransferable transferable, final Table source) {
@SuppressWarnings("unchecked")
final AbstractTable<NamedEntity> table = (AbstractTable<NamedEntity>) source;
return table.getDeletedEntityByTransferable(transferable);
return table.getSelectedEntitiesByTransferable(transferable);
}
private boolean validateDropList(final Set<?> droplist) {
@@ -499,6 +615,27 @@ public abstract class AbstractTable<E extends NamedEntity> extends Table impleme
publishSelectedEntityEvent(entity);
}
protected void selectDroppedEntities(final Long targetId) {
getSelectedEntities().forEach(this::unselect);
select(targetId);
}
protected void selectDraggedEntities(final AbstractTable<?> source, final Set<Long> ids) {
source.setValue(ids);
}
protected EventBus.UIEventBus getEventBus() {
return eventBus;
}
protected VaadinMessageSource getI18n() {
return i18n;
}
protected SpPermissionChecker getPermChecker() {
return permChecker;
}
protected abstract List<String> hasMissingPermissionsForDrop();
protected abstract boolean validateDragAndDropWrapper(final DragAndDropWrapper wrapperSource);

View File

@@ -14,7 +14,7 @@ import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder;
import org.eclipse.hawkbit.ui.components.SPUIButton;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleNoBorder;
import org.eclipse.hawkbit.ui.distributions.state.ManageDistUIState;
import org.eclipse.hawkbit.ui.management.state.ManagementUIState;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
@@ -221,7 +221,7 @@ public abstract class AbstractTableHeader extends VerticalLayout {
private SPUIButton createSearchResetIcon() {
final SPUIButton button = (SPUIButton) SPUIComponentProvider.getButton(getSearchRestIconId(), "", "", null,
false, FontAwesome.SEARCH, SPUIButtonStyleSmallNoBorder.class);
false, FontAwesome.SEARCH, SPUIButtonStyleNoBorder.class);
button.addClickListener(event -> onSearchResetClick());
button.setData(Boolean.FALSE);
return button;
@@ -229,21 +229,21 @@ public abstract class AbstractTableHeader extends VerticalLayout {
private Button createAddIcon() {
final Button button = SPUIComponentProvider.getButton(getAddIconId(), "", "", null, false, FontAwesome.PLUS,
SPUIButtonStyleSmallNoBorder.class);
SPUIButtonStyleNoBorder.class);
button.addClickListener(this::addNewItem);
return button;
}
private Button createBulkUploadIcon() {
final Button button = SPUIComponentProvider.getButton(getBulkUploadIconId(), "", "", null, false,
FontAwesome.UPLOAD, SPUIButtonStyleSmallNoBorder.class);
FontAwesome.UPLOAD, SPUIButtonStyleNoBorder.class);
button.addClickListener(this::bulkUpload);
return button;
}
private Button createShowFilterButtonLayout() {
final Button button = SPUIComponentProvider.getButton(getShowFilterButtonLayoutId(), null, null, null, false,
FontAwesome.TAGS, SPUIButtonStyleSmallNoBorder.class);
FontAwesome.TAGS, SPUIButtonStyleNoBorder.class);
button.setVisible(false);
button.addClickListener(event -> showFilterButtonsIconClicked());
return button;
@@ -251,7 +251,7 @@ public abstract class AbstractTableHeader extends VerticalLayout {
private SPUIButton createMaxMinIcon() {
final SPUIButton button = (SPUIButton) SPUIComponentProvider.getButton(getMaxMinIconId(), "", "", null, false,
FontAwesome.EXPAND, SPUIButtonStyleSmallNoBorder.class);
FontAwesome.EXPAND, SPUIButtonStyleNoBorder.class);
button.addClickListener(event -> maxMinButtonClicked());
return button;
}

View File

@@ -0,0 +1,106 @@
/**
* 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.components;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import com.vaadin.server.FontAwesome;
import com.vaadin.ui.MenuBar;
import com.vaadin.ui.themes.ValoTheme;
/**
* Menubar for configuring tags and types (create, update, delete). The menubar
* is placed in the header of the filter by tags or types tables.
*
*/
public class ConfigMenuBar extends MenuBar {
private static final long serialVersionUID = 1L;
private MenuItem config;
private final boolean createPermission;
private final boolean updatePermission;
private final boolean deletePermission;
private final Command addButtonCommand;
private final Command updateButtonCommand;
private final Command deleteButtonCommand;
private final String id;
/**
* Constructor for the menubar
*
* @param createPermission
* flag if the logged-in user has permission to create the entity
* which should be configured with this menubar
* @param updatePermission
* flag if the logged-in user has permission to update the entity
* which should be configured with this menubar
* @param deletePermission
* flag if the logged-in user has permission to delete the entity
* which should be configured with this menubar
* @param addButtonCommand
* action which should be executed when clicking on the create
* command
* @param updateButtonCommand
* action which should be executed when clicking on the update
* command
* @param deleteButtonCommand
* action which should be executed when clicking on the delete
* command
* @param id
* the id of the menuBar
*/
public ConfigMenuBar(final boolean createPermission, final boolean updatePermission, final boolean deletePermission,
final Command addButtonCommand, final Command updateButtonCommand, final Command deleteButtonCommand,
final String id) {
this.createPermission = createPermission;
this.updatePermission = updatePermission;
this.deletePermission = deletePermission;
this.addButtonCommand = addButtonCommand;
this.updateButtonCommand = updateButtonCommand;
this.deleteButtonCommand = deleteButtonCommand;
this.id = id;
init();
}
private void init() {
setId(id);
if (!createPermission && !updatePermission && !deletePermission) {
return;
}
setStyleName(ValoTheme.MENUBAR_BORDERLESS);
addStyleName(SPUIStyleDefinitions.CONFIG_MENU_BAR_POSITION);
config = addItem("", FontAwesome.COG, null);
config.setStyleName(SPUIStyleDefinitions.CONFIG_MENU_BAR_ITEMS);
addMenuItems();
}
private void addMenuItems() {
if (createPermission) {
config.addItem(UIComponentIdProvider.CONFIG_MENU_BAR_CREATE, FontAwesome.PLUS, addButtonCommand);
}
if (updatePermission) {
config.addItem(UIComponentIdProvider.CONFIG_MENU_BAR_UPDATE, FontAwesome.EDIT, updateButtonCommand);
}
if (deletePermission) {
config.addItem(UIComponentIdProvider.CONFIG_MENU_BAR_DELETE, FontAwesome.TRASH_O, deleteButtonCommand);
}
}
}

View File

@@ -12,7 +12,6 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.hawkbit.ui.push.EventContainer;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.springframework.beans.factory.annotation.Autowired;
@@ -62,7 +61,6 @@ public class NotificationUnreadButton extends Button {
this.unreadNotifications = new ConcurrentHashMap<>();
setIcon(FontAwesome.BELL);
setId(UIComponentIdProvider.NOTIFICATION_UNREAD_ID);
addStyleName(SPUIStyleDefinitions.ACTION_BUTTON);
addStyleName(ValoTheme.BUTTON_SMALL);
addStyleName(STYLE);
setHtmlContentAllowed(true);

View File

@@ -66,13 +66,13 @@ public final class SPUIComponentProvider {
* signifies if combo is mandatory
* @param data
* combo box data
* @param promt
* @param prompt
* input prompt
* @return ComboBox
*/
public static ComboBox getComboBox(final String caption, final String width, final String style,
final String styleName, final boolean required, final String data, final String promt) {
return SPUIComboBoxDecorator.decorate(caption, width, style, styleName, required, data, promt);
final String styleName, final boolean required, final String data, final String prompt) {
return SPUIComboBoxDecorator.decorate(caption, width, style, styleName, required, data, prompt);
}
/**

View File

@@ -16,6 +16,7 @@ import java.util.logging.Logger;
import org.eclipse.hawkbit.ui.dd.criteria.ServerViewClientCriterion;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Document;
@@ -95,8 +96,8 @@ public final class ViewClientCriterion extends VAcceptCriterion implements VAcce
SafeHtml notificationMsg(String msg);
}
private static VAcceptCriterion getCriteria(UIDL configuration, int i) {
UIDL childUIDL = configuration.getChildUIDL(i);
private static VAcceptCriterion getCriteria(final UIDL configuration, final int i) {
final UIDL childUIDL = configuration.getChildUIDL(i);
return VAcceptCriteria.get(childUIDL.getStringAttribute("name"));
}
@@ -121,7 +122,7 @@ public final class ViewClientCriterion extends VAcceptCriterion implements VAcce
if (isDragStarting(drag)) {
final NativePreviewHandler nativeEventHandler = new NativePreviewHandler() {
@Override
public void onPreviewNativeEvent(NativePreviewEvent event) {
public void onPreviewNativeEvent(final NativePreviewEvent event) {
if (isEscKey(event) || isMouseUp(event)) {
try {
hideDropTargetHints(configuration);
@@ -136,10 +137,10 @@ public final class ViewClientCriterion extends VAcceptCriterion implements VAcce
setMultiRowDragDecoration(drag);
}
int childCount = configuration.getChildCount();
final int childCount = configuration.getChildCount();
accepted = false;
for (int childIndex = 0; childIndex < childCount; childIndex++) {
VAcceptCriterion crit = getCriteria(configuration, childIndex);
final VAcceptCriterion crit = getCriteria(configuration, childIndex);
crit.accept(drag, configuration.getChildUIDL(childIndex), this);
if (Boolean.TRUE.equals(accepted)) {
callback.accepted(drag);
@@ -155,18 +156,18 @@ public final class ViewClientCriterion extends VAcceptCriterion implements VAcce
}
@Override
public boolean needsServerSideCheck(VDragEvent drag, UIDL criterioUIDL) {
public boolean needsServerSideCheck(final VDragEvent drag, final UIDL criterioUIDL) {
return false;
}
@Override
protected boolean accept(VDragEvent drag, UIDL configuration) {
protected boolean accept(final VDragEvent drag, final UIDL configuration) {
// not used here:
return false;
}
@Override
public void accepted(VDragEvent event) {
public void accepted(final VDragEvent event) {
accepted = true;
}
@@ -176,24 +177,25 @@ public final class ViewClientCriterion extends VAcceptCriterion implements VAcce
* @param drag
* the current drag event holding the context.
*/
void setMultiRowDragDecoration(VDragEvent drag) {
Widget widget = drag.getTransferable().getDragSource().getWidget();
void setMultiRowDragDecoration(final VDragEvent drag) {
final Widget widget = drag.getTransferable().getDragSource().getWidget();
if (widget instanceof VScrollTable) {
VScrollTable table = (VScrollTable) widget;
int rowCount = table.selectedRowKeys.size();
final VScrollTable table = (VScrollTable) widget;
final int rowCount = table.selectedRowKeys.size();
Element dragCountElement = Document.get().getElementById(SP_DRAG_COUNT);
if (rowCount > 1 && table.selectedRowKeys.contains(table.focusedRow.getKey())) {
if (dragCountElement == null) {
dragCountElement = Document.get().createStyleElement();
dragCountElement.setId(SP_DRAG_COUNT);
HeadElement head = HeadElement.as(Document.get().getElementsByTagName(HeadElement.TAG).getItem(0));
final HeadElement head = HeadElement
.as(Document.get().getElementsByTagName(HeadElement.TAG).getItem(0));
head.appendChild(dragCountElement);
}
SafeHtml formattedCssStyle = getDraggableTemplate().multiSelectionStyle(determineActiveTheme(drag),
String.valueOf(rowCount));
StyleElement dragCountStyleElement = StyleElement.as(dragCountElement);
final SafeHtml formattedCssStyle = getDraggableTemplate()
.multiSelectionStyle(determineActiveTheme(drag), String.valueOf(rowCount));
final StyleElement dragCountStyleElement = StyleElement.as(dragCountElement);
dragCountStyleElement.setInnerSafeHtml(formattedCssStyle);
} else if (dragCountElement != null) {
dragCountElement.removeFromParent();
@@ -210,9 +212,9 @@ public final class ViewClientCriterion extends VAcceptCriterion implements VAcce
* key, otherwise <code>false</code>.
*/
private static boolean isEscKey(final NativePreviewEvent event) {
int typeInt = event.getTypeInt();
final int typeInt = event.getTypeInt();
if (typeInt == Event.ONKEYDOWN) {
int keyCode = event.getNativeEvent().getKeyCode();
final int keyCode = event.getNativeEvent().getKeyCode();
if (KeyCodes.KEY_ESCAPE == keyCode) {
return true;
}
@@ -242,16 +244,16 @@ public final class ViewClientCriterion extends VAcceptCriterion implements VAcce
// Exception squid:S2221 - This code is trans-coded to JavaScript, hence
// Exception semantics changes
@SuppressWarnings({ "squid:S1166", "squid:S2221" })
void hideDropTargetHints(UIDL configuration) {
int totalDropTargetHintsCount = configuration.getIntAttribute(DROP_AREA_CONFIG_COUNT);
void hideDropTargetHints(final UIDL configuration) {
final int totalDropTargetHintsCount = configuration.getIntAttribute(DROP_AREA_CONFIG_COUNT);
for (int dropAreaIndex = 0; dropAreaIndex < totalDropTargetHintsCount; dropAreaIndex++) {
try {
String dropArea = configuration.getStringAttribute(DROP_AREA_CONFIG + dropAreaIndex);
Element hideHintFor = Document.get().getElementById(dropArea);
final String dropArea = configuration.getStringAttribute(DROP_AREA_CONFIG + dropAreaIndex);
final Element hideHintFor = Document.get().getElementById(dropArea);
if (hideHintFor != null) {
hideHintFor.removeClassName(ViewComponentClientCriterion.HINT_AREA_STYLE);
}
} catch (Exception e) {
} catch (final Exception e) {
// log and continue
LOGGER.log(Level.SEVERE, "Error highlighting valid drop targets: " + e.getLocalizedMessage());
}
@@ -264,11 +266,11 @@ public final class ViewClientCriterion extends VAcceptCriterion implements VAcce
* @param drag
* the current drag event holding the context.
*/
private void showErrorNotification(VDragEvent drag) {
VNotification n = VNotification.createNotification(SPUILabelDefinitions.SP_DELAY,
private void showErrorNotification(final VDragEvent drag) {
final VNotification n = VNotification.createNotification(SPUILabelDefinitions.SP_DELAY,
drag.getTransferable().getDragSource().getWidget());
n.show(getDraggableTemplate().notificationMsg(SPUILabelDefinitions.ACTION_NOT_ALLOWED).asString(),
Position.BOTTOM_RIGHT, SPUILabelDefinitions.SP_NOTIFICATION_ERROR_MESSAGE_STYLE);
Position.BOTTOM_RIGHT, SPUIStyleDefinitions.SP_NOTIFICATION_ERROR_MESSAGE_STYLE);
}
/**
@@ -278,7 +280,7 @@ public final class ViewClientCriterion extends VAcceptCriterion implements VAcce
* the event the UI theme is retrieved for.
* @return the active theme (e.g. "hawkbit").
*/
private static String determineActiveTheme(VDragEvent drag) {
private static String determineActiveTheme(final VDragEvent drag) {
return drag.getTransferable().getDragSource().getConnection().getUIConnector().getActiveTheme();
}
@@ -292,7 +294,7 @@ public final class ViewClientCriterion extends VAcceptCriterion implements VAcce
* @return <code>true</code> if the drag operation is starting, otherwise
* <code>false</code>
*/
private boolean isDragStarting(VDragEvent drag) {
private boolean isDragStarting(final VDragEvent drag) {
boolean result = false;
if (!drag.equals(previousDragEvent)) {
result = true;

View File

@@ -8,7 +8,6 @@
*/
package org.eclipse.hawkbit.ui.dd.criteria;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import com.vaadin.spring.annotation.SpringComponent;
@@ -22,10 +21,7 @@ import com.vaadin.spring.annotation.UIScope;
@UIScope
public final class DistributionsViewClientCriterion extends ServerViewClientCriterion {
/**
* serialVersionUID.
*/
private static final long serialVersionUID = 8602945302654554257L;
private static final long serialVersionUID = 1L;
private static final ServerViewComponentClientCriterion[] COMPONENT_CRITERIA = createViewComponentClientCriteria();
@@ -43,30 +39,13 @@ public final class DistributionsViewClientCriterion extends ServerViewClientCrit
* @return accept criterion elements
*/
static ServerViewComponentClientCriterion[] createViewComponentClientCriteria() {
ServerViewComponentClientCriterion[] criteria = new ServerViewComponentClientCriterion[4];
final ServerViewComponentClientCriterion[] criteria = new ServerViewComponentClientCriterion[1];
// Distribution table acceptable components.
criteria[0] = ServerViewComponentClientCriterion.createBuilder()
.dragSourceIdPrefix(UIComponentIdProvider.DIST_TABLE_ID)
.dropTargetIdPrefixes(UIComponentIdProvider.DELETE_BUTTON_WRAPPER_ID)
.dropAreaIds(UIComponentIdProvider.DELETE_BUTTON_WRAPPER_ID).build();
// Distribution set type acceptable components.
criteria[1] = ServerViewComponentClientCriterion.createBuilder()
.dragSourceIdPrefix(SPUIDefinitions.DISTRIBUTION_SET_TYPE_ID_PREFIXS)
.dropTargetIdPrefixes(UIComponentIdProvider.DELETE_BUTTON_WRAPPER_ID)
.dropAreaIds(UIComponentIdProvider.DELETE_BUTTON_WRAPPER_ID).build();
// Upload software module table acceptable components.
criteria[2] = ServerViewComponentClientCriterion.createBuilder()
criteria[0] = ServerViewComponentClientCriterion.createBuilder()
.dragSourceIdPrefix(UIComponentIdProvider.UPLOAD_SOFTWARE_MODULE_TABLE)
.dropTargetIdPrefixes(UIComponentIdProvider.DIST_TABLE_ID,
UIComponentIdProvider.DELETE_BUTTON_WRAPPER_ID)
.dropAreaIds(UIComponentIdProvider.DIST_TABLE_ID, UIComponentIdProvider.DELETE_BUTTON_WRAPPER_ID)
.build();
// Software module tag acceptable components.
criteria[3] = ServerViewComponentClientCriterion.createBuilder()
.dragSourceIdPrefix(SPUIDefinitions.SOFTWARE_MODULE_TAG_ID_PREFIXS)
.dropTargetIdPrefixes(UIComponentIdProvider.DELETE_BUTTON_WRAPPER_ID)
.dropAreaIds(UIComponentIdProvider.DELETE_BUTTON_WRAPPER_ID).build();
.dropTargetIdPrefixes(UIComponentIdProvider.DIST_TABLE_ID)
.dropAreaIds(UIComponentIdProvider.DIST_TABLE_ID).build();
return criteria;
}

View File

@@ -43,40 +43,32 @@ public final class ManagementViewClientCriterion extends ServerViewClientCriteri
* @return accept criterion elements
*/
static ServerViewComponentClientCriterion[] createViewComponentClientCriteria() {
ServerViewComponentClientCriterion[] criteria = new ServerViewComponentClientCriterion[4];
final ServerViewComponentClientCriterion[] criteria = new ServerViewComponentClientCriterion[4];
// Target table acceptable components.
criteria[0] = ServerViewComponentClientCriterion.createBuilder()
.dragSourceIdPrefix(UIComponentIdProvider.TARGET_TABLE_ID)
.dropTargetIdPrefixes(SPUIDefinitions.TARGET_TAG_ID_PREFIXS, UIComponentIdProvider.DIST_TABLE_ID,
UIComponentIdProvider.DELETE_BUTTON_WRAPPER_ID)
.dropAreaIds(UIComponentIdProvider.TARGET_TAG_DROP_AREA_ID, UIComponentIdProvider.DIST_TABLE_ID,
UIComponentIdProvider.DELETE_BUTTON_WRAPPER_ID)
.dropTargetIdPrefixes(SPUIDefinitions.TARGET_TAG_ID_PREFIXS, UIComponentIdProvider.DIST_TABLE_ID)
.dropAreaIds(UIComponentIdProvider.TARGET_TAG_DROP_AREA_ID, UIComponentIdProvider.DIST_TABLE_ID)
.build();
// Target Tag acceptable components.
criteria[1] = ServerViewComponentClientCriterion.createBuilder()
.dragSourceIdPrefix(SPUIDefinitions.TARGET_TAG_ID_PREFIXS)
.dropTargetIdPrefixes(UIComponentIdProvider.TARGET_TABLE_ID, UIComponentIdProvider.DIST_TABLE_ID,
UIComponentIdProvider.DELETE_BUTTON_WRAPPER_ID)
.dropAreaIds(UIComponentIdProvider.TARGET_TABLE_ID, UIComponentIdProvider.DIST_TABLE_ID,
UIComponentIdProvider.DELETE_BUTTON_WRAPPER_ID)
.build();
.dropTargetIdPrefixes(UIComponentIdProvider.TARGET_TABLE_ID, UIComponentIdProvider.DIST_TABLE_ID)
.dropAreaIds(UIComponentIdProvider.TARGET_TABLE_ID, UIComponentIdProvider.DIST_TABLE_ID).build();
// Distribution table acceptable components.
criteria[2] = ServerViewComponentClientCriterion.createBuilder()
.dragSourceIdPrefix(UIComponentIdProvider.DIST_TABLE_ID)
.dropTargetIdPrefixes(UIComponentIdProvider.TARGET_TABLE_ID,
UIComponentIdProvider.TARGET_DROP_FILTER_ICON, SPUIDefinitions.DISTRIBUTION_TAG_ID_PREFIXS,
UIComponentIdProvider.DELETE_BUTTON_WRAPPER_ID)
UIComponentIdProvider.TARGET_DROP_FILTER_ICON, SPUIDefinitions.DISTRIBUTION_TAG_ID_PREFIXS)
.dropAreaIds(UIComponentIdProvider.TARGET_TABLE_ID, UIComponentIdProvider.TARGET_DROP_FILTER_ICON,
UIComponentIdProvider.DISTRIBUTION_TAG_TABLE_ID, UIComponentIdProvider.DELETE_BUTTON_WRAPPER_ID)
UIComponentIdProvider.DISTRIBUTION_TAG_TABLE_ID)
.build();
// Distribution tag acceptable components.
criteria[3] = ServerViewComponentClientCriterion.createBuilder()
.dragSourceIdPrefix(SPUIDefinitions.DISTRIBUTION_TAG_ID_PREFIXS)
.dropTargetIdPrefixes(UIComponentIdProvider.DIST_TABLE_ID,
UIComponentIdProvider.DELETE_BUTTON_WRAPPER_ID)
.dropAreaIds(UIComponentIdProvider.DIST_TABLE_ID, UIComponentIdProvider.DELETE_BUTTON_WRAPPER_ID)
.build();
.dropTargetIdPrefixes(UIComponentIdProvider.DIST_TABLE_ID)
.dropAreaIds(UIComponentIdProvider.DIST_TABLE_ID).build();
return criteria;
}

View File

@@ -8,8 +8,6 @@
*/
package org.eclipse.hawkbit.ui.dd.criteria;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.UIScope;
@@ -42,19 +40,6 @@ public final class UploadViewClientCriterion extends ServerViewClientCriterion {
* @return accept criterion elements
*/
static ServerViewComponentClientCriterion[] createViewComponentClientCriteria() {
ServerViewComponentClientCriterion[] criteria = new ServerViewComponentClientCriterion[2];
// Upload type acceptable components.
criteria[0] = ServerViewComponentClientCriterion.createBuilder()
.dragSourceIdPrefix(UIComponentIdProvider.UPLOAD_TYPE_BUTTON_PREFIX)
.dropTargetIdPrefixes(UIComponentIdProvider.DELETE_BUTTON_WRAPPER_ID)
.dropAreaIds(UIComponentIdProvider.DELETE_BUTTON_WRAPPER_ID).build();
// Upload software module table acceptable components.
criteria[1] = ServerViewComponentClientCriterion.createBuilder()
.dragSourceIdPrefix(UIComponentIdProvider.UPLOAD_SOFTWARE_MODULE_TABLE)
.dropTargetIdPrefixes(UIComponentIdProvider.DELETE_BUTTON_WRAPPER_ID)
.dropAreaIds(UIComponentIdProvider.DELETE_BUTTON_WRAPPER_ID).build();
return criteria;
return new ServerViewComponentClientCriterion[0];
}
}

View File

@@ -15,7 +15,7 @@ import com.vaadin.ui.themes.ValoTheme;
/**
* Style for button: Small NoBorder.
*/
public class SPUIButtonStyleSmallNoBorder implements SPUIButtonDecorator {
public class SPUIButtonStyleNoBorder implements SPUIButtonDecorator {
/**
* Decorate Button and return.
@@ -32,13 +32,11 @@ public class SPUIButtonStyleSmallNoBorder implements SPUIButtonDecorator {
*/
@Override
public Button decorate(final Button button, final String style, final boolean setStyle, final Resource icon) {
// Set Style
if (null != style && setStyle) {
if (style != null && setStyle) {
button.addStyleName(style);
}
button.addStyleName(ValoTheme.BUTTON_BORDERLESS);
// Set icon
if (null != icon) {
if (icon != null) {
button.addStyleName(ValoTheme.BUTTON_ICON_ONLY);
button.addStyleName("button-no-border");
button.setIcon(icon);

View File

@@ -21,16 +21,14 @@ public class SPUIButtonStyleSmall implements SPUIButtonDecorator {
@Override
public Button decorate(final Button button, final String style, final boolean setStyle, final Resource icon) {
button.addStyleName(ValoTheme.BUTTON_SMALL);
// Set Style
if (null != style) {
if (style != null) {
if (setStyle) {
button.setStyleName(style);
} else {
button.addStyleName(style);
}
}
// Set icon
if (null != icon) {
if (icon != null) {
button.addStyleName(ValoTheme.BUTTON_ICON_ONLY);
button.setIcon(icon);
}

View File

@@ -30,11 +30,12 @@ import org.eclipse.hawkbit.ui.components.AbstractNotificationView;
import org.eclipse.hawkbit.ui.components.NotificationUnreadButton;
import org.eclipse.hawkbit.ui.components.RefreshableContainer;
import org.eclipse.hawkbit.ui.dd.criteria.DistributionsViewClientCriterion;
import org.eclipse.hawkbit.ui.distributions.disttype.DSTypeFilterLayout;
import org.eclipse.hawkbit.ui.distributions.disttype.filter.DSTypeFilterButtons;
import org.eclipse.hawkbit.ui.distributions.disttype.filter.DSTypeFilterLayout;
import org.eclipse.hawkbit.ui.distributions.dstable.DistributionSetTableLayout;
import org.eclipse.hawkbit.ui.distributions.footer.DSDeleteActionsLayout;
import org.eclipse.hawkbit.ui.distributions.smtable.SwModuleTableLayout;
import org.eclipse.hawkbit.ui.distributions.smtype.DistSMTypeFilterLayout;
import org.eclipse.hawkbit.ui.distributions.smtype.filter.DistSMTypeFilterButtons;
import org.eclipse.hawkbit.ui.distributions.smtype.filter.DistSMTypeFilterLayout;
import org.eclipse.hawkbit.ui.distributions.state.ManageDistUIState;
import org.eclipse.hawkbit.ui.management.event.DistributionTableEvent;
import org.eclipse.hawkbit.ui.menu.DashboardMenuItem;
@@ -57,7 +58,6 @@ 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.Alignment;
import com.vaadin.ui.GridLayout;
/**
@@ -85,8 +85,6 @@ public class DistributionsView extends AbstractNotificationView implements Brows
private final DistSMTypeFilterLayout filterBySMTypeLayout;
private final DSDeleteActionsLayout deleteActionsLayout;
private final ManageDistUIState manageDistUIState;
private final DistributionsViewMenuItem distributionsViewMenuItem;
@@ -109,9 +107,13 @@ public class DistributionsView extends AbstractNotificationView implements Brows
this.permChecker = permChecker;
this.i18n = i18n;
this.uiNotification = uiNotification;
this.manageDistUIState = manageDistUIState;
final DSTypeFilterButtons dsTypeFilterButtons = new DSTypeFilterButtons(eventBus, manageDistUIState,
distributionsViewClientCriterion, distributionSetTypeManagement, i18n, entityFactory, permChecker,
uiNotification, softwareModuleTypeManagement, distributionSetManagement, systemManagement);
this.filterByDSTypeLayout = new DSTypeFilterLayout(manageDistUIState, i18n, permChecker, eventBus,
entityFactory, uiNotification, softwareModuleTypeManagement, distributionSetTypeManagement,
distributionSetManagement, distributionsViewClientCriterion);
dsTypeFilterButtons);
this.distributionTableLayout = new DistributionSetTableLayout(i18n, eventBus, permChecker, manageDistUIState,
softwareModuleManagement, distributionSetManagement, distributionSetTypeManagement, targetManagement,
entityFactory, uiNotification, distributionSetTagManagement, distributionsViewClientCriterion,
@@ -119,12 +121,12 @@ public class DistributionsView extends AbstractNotificationView implements Brows
this.softwareModuleTableLayout = new SwModuleTableLayout(i18n, uiNotification, eventBus,
softwareModuleManagement, softwareModuleTypeManagement, entityFactory, manageDistUIState, permChecker,
distributionsViewClientCriterion, artifactUploadState, artifactManagement);
final DistSMTypeFilterButtons distSmTypeFilterButtons = new DistSMTypeFilterButtons(eventBus, manageDistUIState,
distributionsViewClientCriterion, softwareModuleTypeManagement, i18n, entityFactory, permChecker,
uiNotification);
this.filterBySMTypeLayout = new DistSMTypeFilterLayout(eventBus, i18n, permChecker, manageDistUIState,
entityFactory, uiNotification, softwareModuleTypeManagement, distributionsViewClientCriterion);
this.deleteActionsLayout = new DSDeleteActionsLayout(i18n, permChecker, eventBus, uiNotification,
systemManagement, manageDistUIState, distributionsViewClientCriterion, distributionSetManagement,
distributionSetTypeManagement, softwareModuleManagement, softwareModuleTypeManagement);
this.manageDistUIState = manageDistUIState;
entityFactory, uiNotification, softwareModuleTypeManagement, distSmTypeFilterButtons);
this.distributionsViewMenuItem = distributionsViewMenuItem;
}
@@ -177,18 +179,18 @@ public class DistributionsView extends AbstractNotificationView implements Brows
}
private void createMainLayout() {
mainLayout = new GridLayout(4, 2);
mainLayout = new GridLayout(4, 1);
mainLayout.setSizeFull();
mainLayout.setSpacing(true);
mainLayout.setStyleName("fullSize");
mainLayout.addComponent(filterByDSTypeLayout, 0, 0);
mainLayout.addComponent(distributionTableLayout, 1, 0);
mainLayout.addComponent(softwareModuleTableLayout, 2, 0);
mainLayout.addComponent(filterBySMTypeLayout, 3, 0);
mainLayout.addComponent(deleteActionsLayout, 1, 1, 2, 1);
mainLayout.setRowExpandRatio(0, 1.0F);
mainLayout.setColumnExpandRatio(1, 0.5F);
mainLayout.setColumnExpandRatio(2, 0.5F);
mainLayout.setComponentAlignment(deleteActionsLayout, Alignment.BOTTOM_CENTER);
}
@EventBusListenerMethod(scope = EventScope.UI)
@@ -212,7 +214,6 @@ public class DistributionsView extends AbstractNotificationView implements Brows
private void maximizeSwTable() {
mainLayout.removeComponent(filterByDSTypeLayout);
mainLayout.removeComponent(distributionTableLayout);
mainLayout.removeComponent(deleteActionsLayout);
mainLayout.setColumnExpandRatio(2, 1F);
mainLayout.setColumnExpandRatio(0, 0F);
mainLayout.setColumnExpandRatio(1, 0F);
@@ -221,26 +222,20 @@ public class DistributionsView extends AbstractNotificationView implements Brows
private void minimizeSwTable() {
mainLayout.addComponent(filterByDSTypeLayout, 0, 0);
mainLayout.addComponent(distributionTableLayout, 1, 0);
mainLayout.addComponent(deleteActionsLayout, 1, 1, 2, 1);
mainLayout.setColumnExpandRatio(1, 0.5F);
mainLayout.setColumnExpandRatio(2, 0.5F);
mainLayout.setComponentAlignment(deleteActionsLayout, Alignment.BOTTOM_CENTER);
}
private void minimizeDistTable() {
mainLayout.addComponent(softwareModuleTableLayout, 2, 0);
mainLayout.addComponent(filterBySMTypeLayout, 3, 0);
mainLayout.addComponent(deleteActionsLayout, 1, 1, 2, 1);
mainLayout.setColumnExpandRatio(1, 0.5F);
mainLayout.setColumnExpandRatio(2, 0.5F);
mainLayout.setComponentAlignment(deleteActionsLayout, Alignment.BOTTOM_CENTER);
}
private void maximizeDistTable() {
mainLayout.removeComponent(softwareModuleTableLayout);
mainLayout.removeComponent(filterBySMTypeLayout);
mainLayout.removeComponent(deleteActionsLayout);
mainLayout.setColumnExpandRatio(1, 1F);
mainLayout.setColumnExpandRatio(2, 0F);
mainLayout.setColumnExpandRatio(3, 0F);
}

View File

@@ -0,0 +1,141 @@
/**
* 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.distributions.disttype;
import java.util.Optional;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.layouts.AbstractTypeLayout;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.spring.events.EventBus.UIEventBus;
/**
* General Layout for Distribution Type pop-up window which is provided on
* Distribution View when creating, updating, or deleting a Distribution Set
* Type
*/
public abstract class AbstractDistributionSetTypeLayout extends AbstractTypeLayout<DistributionSetType> {
private static final long serialVersionUID = 1L;
private final transient DistributionSetTypeManagement distributionSetTypeManagement;
private DistributionSetTypeSoftwareModuleSelectLayout twinTables;
private final transient SoftwareModuleTypeManagement softwareModuleTypeManagement;
/**
* Constructor
*
* @param i18n
* VaadinMessageSource
* @param entityFactory
* EntityFactory
* @param eventBus
* UIEventBus
* @param permChecker
* SpPermissionChecker
* @param uiNotification
* UINotification
* @param distributionSetTypeManagement
* DistributionSetTypeManagement
* @param softwareModuleTypeManagement
* SoftwareModuleTypeManagement
*/
public AbstractDistributionSetTypeLayout(final VaadinMessageSource i18n, final EntityFactory entityFactory,
final UIEventBus eventBus, final SpPermissionChecker permChecker, final UINotification uiNotification,
final DistributionSetTypeManagement distributionSetTypeManagement,
final SoftwareModuleTypeManagement softwareModuleTypeManagement) {
super(i18n, entityFactory, eventBus, permChecker, uiNotification);
this.distributionSetTypeManagement = distributionSetTypeManagement;
this.softwareModuleTypeManagement = softwareModuleTypeManagement;
createTwinTables();
}
private void createTwinTables() {
twinTables = new DistributionSetTypeSoftwareModuleSelectLayout(getI18n(), softwareModuleTypeManagement);
getMainLayout().addComponent(twinTables, 2, 0);
updateRequiredFields();
}
private void updateRequiredFields() {
getWindow().updateAllComponents(getMainLayout());
getWindow().addComponentListeners();
}
@Override
protected int getTagNameSize() {
return DistributionSetType.NAME_MAX_SIZE;
}
@Override
protected int getTagDescSize() {
return DistributionSetType.DESCRIPTION_MAX_SIZE;
}
@Override
protected int getTypeKeySize() {
return DistributionSetType.KEY_MAX_SIZE;
}
@Override
protected String getTagNameId() {
return UIComponentIdProvider.NEW_DISTRIBUTION_TYPE_NAME;
}
@Override
protected String getTagDescId() {
return UIComponentIdProvider.NEW_DISTRIBUTION_TYPE_DESC;
}
@Override
protected String getTypeKeyId() {
return UIComponentIdProvider.NEW_DISTRIBUTION_TYPE_KEY;
}
@Override
protected void resetFields() {
super.resetFields();
twinTables.reset();
}
@Override
protected Optional<DistributionSetType> findEntityByKey() {
return distributionSetTypeManagement.getByKey(getTypeKey().getValue());
}
@Override
protected String getDuplicateKeyErrorMessage(final DistributionSetType existingType) {
return getI18n().getMessage("message.type.key.duplicate.check", existingType.getKey());
}
@Override
protected Optional<DistributionSetType> findEntityByName() {
return distributionSetTypeManagement.getByName(getTagName().getValue());
}
public DistributionSetTypeSoftwareModuleSelectLayout getTwinTables() {
return twinTables;
}
public DistributionSetTypeManagement getDistributionSetTypeManagement() {
return distributionSetTypeManagement;
}
public SoftwareModuleTypeManagement getSoftwareModuleTypeManagement() {
return softwareModuleTypeManagement;
}
}

View File

@@ -0,0 +1,107 @@
/**
* 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.distributions.disttype;
import java.util.List;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper;
import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTypeEvent;
import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTypeEvent.DistributionSetTypeEnum;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.springframework.util.CollectionUtils;
import org.vaadin.spring.events.EventBus.UIEventBus;
/**
* Layout for pop-up window for creating a new Distribution Set Type on
* Distribution View. Logic for storing the new entity.
*/
public class CreateDistributionSetTypeLayout extends AbstractDistributionSetTypeLayout {
private static final long serialVersionUID = 1L;
/**
* Constructor
*
* @param i18n
* VaadinMessageSource
* @param entityFactory
* EntityFactory
* @param eventBus
* UIEventBus
* @param permChecker
* SpPermissionChecker
* @param uiNotification
* UINotification
* @param softwareModuleTypeManagement
* SoftwareModuleTypeManagement
* @param distributionSetTypeManagement
* DistributionSetTypeManagement
*/
public CreateDistributionSetTypeLayout(final VaadinMessageSource i18n, final EntityFactory entityFactory,
final UIEventBus eventBus, final SpPermissionChecker permChecker, final UINotification uiNotification,
final SoftwareModuleTypeManagement softwareModuleTypeManagement,
final DistributionSetTypeManagement distributionSetTypeManagement) {
super(i18n, entityFactory, eventBus, permChecker, uiNotification, distributionSetTypeManagement,
softwareModuleTypeManagement);
}
@Override
protected String getWindowCaption() {
return getI18n().getMessage("caption.create.new", getI18n().getMessage("caption.type"));
}
@Override
protected void saveEntity() {
createNewDistributionSetType();
}
@SuppressWarnings("unchecked")
private void createNewDistributionSetType() {
final String colorPicked = ColorPickerHelper.getColorPickedString(getColorPickerLayout().getSelPreview());
final String typeNameValue = getTagName().getValue();
final String typeKeyValue = getTypeKey().getValue();
final String typeDescValue = getTagDesc().getValue();
final List<Long> itemIds = (List<Long>) getTwinTables().getSelectedTable().getItemIds();
if (typeNameValue != null && typeKeyValue != null && !CollectionUtils.isEmpty(itemIds)) {
final List<Long> mandatory = itemIds.stream()
.filter(itemId -> DistributionSetTypeSoftwareModuleSelectLayout
.isMandatoryModuleType(getTwinTables().getSelectedTable().getItem(itemId)))
.collect(Collectors.toList());
final List<Long> optional = itemIds.stream()
.filter(itemId -> DistributionSetTypeSoftwareModuleSelectLayout
.isOptionalModuleType(getTwinTables().getSelectedTable().getItem(itemId)))
.collect(Collectors.toList());
final DistributionSetType newDistType = getDistributionSetTypeManagement()
.create(getEntityFactory().distributionSetType().create().key(typeKeyValue).name(typeNameValue)
.description(typeDescValue).colour(colorPicked).mandatory(mandatory).optional(optional));
getUiNotification().displaySuccess(getI18n().getMessage("message.save.success", newDistType.getName()));
getEventBus().publish(this,
new DistributionSetTypeEvent(DistributionSetTypeEnum.ADD_DIST_SET_TYPE, newDistType));
} else {
getUiNotification().displayValidationError(getI18n().getMessage("message.error.missing.typenameorkey"));
}
}
@Override
protected boolean isUpdateAction() {
return false;
}
}

View File

@@ -1,614 +0,0 @@
/**
* 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.distributions.disttype;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.repository.builder.DistributionSetTypeUpdate;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerConstants;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper;
import org.eclipse.hawkbit.ui.common.DistributionSetTypeBeanQuery;
import org.eclipse.hawkbit.ui.common.builder.TextAreaBuilder;
import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTypeEvent;
import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTypeEvent.DistributionSetTypeEnum;
import org.eclipse.hawkbit.ui.layouts.CreateUpdateTypeLayout;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.springframework.data.domain.PageRequest;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory;
import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer;
import org.vaadin.spring.events.EventBus.UIEventBus;
import com.vaadin.data.Item;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.server.FontAwesome;
import com.vaadin.shared.ui.colorpicker.Color;
import com.vaadin.ui.AbstractSelect.ItemDescriptionGenerator;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.ValoTheme;
/**
* Window for create update Distribution Set Type.
*/
public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout<DistributionSetType> {
private static final long serialVersionUID = 1L;
private static final String DIST_TYPE_NAME = "name";
private static final String DIST_TYPE_DESCRIPTION = "description";
private static final String DIST_TYPE_MANDATORY = "mandatory";
private static final String STAR = " * ";
private final transient SoftwareModuleTypeManagement softwareModuleTypeManagement;
private final transient DistributionSetTypeManagement distributionSetTypeManagement;
private final transient DistributionSetManagement distributionSetManagement;
private HorizontalLayout distTypeSelectLayout;
private Table sourceTable;
private Table selectedTable;
private IndexedContainer selectedTableContainer;
private IndexedContainer sourceTableContainer;
private IndexedContainer originalSelectedTableContainer;
/**
* Constructor for {@link CreateUpdateDistSetTypeLayout}.
*
* @param i18n
* I18N
* @param entityFactory
* EntityFactory
* @param eventBus
* UIEventBus
* @param permChecker
* SpPermissionChecker
* @param uiNotification
* UINotification
* @param softwareModuleTypeManagement
* management for {@link SoftwareModuleType}s
* @param distributionSetTypeManagement
* DistributionSetTypeManagement
* @param distributionSetManagement
* DistributionSetManagement
*/
public CreateUpdateDistSetTypeLayout(final VaadinMessageSource i18n, final EntityFactory entityFactory,
final UIEventBus eventBus, final SpPermissionChecker permChecker, final UINotification uiNotification,
final SoftwareModuleTypeManagement softwareModuleTypeManagement,
final DistributionSetTypeManagement distributionSetTypeManagement,
final DistributionSetManagement distributionSetManagement) {
super(i18n, entityFactory, eventBus, permChecker, uiNotification);
this.softwareModuleTypeManagement = softwareModuleTypeManagement;
this.distributionSetTypeManagement = distributionSetTypeManagement;
this.distributionSetManagement = distributionSetManagement;
}
@Override
protected void createRequiredComponents() {
super.createRequiredComponents();
tagName = createTextField("textfield.name", SPUIDefinitions.DIST_SET_TYPE_NAME,
SPUIDefinitions.NEW_DISTRIBUTION_TYPE_NAME, DistributionSetType.NAME_MAX_SIZE);
typeKey = createTextField("textfield.key", SPUIDefinitions.DIST_SET_TYPE_KEY,
SPUIDefinitions.NEW_DISTRIBUTION_TYPE_KEY, DistributionSetType.KEY_MAX_SIZE);
tagDesc = new TextAreaBuilder(DistributionSetType.DESCRIPTION_MAX_SIZE)
.caption(i18n.getMessage("textfield.description"))
.styleName(ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.DIST_SET_TYPE_DESC)
.id(SPUIDefinitions.NEW_DISTRIBUTION_TYPE_DESC).buildTextComponent();
}
private TextField createTextField(final String in18Key, final String styleName, final String id,
final int maxSize) {
return new TextFieldBuilder(maxSize).caption(i18n.getMessage(in18Key))
.styleName(ValoTheme.TEXTFIELD_TINY + " " + styleName).required(true, i18n).id(id).buildTextComponent();
}
@Override
protected void buildLayout() {
super.buildLayout();
ColorPickerHelper.setRgbSliderValues(colorPickerLayout);
getFormLayout().addComponent(typeKey, 4);
distTypeSelectLayout = createTwinColumnLayout();
final VerticalLayout twinTableLayout = new VerticalLayout();
twinTableLayout.setSizeFull();
twinTableLayout.addComponent(distTypeSelectLayout);
mainLayout.addComponent(twinTableLayout, 2, 0);
}
@Override
protected Color getColorForColorPicker() {
final Optional<DistributionSetType> existedDistType = distributionSetTypeManagement
.getByName(tagNameComboBox.getValue().toString());
if (existedDistType.isPresent()) {
return existedDistType.get().getColour() != null
? ColorPickerHelper.rgbToColorConverter(existedDistType.get().getColour())
: ColorPickerHelper.rgbToColorConverter(ColorPickerConstants.DEFAULT_COLOR);
}
return ColorPickerHelper.rgbToColorConverter(ColorPickerConstants.DEFAULT_COLOR);
}
private HorizontalLayout createTwinColumnLayout() {
final HorizontalLayout twinColumnLayout = new HorizontalLayout();
twinColumnLayout.setSizeFull();
twinColumnLayout.setWidth("400px");
buildSourceTable();
buildSelectedTable();
final VerticalLayout selectButtonLayout = new VerticalLayout();
final Button selectButton = SPUIComponentProvider.getButton(UIComponentIdProvider.SELECT_DIST_TYPE, "", "",
"arrow-button", true, FontAwesome.FORWARD, SPUIButtonStyleSmallNoBorder.class);
selectButton.addClickListener(event -> addSMType());
final Button unSelectButton = SPUIComponentProvider.getButton("unselect-dist-type", "", "", "arrow-button",
true, FontAwesome.BACKWARD, SPUIButtonStyleSmallNoBorder.class);
unSelectButton.addClickListener(event -> removeSMType());
selectButtonLayout.addComponent(selectButton);
selectButtonLayout.addComponent(unSelectButton);
selectButtonLayout.setComponentAlignment(selectButton, Alignment.MIDDLE_CENTER);
selectButtonLayout.setComponentAlignment(unSelectButton, Alignment.MIDDLE_CENTER);
twinColumnLayout.addComponent(sourceTable);
twinColumnLayout.addComponent(selectButtonLayout);
twinColumnLayout.addComponent(selectedTable);
twinColumnLayout.setComponentAlignment(sourceTable, Alignment.MIDDLE_LEFT);
twinColumnLayout.setComponentAlignment(selectButtonLayout, Alignment.MIDDLE_CENTER);
twinColumnLayout.setComponentAlignment(selectedTable, Alignment.MIDDLE_RIGHT);
twinColumnLayout.setExpandRatio(sourceTable, 0.45F);
twinColumnLayout.setExpandRatio(selectButtonLayout, 0.07F);
twinColumnLayout.setExpandRatio(selectedTable, 0.48F);
sourceTable.setVisibleColumns(DIST_TYPE_NAME);
return twinColumnLayout;
}
private void buildSelectedTable() {
selectedTable = new Table();
selectedTable.setId(SPUIDefinitions.TWIN_TABLE_SELECTED_ID);
selectedTable.setSelectable(true);
selectedTable.setMultiSelect(true);
selectedTable.setSortEnabled(false);
selectedTable.addStyleName(ValoTheme.TABLE_NO_HORIZONTAL_LINES);
selectedTable.addStyleName(ValoTheme.TABLE_NO_STRIPES);
selectedTable.addStyleName(ValoTheme.TABLE_NO_VERTICAL_LINES);
selectedTable.addStyleName(ValoTheme.TABLE_SMALL);
selectedTable.addStyleName("dist_type_twin-table");
selectedTable.setSizeFull();
createSelectedTableContainer();
selectedTable.setContainerDataSource(selectedTableContainer);
addTooltTipToSelectedTable();
selectedTable.setImmediate(true);
selectedTable.setVisibleColumns(DIST_TYPE_NAME, DIST_TYPE_MANDATORY);
selectedTable.setColumnHeaders(i18n.getMessage("header.dist.twintable.selected"), STAR);
selectedTable.setColumnExpandRatio(DIST_TYPE_NAME, 0.75F);
selectedTable.setColumnExpandRatio(DIST_TYPE_MANDATORY, 0.25F);
selectedTable.setRequired(true);
}
private void addTooltTipToSelectedTable() {
selectedTable.setItemDescriptionGenerator(new ItemDescriptionGenerator() {
private static final long serialVersionUID = 99432397408575324L;
@Override
public String generateDescription(final Component source, final Object itemId, final Object propertyId) {
final Item item = selectedTable.getItem(itemId);
final String description = (String) (item.getItemProperty(DIST_TYPE_DESCRIPTION).getValue());
if (DIST_TYPE_NAME.equals(propertyId) && !StringUtils.isEmpty(description)) {
return i18n.getMessage("label.description") + description;
} else if (DIST_TYPE_MANDATORY.equals(propertyId)) {
return i18n.getMessage("tooltip.check.for.mandatory");
}
return null;
}
});
}
/**
*
*/
private void buildSourceTable() {
sourceTable = new Table();
sourceTable.setId(SPUIDefinitions.TWIN_TABLE_SOURCE_ID);
sourceTable.setSelectable(true);
sourceTable.setMultiSelect(true);
sourceTable.addStyleName(ValoTheme.TABLE_NO_HORIZONTAL_LINES);
sourceTable.addStyleName(ValoTheme.TABLE_NO_STRIPES);
sourceTable.addStyleName(ValoTheme.TABLE_NO_VERTICAL_LINES);
sourceTable.addStyleName(ValoTheme.TABLE_SMALL);
sourceTable.setImmediate(true);
sourceTable.setSizeFull();
sourceTable.addStyleName("dist_type_twin-table");
sourceTable.setSortEnabled(false);
sourceTableContainer = new IndexedContainer();
sourceTableContainer.addContainerProperty(DIST_TYPE_NAME, String.class, "");
sourceTableContainer.addContainerProperty(DIST_TYPE_DESCRIPTION, String.class, "");
sourceTable.setContainerDataSource(sourceTableContainer);
sourceTable.setVisibleColumns(DIST_TYPE_NAME);
sourceTable.setColumnHeaders(i18n.getMessage("header.dist.twintable.available"));
sourceTable.setColumnExpandRatio(DIST_TYPE_NAME, 1.0F);
getSourceTableData();
addTooltip();
sourceTable.select(sourceTable.firstItemId());
}
private void createSelectedTableContainer() {
selectedTableContainer = new IndexedContainer();
selectedTableContainer.addContainerProperty(DIST_TYPE_NAME, String.class, "");
selectedTableContainer.addContainerProperty(DIST_TYPE_DESCRIPTION, String.class, "");
selectedTableContainer.addContainerProperty(DIST_TYPE_MANDATORY, CheckBox.class, null);
}
private void createOriginalSelectedTableContainer() {
originalSelectedTableContainer = new IndexedContainer();
originalSelectedTableContainer.addContainerProperty(DIST_TYPE_NAME, String.class, "");
originalSelectedTableContainer.addContainerProperty(DIST_TYPE_DESCRIPTION, String.class, "");
originalSelectedTableContainer.addContainerProperty(DIST_TYPE_MANDATORY, CheckBox.class, null);
}
@SuppressWarnings("unchecked")
private void addSMType() {
final Set<Long> selectedIds = (Set<Long>) sourceTable.getValue();
if (selectedIds == null) {
return;
}
for (final Long id : selectedIds) {
addTargetTableData(id);
}
}
private void removeSMType() {
@SuppressWarnings("unchecked")
final Set<Long> selectedIds = (Set<Long>) selectedTable.getValue();
if (selectedIds == null) {
return;
}
for (final Long id : selectedIds) {
addSourceTableData(id);
selectedTable.removeItem(id);
}
}
@SuppressWarnings("unchecked")
private void getSourceTableData() {
sourceTableContainer.removeAllItems();
final Iterable<SoftwareModuleType> moduleTypeBeans = softwareModuleTypeManagement
.findAll(new PageRequest(0, 1_000));
Item saveTblitem;
for (final SoftwareModuleType swTypeTag : moduleTypeBeans) {
saveTblitem = sourceTableContainer.addItem(swTypeTag.getId());
saveTblitem.getItemProperty(DIST_TYPE_NAME).setValue(swTypeTag.getName());
saveTblitem.getItemProperty(DIST_TYPE_DESCRIPTION).setValue(swTypeTag.getDescription());
}
}
private void addTooltip() {
sourceTable.setItemDescriptionGenerator(new ItemDescriptionGenerator() {
private static final long serialVersionUID = 1L;
@Override
public String generateDescription(final Component source, final Object itemId, final Object propertyId) {
final Item item = sourceTable.getItem(itemId);
final String description = (String) item.getItemProperty(DIST_TYPE_DESCRIPTION).getValue();
if (DIST_TYPE_NAME.equals(propertyId) && !StringUtils.isEmpty(description)) {
return i18n.getMessage("label.description") + description;
}
return null;
}
});
}
private void addTargetTableData(final Long selectedId) {
getSelectedTableItemData(selectedId);
sourceTable.removeItem(selectedId);
}
@SuppressWarnings("unchecked")
private void getSelectedTableItemData(final Long id) {
Item saveTblitem;
if (selectedTableContainer != null) {
saveTblitem = selectedTableContainer.addItem(id);
saveTblitem.getItemProperty(DIST_TYPE_NAME).setValue(
sourceTable.getContainerDataSource().getItem(id).getItemProperty(DIST_TYPE_NAME).getValue());
final CheckBox mandatoryCheckBox = new CheckBox();
window.updateAllComponents(mandatoryCheckBox);
saveTblitem.getItemProperty(DIST_TYPE_MANDATORY).setValue(mandatoryCheckBox);
saveTblitem.getItemProperty(DIST_TYPE_DESCRIPTION).setValue(
sourceTable.getContainerDataSource().getItem(id).getItemProperty(DIST_TYPE_DESCRIPTION).getValue());
}
}
@SuppressWarnings("unchecked")
private void addSourceTableData(final Long selectedId) {
if (sourceTableContainer != null) {
Item saveTblitem;
saveTblitem = sourceTableContainer.addItem(selectedId);
saveTblitem.getItemProperty(DIST_TYPE_NAME).setValue(selectedTable.getContainerDataSource()
.getItem(selectedId).getItemProperty(DIST_TYPE_NAME).getValue());
saveTblitem.getItemProperty(DIST_TYPE_DESCRIPTION).setValue(selectedTable.getContainerDataSource()
.getItem(selectedId).getItemProperty(DIST_TYPE_DESCRIPTION).getValue());
}
}
/**
* Create new DistSet Type tag.
*/
@SuppressWarnings("unchecked")
private void createNewDistributionSetType() {
final String colorPicked = ColorPickerHelper.getColorPickedString(getColorPickerLayout().getSelPreview());
final String typeNameValue = tagName.getValue();
final String typeKeyValue = typeKey.getValue();
final String typeDescValue = tagDesc.getValue();
final List<Long> itemIds = (List<Long>) selectedTable.getItemIds();
if (typeNameValue != null && typeKeyValue != null && !CollectionUtils.isEmpty(itemIds)) {
final List<Long> mandatory = itemIds.stream()
.filter(itemId -> isMandatoryModuleType(selectedTable.getItem(itemId)))
.collect(Collectors.toList());
final List<Long> optional = itemIds.stream()
.filter(itemId -> isOptionalModuleType(selectedTable.getItem(itemId))).collect(Collectors.toList());
final DistributionSetType newDistType = distributionSetTypeManagement
.create(entityFactory.distributionSetType().create().key(typeKeyValue).name(typeNameValue)
.description(typeDescValue).colour(colorPicked).mandatory(mandatory).optional(optional));
uiNotification.displaySuccess(i18n.getMessage("message.save.success", newDistType.getName()));
eventBus.publish(this,
new DistributionSetTypeEvent(DistributionSetTypeEnum.ADD_DIST_SET_TYPE, newDistType));
} else {
uiNotification.displayValidationError(i18n.getMessage("message.error.missing.typenameorkey"));
}
}
private static boolean isMandatoryModuleType(final Item item) {
final CheckBox mandatoryCheckBox = (CheckBox) item.getItemProperty(DIST_TYPE_MANDATORY).getValue();
return mandatoryCheckBox.getValue();
}
private static boolean isOptionalModuleType(final Item item) {
return !isMandatoryModuleType(item);
}
/**
* update distributionSet Type.
*/
@SuppressWarnings("unchecked")
private void updateDistributionSetType(final DistributionSetType existingType) {
final List<Long> itemIds = (List<Long>) selectedTable.getItemIds();
final DistributionSetTypeUpdate update = entityFactory.distributionSetType().update(existingType.getId())
.description(tagDesc.getValue())
.colour(ColorPickerHelper.getColorPickedString(getColorPickerLayout().getSelPreview()));
if (distributionSetManagement.countByTypeId(existingType.getId()) <= 0 && !CollectionUtils.isEmpty(itemIds)) {
update.mandatory(itemIds.stream().filter(itemId -> isMandatoryModuleType(selectedTable.getItem(itemId)))
.collect(Collectors.toList()))
.optional(itemIds.stream().filter(itemId -> isOptionalModuleType(selectedTable.getItem(itemId)))
.collect(Collectors.toList()));
}
final DistributionSetType updateDistSetType = distributionSetTypeManagement.update(update);
uiNotification.displaySuccess(i18n.getMessage("message.update.success", updateDistSetType.getName()));
eventBus.publish(this,
new DistributionSetTypeEvent(DistributionSetTypeEnum.UPDATE_DIST_SET_TYPE, updateDistSetType));
}
/**
* reset the components.
*/
@Override
protected void reset() {
super.reset();
selectedTable.removeAllItems();
getSourceTableData();
}
/**
* Listener for option group - Create tag/Update.
*
* @param event
* ValueChangeEvent
*/
@Override
protected void optionValueChanged(final ValueChangeEvent event) {
super.optionValueChanged(event);
if (updateTagStr.equals(event.getProperty().getValue())) {
selectedTable.getContainerDataSource().removeAllItems();
getSourceTableData();
distTypeSelectLayout.setEnabled(false);
} else {
distTypeSelectLayout.setEnabled(true);
selectedTable.setEnabled(true);
selectedTable.getContainerDataSource().removeAllItems();
sourceTable.getContainerDataSource().removeAllItems();
getSourceTableData();
}
}
/**
* Populate DistributionSet Type name combo.
*/
@Override
public void populateTagNameCombo() {
tagNameComboBox.setContainerDataSource(getDistSetTypeLazyQueryContainer());
tagNameComboBox.setItemCaptionPropertyId(SPUILabelDefinitions.VAR_NAME);
}
/**
* Get the LazyQueryContainer instance for DistributionSetTypes.
*
* @return
*/
private static LazyQueryContainer getDistSetTypeLazyQueryContainer() {
final LazyQueryContainer disttypeContainer = HawkbitCommonUtil
.createLazyQueryContainer(new BeanQueryFactory<>(DistributionSetTypeBeanQuery.class));
disttypeContainer.addContainerProperty(SPUILabelDefinitions.VAR_NAME, String.class, "", true, true);
return disttypeContainer;
}
@Override
protected void resetTagNameField() {
super.resetTagNameField();
typeKey.setEnabled(false);
typeKey.clear();
selectedTable.removeAllItems();
getSourceTableData();
}
/**
* Select tag & set tag name & tag desc values corresponding to selected
* tag.
*
* @param targetTagSelected
* as the selected tag from combo
*/
@Override
protected void setTagDetails(final String distSetTypeSelected) {
tagName.setValue(distSetTypeSelected);
getSourceTableData();
selectedTable.getContainerDataSource().removeAllItems();
distributionSetTypeManagement.getByName(distSetTypeSelected).ifPresent(selectedTypeTag -> {
tagDesc.setValue(selectedTypeTag.getDescription());
typeKey.setValue(selectedTypeTag.getKey());
if (distributionSetManagement.countByTypeId(selectedTypeTag.getId()) <= 0) {
distTypeSelectLayout.setEnabled(true);
selectedTable.setEnabled(true);
} else {
uiNotification.displayValidationError(
selectedTypeTag.getName() + " " + i18n.getMessage("message.error.dist.set.type.update"));
distTypeSelectLayout.setEnabled(false);
selectedTable.setEnabled(false);
}
createOriginalSelectedTableContainer();
selectedTypeTag.getOptionalModuleTypes()
.forEach(swModuleType -> addTargetTableforUpdate(swModuleType, false));
selectedTypeTag.getMandatoryModuleTypes()
.forEach(swModuleType -> addTargetTableforUpdate(swModuleType, true));
setColorPickerComponentsColor(selectedTypeTag.getColour());
});
}
@SuppressWarnings("unchecked")
private void addTargetTableforUpdate(final SoftwareModuleType swModuleType, final boolean mandatory) {
if (selectedTableContainer == null) {
return;
}
final Item saveTblitem = selectedTableContainer.addItem(swModuleType.getId());
sourceTable.removeItem(swModuleType.getId());
saveTblitem.getItemProperty(DIST_TYPE_NAME).setValue(swModuleType.getName());
final CheckBox mandatoryCheckbox = new CheckBox("", mandatory);
mandatoryCheckbox.setId(swModuleType.getName());
saveTblitem.getItemProperty(DIST_TYPE_MANDATORY).setValue(mandatoryCheckbox);
final Item originalItem = originalSelectedTableContainer.addItem(swModuleType.getId());
originalItem.getItemProperty(DIST_TYPE_NAME).setValue(swModuleType.getName());
originalItem.getItemProperty(DIST_TYPE_MANDATORY).setValue(mandatoryCheckbox);
window.updateAllComponents(mandatoryCheckbox);
}
@Override
protected void updateEntity(final DistributionSetType entity) {
updateDistributionSetType(entity);
}
@Override
protected void createEntity() {
createNewDistributionSetType();
}
@Override
protected Optional<DistributionSetType> findEntityByKey() {
return distributionSetTypeManagement.getByKey(typeKey.getValue());
}
@Override
protected Optional<DistributionSetType> findEntityByName() {
return distributionSetTypeManagement.getByName(tagName.getValue());
}
@Override
protected String getDuplicateKeyErrorMessage(final DistributionSetType existingType) {
return i18n.getMessage("message.type.key.duplicate.check", existingType.getKey());
}
@Override
protected String getWindowCaption() {
return i18n.getMessage("caption.add.type");
}
@Override
protected void createOptionGroup(final boolean hasCreatePermission, final boolean hasUpdatePermission) {
super.createOptionGroup(hasCreatePermission, hasUpdatePermission);
optiongroup.setId(SPUIDefinitions.CREATE_OPTION_GROUP_DISTRIBUTION_SET_TYPE_ID);
}
}

View File

@@ -1,122 +0,0 @@
/**
* 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.distributions.disttype;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.ui.common.DistributionSetTypeBeanQuery;
import org.eclipse.hawkbit.ui.common.filterlayout.AbstractFilterButtons;
import org.eclipse.hawkbit.ui.dd.criteria.DistributionsViewClientCriterion;
import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTypeEvent;
import org.eclipse.hawkbit.ui.distributions.event.SaveActionWindowEvent;
import org.eclipse.hawkbit.ui.distributions.state.ManageDistUIState;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory;
import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer;
import org.vaadin.spring.events.EventBus.UIEventBus;
import org.vaadin.spring.events.EventScope;
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
/**
* Distribution Set Type filter buttons.
*/
public class DSTypeFilterButtons extends AbstractFilterButtons {
private static final long serialVersionUID = 771251569981876005L;
private final ManageDistUIState manageDistUIState;
private final DistributionsViewClientCriterion distributionsViewClientCriterion;
DSTypeFilterButtons(final UIEventBus eventBus, final ManageDistUIState manageDistUIState,
final DistributionsViewClientCriterion distributionsViewClientCriterion,
final DistributionSetTypeManagement distributionSetTypeManagement) {
super(eventBus, new DSTypeFilterButtonClick(eventBus, manageDistUIState, distributionSetTypeManagement));
this.manageDistUIState = manageDistUIState;
this.distributionsViewClientCriterion = distributionsViewClientCriterion;
}
@Override
protected String getButtonsTableId() {
return UIComponentIdProvider.DISTRIBUTION_SET_TYPE_TABLE_ID;
}
@Override
protected LazyQueryContainer createButtonsLazyQueryContainer() {
return HawkbitCommonUtil.createLazyQueryContainer(new BeanQueryFactory<>(DistributionSetTypeBeanQuery.class));
}
@Override
protected boolean isClickedByDefault(final String typeName) {
return manageDistUIState.getManageDistFilters().getClickedDistSetType() != null
&& manageDistUIState.getManageDistFilters().getClickedDistSetType().getName().equals(typeName);
}
@Override
protected String createButtonId(final String name) {
return UIComponentIdProvider.DS_TYPE_FILTER_BTN_ID + name;
}
@Override
protected DropHandler getFilterButtonDropHandler() {
return new DropHandler() {
private static final long serialVersionUID = 1L;
@Override
public AcceptCriterion getAcceptCriterion() {
return distributionsViewClientCriterion;
}
@Override
public void drop(final DragAndDropEvent event) {
/* Not required */
}
};
}
@Override
protected String getButtonWrapperData() {
return null;
}
@Override
protected String getButttonWrapperIdPrefix() {
return SPUIDefinitions.DISTRIBUTION_SET_TYPE_ID_PREFIXS;
}
@EventBusListenerMethod(scope = EventScope.UI)
void onEvent(final DistributionSetTypeEvent event) {
if (event.getDistributionSetTypeEnum() == DistributionSetTypeEvent.DistributionSetTypeEnum.ADD_DIST_SET_TYPE
|| event.getDistributionSetTypeEnum() == DistributionSetTypeEvent.DistributionSetTypeEnum.UPDATE_DIST_SET_TYPE) {
refreshTypeTable();
}
}
@EventBusListenerMethod(scope = EventScope.UI)
void onEvent(final SaveActionWindowEvent event) {
if (event == SaveActionWindowEvent.SAVED_DELETE_DIST_SET_TYPES) {
refreshTypeTable();
}
}
private void refreshTypeTable() {
setContainerDataSource(createButtonsLazyQueryContainer());
}
}

View File

@@ -1,98 +0,0 @@
/**
* 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.distributions.disttype;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.common.filterlayout.AbstractFilterHeader;
import org.eclipse.hawkbit.ui.distributions.event.DistributionsUIEvent;
import org.eclipse.hawkbit.ui.distributions.state.ManageDistUIState;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.spring.events.EventBus.UIEventBus;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.UI;
/**
* Distribution Set Type filter buttons header.
*/
public class DSTypeFilterHeader extends AbstractFilterHeader {
private static final long serialVersionUID = 3433417459392880222L;
private final ManageDistUIState manageDistUIState;
private final CreateUpdateDistSetTypeLayout createUpdateDistSetTypeLayout;
DSTypeFilterHeader(final VaadinMessageSource i18n, final SpPermissionChecker permChecker, final UIEventBus eventBus,
final ManageDistUIState manageDistUIState, final EntityFactory entityFactory,
final UINotification uiNotification, final SoftwareModuleTypeManagement softwareModuleTypeManagement,
final DistributionSetTypeManagement distributionSetTypeManagement,
final DistributionSetManagement distributionSetManagement) {
super(permChecker, eventBus, i18n);
this.manageDistUIState = manageDistUIState;
this.createUpdateDistSetTypeLayout = new CreateUpdateDistSetTypeLayout(i18n, entityFactory, eventBus,
permChecker, uiNotification, softwareModuleTypeManagement, distributionSetTypeManagement,
distributionSetManagement);
if (hasCreateUpdatePermission()) {
createUpdateDistSetTypeLayout.init();
}
}
@Override
protected boolean hasCreateUpdatePermission() {
return permChecker.hasCreateRepositoryPermission() || permChecker.hasUpdateRepositoryPermission();
}
@Override
protected String getTitle() {
return SPUILabelDefinitions.TYPE;
}
@Override
protected void settingsIconClicked(final ClickEvent event) {
final CommonDialogWindow addUpdateWindow = createUpdateDistSetTypeLayout.getWindow();
UI.getCurrent().addWindow(addUpdateWindow);
}
@Override
protected boolean dropHitsRequired() {
return false;
}
@Override
protected void hideFilterButtonLayout() {
manageDistUIState.setDistTypeFilterClosed(true);
eventBus.publish(this, DistributionsUIEvent.HIDE_DIST_FILTER_BY_TYPE);
}
@Override
protected String getConfigureFilterButtonId() {
return SPUIDefinitions.ADD_DISTRIBUTION_TYPE_TAG;
}
@Override
protected String getHideButtonId() {
return SPUIDefinitions.HIDE_FILTER_DIST_TYPE;
}
@Override
protected boolean isAddTagRequired() {
return true;
}
}

View File

@@ -0,0 +1,330 @@
/**
* 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.distributions.disttype;
import java.util.Set;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleNoBorder;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.springframework.data.domain.PageRequest;
import org.springframework.util.StringUtils;
import com.vaadin.data.Item;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.server.FontAwesome;
import com.vaadin.ui.AbstractSelect.ItemDescriptionGenerator;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Table;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.ValoTheme;
/**
* Layout for the software modules select tables for managing Distribution Set
* Types on the Distributions View.
*/
public class DistributionSetTypeSoftwareModuleSelectLayout extends VerticalLayout {
private static final long serialVersionUID = 1L;
private static final String DIST_TYPE_DESCRIPTION = "description";
private static final String DIST_TYPE_MANDATORY = "mandatory";
private static final String STAR = " * ";
private static final String DIST_TYPE_NAME = "name";
private final transient SoftwareModuleTypeManagement softwareModuleTypeManagement;
private Table selectedTable;
private Table sourceTable;
private IndexedContainer selectedTableContainer;
private IndexedContainer sourceTableContainer;
private HorizontalLayout distTypeSelectLayout;
private final VaadinMessageSource i18n;
/**
* Constructor
*
* @param i18n
* VaadinMessageSource
* @param softwareModuleTypeManagement
* SoftwareModuleTypeManagement
*/
public DistributionSetTypeSoftwareModuleSelectLayout(final VaadinMessageSource i18n,
final SoftwareModuleTypeManagement softwareModuleTypeManagement) {
this.softwareModuleTypeManagement = softwareModuleTypeManagement;
this.i18n = i18n;
init();
}
protected void init() {
distTypeSelectLayout = createTwinColumnLayout();
setSizeFull();
addComponent(distTypeSelectLayout);
}
private HorizontalLayout createTwinColumnLayout() {
final HorizontalLayout twinColumnLayout = new HorizontalLayout();
twinColumnLayout.setSizeFull();
twinColumnLayout.setWidth("400px");
buildSourceTable();
buildSelectedTable();
final VerticalLayout selectButtonLayout = new VerticalLayout();
final Button selectButton = SPUIComponentProvider.getButton(UIComponentIdProvider.SELECT_DIST_TYPE, "", "",
"arrow-button", true, FontAwesome.FORWARD, SPUIButtonStyleNoBorder.class);
selectButton.addClickListener(event -> addSMType());
final Button unSelectButton = SPUIComponentProvider.getButton("unselect-dist-type", "", "", "arrow-button",
true, FontAwesome.BACKWARD, SPUIButtonStyleNoBorder.class);
unSelectButton.addClickListener(event -> removeSMType());
selectButtonLayout.addComponent(selectButton);
selectButtonLayout.addComponent(unSelectButton);
selectButtonLayout.setComponentAlignment(selectButton, Alignment.MIDDLE_CENTER);
selectButtonLayout.setComponentAlignment(unSelectButton, Alignment.MIDDLE_CENTER);
twinColumnLayout.addComponent(sourceTable);
twinColumnLayout.addComponent(selectButtonLayout);
twinColumnLayout.addComponent(selectedTable);
twinColumnLayout.setComponentAlignment(sourceTable, Alignment.MIDDLE_LEFT);
twinColumnLayout.setComponentAlignment(selectButtonLayout, Alignment.MIDDLE_CENTER);
twinColumnLayout.setComponentAlignment(selectedTable, Alignment.MIDDLE_RIGHT);
twinColumnLayout.setExpandRatio(sourceTable, 0.45F);
twinColumnLayout.setExpandRatio(selectButtonLayout, 0.07F);
twinColumnLayout.setExpandRatio(selectedTable, 0.48F);
sourceTable.setVisibleColumns(DIST_TYPE_NAME);
return twinColumnLayout;
}
private void buildSelectedTable() {
selectedTable = new Table();
selectedTable.setId(SPUIDefinitions.TWIN_TABLE_SELECTED_ID);
selectedTable.setSelectable(true);
selectedTable.setMultiSelect(true);
selectedTable.setSortEnabled(false);
selectedTable.addStyleName(ValoTheme.TABLE_NO_HORIZONTAL_LINES);
selectedTable.addStyleName(ValoTheme.TABLE_NO_STRIPES);
selectedTable.addStyleName(ValoTheme.TABLE_NO_VERTICAL_LINES);
selectedTable.addStyleName(ValoTheme.TABLE_SMALL);
selectedTable.addStyleName("dist_type_twin-table");
selectedTable.setSizeFull();
createSelectedTableContainer();
selectedTable.setContainerDataSource(selectedTableContainer);
addTooltTipToSelectedTable();
selectedTable.setImmediate(true);
selectedTable.setVisibleColumns(DIST_TYPE_NAME, DIST_TYPE_MANDATORY);
selectedTable.setColumnHeaders(i18n.getMessage("header.dist.twintable.selected"), STAR);
selectedTable.setColumnExpandRatio(DIST_TYPE_NAME, 0.75F);
selectedTable.setColumnExpandRatio(DIST_TYPE_MANDATORY, 0.25F);
selectedTable.setRequired(true);
}
private void addTooltTipToSelectedTable() {
selectedTable.setItemDescriptionGenerator(new ItemDescriptionGenerator() {
private static final long serialVersionUID = 1L;
@Override
public String generateDescription(final Component source, final Object itemId, final Object propertyId) {
final Item item = selectedTable.getItem(itemId);
final String description = (String) (item.getItemProperty(DIST_TYPE_DESCRIPTION).getValue());
if (DIST_TYPE_NAME.equals(propertyId) && !StringUtils.isEmpty(description)) {
return i18n.getMessage("label.description") + description;
} else if (DIST_TYPE_MANDATORY.equals(propertyId)) {
return i18n.getMessage("tooltip.check.for.mandatory");
}
return null;
}
});
}
private void buildSourceTable() {
sourceTable = new Table();
sourceTable.setId(SPUIDefinitions.TWIN_TABLE_SOURCE_ID);
sourceTable.setSelectable(true);
sourceTable.setMultiSelect(true);
sourceTable.addStyleName(ValoTheme.TABLE_NO_HORIZONTAL_LINES);
sourceTable.addStyleName(ValoTheme.TABLE_NO_STRIPES);
sourceTable.addStyleName(ValoTheme.TABLE_NO_VERTICAL_LINES);
sourceTable.addStyleName(ValoTheme.TABLE_SMALL);
sourceTable.setImmediate(true);
sourceTable.setSizeFull();
sourceTable.addStyleName("dist_type_twin-table");
sourceTable.setSortEnabled(false);
sourceTableContainer = new IndexedContainer();
sourceTableContainer.addContainerProperty(DIST_TYPE_NAME, String.class, "");
sourceTableContainer.addContainerProperty(DIST_TYPE_DESCRIPTION, String.class, "");
sourceTable.setContainerDataSource(sourceTableContainer);
sourceTable.setVisibleColumns(DIST_TYPE_NAME);
sourceTable.setColumnHeaders(i18n.getMessage("header.dist.twintable.available"));
sourceTable.setColumnExpandRatio(DIST_TYPE_NAME, 1.0F);
createSourceTableData();
addTooltip();
sourceTable.select(sourceTable.firstItemId());
}
@SuppressWarnings("unchecked")
protected void createSourceTableData() {
sourceTableContainer.removeAllItems();
final Iterable<SoftwareModuleType> moduleTypeBeans = softwareModuleTypeManagement
.findAll(new PageRequest(0, 1000));
Item saveTblitem;
for (final SoftwareModuleType swTypeTag : moduleTypeBeans) {
saveTblitem = sourceTableContainer.addItem(swTypeTag.getId());
saveTblitem.getItemProperty(DIST_TYPE_NAME).setValue(swTypeTag.getName());
saveTblitem.getItemProperty(DIST_TYPE_DESCRIPTION).setValue(swTypeTag.getDescription());
}
}
protected void addTooltip() {
sourceTable.setItemDescriptionGenerator(new ItemDescriptionGenerator() {
private static final long serialVersionUID = 1L;
@Override
public String generateDescription(final Component source, final Object itemId, final Object propertyId) {
final Item item = sourceTable.getItem(itemId);
final String description = (String) item.getItemProperty(DIST_TYPE_DESCRIPTION).getValue();
if (DIST_TYPE_NAME.equals(propertyId) && !StringUtils.isEmpty(description)) {
return i18n.getMessage("label.description") + description;
}
return null;
}
});
}
protected void createSelectedTableContainer() {
selectedTableContainer = new IndexedContainer();
selectedTableContainer.addContainerProperty(DIST_TYPE_NAME, String.class, "");
selectedTableContainer.addContainerProperty(DIST_TYPE_DESCRIPTION, String.class, "");
selectedTableContainer.addContainerProperty(DIST_TYPE_MANDATORY, CheckBox.class, null);
}
@SuppressWarnings("unchecked")
private void addSMType() {
final Set<Long> selectedIds = (Set<Long>) sourceTable.getValue();
if (selectedIds == null) {
return;
}
for (final Long id : selectedIds) {
addTargetTableData(id);
}
}
private void addTargetTableData(final Long selectedId) {
getSelectedTableItemData(selectedId);
sourceTable.removeItem(selectedId);
}
@SuppressWarnings("unchecked")
private void getSelectedTableItemData(final Long id) {
Item saveTblitem;
if (selectedTableContainer != null) {
saveTblitem = selectedTableContainer.addItem(id);
saveTblitem.getItemProperty(DIST_TYPE_NAME).setValue(
sourceTable.getContainerDataSource().getItem(id).getItemProperty(DIST_TYPE_NAME).getValue());
final CheckBox mandatoryCheckBox = new CheckBox();
saveTblitem.getItemProperty(DIST_TYPE_MANDATORY).setValue(mandatoryCheckBox);
saveTblitem.getItemProperty(DIST_TYPE_DESCRIPTION).setValue(
sourceTable.getContainerDataSource().getItem(id).getItemProperty(DIST_TYPE_DESCRIPTION).getValue());
}
}
@SuppressWarnings("unchecked")
private void addSourceTableData(final Long selectedId) {
if (sourceTableContainer != null) {
Item saveTblitem;
saveTblitem = sourceTableContainer.addItem(selectedId);
saveTblitem.getItemProperty(DIST_TYPE_NAME).setValue(selectedTable.getContainerDataSource()
.getItem(selectedId).getItemProperty(DIST_TYPE_NAME).getValue());
saveTblitem.getItemProperty(DIST_TYPE_DESCRIPTION).setValue(selectedTable.getContainerDataSource()
.getItem(selectedId).getItemProperty(DIST_TYPE_DESCRIPTION).getValue());
}
}
private void removeSMType() {
@SuppressWarnings("unchecked")
final Set<Long> selectedIds = (Set<Long>) selectedTable.getValue();
if (selectedIds == null) {
return;
}
for (final Long id : selectedIds) {
addSourceTableData(id);
selectedTable.removeItem(id);
}
}
public Table getSelectedTable() {
return selectedTable;
}
public static String getDistTypeMandatory() {
return DIST_TYPE_MANDATORY;
}
public static String getDistTypeDescription() {
return DIST_TYPE_DESCRIPTION;
}
public static String getDistTypeName() {
return DIST_TYPE_NAME;
}
public Table getSourceTable() {
return sourceTable;
}
public IndexedContainer getSourceTableContainer() {
return sourceTableContainer;
}
protected static boolean isMandatoryModuleType(final Item item) {
final CheckBox mandatoryCheckBox = (CheckBox) item.getItemProperty(getDistTypeMandatory()).getValue();
return mandatoryCheckBox.getValue();
}
public IndexedContainer getSelectedTableContainer() {
return selectedTableContainer;
}
protected static boolean isOptionalModuleType(final Item item) {
return !isMandatoryModuleType(item);
}
public HorizontalLayout getDistTypeSelectLayout() {
return distTypeSelectLayout;
}
public void setDistTypeSelectLayout(final HorizontalLayout distTypeSelectLayout) {
this.distTypeSelectLayout = distTypeSelectLayout;
}
/**
* Resets the tables for selecting the software modules
*/
public void reset() {
selectedTableContainer.removeAllItems();
createSourceTableData();
}
}

View File

@@ -0,0 +1,213 @@
/**
* 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.distributions.disttype;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.repository.builder.DistributionSetTypeUpdate;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper;
import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTypeEvent;
import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTypeEvent.DistributionSetTypeEnum;
import org.eclipse.hawkbit.ui.layouts.UpdateTag;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.springframework.util.CollectionUtils;
import org.vaadin.spring.events.EventBus.UIEventBus;
import com.vaadin.data.Item;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.Window.CloseListener;
/**
* Layout for the pop-up window which is created when updating a Distribution
* Set Type on the Distributions View.
*
*/
public class UpdateDistributionSetTypeLayout extends AbstractDistributionSetTypeLayout implements UpdateTag {
private static final long serialVersionUID = 1L;
private final transient DistributionSetManagement distributionSetManagement;
private final String selectedTypeName;
private IndexedContainer originalSelectedTableContainer;
private final CloseListener closeListener;
/**
* Constructor
*
* @param i18n
* VaadinMessageSource
* @param entityFactory
* EntityFactory
* @param eventBus
* UIEventBus
* @param permChecker
* SpPermissionChecker
* @param uiNotification
* UINotification
* @param softwareModuleTypeManagement
* SoftwareModuleTypeManagement
* @param distributionSetTypeManagement
* DistributionSetTypeManagement
* @param distributionSetManagement
* DistributionSetManagement
* @param selectedTypeName
* the name of the distribution set type to update
* @param closeListener
* CloseListener
*/
public UpdateDistributionSetTypeLayout(final VaadinMessageSource i18n, final EntityFactory entityFactory,
final UIEventBus eventBus, final SpPermissionChecker permChecker, final UINotification uiNotification,
final SoftwareModuleTypeManagement softwareModuleTypeManagement,
final DistributionSetTypeManagement distributionSetTypeManagement,
final DistributionSetManagement distributionSetManagement, final String selectedTypeName,
final CloseListener closeListener) {
super(i18n, entityFactory, eventBus, permChecker, uiNotification, distributionSetTypeManagement,
softwareModuleTypeManagement);
this.distributionSetManagement = distributionSetManagement;
this.selectedTypeName = selectedTypeName;
this.closeListener = closeListener;
initUpdatePopup();
}
private void initUpdatePopup() {
setTagDetails(selectedTypeName);
getWindow().addCloseListener(closeListener);
}
@Override
protected String getWindowCaption() {
return getI18n().getMessage("caption.update", getI18n().getMessage("caption.type"));
}
@Override
protected void saveEntity() {
updateDistributionSetType(findEntityByName()
.orElseThrow(() -> new EntityNotFoundException(DistributionSetType.class, getTagName().getValue())));
}
@Override
protected void buildLayout() {
super.buildLayout();
disableFields();
}
@Override
protected void disableFields() {
getTypeKey().setEnabled(false);
getTagName().setEnabled(false);
}
@Override
public void setTagDetails(final String selectedEntity) {
getTwinTables().createSourceTableData();
getTwinTables().getSelectedTable().getContainerDataSource().removeAllItems();
final Optional<DistributionSetType> selectedDistSetType = getDistributionSetTypeManagement()
.getByName(selectedEntity);
selectedDistSetType.ifPresent(selectedType -> {
getTagName().setValue(selectedType.getName());
getTagDesc().setValue(selectedType.getDescription());
getTypeKey().setValue(selectedType.getKey());
if (distributionSetManagement.countByTypeId(selectedType.getId()) <= 0) {
getTwinTables().getDistTypeSelectLayout().setEnabled(true);
getTwinTables().getSelectedTable().setEnabled(true);
} else {
getUiNotification().displayValidationError(
selectedType.getName() + " " + getI18n().getMessage("message.error.dist.set.type.update"));
getTwinTables().getDistTypeSelectLayout().setEnabled(false);
getTwinTables().getSelectedTable().setEnabled(false);
}
createOriginalSelectedTableContainer();
selectedType.getOptionalModuleTypes().forEach(swModuleType -> addTargetTableForUpdate(swModuleType, false));
selectedType.getMandatoryModuleTypes().forEach(swModuleType -> addTargetTableForUpdate(swModuleType, true));
setColorPickerComponentsColor(selectedType.getColour());
});
disableFields();
getWindow().setOrginaleValues();
}
private void createOriginalSelectedTableContainer() {
originalSelectedTableContainer = new IndexedContainer();
originalSelectedTableContainer.addContainerProperty(
DistributionSetTypeSoftwareModuleSelectLayout.getDistTypeName(), String.class, "");
originalSelectedTableContainer.addContainerProperty(
DistributionSetTypeSoftwareModuleSelectLayout.getDistTypeDescription(), String.class, "");
originalSelectedTableContainer.addContainerProperty(
DistributionSetTypeSoftwareModuleSelectLayout.getDistTypeMandatory(), CheckBox.class, null);
}
@SuppressWarnings("unchecked")
private void addTargetTableForUpdate(final SoftwareModuleType swModuleType, final boolean mandatory) {
if (getTwinTables().getSelectedTableContainer() == null) {
return;
}
final Item saveTblitem = getTwinTables().getSelectedTableContainer().addItem(swModuleType.getId());
getTwinTables().getSourceTable().removeItem(swModuleType.getId());
saveTblitem.getItemProperty(DistributionSetTypeSoftwareModuleSelectLayout.getDistTypeName())
.setValue(swModuleType.getName());
final CheckBox mandatoryCheckbox = new CheckBox("", mandatory);
mandatoryCheckbox.setId(swModuleType.getName());
saveTblitem.getItemProperty(DistributionSetTypeSoftwareModuleSelectLayout.getDistTypeMandatory())
.setValue(mandatoryCheckbox);
final Item originalItem = originalSelectedTableContainer.addItem(swModuleType.getId());
originalItem.getItemProperty(DistributionSetTypeSoftwareModuleSelectLayout.getDistTypeName())
.setValue(swModuleType.getName());
originalItem.getItemProperty(DistributionSetTypeSoftwareModuleSelectLayout.getDistTypeMandatory())
.setValue(mandatoryCheckbox);
getWindow().updateAllComponents(mandatoryCheckbox);
}
@SuppressWarnings("unchecked")
private void updateDistributionSetType(final DistributionSetType existingType) {
final List<Long> itemIds = (List<Long>) getTwinTables().getSelectedTable().getItemIds();
final DistributionSetTypeUpdate update = getEntityFactory().distributionSetType().update(existingType.getId())
.description(getTagDesc().getValue())
.colour(ColorPickerHelper.getColorPickedString(getColorPickerLayout().getSelPreview()));
if (distributionSetManagement.countByTypeId(existingType.getId()) <= 0 && !CollectionUtils.isEmpty(itemIds)) {
update.mandatory(itemIds.stream()
.filter(itemId -> DistributionSetTypeSoftwareModuleSelectLayout
.isMandatoryModuleType(getTwinTables().getSelectedTable().getItem(itemId)))
.collect(Collectors.toList()))
.optional(itemIds.stream()
.filter(itemId -> DistributionSetTypeSoftwareModuleSelectLayout
.isOptionalModuleType(getTwinTables().getSelectedTable().getItem(itemId)))
.collect(Collectors.toList()));
}
final DistributionSetType updateDistSetType = getDistributionSetTypeManagement().update(update);
getUiNotification().displaySuccess(getI18n().getMessage("message.update.success", updateDistSetType.getName()));
getEventBus().publish(this,
new DistributionSetTypeEvent(DistributionSetTypeEnum.UPDATE_DIST_SET_TYPE, updateDistSetType));
}
@Override
protected boolean isUpdateAction() {
return true;
}
}

View File

@@ -6,9 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.ui.distributions.disttype;
import java.io.Serializable;
package org.eclipse.hawkbit.ui.distributions.disttype.filter;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.ui.common.filterlayout.AbstractFilterSingleButtonClick;
@@ -22,7 +20,7 @@ import com.vaadin.ui.Button;
/**
* Single button click behaviour of filter buttons layout.
*/
public class DSTypeFilterButtonClick extends AbstractFilterSingleButtonClick implements Serializable {
public class DSTypeFilterButtonClick extends AbstractFilterSingleButtonClick {
private static final long serialVersionUID = 1L;

View File

@@ -0,0 +1,221 @@
/**
* 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.distributions.disttype.filter;
import java.util.Optional;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.common.DistributionSetTypeBeanQuery;
import org.eclipse.hawkbit.ui.common.event.DistributionSetTypeFilterHeaderEvent;
import org.eclipse.hawkbit.ui.common.event.FilterHeaderEvent.FilterHeaderEnum;
import org.eclipse.hawkbit.ui.common.filterlayout.AbstractFilterButtons;
import org.eclipse.hawkbit.ui.dd.criteria.DistributionsViewClientCriterion;
import org.eclipse.hawkbit.ui.distributions.disttype.UpdateDistributionSetTypeLayout;
import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTypeEvent;
import org.eclipse.hawkbit.ui.distributions.event.SaveActionWindowEvent;
import org.eclipse.hawkbit.ui.distributions.state.ManageDistUIState;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory;
import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer;
import org.vaadin.spring.events.EventBus.UIEventBus;
import org.vaadin.spring.events.EventScope;
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
import com.vaadin.ui.Button.ClickEvent;
/**
* Distribution Set Type filter buttons.
*/
public class DSTypeFilterButtons extends AbstractFilterButtons {
private static final long serialVersionUID = 1L;
private final ManageDistUIState manageDistUIState;
private final DistributionsViewClientCriterion distributionsViewClientCriterion;
private final transient EntityFactory entityFactory;
private final SpPermissionChecker permChecker;
private final UINotification uiNotification;
private final transient SoftwareModuleTypeManagement softwareModuleTypeManagement;
private final transient DistributionSetManagement distributionSetManagement;
private final transient DistributionSetTypeManagement distributionSetTypeManagement;
private final transient SystemManagement systemManagement;
/**
* Constructor
*
* @param eventBus
* UIEventBus
* @param manageDistUIState
* ManageDistUIState
* @param distributionsViewClientCriterion
* DistributionsViewClientCriterion
* @param distributionSetTypeManagement
* DistributionSetTypeManagement
* @param i18n
* VaadinMessageSource
* @param entityFactory
* EntityFactory
* @param permChecker
* SpPermissionChecker
* @param uiNotification
* UINotification
* @param softwareModuleTypeManagement
* SoftwareModuleTypeManagement
* @param distributionSetManagement
* DistributionSetManagement
* @param systemManagement
* SystemManagement
*/
public DSTypeFilterButtons(final UIEventBus eventBus, final ManageDistUIState manageDistUIState,
final DistributionsViewClientCriterion distributionsViewClientCriterion,
final DistributionSetTypeManagement distributionSetTypeManagement, final VaadinMessageSource i18n,
final EntityFactory entityFactory, final SpPermissionChecker permChecker,
final UINotification uiNotification, final SoftwareModuleTypeManagement softwareModuleTypeManagement,
final DistributionSetManagement distributionSetManagement, final SystemManagement systemManagement) {
super(eventBus, new DSTypeFilterButtonClick(eventBus, manageDistUIState, distributionSetTypeManagement), i18n);
this.manageDistUIState = manageDistUIState;
this.distributionsViewClientCriterion = distributionsViewClientCriterion;
this.entityFactory = entityFactory;
this.permChecker = permChecker;
this.uiNotification = uiNotification;
this.softwareModuleTypeManagement = softwareModuleTypeManagement;
this.distributionSetManagement = distributionSetManagement;
this.distributionSetTypeManagement = distributionSetTypeManagement;
this.systemManagement = systemManagement;
}
@Override
protected String getButtonsTableId() {
return UIComponentIdProvider.DISTRIBUTION_SET_TYPE_TABLE_ID;
}
@Override
protected LazyQueryContainer createButtonsLazyQueryContainer() {
return HawkbitCommonUtil.createLazyQueryContainer(new BeanQueryFactory<>(DistributionSetTypeBeanQuery.class));
}
@Override
protected boolean isClickedByDefault(final String typeName) {
return manageDistUIState.getManageDistFilters().getClickedDistSetType() != null
&& manageDistUIState.getManageDistFilters().getClickedDistSetType().getName().equals(typeName);
}
@Override
protected String createButtonId(final String name) {
return UIComponentIdProvider.DS_TYPE_FILTER_BTN_ID + name;
}
@Override
protected DropHandler getFilterButtonDropHandler() {
return new DropHandler() {
private static final long serialVersionUID = 1L;
@Override
public AcceptCriterion getAcceptCriterion() {
return distributionsViewClientCriterion;
}
@Override
public void drop(final DragAndDropEvent event) {
/* Not required */
}
};
}
@Override
protected String getButtonWrapperData() {
return null;
}
@Override
protected String getButttonWrapperIdPrefix() {
return SPUIDefinitions.DISTRIBUTION_SET_TYPE_ID_PREFIXS;
}
@EventBusListenerMethod(scope = EventScope.UI)
void onEvent(final DistributionSetTypeEvent event) {
if (event.getDistributionSetTypeEnum() == DistributionSetTypeEvent.DistributionSetTypeEnum.ADD_DIST_SET_TYPE
|| event.getDistributionSetTypeEnum() == DistributionSetTypeEvent.DistributionSetTypeEnum.UPDATE_DIST_SET_TYPE) {
refreshTable();
}
if (event
.getDistributionSetTypeEnum() == DistributionSetTypeEvent.DistributionSetTypeEnum.UPDATE_DIST_SET_TYPE) {
getEventBus().publish(this, new DistributionSetTypeFilterHeaderEvent(FilterHeaderEnum.SHOW_MENUBAR));
}
}
@EventBusListenerMethod(scope = EventScope.UI)
void onEvent(final SaveActionWindowEvent event) {
if (event == SaveActionWindowEvent.SAVED_DELETE_DIST_SET_TYPES) {
refreshTable();
}
}
@Override
protected void addEditButtonClickListener(final ClickEvent event) {
new UpdateDistributionSetTypeLayout(getI18n(), entityFactory, getEventBus(), permChecker, uiNotification,
softwareModuleTypeManagement, distributionSetTypeManagement, distributionSetManagement,
getEntityId(event), getCloseListenerForEditAndDeleteTag(
new DistributionSetTypeFilterHeaderEvent(FilterHeaderEnum.SHOW_MENUBAR)));
}
@Override
protected void addDeleteButtonClickListener(final ClickEvent event) {
openConfirmationWindowForDeletion(getEntityId(event), getI18n().getMessage("caption.entity.distribution.type"),
new DistributionSetTypeFilterHeaderEvent(FilterHeaderEnum.SHOW_MENUBAR));
}
@Override
protected void deleteEntity(final String entityToDelete) {
final Optional<DistributionSetType> distTypeToDelete = distributionSetTypeManagement.getByName(entityToDelete);
distTypeToDelete.ifPresent(tag -> {
if (tag.equals(manageDistUIState.getManageDistFilters().getClickedDistSetType())) {
uiNotification.displayValidationError(getI18n().getMessage("message.tag.delete", entityToDelete));
removeUpdateAndDeleteColumn();
} else if (isDefaultDsType(entityToDelete)) {
uiNotification.displayValidationError(getI18n().getMessage("message.cannot.delete.default.dstype"));
removeUpdateAndDeleteColumn();
} else {
distributionSetTypeManagement.delete(distTypeToDelete.get().getId());
getEventBus().publish(this, SaveActionWindowEvent.SAVED_DELETE_DIST_SET_TYPES);
uiNotification.displaySuccess(getI18n().getMessage("message.delete.success", entityToDelete));
}
});
}
private boolean isDefaultDsType(final String dsTypeName) {
return getCurrentDistributionSetType() != null && getCurrentDistributionSetType().getName().equals(dsTypeName);
}
private DistributionSetType getCurrentDistributionSetType() {
return systemManagement.getTenantMetadata().getDefaultDsType();
}
}

View File

@@ -0,0 +1,157 @@
/**
* 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.distributions.disttype.filter;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.common.event.DistributionSetTypeFilterHeaderEvent;
import org.eclipse.hawkbit.ui.common.event.FilterHeaderEvent.FilterHeaderEnum;
import org.eclipse.hawkbit.ui.common.filterlayout.AbstractFilterHeader;
import org.eclipse.hawkbit.ui.distributions.disttype.CreateDistributionSetTypeLayout;
import org.eclipse.hawkbit.ui.distributions.event.DistributionsUIEvent;
import org.eclipse.hawkbit.ui.distributions.state.ManageDistUIState;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.spring.events.EventBus.UIEventBus;
import org.vaadin.spring.events.EventScope;
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.MenuBar.Command;
/**
* Distribution Set Type filter buttons header.
*/
public class DSTypeFilterHeader extends AbstractFilterHeader {
private static final long serialVersionUID = 1L;
private final ManageDistUIState manageDistUIState;
private final transient EntityFactory entityFactory;
private final transient UINotification uiNotification;
private final transient SoftwareModuleTypeManagement softwareModuleTypeManagement;
private final transient DistributionSetTypeManagement distributionSetTypeManagement;
private final DSTypeFilterButtons dSTypeFilterButtons;
/**
* Constructor
*
* @param i18n
* VaadinMessageSource
* @param permChecker
* SpPermissionChecker
* @param eventBus
* UIEventBus
* @param manageDistUIState
* ManageDistUIState
* @param entityFactory
* EntityFactory
* @param uiNotification
* UINotification
* @param softwareModuleTypeManagement
* SoftwareModuleTypeManagement
* @param distributionSetTypeManagement
* DistributionSetTypeManagement
* @param dSTypeFilterButtons
* DSTypeFilterButtons
*/
DSTypeFilterHeader(final VaadinMessageSource i18n, final SpPermissionChecker permChecker, final UIEventBus eventBus,
final ManageDistUIState manageDistUIState, final EntityFactory entityFactory,
final UINotification uiNotification, final SoftwareModuleTypeManagement softwareModuleTypeManagement,
final DistributionSetTypeManagement distributionSetTypeManagement,
final DSTypeFilterButtons dSTypeFilterButtons) {
super(permChecker, eventBus, i18n);
this.manageDistUIState = manageDistUIState;
this.entityFactory = entityFactory;
this.softwareModuleTypeManagement = softwareModuleTypeManagement;
this.distributionSetTypeManagement = distributionSetTypeManagement;
this.uiNotification = uiNotification;
this.dSTypeFilterButtons = dSTypeFilterButtons;
}
@Override
protected String getTitle() {
return SPUILabelDefinitions.TYPE;
}
@Override
protected boolean dropHitsRequired() {
return false;
}
@Override
protected void hideFilterButtonLayout() {
manageDistUIState.setDistTypeFilterClosed(true);
getEventBus().publish(this, DistributionsUIEvent.HIDE_DIST_FILTER_BY_TYPE);
}
@Override
protected String getConfigureFilterButtonId() {
return UIComponentIdProvider.ADD_DISTRIBUTION_TYPE_TAG;
}
@Override
protected String getHideButtonId() {
return UIComponentIdProvider.HIDE_FILTER_DIST_TYPE;
}
@Override
protected boolean isAddTagRequired() {
return true;
}
@Override
protected Command getAddButtonCommand() {
return command -> new CreateDistributionSetTypeLayout(getI18n(), entityFactory, getEventBus(), getPermChecker(),
uiNotification, softwareModuleTypeManagement, distributionSetTypeManagement);
}
@Override
protected Command getDeleteButtonCommand() {
return command -> {
dSTypeFilterButtons.addDeleteColumn();
getEventBus().publish(this, new DistributionSetTypeFilterHeaderEvent(FilterHeaderEnum.SHOW_CANCEL_BUTTON));
};
}
@Override
protected Command getUpdateButtonCommand() {
return command -> {
dSTypeFilterButtons.addUpdateColumn();
getEventBus().publish(this, new DistributionSetTypeFilterHeaderEvent(FilterHeaderEnum.SHOW_CANCEL_BUTTON));
};
}
@Override
protected void cancelUpdateOrDeleteTag(final ClickEvent event) {
super.cancelUpdateOrDeleteTag(event);
dSTypeFilterButtons.removeUpdateAndDeleteColumn();
}
@EventBusListenerMethod(scope = EventScope.UI)
private void onEvent(final DistributionSetTypeFilterHeaderEvent event) {
processFilterHeaderEvent(event);
}
@Override
protected String getMenuBarId() {
return UIComponentIdProvider.DIST_TAG_MENU_BAR_ID;
}
}

View File

@@ -6,15 +6,13 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.ui.distributions.disttype;
package org.eclipse.hawkbit.ui.distributions.disttype.filter;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.common.filterlayout.AbstractFilterLayout;
import org.eclipse.hawkbit.ui.dd.criteria.DistributionsViewClientCriterion;
import org.eclipse.hawkbit.ui.distributions.event.DistributionsUIEvent;
import org.eclipse.hawkbit.ui.distributions.state.ManageDistUIState;
import org.eclipse.hawkbit.ui.utils.UINotification;
@@ -28,24 +26,42 @@ import org.vaadin.spring.events.annotation.EventBusListenerMethod;
*/
public class DSTypeFilterLayout extends AbstractFilterLayout {
private static final long serialVersionUID = 2689002932344750781L;
private static final long serialVersionUID = 1L;
private final ManageDistUIState manageDistUIState;
/**
* Constructor
*
* @param manageDistUIState
* ManageDistUIState
* @param i18n
* VaadinMessageSource
* @param permChecker
* SpPermissionChecker
* @param eventBus
* UIEventBus
* @param entityFactory
* EntityFactory
* @param uiNotification
* UINotification
* @param softwareModuleTypeManagement
* SoftwareModuleTypeManagement
* @param distributionSetTypeManagement
* DistributionSetTypeManagement
* @param dSTypeFilterButtons
* DSTypeFilterButtons
*/
public DSTypeFilterLayout(final ManageDistUIState manageDistUIState, final VaadinMessageSource i18n,
final SpPermissionChecker permChecker, final UIEventBus eventBus, final EntityFactory entityFactory,
final UINotification uiNotification, final SoftwareModuleTypeManagement softwareModuleTypeManagement,
final DistributionSetTypeManagement distributionSetTypeManagement,
final DistributionSetManagement distributionSetManagement,
final DistributionsViewClientCriterion distributionsViewClientCriterion) {
final DSTypeFilterButtons dSTypeFilterButtons) {
super(new DSTypeFilterHeader(i18n, permChecker, eventBus, manageDistUIState, entityFactory, uiNotification,
softwareModuleTypeManagement, distributionSetTypeManagement, distributionSetManagement),
new DSTypeFilterButtons(eventBus, manageDistUIState, distributionsViewClientCriterion,
distributionSetTypeManagement));
softwareModuleTypeManagement, distributionSetTypeManagement, dSTypeFilterButtons), dSTypeFilterButtons,
eventBus);
this.manageDistUIState = manageDistUIState;
restoreState();
eventBus.subscribe(this);
}
@EventBusListenerMethod(scope = EventScope.UI)
@@ -60,7 +76,6 @@ public class DSTypeFilterLayout extends AbstractFilterLayout {
@Override
public Boolean onLoadIsTypeFilterIsClosed() {
return manageDistUIState.isDistTypeFilterClosed();
}

View File

@@ -25,7 +25,7 @@ import org.eclipse.hawkbit.ui.common.detailslayout.SoftwareModuleDetailsTable;
import org.eclipse.hawkbit.ui.common.detailslayout.TargetFilterQueryDetailsTable;
import org.eclipse.hawkbit.ui.common.entity.SoftwareModuleIdName;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleNoBorder;
import org.eclipse.hawkbit.ui.distributions.event.SaveActionWindowEvent;
import org.eclipse.hawkbit.ui.distributions.state.ManageDistUIState;
import org.eclipse.hawkbit.ui.management.dstable.DistributionAddUpdateWindowLayout;
@@ -158,7 +158,7 @@ public class DistributionSetDetails extends AbstractDistributionSetDetails {
.map(selected -> targetManagement.countByAssignedDistributionSet(selected) <= 0).orElse(false)) {
final Button reassignSoftModule = SPUIComponentProvider.getButton(softwareModuleName, "", "", "", true,
FontAwesome.TIMES, SPUIButtonStyleSmallNoBorder.class);
FontAwesome.TIMES, SPUIButtonStyleNoBorder.class);
reassignSoftModule.setEnabled(false);
return reassignSoftModule;
}

View File

@@ -18,6 +18,7 @@ import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
@@ -29,14 +30,13 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent.SoftwareModuleEventType;
import org.eclipse.hawkbit.ui.common.ConfirmationDialog;
import org.eclipse.hawkbit.ui.common.entity.DistributionSetIdName;
import org.eclipse.hawkbit.ui.common.entity.SoftwareModuleIdName;
import org.eclipse.hawkbit.ui.common.table.AbstractNamedVersionTable;
import org.eclipse.hawkbit.ui.common.table.AbstractTable;
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.dd.criteria.DistributionsViewClientCriterion;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.distributions.event.DistributionsUIEvent;
import org.eclipse.hawkbit.ui.distributions.event.SaveActionWindowEvent;
import org.eclipse.hawkbit.ui.distributions.state.ManageDistUIState;
@@ -46,14 +46,10 @@ import org.eclipse.hawkbit.ui.push.DistributionSetUpdatedEventContainer;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
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.TableColumn;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.eclipse.hawkbit.ui.view.filter.OnlyEventsFromDistributionsViewFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory;
import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer;
import org.vaadin.addons.lazyquerycontainer.LazyQueryDefinition;
@@ -66,8 +62,6 @@ import com.vaadin.data.Container;
import com.vaadin.data.Item;
import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
import com.vaadin.server.FontAwesome;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component;
import com.vaadin.ui.Table;
import com.vaadin.ui.UI;
@@ -79,8 +73,6 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
private static final long serialVersionUID = 1L;
private static final Logger LOG = LoggerFactory.getLogger(DistributionSetTable.class);
private final SpPermissionChecker permissionChecker;
private final ManageDistUIState manageDistUIState;
@@ -93,22 +85,19 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
private final transient TargetManagement targetManagement;
private final DsMetadataPopupLayout dsMetadataPopupLayout;
DistributionSetTable(final UIEventBus eventBus, final VaadinMessageSource i18n, final UINotification notification,
final SpPermissionChecker permissionChecker, final ManageDistUIState manageDistUIState,
final DistributionSetManagement distributionSetManagement,
final SoftwareModuleManagement softwareManagement,
final DistributionsViewClientCriterion distributionsViewClientCriterion,
final TargetManagement targetManagement, final DsMetadataPopupLayout dsMetadataPopupLayout) {
super(eventBus, i18n, notification);
final TargetManagement targetManagement) {
super(eventBus, i18n, notification, permissionChecker);
this.permissionChecker = permissionChecker;
this.manageDistUIState = manageDistUIState;
this.distributionSetManagement = distributionSetManagement;
this.softwareModuleManagement = softwareManagement;
this.distributionsViewClientCriterion = distributionsViewClientCriterion;
this.targetManagement = targetManagement;
this.dsMetadataPopupLayout = dsMetadataPopupLayout;
addTableStyleGenerator();
addNewContainerDS();
setColumnProperties();
@@ -127,7 +116,7 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
manageDistUIState.getLastSelectedDistribution()
.ifPresent(lastSelectedDsIdName -> events.stream().filter(Objects::nonNull)
.filter(event -> event.getEntityId().equals(lastSelectedDsIdName)).findAny()
.ifPresent(event -> eventBus.publish(this,
.ifPresent(event -> getEventBus().publish(this,
new DistributionTableEvent(BaseEntityEventType.SELECTED_ENTITY, event.getEntity()))));
}
@@ -173,14 +162,10 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
Boolean.class, null, false, true);
}
@Override
protected boolean isFirstRowSelectedOnLoad() {
return manageDistUIState.getSelectedDistributions().isEmpty();
}
@Override
protected Object getItemIdToSelect() {
return isFirstRowSelectedOnLoad() ? null : manageDistUIState.getSelectedDistributions();
return manageDistUIState.getSelectedDistributions().isEmpty() ? null
: manageDistUIState.getSelectedDistributions();
}
@Override
@@ -195,12 +180,12 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
@Override
protected void afterEntityIsSelected() {
eventBus.publish(this, DistributionsUIEvent.ORDER_BY_DISTRIBUTION);
getEventBus().publish(this, DistributionsUIEvent.ORDER_BY_DISTRIBUTION);
}
@Override
protected void publishSelectedEntityEvent(final DistributionSet distributionSet) {
eventBus.publish(this, new DistributionTableEvent(BaseEntityEventType.SELECTED_ENTITY, distributionSet));
getEventBus().publish(this, new DistributionTableEvent(BaseEntityEventType.SELECTED_ENTITY, distributionSet));
}
@Override
@@ -217,13 +202,14 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
protected void onDropEventFromTable(final DragAndDropEvent event) {
final TableTransferable transferable = (TableTransferable) event.getTransferable();
final AbstractTable<?> source = (AbstractTable<?>) transferable.getSourceComponent();
final Set<Long> softwareModulesIdList = source.getDeletedEntityByTransferable(transferable);
final Set<Long> softwareModulesIdList = source.getSelectedEntitiesByTransferable(transferable);
selectDraggedEntities(source, softwareModulesIdList);
final AbstractSelectTargetDetails dropData = (AbstractSelectTargetDetails) event.getTargetDetails();
final Object distItemId = dropData.getItemIdOver();
if (distItemId != null) {
handleDropEvent(source, softwareModulesIdList, distItemId);
assignSwmToDs(source, softwareModulesIdList, (long) distItemId);
}
}
@@ -236,30 +222,44 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
protected boolean isDropValid(final DragAndDropEvent dragEvent) {
final Component compsource = dragEvent.getTransferable().getSourceComponent();
if (!(compsource instanceof Table)) {
notification.displayValidationError(i18n.getMessage(ACTION_NOT_ALLOWED_MSG));
getNotification().displayValidationError(getI18n().getMessage(ACTION_NOT_ALLOWED_MSG));
return false;
}
return super.isDropValid(dragEvent);
}
private void handleDropEvent(final Table source, final Set<Long> softwareModulesIdList, final Object distId) {
final Optional<DistributionSet> distributionSet = distributionSetManagement.get((Long) distId);
private void assignSwmToDs(final Table source, final Set<Long> softwareModulesIdList, final long distId) {
final Optional<DistributionSet> distributionSet = distributionSetManagement.get(distId);
distributionSet.ifPresent(set -> {
final DistributionSetIdName distributionSetIdName = new DistributionSetIdName(set);
selectDroppedEntities(distributionSetIdName.getId());
final HashMap<Long, HashSet<SoftwareModuleIdName>> map = createAssignmentMap(distributionSetIdName);
handleSoftwareModulesForAssignment(source, softwareModulesIdList, distId, map);
final HashSet<SoftwareModuleIdName> softwareModules = new HashSet<>();
map.keySet().forEach(typeId -> softwareModules.addAll(map.get(typeId)));
manageDistUIState.getAssignedList().put(distributionSetIdName, softwareModules);
openConfirmationWindowForAssignment(distributionSetIdName.getName(),
softwareModules.toArray(new SoftwareModuleIdName[softwareModules.size()]));
});
if (!distributionSet.isPresent()) {
notification.displayWarning(i18n.getMessage("distributionset.not.exists"));
return;
getNotification().displayWarning(getI18n().getMessage("distributionset.not.exists"));
}
}
final DistributionSetIdName distributionSetIdName = new DistributionSetIdName(distributionSet.get());
private HashMap<Long, HashSet<SoftwareModuleIdName>> createAssignmentMap(
final DistributionSetIdName distributionSetIdName) {
final HashMap<Long, HashSet<SoftwareModuleIdName>> map;
if (manageDistUIState.getConsolidatedDistSoftwarewList().containsKey(distributionSetIdName)) {
map = manageDistUIState.getConsolidatedDistSoftwarewList().get(distributionSetIdName);
if (manageDistUIState.getConsolidatedDistSoftwareList().containsKey(distributionSetIdName)) {
map = manageDistUIState.getConsolidatedDistSoftwareList().get(distributionSetIdName);
} else {
map = new HashMap<>();
manageDistUIState.getConsolidatedDistSoftwarewList().put(distributionSetIdName, map);
manageDistUIState.getConsolidatedDistSoftwareList().put(distributionSetIdName, map);
}
return map;
}
private void handleSoftwareModulesForAssignment(final Table source, final Set<Long> softwareModulesIdList,
final long distId, final HashMap<Long, HashSet<SoftwareModuleIdName>> map) {
for (final Long softwareModuleId : softwareModulesIdList) {
final Item softwareItem = source.getContainerDataSource().getItem(softwareModuleId);
final String name = (String) softwareItem.getItemProperty(SPUILabelDefinitions.VAR_NAME).getValue();
@@ -267,27 +267,19 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
final Optional<SoftwareModule> softwareModule = softwareModuleManagement.get(softwareModuleId);
if (softwareModule.isPresent() && validSoftwareModule((Long) distId, softwareModule.get())) {
if (softwareModule.isPresent() && validSoftwareModule(distId, softwareModule.get())) {
final SoftwareModuleIdName softwareModuleIdName = new SoftwareModuleIdName(softwareModuleId,
name.concat(":" + swVersion));
publishAssignEvent((Long) distId, softwareModule.get());
publishAssignEvent(distId, softwareModule.get());
handleSoftwareCase(map, softwareModule.get(), softwareModuleIdName);
handleFirmwareCase(map, softwareModule.get(), softwareModuleIdName);
} else {
return;
}
}
// hashset is seriablizable
final HashSet<SoftwareModuleIdName> softwareModules = new HashSet<>();
map.keySet().forEach(typeId -> softwareModules.addAll(map.get(typeId)));
updateDropedDetails(distributionSetIdName, softwareModules);
}
private void publishAssignEvent(final Long distId, final SoftwareModule softwareModule) {
if (manageDistUIState.getLastSelectedDistribution().map(distId::equals).orElse(false)) {
eventBus.publish(this,
getEventBus().publish(this,
new SoftwareModuleEvent(SoftwareModuleEventType.ASSIGN_SOFTWARE_MODULE, softwareModule));
}
}
@@ -313,11 +305,56 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
}
}
private void updateDropedDetails(final DistributionSetIdName distributionSetIdName,
final HashSet<SoftwareModuleIdName> softwareModules) {
LOG.debug("Adding a log to check if distributionSetIdName is null : {} ", distributionSetIdName);
manageDistUIState.getAssignedList().put(distributionSetIdName, softwareModules);
eventBus.publish(this, DistributionsUIEvent.UPDATE_COUNT);
private void openConfirmationWindowForAssignment(final String distributionNameToAssign,
final SoftwareModuleIdName[] softwareModules) {
final String confirmQuestion = createConfirmationMessageForAssignment(distributionNameToAssign,
softwareModules);
final ConfirmationDialog confirmDialog = createConfirmationWindowForAssignment(confirmQuestion);
UI.getCurrent().addWindow(confirmDialog.getWindow());
confirmDialog.getWindow().bringToFront();
}
private ConfirmationDialog createConfirmationWindowForAssignment(final String confirmQuestion) {
return new ConfirmationDialog(getI18n().getMessage(CAPTION_ENTITY_ASSIGN_ACTION_CONFIRMBOX), confirmQuestion,
getI18n().getMessage(SPUIDefinitions.BUTTON_OK), getI18n().getMessage(SPUIDefinitions.BUTTON_CANCEL),
ok -> {
if (ok) {
saveAllAssignments();
} else {
manageDistUIState.getAssignedList().clear();
manageDistUIState.getConsolidatedDistSoftwareList().clear();
}
}, UIComponentIdProvider.SOFT_MODULE_TO_DIST_ASSIGNMENT_CONFIRM_ID);
}
private String createConfirmationMessageForAssignment(final String distributionNameToAssign,
final SoftwareModuleIdName[] softwareModules) {
if (softwareModules.length == 1) {
return getI18n().getMessage(MESSAGE_CONFIRM_ASSIGN_ENTITY, distributionNameToAssign, "software module",
softwareModules[0].getName());
} else {
return getI18n().getMessage(MESSAGE_CONFIRM_ASSIGN_MULTIPLE_ENTITIES, softwareModules.length,
"software modules", distributionNameToAssign);
}
}
private void saveAllAssignments() {
manageDistUIState.getAssignedList().forEach((distIdName, softIdNameSet) -> {
final List<Long> softIds = softIdNameSet.stream().map(softIdName -> softIdName.getId())
.collect(Collectors.toList());
distributionSetManagement.assignSoftwareModules(distIdName.getId(), softIds);
});
int count = 0;
for (final Entry<DistributionSetIdName, HashSet<SoftwareModuleIdName>> entry : manageDistUIState
.getAssignedList().entrySet()) {
count += entry.getValue().size();
}
getNotification().displaySuccess(getI18n().getMessage("message.software.assignment", count));
manageDistUIState.getAssignedList().clear();
manageDistUIState.getConsolidatedDistSoftwareList().clear();
getEventBus().publish(this, SaveActionWindowEvent.SAVED_ASSIGNMENTS);
}
private boolean validSoftwareModule(final Long distId, final SoftwareModule sm) {
@@ -330,8 +367,8 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
}
if (distributionSetManagement.isInUse(ds.get().getId())) {
notification.displayValidationError(i18n.getMessage("message.error.notification.ds.target.assigned",
ds.get().getName(), ds.get().getVersion()));
getNotification().displayValidationError(getI18n().getMessage(
"message.error.notification.ds.target.assigned", ds.get().getName(), ds.get().getVersion()));
return false;
}
return true;
@@ -340,14 +377,14 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
private boolean validateSoftwareModule(final SoftwareModule sm, final DistributionSet ds) {
if (targetManagement.countByFilters(null, null, null, ds.getId(), Boolean.FALSE, new String[] {}) > 0) {
/* Distribution is already assigned */
notification.displayValidationError(i18n.getMessage("message.dist.inuse",
getNotification().displayValidationError(getI18n().getMessage("message.dist.inuse",
HawkbitCommonUtil.concatStrings(":", ds.getName(), ds.getVersion())));
return false;
}
if (ds.getModules().contains(sm)) {
/* Already has software module */
notification.displayValidationError(i18n.getMessage("message.software.dist.already.assigned",
getNotification().displayValidationError(getI18n().getMessage("message.software.dist.already.assigned",
HawkbitCommonUtil.concatStrings(":", sm.getName(), sm.getVersion()),
HawkbitCommonUtil.concatStrings(":", ds.getName(), ds.getVersion())));
return false;
@@ -355,7 +392,7 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
if (!ds.getType().containsModuleType(sm.getType())) {
/* Invalid type of the software module */
notification.displayValidationError(i18n.getMessage("message.software.dist.type.notallowed",
getNotification().displayValidationError(getI18n().getMessage("message.software.dist.type.notallowed",
HawkbitCommonUtil.concatStrings(":", sm.getName(), sm.getVersion()),
HawkbitCommonUtil.concatStrings(":", ds.getName(), ds.getVersion()), sm.getType().getName()));
return false;
@@ -372,7 +409,7 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
final Set<SoftwareModuleIdName> swModuleIdNames = entry.getValue();
for (final SoftwareModuleIdName swModuleIdName : swModuleIdNames) {
if ((sm.getName().concat(":" + sm.getVersion())).equals(swModuleIdName.getName())) {
notification.displayValidationError(i18n.getMessage("message.software.already.dragged",
getNotification().displayValidationError(getI18n().getMessage("message.software.already.dragged",
HawkbitCommonUtil.concatStrings(":", sm.getName(), sm.getVersion())));
return false;
}
@@ -449,54 +486,46 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
manageDistUIState.setNoDataAvailableDist(!available);
}
@Override
protected void addCustomGeneratedColumns() {
addGeneratedColumn(SPUILabelDefinitions.METADATA_ICON, new ColumnGenerator() {
private static final long serialVersionUID = 1L;
@Override
public Object generateCell(final Table source, final Object itemId, final Object columnId) {
final String nameVersionStr = getNameAndVerion(itemId);
final Button manageMetaDataBtn = createManageMetadataButton(nameVersionStr);
manageMetaDataBtn.addClickListener(event -> showMetadataDetails((Long) itemId));
return manageMetaDataBtn;
}
});
}
@Override
protected List<TableColumn> getTableVisibleColumns() {
final List<TableColumn> columnList = super.getTableVisibleColumns();
if (!isMaximized()) {
columnList.add(new TableColumn(SPUILabelDefinitions.METADATA_ICON, "", 0.1F));
}
return columnList;
}
private Button createManageMetadataButton(final String nameVersionStr) {
final Button manageMetadataBtn = SPUIComponentProvider.getButton(
UIComponentIdProvider.DS_TABLE_MANAGE_METADATA_ID + "." + nameVersionStr, "", "", null, false,
FontAwesome.LIST_ALT, SPUIButtonStyleSmallNoBorder.class);
manageMetadataBtn.addStyleName(SPUIStyleDefinitions.ARTIFACT_DTLS_ICON);
manageMetadataBtn.setDescription(i18n.getMessage("tooltip.metadata.icon"));
return manageMetadataBtn;
}
private void showMetadataDetails(final Long itemId) {
distributionSetManagement.getWithDetails(itemId)
.ifPresent(ds -> UI.getCurrent().addWindow(dsMetadataPopupLayout.getWindow(ds, null)));
}
private String getNameAndVerion(final Object itemId) {
final Item item = getItem(itemId);
final String name = (String) item.getItemProperty(SPUILabelDefinitions.VAR_NAME).getValue();
final String version = (String) item.getItemProperty(SPUILabelDefinitions.VAR_VERSION).getValue();
return name + "." + version;
}
private void updateDistributionInTable(final DistributionSet editedDs) {
final Item item = getContainerDataSource().getItem(editedDs.getId());
updateEntity(editedDs, item);
}
@Override
protected void handleOkDelete(final List<Long> entitiesToDelete) {
distributionSetManagement.delete(entitiesToDelete);
getEventBus().publish(this, new DistributionTableEvent(BaseEntityEventType.REMOVE_ENTITY, entitiesToDelete));
getNotification().displaySuccess(getI18n().getMessage("message.delete.success",
entitiesToDelete.size() + " " + getI18n().getMessage("distribution.details.header") + "(s)"));
manageDistUIState.getSelectedDistributions().clear();
getEventBus().publish(this, SaveActionWindowEvent.DELETED_DISTRIBUTIONS);
}
@Override
protected String getEntityType() {
return getI18n().getMessage("distribution.details.header");
}
@Override
protected Set<Long> getSelectedEntities() {
return manageDistUIState.getSelectedDistributions();
}
@Override
protected String getEntityId(final Object itemId) {
final String entityId = String.valueOf(
getContainerDataSource().getItem(itemId).getItemProperty(SPUILabelDefinitions.DIST_ID).getValue());
return "distributionSet." + entityId;
}
@Override
protected String getDeletedEntityName(final Long entityId) {
final Optional<DistributionSet> distribution = distributionSetManagement.get(entityId);
if (distribution.isPresent()) {
return distribution.get().getName();
}
return "";
}
}

View File

@@ -43,17 +43,17 @@ public class DistributionSetTableLayout extends AbstractTableLayout<Distribution
final DistributionsViewClientCriterion distributionsViewClientCriterion,
final SystemManagement systemManagement) {
final DsMetadataPopupLayout popupLayout = new DsMetadataPopupLayout(i18n, uiNotification, eventBus,
distributionSetManagement, entityFactory, permissionChecker);
this.distributionSetTable = new DistributionSetTable(eventBus, i18n, uiNotification, permissionChecker,
manageDistUIState, distributionSetManagement, softwareManagement, distributionsViewClientCriterion,
targetManagement, popupLayout);
targetManagement);
final DistributionAddUpdateWindowLayout distributionAddUpdateWindowLayout = new DistributionAddUpdateWindowLayout(
i18n, uiNotification, eventBus, distributionSetManagement, distributionSetTypeManagement,
systemManagement, entityFactory, distributionSetTable);
final DsMetadataPopupLayout popupLayout = new DsMetadataPopupLayout(i18n, uiNotification, eventBus,
distributionSetManagement, entityFactory, permissionChecker);
super.init(
new DistributionSetTableHeader(i18n, permissionChecker, eventBus, manageDistUIState,
distributionAddUpdateWindowLayout),

View File

@@ -38,13 +38,14 @@ import org.vaadin.addons.lazyquerycontainer.QueryDefinition;
*/
public class ManageDistBeanQuery extends AbstractBeanQuery<ProxyDistribution> {
private static final long serialVersionUID = 5176481314404662215L;
private static final long serialVersionUID = 1L;
private Sort sort = new Sort(Direction.ASC, "id");
private String searchText;
private transient DistributionSetManagement distributionSetManagement;
private transient Page<DistributionSet> firstPageDistributionSets;
private DistributionSetType distributionSetType;
private transient DistributionSetType distributionSetType;
private Boolean dsComplete;
/**

Some files were not shown because too many files have changed in this diff Show More