Enable sorting in tables (#1279)

* provided infrastructure to enable sorting in grids
* Fixed sorting in RolloutGroupTarget
* fixed sorting with pinning and assigned SoftwareModules
* Added sorting for columns createdBy, createdAt, lastModifiedBy and lastModifiedAt
* Adapted status columns to be sortable
* fixed unit tests
* fixing sonar findings
* making Sonar happy
* added testcases for management classes regarding sorting
* added testcases for management classes regarding sorting
* using name for element ids in DOM
* incorporated code review remarks

Signed-off-by: Markus Block <markus.block@bosch-si.com>
This commit is contained in:
Markus Block
2022-09-30 09:54:17 +02:00
committed by GitHub
parent 3d3481110e
commit 60e33afca4
23 changed files with 593 additions and 154 deletions

View File

@@ -1,4 +1,4 @@
/**
/**
* Copyright (c) 2020 Bosch.IO GmbH and others.
*
* All rights reserved. This program and the accompanying materials
@@ -20,7 +20,7 @@ import org.eclipse.hawkbit.ui.common.data.proxies.ProxyIdentifiableEntity;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyNamedEntity;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTarget;
import org.eclipse.hawkbit.ui.common.grid.support.DeleteSupport;
import org.eclipse.hawkbit.ui.utils.ControllerIdHtmlEncoder;
import org.eclipse.hawkbit.ui.utils.StringHtmlEncoder;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.UIMessageIdProvider;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
@@ -43,7 +43,6 @@ import com.vaadin.ui.themes.ValoTheme;
* Builder class for grid components
*/
public final class GridComponentBuilder {
public static final double DEFAULT_MIN_WIDTH = 100D;
public static final String CREATED_BY_ID = "createdBy";
@@ -51,12 +50,20 @@ public final class GridComponentBuilder {
public static final String MODIFIED_BY_ID = "modifiedBy";
public static final String MODIFIED_DATE_ID = "modifiedDate";
public static final String CREATED_BY_PROPERTY_NAME = "createdBy";
public static final String CREATED_AT_PROPERTY_NAME = "createdAt";
public static final String LAST_MODIFIED_BY_PROPERTY_NAME = "lastModifiedBy";
public static final String LAST_MODIFIED_AT_PROPERTY_NAME = "lastModifiedAt";
public static final String VERSION_PROPERTY_NAME = "version";
public static final String NAME_PROPERTY_NAME = "name";
public static final String CONTROLLER_ID_PROPERTY_NAME = "controllerId";
private GridComponentBuilder() {
}
/**
* Create a {@link Button} with link optic
*
*
* @param idSuffix
* suffix to build the button ID
* @param idPrefix
@@ -90,7 +97,7 @@ public final class GridComponentBuilder {
/**
* Create a {@link Button} with link optic
*
*
* @param entity
* to build the button ID
* @param idPrefix
@@ -103,14 +110,16 @@ public final class GridComponentBuilder {
* execute on button click (null for none)
* @return the button
*/
public static <E extends ProxyIdentifiableEntity> Button buildLink(final E entity, final String idPrefix,
public static <E extends ProxyNamedEntity> Button buildLink(final E entity, final String idPrefix,
final String caption, final boolean enabled, final ClickListener clickListener) {
return buildLink(entity.getId().toString(), idPrefix, caption, enabled, clickListener);
final String idSuffix = StringHtmlEncoder.encode(entity.getName());
return buildLink(idSuffix, idPrefix, caption, enabled, clickListener);
}
/**
* Add name column to grid
*
* Add name column to grid. The column is set to sortable which implies a
* JPA field "name" that is used for sorting.
*
* @param <E>
* entity type of the grid
* @param grid
@@ -123,11 +132,15 @@ public final class GridComponentBuilder {
*/
public static <E extends ProxyNamedEntity> Column<E, String> addNameColumn(final Grid<E> grid,
final VaadinMessageSource i18n, final String columnId) {
return addColumn(i18n, grid, E::getName, "header.name", columnId, DEFAULT_MIN_WIDTH);
final Column<E, String> nameColumn = addColumn(i18n, grid, E::getName, "header.name", columnId,
DEFAULT_MIN_WIDTH);
setColumnSortable(nameColumn, NAME_PROPERTY_NAME);
return nameColumn;
}
/**
* Add controllerId column to grid
* Add controllerId column to grid. The column is set to sortable which implies a
* JPA field "controllerId" that is used for sorting.
*
* @param grid
* to add the column to
@@ -139,20 +152,23 @@ public final class GridComponentBuilder {
*/
public static Column<ProxyTarget, Button> addControllerIdColumn(final Grid<ProxyTarget> grid,
final VaadinMessageSource i18n, final String columnId) {
return addComponentColumn(grid, t -> GridComponentBuilder.buildControllerIdLink(t, columnId)).setId(columnId)
.setCaption(i18n.getMessage("header.controllerId")).setHidable(false)
.setMinimumWidth(DEFAULT_MIN_WIDTH);
final Column<ProxyTarget, Button> column = addComponentColumn(grid,
t -> buildControllerIdLink(t, columnId)).setId(columnId)
.setCaption(i18n.getMessage("header.controllerId")).setHidable(false)
.setMinimumWidth(DEFAULT_MIN_WIDTH);
setColumnSortable(column, CONTROLLER_ID_PROPERTY_NAME);
return column;
}
private static Button buildControllerIdLink(final ProxyTarget target, final String linkIdPrefix) {
final String idSuffix = ControllerIdHtmlEncoder.encode(target.getControllerId());
final String idSuffix = StringHtmlEncoder.encode(target.getControllerId());
return buildLink(idSuffix, linkIdPrefix, target.getControllerId(), true, clickEvent -> UI.getCurrent()
.getNavigator().navigateTo("deployment/target=" + target.getControllerId()));
}
/**
* Add description column to grid
*
*
* @param <E>
* entity type of the grid
* @param grid
@@ -170,7 +186,7 @@ public final class GridComponentBuilder {
/**
* Add "created by", "created at", "modified by" and "modified at" column
*
*
* @param <E>
* entity type of the grid
* @param grid
@@ -182,18 +198,30 @@ public final class GridComponentBuilder {
public static <E extends ProxyNamedEntity> List<Column<E, String>> addCreatedAndModifiedColumns(final Grid<E> grid,
final VaadinMessageSource i18n) {
final List<Column<E, String>> columns = new ArrayList<>();
columns.add(addColumn(i18n, grid, E::getCreatedBy, "header.createdBy", CREATED_BY_ID, DEFAULT_MIN_WIDTH));
columns.add(addColumn(i18n, grid, E::getCreatedDate, "header.createdDate", CREATED_DATE_ID, DEFAULT_MIN_WIDTH));
columns.add(
addColumn(i18n, grid, E::getLastModifiedBy, "header.modifiedBy", MODIFIED_BY_ID, DEFAULT_MIN_WIDTH));
columns.add(
addColumn(i18n, grid, E::getModifiedDate, "header.modifiedDate", MODIFIED_DATE_ID, DEFAULT_MIN_WIDTH));
final Column<E, String> createdByColumn = addColumn(i18n, grid, E::getCreatedBy, "header.createdBy",
CREATED_BY_ID, DEFAULT_MIN_WIDTH);
setColumnSortable(createdByColumn, CREATED_BY_PROPERTY_NAME);
columns.add(createdByColumn);
final Column<E, String> createdDate = addColumn(i18n, grid, E::getCreatedDate, "header.createdDate", CREATED_DATE_ID, DEFAULT_MIN_WIDTH);
setColumnSortable(createdDate, CREATED_AT_PROPERTY_NAME);
columns.add(createdDate);
final Column<E, String> modifiedBy = addColumn(i18n, grid, E::getLastModifiedBy, "header.modifiedBy", MODIFIED_BY_ID, DEFAULT_MIN_WIDTH);
setColumnSortable(modifiedBy, LAST_MODIFIED_BY_PROPERTY_NAME);
columns.add(modifiedBy);
final Column<E, String> modifiedDate = addColumn(i18n, grid, E::getModifiedDate, "header.modifiedDate", MODIFIED_DATE_ID, DEFAULT_MIN_WIDTH);
setColumnSortable(modifiedDate, LAST_MODIFIED_AT_PROPERTY_NAME);
columns.add(modifiedDate);
return columns;
}
/**
* Add version column to grid
*
*
* @param <E>
* entity type of the grid
* @param grid
@@ -208,7 +236,10 @@ public final class GridComponentBuilder {
*/
public static <E> Column<E, String> addVersionColumn(final Grid<E> grid, final VaadinMessageSource i18n,
final ValueProvider<E, String> valueProvider, final String columnId) {
return addColumn(i18n, grid, valueProvider, "header.version", columnId, DEFAULT_MIN_WIDTH);
final Column<E, String> column = addColumn(i18n, grid, valueProvider, "header.version", columnId,
DEFAULT_MIN_WIDTH);
setColumnSortable(column, VERSION_PROPERTY_NAME);
return column;
}
private static <E, T> Column<E, T> addColumn(final VaadinMessageSource i18n, final Grid<E> grid,
@@ -225,7 +256,7 @@ public final class GridComponentBuilder {
/**
* Add column to grid with the standard settings
*
*
* @param <E>
* entity type of the grid
* @param grid
@@ -240,7 +271,7 @@ public final class GridComponentBuilder {
/**
* Add column to grid with the standard settings
*
*
* @param <E>
* entity type of the grid
* @param grid
@@ -253,16 +284,14 @@ public final class GridComponentBuilder {
*/
public static <E, T> Column<E, T> addColumn(final Grid<E> grid, final ValueProvider<E, T> valueProvider,
final StyleGenerator<E> styleGenerator) {
final Column<E, T> column = grid.addColumn(valueProvider).setMinimumWidthFromContent(false).setExpandRatio(1);
if (styleGenerator != null) {
column.setStyleGenerator(styleGenerator);
}
final Column<E, T> column = grid.addColumn(valueProvider);
commonColumnConfiguration(column, styleGenerator);
return column;
}
/**
* Add column to grid with the standard settings
*
*
* @param <E>
* entity type of the grid
* @param grid
@@ -278,7 +307,7 @@ public final class GridComponentBuilder {
/**
* Add column to grid with the standard settings
*
*
* @param <E>
* entity type of the grid
* @param grid
@@ -291,8 +320,17 @@ public final class GridComponentBuilder {
*/
public static <E, T extends Component> Column<E, T> addComponentColumn(final Grid<E> grid,
final ValueProvider<E, T> componentProvider, final StyleGenerator<E> styleGenerator) {
final Column<E, T> column = grid.addComponentColumn(componentProvider).setMinimumWidthFromContent(false)
.setExpandRatio(1);
final Column<E, T> column = grid.addComponentColumn(componentProvider);
commonColumnConfiguration(column, styleGenerator);
return column;
}
private static <E, T> Column<E, T> commonColumnConfiguration(final Column<E, T> column,
final StyleGenerator<E> styleGenerator) {
column.setMinimumWidthFromContent(false);
column.setExpandRatio(1);
column.setSortable(false);
if (styleGenerator != null) {
column.setStyleGenerator(styleGenerator);
}
@@ -301,7 +339,7 @@ public final class GridComponentBuilder {
/**
* Add delete button column to grid
*
*
* @param <E>
* entity type of the grid
* @param grid
@@ -331,7 +369,7 @@ public final class GridComponentBuilder {
/**
* Add an action button column to a grid
*
*
* @param <T>
* type of the entity displayed by the grid
* @param grid
@@ -351,7 +389,7 @@ public final class GridComponentBuilder {
/**
* Add an action button column to a grid
*
*
* @param <T>
* type of the entity displayed by the grid
* @param grid
@@ -374,13 +412,32 @@ public final class GridComponentBuilder {
final StyleGenerator<T> finalStyleGenerator = merge(Arrays.asList(styleGenerator, additionalStyleGenerator));
final Column<T, V> column = grid.addComponentColumn(iconProvider).setId(columnId)
.setStyleGenerator(finalStyleGenerator).setWidth(60D).setResizable(false);
.setStyleGenerator(finalStyleGenerator).setWidth(60D).setResizable(false).setSortable(false);
if (!StringUtils.isEmpty(caption)) {
column.setCaption(caption);
}
return column;
}
/**
* Makes the column sortable.
*
* @param <T>
* type of the entity displayed by the grid
* @param <V>
* type of column value
* @param column
* the column to set sortable
* @param sortPropertyName
* the jpa property name to sort by
* @return the provided column
*/
public static <T, V> Column<T, V> setColumnSortable(final Column<T, V> column,
final String sortPropertyName) {
column.setSortable(true).setSortProperty(sortPropertyName);
return column;
}
private static <T> StyleGenerator<T> merge(final Collection<StyleGenerator<T>> generators) {
return item -> generators.stream().filter(Objects::nonNull).map(gen -> gen.apply(item)).filter(Objects::nonNull)
.collect(Collectors.joining(" "));
@@ -388,7 +445,7 @@ public final class GridComponentBuilder {
/**
* Join columns to form an action column
*
*
* @param i18n
* message source for internationalization
* @param headerRow
@@ -403,7 +460,7 @@ public final class GridComponentBuilder {
/**
* Join columns to form an icon column
*
*
* @param headerRow
* header row
* @param headerCaption
@@ -423,7 +480,7 @@ public final class GridComponentBuilder {
/**
* Create an action button (e.g. a delete button)
*
*
* @param i18n
* message source for internationalization
* @param clickListener
@@ -458,5 +515,4 @@ public final class GridComponentBuilder {
return actionButton;
}
}
}

View File

@@ -8,7 +8,9 @@
*/
package org.eclipse.hawkbit.ui.common.data.providers;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.hawkbit.repository.OffsetBasedPageRequest;
@@ -18,9 +20,12 @@ import org.slf4j.LoggerFactory;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;
import org.springframework.util.CollectionUtils;
import com.vaadin.data.provider.AbstractBackEndDataProvider;
import com.vaadin.data.provider.Query;
import com.vaadin.data.provider.QuerySortOrder;
/**
* Base class for loading a batch of entities from backend mapping them to UI
@@ -54,7 +59,38 @@ public abstract class AbstractGenericDataProvider<T extends ProxyIdentifiableEnt
@Override
protected Stream<T> fetchFromBackEnd(final Query<T, F> query) {
return getProxyEntities(
loadBackendEntities(convertToPageRequest(query, defaultSortOrder), query.getFilter().orElse(null)));
loadBackendEntities(
convertToPageRequest(query, convertToSortCriteria(query.getSortOrders())),
query.getFilter().orElse(null)));
}
private Sort convertToSortCriteria(final List<QuerySortOrder> querySortOrders) {
if (CollectionUtils.isEmpty(querySortOrders)) {
return defaultSortOrder;
} else {
return Sort.by(convertToListOfOrders(querySortOrders));
}
}
private List<Order> convertToListOfOrders(final List<QuerySortOrder> querySortOrders) {
return querySortOrders.stream()
.map(querySortOrder -> convertToOrderCriteria(querySortOrder))
.collect(Collectors.toList());
}
private Order convertToOrderCriteria(final QuerySortOrder querySortOrder) {
final Sort.Direction sortDirection;
switch (querySortOrder.getDirection()) {
case ASCENDING:
sortDirection = Sort.Direction.ASC;
break;
case DESCENDING:
// fall through intended to get default behavior
default:
sortDirection = Sort.Direction.DESC;
break;
}
return new Sort.Order(sortDirection, querySortOrder.getSorted());
}
private PageRequest convertToPageRequest(final Query<T, F> query, final Sort sort) {
@@ -67,7 +103,7 @@ public abstract class AbstractGenericDataProvider<T extends ProxyIdentifiableEnt
@Override
protected int sizeInBackEnd(final Query<T, F> query) {
final long size = sizeInBackEnd(convertToPageRequest(query, defaultSortOrder), query.getFilter().orElse(null));
final long size = sizeInBackEnd(convertToPageRequest(query, convertToSortCriteria(query.getSortOrders())), query.getFilter().orElse(null));
try {
return Math.toIntExact(size);
@@ -85,4 +121,4 @@ public abstract class AbstractGenericDataProvider<T extends ProxyIdentifiableEnt
Objects.requireNonNull(item, "Cannot provide an id for a null item.");
return item.getId();
}
}
}

View File

@@ -19,11 +19,15 @@ import org.eclipse.hawkbit.ui.common.grid.support.SelectionSupport;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.spring.events.EventBus.UIEventBus;
import com.vaadin.data.ValueProvider;
import com.vaadin.data.provider.DataCommunicator;
import com.vaadin.data.provider.DataProviderListener;
import com.vaadin.data.provider.Query;
import com.vaadin.ui.Component;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Grid.Column.NestedNullBehavior;
import com.vaadin.ui.components.grid.GridSelectionModel;
import com.vaadin.ui.renderers.AbstractRenderer;
/**
* Abstract grid that offers various capabilities (aka support) to offer
@@ -123,7 +127,6 @@ public abstract class AbstractGrid<T extends ProxyIdentifiableEntity, F> extends
setId(getGridId());
setColumnReorderingAllowed(false);
addColumns();
disableColumnSorting();
setFrozenColumnCount(-1);
if (selectionSupport == null) {
@@ -176,10 +179,48 @@ public abstract class AbstractGrid<T extends ProxyIdentifiableEntity, F> extends
*/
public abstract void addColumns();
private void disableColumnSorting() {
for (final Column<T, ?> c : getColumns()) {
c.setSortable(false);
}
@Override
public Column<T, ?> addColumn(final String propertyName) {
return super.addColumn(propertyName).setSortable(false);
}
@Override
public Column<T, ?> addColumn(final String propertyName, final AbstractRenderer<? super T, ?> renderer) {
return super.addColumn(propertyName, renderer).setSortable(false);
}
@Override
public Column<T, ?> addColumn(final String propertyName, final AbstractRenderer<? super T, ?> renderer,
final NestedNullBehavior nestedNullBehavior) {
return super.addColumn(propertyName, renderer, nestedNullBehavior).setSortable(false);
}
@Override
public <V> Column<T, V> addColumn(final ValueProvider<T, V> valueProvider) {
return super.addColumn(valueProvider).setSortable(false);
}
@Override
public <V> Column<T, V> addColumn(final ValueProvider<T, V> valueProvider,
final AbstractRenderer<? super T, ? super V> renderer) {
return super.addColumn(valueProvider, renderer).setSortable(false);
}
@Override
public <V, P> Column<T, V> addColumn(final ValueProvider<T, V> valueProvider,
final ValueProvider<V, P> presentationProvider, final AbstractRenderer<? super T, ? super P> renderer) {
return super.addColumn(valueProvider, presentationProvider, renderer).setSortable(false);
}
@Override
public <V> Column<T, V> addColumn(final ValueProvider<T, V> valueProvider,
final ValueProvider<V, String> presentationProvider) {
return super.addColumn(valueProvider, presentationProvider).setSortable(false);
}
@Override
public <V extends Component> Column<T, V> addComponentColumn(final ValueProvider<T, V> componentProvider) {
return super.addComponentColumn(componentProvider).setSortable(false);
}
/**

View File

@@ -128,8 +128,11 @@ public class TargetFilterGrid extends AbstractGrid<ProxyTargetFilterQuery, Strin
@Override
public void addColumns() {
GridComponentBuilder.addComponentColumn(this, this::buildFilterLink).setId(FILTER_NAME_ID)
final Column<ProxyTargetFilterQuery, Button> nameColumn = GridComponentBuilder
.addComponentColumn(this, this::buildFilterLink).setId(FILTER_NAME_ID)
.setCaption(i18n.getMessage("header.name"));
GridComponentBuilder.setColumnSortable(nameColumn, "name");
GridComponentBuilder.addCreatedAndModifiedColumns(this, i18n);

View File

@@ -19,6 +19,8 @@ import org.eclipse.hawkbit.ui.common.grid.support.FilterSupport;
import org.eclipse.hawkbit.ui.filtermanagement.state.TargetFilterDetailsLayoutUiState;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import com.vaadin.ui.Label;
/**
* Shows the targets as a result of the executed filter query.
*/
@@ -88,8 +90,10 @@ public class TargetFilterTargetGrid extends AbstractGrid<ProxyTarget, String> {
GridComponentBuilder.addDescriptionColumn(this, i18n, TARGET_DESCRIPTION_ID);
GridComponentBuilder.addIconColumn(this, targetStatusIconSupplier::getLabel, TARGET_STATUS_ID,
final Column<ProxyTarget, Label> statusColumn = GridComponentBuilder.addIconColumn(this,
targetStatusIconSupplier::getLabel, TARGET_STATUS_ID,
i18n.getMessage("header.status"));
GridComponentBuilder.setColumnSortable(statusColumn, "updateStatus");
GridComponentBuilder.addCreatedAndModifiedColumns(this, i18n);

View File

@@ -61,6 +61,7 @@ import com.vaadin.data.ValueProvider;
import com.vaadin.icons.VaadinIcons;
import com.vaadin.shared.ui.ContentMode;
import com.vaadin.ui.Button;
import com.vaadin.ui.Label;
import com.vaadin.ui.UI;
import com.vaadin.ui.Window;
import com.vaadin.ui.renderers.HtmlRenderer;
@@ -75,6 +76,7 @@ public class RolloutGrid extends AbstractGrid<ProxyRollout, String> {
private static final String ROLLOUT_LINK_ID = "rollout";
private static final String DIST_NAME_VERSION_ID = "distNameVersion";
private static final String STATUS_ID = "status";
private static final String STATUS_PROPERTY_NAME = "status";
private static final String TOTAL_TARGETS_COUNT_STATUS_ID = "totalTargetsCountStatus";
private static final String NUMBER_OF_GROUPS_ID = "numberOfGroups";
private static final String TOTAL_TARGETS_ID = "totalTargets";
@@ -263,8 +265,10 @@ public class RolloutGrid extends AbstractGrid<ProxyRollout, String> {
@Override
public void addColumns() {
GridComponentBuilder.addComponentColumn(this, this::buildRolloutLink).setId(ROLLOUT_LINK_ID)
final Column<ProxyRollout, Button> nameColumn = GridComponentBuilder
.addComponentColumn(this, this::buildRolloutLink).setId(ROLLOUT_LINK_ID)
.setCaption(i18n.getMessage("header.name")).setHidable(false).setExpandRatio(3);
GridComponentBuilder.setColumnSortable(nameColumn, "name");
GridComponentBuilder.addDescriptionColumn(this, i18n, DESC_ID).setHidable(true).setHidden(true);
@@ -272,9 +276,10 @@ public class RolloutGrid extends AbstractGrid<ProxyRollout, String> {
.setId(DIST_NAME_VERSION_ID).setCaption(i18n.getMessage("header.distributionset"))
.setDescriptionGenerator(this::createDSTooltipText).setHidable(true).setExpandRatio(2);
GridComponentBuilder
final Column<ProxyRollout, Label> statusColumn = GridComponentBuilder
.addIconColumn(this, rolloutStatusIconSupplier::getLabel, STATUS_ID, i18n.getMessage("header.status"))
.setHidable(true);
GridComponentBuilder.setColumnSortable(statusColumn, STATUS_PROPERTY_NAME);
GridComponentBuilder
.addIconColumn(this, actionTypeIconSupplier::getLabel, ACTION_TYPE_ID, i18n.getMessage("header.type"))

View File

@@ -40,6 +40,7 @@ import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import com.google.common.base.Predicates;
import com.vaadin.shared.ui.ContentMode;
import com.vaadin.ui.Button;
import com.vaadin.ui.Label;
import com.vaadin.ui.renderers.HtmlRenderer;
/**
@@ -112,14 +113,17 @@ public class RolloutGroupGrid extends AbstractGrid<ProxyRolloutGroup, Long> {
@Override
public void addColumns() {
GridComponentBuilder.addComponentColumn(this, this::buildRolloutGroupLink).setId(ROLLOUT_GROUP_LINK_ID)
final Column<ProxyRolloutGroup, Button> nameColumn = GridComponentBuilder.addComponentColumn(this, this::buildRolloutGroupLink).setId(ROLLOUT_GROUP_LINK_ID)
.setCaption(i18n.getMessage("header.name")).setHidable(false).setExpandRatio(3);
GridComponentBuilder.setColumnSortable(nameColumn, "name");
GridComponentBuilder.addDescriptionColumn(this, i18n, SPUILabelDefinitions.VAR_DESC).setHidable(true)
.setHidden(true);
GridComponentBuilder.addIconColumn(this, rolloutGroupStatusIconSupplier::getLabel,
final Column<ProxyRolloutGroup, Label> statusColumn = GridComponentBuilder
.addIconColumn(this, rolloutGroupStatusIconSupplier::getLabel,
SPUILabelDefinitions.VAR_STATUS, i18n.getMessage("header.status")).setHidable(true);
GridComponentBuilder.setColumnSortable(statusColumn, "status");
addColumn(rolloutGroup -> DistributionBarHelper
.getDistributionBarAsHTMLString(rolloutGroup.getTotalTargetCountStatus().getStatusTotalCountMap()),
@@ -155,7 +159,7 @@ public class RolloutGroupGrid extends AbstractGrid<ProxyRolloutGroup, Long> {
final boolean enableButton = RolloutGroupStatus.CREATING != rolloutGroup.getStatus()
&& permissionChecker.hasRolloutTargetsReadPermission();
return GridComponentBuilder.buildLink(rolloutGroup, "rolloutgroup.link.", rolloutGroup.getName(), enableButton,
return GridComponentBuilder.buildLink(rolloutGroup, "rolloutgroup.link", rolloutGroup.getName(), enableButton,
clickEvent -> onClickOfRolloutGroupName(rolloutGroup));
}

View File

@@ -24,6 +24,8 @@ import org.eclipse.hawkbit.ui.rollout.RolloutManagementUIState;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import com.vaadin.ui.Label;
/**
* Grid component with targets of rollout group.
*/
@@ -73,8 +75,10 @@ public class RolloutGroupTargetGrid extends AbstractGrid<ProxyTarget, Long> {
GridComponentBuilder.addDescriptionColumn(this, i18n, SPUILabelDefinitions.VAR_DESC).setExpandRatio(2);
GridComponentBuilder.addIconColumn(this, actionStatusIconSupplier::getLabel, SPUILabelDefinitions.VAR_STATUS,
final Column<ProxyTarget, Label> statusColumn = GridComponentBuilder.addIconColumn(this,
actionStatusIconSupplier::getLabel, SPUILabelDefinitions.VAR_STATUS,
i18n.getMessage("header.status"));
GridComponentBuilder.setColumnSortable(statusColumn, "status");
GridComponentBuilder.addCreatedAndModifiedColumns(this, i18n);

View File

@@ -13,33 +13,34 @@ import java.util.Base64.Encoder;
import java.util.Objects;
/**
* Encodes controller IDs to make them embeddable into HTML as element
* identifiers.
* Encodes a string attribute of an entity (e.g. name) to make it embeddable
* into HTML as element identifiers.
*/
public class ControllerIdHtmlEncoder {
public class StringHtmlEncoder {
/**
* Base64 encoder which suppresses trailing padding characters.
*/
private static Encoder BASE64 = Base64.getEncoder().withoutPadding();
private ControllerIdHtmlEncoder() {
private StringHtmlEncoder() {
// class should not be instantiated
}
/**
* Encodes the given controller ID so that it can be used as part of DOM
* Encodes the given string attribute so that it can be used as part of DOM
* element IDs.
*
* @param controllerId
* The controller ID to be encoded. Must not be
*
* @param attribute
* The attribute of an entity to be encoded. Must not be
* <code>null</code>.
*
* @return The encoded controller ID.
*
* @return The encoded string attribute to be used as element identifier in
* DOM tree.
*/
public static String encode(final String controllerId) {
Objects.requireNonNull(controllerId);
return BASE64.encodeToString(controllerId.getBytes());
public static String encode(final String attribute) {
Objects.requireNonNull(attribute);
return BASE64.encodeToString(attribute.getBytes());
}
}