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:
@@ -287,8 +287,11 @@ public interface SoftwareModuleManagement
|
||||
* deleted and sort them by means of given distribution set related modules
|
||||
* on top of the list.
|
||||
*
|
||||
* After that the modules are sorted by {@link SoftwareModule#getName()} and
|
||||
* {@link SoftwareModule#getVersion()} in ascending order.
|
||||
* After that the modules are sorted by by default by
|
||||
* {@link SoftwareModule#getName()} and {@link SoftwareModule#getVersion()}
|
||||
* in ascending order if no other sorting is provided in {@link Pageable}.
|
||||
* If sorting is provided in {@link Pageable} parameter the provided sorting
|
||||
* is used.
|
||||
*
|
||||
* @param pageable
|
||||
* page parameter
|
||||
|
||||
@@ -374,14 +374,14 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
@Override
|
||||
public Slice<DistributionSet> findByDistributionSetFilterOrderByLinkedTarget(final Pageable pageable,
|
||||
final DistributionSetFilter distributionSetFilter, final String assignedOrInstalled) {
|
||||
final List<Specification<JpaDistributionSet>> specList = buildDistributionSetSpecifications(
|
||||
distributionSetFilter);
|
||||
specList.add(DistributionSetSpecification.orderedByLinkedTarget(assignedOrInstalled));
|
||||
|
||||
// remove default sort from pageable to not overwrite sorted spec
|
||||
final OffsetBasedPageRequest unsortedPage = new OffsetBasedPageRequest(pageable.getOffset(),
|
||||
pageable.getPageSize(), Sort.unsorted());
|
||||
|
||||
final List<Specification<JpaDistributionSet>> specList = buildDistributionSetSpecifications(
|
||||
distributionSetFilter);
|
||||
specList.add(DistributionSetSpecification.orderedByLinkedTarget(assignedOrInstalled, pageable.getSort()));
|
||||
|
||||
return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, unsortedPage, specList);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Join;
|
||||
import javax.persistence.criteria.JoinType;
|
||||
import javax.persistence.criteria.ListJoin;
|
||||
import javax.persistence.criteria.Order;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.eclipse.hawkbit.repository.RolloutGroupFields;
|
||||
@@ -51,7 +52,9 @@ import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.data.jpa.repository.query.QueryUtils;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
@@ -259,7 +262,8 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
|
||||
|
||||
final CriteriaQuery<Object[]> multiselect = query.multiselect(targetJoin, actionJoin.get(JpaAction_.status))
|
||||
.where(cb.equal(targetRoot.get(RolloutTargetGroup_.rolloutGroup).get(JpaRolloutGroup_.id),
|
||||
rolloutGroupId));
|
||||
rolloutGroupId))
|
||||
.orderBy(getOrderBy(pageRequest, cb, targetJoin, actionJoin));
|
||||
final List<TargetWithActionStatus> targetWithActionStatus = entityManager.createQuery(multiselect)
|
||||
.setFirstResult((int) pageRequest.getOffset()).setMaxResults(pageRequest.getPageSize()).getResultList()
|
||||
.stream().map(o -> new TargetWithActionStatus((Target) o[0], (Action.Status) o[1]))
|
||||
@@ -268,6 +272,25 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
|
||||
return new PageImpl<>(targetWithActionStatus, pageRequest, totalCount);
|
||||
}
|
||||
|
||||
private List<Order> getOrderBy(final Pageable pageRequest, final CriteriaBuilder cb,
|
||||
final Join<RolloutTargetGroup, JpaTarget> targetJoin,
|
||||
final ListJoin<RolloutTargetGroup, JpaAction> actionJoin) {
|
||||
|
||||
return pageRequest.getSort().get().flatMap(order -> {
|
||||
final List<Order> orders;
|
||||
final String property = order.getProperty();
|
||||
// we consider status as property from JpaAction ...
|
||||
if ("status".equals(property)) {
|
||||
orders = QueryUtils.toOrders(Sort.by(order.getDirection(), property), actionJoin, cb);
|
||||
}
|
||||
// ... and every other property from JpaTarget
|
||||
else {
|
||||
orders = QueryUtils.toOrders(Sort.by(order.getDirection(), property), targetJoin, cb);
|
||||
}
|
||||
return orders.stream();
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countTargetsOfRolloutsGroup(final long rolloutGroupId) {
|
||||
throwExceptionIfRolloutGroupDoesNotExist(rolloutGroupId);
|
||||
|
||||
@@ -47,6 +47,7 @@ import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout_;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
|
||||
import org.eclipse.hawkbit.repository.jpa.specifications.RolloutSpecification;
|
||||
import org.eclipse.hawkbit.repository.jpa.utils.DeploymentHelper;
|
||||
@@ -75,6 +76,8 @@ import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.integration.support.locks.LockRegistry;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
@@ -162,7 +165,8 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
@Override
|
||||
public Page<Rollout> findAll(final Pageable pageable, final boolean deleted) {
|
||||
return JpaManagementHelper.findAllWithCountBySpec(rolloutRepository, pageable,
|
||||
Collections.singletonList(RolloutSpecification.isDeletedWithDistributionSet(deleted)));
|
||||
Collections
|
||||
.singletonList(RolloutSpecification.isDeletedWithDistributionSet(deleted, pageable.getSort())));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -170,7 +174,7 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
final List<Specification<JpaRollout>> specList = Lists.newArrayListWithExpectedSize(2);
|
||||
specList.add(
|
||||
RSQLUtility.buildRsqlSpecification(rsqlParam, RolloutFields.class, virtualPropertyReplacer, database));
|
||||
specList.add(RolloutSpecification.isDeletedWithDistributionSet(deleted));
|
||||
specList.add(RolloutSpecification.isDeletedWithDistributionSet(deleted, pageable.getSort()));
|
||||
|
||||
return JpaManagementHelper.findAllWithCountBySpec(rolloutRepository, pageable, specList);
|
||||
}
|
||||
@@ -481,7 +485,8 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
return rolloutRepository.count(RolloutSpecification.isDeletedWithDistributionSet(false));
|
||||
return rolloutRepository.count(
|
||||
RolloutSpecification.isDeletedWithDistributionSet(false, Sort.by(Direction.DESC, JpaRollout_.ID)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -553,7 +558,8 @@ public class JpaRolloutManagement implements RolloutManagement {
|
||||
@Override
|
||||
public Slice<Rollout> findAllWithDetailedStatus(final Pageable pageable, final boolean deleted) {
|
||||
final Slice<Rollout> rollouts = JpaManagementHelper.findAllWithoutCountBySpec(rolloutRepository, pageable,
|
||||
Collections.singletonList(RolloutSpecification.isDeletedWithDistributionSet(deleted)));
|
||||
Collections
|
||||
.singletonList(RolloutSpecification.isDeletedWithDistributionSet(deleted, pageable.getSort())));
|
||||
setRolloutStatusDetails(rollouts);
|
||||
return rollouts;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Expression;
|
||||
import javax.persistence.criteria.JoinType;
|
||||
import javax.persistence.criteria.ListJoin;
|
||||
import javax.persistence.criteria.Order;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
@@ -73,7 +74,9 @@ import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.domain.SliceImpl;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.data.jpa.repository.query.QueryUtils;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
import org.springframework.retry.annotation.Backoff;
|
||||
import org.springframework.retry.annotation.Retryable;
|
||||
@@ -308,6 +311,10 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
|
||||
}
|
||||
|
||||
@Override
|
||||
// In the interface org.springframework.data.domain.Pageable.getSort the
|
||||
// return value is not guaranteed to be non-null, therefore a null check is
|
||||
// necessary otherwise we rely on the implementation but this could change.
|
||||
@SuppressWarnings({ "squid:S2583", "squid:S2589" })
|
||||
public Slice<AssignedSoftwareModule> findAllOrderBySetAssignmentAndModuleNameAscModuleVersionAsc(
|
||||
final Pageable pageable, final long dsId, final String searchText, final Long smTypeId) {
|
||||
final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
|
||||
@@ -331,8 +338,16 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
|
||||
|
||||
query.groupBy(smRoot);
|
||||
|
||||
query.orderBy(cb.desc(assignedCaseMax), cb.asc(smRoot.get(JpaSoftwareModule_.name)),
|
||||
cb.asc(smRoot.get(JpaSoftwareModule_.version)));
|
||||
final Sort sort = pageable.getSort();
|
||||
final List<Order> orders = new ArrayList<>();
|
||||
orders.add(cb.desc(assignedCaseMax));
|
||||
if (sort == null || sort.isEmpty()) {
|
||||
orders.add(cb.asc(smRoot.get(JpaSoftwareModule_.name)));
|
||||
orders.add(cb.asc(smRoot.get(JpaSoftwareModule_.version)));
|
||||
} else {
|
||||
orders.addAll(QueryUtils.toOrders(sort, smRoot, cb));
|
||||
}
|
||||
query.orderBy(orders);
|
||||
|
||||
final int pageSize = pageable.getPageSize();
|
||||
final List<Tuple> smWithAssignedFlagList = entityManager.createQuery(query)
|
||||
|
||||
@@ -638,7 +638,7 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
pageable.getPageSize(), Sort.unsorted());
|
||||
|
||||
final List<Specification<JpaTarget>> specList = buildSpecificationList(filterParams);
|
||||
specList.add(TargetSpecifications.orderedByLinkedDistributionSet(orderByDistributionId));
|
||||
specList.add(TargetSpecifications.orderedByLinkedDistributionSet(orderByDistributionId, pageable.getSort()));
|
||||
|
||||
return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, unsortedPage, specList);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.Expression;
|
||||
import javax.persistence.criteria.JoinType;
|
||||
import javax.persistence.criteria.ListJoin;
|
||||
import javax.persistence.criteria.Order;
|
||||
import javax.persistence.criteria.Path;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
@@ -29,7 +30,9 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.data.jpa.repository.query.QueryUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
@@ -265,7 +268,8 @@ public final class DistributionSetSpecification {
|
||||
* Can be added to specification chain to order result by provided target
|
||||
*
|
||||
* Order: 1. Distribution set installed on target, 2. Distribution set(s)
|
||||
* assigned to target, 3. Based on distribution set id
|
||||
* assigned to target, 3. Based on requested sorting or id if
|
||||
* <code>null</code>.
|
||||
*
|
||||
* NOTE: Other specs, pagables and sort objects may alter the queries
|
||||
* orderBy entry too, possibly invalidating the applied order, keep in mind
|
||||
@@ -273,16 +277,26 @@ public final class DistributionSetSpecification {
|
||||
*
|
||||
* @param linkedControllerId
|
||||
* controller id to get installed/assigned DS for
|
||||
* @param sort
|
||||
* @return specification that applies order by target, may be overwritten
|
||||
*/
|
||||
public static Specification<JpaDistributionSet> orderedByLinkedTarget(final String linkedControllerId) {
|
||||
public static Specification<JpaDistributionSet> orderedByLinkedTarget(final String linkedControllerId,
|
||||
final Sort sort) {
|
||||
return (dsRoot, query, cb) -> {
|
||||
final Root<JpaTarget> targetRoot = query.from(JpaTarget.class);
|
||||
|
||||
final Expression<Object> assignedInstalledCase = cb.selectCase()
|
||||
.when(cb.equal(targetRoot.get(JpaTarget_.installedDistributionSet), dsRoot), 1)
|
||||
.when(cb.equal(targetRoot.get(JpaTarget_.assignedDistributionSet), dsRoot), 2).otherwise(3);
|
||||
query.orderBy(cb.asc(assignedInstalledCase), cb.asc(dsRoot.get(JpaDistributionSet_.id)));
|
||||
|
||||
final List<Order> orders = new ArrayList<>();
|
||||
orders.add(cb.asc(assignedInstalledCase));
|
||||
if (sort == null || sort.isEmpty()) {
|
||||
orders.add(cb.asc(dsRoot.get(JpaDistributionSet_.id)));
|
||||
} else {
|
||||
orders.addAll(QueryUtils.toOrders(sort, dsRoot, cb));
|
||||
}
|
||||
query.orderBy(orders);
|
||||
|
||||
return cb.equal(targetRoot.get(JpaTarget_.controllerId), linkedControllerId);
|
||||
};
|
||||
|
||||
@@ -13,7 +13,9 @@ import javax.persistence.criteria.Predicate;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout_;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.data.jpa.repository.query.QueryUtils;
|
||||
|
||||
/**
|
||||
* Specifications class for {@link Rollout}s. The class provides Spring Data
|
||||
@@ -35,11 +37,12 @@ public final class RolloutSpecification {
|
||||
* attribute is ignored
|
||||
* @return the {@link Rollout} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaRollout> isDeletedWithDistributionSet(final Boolean isDeleted) {
|
||||
public static Specification<JpaRollout> isDeletedWithDistributionSet(final Boolean isDeleted, final Sort sort) {
|
||||
return (root, query, cb) -> {
|
||||
|
||||
final Predicate predicate = cb.equal(root.<Boolean> get(JpaRollout_.deleted), isDeleted);
|
||||
root.fetch(JpaRollout_.distributionSet);
|
||||
query.orderBy(QueryUtils.toOrders(sort, root, cb));
|
||||
return predicate;
|
||||
};
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import javax.persistence.criteria.Join;
|
||||
import javax.persistence.criteria.JoinType;
|
||||
import javax.persistence.criteria.ListJoin;
|
||||
import javax.persistence.criteria.MapJoin;
|
||||
import javax.persistence.criteria.Order;
|
||||
import javax.persistence.criteria.Path;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
@@ -47,7 +48,9 @@ import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||
import org.eclipse.hawkbit.repository.model.TargetType;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.data.jpa.repository.query.QueryUtils;
|
||||
|
||||
/**
|
||||
* Specifications class for {@link Target}s. The class provides Spring Data JPQL
|
||||
@@ -571,7 +574,7 @@ public final class TargetSpecifications {
|
||||
* distribution set
|
||||
*
|
||||
* Order: 1. Targets with DS installed, 2. Targets with DS assigned, 3.
|
||||
* Based on target id
|
||||
* Based on requested sorting or id if <code>null</code>.
|
||||
*
|
||||
* NOTE: Other specs, pagables and sort objects may alter the queries
|
||||
* orderBy entry too, possibly invalidating the applied order, keep in mind
|
||||
@@ -579,9 +582,12 @@ public final class TargetSpecifications {
|
||||
*
|
||||
* @param distributionSetIdForOrder
|
||||
* distribution set to consider
|
||||
* @param sort
|
||||
* the sorting requested
|
||||
* @return specification that applies order by ds, may be overwritten
|
||||
*/
|
||||
public static Specification<JpaTarget> orderedByLinkedDistributionSet(final long distributionSetIdForOrder) {
|
||||
public static Specification<JpaTarget> orderedByLinkedDistributionSet(final long distributionSetIdForOrder,
|
||||
final Sort sort) {
|
||||
return (targetRoot, query, cb) -> {
|
||||
// Enhance query with custom select based sort
|
||||
final Expression<Object> selectCase = cb.selectCase()
|
||||
@@ -590,7 +596,14 @@ public final class TargetSpecifications {
|
||||
.when(cb.equal(targetRoot.get(JpaTarget_.assignedDistributionSet).get(JpaDistributionSet_.id),
|
||||
distributionSetIdForOrder), 2)
|
||||
.otherwise(100);
|
||||
query.orderBy(cb.asc(selectCase), cb.desc(targetRoot.get(JpaTarget_.id)));
|
||||
final List<Order> orders = new ArrayList<>();
|
||||
orders.add(cb.asc(selectCase));
|
||||
if (sort == null || sort.isEmpty()) {
|
||||
orders.add(cb.desc(targetRoot.get(JpaTarget_.id)));
|
||||
} else {
|
||||
orders.addAll(QueryUtils.toOrders(sort, targetRoot, cb));
|
||||
}
|
||||
query.orderBy(orders);
|
||||
|
||||
// Spec only provides order, so no further filtering
|
||||
return query.getRestriction();
|
||||
|
||||
@@ -63,6 +63,8 @@ import org.eclipse.hawkbit.repository.test.util.WithUser;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
@@ -627,7 +629,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
final Iterator<DistributionSet> dsIterator = buildDistributionSets.iterator();
|
||||
final Iterator<Target> tIterator = buildTargetFixtures.iterator();
|
||||
dsIterator.next();
|
||||
final DistributionSet dsFirst = dsIterator.next();
|
||||
final DistributionSet dsSecond = dsIterator.next();
|
||||
final DistributionSet dsThree = dsIterator.next();
|
||||
final DistributionSet dsFour = dsIterator.next();
|
||||
@@ -650,17 +652,50 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
final List<DistributionSet> tFirstPin = distributionSetManagement
|
||||
.findByDistributionSetFilterOrderByLinkedTarget(PAGE, distributionSetFilter, tFirst.getControllerId())
|
||||
.getContent();
|
||||
assertThat(tFirstPin.get(0)).isEqualTo(dsThree);
|
||||
assertThat(tFirstPin).hasSize(10);
|
||||
// assigned
|
||||
assertThat(tFirstPin.get(0)).isEqualTo(dsThree);
|
||||
// remaining id:ASC
|
||||
assertThat(tFirstPin.get(1)).isEqualTo(dsFirst);
|
||||
assertThat(tFirstPin.get(2)).isEqualTo(dsSecond);
|
||||
assertThat(tFirstPin.get(3)).isEqualTo(dsFour);
|
||||
|
||||
// target second has installed DS-2 and assigned DS-4 so check order
|
||||
// correct
|
||||
final List<DistributionSet> tSecondPin = distributionSetManagement
|
||||
.findByDistributionSetFilterOrderByLinkedTarget(PAGE, distributionSetFilter, tSecond.getControllerId())
|
||||
.getContent();
|
||||
assertThat(tSecondPin).hasSize(10);
|
||||
// installed
|
||||
assertThat(tSecondPin.get(0)).isEqualTo(dsSecond);
|
||||
// assigned
|
||||
assertThat(tSecondPin.get(1)).isEqualTo(dsFour);
|
||||
assertThat(tFirstPin).hasSize(10);
|
||||
// remaining id:ASC
|
||||
assertThat(tSecondPin.get(2)).isEqualTo(dsFirst);
|
||||
assertThat(tSecondPin.get(3)).isEqualTo(dsThree);
|
||||
|
||||
// target second has installed DS-2 and assigned DS-4 so check order
|
||||
// correct
|
||||
final List<DistributionSet> tSecondPinOrderedByName = distributionSetManagement
|
||||
.findByDistributionSetFilterOrderByLinkedTarget(
|
||||
PageRequest.of(0, 500, Sort.by(Direction.DESC, "version")),
|
||||
distributionSetFilter, tSecond.getControllerId())
|
||||
.getContent();
|
||||
assertThat(tSecondPinOrderedByName).hasSize(10);
|
||||
// installed
|
||||
assertThat(tSecondPinOrderedByName.get(0)).isEqualTo(buildDistributionSets.get(1));
|
||||
// assigned
|
||||
assertThat(tSecondPinOrderedByName.get(1)).isEqualTo(buildDistributionSets.get(3));
|
||||
// remaining version:DESC
|
||||
assertThat(tSecondPinOrderedByName.get(2)).isEqualTo(buildDistributionSets.get(9));
|
||||
assertThat(tSecondPinOrderedByName.get(3)).isEqualTo(buildDistributionSets.get(8));
|
||||
assertThat(tSecondPinOrderedByName.get(4)).isEqualTo(buildDistributionSets.get(7));
|
||||
assertThat(tSecondPinOrderedByName.get(5)).isEqualTo(buildDistributionSets.get(6));
|
||||
assertThat(tSecondPinOrderedByName.get(6)).isEqualTo(buildDistributionSets.get(5));
|
||||
assertThat(tSecondPinOrderedByName.get(7)).isEqualTo(buildDistributionSets.get(4));
|
||||
assertThat(tSecondPinOrderedByName.get(8)).isEqualTo(buildDistributionSets.get(2));
|
||||
assertThat(tSecondPinOrderedByName.get(9)).isEqualTo(buildDistributionSets.get(0));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -10,6 +10,9 @@ package org.eclipse.hawkbit.repository.jpa;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.eclipse.hawkbit.repository.event.remote.RolloutDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.RolloutCreatedEvent;
|
||||
@@ -18,9 +21,17 @@ import org.eclipse.hawkbit.repository.event.remote.entity.RolloutGroupUpdatedEve
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.RolloutUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetWithActionStatus;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.Expect;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
@@ -28,13 +39,13 @@ import io.qameta.allure.Story;
|
||||
|
||||
@Feature("Component Tests - Repository")
|
||||
@Story("Rollout Management")
|
||||
public class RolloutGroupManagementTest extends AbstractJpaIntegrationTest {
|
||||
class RolloutGroupManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Verifies that management get access reacts as specfied on calls for non existing entities by means "
|
||||
+ "of Optional not present.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void nonExistingEntityAccessReturnsNotPresent() {
|
||||
void nonExistingEntityAccessReturnsNotPresent() {
|
||||
assertThat(rolloutGroupManagement.get(NOT_EXIST_IDL)).isNotPresent();
|
||||
assertThat(rolloutGroupManagement.getWithDetailedStatus(NOT_EXIST_IDL)).isNotPresent();
|
||||
|
||||
@@ -52,7 +63,7 @@ public class RolloutGroupManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Expect(type = TargetCreatedEvent.class, count = 125),
|
||||
@Expect(type = RolloutCreatedEvent.class, count = 1) })
|
||||
|
||||
public void entityQueriesReferringToNotExistingEntitiesThrowsException() {
|
||||
void entityQueriesReferringToNotExistingEntitiesThrowsException() {
|
||||
testdataFactory.createRollout("xxx");
|
||||
|
||||
verifyThrownExceptionBy(() -> rolloutGroupManagement.countByRollout(NOT_EXIST_IDL), "Rollout");
|
||||
@@ -73,4 +84,71 @@ public class RolloutGroupManagementTest extends AbstractJpaIntegrationTest {
|
||||
"RolloutGroup");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that the returned result considers the provided sort parameters.")
|
||||
void findAllTargetsOfRolloutGroupWithActionStatusConsidersSorting() {
|
||||
final String prefix = RandomStringUtils.randomAlphanumeric(5);
|
||||
final Rollout rollout = testdataFactory.createRollout(prefix);
|
||||
final List<RolloutGroup> rolloutGroups = rolloutGroupManagement.findByRollout(PAGE, rollout.getId())
|
||||
.getContent();
|
||||
final RolloutGroup rolloutGroup = rolloutGroups.get(0);
|
||||
rolloutManagement.handleRollouts();
|
||||
rolloutManagement.start(rollout.getId());
|
||||
rolloutManagement.handleRollouts();
|
||||
rolloutManagement.pauseRollout(rollout.getId());
|
||||
rolloutManagement.handleRollouts();
|
||||
final List<Target> targets = rolloutGroupManagement.findTargetsOfRolloutGroup(PAGE, rolloutGroup.getId())
|
||||
.getContent();
|
||||
Target targetCancelled = targets.get(0);
|
||||
final Action actionCancelled = deploymentManagement.findActionsByTarget(targetCancelled.getControllerId(), PAGE)
|
||||
.getContent().get(0);
|
||||
deploymentManagement.cancelAction(actionCancelled.getId());
|
||||
deploymentManagement.forceQuitAction(actionCancelled.getId());
|
||||
targetCancelled = reloadTarget(targetCancelled);
|
||||
Target targetCancelling = targets.get(1);
|
||||
final Action actionCancelling = deploymentManagement
|
||||
.findActionsByTarget(targetCancelling.getControllerId(), PAGE).getContent().get(0);
|
||||
deploymentManagement.cancelAction(actionCancelling.getId());
|
||||
targetCancelling = reloadTarget(targetCancelling);
|
||||
|
||||
final List<TargetWithActionStatus> targetsWithActionStatus = rolloutGroupManagement
|
||||
.findAllTargetsOfRolloutGroupWithActionStatus(PageRequest.of(0, 500, Sort.by(Direction.DESC, "status")),
|
||||
rolloutGroup.getId())
|
||||
.getContent();
|
||||
assertThat(targetsWithActionStatus.get(0).getTarget()).isEqualTo(targetCancelling);
|
||||
assertThat(targetsWithActionStatus.get(1).getTarget()).isEqualTo(targetCancelled);
|
||||
|
||||
final List<TargetWithActionStatus> targetsWithActionStatusOrderedByNameDesc = rolloutGroupManagement
|
||||
.findAllTargetsOfRolloutGroupWithActionStatus(PageRequest.of(0, 500, Sort.by(Direction.DESC, "name")),
|
||||
rolloutGroup.getId())
|
||||
.getContent();
|
||||
assertThatListIsSortedByTargetName(targetsWithActionStatusOrderedByNameDesc, Direction.DESC);
|
||||
|
||||
final List<TargetWithActionStatus> targetsWithActionStatusOrderedByNameAsc = rolloutGroupManagement
|
||||
.findAllTargetsOfRolloutGroupWithActionStatus(PageRequest.of(0, 500, Sort.by(Direction.ASC, "name")),
|
||||
rolloutGroup.getId())
|
||||
.getContent();
|
||||
assertThatListIsSortedByTargetName(targetsWithActionStatusOrderedByNameAsc, Direction.ASC);
|
||||
}
|
||||
|
||||
private void assertThatListIsSortedByTargetName(final List<TargetWithActionStatus> targets,
|
||||
final Direction sortDirection) {
|
||||
String previousName = null;
|
||||
for (final TargetWithActionStatus targetWithActionStatus : targets) {
|
||||
final String actualName = targetWithActionStatus.getTarget().getName();
|
||||
if (previousName != null) {
|
||||
if (Direction.ASC == sortDirection) {
|
||||
assertThat(actualName).isGreaterThan(previousName);
|
||||
} else {
|
||||
assertThat(actualName).isLessThan(previousName);
|
||||
}
|
||||
}
|
||||
previousName = actualName;
|
||||
}
|
||||
}
|
||||
|
||||
private Target reloadTarget(final Target targetCancelled) {
|
||||
return targetManagement.get(targetCancelled.getId()).orElseThrow();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.util.stream.Collectors;
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import javax.validation.ValidationException;
|
||||
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.assertj.core.api.Condition;
|
||||
import org.awaitility.Awaitility;
|
||||
@@ -81,6 +82,7 @@ import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.T
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.domain.Sort;
|
||||
@@ -1761,6 +1763,47 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
||||
.getNumberOfElements()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that returned result considers provided sort parameter.")
|
||||
void findAllRolloutsConsidersSorting() {
|
||||
final String randomString = RandomStringUtils.randomAlphanumeric(5);
|
||||
final DistributionSet testDs = testdataFactory.createDistributionSet(randomString + "-testDs");
|
||||
testdataFactory.createTargets(10, randomString + "-testTarget-");
|
||||
final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder().withDefaults().build();
|
||||
|
||||
final String prefixRolloutRunning = randomString + "1";
|
||||
final RolloutCreate rolloutRunningCreate = entityFactory.rollout().create()
|
||||
.name(prefixRolloutRunning + "-testRollout").targetFilterQuery("name==" + randomString + "*")
|
||||
.set(testDs);
|
||||
|
||||
Rollout rolloutRunning = rolloutManagement.create(rolloutRunningCreate, 1, conditions);
|
||||
// Let the executor handle created Rollout
|
||||
rolloutManagement.handleRollouts();
|
||||
// start the rollout, so it has active running actions and a group which
|
||||
// has been started
|
||||
rolloutManagement.start(rolloutRunning.getId());
|
||||
rolloutManagement.handleRollouts();
|
||||
rolloutRunning = reloadRollout(rolloutRunning);
|
||||
|
||||
final String prefixRolloutReady = randomString + "2";
|
||||
final RolloutCreate rolloutReadyCreate = entityFactory.rollout().create()
|
||||
.name(prefixRolloutReady + "-testRollout").targetFilterQuery("name==" + randomString + "*")
|
||||
.set(testDs);
|
||||
Rollout rolloutReady = rolloutManagement.create(rolloutReadyCreate, 1, conditions);
|
||||
// Let the executor handle created Rollout
|
||||
rolloutManagement.handleRollouts();
|
||||
rolloutReady = reloadRollout(rolloutReady);
|
||||
|
||||
final List<Rollout> rolloutsOrderedByStatus = rolloutManagement
|
||||
.findAll(PageRequest.of(0, 500, Sort.by(Direction.ASC, "status")), false).getContent();
|
||||
assertThat(rolloutsOrderedByStatus).containsSubsequence(List.of(rolloutReady, rolloutRunning));
|
||||
|
||||
final List<Rollout> rolloutsOrderedByName = rolloutManagement
|
||||
.findAll(PageRequest.of(0, 500, Sort.by(Direction.ASC, "name")), false).getContent();
|
||||
assertThat(rolloutsOrderedByName).containsSubsequence(List.of(rolloutRunning, rolloutReady));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Description("Creating a rollout without weight value when multi assignment in enabled.")
|
||||
void weightNotRequiredInMultiAssignmentMode() {
|
||||
|
||||
@@ -46,6 +46,8 @@ import org.eclipse.hawkbit.repository.test.util.WithUser;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
@@ -545,19 +547,28 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
.containsExactly(new AssignedSoftwareModule(one, true), new AssignedSoftwareModule(two, true),
|
||||
new AssignedSoftwareModule(unassigned, false));
|
||||
|
||||
// with filter on name, version and module type, sorting defined by
|
||||
// Pagerequest
|
||||
assertThat(softwareModuleManagement.findAllOrderBySetAssignmentAndModuleNameAscModuleVersionAsc(
|
||||
PageRequest.of(0, 500, Sort.by(Direction.DESC, "name")), set.getId(), "%found%", testType.getId())
|
||||
.getContent()).as(
|
||||
"Found modules with given name, given module type, the assigned ones first, ordered by name DESC")
|
||||
.containsExactly(new AssignedSoftwareModule(two, true), new AssignedSoftwareModule(one, true),
|
||||
new AssignedSoftwareModule(unassigned, false));
|
||||
|
||||
// with filter on module type only
|
||||
assertThat(softwareModuleManagement
|
||||
.findAllOrderBySetAssignmentAndModuleNameAscModuleVersionAsc(PAGE, set.getId(), null, testType.getId())
|
||||
.getContent()).as("Found modules with given module type and the assigned ones first").containsExactly(
|
||||
new AssignedSoftwareModule(differentName, true), new AssignedSoftwareModule(one, true),
|
||||
new AssignedSoftwareModule(two, true), new AssignedSoftwareModule(unassigned, false));
|
||||
new AssignedSoftwareModule(one, true), new AssignedSoftwareModule(two, true),
|
||||
new AssignedSoftwareModule(differentName, true), new AssignedSoftwareModule(unassigned, false));
|
||||
|
||||
// without any filter
|
||||
assertThat(softwareModuleManagement
|
||||
.findAllOrderBySetAssignmentAndModuleNameAscModuleVersionAsc(PAGE, set.getId(), null, null)
|
||||
.getContent()).as("Found modules with the assigned ones first").containsExactly(
|
||||
new AssignedSoftwareModule(differentName, true), new AssignedSoftwareModule(one, true),
|
||||
new AssignedSoftwareModule(two, true), new AssignedSoftwareModule(four, true),
|
||||
new AssignedSoftwareModule(one, true), new AssignedSoftwareModule(two, true),
|
||||
new AssignedSoftwareModule(differentName, true), new AssignedSoftwareModule(four, true),
|
||||
new AssignedSoftwareModule(unassigned, false));
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,10 @@ import org.eclipse.hawkbit.repository.model.TargetType;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.primitives.Ints;
|
||||
@@ -573,7 +576,7 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
|
||||
final Slice<Target> result = targetManagement.findByFilterOrderByLinkedDistributionSet(PAGE, ds.getId(),
|
||||
new FilterParams(null, null, null, null, Boolean.FALSE));
|
||||
|
||||
final Comparator<TenantAwareBaseEntity> byId = (e1, e2) -> Long.compare(e2.getId(), e1.getId());
|
||||
final Comparator<TenantAwareBaseEntity> byId = (e1, e2) -> Long.compare(e1.getId(), e2.getId());
|
||||
|
||||
assertThat(result.getNumberOfElements()).isEqualTo(9);
|
||||
final List<Target> expected = new ArrayList<>();
|
||||
@@ -586,7 +589,45 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
assertThat(result.getContent()).usingElementComparator(controllerIdComparator())
|
||||
.containsExactly(expected.toArray(new Target[0]));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests the correct order of targets based on selected distribution set and sort parameter. The system expects to have an order based on installed, assigned DS.")
|
||||
void targetSearchWithOrderByDistributionSetAndSortParam() {
|
||||
|
||||
final List<Target> notAssigned = testdataFactory.createTargets(3, "not", "first description");
|
||||
List<Target> targAssigned = testdataFactory.createTargets(3, "assigned", "first description");
|
||||
List<Target> targInstalled = testdataFactory.createTargets(3, "installed", "first description");
|
||||
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("a");
|
||||
|
||||
targAssigned = assignDistributionSet(ds, targAssigned).getAssignedEntity().stream().map(Action::getTarget)
|
||||
.collect(Collectors.toList());
|
||||
targInstalled = assignDistributionSet(ds, targInstalled).getAssignedEntity().stream().map(Action::getTarget)
|
||||
.collect(Collectors.toList());
|
||||
targInstalled = testdataFactory
|
||||
.sendUpdateActionStatusToTargets(targInstalled, Status.FINISHED, Collections.singletonList("installed"))
|
||||
.stream().map(Action::getTarget).collect(Collectors.toList());
|
||||
|
||||
final List<Target> targetsOrderedByDistAndName = targetManagement
|
||||
.findByFilterOrderByLinkedDistributionSet(PageRequest.of(0, 500, Sort.by(Direction.DESC, "name")),
|
||||
ds.getId(), new FilterParams(null, null, null, null, Boolean.FALSE))
|
||||
.getContent();
|
||||
assertThat(targetsOrderedByDistAndName).hasSize(9);
|
||||
assertThatTargetNameEquals(targetsOrderedByDistAndName, 0, targInstalled, 2);
|
||||
assertThatTargetNameEquals(targetsOrderedByDistAndName, 1, targInstalled, 1);
|
||||
assertThatTargetNameEquals(targetsOrderedByDistAndName, 2, targInstalled, 0);
|
||||
assertThatTargetNameEquals(targetsOrderedByDistAndName, 3, targAssigned, 2);
|
||||
assertThatTargetNameEquals(targetsOrderedByDistAndName, 4, targAssigned, 1);
|
||||
assertThatTargetNameEquals(targetsOrderedByDistAndName, 5, targAssigned, 0);
|
||||
assertThatTargetNameEquals(targetsOrderedByDistAndName, 6, notAssigned, 2);
|
||||
assertThatTargetNameEquals(targetsOrderedByDistAndName, 7, notAssigned, 1);
|
||||
assertThatTargetNameEquals(targetsOrderedByDistAndName, 8, notAssigned, 0);
|
||||
}
|
||||
|
||||
private void assertThatTargetNameEquals(final List<Target> targets1, final int index1, final List<Target> targets2,
|
||||
final int index2) {
|
||||
assertThat(targets1.get(index1).getName()).isEqualTo(targets2.get(index2).getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -626,7 +667,7 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
|
||||
final Slice<Target> result = targetManagement.findByFilterOrderByLinkedDistributionSet(PAGE, ds.getId(),
|
||||
new FilterParams(null, Boolean.TRUE, null, null, Boolean.FALSE));
|
||||
|
||||
final Comparator<TenantAwareBaseEntity> byId = (e1, e2) -> Long.compare(e2.getId(), e1.getId());
|
||||
final Comparator<TenantAwareBaseEntity> byId = (e1, e2) -> Long.compare(e1.getId(), e2.getId());
|
||||
|
||||
assertThat(result.getNumberOfElements()).isEqualTo(9);
|
||||
final List<Target> expected = new ArrayList<>();
|
||||
|
||||
@@ -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,6 +50,14 @@ 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() {
|
||||
}
|
||||
|
||||
@@ -103,13 +110,15 @@ 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
|
||||
@@ -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,13 +152,16 @@ 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()));
|
||||
}
|
||||
@@ -182,12 +198,24 @@ 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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
@@ -253,10 +284,8 @@ 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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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(" "));
|
||||
@@ -458,5 +515,4 @@ public final class GridComponentBuilder {
|
||||
|
||||
return actionButton;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user