Fix xss vulnerability (#924)

* Fix XSS vulnerability for Distribution Set and Software Module field
* Fix XSS vulnerability for Artifact Details of header in Upload view
* Fix XSS vulnerability in Distribution View Software Module box show artifact details window and fix SonarQube issue
* Fix XSS vulnerability in Upload View Software Module field manage metadata
* Fix XSS vulnerability for Notifications when creating or deleting new or existing Distributions or Software Modules plus adapting error notifications when trying to duplicate
* Fix XSS vulnerability for Distributions View when assigning sm to dist confirmation popup text
* Fix XSS vulnerability for Distributions View modules tab of distribution value of SoftwareModule
* Fix XSS vulnerability for Deployment View assigned tab of target which has risky distribution assigned
* Fix XSS vulnerability in Deployment view action history (of) field and eliminate bugs
* Fix XSS vulnerability bug in Deployment View Action history of field
* Fix XSS vulnerability for Distributions View Module tab as it rendered tool tip
* Fix XSS vulnerability formatting
* Invented some IDs to ease testing regarding XSS vulnerability
* Fix XSS peer review findings
* Fix XSS vulnerability for Distribution Set and Software Module field
* Resolve merge conflicts

Signed-off-by: Ammar Bikic <ammar.bikic@bosch-si.com>
This commit is contained in:
amic
2020-01-27 14:41:07 +01:00
committed by Stefan Behl
parent 62c876a435
commit 6c162b2e93
19 changed files with 336 additions and 176 deletions

View File

@@ -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.event.SoftwareModuleEvent.SoftwareModuleEventType;
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState; import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
import org.eclipse.hawkbit.ui.common.ConfirmationDialog; 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.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.components.SPUIButton; import org.eclipse.hawkbit.ui.components.SPUIButton;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; 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.google.common.collect.Maps;
import com.vaadin.data.Container; import com.vaadin.data.Container;
import com.vaadin.server.FontAwesome; import com.vaadin.server.FontAwesome;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.Alignment; import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button; import com.vaadin.ui.Button;
import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.HorizontalLayout;
@@ -91,8 +89,12 @@ public class ArtifactDetailsLayout extends VerticalLayout {
private final UINotification uINotification; private final UINotification uINotification;
private Label prefixTitleOfArtifactDetails;
private Label titleOfArtifactDetails; private Label titleOfArtifactDetails;
private HorizontalLayout headerCaptionLayout;
private SPUIButton maxMinButton; private SPUIButton maxMinButton;
private Table artifactDetailsTable; private Table artifactDetailsTable;
@@ -140,7 +142,7 @@ public class ArtifactDetailsLayout extends VerticalLayout {
labelSoftwareModule = HawkbitCommonUtil.getFormattedNameVersion(selectedSoftwareModule.get().getName(), labelSoftwareModule = HawkbitCommonUtil.getFormattedNameVersion(selectedSoftwareModule.get().getName(),
selectedSoftwareModule.get().getVersion()); selectedSoftwareModule.get().getVersion());
} }
createComponents(labelSoftwareModule); createComponents();
buildLayout(); buildLayout();
eventBus.subscribe(this); eventBus.subscribe(this);
@@ -162,12 +164,36 @@ public class ArtifactDetailsLayout extends VerticalLayout {
return Optional.empty(); return Optional.empty();
} }
private void createComponents(final String labelSoftwareModule) { private void createComponents() {
titleOfArtifactDetails = new LabelBuilder().id(UIComponentIdProvider.ARTIFACT_DETAILS_HEADER_LABEL_ID) prefixTitleOfArtifactDetails = new Label();
.name(HawkbitCommonUtil.getArtifactoryDetailsLabelId(labelSoftwareModule, i18n)).buildCaptionLabel(); prefixTitleOfArtifactDetails.addStyleName(ValoTheme.LABEL_SMALL);
titleOfArtifactDetails.setContentMode(ContentMode.HTML); prefixTitleOfArtifactDetails.addStyleName(ValoTheme.LABEL_BOLD);
prefixTitleOfArtifactDetails.setSizeUndefined();
titleOfArtifactDetails = new Label();
titleOfArtifactDetails.setId(UIComponentIdProvider.ARTIFACT_DETAILS_HEADER_LABEL_ID);
titleOfArtifactDetails.setSizeFull(); titleOfArtifactDetails.setSizeFull();
titleOfArtifactDetails.setImmediate(true); 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(); maxMinButton = createMaxMinButton();
artifactDetailsTable = createArtifactDetailsTable(); artifactDetailsTable = createArtifactDetailsTable();
@@ -199,10 +225,10 @@ public class ArtifactDetailsLayout extends VerticalLayout {
header.setSizeFull(); header.setSizeFull();
header.setHeightUndefined(); header.setHeightUndefined();
header.setImmediate(true); header.setImmediate(true);
header.addComponents(titleOfArtifactDetails, maxMinButton); header.addComponents(headerCaptionLayout, maxMinButton);
header.setComponentAlignment(titleOfArtifactDetails, Alignment.TOP_LEFT); header.setComponentAlignment(headerCaptionLayout, Alignment.TOP_LEFT);
header.setComponentAlignment(maxMinButton, Alignment.TOP_RIGHT); header.setComponentAlignment(maxMinButton, Alignment.TOP_RIGHT);
header.setExpandRatio(titleOfArtifactDetails, 1.0F); header.setExpandRatio(headerCaptionLayout, 1.0F);
setSizeFull(); setSizeFull();
setImmediate(true); setImmediate(true);
@@ -426,12 +452,14 @@ public class ArtifactDetailsLayout extends VerticalLayout {
private void populateArtifactDetails(final Long baseSwModuleId, final String swModuleName) { private void populateArtifactDetails(final Long baseSwModuleId, final String swModuleName) {
if (!readOnly) { if (!readOnly) {
if (StringUtils.isEmpty(swModuleName)) {
setTitleOfLayoutHeader(); if (StringUtils.hasText(swModuleName)) {
prefixTitleOfArtifactDetails.setValue(i18n.getMessage(UIMessageIdProvider.CAPTION_ARTIFACT_DETAILS_OF));
titleOfArtifactDetails.setValue(swModuleName);
} else { } else {
titleOfArtifactDetails.setValue(HawkbitCommonUtil.getArtifactoryDetailsLabelId(swModuleName, i18n)); setTitleOfLayoutHeader();
titleOfArtifactDetails.setContentMode(ContentMode.HTML);
} }
} }
final Map<String, Object> queryConfiguration; final Map<String, Object> queryConfiguration;
if (baseSwModuleId != null) { if (baseSwModuleId != null) {
@@ -452,8 +480,8 @@ public class ArtifactDetailsLayout extends VerticalLayout {
* Set title of artifact details header layout. * Set title of artifact details header layout.
*/ */
private void setTitleOfLayoutHeader() { private void setTitleOfLayoutHeader() {
titleOfArtifactDetails.setValue(HawkbitCommonUtil.getArtifactoryDetailsLabelId("", i18n)); prefixTitleOfArtifactDetails.setValue(i18n.getMessage(UIMessageIdProvider.CAPTION_ARTIFACT_DETAILS));
titleOfArtifactDetails.setContentMode(ContentMode.HTML); titleOfArtifactDetails.setValue("");
} }
@EventBusListenerMethod(scope = EventScope.UI) @EventBusListenerMethod(scope = EventScope.UI)

View File

@@ -22,7 +22,6 @@ import org.eclipse.hawkbit.ui.common.builder.WindowBuilder;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.customrenderers.renderers.HtmlButtonRenderer; import org.eclipse.hawkbit.ui.customrenderers.renderers.HtmlButtonRenderer;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleNoBorder; 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.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions; import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider; import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
@@ -131,10 +130,15 @@ public abstract class AbstractMetadataPopupLayout<E extends NamedEntity, M exten
public CommonDialogWindow getWindow(final E entity, final String metaDatakey) { public CommonDialogWindow getWindow(final E entity, final String metaDatakey) {
selectedEntity = entity; selectedEntity = entity;
metadataWindow = new WindowBuilder(SPUIDefinitions.CREATE_UPDATE_WINDOW).caption(getMetadataCaption()) metadataWindow = new WindowBuilder(SPUIDefinitions.CREATE_UPDATE_WINDOW).content(this)
.content(this).cancelButtonClickListener(event -> onCancel()) .cancelButtonClickListener(event -> onCancel()).id(UIComponentIdProvider.METADATA_POPUP_ID)
.id(UIComponentIdProvider.METADATA_POPUP_ID).layout(mainLayout).i18n(i18n) .layout(mainLayout).i18n(i18n).saveDialogCloseListener(new SaveOnDialogCloseListener())
.saveDialogCloseListener(new SaveOnDialogCloseListener()).buildCommonDialogWindow(); .buildCommonDialogWindow();
metadataWindow.setCaptionAsHtml(false);
metadataWindow.setAssistivePrefix(i18n.getMessage("caption.metadata.popup") + " " + "<b>");
metadataWindow.setCaption(getElementTitle());
metadataWindow.setAssistivePostfix("</b>");
metadataWindow.setHeight(550, Unit.PIXELS); metadataWindow.setHeight(550, Unit.PIXELS);
metadataWindow.setWidth(800, Unit.PIXELS); metadataWindow.setWidth(800, Unit.PIXELS);
@@ -431,14 +435,6 @@ public abstract class AbstractMetadataPopupLayout<E extends NamedEntity, M exten
return true; return true;
} }
private String getMetadataCaption() {
final StringBuilder caption = new StringBuilder();
caption.append(HawkbitCommonUtil.DIV_DESCRIPTION_START + i18n.getMessage("caption.metadata.popup") + " "
+ HawkbitCommonUtil.getBoldHTMLText(getElementTitle()));
caption.append(HawkbitCommonUtil.DIV_DESCRIPTION_END);
return caption.toString();
}
protected String getElementTitle() { protected String getElementTitle() {
return getSelectedEntity().getName(); return getSelectedEntity().getName();
} }

View File

@@ -58,8 +58,8 @@ public class ConfirmationDialog implements Button.ClickListener {
* @param callback * @param callback
* the callback. * the callback.
* @param tab * @param tab
* ConfirmationTab which contains more information about the * ConfirmationTab which contains more information about the action
* action which has to be confirmed, e.g. maintenance window * which has to be confirmed, e.g. maintenance window
* @param id * @param id
* the id of the confirmation window * the id of the confirmation window
*/ */
@@ -71,7 +71,7 @@ public class ConfirmationDialog implements Button.ClickListener {
/** /**
* Constructor for configuring confirmation dialog. * Constructor for configuring confirmation dialog.
* *
* @param caption * @param caption
* the dialog caption. * the dialog caption.
* @param question * @param question
@@ -90,7 +90,7 @@ public class ConfirmationDialog implements Button.ClickListener {
/** /**
* Constructor for configuring confirmation dialog. * Constructor for configuring confirmation dialog.
* *
* @param caption * @param caption
* the dialog caption. * the dialog caption.
* @param question * @param question
@@ -111,7 +111,7 @@ public class ConfirmationDialog implements Button.ClickListener {
/** /**
* Constructor for configuring confirmation dialog. * Constructor for configuring confirmation dialog.
* *
* @param caption * @param caption
* the dialog caption. * the dialog caption.
* @param question * @param question
@@ -125,8 +125,8 @@ public class ConfirmationDialog implements Button.ClickListener {
* @param id * @param id
* the id of the confirmation dialog * the id of the confirmation dialog
* @param mapCloseToCancel * @param mapCloseToCancel
* Flag indicating whether or not the close event on the * Flag indicating whether or not the close event on the enclosing
* enclosing window should be mapped to a cancel event. * window should be mapped to a cancel event.
*/ */
public ConfirmationDialog(final String caption, final String question, final String okLabel, public ConfirmationDialog(final String caption, final String question, final String okLabel,
final String cancelLabel, final ConfirmationDialogCallback callback, final String id, final String cancelLabel, final ConfirmationDialogCallback callback, final String id,
@@ -136,7 +136,7 @@ public class ConfirmationDialog implements Button.ClickListener {
/** /**
* Constructor for configuring confirmation dialog. * Constructor for configuring confirmation dialog.
* *
* @param caption * @param caption
* the dialog caption. * the dialog caption.
* @param question * @param question
@@ -157,7 +157,7 @@ public class ConfirmationDialog implements Button.ClickListener {
/** /**
* Constructor for configuring confirmation dialog. * Constructor for configuring confirmation dialog.
* *
* @param caption * @param caption
* the dialog caption. * the dialog caption.
* @param question * @param question
@@ -173,8 +173,8 @@ public class ConfirmationDialog implements Button.ClickListener {
* @param id * @param id
* the id of the confirmation dialog * the id of the confirmation dialog
* @param tab * @param tab
* ConfirmationTab which contains more information about the * ConfirmationTab which contains more information about the action
* action which has to be confirmed, e.g. maintenance window * which has to be confirmed, e.g. maintenance window
*/ */
public ConfirmationDialog(final String caption, final String question, final String okLabel, 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,
@@ -185,7 +185,7 @@ public class ConfirmationDialog implements Button.ClickListener {
/** /**
* Constructor for configuring confirmation dialog. * Constructor for configuring confirmation dialog.
* *
* @param caption * @param caption
* the dialog caption. * the dialog caption.
* @param question * @param question
@@ -201,11 +201,11 @@ public class ConfirmationDialog implements Button.ClickListener {
* @param id * @param id
* the id of the confirmation dialog * the id of the confirmation dialog
* @param tab * @param tab
* ConfirmationTab which contains more information about the * ConfirmationTab which contains more information about the action
* action which has to be confirmed, e.g. maintenance window * which has to be confirmed, e.g. maintenance window
* @param mapCloseToCancel * @param mapCloseToCancel
* Flag indicating whether or not the close event on the * Flag indicating whether or not the close event on the enclosing
* enclosing window should be mapped to a cancel event. * window should be mapped to a cancel event.
*/ */
public ConfirmationDialog(final String caption, final String question, final String okLabel, 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,
@@ -253,9 +253,9 @@ public class ConfirmationDialog implements Button.ClickListener {
} }
private static Label createConfirmationQuestion(final String question) { private static Label createConfirmationQuestion(final String question) {
final Label questionLbl = new Label(String.format("<p>%s</p>", question.replaceAll("\n", "<br/>")), final Label questionLbl = new Label(question, ContentMode.TEXT);
ContentMode.HTML);
questionLbl.addStyleName(SPUIStyleDefinitions.CONFIRMBOX_QUESTION_LABEL); questionLbl.addStyleName(SPUIStyleDefinitions.CONFIRMBOX_QUESTION_LABEL);
return questionLbl; return questionLbl;
} }

View File

@@ -10,7 +10,6 @@ package org.eclipse.hawkbit.ui.common.detailslayout;
import org.eclipse.hawkbit.repository.model.NamedEntity; import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.ui.SpPermissionChecker; import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.common.table.BaseUIEntityEvent; import org.eclipse.hawkbit.ui.common.table.BaseUIEntityEvent;
import org.eclipse.hawkbit.ui.common.tagdetails.AbstractTagToken; import org.eclipse.hawkbit.ui.common.tagdetails.AbstractTagToken;
@@ -26,7 +25,6 @@ import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.spring.events.EventBus.UIEventBus; import org.vaadin.spring.events.EventBus.UIEventBus;
import com.vaadin.server.FontAwesome; import com.vaadin.server.FontAwesome;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.Alignment; import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button; import com.vaadin.ui.Button;
import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.HorizontalLayout;
@@ -34,6 +32,7 @@ import com.vaadin.ui.Label;
import com.vaadin.ui.TabSheet; import com.vaadin.ui.TabSheet;
import com.vaadin.ui.UI; import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.ValoTheme;
/** /**
* Abstract Layout to show the entity details. * Abstract Layout to show the entity details.
@@ -50,7 +49,9 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
private T selectedBaseEntity; private T selectedBaseEntity;
private Label caption; private Label captionPrefix;
private Label captionNameVersion;
private Button editButton; private Button editButton;
@@ -91,8 +92,8 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
/** /**
* Subscribes the view to the eventBus. Method has to be overriden (return * 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 * false) if the view does not contain any listener to avoid Vaadin blowing up
* up our logs with warnings. * our logs with warnings.
*/ */
protected boolean doSubscribeToEventBus() { protected boolean doSubscribeToEventBus() {
return true; return true;
@@ -122,7 +123,7 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
/** /**
* Default implementation to handle an entity event. * Default implementation to handle an entity event.
* *
* @param baseEntityEvent * @param baseEntityEvent
* the event * the event
*/ */
@@ -139,7 +140,8 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
} }
protected void setName(final String headerCaption, final String value) { protected void setName(final String headerCaption, final String value) {
caption.setValue(HawkbitCommonUtil.getSoftwareModuleName(headerCaption, value)); captionPrefix.setValue(headerCaption + " : ");
captionNameVersion.setValue(HawkbitCommonUtil.getFormattedName(value));
} }
/** /**
@@ -176,8 +178,8 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
descriptionLayout.removeAllComponents(); descriptionLayout.removeAllComponents();
final Label descLabel = SPUIComponentProvider.createNameValueLabel("", description == null ? "" : description); final Label descLabel = SPUIComponentProvider.createNameValueLabel("", description == null ? "" : description);
/** /**
* By default text will be truncated based on layout width. So removing * By default text will be truncated based on layout width. So removing it as we
* it as we need full description. * need full description.
*/ */
descLabel.removeStyleName("label-style"); descLabel.removeStyleName("label-style");
descLabel.setId(UIComponentIdProvider.DETAILS_DESCRIPTION_LABEL_ID); descLabel.setId(UIComponentIdProvider.DETAILS_DESCRIPTION_LABEL_ID);
@@ -213,10 +215,20 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
} }
protected void createComponents() { protected void createComponents() {
caption = createHeaderCaption(); captionPrefix = new Label(getDefaultCaption());
caption.setImmediate(true); captionPrefix.setImmediate(true);
caption.setContentMode(ContentMode.HTML); captionPrefix.addStyleName(ValoTheme.LABEL_SMALL);
caption.setId(getDetailsHeaderCaptionId()); captionPrefix.addStyleName(ValoTheme.LABEL_BOLD);
captionPrefix.setSizeUndefined();
captionNameVersion = new Label();
captionNameVersion.setImmediate(true);
captionNameVersion.setId(getDetailsHeaderCaptionId());
captionNameVersion.setWidth("100%");
captionNameVersion.addStyleName(ValoTheme.LABEL_SMALL);
captionNameVersion.addStyleName("text-bold");
captionNameVersion.addStyleName("text-cut");
captionNameVersion.addStyleName("header-caption-right");
editButton = SPUIComponentProvider.getButton("", "", i18n.getMessage(UIMessageIdProvider.TOOLTIP_UPDATE), null, editButton = SPUIComponentProvider.getButton("", "", i18n.getMessage(UIMessageIdProvider.TOOLTIP_UPDATE), null,
false, FontAwesome.PENCIL_SQUARE_O, SPUIButtonStyleNoBorder.class); false, FontAwesome.PENCIL_SQUARE_O, SPUIButtonStyleNoBorder.class);
@@ -242,16 +254,31 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
protected void buildLayout() { protected void buildLayout() {
nameEditLayout = new HorizontalLayout(); nameEditLayout = new HorizontalLayout();
final HorizontalLayout headerCaptionLayout = new HorizontalLayout();
headerCaptionLayout.setMargin(false);
headerCaptionLayout.setSpacing(true);
headerCaptionLayout.setSizeFull();
headerCaptionLayout.addStyleName("header-caption");
headerCaptionLayout.addComponent(captionPrefix);
headerCaptionLayout.setComponentAlignment(captionPrefix, Alignment.TOP_LEFT);
headerCaptionLayout.setExpandRatio(captionPrefix, 0.0F);
headerCaptionLayout.addComponent(captionNameVersion);
headerCaptionLayout.setComponentAlignment(captionNameVersion, Alignment.TOP_LEFT);
headerCaptionLayout.setExpandRatio(captionNameVersion, 1.0F);
nameEditLayout.setWidth(100.0F, Unit.PERCENTAGE); nameEditLayout.setWidth(100.0F, Unit.PERCENTAGE);
nameEditLayout.addComponent(caption); nameEditLayout.addComponents(headerCaptionLayout);
nameEditLayout.setComponentAlignment(caption, Alignment.TOP_LEFT); nameEditLayout.setComponentAlignment(headerCaptionLayout, Alignment.TOP_LEFT);
if (hasEditPermission()) { if (hasEditPermission()) {
nameEditLayout.addComponent(editButton); nameEditLayout.addComponent(editButton);
nameEditLayout.setComponentAlignment(editButton, Alignment.TOP_RIGHT); nameEditLayout.setComponentAlignment(editButton, Alignment.TOP_RIGHT);
nameEditLayout.addComponent(manageMetadataBtn); nameEditLayout.addComponent(manageMetadataBtn);
nameEditLayout.setComponentAlignment(manageMetadataBtn, Alignment.TOP_RIGHT); nameEditLayout.setComponentAlignment(manageMetadataBtn, Alignment.TOP_RIGHT);
} }
nameEditLayout.setExpandRatio(caption, 1.0F); nameEditLayout.setExpandRatio(headerCaptionLayout, 1.0F);
nameEditLayout.addStyleName(SPUIStyleDefinitions.WIDGET_TITLE); nameEditLayout.addStyleName(SPUIStyleDefinitions.WIDGET_TITLE);
addComponent(nameEditLayout); addComponent(nameEditLayout);
@@ -264,13 +291,9 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
addStyleName(SPUIStyleDefinitions.WIDGET_STYLE); addStyleName(SPUIStyleDefinitions.WIDGET_STYLE);
} }
private Label createHeaderCaption() {
return new LabelBuilder().name(getDefaultCaption()).buildCaptionLabel();
}
/** /**
* If there is no data in table (i.e. no row selected), then disable the * If there is no data in table (i.e. no row selected), then disable the edit
* edit button. If row is selected, enable edit button. * button. If row is selected, enable edit button.
*/ */
protected void populateData(final T selectedBaseEntity) { protected void populateData(final T selectedBaseEntity) {
this.selectedBaseEntity = selectedBaseEntity; this.selectedBaseEntity = selectedBaseEntity;
@@ -307,7 +330,7 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
protected abstract void populateMetadataDetails(); protected abstract void populateMetadataDetails();
/** /**
* Default caption of header to be displayed when no data row selected in * Default captionPrefix of header to be displayed when no data row selected in
* table. * table.
* *
* @return String * @return String

View File

@@ -79,8 +79,8 @@ public class SoftwareModuleDetailsTable extends Table {
* @param i18n * @param i18n
* I18N * I18N
* @param isUnassignSoftModAllowed * @param isUnassignSoftModAllowed
* boolean flag to check for unassign functionality allowed for * boolean flag to check for unassign functionality allowed for the
* the view. * view.
* @param distributionSetManagement * @param distributionSetManagement
* DistributionSetManagement * DistributionSetManagement
* @param permissionChecker * @param permissionChecker

View File

@@ -8,7 +8,6 @@
*/ */
package org.eclipse.hawkbit.ui.common.grid; 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.SPUIButton;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleNoBorder; import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleNoBorder;
@@ -16,13 +15,14 @@ import org.eclipse.hawkbit.ui.management.state.ManagementUIState;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions; import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.UIMessageIdProvider; import org.eclipse.hawkbit.ui.utils.UIMessageIdProvider;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.springframework.util.StringUtils;
import com.vaadin.server.FontAwesome; import com.vaadin.server.FontAwesome;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.Alignment; import com.vaadin.ui.Alignment;
import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label; import com.vaadin.ui.Label;
import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.ValoTheme;
/** /**
* Abstract grid header placed on top of a grid. * Abstract grid header placed on top of a grid.
@@ -34,6 +34,8 @@ public class DefaultGridHeader extends VerticalLayout {
private final String titleText; private final String titleText;
private Label title; private Label title;
private Label prefixText;
private HorizontalLayout prefixWithTitle;
private HorizontalLayout titleLayout; private HorizontalLayout titleLayout;
private transient AbstractHeaderMaximizeSupport maximizeSupport; private transient AbstractHeaderMaximizeSupport maximizeSupport;
@@ -67,24 +69,49 @@ public class DefaultGridHeader extends VerticalLayout {
* @return this DefaultGridHeader in order to allow method chaining * @return this DefaultGridHeader in order to allow method chaining
*/ */
public DefaultGridHeader init() { public DefaultGridHeader init() {
buildTitleLabel(); buildTitleHorizontalLayout();
buildTitleLayout(); buildTitleLayout();
buildComponent(); buildComponent();
return this; return this;
} }
/** /**
* Builds the title label. * Builds the title HorizontalLayout containing two labels.
* *
* @return title-label * @return title as HorizontalLayout
*/ */
protected Label buildTitleLabel() { protected HorizontalLayout buildTitleHorizontalLayout() {
// create default title - even shown when no data is available
title = new LabelBuilder().name(titleText).buildCaptionLabel();
title.setImmediate(true);
title.setContentMode(ContentMode.HTML);
return title; prefixText = new Label();
prefixText.setValue(titleText);
prefixText.addStyleName(ValoTheme.LABEL_SMALL);
prefixText.addStyleName(ValoTheme.LABEL_BOLD);
prefixText.setSizeUndefined();
title = new Label();
title.setSizeFull();
title.setImmediate(true);
title.setWidth("100%");
title.addStyleName(ValoTheme.LABEL_SMALL);
title.addStyleName("text-bold");
title.addStyleName("text-cut");
title.addStyleName("header-caption-right");
prefixWithTitle = new HorizontalLayout();
prefixWithTitle.setMargin(false);
prefixWithTitle.setSpacing(true);
prefixWithTitle.setSizeFull();
prefixWithTitle.addStyleName("header-caption");
prefixWithTitle.addComponent(prefixText);
prefixWithTitle.setComponentAlignment(prefixText, Alignment.TOP_LEFT);
prefixWithTitle.setExpandRatio(prefixText, 0.0F);
prefixWithTitle.addComponent(title);
prefixWithTitle.setComponentAlignment(title, Alignment.TOP_LEFT);
prefixWithTitle.setExpandRatio(title, 1.0F);
return prefixWithTitle;
} }
/** /**
@@ -98,9 +125,9 @@ public class DefaultGridHeader extends VerticalLayout {
titleLayout.setSpacing(false); titleLayout.setSpacing(false);
titleLayout.setMargin(false); titleLayout.setMargin(false);
titleLayout.setSizeFull(); titleLayout.setSizeFull();
titleLayout.addComponent(title); titleLayout.addComponent(prefixWithTitle);
titleLayout.setComponentAlignment(title, Alignment.TOP_LEFT); titleLayout.setComponentAlignment(prefixWithTitle, Alignment.TOP_LEFT);
titleLayout.setExpandRatio(title, 0.8F); titleLayout.setExpandRatio(prefixWithTitle, 0.8F);
if (hasHeaderMaximizeSupport()) { if (hasHeaderMaximizeSupport()) {
titleLayout.addComponents(getHeaderMaximizeSupport().maxMinButton); titleLayout.addComponents(getHeaderMaximizeSupport().maxMinButton);
@@ -125,12 +152,12 @@ public class DefaultGridHeader extends VerticalLayout {
} }
/** /**
* Enables maximize-support for the header by setting a * Enables maximize-support for the header by setting a HeaderMaximizeSupport
* HeaderMaximizeSupport implementation. * implementation.
* *
* @param maximizeSupport * @param maximizeSupport
* encapsulates layout of min-max-button and behavior for * encapsulates layout of min-max-button and behavior for minimize
* minimize and maximize. * and maximize.
*/ */
public void setHeaderMaximizeSupport(final AbstractHeaderMaximizeSupport maximizeSupport) { public void setHeaderMaximizeSupport(final AbstractHeaderMaximizeSupport maximizeSupport) {
this.maximizeSupport = maximizeSupport; this.maximizeSupport = maximizeSupport;
@@ -140,8 +167,7 @@ public class DefaultGridHeader extends VerticalLayout {
* Gets the HeaderMaximizeSupport implementation describing behavior for * Gets the HeaderMaximizeSupport implementation describing behavior for
* minimize and maximize. * minimize and maximize.
* *
* @return maximizeSupport that encapsulates behavior for minimize and * @return maximizeSupport that encapsulates behavior for minimize and maximize.
* maximize.
*/ */
public AbstractHeaderMaximizeSupport getHeaderMaximizeSupport() { public AbstractHeaderMaximizeSupport getHeaderMaximizeSupport() {
return maximizeSupport; return maximizeSupport;
@@ -162,8 +188,15 @@ public class DefaultGridHeader extends VerticalLayout {
* *
* @param newTitle * @param newTitle
*/ */
public void updateTitle(final String newTitle) { public void updateTitle(final String newTitle, final String hasTextCasePrefixText, final String hasNoTextCasePrefixText) {
title.setValue(newTitle);
if (StringUtils.hasText(newTitle)) {
prefixText.setValue(i18n.getMessage(hasTextCasePrefixText));
title.setValue(newTitle);
} else {
prefixText.setValue(i18n.getMessage(hasNoTextCasePrefixText));
title.setValue("");
}
} }
/** /**
@@ -204,14 +237,12 @@ public class DefaultGridHeader extends VerticalLayout {
} }
/** /**
* Additional actions for maximize operation might be performed by this * Additional actions for maximize operation might be performed by this method.
* method.
*/ */
protected abstract void maximize(); protected abstract void maximize();
/** /**
* Additional actions for minimize operation might be performed by this * Additional actions for minimize operation might be performed by this method.
* method.
*/ */
protected abstract void minimize(); protected abstract void minimize();

View File

@@ -25,9 +25,11 @@ import com.vaadin.server.ExternalResource;
import com.vaadin.server.FontAwesome; import com.vaadin.server.FontAwesome;
import com.vaadin.server.Resource; import com.vaadin.server.Resource;
import com.vaadin.shared.ui.label.ContentMode; import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button; import com.vaadin.ui.Button;
import com.vaadin.ui.CheckBox; import com.vaadin.ui.CheckBox;
import com.vaadin.ui.ComboBox; import com.vaadin.ui.ComboBox;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label; import com.vaadin.ui.Label;
import com.vaadin.ui.Link; import com.vaadin.ui.Link;
import com.vaadin.ui.Panel; import com.vaadin.ui.Panel;
@@ -44,6 +46,8 @@ import com.vaadin.ui.themes.ValoTheme;
public final class SPUIComponentProvider { public final class SPUIComponentProvider {
private static final Logger LOG = LoggerFactory.getLogger(SPUIComponentProvider.class); private static final Logger LOG = LoggerFactory.getLogger(SPUIComponentProvider.class);
private static final String LABEL_STYLE = "label-style";
/** /**
* Prevent Instance creation as utility class. * Prevent Instance creation as utility class.
*/ */
@@ -202,10 +206,50 @@ public final class SPUIComponentProvider {
final Label nameValueLabel = new Label(getBoldHTMLText(label) + valueStr, ContentMode.HTML); final Label nameValueLabel = new Label(getBoldHTMLText(label) + valueStr, ContentMode.HTML);
nameValueLabel.setSizeFull(); nameValueLabel.setSizeFull();
nameValueLabel.addStyleName(SPUIDefinitions.TEXT_STYLE); nameValueLabel.addStyleName(SPUIDefinitions.TEXT_STYLE);
nameValueLabel.addStyleName("label-style"); nameValueLabel.addStyleName(LABEL_STYLE);
return nameValueLabel; return nameValueLabel;
} }
/**
* Method to CreateName value labels.
*
* @param label
* as string
* @param values
* as string
* @return HorizontalLayout
*/
public static HorizontalLayout createNameValueLayout(final String label, final String... values) {
final String valueStr = StringUtils.arrayToDelimitedString(values, " ");
final Label nameValueLabel = new Label( label );
nameValueLabel.setContentMode(ContentMode.TEXT);
nameValueLabel.addStyleName(SPUIDefinitions.TEXT_STYLE);
nameValueLabel.addStyleName("text-bold");
nameValueLabel.setSizeUndefined();
final Label valueStrLabel = new Label(valueStr);
valueStrLabel.setWidth("100%");
valueStrLabel.addStyleName("text-cut");
valueStrLabel.addStyleName(SPUIDefinitions.TEXT_STYLE);
valueStrLabel.addStyleName(LABEL_STYLE);
final HorizontalLayout nameValueLayout = new HorizontalLayout();
nameValueLayout.setMargin(false);
nameValueLayout.setSpacing(true);
nameValueLayout.setSizeFull();
nameValueLayout.addComponent(nameValueLabel);
nameValueLayout.setComponentAlignment(nameValueLabel, Alignment.TOP_LEFT);
nameValueLayout.setExpandRatio(nameValueLabel, 0.0F);
nameValueLayout.addComponent(valueStrLabel);
nameValueLayout.setComponentAlignment(valueStrLabel, Alignment.TOP_LEFT);
nameValueLayout.setExpandRatio(valueStrLabel, 1.0F);
return nameValueLayout;
}
private static Label createUsernameLabel(final String label, final String username) { private static Label createUsernameLabel(final String label, final String username) {
String loadAndFormatUsername = ""; String loadAndFormatUsername = "";
if (!StringUtils.isEmpty(username)) { if (!StringUtils.isEmpty(username)) {
@@ -215,14 +259,14 @@ public final class SPUIComponentProvider {
final Label nameValueLabel = new Label(getBoldHTMLText(label) + loadAndFormatUsername, ContentMode.HTML); final Label nameValueLabel = new Label(getBoldHTMLText(label) + loadAndFormatUsername, ContentMode.HTML);
nameValueLabel.setSizeFull(); nameValueLabel.setSizeFull();
nameValueLabel.addStyleName(SPUIDefinitions.TEXT_STYLE); nameValueLabel.addStyleName(SPUIDefinitions.TEXT_STYLE);
nameValueLabel.addStyleName("label-style"); nameValueLabel.addStyleName(LABEL_STYLE);
nameValueLabel.setDescription(loadAndFormatUsername); nameValueLabel.setDescription(loadAndFormatUsername);
return nameValueLabel; return nameValueLabel;
} }
/** /**
* Create label which represents the {@link BaseEntity#getCreatedBy()} by * Create label which represents the {@link BaseEntity#getCreatedBy()} by user
* user name * name
* *
* @param i18n * @param i18n
* the i18n * the i18n
@@ -236,8 +280,8 @@ public final class SPUIComponentProvider {
} }
/** /**
* Create label which represents the {@link BaseEntity#getLastModifiedBy()} * Create label which represents the {@link BaseEntity#getLastModifiedBy()} by
* by user name * user name
* *
* @param i18n * @param i18n
* the i18n * the i18n
@@ -306,11 +350,10 @@ public final class SPUIComponentProvider {
* @param icon * @param icon
* of the link * of the link
* @param targetOpen * @param targetOpen
* specify how the link should be open (f. e. new windows = * specify how the link should be open (f. e. new windows = _blank)
* _blank)
* @param style * @param style
* chosen style of the link. Might be {@code null} if no style * chosen style of the link. Might be {@code null} if no style should
* should be used * be used
* @return a link UI component * @return a link UI component
*/ */
public static Link getLink(final String id, final String name, final String resource, final FontAwesome icon, public static Link getLink(final String id, final String name, final String resource, final FontAwesome icon,

View File

@@ -87,7 +87,7 @@ public class SwModuleDetails extends AbstractSoftwareModuleDetails {
} }
private Button createShowArtifactDetailsButton() { private Button createShowArtifactDetailsButton() {
artifactDetailsButton = SPUIComponentProvider.getButton("", "", "", null, false, FontAwesome.FILE_O, artifactDetailsButton = SPUIComponentProvider.getButton(UIComponentIdProvider.UPLOAD_SW_MODULE_SHOW_ARTIFACT_DETAILS_BUTTON, "", "", null, false, FontAwesome.FILE_O,
SPUIButtonStyleNoBorder.class); SPUIButtonStyleNoBorder.class);
artifactDetailsButton.setDescription(getI18n().getMessage(UIMessageIdProvider.TOOLTIP_ARTIFACT_ICON)); artifactDetailsButton.setDescription(getI18n().getMessage(UIMessageIdProvider.TOOLTIP_ARTIFACT_ICON));
artifactDetailsButton.addClickListener(event -> showArtifactDetailsWindow(getSelectedBaseEntity())); artifactDetailsButton.addClickListener(event -> showArtifactDetailsWindow(getSelectedBaseEntity()));
@@ -96,9 +96,11 @@ public class SwModuleDetails extends AbstractSoftwareModuleDetails {
private void showArtifactDetailsWindow(final SoftwareModule softwareModule) { private void showArtifactDetailsWindow(final SoftwareModule softwareModule) {
final Window artifactDtlsWindow = new Window(); final Window artifactDtlsWindow = new Window();
artifactDtlsWindow.setCaption(HawkbitCommonUtil artifactDtlsWindow.setId(UIComponentIdProvider.SHOW_ARTIFACT_DETAILS_POPUP_ID);
.getArtifactoryDetailsLabelId(softwareModule.getName() + "." + softwareModule.getVersion(), getI18n())); artifactDtlsWindow.setAssistivePrefix(HawkbitCommonUtil
artifactDtlsWindow.setCaptionAsHtml(true); .getArtifactoryDetailsLabelId(softwareModule.getName(), getI18n()) + " " + "<b>");
artifactDtlsWindow.setCaption(softwareModule.getName() + ":" + softwareModule.getVersion());
artifactDtlsWindow.setAssistivePostfix("</b>");
artifactDtlsWindow.setClosable(true); artifactDtlsWindow.setClosable(true);
artifactDtlsWindow.setResizable(true); artifactDtlsWindow.setResizable(true);
artifactDtlsWindow.setImmediate(true); artifactDtlsWindow.setImmediate(true);

View File

@@ -21,7 +21,6 @@ import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.management.event.ManagementUIEvent; import org.eclipse.hawkbit.ui.management.event.ManagementUIEvent;
import org.eclipse.hawkbit.ui.management.event.TargetTableEvent; import org.eclipse.hawkbit.ui.management.event.TargetTableEvent;
import org.eclipse.hawkbit.ui.management.state.ManagementUIState; import org.eclipse.hawkbit.ui.management.state.ManagementUIState;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions; import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.UIMessageIdProvider; import org.eclipse.hawkbit.ui.utils.UIMessageIdProvider;
import org.eclipse.hawkbit.ui.utils.UINotification; import org.eclipse.hawkbit.ui.utils.UINotification;
@@ -79,13 +78,12 @@ public class ActionHistoryLayout extends AbstractGridComponentLayout {
private String getActionHistoryCaption(final String targetName) { private String getActionHistoryCaption(final String targetName) {
final String caption; final String caption;
if (StringUtils.hasText(targetName)) { if (StringUtils.hasText(targetName)) {
caption = getI18n().getMessage(UIMessageIdProvider.CAPTION_ACTION_HISTORY_FOR, caption = getI18n().getMessage(UIMessageIdProvider.CAPTION_ACTION_HISTORY_FOR, targetName);
HawkbitCommonUtil.getBoldHTMLText(targetName));
} else { } else {
caption = getI18n().getMessage(UIMessageIdProvider.CAPTION_ACTION_HISTORY); caption = getI18n().getMessage(UIMessageIdProvider.CAPTION_ACTION_HISTORY);
} }
return HawkbitCommonUtil.getCaptionText(caption); return caption;
} }
@Override @Override
@@ -113,12 +111,12 @@ public class ActionHistoryLayout extends AbstractGridComponentLayout {
} }
/** /**
* Override default registration for selection propagation in order to * Override default registration for selection propagation in order to interrupt
* interrupt update cascade in minimized state to prevent updates on * update cascade in minimized state to prevent updates on invisible
* invisible action-status-grid and message-grid. * action-status-grid and message-grid.
* <p> * <p>
* The master selection is stored and propagation is performed as soon as * The master selection is stored and propagation is performed as soon as the
* the state changes to maximize and hence the dependent grids are updated. * state changes to maximize and hence the dependent grids are updated.
*/ */
@Override @Override
public void registerDetails(final AbstractGrid<?>.DetailsSupport details) { public void registerDetails(final AbstractGrid<?>.DetailsSupport details) {
@@ -188,7 +186,8 @@ public class ActionHistoryLayout extends AbstractGridComponentLayout {
* name of the target * name of the target
*/ */
public void updateActionHistoryHeader(final String targetName) { public void updateActionHistoryHeader(final String targetName) {
updateTitle(getActionHistoryCaption(targetName)); updateTitle(targetName, UIMessageIdProvider.CAPTION_ACTION_HISTORY_FOR,
UIMessageIdProvider.CAPTION_ACTION_HISTORY);
} }
/** /**

View File

@@ -350,7 +350,7 @@ public class BulkUploadHandler extends CustomComponent
errorMessage.append(dsAssignmentFailedMsg); errorMessage.append(dsAssignmentFailedMsg);
} }
if (errorMessage.length() > 0) { if (errorMessage.length() > 0) {
errorMessage.append("<br>"); errorMessage.append("\n");
} }
if (tagAssignmentFailedMsg != null) { if (tagAssignmentFailedMsg != null) {
errorMessage.append(tagAssignmentFailedMsg); errorMessage.append(tagAssignmentFailedMsg);

View File

@@ -225,18 +225,18 @@ public class TargetDetails extends AbstractTableDetailsLayout<Target> {
private void populateDistributionDtls(final VerticalLayout layout, final DistributionSet distributionSet) { private void populateDistributionDtls(final VerticalLayout layout, final DistributionSet distributionSet) {
layout.removeAllComponents(); layout.removeAllComponents();
layout.addComponent(SPUIComponentProvider.createNameValueLabel(getI18n().getMessage("label.dist.details.name"), layout.addComponent(SPUIComponentProvider.createNameValueLayout(getI18n().getMessage("label.dist.details.name"),
distributionSet == null ? "" : distributionSet.getName())); distributionSet == null ? "" : distributionSet.getName()));
layout.addComponent( layout.addComponent(
SPUIComponentProvider.createNameValueLabel(getI18n().getMessage("label.dist.details.version"), SPUIComponentProvider.createNameValueLayout(getI18n().getMessage("label.dist.details.version"),
distributionSet == null ? "" : distributionSet.getVersion())); distributionSet == null ? "" : distributionSet.getVersion()));
if (distributionSet == null) { if (distributionSet == null) {
return; return;
} }
distributionSet.getModules() distributionSet.getModules()
.forEach(module -> layout.addComponent(getSWModlabel(module.getType().getName(), module))); .forEach(module -> layout.addComponent(getSWModLayout(module.getType().getName(), module)));
} }
private void updateAttributesLayout(final String controllerId) { private void updateAttributesLayout(final String controllerId) {
@@ -264,11 +264,11 @@ public class TargetDetails extends AbstractTableDetailsLayout<Target> {
final TreeMap<String, String> sortedAttributes = new TreeMap<>((key1, key2) -> key1.compareToIgnoreCase(key2)); final TreeMap<String, String> sortedAttributes = new TreeMap<>((key1, key2) -> key1.compareToIgnoreCase(key2));
sortedAttributes.putAll(attributes); sortedAttributes.putAll(attributes);
sortedAttributes.forEach((key, value) -> { sortedAttributes.forEach((key, value) -> {
final Label conAttributeLabel = SPUIComponentProvider.createNameValueLabel(key.concat(" : "), final HorizontalLayout conAttributeLayout = SPUIComponentProvider.createNameValueLayout(key.concat(" : "),
value == null ? "" : value); value == null ? "" : value);
conAttributeLabel.setDescription(key.concat(" : ") + value); conAttributeLayout.setDescription(key.concat(" : ") + value);
conAttributeLabel.addStyleName("label-style"); conAttributeLayout.addStyleName("label-style");
attributesLayout.addComponent(conAttributeLabel); attributesLayout.addComponent(conAttributeLayout);
}); });
} }
@@ -322,8 +322,9 @@ public class TargetDetails extends AbstractTableDetailsLayout<Target> {
* as Module (JVM|OS|AH) * as Module (JVM|OS|AH)
* @return Label as UI * @return Label as UI
*/ */
private static Label getSWModlabel(final String labelName, final SoftwareModule swModule) { private static HorizontalLayout getSWModLayout(final String labelName, final SoftwareModule swModule) {
return SPUIComponentProvider.createNameValueLabel(labelName + " : ", swModule.getName(), swModule.getVersion()); return SPUIComponentProvider.createNameValueLayout(labelName + " : ", swModule.getName(),
swModule.getVersion());
} }
@Override @Override

View File

@@ -84,8 +84,8 @@ public final class HawkbitCommonUtil {
* *
* @param text * @param text
* text to be trimmed * text to be trimmed
* @return null if the text is null or if the text is blank, text.trim() if * @return null if the text is null or if the text is blank, text.trim() if the
* the text is not empty. * text is not empty.
*/ */
public static String trimAndNullIfEmpty(final String text) { public static String trimAndNullIfEmpty(final String text) {
if (text != null && !text.trim().isEmpty()) { if (text != null && !text.trim().isEmpty()) {
@@ -95,18 +95,16 @@ public final class HawkbitCommonUtil {
} }
/** /**
* Concatenate the given text all the string arguments with the given * Concatenate the given text all the string arguments with the given delimiter.
* delimiter.
* *
* @param delimiter * @param delimiter
* the delimiter text to be used while concatenation. * the delimiter text to be used while concatenation.
* @param texts * @param texts
* all these string values will be concatenated with the given * all these string values will be concatenated with the given
* delimiter. * delimiter.
* @return null in case no text arguments to be compared. just concatenation * @return null in case no text arguments to be compared. just concatenation of
* of all texts arguments if "delimiter" is null or empty. * all texts arguments if "delimiter" is null or empty. concatenation of
* concatenation of all texts arguments with "delimiter" if it not * all texts arguments with "delimiter" if it not null.
* null.
*/ */
public static String concatStrings(final String delimiter, final String... texts) { public static String concatStrings(final String delimiter, final String... texts) {
final String delim = delimiter == null ? "" : delimiter; final String delim = delimiter == null ? "" : delimiter;
@@ -140,21 +138,6 @@ public final class HawkbitCommonUtil {
return boldStr; return boldStr;
} }
/**
* Get Label for Artifact Details.
*
* @param caption
* as caption of the details
* @param name
* as name
* @return SoftwareModuleName
*/
public static String getSoftwareModuleName(final String caption, final String name) {
return new StringBuilder()
.append(DIV_DESCRIPTION_START + caption + " : " + getBoldHTMLText(getFormattedName(name)))
.append(DIV_DESCRIPTION_END).toString();
}
/** /**
* Get tool tip for Poll status. * Get tool tip for Poll status.
* *
@@ -181,7 +164,7 @@ public final class HawkbitCommonUtil {
* @return String formatted text * @return String formatted text
*/ */
public static String getFormattedName(final String orgText) { public static String getFormattedName(final String orgText) {
return trimAndNullIfEmpty(orgText) == null ? SPUIDefinitions.SPACE : orgText; return trimAndNullIfEmpty(orgText) == null ? "" : orgText;
} }
private static float findRequiredSwModuleExtraWidth(final float newBrowserWidth) { private static float findRequiredSwModuleExtraWidth(final float newBrowserWidth) {
@@ -246,10 +229,11 @@ public final class HawkbitCommonUtil {
* @return Label * @return Label
*/ */
public static Label getFormatedLabel(final String labelContent) { public static Label getFormatedLabel(final String labelContent) {
final Label labelValue = new Label(labelContent, ContentMode.HTML); final Label labelValue = new Label(labelContent, ContentMode.TEXT);
labelValue.setSizeFull(); labelValue.setSizeFull();
labelValue.addStyleName(SPUIDefinitions.TEXT_STYLE); labelValue.addStyleName(SPUIDefinitions.TEXT_STYLE);
labelValue.addStyleName("label-style"); labelValue.addStyleName("label-style");
labelValue.addStyleName("avoid-tooltip");
return labelValue; return labelValue;
} }
@@ -301,20 +285,20 @@ public final class HawkbitCommonUtil {
final int unassignedCount = result.getUnassigned(); final int unassignedCount = result.getUnassigned();
if (assignedCount == 1) { if (assignedCount == 1) {
formMsg.append(i18n.getMessage("message.target.assigned.one", result.getAssignedEntity().get(0).getName(), formMsg.append(i18n.getMessage("message.target.assigned.one", result.getAssignedEntity().get(0).getName(),
tagName)).append("<br>"); tagName)).append("\n");
} else if (assignedCount > 1) { } else if (assignedCount > 1) {
formMsg.append(i18n.getMessage("message.target.assigned.many", assignedCount, tagName)).append("<br>"); formMsg.append(i18n.getMessage("message.target.assigned.many", assignedCount, tagName)).append("\n");
if (alreadyAssignedCount > 0) { if (alreadyAssignedCount > 0) {
final String alreadyAssigned = i18n.getMessage("message.target.alreadyAssigned", alreadyAssignedCount); final String alreadyAssigned = i18n.getMessage("message.target.alreadyAssigned", alreadyAssignedCount);
formMsg.append(alreadyAssigned).append("<br>"); formMsg.append(alreadyAssigned).append("\n");
} }
} }
if (unassignedCount == 1) { if (unassignedCount == 1) {
formMsg.append(i18n.getMessage("message.target.unassigned.one", formMsg.append(i18n.getMessage("message.target.unassigned.one",
result.getUnassignedEntity().get(0).getName(), tagName)).append("<br>"); result.getUnassignedEntity().get(0).getName(), tagName)).append("\n");
} else if (unassignedCount > 1) { } else if (unassignedCount > 1) {
formMsg.append(i18n.getMessage("message.target.unassigned.many", unassignedCount, tagName)).append("<br>"); formMsg.append(i18n.getMessage("message.target.unassigned.many", unassignedCount, tagName)).append("\n");
} }
return formMsg.toString(); return formMsg.toString();
} }
@@ -552,14 +536,13 @@ public final class HawkbitCommonUtil {
* @return complete caption text of the table * @return complete caption text of the table
*/ */
public static String getArtifactoryDetailsLabelId(final String name, final VaadinMessageSource i18n) { public static String getArtifactoryDetailsLabelId(final String name, final VaadinMessageSource i18n) {
String caption; final String caption;
if (StringUtils.hasText(name)) { if (StringUtils.hasText(name)) {
caption = i18n.getMessage(UIMessageIdProvider.CAPTION_ARTIFACT_DETAILS_OF, caption = i18n.getMessage(UIMessageIdProvider.CAPTION_ARTIFACT_DETAILS_OF);
HawkbitCommonUtil.getBoldHTMLText(name));
} else { } else {
caption = i18n.getMessage(UIMessageIdProvider.CAPTION_ARTIFACT_DETAILS); caption = i18n.getMessage(UIMessageIdProvider.CAPTION_ARTIFACT_DETAILS);
} }
return getCaptionText(caption); return caption;
} }
/** /**

View File

@@ -65,7 +65,7 @@ public class NotificationMessage extends Notification {
setCaption(caption); setCaption(caption);
setDescription(description); setDescription(description);
setStyleName(styleName); setStyleName(styleName);
setHtmlContentAllowed(true); setHtmlContentAllowed(false);
setPosition(Position.BOTTOM_RIGHT); setPosition(Position.BOTTOM_RIGHT);
if (autoClose) { if (autoClose) {
setDelayMsec(SPUILabelDefinitions.SP_DELAY); setDelayMsec(SPUILabelDefinitions.SP_DELAY);

View File

@@ -252,6 +252,16 @@ public final class SPUIStyleDefinitions {
*/ */
public static final String COLOR_LABEL_STYLE = "color-label-style"; 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. * Style - Message.
*/ */

View File

@@ -445,6 +445,11 @@ public final class UIComponentIdProvider {
*/ */
public static final String UPLOAD_SW_MODULE_EDIT_BUTTON = "swmodule.edit.button"; 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. * 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"; 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. * Rollout popup id.
*/ */

View File

@@ -39,6 +39,7 @@ public class UINotification implements Serializable {
* is the message to displayed as success. * is the message to displayed as success.
*/ */
public void displaySuccess(final String message) { public void displaySuccess(final String message) {
notificationMessage.setIcon(null);
notificationMessage.showNotification(SPUIStyleDefinitions.SP_NOTIFICATION_SUCCESS_MESSAGE_STYLE, null, message, notificationMessage.showNotification(SPUIStyleDefinitions.SP_NOTIFICATION_SUCCESS_MESSAGE_STYLE, null, message,
true); true);
} }
@@ -50,6 +51,7 @@ public class UINotification implements Serializable {
* is the message to displayed as warning. * is the message to displayed as warning.
*/ */
public void displayWarning(final String message) { public void displayWarning(final String message) {
notificationMessage.setIcon(null);
notificationMessage.showNotification(SPUIStyleDefinitions.SP_NOTIFICATION_WARNING_MESSAGE_STYLE, null, message, notificationMessage.showNotification(SPUIStyleDefinitions.SP_NOTIFICATION_WARNING_MESSAGE_STYLE, null, message,
true); true);
} }
@@ -61,11 +63,10 @@ public class UINotification implements Serializable {
* as message. * as message.
*/ */
public void displayValidationError(final String message) { public void displayValidationError(final String message) {
final StringBuilder updatedMsg = new StringBuilder(FontAwesome.EXCLAMATION_TRIANGLE.getHtml()); final StringBuilder updatedMsg = new StringBuilder(message);
updatedMsg.append(' '); notificationMessage.setIcon(FontAwesome.EXCLAMATION_TRIANGLE);
updatedMsg.append(message); notificationMessage.showNotification(SPUIStyleDefinitions.SP_NOTIFICATION_ERROR_MESSAGE_STYLE, updatedMsg.toString(), null
notificationMessage.showNotification(SPUIStyleDefinitions.SP_NOTIFICATION_ERROR_MESSAGE_STYLE, null, , true);
updatedMsg.toString(), true);
} }
} }

View File

@@ -38,7 +38,7 @@ $generic-text-font-size: $generic-text-font-scale * $v-font-size;
//Report widget max icon style //Report widget max icon style
.icon-only { .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-bottom: 12px !important;
margin-right: 6px !important; margin-right: 6px !important;
} }
@@ -91,6 +91,39 @@ $generic-text-font-size: $generic-text-font-scale * $v-font-size;
-webkit-text-overflow: ellipsis; -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-panel,
.v-textfield { .v-textfield {
background: $widget-bg; background: $widget-bg;

View File

@@ -169,7 +169,7 @@
//confimation dialogue popup - Content margin adjustment //confimation dialogue popup - Content margin adjustment
.confirmbox-question-label { .confirmbox-question-label {
margin: 0 8px 8px; margin: 15px 8px 18px 8px;
} }
.bulk-upload-button{ .bulk-upload-button{

View File

@@ -98,9 +98,9 @@ distribution.set.tag.updated.event.container.notifcation.message=distribution se
caption.filter.by.type = Filter by type caption.filter.by.type = Filter by type
caption.bulk.upload = Bulk Upload caption.bulk.upload = Bulk Upload
caption.action.history = Action history 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 = Artifact Details
caption.artifact.details.of = Artifact Details of {0} caption.artifact.details.of = Artifact Details of
caption.action.states= Action States caption.action.states= Action States
caption.action.messages = Messages caption.action.messages = Messages
caption.error = Error caption.error = Error