diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java index 5fdfb318e..40fd7cc27 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java @@ -67,7 +67,11 @@ public interface TargetManagement { * Count {@link Target}s for all the given filter parameters. * * @param status - * find targets having on of these {@link TargetUpdateStatus}s. + * find targets having one of these {@link TargetUpdateStatus}s. + * Set to null in case this is not required. + * @param overdueState + * find targets that are overdue (targets that did not respond + * during the configured intervals: poll_itvl + overdue_itvl). * Set to null in case this is not required. * @param searchText * to find targets having the text anywhere in name or @@ -86,7 +90,7 @@ public interface TargetManagement { * @return the found number {@link Target}s */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) - Long countTargetByFilters(Collection status, String searchText, + Long countTargetByFilters(Collection status, Boolean overdueState, String searchText, Long installedOrAssignedDistributionSetId, Boolean selectTargetWithNoTag, String... tagNames); /** @@ -203,10 +207,12 @@ public interface TargetManagement { * * @param pageRequest * the pageRequest to enhance the query for paging and sorting - * * @param filterByStatus * find targets having this {@link TargetUpdateStatus}s. Set to * null in case this is not required. + * @param overdueState + * find targets that are overdue (targets that did not respond + * during the configured intervals: poll_itvl + overdue_itvl). * @param filterBySearchText * to find targets having the text anywhere in name or * description. Set null in case this is not @@ -225,7 +231,7 @@ public interface TargetManagement { */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) List findAllTargetIdsByFilters(@NotNull Pageable pageRequest, - Collection filterByStatus, String filterBySearchText, + Collection filterByStatus, Boolean overdueState, String filterBySearchText, Long installedOrAssignedDistributionSetId, Boolean selectTargetWithNoTag, String... filterByTagNames); /** @@ -274,7 +280,7 @@ public interface TargetManagement { * given {@code fieldNameProvider} * @throws RSQLParameterSyntaxException * if the RSQL syntax is wrong - * + * */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET) Page findTargetByAssignedDistributionSet(@NotNull Long distributionSetID, @NotNull String rsqlParam, @@ -328,6 +334,9 @@ public interface TargetManagement { * @param status * find targets having this {@link TargetUpdateStatus}s. Set to * null in case this is not required. + * @param overdueState + * find targets that are overdue (targets that did not respond + * during the configured intervals: poll_itvl + overdue_itvl). * @param searchText * to find targets having the text anywhere in name or * description. Set null in case this is not @@ -346,7 +355,7 @@ public interface TargetManagement { */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) Slice findTargetByFilters(@NotNull Pageable pageable, Collection status, - String searchText, Long installedOrAssignedDistributionSetId, Boolean selectTargetWithNoTag, + Boolean overdueState, String searchText, Long installedOrAssignedDistributionSetId, Boolean selectTargetWithNoTag, String... tagNames); /** @@ -375,7 +384,7 @@ public interface TargetManagement { * @param pageable * page parameter * @return the found {@link Target}s, never {@code null} - * + * * @throws RSQLParameterUnsupportedFieldException * if a field in the RSQL string is used but not provided by the * given {@code fieldNameProvider} @@ -420,9 +429,9 @@ public interface TargetManagement { * in string notation * @param pageable * pagination parameter - * + * * @return the found {@link Target}s, never {@code null} - * + * * @throws RSQLParameterUnsupportedFieldException * if a field in the RSQL string is used but not provided by the * given {@code fieldNameProvider} @@ -441,9 +450,9 @@ public interface TargetManagement { * the specification for the query * @param pageable * pagination parameter - * + * * @return the found {@link Target}s, never {@code null} - * + * * @throws RSQLParameterUnsupportedFieldException * if a field in the RSQL string is used but not provided by the * given {@code fieldNameProvider} @@ -477,6 +486,9 @@ public interface TargetManagement { * @param filterByStatus * find targets having this {@link TargetUpdateStatus}s. Set to * null in case this is not required. + * @param overdueState + * find targets that are overdue (targets that did not respond + * during the configured intervals: poll_itvl + overdue_itvl). * @param filterBySearchText * to find targets having the text anywhere in name or * description. Set null in case this is not @@ -496,8 +508,8 @@ public interface TargetManagement { @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) Slice findTargetsAllOrderByLinkedDistributionSet(@NotNull Pageable pageable, @NotNull Long orderByDistributionId, Long filterByDistributionId, - Collection filterByStatus, String filterBySearchText, Boolean selectTargetWithNoTag, - String... filterByTagNames); + Collection filterByStatus, Boolean overdueState, String filterBySearchText, + Boolean selectTargetWithNoTag, String... filterByTagNames); /** * retrieves a list of {@link Target}s by their controller ID with details, diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java index b901ee6df..2528ed5ac 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java @@ -279,29 +279,33 @@ public class JpaTargetManagement implements TargetManagement { @Override public Slice findTargetByFilters(final Pageable pageable, final Collection status, - final String searchText, final Long installedOrAssignedDistributionSetId, + final Boolean overdueState, final String searchText, final Long installedOrAssignedDistributionSetId, final Boolean selectTargetWithNoTag, final String... tagNames) { - final List> specList = buildSpecificationList(status, searchText, + final List> specList = buildSpecificationList(status, overdueState, searchText, installedOrAssignedDistributionSetId, selectTargetWithNoTag, true, tagNames); return findByCriteriaAPI(pageable, specList); } @Override - public Long countTargetByFilters(final Collection status, final String searchText, - final Long installedOrAssignedDistributionSetId, final Boolean selectTargetWithNoTag, - final String... tagNames) { - final List> specList = buildSpecificationList(status, searchText, + public Long countTargetByFilters(final Collection status, final Boolean overdueState, + final String searchText, final Long installedOrAssignedDistributionSetId, + final Boolean selectTargetWithNoTag, final String... tagNames) { + final List> specList = buildSpecificationList(status, overdueState, searchText, installedOrAssignedDistributionSetId, selectTargetWithNoTag, true, tagNames); return countByCriteriaAPI(specList); } private static List> buildSpecificationList(final Collection status, - final String searchText, final Long installedOrAssignedDistributionSetId, + final Boolean overdueState, final String searchText, final Long installedOrAssignedDistributionSetId, final Boolean selectTargetWithNoTag, final boolean fetch, final String... tagNames) { final List> specList = new ArrayList<>(); if (status != null && !status.isEmpty()) { specList.add(TargetSpecifications.hasTargetUpdateStatus(status, fetch)); } + if (overdueState != null) { + specList.add( + TargetSpecifications.isOverdue(new VirtualPropertyMakroResolver().calculateOverdueTimestamp())); + } if (installedOrAssignedDistributionSetId != null) { specList.add( TargetSpecifications.hasInstalledOrAssignedDistributionSet(installedOrAssignedDistributionSetId)); @@ -425,7 +429,8 @@ public class JpaTargetManagement implements TargetManagement { @Override public Slice findTargetsAllOrderByLinkedDistributionSet(final Pageable pageable, final Long orderByDistributionId, final Long filterByDistributionId, - final Collection filterByStatus, final String filterBySearchText, + final Collection filterByStatus, final Boolean overdueState, + final String filterBySearchText, final Boolean selectTargetWithNoTag, final String... filterByTagNames) { final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); final CriteriaQuery query = cb.createQuery(JpaTarget.class); @@ -449,7 +454,7 @@ public class JpaTargetManagement implements TargetManagement { // build the specifications and then to predicates necessary by the // given filters final Predicate[] specificationsForMultiSelect = specificationsToPredicate( - buildSpecificationList(filterByStatus, filterBySearchText, filterByDistributionId, + buildSpecificationList(filterByStatus, overdueState, filterBySearchText, filterByDistributionId, selectTargetWithNoTag, true, filterByTagNames), targetRoot, query, cb); @@ -506,7 +511,8 @@ public class JpaTargetManagement implements TargetManagement { @Override public List findAllTargetIdsByFilters(final Pageable pageRequest, - final Collection filterByStatus, final String filterBySearchText, + final Collection filterByStatus, final Boolean overdueState, + final String filterBySearchText, final Long installedOrAssignedDistributionSetId, final Boolean selectTargetWithNoTag, final String... filterByTagNames) { final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); @@ -523,7 +529,8 @@ public class JpaTargetManagement implements TargetManagement { targetRoot.get(JpaTarget_.controllerId), targetRoot.get(JpaTarget_.name), targetRoot.get(sortProperty)); final Predicate[] specificationsForMultiSelect = specificationsToPredicate( - buildSpecificationList(filterByStatus, filterBySearchText, installedOrAssignedDistributionSetId, + buildSpecificationList(filterByStatus, overdueState, filterBySearchText, + installedOrAssignedDistributionSetId, selectTargetWithNoTag, false, filterByTagNames), targetRoot, multiselect, cb); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/VirtualPropertyMakroResolver.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/VirtualPropertyMakroResolver.java index 8425e4a11..5ade64630 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/VirtualPropertyMakroResolver.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/VirtualPropertyMakroResolver.java @@ -48,13 +48,18 @@ public class VirtualPropertyMakroResolver extends StrLookup { if ("now_ts".equals(rhs.toLowerCase())) { resolved = String.valueOf(Instant.now().toEpochMilli()); } else if ("overdue_ts".equals(rhs.toLowerCase())) { - resolved = String.valueOf(Instant.now().toEpochMilli() // - - getDurationForKey(TenantConfigurationKey.POLLING_TIME_INTERVAL).toMillis() // - - getDurationForKey(TenantConfigurationKey.POLLING_OVERDUE_TIME_INTERVAL).toMillis()); + resolved = String.valueOf(calculateOverdueTimestamp()); } return resolved; } + public long calculateOverdueTimestamp() { + long overdueTs = Instant.now().toEpochMilli() // + - getDurationForKey(TenantConfigurationKey.POLLING_TIME_INTERVAL).toMillis() // + - getDurationForKey(TenantConfigurationKey.POLLING_OVERDUE_TIME_INTERVAL).toMillis(); + return overdueTs; + } + private Duration getDurationForKey(TenantConfigurationKey key) { return DurationHelper.formattedStringToDuration(getRawStringForKey(key)); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java index 6571f8668..5503ae36e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java @@ -86,7 +86,7 @@ public final class TargetSpecifications { /** * {@link Specification} for retrieving {@link Target}s by "equal to given * {@link TargetUpdateStatus}". - * + * * @param updateStatus * to be filtered on * @param fetch @@ -110,10 +110,34 @@ public final class TargetSpecifications { }; } + /** + * {@link Specification} for retrieving {@link Target}s that are overdue. A + * target is overdue if it did not respond during the configured + * intervals:
+ * poll_itvl + overdue_itvl + * + * @param overdueTimestamp + * the calculated timestamp to compare with the last respond of a + * target (lastTargetQuery).
+ * The overdueTimestamp has to be calculated with + * the following expression:
+ * overdueTimestamp = nowTimestamp - poll_itvl - + * overdue_itvl + * + * @return the {@link Target} {@link Specification} + */ + public static Specification isOverdue(final long overdueTimestamp) { + return (targetRoot, query, cb) -> { + final Join targetInfoJoin = targetRoot.join(JpaTarget_.targetInfo); + return cb.lessThanOrEqualTo( + targetInfoJoin.get(JpaTargetInfo_.lastTargetQuery), overdueTimestamp); + }; + } + /** * {@link Specification} for retrieving {@link Target}s by * "like controllerId or like description or like ip address". - * + * * @param searchText * to be filtered on * @return the {@link Target} {@link Specification} @@ -129,7 +153,7 @@ public final class TargetSpecifications { /** * {@link Specification} for retrieving {@link Target}s by * "like controllerId". - * + * * @param distributionId * to be filtered on * @return the {@link Target} {@link Specification} @@ -166,7 +190,7 @@ public final class TargetSpecifications { /** * {@link Specification} for retrieving {@link Target}s by * "has no tag names"or "has at least on of the given tag names". - * + * * @param tagNames * to be filtered on * @param selectTargetWithNoTag @@ -199,7 +223,7 @@ public final class TargetSpecifications { /** * {@link Specification} for retrieving {@link Target}s by assigned * distribution set. - * + * * @param distributionSetId * the ID of the distribution set which must be assigned * @return the {@link Target} {@link Specification} @@ -213,7 +237,7 @@ public final class TargetSpecifications { /** * {@link Specification} for retrieving {@link Target}s by assigned * distribution set. - * + * * @param distributionSetId * the ID of the distribution set which must be assigned * @return the {@link Target} {@link Specification} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementSearchTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementSearchTest.java index 1e8f102c7..e4c6a15b9 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementSearchTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementSearchTest.java @@ -10,20 +10,27 @@ package org.eclipse.hawkbit.repository.jpa; import static org.fest.assertions.api.Assertions.assertThat; +import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.Map; +import java.util.stream.Collector; import java.util.stream.Collectors; +import java.util.stream.IntStream; +import org.eclipse.hawkbit.ControllerPollProperties; import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag; +import org.eclipse.hawkbit.repository.jpa.model.helper.TenantConfigurationManagementHolder; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.Status; +import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey; import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Target; @@ -32,6 +39,7 @@ import org.eclipse.hawkbit.repository.model.TargetTag; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity; import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Slice; import com.google.common.collect.Lists; @@ -60,26 +68,42 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { final DistributionSet installedSet = testdataFactory.createDistributionSet("another"); + final Long lastTargetQueryNotOverdue = Instant.now().toEpochMilli(); + final Long lastTargetQueryAlwaysOverdue = 0L; + final Long lastTargetNull = null; + final String targetDsAIdPref = "targ-A"; - List targAs = targetManagement.createTargets( - testdataFactory.generateTargets(100, targetDsAIdPref, targetDsAIdPref.concat(" description"))); + List targAs = new ArrayList(); + for (Target t : testdataFactory.generateTargets(100, targetDsAIdPref, targetDsAIdPref.concat(" description"))) { + targAs.add(targetManagement.createTarget(t, TargetUpdateStatus.UNKNOWN, lastTargetQueryNotOverdue, + t.getTargetInfo().getAddress())); + } targAs = targetManagement.toggleTagAssignment(targAs, targTagX).getAssignedEntity(); final String targetDsBIdPref = "targ-B"; - List targBs = targetManagement.createTargets( - testdataFactory.generateTargets(100, targetDsBIdPref, targetDsBIdPref.concat(" description"))); + List targBs = new ArrayList(); + for (Target t : testdataFactory.generateTargets(100, targetDsBIdPref, targetDsBIdPref.concat(" description"))) { + targBs.add(targetManagement.createTarget(t, TargetUpdateStatus.UNKNOWN, lastTargetQueryAlwaysOverdue, + t.getTargetInfo().getAddress())); + } targBs = targetManagement.toggleTagAssignment(targBs, targTagY).getAssignedEntity(); targBs = targetManagement.toggleTagAssignment(targBs, targTagW).getAssignedEntity(); final String targetDsCIdPref = "targ-C"; - List targCs = targetManagement.createTargets( - testdataFactory.generateTargets(100, targetDsCIdPref, targetDsCIdPref.concat(" description"))); + List targCs = new ArrayList(); + for (Target t : testdataFactory.generateTargets(100, targetDsCIdPref, targetDsCIdPref.concat(" description"))) { + targCs.add(targetManagement.createTarget(t, TargetUpdateStatus.UNKNOWN, lastTargetQueryAlwaysOverdue, + t.getTargetInfo().getAddress())); + } targCs = targetManagement.toggleTagAssignment(targCs, targTagZ).getAssignedEntity(); targCs = targetManagement.toggleTagAssignment(targCs, targTagW).getAssignedEntity(); final String targetDsDIdPref = "targ-D"; - final List targDs = targetManagement.createTargets( - testdataFactory.generateTargets(100, targetDsDIdPref, targetDsDIdPref.concat(" description"))); + List targDs = new ArrayList(); + for (Target t : testdataFactory.generateTargets(100, targetDsDIdPref, targetDsDIdPref.concat(" description"))) { + targDs.add(targetManagement.createTarget(t, TargetUpdateStatus.UNKNOWN, lastTargetNull, + t.getTargetInfo().getAddress())); + } final String assignedC = targCs.iterator().next().getControllerId(); deploymentManagement.assignDistributionSet(setA.getId(), assignedC); @@ -155,6 +179,10 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { verifyThat200targetsWithGivenTagAreInStatusPendingorUnknown(targTagW, both, concat(targBs, targCs)); verfiyThat1TargetAIsInStatusPendingAndHasDSInstalled(installedSet, pending, targetManagement.findTargetByControllerID(installedC)); + + expected = concat(targBs, targCs); + expected.removeAll(targetManagement.findTargetByControllerID(Lists.newArrayList(assignedB, assignedC))); + verifyThat198TargetsAreInStatusUnknownAndOverdue(unknown, expected); } @Step @@ -164,10 +192,10 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { final String query = "updatestatus==pending and installedds.name==" + installedSet.getName(); assertThat(targetManagement - .findTargetByFilters(pageReq, pending, null, installedSet.getId(), Boolean.FALSE, new String[0]) + .findTargetByFilters(pageReq, pending, null, null, installedSet.getId(), Boolean.FALSE, new String[0]) .getContent()).as("has number of elements").hasSize(1) .as("that number is also returned by count query") - .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(pending, null, + .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(pending, null, null, installedSet.getId(), Boolean.FALSE, new String[0]))) .as("and contains the following elements").containsExactly(expected) .as("and filter query returns the same result") @@ -175,7 +203,7 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { .as("and NAMED filter query returns the same result").containsAll(targetManagement .findTargetsAll(new JpaTargetFilterQuery("test", query), pageReq).getContent()); - assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, pending, null, installedSet.getId(), + assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, pending, null, null, installedSet.getId(), Boolean.FALSE, new String[0])).as("has number of elements").hasSize(1) .as("and contains the following elements").containsExactly(expectedIdName) .as("and NAMED filter query returns the same result").containsAll(targetManagement @@ -190,10 +218,10 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { final String query = "(updatestatus==pending or updatestatus==unknown) and tag==" + targTagW.getName(); - assertThat(targetManagement.findTargetByFilters(pageReq, both, null, null, Boolean.FALSE, targTagW.getName()) - .getContent()).as("has number of elements").hasSize(200) - .as("that number is also returned by count query") - .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(both, null, null, + assertThat(targetManagement + .findTargetByFilters(pageReq, both, null, null, null, Boolean.FALSE, targTagW.getName()).getContent()) + .as("has number of elements").hasSize(200).as("that number is also returned by count query") + .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(both, null, null, null, Boolean.FALSE, targTagW.getName()))) .as("and contains the following elements").containsAll(expected) .as("and filter query returns the same result") @@ -201,7 +229,7 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { .as("and NAMED filter query returns the same result").containsAll(targetManagement .findTargetsAll(new JpaTargetFilterQuery("test", query), pageReq).getContent()); - assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, both, null, null, Boolean.FALSE, + assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, both, null, null, null, Boolean.FALSE, targTagW.getName())).as("has number of elements").hasSize(200).as("and contains the following elements") .containsAll(expectedIdNames).as("and NAMED filter query returns the same result") .containsAll(targetManagement.findAllTargetIdsByTargetFilterQuery(pageReq, @@ -224,10 +252,11 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { final List expectedIdNames = convertToIdNames(expected); final String query = "updatestatus==pending and tag==" + targTagW.getName(); - assertThat(targetManagement.findTargetByFilters(pageReq, pending, null, null, Boolean.FALSE, targTagW.getName()) + assertThat(targetManagement + .findTargetByFilters(pageReq, pending, null, null, null, Boolean.FALSE, targTagW.getName()) .getContent()).as("has number of elements").hasSize(2) .as("that number is also returned by count query") - .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(pending, null, null, + .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(pending, null, null, null, Boolean.FALSE, targTagW.getName()))) .as("and contains the following elements").containsAll(expected) .as("and filter query returns the same result") @@ -235,7 +264,7 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { .as("and NAMED filter query returns the same result").containsAll(targetManagement .findTargetsAll(new JpaTargetFilterQuery("test", query), pageReq).getContent()); - assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, pending, null, null, Boolean.FALSE, + assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, pending, null, null, null, Boolean.FALSE, targTagW.getName())).as("has number of elements").hasSize(2).as("and contains the following elements") .containsAll(expectedIdNames).as("and NAMED filter query returns the same result") .containsAll(targetManagement.findAllTargetIdsByTargetFilterQuery(pageReq, @@ -250,18 +279,18 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { + setA.getName() + ") and tag==" + targTagW.getName(); assertThat(targetManagement - .findTargetByFilters(pageReq, pending, null, setA.getId(), Boolean.FALSE, targTagW.getName()) + .findTargetByFilters(pageReq, pending, null, null, setA.getId(), Boolean.FALSE, targTagW.getName()) .getContent()).as("has number of elements").hasSize(2) .as("that number is also returned by count query") - .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(pending, null, setA.getId(), - Boolean.FALSE, targTagW.getName()))) + .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(pending, null, null, + setA.getId(), Boolean.FALSE, targTagW.getName()))) .as("and contains the following elements").containsAll(expected) .as("and filter query returns the same result") .containsAll(targetManagement.findTargetsAll(query, pageReq).getContent()) .as("and NAMED filter query returns the same result").containsAll(targetManagement .findTargetsAll(new JpaTargetFilterQuery("test", query), pageReq).getContent()); - assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, pending, null, null, Boolean.FALSE, + assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, pending, null, null, null, Boolean.FALSE, targTagW.getName())).as("has number of elements").hasSize(2).as("and contains the following elements") .containsAll(expectedIdNames).as("and NAMED filter query returns the same result") .containsAll(targetManagement.findAllTargetIdsByTargetFilterQuery(pageReq, @@ -275,11 +304,10 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { final String query = "updatestatus==pending and (assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName() + ") and (name==*targ-B* or description==*targ-B*) and tag==" + targTagW.getName(); - assertThat(targetManagement - .findTargetByFilters(pageReq, pending, "%targ-B%", setA.getId(), Boolean.FALSE, targTagW.getName()) - .getContent()).as("has number of elements").hasSize(1) + assertThat(targetManagement.findTargetByFilters(pageReq, pending, null, "%targ-B%", setA.getId(), Boolean.FALSE, + targTagW.getName()).getContent()).as("has number of elements").hasSize(1) .as("that number is also returned by count query") - .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(pending, "%targ-B%", + .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(pending, null, "%targ-B%", setA.getId(), Boolean.FALSE, targTagW.getName()))) .as("and contains the following elements").containsExactly(expected) .as("and filter query returns the same result") @@ -287,11 +315,11 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { .as("and NAMED filter query returns the same result").containsAll(targetManagement .findTargetsAll(new JpaTargetFilterQuery("test", query), pageReq).getContent()); - assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, pending, "%targ-B%", setA.getId(), Boolean.FALSE, - targTagW.getName())).as("has number of elements").hasSize(1).as("and contains the following elements") - .containsExactly(expectedIdName).as("and NAMED filter query returns the same result") - .containsAll(targetManagement.findAllTargetIdsByTargetFilterQuery(pageReq, - new JpaTargetFilterQuery("test", query))); + assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, pending, null, "%targ-B%", setA.getId(), + Boolean.FALSE, targTagW.getName())).as("has number of elements").hasSize(1) + .as("and contains the following elements").containsExactly(expectedIdName) + .as("and NAMED filter query returns the same result").containsAll(targetManagement + .findAllTargetIdsByTargetFilterQuery(pageReq, new JpaTargetFilterQuery("test", query))); } @Step @@ -302,10 +330,10 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { + setA.getName() + ") and (name==*targ-A* or description==*targ-A*)"; assertThat(targetManagement - .findTargetByFilters(pageReq, pending, "%targ-A%", setA.getId(), Boolean.FALSE, new String[0]) + .findTargetByFilters(pageReq, pending, null, "%targ-A%", setA.getId(), Boolean.FALSE, new String[0]) .getContent()).as("has number of elements").hasSize(1) .as("that number is also returned by count query") - .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(pending, "%targ-A%", + .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(pending, null, "%targ-A%", setA.getId(), Boolean.FALSE, new String[0]))) .as("and contains the following elements").containsExactly(expected) .as("and filter query returns the same result") @@ -313,11 +341,11 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { .as("and NAMED filter query returns the same result").containsAll(targetManagement .findTargetsAll(new JpaTargetFilterQuery("test", query), pageReq).getContent()); - assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, pending, "%targ-A%", setA.getId(), Boolean.FALSE, - new String[0])).as("has number of elements").hasSize(1).as("and contains the following elements") - .containsExactly(expectedIdName).as("and NAMED filter query returns the same result") - .containsAll(targetManagement.findAllTargetIdsByTargetFilterQuery(pageReq, - new JpaTargetFilterQuery("test", query))); + assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, pending, null, "%targ-A%", setA.getId(), + Boolean.FALSE, new String[0])).as("has number of elements").hasSize(1) + .as("and contains the following elements").containsExactly(expectedIdName) + .as("and NAMED filter query returns the same result").containsAll(targetManagement + .findAllTargetIdsByTargetFilterQuery(pageReq, new JpaTargetFilterQuery("test", query))); } @Step @@ -328,17 +356,17 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { + setA.getName() + ")"; assertThat(targetManagement - .findTargetByFilters(pageReq, pending, null, setA.getId(), Boolean.FALSE, new String[0]).getContent()) - .as("has number of elements").hasSize(3).as("that number is also returned by count query") - .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(pending, null, setA.getId(), - Boolean.FALSE, new String[0]))) + .findTargetByFilters(pageReq, pending, null, null, setA.getId(), Boolean.FALSE, new String[0]) + .getContent()).as("has number of elements").hasSize(3).as("that number is also returned by count query") + .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(pending, null, null, + setA.getId(), Boolean.FALSE, new String[0]))) .as("and contains the following elements").containsAll(expected) .as("and filter query returns the same result") .containsAll(targetManagement.findTargetsAll(query, pageReq).getContent()) .as("and NAMED filter query returns the same result").containsAll(targetManagement .findTargetsAll(new JpaTargetFilterQuery("test", query), pageReq).getContent()); - assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, pending, null, setA.getId(), Boolean.FALSE, + assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, pending, null, null, setA.getId(), Boolean.FALSE, new String[0])).as("has number of elements").hasSize(3).as("and contains the following elements") .containsAll(expectedIdNames).as("and NAMED filter query returns the same result") .containsAll(targetManagement.findAllTargetIdsByTargetFilterQuery(pageReq, @@ -351,10 +379,10 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { final List expectedIdNames = convertToIdNames(expected); final String query = "updatestatus==pending"; - assertThat(targetManagement.findTargetByFilters(pageReq, pending, null, null, Boolean.FALSE, new String[0]) - .getContent()).as("has number of elements").hasSize(3) - .as("that number is also returned by count query") - .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(pending, null, null, + assertThat(targetManagement + .findTargetByFilters(pageReq, pending, null, null, null, Boolean.FALSE, new String[0]).getContent()) + .as("has number of elements").hasSize(3).as("that number is also returned by count query") + .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(pending, null, null, null, Boolean.FALSE, new String[0]))) .as("and contains the following elements").containsAll(expected) .as("and filter query returns the same result") @@ -362,9 +390,8 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { .as("and NAMED filter query returns the same result").containsAll(targetManagement .findTargetsAll(new JpaTargetFilterQuery("test", query), pageReq).getContent()); - assertThat( - targetManagement.findAllTargetIdsByFilters(pageReq, pending, null, null, Boolean.FALSE, new String[0])) - .as("has number of elements").hasSize(3).as("and contains the following elements") + assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, pending, null, null, null, Boolean.FALSE, + new String[0])).as("has number of elements").hasSize(3).as("and contains the following elements") .containsAll(expectedIdNames).as("and NAMED filter query returns the same result") .containsAll(targetManagement.findAllTargetIdsByTargetFilterQuery(pageReq, new JpaTargetFilterQuery("test", query))); @@ -378,18 +405,18 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { + targTagW.getName(); assertThat(targetManagement - .findTargetByFilters(pageReq, unknown, "%targ-B%", null, Boolean.FALSE, targTagW.getName()) + .findTargetByFilters(pageReq, unknown, null, "%targ-B%", null, Boolean.FALSE, targTagW.getName()) .getContent()).as("has number of elements").hasSize(99) .as("that number is also returned by count query") - .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(unknown, "%targ-B%", null, - Boolean.FALSE, targTagW.getName()))) + .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(unknown, null, "%targ-B%", + null, Boolean.FALSE, targTagW.getName()))) .as("and contains the following elements").containsAll(expected) .as("and filter query returns the same result") .containsAll(targetManagement.findTargetsAll(query, pageReq).getContent()) .as("and NAMED filter query returns the same result").containsAll(targetManagement .findTargetsAll(new JpaTargetFilterQuery("test", query), pageReq).getContent()); - assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, unknown, "%targ-B%", null, Boolean.FALSE, + assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, unknown, null, "%targ-B%", null, Boolean.FALSE, targTagW.getName())).as("has number of elements").hasSize(99).as("and contains the following elements") .containsAll(expectedIdNames).as("and NAMED filter query returns the same result") .containsAll(targetManagement.findAllTargetIdsByTargetFilterQuery(pageReq, @@ -403,17 +430,17 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { final String query = "updatestatus==unknown and (name==*targ-A* or description==*targ-A*)"; assertThat(targetManagement - .findTargetByFilters(pageReq, unknown, "%targ-A%", null, Boolean.FALSE, new String[0]).getContent()) - .as("has number of elements").hasSize(99).as("that number is also returned by count query") - .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(unknown, "%targ-A%", null, - Boolean.FALSE, new String[0]))) + .findTargetByFilters(pageReq, unknown, null, "%targ-A%", null, Boolean.FALSE, new String[0]) + .getContent()).as("has number of elements").hasSize(99) + .as("that number is also returned by count query").hasSize(Ints.saturatedCast(targetManagement + .countTargetByFilters(unknown, null, "%targ-A%", null, Boolean.FALSE, new String[0]))) .as("and contains the following elements").containsAll(expected) .as("and filter query returns the same result") .containsAll(targetManagement.findTargetsAll(query, pageReq).getContent()) .as("and NAMED filter query returns the same result").containsAll(targetManagement .findTargetsAll(new JpaTargetFilterQuery("test", query), pageReq).getContent()); - assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, unknown, "%targ-A%", null, Boolean.FALSE, + assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, unknown, null, "%targ-A%", null, Boolean.FALSE, new String[0])).as("has number of elements").hasSize(99).as("and contains the following elements") .containsAll(expectedIdNames).as("and NAMED filter query returns the same result") .containsAll(targetManagement.findAllTargetIdsByTargetFilterQuery(pageReq, @@ -427,16 +454,16 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { + setA.getName() + ")"; assertThat(targetManagement - .findTargetByFilters(pageReq, unknown, null, setA.getId(), Boolean.FALSE, new String[0]).getContent()) - .as("has number of elements").hasSize(0).as("that number is also returned by count query") - .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(unknown, null, setA.getId(), - Boolean.FALSE, new String[0]))) + .findTargetByFilters(pageReq, unknown, null, null, setA.getId(), Boolean.FALSE, new String[0]) + .getContent()).as("has number of elements").hasSize(0).as("that number is also returned by count query") + .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(unknown, null, null, + setA.getId(), Boolean.FALSE, new String[0]))) .as("and filter query returns the same result") .hasSize(targetManagement.findTargetsAll(query, pageReq).getContent().size()) .as("and NAMED filter query returns the same result").hasSize(targetManagement .findTargetsAll(new JpaTargetFilterQuery("test", query), pageReq).getContent().size()); - assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, unknown, null, setA.getId(), Boolean.FALSE, + assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, unknown, null, null, setA.getId(), Boolean.FALSE, new String[0])).as("has number of elements").hasSize(0) .as("and NAMED filter query returns the same result").containsAll(targetManagement .findAllTargetIdsByTargetFilterQuery(pageReq, new JpaTargetFilterQuery("test", query))); @@ -449,10 +476,10 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { final String query = "updatestatus==unknown and (tag==" + targTagY.getName() + " or tag==" + targTagW.getName() + ")"; - assertThat(targetManagement.findTargetByFilters(pageReq, unknown, null, null, Boolean.FALSE, targTagY.getName(), - targTagW.getName()).getContent()).as("has number of elements").hasSize(198) + assertThat(targetManagement.findTargetByFilters(pageReq, unknown, null, null, null, Boolean.FALSE, + targTagY.getName(), targTagW.getName()).getContent()).as("has number of elements").hasSize(198) .as("that number is also returned by count query") - .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(unknown, null, null, + .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(unknown, null, null, null, Boolean.FALSE, targTagY.getName(), targTagW.getName()))) .as("and contains the following elements").containsAll(expected) .as("and filter query returns the same result") @@ -460,7 +487,7 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { .as("and NAMED filter query returns the same result").containsAll(targetManagement .findTargetsAll(new JpaTargetFilterQuery("test", query), pageReq).getContent()); - assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, unknown, null, null, Boolean.FALSE, + assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, unknown, null, null, null, Boolean.FALSE, targTagY.getName(), targTagW.getName())).as("has number of elements").hasSize(198) .as("and contains the following elements").containsAll(expectedIdNames) .as("and NAMED filter query returns the same result").containsAll(targetManagement @@ -473,10 +500,10 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { final List expectedIdNames = convertToIdNames(expected); final String query = "updatestatus==unknown"; - assertThat(targetManagement.findTargetByFilters(pageReq, unknown, null, null, Boolean.FALSE, new String[0]) - .getContent()).as("has number of elements").hasSize(397) - .as("that number is also returned by count query") - .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(unknown, null, null, + assertThat(targetManagement + .findTargetByFilters(pageReq, unknown, null, null, null, Boolean.FALSE, new String[0]).getContent()) + .as("has number of elements").hasSize(397).as("that number is also returned by count query") + .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(unknown, null, null, null, Boolean.FALSE, new String[0]))) .as("and contains the following elements").containsAll(expected) .as("and filter query returns the same result") @@ -484,9 +511,34 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { .as("and NAMED filter query returns the same result").containsAll(targetManagement .findTargetsAll(new JpaTargetFilterQuery("test", query), pageReq).getContent()); - assertThat( - targetManagement.findAllTargetIdsByFilters(pageReq, unknown, null, null, Boolean.FALSE, new String[0])) - .as("has number of elements").hasSize(397).as("and contains the following elements") + assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, unknown, null, null, null, Boolean.FALSE, + new String[0])).as("has number of elements").hasSize(397).as("and contains the following elements") + .containsAll(expectedIdNames).as("and NAMED filter query returns the same result") + .containsAll(targetManagement.findAllTargetIdsByTargetFilterQuery(pageReq, + new JpaTargetFilterQuery("test", query))); + } + + @Step + private void verifyThat198TargetsAreInStatusUnknownAndOverdue(final List unknown, + final List expected) { + final List expectedIdNames = convertToIdNames(expected); + // be careful: simple filters are concatenated using AND-gating + final String query = "lastcontrollerrequestat=le=${overdue_ts};updatestatus==UNKNOWN"; + + assertThat(targetManagement + .findTargetByFilters(pageReq, unknown, Boolean.TRUE, null, null, Boolean.FALSE, new String[0]) + .getContent()).as("has number of elements").hasSize(198) + .as("that number is also returned by count query") + .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(unknown, Boolean.TRUE, null, + null, Boolean.FALSE, new String[0]))) + .as("and contains the following elements").containsAll(expected) + .as("and filter query returns the same result") + .containsAll(targetManagement.findTargetsAll(query, pageReq).getContent()) + .as("and NAMED filter query returns the same result").containsAll(targetManagement + .findTargetsAll(new JpaTargetFilterQuery("test", query), pageReq).getContent()); + + assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, unknown, Boolean.TRUE, null, null, Boolean.FALSE, + new String[0])).as("has number of elements").hasSize(198).as("and contains the following elements") .containsAll(expectedIdNames).as("and NAMED filter query returns the same result") .containsAll(targetManagement.findAllTargetIdsByTargetFilterQuery(pageReq, new JpaTargetFilterQuery("test", query))); @@ -499,10 +551,10 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { + " or installedds.name==" + setA.getName() + ")"; assertThat(targetManagement - .findTargetByFilters(pageReq, null, "%targ-A%", setA.getId(), Boolean.FALSE, new String[0]) + .findTargetByFilters(pageReq, null, null, "%targ-A%", setA.getId(), Boolean.FALSE, new String[0]) .getContent()).as("has number of elements").hasSize(1) .as("that number is also returned by count query") - .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(null, "%targ-A%", + .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(null, null, "%targ-A%", setA.getId(), Boolean.FALSE, new String[0]))) .as("and contains the following elements").containsExactly(expected) .as("and filter query returns the same result") @@ -510,11 +562,11 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { .as("and NAMED filter query returns the same result").containsAll(targetManagement .findTargetsAll(new JpaTargetFilterQuery("test", query), pageReq).getContent()); - assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, null, "%targ-A%", setA.getId(), Boolean.FALSE, - new String[0])).as("has number of elements").hasSize(1).as("and contains the following elements") - .containsExactly(expectedIdName).as("and NAMED filter query returns the same result") - .containsAll(targetManagement.findAllTargetIdsByTargetFilterQuery(pageReq, - new JpaTargetFilterQuery("test", query))); + assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, null, null, "%targ-A%", setA.getId(), + Boolean.FALSE, new String[0])).as("has number of elements").hasSize(1) + .as("and contains the following elements").containsExactly(expectedIdName) + .as("and NAMED filter query returns the same result").containsAll(targetManagement + .findAllTargetIdsByTargetFilterQuery(pageReq, new JpaTargetFilterQuery("test", query))); } @Step @@ -522,18 +574,19 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { final List expectedIdNames = convertToIdNames(expected); final String query = "assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName(); - assertThat(targetManagement.findTargetByFilters(pageReq, null, null, setA.getId(), Boolean.FALSE, new String[0]) + assertThat(targetManagement + .findTargetByFilters(pageReq, null, null, null, setA.getId(), Boolean.FALSE, new String[0]) .getContent()).as("has number of elements").hasSize(3) .as("that number is also returned by count query") - .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(null, null, setA.getId(), - Boolean.FALSE, new String[0]))) + .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(null, null, null, + setA.getId(), Boolean.FALSE, new String[0]))) .as("and contains the following elements").containsAll(expected) .as("and filter query returns the same result") .containsAll(targetManagement.findTargetsAll(query, pageReq).getContent()) .as("and NAMED filter query returns the same result").containsAll(targetManagement .findTargetsAll(new JpaTargetFilterQuery("test", query), pageReq).getContent()); - assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, null, null, setA.getId(), Boolean.FALSE, + assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, null, null, null, setA.getId(), Boolean.FALSE, new String[0])).as("has number of elements").hasSize(3).as("and contains the following elements") .containsAll(expectedIdNames).as("and NAMED filter query returns the same result") .containsAll(targetManagement.findAllTargetIdsByTargetFilterQuery(pageReq, @@ -545,18 +598,18 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { final String query = "(name==*targ-C* or description==*targ-C*) and tag==" + targTagX.getName() + " and (assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName() + ")"; assertThat(targetManagement - .findTargetByFilters(pageReq, null, "%targ-C%", setA.getId(), Boolean.FALSE, targTagX.getName()) + .findTargetByFilters(pageReq, null, null, "%targ-C%", setA.getId(), Boolean.FALSE, targTagX.getName()) .getContent()).as("has number of elements").hasSize(0) .as("that number is also returned by count query") - .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(null, "%targ-C%", + .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(null, null, "%targ-C%", setA.getId(), Boolean.FALSE, targTagX.getName()))) .as("and filter query returns the same result") .hasSize(targetManagement.findTargetsAll(query, pageReq).getContent().size()) .as("and NAMED filter query returns the same result").hasSize(targetManagement .findTargetsAll(new JpaTargetFilterQuery("test", query), pageReq).getContent().size()); - assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, null, "%targ-C%", setA.getId(), Boolean.FALSE, - targTagX.getName())).as("has number of elements").hasSize(0) + assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, null, null, "%targ-C%", setA.getId(), + Boolean.FALSE, targTagX.getName())).as("has number of elements").hasSize(0) .as("and NAMED filter query returns the same result").containsAll(targetManagement .findAllTargetIdsByTargetFilterQuery(pageReq, new JpaTargetFilterQuery("test", query))); } @@ -566,18 +619,18 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { final String query = "(name==*targ-A* or description==*targ-A*) and tag==" + targTagW.getName() + " and (assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName() + ")"; assertThat(targetManagement - .findTargetByFilters(pageReq, null, "%targ-A%", setA.getId(), Boolean.FALSE, targTagW.getName()) + .findTargetByFilters(pageReq, null, null, "%targ-A%", setA.getId(), Boolean.FALSE, targTagW.getName()) .getContent()).as("has number of elements").hasSize(0) .as("that number is also returned by count query") - .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(null, "%targ-A%", + .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(null, null, "%targ-A%", setA.getId(), Boolean.FALSE, targTagW.getName()))) .as("and filter query returns the same result") .hasSize(targetManagement.findTargetsAll(query, pageReq).getContent().size()) .as("and NAMED filter query returns the same result").hasSize(targetManagement .findTargetsAll(new JpaTargetFilterQuery("test", query), pageReq).getContent().size()); - assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, null, "%targ-A%", setA.getId(), Boolean.FALSE, - targTagW.getName())).as("has number of elements").hasSize(0) + assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, null, null, "%targ-A%", setA.getId(), + Boolean.FALSE, targTagW.getName())).as("has number of elements").hasSize(0) .as("and NAMED filter query returns the same result").containsAll(targetManagement .findAllTargetIdsByTargetFilterQuery(pageReq, new JpaTargetFilterQuery("test", query))); } @@ -589,10 +642,10 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { final String query = "(name==*targ-c* or description==*targ-C*) and tag==" + targTagW.getName() + " and (assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName() + ")"; assertThat(targetManagement - .findTargetByFilters(pageReq, null, "%targ-C%", setA.getId(), Boolean.FALSE, targTagW.getName()) + .findTargetByFilters(pageReq, null, null, "%targ-C%", setA.getId(), Boolean.FALSE, targTagW.getName()) .getContent()).as("has number of elements").hasSize(1) .as("that number is also returned by count query") - .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(null, "%targ-C%", + .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(null, null, "%targ-C%", setA.getId(), Boolean.FALSE, targTagW.getName()))) .as("and contains the following elements").containsExactly(expected) .as("and filter query returns the same result") @@ -600,11 +653,11 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { .as("and NAMED filter query returns the same result").containsAll(targetManagement .findTargetsAll(new JpaTargetFilterQuery("test", query), pageReq).getContent()); - assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, null, "%targ-C%", setA.getId(), Boolean.FALSE, - targTagW.getName())).as("has number of elements").hasSize(1).as("and contains the following elements") - .containsExactly(expectedIdName).as("and NAMED filter query returns the same result") - .containsAll(targetManagement.findAllTargetIdsByTargetFilterQuery(pageReq, - new JpaTargetFilterQuery("test", query))); + assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, null, null, "%targ-C%", setA.getId(), + Boolean.FALSE, targTagW.getName())).as("has number of elements").hasSize(1) + .as("and contains the following elements").containsExactly(expectedIdName) + .as("and NAMED filter query returns the same result").containsAll(targetManagement + .findAllTargetIdsByTargetFilterQuery(pageReq, new JpaTargetFilterQuery("test", query))); } @Step @@ -613,10 +666,10 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { final List expectedIdNames = convertToIdNames(expected); final String query = "(name==*targ-B* or description==*targ-B*) and (tag==" + targTagY.getName() + " or tag==" + targTagW.getName() + ")"; - assertThat(targetManagement.findTargetByFilters(pageReq, null, "%targ-B%", null, Boolean.FALSE, + assertThat(targetManagement.findTargetByFilters(pageReq, null, null, "%targ-B%", null, Boolean.FALSE, targTagY.getName(), targTagW.getName()).getContent()).as("has number of elements").hasSize(100) .as("that number is also returned by count query") - .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(null, "%targ-B%", null, + .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(null, null, "%targ-B%", null, Boolean.FALSE, targTagY.getName(), targTagW.getName()))) .as("and contains the following elements").containsAll(expected) .as("and filter query returns the same result") @@ -624,7 +677,7 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { .as("and NAMED filter query returns the same result").containsAll(targetManagement .findTargetsAll(new JpaTargetFilterQuery("test", query), pageReq).getContent()); - assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, null, "%targ-B%", null, Boolean.FALSE, + assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, null, null, "%targ-B%", null, Boolean.FALSE, targTagY.getName(), targTagW.getName())).as("has number of elements").hasSize(100) .as("and contains the following elements").containsAll(expectedIdNames) .as("and NAMED filter query returns the same result").containsAll(targetManagement @@ -643,10 +696,11 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { private void verifyThat200TargetsHaveTagD(final TargetTag targTagD, final List expected) { final List expectedIdNames = convertToIdNames(expected); final String query = "tag==" + targTagD.getName(); - assertThat(targetManagement.findTargetByFilters(pageReq, null, null, null, Boolean.FALSE, targTagD.getName()) - .getContent()).as("Expected number of results is").hasSize(200) + assertThat(targetManagement + .findTargetByFilters(pageReq, null, null, null, null, Boolean.FALSE, targTagD.getName()).getContent()) + .as("Expected number of results is").hasSize(200) .as("and is expected number of results is equal to ") - .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(null, null, null, + .hasSize(Ints.saturatedCast(targetManagement.countTargetByFilters(null, null, null, null, Boolean.FALSE, targTagD.getName()))) .as("and contains the following elements").containsAll(expected) .as("and filter query returns the same result") @@ -654,7 +708,7 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { .as("and NAMED filter query returns the same result").containsAll(targetManagement .findTargetsAll(new JpaTargetFilterQuery("test", query), pageReq).getContent()); - assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, null, null, null, Boolean.FALSE, + assertThat(targetManagement.findAllTargetIdsByFilters(pageReq, null, null, null, null, Boolean.FALSE, targTagD.getName())).as("has number of elements").hasSize(200).as("and contains the following elements") .containsAll(expectedIdNames).as("and NAMED filter query returns the same result") .containsAll(targetManagement.findAllTargetIdsByTargetFilterQuery(pageReq, @@ -664,12 +718,13 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { @Step private void verifyThatRepositoryContains400Targets() { - assertThat(targetManagement.findTargetByFilters(pageReq, null, null, null, null, new String[0]).getContent()) - .as("Overall we expect that many targets in the repository").hasSize(400) - .as("which is also reflected by repository count") - .hasSize(Ints.saturatedCast(targetManagement.countTargetsAll())) - .as("which is also reflected by call without specification") - .containsAll(targetManagement.findTargetsAll(pageReq).getContent()); + assertThat( + targetManagement.findTargetByFilters(pageReq, null, null, null, null, null, new String[0]).getContent()) + .as("Overall we expect that many targets in the repository").hasSize(400) + .as("which is also reflected by repository count") + .hasSize(Ints.saturatedCast(targetManagement.countTargetsAll())) + .as("which is also reflected by call without specification") + .containsAll(targetManagement.findTargetsAll(pageReq).getContent()); } @@ -691,7 +746,7 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { targInstalled = sendUpdateActionStatusToTargets(ds, targInstalled, Status.FINISHED, "installed"); final Slice result = targetManagement.findTargetsAllOrderByLinkedDistributionSet(pageReq, ds.getId(), - null, null, null, Boolean.FALSE, new String[0]); + null, null, null, null, Boolean.FALSE, new String[0]); final Comparator byId = (e1, e2) -> Long.compare(e2.getId(), e1.getId()); @@ -708,6 +763,64 @@ public class TargetManagementSearchTest extends AbstractJpaIntegrationTest { } + @Test + @Description("Tests the correct order of targets with applied overdue filter based on selected distribution set. The system expects to have an order based on installed, assigned DS.") + public void targetSearchWithOverdueFilterAndOrderByDistributionSet() { + + final Long lastTargetQueryAlwaysOverdue = 0L; + final Long lastTargetQueryNotOverdue = Instant.now().toEpochMilli(); + final Long lastTargetNull = null; + + final Long[] overdueMix = { lastTargetQueryAlwaysOverdue, lastTargetQueryNotOverdue, + lastTargetQueryAlwaysOverdue, lastTargetNull, lastTargetQueryAlwaysOverdue }; + + List notAssignedToBeCreated = testdataFactory.generateTargets(overdueMix.length, "not", + "first description"); + List targAssignedToBeCreated = testdataFactory.generateTargets(overdueMix.length, "assigned", + "first description"); + List targInstalledToBeCreated = testdataFactory.generateTargets(overdueMix.length, "installed", + "first description"); + + List notAssigned = new ArrayList<>(); + List targAssigned = new ArrayList<>(); + List targInstalled = new ArrayList<>(); + + for (int i = 0; i < overdueMix.length; i++) { + notAssigned.add(targetManagement.createTarget(notAssignedToBeCreated.get(i), TargetUpdateStatus.UNKNOWN, + overdueMix[i], notAssignedToBeCreated.get(i).getTargetInfo().getAddress())); + targAssigned.add(targetManagement.createTarget(targAssignedToBeCreated.get(i), TargetUpdateStatus.UNKNOWN, + overdueMix[i], targAssignedToBeCreated.get(i).getTargetInfo().getAddress())); + targInstalled.add(targetManagement.createTarget(targInstalledToBeCreated.get(i), TargetUpdateStatus.UNKNOWN, + overdueMix[i], targInstalledToBeCreated.get(i).getTargetInfo().getAddress())); + } + + final DistributionSet ds = testdataFactory.createDistributionSet("a"); + + targAssigned = deploymentManagement.assignDistributionSet(ds, targAssigned).getAssignedEntity(); + targInstalled = deploymentManagement.assignDistributionSet(ds, targInstalled).getAssignedEntity(); + targInstalled = sendUpdateActionStatusToTargets(ds, targInstalled, Status.FINISHED, "installed"); + + final Slice result = targetManagement.findTargetsAllOrderByLinkedDistributionSet(pageReq, ds.getId(), + null, null, Boolean.TRUE, null, Boolean.FALSE, new String[0]); + + final Comparator byId = (e1, e2) -> Long.compare(e2.getId(), e1.getId()); + + assertThat(result.getNumberOfElements()).isEqualTo(9); + final List expected = new ArrayList<>(); + expected.addAll(targInstalled.stream().sorted(byId) + .filter(item -> lastTargetQueryAlwaysOverdue.equals(item.getTargetInfo().getLastTargetQuery())) + .collect(Collectors.toList())); + expected.addAll(targAssigned.stream().sorted(byId) + .filter(item -> lastTargetQueryAlwaysOverdue.equals(item.getTargetInfo().getLastTargetQuery())) + .collect(Collectors.toList())); + expected.addAll(notAssigned.stream().sorted(byId) + .filter(item -> lastTargetQueryAlwaysOverdue.equals(item.getTargetInfo().getLastTargetQuery())) + .collect(Collectors.toList())); + + assertThat(result.getContent()).containsExactly(expected.toArray(new Target[0])); + + } + @Test @Description("Verfies that targets with given assigned DS are returned from repository.") public void findTargetByAssignedDistributionSet() { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementTest.java index 06f853db6..b71266aa4 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementTest.java @@ -599,7 +599,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest { targetManagement.toggleTagAssignment(tagABCTargets, tagB); targetManagement.toggleTagAssignment(tagABCTargets, tagC); - assertThat(targetManagement.countTargetByFilters(null, null, null, Boolean.FALSE, "X")) + assertThat(targetManagement.countTargetByFilters(null, null, null, null, Boolean.FALSE, "X")) .as("Target count is wrong").isEqualTo(0); // search for targets with tag tagA @@ -629,11 +629,11 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest { checkTargetHasNotTags(tagCTargets, tagA, tagB); // check again target lists refreshed from DB - assertThat(targetManagement.countTargetByFilters(null, null, null, Boolean.FALSE, "A")) + assertThat(targetManagement.countTargetByFilters(null, null, null, null, Boolean.FALSE, "A")) .as("Target count is wrong").isEqualTo(targetWithTagA.size()); - assertThat(targetManagement.countTargetByFilters(null, null, null, Boolean.FALSE, "B")) + assertThat(targetManagement.countTargetByFilters(null, null, null, null, Boolean.FALSE, "B")) .as("Target count is wrong").isEqualTo(targetWithTagB.size()); - assertThat(targetManagement.countTargetByFilters(null, null, null, Boolean.FALSE, "C")) + assertThat(targetManagement.countTargetByFilters(null, null, null, null, Boolean.FALSE, "C")) .as("Target count is wrong").isEqualTo(targetWithTagC.size()); } @@ -750,7 +750,8 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest { final String[] tagNames = null; final List targetsListWithNoTag = targetManagement - .findTargetByFilters(new PageRequest(0, 500), null, null, null, Boolean.TRUE, tagNames).getContent(); + .findTargetByFilters(new PageRequest(0, 500), null, null, null, null, Boolean.TRUE, tagNames) + .getContent(); assertThat(50).as("Total targets").isEqualTo(targetManagement.findAllTargetIds().size()); assertThat(25).as("Targets with no tag").isEqualTo(targetsListWithNoTag.size()); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTable.java index 2a860c9b8..c3c6e9294 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTable.java @@ -370,7 +370,7 @@ public class DistributionSetTable extends AbstractNamedVersionTable 0) { + if (targetManagement.countTargetByFilters(null, null, null, ds.getId(), Boolean.FALSE, new String[] {}) > 0) { /* Distribution is already assigned */ notification.displayValidationError(i18n.get("message.dist.inuse", HawkbitCommonUtil.concatStrings(":", ds.getName(), ds.getVersion()))); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/event/ManagementUIEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/event/ManagementUIEvent.java index 4874bd960..2c6c83e8a 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/event/ManagementUIEvent.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/event/ManagementUIEvent.java @@ -14,5 +14,22 @@ package org.eclipse.hawkbit.ui.management.event; * */ public enum ManagementUIEvent { - SHOW_COUNT_MESSAGE, UPDATE_COUNT, UPDATE_FILTERCOUNT_MESSAGE, HIDE_TARGET_TAG_LAYOUT, SHOW_TARGET_TAG_LAYOUT, HIDE_DISTRIBUTION_TAG_LAYOUT, SHOW_DISTRIBUTION_TAG_LAYOUT, MAX_ACTION_HISTORY, MIN_ACTION_HISTORY, CLOSE_SAVE_ACTIONS_WINDOW, UNASSIGN_TARGET_TAG, UNASSIGN_DISTRIBUTION_TAG, ASSIGN_TARGET_TAG, ASSIGN_DISTRIBUTION_TAG, TARGET_TABLE_FILTER, RESET_SIMPLE_FILTERS, RESET_TARGET_FILTER_QUERY + SHOW_COUNT_MESSAGE, // + UPDATE_COUNT, // + UPDATE_FILTERCOUNT_MESSAGE, // + HIDE_TARGET_TAG_LAYOUT, // + SHOW_TARGET_TAG_LAYOUT, // + HIDE_DISTRIBUTION_TAG_LAYOUT, // + SHOW_DISTRIBUTION_TAG_LAYOUT, // + MAX_ACTION_HISTORY, // + MIN_ACTION_HISTORY, // + CLOSE_SAVE_ACTIONS_WINDOW, // + UNASSIGN_TARGET_TAG, // + UNASSIGN_DISTRIBUTION_TAG, // + ASSIGN_TARGET_TAG, // + ASSIGN_DISTRIBUTION_TAG, // + TARGET_TABLE_FILTER, // + RESET_SIMPLE_FILTERS, // + RESET_TARGET_FILTER_QUERY + } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/event/TargetFilterEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/event/TargetFilterEvent.java index 1c1d14d94..834f06031 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/event/TargetFilterEvent.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/event/TargetFilterEvent.java @@ -14,5 +14,14 @@ package org.eclipse.hawkbit.ui.management.event; * */ public enum TargetFilterEvent { - FILTER_BY_TEXT, FILTER_BY_TAG, REMOVE_FILTER_BY_TEXT, REMOVE_FILTER_BY_TAG, FILTER_BY_STATUS, FILTER_BY_DISTRIBUTION, REMOVE_FILTER_BY_STATUS, REMOVE_FILTER_BY_DISTRIBUTION, FILTER_BY_TARGET_FILTER_QUERY, REMOVE_FILTER_BY_TARGET_FILTER_QUERY + FILTER_BY_TEXT, // + FILTER_BY_TAG, // + REMOVE_FILTER_BY_TEXT, // + REMOVE_FILTER_BY_TAG, // + FILTER_BY_STATUS, // + FILTER_BY_DISTRIBUTION, // + REMOVE_FILTER_BY_STATUS, // + REMOVE_FILTER_BY_DISTRIBUTION, // + FILTER_BY_TARGET_FILTER_QUERY, // + REMOVE_FILTER_BY_TARGET_FILTER_QUERY } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/footer/CountMessageLabel.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/footer/CountMessageLabel.java index 70ed995a6..60aa78abc 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/footer/CountMessageLabel.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/footer/CountMessageLabel.java @@ -143,6 +143,7 @@ public class CountMessageLabel extends Label { } message.append(HawkbitCommonUtil.SP_STRING_SPACE); final String status = i18n.get("label.filter.status"); + final String overdue = i18n.get("label.filter.overdue"); final String tags = i18n.get("label.filter.tags"); final String text = i18n.get("label.filter.text"); final String dists = i18n.get("label.filter.dist"); @@ -150,6 +151,7 @@ public class CountMessageLabel extends Label { final StringBuilder filterMesgBuf = new StringBuilder(i18n.get("label.filter")); filterMesgBuf.append(HawkbitCommonUtil.SP_STRING_SPACE); filterMesgBuf.append(getStatusMsg(targFilParams.getClickedStatusTargetTags(), status)); + filterMesgBuf.append(getOverdueStateMsg(targFilParams.isOverdueFilterEnabled(), overdue)); filterMesgBuf .append(getTagsMsg(targFilParams.isNoTagSelected(), targFilParams.getClickedTargetTags(), tags)); filterMesgBuf.append(getSerachMsg( @@ -230,6 +232,17 @@ public class CountMessageLabel extends Label { return status.isEmpty() ? HawkbitCommonUtil.SP_STRING_SPACE : param; } + /** + * Get Overdue State Message. + * + * @param overdueState + * as flag + * @return String as msg. + */ + private static String getOverdueStateMsg(final boolean overdueState, final String param) { + return !overdueState ? HawkbitCommonUtil.SP_STRING_SPACE : param; + } + /** * Get Tags Message. * diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/state/TargetTableFilters.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/state/TargetTableFilters.java index 289927660..92dd627ae 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/state/TargetTableFilters.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/state/TargetTableFilters.java @@ -31,6 +31,8 @@ public class TargetTableFilters implements Serializable { private final List clickedTargetTags = new ArrayList<>(); private final List clickedStatusTargetTags = new ArrayList<>(); + private boolean isOverdueFilterEnabled = Boolean.FALSE; + private String searchText; private DistributionSetIdName distributionSet; private Long pinnedDistId; @@ -130,7 +132,8 @@ public class TargetTableFilters implements Serializable { * {@code false} */ public boolean hasFilter() { - return isFilteredByTextOrDs() || hasTagsSelected() || isFilteredByStatusOrCustomFilter(); + return isFilteredByTextOrDs() || hasTagsSelected() || isFilteredByStatusOrCustomFilter() + || isOverdueFilterEnabled(); } private boolean hasTagsSelected() { @@ -160,4 +163,12 @@ public class TargetTableFilters implements Serializable { this.targetFilterQuery = targetFilterQuery; } + public boolean isOverdueFilterEnabled() { + return isOverdueFilterEnabled; + } + + public void setOverdueFilterEnabled(boolean isOverdueFilterEnabled) { + this.isOverdueFilterEnabled = isOverdueFilterEnabled; + } + } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetBeanQuery.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetBeanQuery.java index 079544e63..6459935ab 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetBeanQuery.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetBeanQuery.java @@ -51,6 +51,7 @@ public class TargetBeanQuery extends AbstractBeanQuery { private Sort sort = new Sort(TARGET_TABLE_CREATE_AT_SORT_ORDER, "createdAt"); private transient Collection status = null; + private transient Boolean overdueState = null; private String[] targetTags = null; private Long distributionId = null; private String searchText = null; @@ -80,6 +81,7 @@ public class TargetBeanQuery extends AbstractBeanQuery { if (isNotNullOrEmpty(queryConfig)) { status = (Collection) queryConfig.get(SPUIDefinitions.FILTER_BY_STATUS); + overdueState = (Boolean) queryConfig.get(SPUIDefinitions.FILTER_BY_OVERDUE_STATE); targetTags = (String[]) queryConfig.get(SPUIDefinitions.FILTER_BY_TAG); noTagClicked = (Boolean) queryConfig.get(SPUIDefinitions.FILTER_BY_NO_TAG); distributionId = (Long) queryConfig.get(SPUIDefinitions.FILTER_BY_DISTRIBUTION); @@ -113,7 +115,7 @@ public class TargetBeanQuery extends AbstractBeanQuery { if (pinnedDistId != null) { targetBeans = getTargetManagement().findTargetsAllOrderByLinkedDistributionSet( new OffsetBasedPageRequest(startIndex, SPUIDefinitions.PAGE_SIZE, sort), pinnedDistId, - distributionId, status, searchText, noTagClicked, targetTags); + distributionId, status, overdueState, searchText, noTagClicked, targetTags); } else if (null != targetFilterQuery) { targetBeans = getTargetManagement().findTargetsAll(targetFilterQuery, new PageRequest(startIndex / SPUIDefinitions.PAGE_SIZE, SPUIDefinitions.PAGE_SIZE, sort)); @@ -123,7 +125,7 @@ public class TargetBeanQuery extends AbstractBeanQuery { } else { targetBeans = getTargetManagement().findTargetByFilters( new PageRequest(startIndex / SPUIDefinitions.PAGE_SIZE, SPUIDefinitions.PAGE_SIZE, sort), status, - searchText, distributionId, noTagClicked, targetTags); + overdueState, searchText, distributionId, noTagClicked, targetTags); } for (final Target targ : targetBeans) { final ProxyTarget prxyTarget = new ProxyTarget(); @@ -169,6 +171,13 @@ public class TargetBeanQuery extends AbstractBeanQuery { return true; } + private Boolean isOverdueFilterEnabled() { + if (Boolean.TRUE.equals(overdueState)) { + return Boolean.TRUE; + } + return Boolean.FALSE; + } + @Override protected void saveBeans(final List addedTargets, final List modifiedTargets, final List removedTargets) { @@ -176,7 +185,8 @@ public class TargetBeanQuery extends AbstractBeanQuery { } private Boolean anyFilterSelected() { - if (status == null && distributionId == null && Strings.isNullOrEmpty(searchText) && !isTagSelected()) { + if (status == null && distributionId == null && Strings.isNullOrEmpty(searchText) && !isTagSelected() + && !isOverdueFilterEnabled()) { return false; } return true; @@ -191,8 +201,8 @@ public class TargetBeanQuery extends AbstractBeanQuery { } else if (!anyFilterSelected()) { size = totSize; } else { - size = getTargetManagement().countTargetByFilters(status, searchText, distributionId, noTagClicked, - targetTags); + size = getTargetManagement().countTargetByFilters(status, overdueState, searchText, distributionId, + noTagClicked, targetTags); } final ManagementUIState tmpManagementUIState = getManagementUIState(); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTable.java index cc4ad98bc..9773f2adb 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTable.java @@ -369,6 +369,9 @@ public class TargetTable extends AbstractTable { .getClickedStatusTargetTags(); queryConfig.put(SPUIDefinitions.FILTER_BY_STATUS, statusList); } + if (managementUIState.getTargetTableFilters().isOverdueFilterEnabled()) { + queryConfig.put(SPUIDefinitions.FILTER_BY_OVERDUE_STATE, Boolean.TRUE); + } return queryConfig; } @@ -873,6 +876,7 @@ public class TargetTable extends AbstractTable { managementUIState.setTargetsCountAll(totalTargetsCount); Collection status = null; + Boolean overdueState = null; String[] targetTags = null; Long distributionId = null; String searchText = null; @@ -884,6 +888,9 @@ public class TargetTable extends AbstractTable { if (isFilteredByStatus()) { status = managementUIState.getTargetTableFilters().getClickedStatusTargetTags(); } + if (managementUIState.getTargetTableFilters().isOverdueFilterEnabled()) { + overdueState = managementUIState.getTargetTableFilters().isOverdueFilterEnabled(); + } if (managementUIState.getTargetTableFilters().getDistributionSet().isPresent()) { distributionId = managementUIState.getTargetTableFilters().getDistributionSet().get().getId(); } @@ -895,8 +902,8 @@ public class TargetTable extends AbstractTable { pinnedDistId = managementUIState.getTargetTableFilters().getPinnedDistId().get(); } - final long size = getTargetsCountWithFilter(totalTargetsCount, status, targetTags, distributionId, searchText, - noTagClicked, pinnedDistId); + final long size = getTargetsCountWithFilter(totalTargetsCount, status, overdueState, targetTags, distributionId, + searchText, noTagClicked, pinnedDistId); if (size > SPUIDefinitions.MAX_TABLE_ENTRIES) { managementUIState.setTargetsTruncated(size - SPUIDefinitions.MAX_TABLE_ENTRIES); @@ -904,8 +911,8 @@ public class TargetTable extends AbstractTable { } private long getTargetsCountWithFilter(final long totalTargetsCount, final Collection status, - final String[] targetTags, final Long distributionId, final String searchText, final Boolean noTagClicked, - final Long pinnedDistId) { + final Boolean overdueState, final String[] targetTags, final Long distributionId, final String searchText, + final Boolean noTagClicked, final Long pinnedDistId) { final long size; if (managementUIState.getTargetTableFilters().getTargetFilterQuery().isPresent()) { size = targetManagement.countTargetByTargetFilterQuery( @@ -913,7 +920,8 @@ public class TargetTable extends AbstractTable { } else if (!anyFilterSelected(status, pinnedDistId, noTagClicked, targetTags, searchText)) { size = totalTargetsCount; } else { - size = targetManagement.countTargetByFilters(status, searchText, distributionId, noTagClicked, targetTags); + size = targetManagement.countTargetByFilters(status, overdueState, searchText, distributionId, noTagClicked, + targetTags); } return size; } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettag/FilterByStatusLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettag/FilterByStatusLayout.java index d2be86aa1..b393e1ff1 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettag/FilterByStatusLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettag/FilterByStatusLayout.java @@ -54,16 +54,20 @@ public class FilterByStatusLayout extends VerticalLayout implements Button.Click @Autowired private ManagementUIState managementUIState; + private static final String overdueCaption = "overdue"; + private Button unknown; private Button inSync; private Button pending; private Button error; private Button registered; + private Button overdue; private Boolean unknownBtnClicked = false; private Boolean errorBtnClicked = false; private Boolean pendingBtnClicked = false; private Boolean inSyncBtnClicked = false; private Boolean registeredBtnClicked = false; + private Boolean overdueBtnClicked = false; private Button buttonClicked; private static final String BTN_CLICKED = "btnClicked"; @@ -105,6 +109,15 @@ public class FilterByStatusLayout extends VerticalLayout implements Button.Click addComponent(buttonLayout); setComponentAlignment(buttonLayout, Alignment.MIDDLE_CENTER); + final HorizontalLayout overdueLayout = new HorizontalLayout(); + final Label overdueLabel = new LabelBuilder().name(i18n.get("label.filter.by.overdue")).buildLabel(); + overdueLayout.setStyleName("overdue-button-layout"); + overdueLayout.addComponent(overdue); + overdueLayout.setComponentAlignment(overdue, Alignment.MIDDLE_LEFT); + overdueLayout.addComponent(overdueLabel); + overdueLayout.setComponentAlignment(overdueLabel, Alignment.MIDDLE_LEFT); + addComponent(overdueLayout); + } private void restorePreviousState() { @@ -129,6 +142,10 @@ public class FilterByStatusLayout extends VerticalLayout implements Button.Click } } } + if (managementUIState.getTargetTableFilters().isOverdueFilterEnabled()) { + overdue.addStyleName(BTN_CLICKED); + overdueBtnClicked = Boolean.TRUE; + } } /** @@ -150,18 +167,23 @@ public class FilterByStatusLayout extends VerticalLayout implements Button.Click registered = SPUIComponentProvider.getButton(UIComponentIdProvider.REGISTERED_STATUS_ICON, TargetUpdateStatus.REGISTERED.toString(), i18n.get("tooltip.status.registered"), SPUIButtonDefinitions.SP_BUTTON_STATUS_STYLE, false, FontAwesome.SQUARE, SPUIButtonStyleSmall.class); + overdue = SPUIComponentProvider.getButton(SPUIComponentIdProvider.OVERDUE_STATUS_ICON, + overdueCaption, i18n.get("tooltip.status.overdue"), + SPUIButtonDefinitions.SP_BUTTON_STATUS_STYLE, false, FontAwesome.SQUARE, SPUIButtonStyleSmall.class); applyStatusBtnStyle(); unknown.setData("filterStatusOne"); inSync.setData("filterStatusTwo"); pending.setData("filterStatusThree"); error.setData("filterStatusFour"); registered.setData("filterStatusFive"); + overdue.setData("filterStatusSix"); unknown.addClickListener(this); inSync.addClickListener(this); pending.addClickListener(this); error.addClickListener(this); registered.addClickListener(this); + overdue.addClickListener(this); } /** @@ -173,6 +195,7 @@ public class FilterByStatusLayout extends VerticalLayout implements Button.Click pending.addStyleName("pendingBtn"); error.addStyleName("errorBtn"); registered.addStyleName("registeredBtn"); + overdue.addStyleName("overdueBtn"); } @Override @@ -188,6 +211,8 @@ public class FilterByStatusLayout extends VerticalLayout implements Button.Click processErrorFilterStatus(); } else if (event.getButton().getCaption().equalsIgnoreCase(TargetUpdateStatus.REGISTERED.toString())) { processRegisteredFilterStatus(); + } else if (event.getButton().getCaption().equalsIgnoreCase(overdueCaption)) { + processOverdueFilterStatus(); } } @@ -231,9 +256,26 @@ public class FilterByStatusLayout extends VerticalLayout implements Button.Click processCommonFilterStatus(TargetUpdateStatus.REGISTERED, registeredBtnClicked); } + /** + * Process - OVERDUE. + */ + private void processOverdueFilterStatus() { + overdueBtnClicked = !overdueBtnClicked; + managementUIState.getTargetTableFilters().setOverdueFilterEnabled(overdueBtnClicked); + + if (overdueBtnClicked) { + buttonClicked.addStyleName(BTN_CLICKED); + eventBus.publish(this, TargetFilterEvent.FILTER_BY_STATUS); + } else { + buttonClicked.removeStyleName(BTN_CLICKED); + eventBus.publish(this, TargetFilterEvent.REMOVE_FILTER_BY_STATUS); + } + + } + /** * Process - COMMON PROCESS. - * + * * @param status * as enum * @param buttonReset @@ -268,11 +310,12 @@ public class FilterByStatusLayout extends VerticalLayout implements Button.Click inSync.removeStyleName(BTN_CLICKED); error.removeStyleName(BTN_CLICKED); pending.removeStyleName(BTN_CLICKED); + overdue.removeStyleName(BTN_CLICKED); } /** * Check if any status button in clicked. - * + * * @return */ private boolean isStatusFilterApplied() { diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIComponentIdProvider.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIComponentIdProvider.java new file mode 100644 index 000000000..13d7ced1a --- /dev/null +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIComponentIdProvider.java @@ -0,0 +1,846 @@ +/** + * Copyright (c) 2015 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.ui.utils; + +/** + * Interface to provide the unchanged constants. + * + * + * + * + * + */ +public final class SPUIComponentIdProvider { + /** + * ID-Target. + */ + public static final String TARGET_TABLE_ID = "target.tableId"; + /** + * ID- Targ.Cont ID. + */ + public static final String TARGET_ADD_CONTROLLER_ID = "target.add.ctrlId"; + /** + * ID-Targ.Name. + */ + public static final String TARGET_ADD_NAME = "target.add.name"; + /** + * ID-Targ.Disc. + */ + public static final String TARGET_ADD_DESC = "target.add.desc"; + /** + * ID-Targ.DEL. + */ + public static final String TARGET_DELETE_ALL = "target.delete.all"; + /** + * ID-SW.DEL. + */ + public static final String SW_DELETE_ALL = "swmodule.delete.all"; + /** + * ID-Targ.Edit.icon. + */ + public static final String TARGET_EDIT_ICON = "target.edit.icon"; + /** + * ID-Targ.PIN. + */ + public static final String TARGET_PIN_ICON = "target.pin.icon"; + + /** + * Target search text id. + */ + public static final String TARGET_TEXT_FIELD = "target.search.textfield"; + + /** + * ID for add target filter icon + */ + public static final String TARGET_FILTER_ADD_ICON_ID = "target.filter.add.id"; + + /** + * ID-Dist. + */ + public static final String DIST_TABLE_ID = "dist.tableId"; + /** + * ID-Dist.Name. + */ + public static final String DIST_ADD_NAME = "dist.add.name"; + /** + * ID-Dist.Version. + */ + public static final String DIST_ADD_VERSION = "dist.add.version"; + /** + * ID-Dist.DistSetType. + */ + public static final String DIST_ADD_DISTSETTYPE = "dist.add.distsettype"; + /** + * ID-Dist.desc. + */ + public static final String DIST_ADD_DESC = "dist.add.desc"; + /** + * /** ID-Dist.DELETE. + */ + public static final String DIST_DELETE_ALL = "dist.delete.all"; + /** + * ID-Dist.MigCheck. + */ + public static final String DIST_ADD_MIGRATION_CHECK = "dist.add.required.migration"; + /** + * ID-Dist.Search.icon. + */ + public static final String DIST_SEARCH_ICON = "dist.search.rest.icon"; + /** + * ID-Dist.Search.txt. + */ + public static final String DIST_SEARCH_TEXTFIELD = "dist.search.textfield"; + /** + * ID - Dist.Add. + */ + public static final String DIST_ADD_ICON = "dist.add.icon"; + /** + * ID for Distribution Tag ComboBox + */ + public static final String DIST_TAG_COMBO = "dist.tag.combo"; + /** + * ID-Dist.PIN. + */ + public static final String DIST_PIN_BUTTON = "dist.pin.button"; + /** + * ID - soft.module.name. + */ + public static final String SOFT_MODULE_NAME = "soft.module.name"; + /** + * ID - soft.module.version. + */ + public static final String SOFT_MODULE_VERSION = "soft.module.version"; + + /** + * ID - soft.module.vendor. + */ + public static final String SOFT_MODULE_VENDOR = "soft.module.vendor"; + + /** + * ID - Save Assign. + */ + public static final String SAVE_ASSIGNMENT = "save.actions.popup.assign"; + + /** + * ID - Discard Assign. + */ + public static final String DISCARD_ASSIGNMENT = "discard.actions.popup.assign"; + + /** + * ID - Delete Distribution SetType Save. + */ + public static final String SAVE_DELETE_DIST_SET_TYPE = "save.actions.popup.delete.dist.set.type"; + + /** + * ID - Discard Distribution SetType. + */ + public static final String DISCARD_DIST_SET_TYPE = "save.actions.popup.discard.dist.set.type"; + /** + * ID Delete Software Module Type save. + */ + public static final String SAVE_DELETE_SW_MODULE_TYPE = "save.actions.popup.delete.sw.module.type"; + + /** + * ID - Discard SW Module Type. + */ + public static final String DISCARD_SW_MODULE_TYPE = "save.actions.popup.discard.sw.module.type"; + + /** + * Action history table cancel Id. + */ + public static final String ACTION_DETAILS_SOFT_ID = "action.details.soft.group"; + + /** + * ID - Label. + */ + public static final String ACTION_LABEL = "save.actions.popup.actionMsg"; + /** + * ID - Count. + */ + public static final String COUNT_LABEL = "count.message.label"; + /** + * UNKNOWN_STATUS_ICON ID. + */ + public static final String UNKNOWN_STATUS_ICON = "unknown.status.icon"; + /** + * INSYNCH_STATUS_ICON ID. + */ + public static final String INSYNCH_STATUS_ICON = "insynch.status.icon"; + /** + * PENDING_STATUS_ICON ID. + */ + public static final String PENDING_STATUS_ICON = "pending.status.icon"; + /** + * ERROR_STATUS_ICON ID. + */ + public static final String ERROR_STATUS_ICON = "error.status.icon"; + /** + * REGISTERED_STATUS_ICON ID. + */ + public static final String REGISTERED_STATUS_ICON = "registered.status.icon"; + /** + * OVERDUE_STATUS_ICON ID. + */ + public static final String OVERDUE_STATUS_ICON = "overdue.status.icon"; + /** + * DROP filter icon id. + */ + public static final String TARGET_DROP_FILTER_ICON = "target.drop.filter.icon"; + + /** + * Pending action button id. + */ + public static final String PENDING_ACTION_BUTTON = "pending.action.button"; + /** + * Action history table Id. + */ + public static final String ACTION_HISTORY_TABLE_ID = "action.history.tableId"; + + /** + * Action history table cancel Id. + */ + public static final String ACTION_HISTORY_TABLE_CANCEL_ID = "action.history.table.action.cancel"; + + /** + * Action history table force Id. + */ + public static final String ACTION_HISTORY_TABLE_FORCE_ID = "action.history.table.action.force"; + + /** + * Action history table force quit Id. + */ + public static final String ACTION_HISTORY_TABLE_FORCE_QUIT_ID = "action.history.table.action.force.quit"; + + /** + * Target filter wrapper id. + */ + public static final String TARGET_FILTER_WRAPPER_ID = "target-drop-filter"; + + /** + * Delete button wrapper id. + */ + public static final String DELETE_BUTTON_WRAPPER_ID = "delete.button"; + /** + * tag color preview button id. + */ + public static final String TAG_COLOR_PREVIEW_ID = "tag.color.preview"; + /** + * Id for ColorPickerLayout + */ + public static final String COLOR_PICKER_LAYOUT = "color.picker.layout"; + /** + * Id for ColorPickerLayout's red slider + */ + public static final String COLOR_PICKER_RED_SLIDER = "color.picker.red.slider"; + /** + * Id for Color preview field with the color code + */ + public static final String COLOR_PREVIEW_FIELD = "color-preview-field"; + /** + * Id for OptionGroup Create/Update tag + */ + public static final String OPTION_GROUP = "create.update.tag"; + /** + * Confirmation dialogue OK button id. + */ + public static final String OK_BUTTON = "ok.button"; + /** + * Upload - type button id. + */ + public static final String UPLOAD_TYPE_BUTTON_PREFIX = "upload.type.button."; + /** + * Upload - process button id. + */ + public static final String UPLOAD_PROCESS_BUTTON = "upload.process.button"; + /** + * Upload - discard button id. + */ + public static final String UPLOAD_DISCARD_BUTTON = "upload.discard.button"; + + /** + * Upload - artifact detail close button. + */ + public static final String UPLOAD_ARTIFACT_DETAILS_CLOSE = "upload.artifactdetails.close.button"; + /** + * Upload - artifact detail table. + */ + public static final String UPLOAD_ARTIFACT_DETAILS_TABLE = "upload.artifactdetails.table"; + + /** + * Upload - artifact upload button. + */ + public static final String UPLOAD_BUTTON = "artifact.upload.button"; + /** + * Upload - process button id. + */ + public static final String UPLOAD_DISCARD_DETAILS_BUTTON = "upload.discard.details.button"; + /** + * Upload - delete button id. + */ + public static final String UPLOAD_DELETE_ICON = "upload.delete.button"; + + /** + * Upload- file delete button id. + */ + public static final String UPLOAD_FILE_DELETE_ICON = "upload.file.delete.button"; + /** + * ID-Dist. + */ + public static final String UPLOAD_SOFTWARE_MODULE_TABLE = "upload.swModule.table"; + + /** + * Upload result popup close button. + */ + public static final String UPLOAD_ARTIFACT_RESULT_POPUP_CLOSE = "upload.resultwindow.close.button"; + + /** + * Upload result popup close button. + */ + public static final String UPLOAD_ARTIFACT_RESULT_CLOSE = "upload.results.close.button"; + /** + * Upload - artifact result table. + */ + public static final String UPLOAD_RESULT_TABLE = "upload.result.table"; + /** + * Upload - software module search text id. + */ + public static final String SW_MODULE_SEARCH_TEXT_FIELD = "swmodule.search.textfield"; + /** + * Upload - software module search reset icon id. + */ + public static final String SW_MODULE_SEARCH_RESET_ICON = "sw.search.reset.icon"; + + /** + * Upload - artifact upload error reason. + */ + public static final String UPLOAD_ERROR_REASON = "upload-error-reason"; + + /** + * Upload - artifact upload - Software module add button. + */ + public static final String SW_MODULE_ADD_BUTTON = "sw.module.add.button"; + + /** + * Upload - artifact upload - Software module type combo id. + */ + public static final String SW_MODULE_TYPE = "sw.module.select.type"; + + /** + * Upload - artifact upload - Software module description. + */ + public static final String ADD_SW_MODULE_DESCRIPTION = "sw.module.description"; + + /** + * ID-Targ.Detail.icon. + */ + public static final String SW_TABLE_ATRTIFACT_DETAILS_ICON = "swmodule.artifact.details.icon"; + + /** + * Artifact upload - sw module edit button id. + */ + public static final String UPLOAD_SW_MODULE_EDIT_BUTTON = "swmodule.edit.button"; + + /** + * Ds edit button id. + */ + public static final String DS_EDIT_BUTTON = "ds.edit.button"; + /** + * Upload Artifact details max table Id. + */ + public static final String UPLOAD_ARTIFACT_DETAILS_TABLE_MAX = "upload.artifactdetails.table.max"; + + /** + * Target tag close button. + */ + public static final String HIDE_TARGET_TAGS = "hide.target.tags"; + + /** + * Show target tag layout icon. + */ + public static final String SHOW_TARGET_TAGS = "show.target.tags.icon"; + + /** + * ID-Target tag table. + */ + public static final String TARGET_TAG_TABLE_ID = "target.tag.tableId"; + /** + * ID-Distibution tag table. + */ + public static final String DISTRIBUTION_TAG_TABLE_ID = "distriution.tag.tableId"; + /** + * ID-Software module type table. + */ + public static final String SW_MODULE_TYPE_TABLE_ID = "sw.module.type.table"; + + /** + * ID-Target tag table. + */ + public static final String DISTRIBUTION_SET_TYPE_TABLE_ID = "dist.set.type.tableId"; + + /** + * Tab sheet id. + */ + public static final String TARGET_DETAILS_TABSHEET = "target.details.tabsheet"; + /** + * Tab sheet id. + */ + public static final String DISTRIBUTION_DETAILS_TABSHEET = "distribution.details.tabsheet."; + + /** + * Combobox id. + */ + public static final String SYSTEM_CONFIGURATION_DEFAULTDIS_COMBOBOX = "default.disset.combobox"; + + /** + * Button save id. + */ + public static final String SYSTEM_CONFIGURATION_SAVE = "system.configuration.save"; + + /** + * ID for save button in pop-up-windows instance of commonDialogWindow + */ + public static final String SAVE_BUTTON = "common.dialog.window.save"; + + /** + * ID for cancel button in pop-up-windows instance of commonDialogWindow + */ + public static final String CANCEL_BUTTON = "common.dialog.window.cancel"; + + /** + * Cancel button is. + */ + public static final String SYSTEM_CONFIGURATION_CANCEL = "system.configuration.cancel"; + + /** + * Id of maximize/minimize icon of table - Software module table. + */ + public static final String SW_MAX_MIN_TABLE_ICON = "sw.max.min.table.icon"; + + /** + * Id of maximize/minimize icon of table - Distribution table. + */ + public static final String DS_MAX_MIN_TABLE_ICON = "ds.max.min.table.icon"; + + /** + * Software module table in upload UI. + */ + public static final String SM_TYPE_FILTER_BTN_ID = "sm.type.filter.btn."; + + /** + * Software module table details header caption id. + */ + public static final String TARGET_DETAILS_HEADER_LABEL_ID = "target.details.header.caption"; + + /** + * Software module table details header caption id. + */ + public static final String DISTRIBUTION_DETAILS_HEADER_LABEL_ID = "distribution.details.header.caption"; + + /** + * Software module table details vendor label id. + */ + public static final String DETAILS_VENDOR_LABEL_ID = "details.vendor"; + + /** + * Software module table details description label id. + */ + public static final String DETAILS_DESCRIPTION_LABEL_ID = "details.description"; + + /** + * Software module table details type label id. + */ + public static final String DETAILS_TYPE_LABEL_ID = "details.type"; + + /** + * Id of show filter button in software module table. + */ + public static final String SM_SHOW_FILTER_BUTTON_ID = "show.filter.layout"; + + /** + * Software module table in upload UI. + */ + public static final String DS_TYPE_FILTER_BTN_ID = "ds.type.filter.btn."; + + /** + * Id of target table search reset Icon. + */ + public static final String TARGET_TBL_SEARCH_RESET_ID = "target.search.rest.icon"; + + /** + * Id of the target table add Icon. + */ + public static final String TARGET_TBL_ADD_ICON_ID = "target.add"; + + /** + * Id of IP address label in target details. + */ + public static final String TARGET_IP_ADDRESS = "target.ip.address"; + + /** + * Id of Last query date label in target details. + */ + public static final String TARGET_LAST_QUERY_DT = "target.last.query.date"; + + /** + * Id of Controller Id label in target details. + */ + public static final String TARGET_CONTROLLER_ID = "target.controller.id"; + + /** + * Id of security token label in target details. + */ + public static final String TARGET_SECURITY_TOKEN = "target.security.token"; + + /** + * Id of maximize/minimize icon of table - Software module table. + */ + public static final String TARGET_MAX_MIN_TABLE_ICON = "target.max.min.table.icon"; + + /** + * Software module table in upload UI. + */ + public static final String SWM_DTLS_MAX_ASSIGN = "max.assign"; + + /** + * Documentation Link in Login view and menu. + */ + public static final String LINK_DOCUMENTATION = "link.documentation"; + + /** + * Demo Link in Login view and menu. + */ + public static final String LINK_DEMO = "link.demo"; + + /** + * Request account Link in Login view and menu. + */ + public static final String LINK_REQUESTACCOUNT = "link.requestaccount"; + + /** + * Support Link in Login view and menu. + */ + public static final String LINK_SUPPORT = "link.support"; + + /** + * User management Link in Login view and menu. + */ + public static final String LINK_USERMANAGEMENT = "link.usermanagement"; + + /** + * New Target tag add icon id. + */ + public static final String ADD_TARGET_TAG = "target.tag.add"; + + /** + * New distribution set tag add icon id. + */ + public static final String ADD_DISTRIBUTION_TAG = "distribution.tag.add"; + /** + * Bulk target upload - distribution set combo. + */ + public static final String BULK_UPLOAD_DS_COMBO = "bulkupload.ds.combo"; + + /** + * Bulk target upload - description. + */ + public static final String BULK_UPLOAD_DESC = "bulkupload.description"; + /** + * Bulk target upload - tag field. + */ + public static final String BULK_UPLOAD_TAG = "bulkupload.tag"; + /** + * Bulk target upload - count label. + */ + public static final String BULK_UPLOAD_COUNT = "bulkupload.upload.count"; + + /** + * Id of the target table bulk upload Icon. + */ + public static final String TARGET_TBL_BULK_UPLOAD_ICON_ID = "target.bulk.upload"; + + /** + * Id of target filter table search reset Icon. + */ + public static final String TARGET_FILTER_TBL_SEARCH_RESET_ID = "target.filter.search.rest.icon"; + + /** + * ID- Customfilter.Name. + */ + public static final String CUSTOM_FILTER_ADD_NAME = "custom.filter.add.name"; + + /** + * custom filter - delete button id. + */ + public static final String CUSTOM_FILTER_DELETE_ICON = "custom.filter.delete.button"; + + /** + * custom filter - update button id. + */ + public static final String CUSTOM_FILTER_DETAIL_LINK = "custom.filter.detail.link"; + + /** + * custom filter - save button id. + */ + public static final String CUSTOM_FILTER_SAVE_ICON = "custom.filter.save.button.Id"; + + /** + * ID-Custom target tag table. + */ + public static final String CUSTOM_TARGET_TAG_TABLE_ID = "custom.target.tag.tableId"; + + /** + * Target filter table id. + */ + public static final String TAEGET_FILTER_TABLE_ID = "target.query.filter.table.Id"; + + /** + * create or update target filter query - name label id. + */ + public static final String TARGET_FILTER_QUERY_NAME_LABEL_ID = "target.filter.name.label.id"; + + /** + * create or update target filter query - name layout id. + */ + public static final String TARGET_FILTER_QUERY_NAME_LAYOUT_ID = "target.filter.name.layout.id"; + /** + * * create or update target filter query - target table id. + */ + public static final String CUSTOM_FILTER_TARGET_TABLE_ID = "custom.filter.target.table.id"; + + /** + * Bulk upload notification button id. + */ + public static final String BULK_UPLOAD_STATUS_BUTTON = "bulk.upload.notification.id"; + + /** + * Target bulk upload minimize button id. + */ + public static final String BULK_UPLOAD_MINIMIZE_BUTTON_ID = "bulk.upload.minimize.button.id"; + + /** + * Target bulk upload minimize button id. + */ + + public static final String BULK_UPLOAD_CLOSE_BUTTON_ID = "bulk.upload.close.button.id"; + + /** + * Rollout list view - search box id. + */ + public static final String ROLLOUT_LIST_SEARCH_BOX_ID = "rollout.list.search.id"; + + /** + * Rollout list view - search reset icon id. + */ + public static final String ROLLOUT_LIST_SEARCH_RESET_ICON_ID = "rollout.list.search.reset.icon.id"; + + /** + * Rollout list view - add icon id. + */ + public static final String ROLLOUT_ADD_ICON_ID = "rollout.add.button.id"; + + /** + * Rollout list grid id. + */ + public static final String ROLLOUT_LIST_GRID_ID = "rollout.grid.id"; + + /** + * Rollout group list grid id. + */ + public static final String ROLLOUT_GROUP_LIST_GRID_ID = "rollout.group.grid.id"; + + /** + * Rollout group list grid id. + */ + public static final String ROLLOUT_GROUP_TARGETS_LIST_GRID_ID = "rollout.group.targets.grid.id"; + + /** + * Rollout text field name id. + */ + public static final String ROLLOUT_NAME_FIELD_ID = "rollout.name.field.id"; + /** + * Rollout number of groups id. + */ + public static final String ROLLOUT_NO_OF_GROUPS_ID = "rollout.no.ofgroups.id"; + + /** + * Rollout trigger threshold field if. + */ + public static final String ROLLOUT_TRIGGER_THRESOLD_ID = "rollout.trigger.thresold.id"; + + /** + * Rollout error thresold field id. + */ + public static final String ROLLOUT_ERROR_THRESOLD_ID = "rollout.error.thresold.id"; + + /** + * Rollout distribution set combo id. + */ + public static final String ROLLOUT_DS_ID = "rollout.ds.id"; + /** + * Rollout description field id. + */ + public static final String ROLLOUT_DESCRIPTION_ID = "rollout.description.id"; + /** + * Rollout target filter query combo id. + */ + public static final String ROLLOUT_TARGET_FILTER_COMBO_ID = "rollout.target.filter.combo.id"; + + /** + * Rollout action button id. + */ + public static final String ROLLOUT_ACTION_ID = "rollout.action.button.id"; + + /** + * Rollout start button id. + */ + public static final String ROLLOUT_RUN_BUTTON_ID = ROLLOUT_ACTION_ID + ".9"; + + /** + * Rollout pause button id. + */ + public static final String ROLLOUT_PAUSE_BUTTON_ID = ROLLOUT_ACTION_ID + ".10"; + + /** + * Rollout resume button id. + */ + public static final String ROLLOUT_UPDATE_BUTTON_ID = ROLLOUT_ACTION_ID + ".11"; + + /** + * Rollout status label id. + */ + public static final String ROLLOUT_STATUS_LABEL_ID = "rollout.status.id"; + + /** + * Rollout group status label id. + */ + public static final String ROLLOUT_GROUP_STATUS_LABEL_ID = "rollout.group.status.id"; + + /** + * Rollout % or count option group id. + */ + public static final String ROLLOUT_ERROR_THRESOLD_OPTION_ID = "rollout.error.thresold.option.id"; + + /** + * Rollout target filter query value text area id. + */ + public static final String ROLLOUT_TARGET_FILTER_QUERY_FIELD = "rollout.target.filter.query.field.id"; + + /** + * Rollout target view- close button id. + */ + public static final String ROLLOUT_TARGET_VIEW_CLOSE_BUTTON_ID = "rollout.group.target.close.id"; + /** + * Rollout group header caption. + */ + public static final String ROLLOUT_GROUP_HEADER_CAPTION = "rollout.group.header.caption"; + /** + * Rollout group close id. + */ + public static final String ROLLOUT_GROUP_CLOSE = "rollout.group.close.id"; + /** + * Rollout group targets count message label. + */ + public static final String ROLLOUT_GROUP_TARGET_LABEL = "rollout.group.target.label"; + + /** + * Action confirmation popup id. + */ + public static final String CONFIRMATION_POPUP_ID = "action.confirmation.popup.id"; + + /** + * Validation status icon . + */ + public static final String VALIDATION_STATUS_ICON_ID = "validation.status.icon"; + + /** + * Artifact upload status popup - minimize button id. + */ + public static final String UPLOAD_STATUS_POPUP_MINIMIZE_BUTTON_ID = "artifact.upload.minimize.button.id"; + + /** + * Artifact upload status popup - close button id. + */ + public static final String UPLOAD_STATUS_POPUP_CLOSE_BUTTON_ID = "artifact.upload.close.button.id"; + + /** + * Artifact upload status popup - resize button id. + */ + public static final String UPLOAD_STATUS_POPUP_RESIZE_BUTTON_ID = "artifact.upload.resize.button.id"; + + /** + * Artifact upload view - upload status button id. + */ + public static final String UPLOAD_STATUS_BUTTON = "artficat.upload.status.button.id"; + + /** + * Artifact uplaod view - uplod status popup id. + */ + public static final String UPLOAD_STATUS_POPUP_ID = "artifact.upload.status.popup.id"; + + /** + * Software module table - Manage metadata id. + */ + public static final String SW_TABLE_MANAGE_METADATA_ID = "swtable.manage.metadata.id"; + + /** + * Metadata key id. + */ + public static final String METADATA_KEY_FIELD_ID = "metadata.key.id"; + + /** + * Metadata value id. + */ + public static final String METADATA_VALUE_ID = "metadata.value.id"; + + /** + * Metadata add icon id. + */ + public static final String METADTA_ADD_ICON_ID = "metadata.add.icon.id"; + /** + * Metadata table id. + */ + public static final String METDATA_TABLE_ID = "metadata.table.id"; + + /** + * Distribution set table - Manage metadata id. + */ + public static final String DS_TABLE_MANAGE_METADATA_ID = "dstable.manage.metadata.id"; + + /** + * DistributionSet - Metadata button id. + */ + public static final String DS_METADATA_DETAIL_LINK = "distributionset.metadata.detail.link"; + + /** + * Metadata popup id. + */ + public static final String METADATA_POPUP_ID = "metadata.popup.id"; + + /** + * DistributionSet table details tab id in Distributions . + */ + public static final String DISTRIBUTIONSET_DETAILS_TABSHEET_ID = "distributionset.details.tabsheet"; + + /** + * Software module table details tab id in Distributions . + */ + public static final String DIST_SW_MODULE_DETAILS_TABSHEET_ID = "dist.sw.module.details.tabsheet"; + + /** + * Software Module - Metadata button id. + */ + public static final String SW_METADATA_DETAIL_LINK = "softwaremodule.metadata.detail.link"; + + /** + * /* Private Constructor. + */ + private SPUIComponentIdProvider() { + + } +} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIDefinitions.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIDefinitions.java index aae1da513..3a85bc791 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIDefinitions.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIDefinitions.java @@ -205,6 +205,12 @@ public final class SPUIDefinitions { * Filter by status key. */ public static final String FILTER_BY_STATUS = "FilterByStatus"; + + /** + * Filter by overdue state key. + */ + public static final String FILTER_BY_OVERDUE_STATE = "FilterByOverdueState"; + /** * Filter by tag key. */ @@ -407,7 +413,7 @@ public final class SPUIDefinitions { /** * Filter by type layout width. */ - public static final float FILTER_BY_TYPE_WIDTH = 150.0F; + public static final float FILTER_BY_TYPE_WIDTH = 190.0F; /** * Confirmation jukebox type. diff --git a/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/filter-status.scss b/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/filter-status.scss index c3cdb6eba..d1ae21f62 100644 --- a/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/filter-status.scss +++ b/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/filter-status.scss @@ -13,8 +13,9 @@ $unknown-color: $status-unknown-color; $in-sync-color: $signal-green-color; $pending-color: $signal-yellow-color; - $error-color: $signal-red-color; - $registered-color: $bosch-color-light-blue; + $error-color: $signal-red-color; + $overdue-color: $signal-black-color; + $registered-color: $signal-light-blue-color; //Filter by status buttons group alignment .target-status-filters { @@ -27,6 +28,10 @@ .status-button-layout { height: 40px !important; } + + .overdue-button-layout { + height: 40px !important; + } //Filter Button applied with below styles based on the color .unknownBtn { @@ -68,6 +73,16 @@ .errorBtn:active:after { border-color: $error-color; } + + .overdueBtn { + background: $overdue-color; + border: solid 3px $overdue-color; + } + + .overdueBtn:focus:after, + .overdueBtn:active:after { + border-color: $overdue-color; + } .registeredBtn { background: $registered-color; diff --git a/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/hawkbitvariables.scss b/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/hawkbitvariables.scss index 81e0617b3..a3a6dc381 100644 --- a/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/hawkbitvariables.scss +++ b/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/hawkbitvariables.scss @@ -101,10 +101,12 @@ $details-tab-caption-font-scale: .8; //Generic text style $generic-text-font-scale: .85; -$status-unknown-color: #3085cb; +$status-unknown-color: #d5d5d5; $signal-green-color: #6eb553; $signal-yellow-color: #ff0; +$signal-light-blue-color: #3085cb; $signal-red-color: #f00; +$signal-black-color: #000; $signal-orange-color: #ffa500; $grey-light: #d5d5d5; diff --git a/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/others.scss b/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/others.scss index 69dacfa57..3f70e139e 100644 --- a/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/others.scss +++ b/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/others.scss @@ -178,7 +178,7 @@ } .statusIconLightBlue { - color: $bosch-color-light-blue; + color: $signal-light-blue-color; } .v-button-statusIconLightBlue:after { @@ -219,7 +219,7 @@ pointer-events: auto !important; } .blueSpinner{ - @include valo-spinner($size: $v-font-size--small,$color: $bosch-color-light-blue); + @include valo-spinner($size: $v-font-size--small,$color: $signal-light-blue-color); pointer-events: auto !important; } diff --git a/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/target-filter-query.scss b/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/target-filter-query.scss index 33ae2dd85..f4f91f2f6 100644 --- a/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/target-filter-query.scss +++ b/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/target-filter-query.scss @@ -44,7 +44,7 @@ .target-filter-spinner{ @include valo-spinner( $size: $v-font-size--small, - $color: $bosch-color-light-blue + $color: $signal-light-blue-color ); } diff --git a/hawkbit-ui/src/main/resources/messages.properties b/hawkbit-ui/src/main/resources/messages.properties index 6a68eeff8..c067d27f5 100644 --- a/hawkbit-ui/src/main/resources/messages.properties +++ b/hawkbit-ui/src/main/resources/messages.properties @@ -128,8 +128,6 @@ label.combobox.type = Select Type label.combobox.tag = Select Tag label.choose.tag = Choose Tag to update label.choose.tag.color = Choose Tag Color -label.filter = Filter: -label.target.filter.count = Total Targets: label.target.filtered.total = Total filtered targets : label.filter.selected = Selected: label.filter.shown = Shown: @@ -139,6 +137,7 @@ label.filter.selected = Selected : label.filter.shown = Shown : label.filter.targets = Filtered targets : label.filter.status = Status, +label.filter.overdue = Overdue, label.filter.tags = Tags, label.filter.text = Search Text label.filter.dist = Distribution, @@ -159,6 +158,7 @@ label.target.id = Controller Id : label.target.ip = Controller IP : label.target.security.token = Security token : label.filter.by.status = Filter by Status +label.filter.by.overdue = Filter by Overdue State label.target.controller.attrs = Controller attributes label.target.lastpolldate = Last poll : label.no.tag.assigned = NO TAG @@ -192,6 +192,7 @@ tooltip.status.registered = Registered tooltip.status.pending = Pending tooltip.status.error = Error tooltip.status.insync = In-sync +tooltip.status.overdue = Overdue tooltip.delete.module = Select and delete Software Module tooltip.forced.item=Forced update action tooltip.soft.item=Soft update action which interacts with an user as a attempt update action for example diff --git a/hawkbit-ui/src/main/resources/messages_de.properties b/hawkbit-ui/src/main/resources/messages_de.properties index e46be6b6e..fca470698 100644 --- a/hawkbit-ui/src/main/resources/messages_de.properties +++ b/hawkbit-ui/src/main/resources/messages_de.properties @@ -128,8 +128,6 @@ label.combobox.type = Select Type label.combobox.tag = Select Tag label.choose.tag = Choose Tag to update label.choose.tag.color = Choose Tag Color -label.filter = Filter: -label.target.filter.count = Total Targets: label.target.filtered.total = Total filtered targets : label.filter.selected = Selected: label.filter.shown = Shown: @@ -138,6 +136,7 @@ label.target.filter.count = Total Targets : label.filter.selected = Selected : label.filter.shown = Shown : label.filter.status = Status, +label.filter.overdue = Overdue, label.filter.tags = Tags, label.filter.text = Search Text label.filter.dist = Distribution, @@ -158,6 +157,7 @@ label.target.id = Controller Id : label.target.ip = Controller IP : label.target.security.token = Security token : label.filter.by.status = Filter by Status +label.filter.by.overdue = Filter by Overdue State label.target.controller.attrs = Controller attributes label.target.lastpolldate = Last poll : label.no.tag.assigned = NO TAG @@ -191,6 +191,7 @@ tooltip.status.registered = Registered tooltip.status.pending = Pending tooltip.status.error = Error tooltip.status.insync = In-sync +tooltip.status.overdue = Overdue tooltip.delete.module = Select and delete Software Module tooltip.forced.item=Forced update action tooltip.soft.item=Soft update action which interacts with an user as a attempt update action for example diff --git a/hawkbit-ui/src/main/resources/messages_en.properties b/hawkbit-ui/src/main/resources/messages_en.properties index 4328b83f8..dceb658df 100644 --- a/hawkbit-ui/src/main/resources/messages_en.properties +++ b/hawkbit-ui/src/main/resources/messages_en.properties @@ -127,8 +127,6 @@ label.combobox.type = Select Type label.combobox.tag = Select Tag label.choose.tag = Choose Tag to update label.choose.tag.color = Choose Tag Color -label.filter = Filter: -label.target.filter.count = Total Targets: label.target.filtered.total = Total filtered targets : label.filter.selected = Selected: label.filter.shown = Shown: @@ -138,6 +136,7 @@ label.target.filter.count = Total Targets : label.filter.selected = Selected : label.filter.shown = Shown : label.filter.status = Status, +label.filter.overdue = Overdue, label.filter.tags = Tags, label.filter.text = Search Text label.filter.dist = Distribution, @@ -158,6 +157,7 @@ label.target.id = Controller Id : label.target.ip = Controller IP : label.target.security.token = Security token : label.filter.by.status = Filter by Status +label.filter.by.overdue = Filter by Overdue State label.target.controller.attrs = Controller attributes label.target.lastpolldate = Last poll : label.no.tag.assigned = NO TAG @@ -191,6 +191,7 @@ tooltip.status.registered = Registered tooltip.status.pending = Pending tooltip.status.error = Error tooltip.status.insync = In-sync +tooltip.status.overdue = Overdue tooltip.delete.module = Select and delete Software Module tooltip.forced.item=Forced update action tooltip.soft.item=Soft update action which interacts with an user as a attempt update action for example