diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/details/ArtifactDetailsLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/details/ArtifactDetailsLayout.java
index f61879b53..1b5cb3c8f 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/details/ArtifactDetailsLayout.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/details/ArtifactDetailsLayout.java
@@ -24,7 +24,6 @@ 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.common.ConfirmationDialog;
-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;
@@ -48,7 +47,6 @@ import org.vaadin.spring.events.annotation.EventBusListenerMethod;
import com.google.common.collect.Maps;
import com.vaadin.data.Container;
import com.vaadin.server.FontAwesome;
-import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.HorizontalLayout;
@@ -91,8 +89,12 @@ public class ArtifactDetailsLayout extends VerticalLayout {
private final UINotification uINotification;
+ private Label prefixTitleOfArtifactDetails;
+
private Label titleOfArtifactDetails;
+ private HorizontalLayout headerCaptionLayout;
+
private SPUIButton maxMinButton;
private Table artifactDetailsTable;
@@ -140,7 +142,7 @@ public class ArtifactDetailsLayout extends VerticalLayout {
labelSoftwareModule = HawkbitCommonUtil.getFormattedNameVersion(selectedSoftwareModule.get().getName(),
selectedSoftwareModule.get().getVersion());
}
- createComponents(labelSoftwareModule);
+ createComponents();
buildLayout();
eventBus.subscribe(this);
@@ -162,12 +164,36 @@ public class ArtifactDetailsLayout extends VerticalLayout {
return Optional.empty();
}
- private void createComponents(final String labelSoftwareModule) {
- titleOfArtifactDetails = new LabelBuilder().id(UIComponentIdProvider.ARTIFACT_DETAILS_HEADER_LABEL_ID)
- .name(HawkbitCommonUtil.getArtifactoryDetailsLabelId(labelSoftwareModule, i18n)).buildCaptionLabel();
- titleOfArtifactDetails.setContentMode(ContentMode.HTML);
+ private void createComponents() {
+ prefixTitleOfArtifactDetails = new Label();
+ prefixTitleOfArtifactDetails.addStyleName(ValoTheme.LABEL_SMALL);
+ prefixTitleOfArtifactDetails.addStyleName(ValoTheme.LABEL_BOLD);
+ prefixTitleOfArtifactDetails.setSizeUndefined();
+
+ titleOfArtifactDetails = new Label();
+ titleOfArtifactDetails.setId(UIComponentIdProvider.ARTIFACT_DETAILS_HEADER_LABEL_ID);
titleOfArtifactDetails.setSizeFull();
titleOfArtifactDetails.setImmediate(true);
+ titleOfArtifactDetails.setWidth("100%");
+ titleOfArtifactDetails.addStyleName(ValoTheme.LABEL_SMALL);
+ titleOfArtifactDetails.addStyleName("text-bold");
+ titleOfArtifactDetails.addStyleName("text-cut");
+ titleOfArtifactDetails.addStyleName("header-caption-right");
+
+ headerCaptionLayout = new HorizontalLayout();
+ headerCaptionLayout.setMargin(false);
+ headerCaptionLayout.setSpacing(true);
+ headerCaptionLayout.setSizeFull();
+ headerCaptionLayout.addStyleName("header-caption");
+
+ headerCaptionLayout.addComponent(prefixTitleOfArtifactDetails);
+ headerCaptionLayout.setComponentAlignment(prefixTitleOfArtifactDetails, Alignment.TOP_LEFT);
+ headerCaptionLayout.setExpandRatio(prefixTitleOfArtifactDetails, 0.0F);
+
+ headerCaptionLayout.addComponent(titleOfArtifactDetails);
+ headerCaptionLayout.setComponentAlignment(titleOfArtifactDetails, Alignment.TOP_LEFT);
+ headerCaptionLayout.setExpandRatio(titleOfArtifactDetails, 1.0F);
+
maxMinButton = createMaxMinButton();
artifactDetailsTable = createArtifactDetailsTable();
@@ -199,10 +225,10 @@ public class ArtifactDetailsLayout extends VerticalLayout {
header.setSizeFull();
header.setHeightUndefined();
header.setImmediate(true);
- header.addComponents(titleOfArtifactDetails, maxMinButton);
- header.setComponentAlignment(titleOfArtifactDetails, Alignment.TOP_LEFT);
+ header.addComponents(headerCaptionLayout, maxMinButton);
+ header.setComponentAlignment(headerCaptionLayout, Alignment.TOP_LEFT);
header.setComponentAlignment(maxMinButton, Alignment.TOP_RIGHT);
- header.setExpandRatio(titleOfArtifactDetails, 1.0F);
+ header.setExpandRatio(headerCaptionLayout, 1.0F);
setSizeFull();
setImmediate(true);
@@ -426,12 +452,14 @@ public class ArtifactDetailsLayout extends VerticalLayout {
private void populateArtifactDetails(final Long baseSwModuleId, final String swModuleName) {
if (!readOnly) {
- if (StringUtils.isEmpty(swModuleName)) {
- setTitleOfLayoutHeader();
+
+ if (StringUtils.hasText(swModuleName)) {
+ prefixTitleOfArtifactDetails.setValue(i18n.getMessage(UIMessageIdProvider.CAPTION_ARTIFACT_DETAILS_OF));
+ titleOfArtifactDetails.setValue(swModuleName);
} else {
- titleOfArtifactDetails.setValue(HawkbitCommonUtil.getArtifactoryDetailsLabelId(swModuleName, i18n));
- titleOfArtifactDetails.setContentMode(ContentMode.HTML);
+ setTitleOfLayoutHeader();
}
+
}
final Map
- * The master selection is stored and propagation is performed as soon as
- * the state changes to maximize and hence the dependent grids are updated.
+ * The master selection is stored and propagation is performed as soon as the
+ * state changes to maximize and hence the dependent grids are updated.
*/
@Override
public void registerDetails(final AbstractGrid>.DetailsSupport details) {
@@ -188,7 +186,8 @@ public class ActionHistoryLayout extends AbstractGridComponentLayout {
* name of the target
*/
public void updateActionHistoryHeader(final String targetName) {
- updateTitle(getActionHistoryCaption(targetName));
+ updateTitle(targetName, UIMessageIdProvider.CAPTION_ACTION_HISTORY_FOR,
+ UIMessageIdProvider.CAPTION_ACTION_HISTORY);
}
/**
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/BulkUploadHandler.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/BulkUploadHandler.java
index 49a794f81..8475b0122 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/BulkUploadHandler.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/BulkUploadHandler.java
@@ -350,7 +350,7 @@ public class BulkUploadHandler extends CustomComponent
errorMessage.append(dsAssignmentFailedMsg);
}
if (errorMessage.length() > 0) {
- errorMessage.append("
");
+ errorMessage.append("\n");
}
if (tagAssignmentFailedMsg != null) {
errorMessage.append(tagAssignmentFailedMsg);
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetDetails.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetDetails.java
index 8242f021f..d2f033b4c 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetDetails.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetDetails.java
@@ -225,18 +225,18 @@ public class TargetDetails extends AbstractTableDetailsLayout
");
+ tagName)).append("\n");
} else if (assignedCount > 1) {
- formMsg.append(i18n.getMessage("message.target.assigned.many", assignedCount, tagName)).append("
");
+ formMsg.append(i18n.getMessage("message.target.assigned.many", assignedCount, tagName)).append("\n");
if (alreadyAssignedCount > 0) {
final String alreadyAssigned = i18n.getMessage("message.target.alreadyAssigned", alreadyAssignedCount);
- formMsg.append(alreadyAssigned).append("
");
+ formMsg.append(alreadyAssigned).append("\n");
}
}
if (unassignedCount == 1) {
formMsg.append(i18n.getMessage("message.target.unassigned.one",
- result.getUnassignedEntity().get(0).getName(), tagName)).append("
");
+ result.getUnassignedEntity().get(0).getName(), tagName)).append("\n");
} else if (unassignedCount > 1) {
- formMsg.append(i18n.getMessage("message.target.unassigned.many", unassignedCount, tagName)).append("
");
+ formMsg.append(i18n.getMessage("message.target.unassigned.many", unassignedCount, tagName)).append("\n");
}
return formMsg.toString();
}
@@ -552,14 +536,13 @@ public final class HawkbitCommonUtil {
* @return complete caption text of the table
*/
public static String getArtifactoryDetailsLabelId(final String name, final VaadinMessageSource i18n) {
- String caption;
+ final String caption;
if (StringUtils.hasText(name)) {
- caption = i18n.getMessage(UIMessageIdProvider.CAPTION_ARTIFACT_DETAILS_OF,
- HawkbitCommonUtil.getBoldHTMLText(name));
+ caption = i18n.getMessage(UIMessageIdProvider.CAPTION_ARTIFACT_DETAILS_OF);
} else {
caption = i18n.getMessage(UIMessageIdProvider.CAPTION_ARTIFACT_DETAILS);
}
- return getCaptionText(caption);
+ return caption;
}
/**
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/NotificationMessage.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/NotificationMessage.java
index 112532622..a5a6aaf13 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/NotificationMessage.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/NotificationMessage.java
@@ -65,7 +65,7 @@ public class NotificationMessage extends Notification {
setCaption(caption);
setDescription(description);
setStyleName(styleName);
- setHtmlContentAllowed(true);
+ setHtmlContentAllowed(false);
setPosition(Position.BOTTOM_RIGHT);
if (autoClose) {
setDelayMsec(SPUILabelDefinitions.SP_DELAY);
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIStyleDefinitions.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIStyleDefinitions.java
index a521fb071..20fbd4ffc 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIStyleDefinitions.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIStyleDefinitions.java
@@ -252,6 +252,16 @@ public final class SPUIStyleDefinitions {
*/
public static final String COLOR_LABEL_STYLE = "color-label-style";
+ /**
+ * Label bold style.
+ */
+ public static final String BOLD_LABEL_STYLE = "label-bold-style";
+
+ /**
+ * Label right padding style
+ */
+ public static final String RIGHT_PADDING_LABEL_STYLE = "header-caption-right";
+
/**
* Style - Message.
*/
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIComponentIdProvider.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIComponentIdProvider.java
index aa4fbbd35..32c89a974 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIComponentIdProvider.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIComponentIdProvider.java
@@ -445,6 +445,11 @@ public final class UIComponentIdProvider {
*/
public static final String UPLOAD_SW_MODULE_EDIT_BUTTON = "swmodule.edit.button";
+ /**
+ * Artifact upload - sw module show artifact details button id.
+ */
+ public static final String UPLOAD_SW_MODULE_SHOW_ARTIFACT_DETAILS_BUTTON = "swmodule.show.artifacts.details.button";
+
/**
* Artifact upload - sw module metadata button id.
*/
@@ -1167,6 +1172,11 @@ public final class UIComponentIdProvider {
*/
public static final String METADATA_POPUP_ID = "metadata.popup.id";
+ /**
+ * Show artifact details popup id.
+ */
+ public static final String SHOW_ARTIFACT_DETAILS_POPUP_ID = "show.artifact.details.popup.id";
+
/**
* Rollout popup id.
*/
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UINotification.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UINotification.java
index 96f04bf29..19cd9d43b 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UINotification.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UINotification.java
@@ -39,6 +39,7 @@ public class UINotification implements Serializable {
* is the message to displayed as success.
*/
public void displaySuccess(final String message) {
+ notificationMessage.setIcon(null);
notificationMessage.showNotification(SPUIStyleDefinitions.SP_NOTIFICATION_SUCCESS_MESSAGE_STYLE, null, message,
true);
}
@@ -50,6 +51,7 @@ public class UINotification implements Serializable {
* is the message to displayed as warning.
*/
public void displayWarning(final String message) {
+ notificationMessage.setIcon(null);
notificationMessage.showNotification(SPUIStyleDefinitions.SP_NOTIFICATION_WARNING_MESSAGE_STYLE, null, message,
true);
}
@@ -61,11 +63,10 @@ public class UINotification implements Serializable {
* as message.
*/
public void displayValidationError(final String message) {
- final StringBuilder updatedMsg = new StringBuilder(FontAwesome.EXCLAMATION_TRIANGLE.getHtml());
- updatedMsg.append(' ');
- updatedMsg.append(message);
- notificationMessage.showNotification(SPUIStyleDefinitions.SP_NOTIFICATION_ERROR_MESSAGE_STYLE, null,
- updatedMsg.toString(), true);
+ final StringBuilder updatedMsg = new StringBuilder(message);
+ notificationMessage.setIcon(FontAwesome.EXCLAMATION_TRIANGLE);
+ notificationMessage.showNotification(SPUIStyleDefinitions.SP_NOTIFICATION_ERROR_MESSAGE_STYLE, updatedMsg.toString(), null
+ , true);
}
}
diff --git a/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/generic-styles.scss b/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/generic-styles.scss
index 8c2d88357..cacd9dca0 100644
--- a/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/generic-styles.scss
+++ b/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/generic-styles.scss
@@ -38,7 +38,7 @@ $generic-text-font-size: $generic-text-font-scale * $v-font-size;
//Report widget max icon style
.icon-only {
- @include sp-icon-style($sp-button-size : $icon-font-size);
+ @include sp-icon-style($sp-button-size: $icon-font-size);
margin-bottom: 12px !important;
margin-right: 6px !important;
}
@@ -91,6 +91,39 @@ $generic-text-font-size: $generic-text-font-scale * $v-font-size;
-webkit-text-overflow: ellipsis;
}
+ .text-bold {
+ font-weight: bold !important;
+ }
+
+ .v-Notification-error .v-icon {
+ color: white;
+ }
+
+ .header-caption-right {
+ padding-right: 0.5em;
+ }
+
+ .avoid-tooltip {
+ pointer-events: none !important;
+ }
+
+ //This was needed to make the split of prefix "Artifact details of"
+ //and the actual value "smName:smVersion" in context of the XSS vulnerabilities
+ //possible after changing ContentMode
+ //from HTML to TEXT. As no Labels allowed at the windows caption field of the
+ //artifact details window , decision was made to use the methods
+ //Window.setAssistivePrefix() and Window.setAssistivePostfix() to solve the XSS-problem.
+ //Both, assistive postfix and prefix are usually not visible on the page and only for
+ //assistive purpose, but with overwriting this third party html class it's a possible
+ //workaround for the XSS vulnerability. I added a comment in the generic-styles.scss.
+ .v-assistive-device-only {
+ position: static;
+ top: auto;
+ left: auto;
+ width: auto;
+ overflow: visible;
+ }
+
.v-panel,
.v-textfield {
background: $widget-bg;
diff --git a/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/popup-window.scss b/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/popup-window.scss
index 809547aa8..d24cbf7ee 100644
--- a/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/popup-window.scss
+++ b/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/popup-window.scss
@@ -169,7 +169,7 @@
//confimation dialogue popup - Content margin adjustment
.confirmbox-question-label {
- margin: 0 8px 8px;
+ margin: 15px 8px 18px 8px;
}
.bulk-upload-button{
diff --git a/hawkbit-ui/src/main/resources/messages.properties b/hawkbit-ui/src/main/resources/messages.properties
index d9fe9953f..dd05ef176 100644
--- a/hawkbit-ui/src/main/resources/messages.properties
+++ b/hawkbit-ui/src/main/resources/messages.properties
@@ -98,9 +98,9 @@ distribution.set.tag.updated.event.container.notifcation.message=distribution se
caption.filter.by.type = Filter by type
caption.bulk.upload = Bulk Upload
caption.action.history = Action history
-caption.action.history.for = Action history for {0}
+caption.action.history.for = Action history for
caption.artifact.details = Artifact Details
-caption.artifact.details.of = Artifact Details of {0}
+caption.artifact.details.of = Artifact Details of
caption.action.states= Action States
caption.action.messages = Messages
caption.error = Error