Migration of Action History to vaadin grid (#420)
* Migration of Action History to vaadin Grid Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
This commit is contained in:
committed by
Kai Zimmermann
parent
081c3cccbf
commit
c8db41ff85
@@ -96,7 +96,7 @@ public final class MgmtRestConstants {
|
|||||||
/**
|
/**
|
||||||
* The tag URL mapping rest resource.
|
* The tag URL mapping rest resource.
|
||||||
*/
|
*/
|
||||||
public static final String TARGET_TAG_TAGERTS_REQUEST_MAPPING = "/{targetTagId}/targets";
|
public static final String TARGET_TAG_TARGETS_REQUEST_MAPPING = "/{targetTagId}/targets";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The tag URL mapping rest resource.
|
* The tag URL mapping rest resource.
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ public interface MgmtTargetTagRestApi {
|
|||||||
*
|
*
|
||||||
* @return the list of assigned targets.
|
* @return the list of assigned targets.
|
||||||
*/
|
*/
|
||||||
@RequestMapping(method = RequestMethod.GET, value = MgmtRestConstants.TARGET_TAG_TAGERTS_REQUEST_MAPPING, produces = {
|
@RequestMapping(method = RequestMethod.GET, value = MgmtRestConstants.TARGET_TAG_TARGETS_REQUEST_MAPPING, produces = {
|
||||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||||
ResponseEntity<List<MgmtTarget>> getAssignedTargets(@PathVariable("targetTagId") final Long targetTagId);
|
ResponseEntity<List<MgmtTarget>> getAssignedTargets(@PathVariable("targetTagId") final Long targetTagId);
|
||||||
|
|
||||||
@@ -136,7 +136,7 @@ public interface MgmtTargetTagRestApi {
|
|||||||
*
|
*
|
||||||
* @return the list of assigned targets and unassigned targets.
|
* @return the list of assigned targets and unassigned targets.
|
||||||
*/
|
*/
|
||||||
@RequestMapping(method = RequestMethod.POST, value = MgmtRestConstants.TARGET_TAG_TAGERTS_REQUEST_MAPPING
|
@RequestMapping(method = RequestMethod.POST, value = MgmtRestConstants.TARGET_TAG_TARGETS_REQUEST_MAPPING
|
||||||
+ "/toggleTagAssignment", consumes = { MediaTypes.HAL_JSON_VALUE,
|
+ "/toggleTagAssignment", consumes = { MediaTypes.HAL_JSON_VALUE,
|
||||||
MediaType.APPLICATION_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE,
|
MediaType.APPLICATION_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE,
|
||||||
MediaType.APPLICATION_JSON_VALUE })
|
MediaType.APPLICATION_JSON_VALUE })
|
||||||
@@ -154,7 +154,7 @@ public interface MgmtTargetTagRestApi {
|
|||||||
*
|
*
|
||||||
* @return the list of assigned targets.
|
* @return the list of assigned targets.
|
||||||
*/
|
*/
|
||||||
@RequestMapping(method = RequestMethod.POST, value = MgmtRestConstants.TARGET_TAG_TAGERTS_REQUEST_MAPPING, consumes = {
|
@RequestMapping(method = RequestMethod.POST, value = MgmtRestConstants.TARGET_TAG_TARGETS_REQUEST_MAPPING, consumes = {
|
||||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE,
|
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE,
|
||||||
MediaType.APPLICATION_JSON_VALUE })
|
MediaType.APPLICATION_JSON_VALUE })
|
||||||
ResponseEntity<List<MgmtTarget>> assignTargets(@PathVariable("targetTagId") final Long targetTagId,
|
ResponseEntity<List<MgmtTarget>> assignTargets(@PathVariable("targetTagId") final Long targetTagId,
|
||||||
@@ -167,7 +167,7 @@ public interface MgmtTargetTagRestApi {
|
|||||||
* the ID of the target tag to retrieve
|
* the ID of the target tag to retrieve
|
||||||
* @return http status code
|
* @return http status code
|
||||||
*/
|
*/
|
||||||
@RequestMapping(method = RequestMethod.DELETE, value = MgmtRestConstants.TARGET_TAG_TAGERTS_REQUEST_MAPPING)
|
@RequestMapping(method = RequestMethod.DELETE, value = MgmtRestConstants.TARGET_TAG_TARGETS_REQUEST_MAPPING)
|
||||||
ResponseEntity<Void> unassignTargets(@PathVariable("targetTagId") final Long targetTagId);
|
ResponseEntity<Void> unassignTargets(@PathVariable("targetTagId") final Long targetTagId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -179,7 +179,7 @@ public interface MgmtTargetTagRestApi {
|
|||||||
* the ID of the target to unassign
|
* the ID of the target to unassign
|
||||||
* @return http status code
|
* @return http status code
|
||||||
*/
|
*/
|
||||||
@RequestMapping(method = RequestMethod.DELETE, value = MgmtRestConstants.TARGET_TAG_TAGERTS_REQUEST_MAPPING
|
@RequestMapping(method = RequestMethod.DELETE, value = MgmtRestConstants.TARGET_TAG_TARGETS_REQUEST_MAPPING
|
||||||
+ "/{controllerId}")
|
+ "/{controllerId}")
|
||||||
ResponseEntity<Void> unassignTarget(@PathVariable("targetTagId") final Long targetTagId,
|
ResponseEntity<Void> unassignTarget(@PathVariable("targetTagId") final Long targetTagId,
|
||||||
@PathVariable("controllerId") final String controllerId);
|
@PathVariable("controllerId") final String controllerId);
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ public interface DeploymentManagement {
|
|||||||
* @throws IncompleteDistributionSetException
|
* @throws IncompleteDistributionSetException
|
||||||
* if mandatory {@link SoftwareModuleType} are not assigned as
|
* if mandatory {@link SoftwareModuleType} are not assigned as
|
||||||
* define by the {@link DistributionSetType}.
|
* define by the {@link DistributionSetType}.
|
||||||
*
|
*
|
||||||
* @throws EntityNotFoundException
|
* @throws EntityNotFoundException
|
||||||
* if either provided {@link DistributionSet} or {@link Target}s
|
* if either provided {@link DistributionSet} or {@link Target}s
|
||||||
* do not exist
|
* do not exist
|
||||||
@@ -84,7 +84,7 @@ public interface DeploymentManagement {
|
|||||||
* @throws IncompleteDistributionSetException
|
* @throws IncompleteDistributionSetException
|
||||||
* if mandatory {@link SoftwareModuleType} are not assigned as
|
* if mandatory {@link SoftwareModuleType} are not assigned as
|
||||||
* define by the {@link DistributionSetType}.
|
* define by the {@link DistributionSetType}.
|
||||||
*
|
*
|
||||||
* @throws EntityNotFoundException
|
* @throws EntityNotFoundException
|
||||||
* if either provided {@link DistributionSet} or {@link Target}s
|
* if either provided {@link DistributionSet} or {@link Target}s
|
||||||
* do not exist
|
* do not exist
|
||||||
@@ -108,7 +108,7 @@ public interface DeploymentManagement {
|
|||||||
* @throws IncompleteDistributionSetException
|
* @throws IncompleteDistributionSetException
|
||||||
* if mandatory {@link SoftwareModuleType} are not assigned as
|
* if mandatory {@link SoftwareModuleType} are not assigned as
|
||||||
* define by the {@link DistributionSetType}.
|
* define by the {@link DistributionSetType}.
|
||||||
*
|
*
|
||||||
* @throws EntityNotFoundException
|
* @throws EntityNotFoundException
|
||||||
* if either provided {@link DistributionSet} or {@link Target}s
|
* if either provided {@link DistributionSet} or {@link Target}s
|
||||||
* do not exist
|
* do not exist
|
||||||
@@ -145,7 +145,7 @@ public interface DeploymentManagement {
|
|||||||
* @param controllerId
|
* @param controllerId
|
||||||
* the target associated to the actions to count
|
* the target associated to the actions to count
|
||||||
* @return the count value of found actions associated to the target
|
* @return the count value of found actions associated to the target
|
||||||
*
|
*
|
||||||
* @throws RSQLParameterUnsupportedFieldException
|
* @throws RSQLParameterUnsupportedFieldException
|
||||||
* if a field in the RSQL string is used but not provided by the
|
* if a field in the RSQL string is used but not provided by the
|
||||||
* given {@code fieldNameProvider}
|
* given {@code fieldNameProvider}
|
||||||
@@ -290,6 +290,19 @@ public interface DeploymentManagement {
|
|||||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
||||||
Page<ActionStatus> findActionStatusByActionWithMessages(@NotNull Pageable pageable, @NotNull Long actionId);
|
Page<ActionStatus> findActionStatusByActionWithMessages(@NotNull Pageable pageable, @NotNull Long actionId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all messages for an {@link ActionStatus}.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param pageable
|
||||||
|
* the page request parameter for paging and sorting the result
|
||||||
|
* @param actionStatusId
|
||||||
|
* the id of {@link ActionStatus} to retrieve the messages from
|
||||||
|
* @return a page of messages by a specific {@link ActionStatus} id
|
||||||
|
*/
|
||||||
|
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
||||||
|
Page<String> findMessagesByActionStatusId(@NotNull Pageable pageable, @NotNull Long actionStatusId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves all {@link Action}s of a specific target ordered by action ID.
|
* Retrieves all {@link Action}s of a specific target ordered by action ID.
|
||||||
*
|
*
|
||||||
@@ -297,7 +310,7 @@ public interface DeploymentManagement {
|
|||||||
* the target associated with the actions
|
* the target associated with the actions
|
||||||
* @return a list of actions associated with the given target ordered by
|
* @return a list of actions associated with the given target ordered by
|
||||||
* action ID
|
* action ID
|
||||||
*
|
*
|
||||||
* @throws EntityNotFoundException
|
* @throws EntityNotFoundException
|
||||||
* if target with given ID does not exist
|
* if target with given ID does not exist
|
||||||
*/
|
*/
|
||||||
@@ -392,7 +405,7 @@ public interface DeploymentManagement {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* All {@link ActionStatus} entries in the repository.
|
* All {@link ActionStatus} entries in the repository.
|
||||||
*
|
*
|
||||||
* @param pageable
|
* @param pageable
|
||||||
* the pagination parameter
|
* the pagination parameter
|
||||||
* @return {@link Page} of {@link ActionStatus} entries
|
* @return {@link Page} of {@link ActionStatus} entries
|
||||||
|
|||||||
@@ -78,6 +78,17 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
|||||||
*/
|
*/
|
||||||
Slice<Action> findByTargetControllerId(Pageable pageable, String controllerId);
|
Slice<Action> findByTargetControllerId(Pageable pageable, String controllerId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all {@link Action}s which are referring the given targetId
|
||||||
|
*
|
||||||
|
* @param pageable
|
||||||
|
* page parameters
|
||||||
|
* @param targetId
|
||||||
|
* the target to find assigned actions for
|
||||||
|
* @return the found {@link Action}s
|
||||||
|
*/
|
||||||
|
Page<Action> findByTargetId(Pageable pageable, Long targetId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves all {@link Action}s which are active and referring to the given
|
* Retrieves all {@link Action}s which are active and referring to the given
|
||||||
* {@link Target} order by ID ascending.
|
* {@link Target} order by ID ascending.
|
||||||
@@ -93,14 +104,14 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
|||||||
/**
|
/**
|
||||||
* Retrieves the oldest {@link Action} that is active and referring to the
|
* Retrieves the oldest {@link Action} that is active and referring to the
|
||||||
* given {@link Target}.
|
* given {@link Target}.
|
||||||
*
|
*
|
||||||
* @param sort
|
* @param sort
|
||||||
* order
|
* order
|
||||||
* @param controllerId
|
* @param controllerId
|
||||||
* the target to find assigned actions
|
* the target to find assigned actions
|
||||||
* @param active
|
* @param active
|
||||||
* the action active flag
|
* the action active flag
|
||||||
*
|
*
|
||||||
* @return the found {@link Action}
|
* @return the found {@link Action}
|
||||||
*/
|
*/
|
||||||
@EntityGraph(value = "Action.ds", type = EntityGraphType.LOAD)
|
@EntityGraph(value = "Action.ds", type = EntityGraphType.LOAD)
|
||||||
@@ -209,6 +220,15 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
|||||||
*/
|
*/
|
||||||
Long countByTargetControllerId(String controllerId);
|
Long countByTargetControllerId(String controllerId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Counts all {@link Action}s referring to the given targetId.
|
||||||
|
*
|
||||||
|
* @param targetId
|
||||||
|
* the target to count the {@link Action}s
|
||||||
|
* @return the count of actions referring to the given target
|
||||||
|
*/
|
||||||
|
Long countByTargetId(Long targetId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Counts all {@link Action}s referring to the given DistributionSet.
|
* Counts all {@link Action}s referring to the given DistributionSet.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ public interface ActionStatusRepository
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves all {@link ActionStatus} entries from repository of given
|
* Retrieves all {@link ActionStatus} entries from repository of given
|
||||||
* {@link Action}.
|
* ActionId.
|
||||||
*
|
*
|
||||||
* @param pageReq
|
* @param pageReq
|
||||||
* parameters
|
* parameters
|
||||||
* @param actionId
|
* @param actionId
|
||||||
@@ -64,5 +64,4 @@ public interface ActionStatusRepository
|
|||||||
*/
|
*/
|
||||||
@EntityGraph(value = "ActionStatus.withMessages", type = EntityGraphType.LOAD)
|
@EntityGraph(value = "ActionStatus.withMessages", type = EntityGraphType.LOAD)
|
||||||
Page<ActionStatus> getByActionId(Pageable pageReq, Long actionId);
|
Page<ActionStatus> getByActionId(Pageable pageReq, Long actionId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
|||||||
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus_;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaActionWithStatusCount;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaActionWithStatusCount;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction_;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaAction_;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||||
@@ -656,6 +657,29 @@ public class JpaDeploymentManagement implements DeploymentManagement {
|
|||||||
return actionStatusRepository.getByActionId(pageReq, actionId);
|
return actionStatusRepository.getByActionId(pageReq, actionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Page<String> findMessagesByActionStatusId(final Pageable pageable, final Long actionStatusId) {
|
||||||
|
final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
|
||||||
|
|
||||||
|
final CriteriaQuery<Long> countMsgQuery = cb.createQuery(Long.class);
|
||||||
|
final Root<JpaActionStatus> countMsgQueryFrom = countMsgQuery.distinct(true).from(JpaActionStatus.class);
|
||||||
|
final ListJoin<JpaActionStatus, String> cJoin = countMsgQueryFrom.joinList("messages", JoinType.LEFT);
|
||||||
|
countMsgQuery.select(cb.count(cJoin))
|
||||||
|
.where(cb.equal(countMsgQueryFrom.get(JpaActionStatus_.id), actionStatusId));
|
||||||
|
final Long totalCount = entityManager.createQuery(countMsgQuery).getSingleResult();
|
||||||
|
|
||||||
|
final CriteriaQuery<String> msgQuery = cb.createQuery(String.class);
|
||||||
|
final Root<JpaActionStatus>as = msgQuery.from(JpaActionStatus.class);
|
||||||
|
final ListJoin<JpaActionStatus, String> join = as.joinList("messages", JoinType.LEFT);
|
||||||
|
final CriteriaQuery<String> selMsgQuery = msgQuery.select(join);
|
||||||
|
selMsgQuery.where(cb.equal(as.get(JpaActionStatus_.id), actionStatusId));
|
||||||
|
|
||||||
|
final List<String> result = entityManager.createQuery(selMsgQuery).setFirstResult(pageable.getOffset())
|
||||||
|
.setMaxResults(pageable.getPageSize()).getResultList().stream().collect(Collectors.toList());
|
||||||
|
|
||||||
|
return new PageImpl<>(result, pageable, totalCount);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Page<ActionStatus> findActionStatusAll(final Pageable pageable) {
|
public Page<ActionStatus> findActionStatusAll(final Pageable pageable) {
|
||||||
return convertAcSPage(actionStatusRepository.findAll(pageable), pageable);
|
return convertAcSPage(actionStatusRepository.findAll(pageable), pageable);
|
||||||
|
|||||||
@@ -30,13 +30,12 @@ import org.eclipse.hawkbit.repository.exception.ForceQuitActionNotAllowedExcepti
|
|||||||
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
|
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
|
||||||
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus;
|
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||||
import org.eclipse.hawkbit.repository.model.Action;
|
import org.eclipse.hawkbit.repository.model.Action;
|
||||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||||
import org.eclipse.hawkbit.repository.model.ActionWithStatusCount;
|
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
|
import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||||
@@ -53,6 +52,7 @@ import org.springframework.context.ApplicationListener;
|
|||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
import org.springframework.data.domain.Slice;
|
||||||
import org.springframework.data.domain.Sort.Direction;
|
import org.springframework.data.domain.Sort.Direction;
|
||||||
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
@@ -148,24 +148,65 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Test verifies that the custom query to find all actions include the count of action status is working correctly")
|
@Description("Test verifies that actions of a target are found by using id-based search.")
|
||||||
public void findActionsWithStatusCountByTarget() {
|
public void findActionByTargetId() {
|
||||||
final DistributionSet testDs = testdataFactory.createDistributionSet("TestDs", "1.0",
|
final DistributionSet testDs = testdataFactory.createDistributionSet("TestDs", "1.0",
|
||||||
new ArrayList<DistributionSetTag>());
|
new ArrayList<DistributionSetTag>());
|
||||||
final List<Target> testTarget = testdataFactory.createTargets(1);
|
final List<Target> testTarget = testdataFactory.createTargets(1);
|
||||||
// one action with one action status is generated
|
// one action with one action status is generated
|
||||||
final Action action = deploymentManagement
|
final Long actionId = assignDistributionSet(testDs, testTarget).getActions().get(0);
|
||||||
.findActionWithDetails(assignDistributionSet(testDs, testTarget).getActions().get(0)).get();
|
|
||||||
// save 2 action status
|
|
||||||
actionStatusRepository.save(new JpaActionStatus(action, Status.RETRIEVED, System.currentTimeMillis()));
|
|
||||||
actionStatusRepository.save(new JpaActionStatus(action, Status.RUNNING, System.currentTimeMillis()));
|
|
||||||
|
|
||||||
final List<ActionWithStatusCount> findActionsWithStatusCountByTarget = deploymentManagement
|
// act
|
||||||
.findActionsWithStatusCountByTargetOrderByIdDesc(testTarget.get(0).getControllerId());
|
final Slice<Action> actions = deploymentManagement.findActionsByTarget(testTarget.get(0).getControllerId(),
|
||||||
|
pageReq);
|
||||||
|
final Long count = deploymentManagement.countActionsByTarget(testTarget.get(0).getControllerId());
|
||||||
|
|
||||||
assertThat(findActionsWithStatusCountByTarget).as("wrong action size").hasSize(1);
|
assertThat(count).as("One Action for target").isEqualTo(1L).isEqualTo(actions.getContent().size());
|
||||||
assertThat(findActionsWithStatusCountByTarget.get(0).getActionStatusCount()).as("wrong action status size")
|
assertThat(actions.getContent().get(0).getId()).as("Action of target").isEqualTo(actionId);
|
||||||
.isEqualTo(3);
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Test verifies that action-states of an action are found by using id-based search.")
|
||||||
|
public void findActionStatusByActionId() {
|
||||||
|
final DistributionSet testDs = testdataFactory.createDistributionSet("TestDs", "1.0",
|
||||||
|
new ArrayList<DistributionSetTag>());
|
||||||
|
final List<Target> testTarget = testdataFactory.createTargets(1);
|
||||||
|
// one action with one action status is generated
|
||||||
|
final Long actionId = assignDistributionSet(testDs, testTarget).getActions().get(0);
|
||||||
|
final Slice<Action> actions = deploymentManagement.findActionsByTarget(testTarget.get(0).getControllerId(),
|
||||||
|
pageReq);
|
||||||
|
final ActionStatus expectedActionStatus = actions.getContent().get(0).getActionStatus().get(0);
|
||||||
|
|
||||||
|
// act
|
||||||
|
final Page<ActionStatus> actionStates = deploymentManagement.findActionStatusByAction(pageReq, actionId);
|
||||||
|
|
||||||
|
assertThat(actionStates.getContent()).hasSize(1);
|
||||||
|
assertThat(actionStates.getContent().get(0)).as("Action-status of action").isEqualTo(expectedActionStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Test verifies that messages of an action-status are found by using id-based search.")
|
||||||
|
public void findMessagesByActionStatusId() {
|
||||||
|
final DistributionSet testDs = testdataFactory.createDistributionSet("TestDs", "1.0",
|
||||||
|
new ArrayList<DistributionSetTag>());
|
||||||
|
final List<Target> testTarget = testdataFactory.createTargets(1);
|
||||||
|
// one action with one action status is generated
|
||||||
|
final Long actionId = assignDistributionSet(testDs, testTarget).getActions().get(0);
|
||||||
|
// create action-status entry with one message
|
||||||
|
controllerManagement.addUpdateActionStatus(entityFactory.actionStatus().create(actionId)
|
||||||
|
.status(Action.Status.FINISHED).messages(Lists.newArrayList("finished message")));
|
||||||
|
final Page<ActionStatus> actionStates = deploymentManagement.findActionStatusByAction(pageReq, actionId);
|
||||||
|
// find newly created action-status entry with message
|
||||||
|
final ActionStatus actionStatusWithMessage = actionStates.getContent().stream()
|
||||||
|
.filter(entry -> entry.getMessages() != null && entry.getMessages().size() > 0).findFirst().get();
|
||||||
|
final String expectedMsg = actionStatusWithMessage.getMessages().get(0);
|
||||||
|
|
||||||
|
// act
|
||||||
|
final Page<String> messages = deploymentManagement.findMessagesByActionStatusId(pageReq,
|
||||||
|
actionStatusWithMessage.getId());
|
||||||
|
|
||||||
|
assertThat(actionStates.getTotalElements()).as("Two action-states in total").isEqualTo(2L);
|
||||||
|
assertThat(messages.getContent().get(0)).as("Message of action-status").isEqualTo(expectedMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -176,7 +217,7 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
assignDS.add(testdataFactory.createDistributionSet("DS" + i, "1.0", Collections.emptyList()).getId());
|
assignDS.add(testdataFactory.createDistributionSet("DS" + i, "1.0", Collections.emptyList()).getId());
|
||||||
}
|
}
|
||||||
// not exists
|
// not exists
|
||||||
assignDS.add(Long.valueOf(100));
|
assignDS.add(100L);
|
||||||
|
|
||||||
final DistributionSetTag tag = tagManagement
|
final DistributionSetTag tag = tagManagement
|
||||||
.createDistributionSetTag(entityFactory.tag().create().name("Tag1"));
|
.createDistributionSetTag(entityFactory.tag().create().name("Tag1"));
|
||||||
|
|||||||
@@ -8,8 +8,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.ui;
|
package org.eclipse.hawkbit.ui;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@@ -28,7 +26,6 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.core.io.Resource;
|
|
||||||
import org.vaadin.spring.events.EventBus;
|
import org.vaadin.spring.events.EventBus;
|
||||||
|
|
||||||
import com.vaadin.annotations.Title;
|
import com.vaadin.annotations.Title;
|
||||||
@@ -44,7 +41,6 @@ import com.vaadin.spring.navigator.SpringViewProvider;
|
|||||||
import com.vaadin.ui.Alignment;
|
import com.vaadin.ui.Alignment;
|
||||||
import com.vaadin.ui.Component;
|
import com.vaadin.ui.Component;
|
||||||
import com.vaadin.ui.CssLayout;
|
import com.vaadin.ui.CssLayout;
|
||||||
import com.vaadin.ui.CustomLayout;
|
|
||||||
import com.vaadin.ui.HorizontalLayout;
|
import com.vaadin.ui.HorizontalLayout;
|
||||||
import com.vaadin.ui.Label;
|
import com.vaadin.ui.Label;
|
||||||
import com.vaadin.ui.Panel;
|
import com.vaadin.ui.Panel;
|
||||||
@@ -84,6 +80,8 @@ public class HawkbitUI extends DefaultHawkbitUI implements DetachListener {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private NotificationUnreadButton notificationUnreadButton;
|
private NotificationUnreadButton notificationUnreadButton;
|
||||||
|
|
||||||
|
private Label viewTitle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor taking the push strategy.
|
* Constructor taking the push strategy.
|
||||||
*
|
*
|
||||||
@@ -120,47 +118,22 @@ public class HawkbitUI extends DefaultHawkbitUI implements DetachListener {
|
|||||||
rootLayout.setSizeFull();
|
rootLayout.setSizeFull();
|
||||||
|
|
||||||
dashboardMenu.init();
|
dashboardMenu.init();
|
||||||
dashboardMenu.setResponsive(Boolean.TRUE);
|
dashboardMenu.setResponsive(true);
|
||||||
|
|
||||||
final VerticalLayout contentVerticalLayout = new VerticalLayout();
|
final VerticalLayout contentVerticalLayout = new VerticalLayout();
|
||||||
contentVerticalLayout.addComponent(buildHeader());
|
|
||||||
contentVerticalLayout.setSizeFull();
|
contentVerticalLayout.setSizeFull();
|
||||||
|
contentVerticalLayout.setStyleName("main-content");
|
||||||
|
contentVerticalLayout.addComponent(buildHeader());
|
||||||
|
contentVerticalLayout.addComponent(buildViewTitle());
|
||||||
|
|
||||||
|
final Panel content = buildContent();
|
||||||
|
contentVerticalLayout.addComponent(content);
|
||||||
|
contentVerticalLayout.setExpandRatio(content, 1);
|
||||||
|
|
||||||
rootLayout.addComponent(dashboardMenu);
|
rootLayout.addComponent(dashboardMenu);
|
||||||
rootLayout.addComponent(contentVerticalLayout);
|
rootLayout.addComponent(contentVerticalLayout);
|
||||||
|
rootLayout.setExpandRatio(contentVerticalLayout, 1);
|
||||||
final HorizontalLayout viewHeadercontent = new HorizontalLayout();
|
|
||||||
contentVerticalLayout.addComponent(viewHeadercontent);
|
|
||||||
viewHeadercontent.setWidth("100%");
|
|
||||||
viewHeadercontent.setHeight("43px");
|
|
||||||
viewHeadercontent.addStyleName("view-header-layout");
|
|
||||||
|
|
||||||
final Label viewHeader = new Label();
|
|
||||||
viewHeader.setWidth("100%");
|
|
||||||
viewHeader.setStyleName("header-content");
|
|
||||||
viewHeadercontent.addComponent(viewHeader);
|
|
||||||
|
|
||||||
viewHeadercontent.addComponent(notificationUnreadButton);
|
|
||||||
viewHeadercontent.setComponentAlignment(notificationUnreadButton, Alignment.MIDDLE_RIGHT);
|
|
||||||
|
|
||||||
final Panel content = new Panel();
|
|
||||||
content.setSizeFull();
|
|
||||||
content.setStyleName("view-content");
|
|
||||||
contentVerticalLayout.addComponent(content);
|
|
||||||
|
|
||||||
rootLayout.setExpandRatio(contentVerticalLayout, 1.0F);
|
|
||||||
contentVerticalLayout.setStyleName("main-content");
|
|
||||||
contentVerticalLayout.setExpandRatio(content, 1.0F);
|
|
||||||
setContent(rootLayout);
|
setContent(rootLayout);
|
||||||
final Resource resource = context
|
|
||||||
.getResource("classpath:/VAADIN/themes/" + UI.getCurrent().getTheme() + "/layouts/footer.html");
|
|
||||||
try (InputStream resourceStream = resource.getInputStream()) {
|
|
||||||
final CustomLayout customLayout = new CustomLayout(resourceStream);
|
|
||||||
customLayout.setSizeUndefined();
|
|
||||||
contentVerticalLayout.addComponent(customLayout);
|
|
||||||
} catch (final IOException ex) {
|
|
||||||
LOG.error("Footer file cannot be loaded", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
final Navigator navigator = new Navigator(this, content);
|
final Navigator navigator = new Navigator(this, content);
|
||||||
navigator.addViewChangeListener(new ViewChangeListener() {
|
navigator.addViewChangeListener(new ViewChangeListener() {
|
||||||
@@ -176,10 +149,10 @@ public class HawkbitUI extends DefaultHawkbitUI implements DetachListener {
|
|||||||
final DashboardMenuItem view = dashboardMenu.getByViewName(event.getViewName());
|
final DashboardMenuItem view = dashboardMenu.getByViewName(event.getViewName());
|
||||||
dashboardMenu.postViewChange(new PostViewChangeEvent(view));
|
dashboardMenu.postViewChange(new PostViewChangeEvent(view));
|
||||||
if (view == null) {
|
if (view == null) {
|
||||||
viewHeader.setCaption(null);
|
viewTitle.setCaption(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
viewHeader.setCaption(view.getDashboardCaptionLong());
|
viewTitle.setCaption(view.getDashboardCaptionLong());
|
||||||
notificationUnreadButton.setCurrentView(event.getNewView());
|
notificationUnreadButton.setCurrentView(event.getNewView());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -200,6 +173,28 @@ public class HawkbitUI extends DefaultHawkbitUI implements DetachListener {
|
|||||||
LOG.info("Current locale of the application is : {}", HawkbitCommonUtil.getLocale());
|
LOG.info("Current locale of the application is : {}", HawkbitCommonUtil.getLocale());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Panel buildContent() {
|
||||||
|
final Panel content = new Panel();
|
||||||
|
content.setSizeFull();
|
||||||
|
content.setStyleName("view-content");
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
private HorizontalLayout buildViewTitle() {
|
||||||
|
final HorizontalLayout viewHeadercontent = new HorizontalLayout();
|
||||||
|
viewHeadercontent.setWidth("100%");
|
||||||
|
viewHeadercontent.addStyleName("view-header-layout");
|
||||||
|
|
||||||
|
viewTitle = new Label();
|
||||||
|
viewTitle.setWidth("100%");
|
||||||
|
viewTitle.setStyleName("header-content");
|
||||||
|
viewHeadercontent.addComponent(viewTitle);
|
||||||
|
|
||||||
|
viewHeadercontent.addComponent(notificationUnreadButton);
|
||||||
|
viewHeadercontent.setComponentAlignment(notificationUnreadButton, Alignment.MIDDLE_RIGHT);
|
||||||
|
return viewHeadercontent;
|
||||||
|
}
|
||||||
|
|
||||||
private Component buildHeader() {
|
private Component buildHeader() {
|
||||||
final CssLayout cssLayout = new CssLayout();
|
final CssLayout cssLayout = new CssLayout();
|
||||||
cssLayout.setStyleName("view-header");
|
cssLayout.setStyleName("view-header");
|
||||||
|
|||||||
@@ -467,12 +467,12 @@ public class ArtifactDetailsLayout extends VerticalLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void showMinIcon() {
|
private void showMinIcon() {
|
||||||
maxMinButton.togleIcon(FontAwesome.COMPRESS);
|
maxMinButton.toggleIcon(FontAwesome.COMPRESS);
|
||||||
maxMinButton.setData(Boolean.TRUE);
|
maxMinButton.setData(Boolean.TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showMaxIcon() {
|
private void showMaxIcon() {
|
||||||
maxMinButton.togleIcon(FontAwesome.EXPAND);
|
maxMinButton.toggleIcon(FontAwesome.EXPAND);
|
||||||
maxMinButton.setData(Boolean.FALSE);
|
maxMinButton.setData(Boolean.FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,40 +8,70 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.ui.common.grid;
|
package org.eclipse.hawkbit.ui.common.grid;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.eclipse.hawkbit.ui.SpPermissionChecker;
|
import org.eclipse.hawkbit.ui.SpPermissionChecker;
|
||||||
import org.eclipse.hawkbit.ui.components.RefreshableContainer;
|
import org.eclipse.hawkbit.ui.components.RefreshableContainer;
|
||||||
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
||||||
import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer;
|
import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer;
|
||||||
import org.vaadin.spring.events.EventBus;
|
import org.vaadin.spring.events.EventBus;
|
||||||
import org.vaadin.spring.events.EventBus.UIEventBus;
|
import org.vaadin.spring.events.EventBus.UIEventBus;
|
||||||
|
|
||||||
import com.vaadin.data.Container;
|
|
||||||
import com.vaadin.data.Container.Indexed;
|
import com.vaadin.data.Container.Indexed;
|
||||||
|
import com.vaadin.data.util.GeneratedPropertyContainer;
|
||||||
|
import com.vaadin.data.util.converter.Converter;
|
||||||
import com.vaadin.ui.Grid;
|
import com.vaadin.ui.Grid;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract table class.
|
* Abstract grid that offers various capabilities (aka support) to offer
|
||||||
|
* convenient enhancements to the vaadin standard grid.
|
||||||
*
|
*
|
||||||
|
* @param <T>
|
||||||
|
* The container-type used by the grid
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractGrid extends Grid implements RefreshableContainer {
|
public abstract class AbstractGrid<T extends Indexed> extends Grid implements RefreshableContainer {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
private static final long serialVersionUID = 4856562746502217630L;
|
|
||||||
|
|
||||||
protected final VaadinMessageSource i18n;
|
protected final VaadinMessageSource i18n;
|
||||||
|
|
||||||
protected final transient EventBus.UIEventBus eventBus;
|
protected final transient EventBus.UIEventBus eventBus;
|
||||||
|
|
||||||
protected final SpPermissionChecker permissionChecker;
|
protected final SpPermissionChecker permissionChecker;
|
||||||
|
|
||||||
protected AbstractGrid(final VaadinMessageSource i18n, final UIEventBus eventBus, final SpPermissionChecker permissionChecker) {
|
private transient AbstractMaximizeSupport maximizeSupport;
|
||||||
|
private transient AbstractGeneratedPropertySupport generatedPropertySupport;
|
||||||
|
private transient SingleSelectionSupport singleSelectionSupport;
|
||||||
|
private transient DetailsSupport detailsSupport;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param i18n
|
||||||
|
* @param eventBus
|
||||||
|
* @param permissionChecker
|
||||||
|
*/
|
||||||
|
protected AbstractGrid(final VaadinMessageSource i18n, final UIEventBus eventBus,
|
||||||
|
final SpPermissionChecker permissionChecker) {
|
||||||
this.i18n = i18n;
|
this.i18n = i18n;
|
||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
this.permissionChecker = permissionChecker;
|
this.permissionChecker = permissionChecker;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the grid.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* <b>NOTE:</b> Sub-classes should configure the grid before calling this
|
||||||
|
* method (this means: set all support-classes needed, and then call init).
|
||||||
|
*/
|
||||||
|
protected void init() {
|
||||||
setSizeFull();
|
setSizeFull();
|
||||||
setImmediate(true);
|
setImmediate(true);
|
||||||
setId(getGridId());
|
setId(getGridId());
|
||||||
setSelectionMode(SelectionMode.NONE);
|
if (!hasSingleSelectionSupport()) {
|
||||||
|
setSelectionMode(SelectionMode.NONE);
|
||||||
|
}
|
||||||
setColumnReorderingAllowed(true);
|
setColumnReorderingAllowed(true);
|
||||||
addNewContainerDS();
|
addNewContainerDS();
|
||||||
eventBus.subscribe(this);
|
eventBus.subscribe(this);
|
||||||
@@ -52,56 +82,593 @@ public abstract class AbstractGrid extends Grid implements RefreshableContainer
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void refreshContainer() {
|
public void refreshContainer() {
|
||||||
final Container container = getContainerDataSource();
|
final Indexed container = getContainerDataSource();
|
||||||
if (!(container instanceof LazyQueryContainer)) {
|
if (hasGeneratedPropertySupport()
|
||||||
|
&& getGeneratedPropertySupport().getRawContainer() instanceof LazyQueryContainer) {
|
||||||
|
((LazyQueryContainer) getGeneratedPropertySupport().getRawContainer()).refresh();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
((LazyQueryContainer) container).refresh();
|
|
||||||
|
if (container instanceof LazyQueryContainer) {
|
||||||
|
((LazyQueryContainer) container).refresh();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addNewContainerDS() {
|
/**
|
||||||
final Container container = createContainer();
|
* Creates a new container instance by calling the required
|
||||||
setContainerDataSource((Indexed) container);
|
* template-methods.
|
||||||
|
* <p>
|
||||||
|
* A new container is created on initialization as well as when container
|
||||||
|
* content fundamentally changes (e.g. if container content depends on a
|
||||||
|
* selection as common in master-details relations)
|
||||||
|
*/
|
||||||
|
protected void addNewContainerDS() {
|
||||||
|
final T container = createContainer();
|
||||||
|
Indexed indexedContainer = container;
|
||||||
|
if (hasGeneratedPropertySupport()) {
|
||||||
|
indexedContainer = getGeneratedPropertySupport().decorate(container);
|
||||||
|
setContainerDataSource(indexedContainer);
|
||||||
|
getGeneratedPropertySupport().addGeneratedContainerProperties();
|
||||||
|
} else {
|
||||||
|
setContainerDataSource(indexedContainer);
|
||||||
|
}
|
||||||
addContainerProperties();
|
addContainerProperties();
|
||||||
setColumnExpandRatio();
|
|
||||||
setColumnProperties();
|
setColumnProperties();
|
||||||
setColumnHeaderNames();
|
setColumnHeaderNames();
|
||||||
|
setColumnsHidable();
|
||||||
addColumnRenderes();
|
addColumnRenderes();
|
||||||
|
setColumnExpandRatio();
|
||||||
|
|
||||||
|
setHiddenColumns();
|
||||||
|
|
||||||
final CellDescriptionGenerator cellDescriptionGenerator = getDescriptionGenerator();
|
final CellDescriptionGenerator cellDescriptionGenerator = getDescriptionGenerator();
|
||||||
if (getDescriptionGenerator() != null) {
|
if (getDescriptionGenerator() != null) {
|
||||||
setCellDescriptionGenerator(cellDescriptionGenerator);
|
setCellDescriptionGenerator(cellDescriptionGenerator);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow column hiding
|
if (indexedContainer != null && indexedContainer.size() == 0) {
|
||||||
for (final Column c : getColumns()) {
|
|
||||||
c.setHidable(true);
|
|
||||||
}
|
|
||||||
setHiddenColumns();
|
|
||||||
int size = 0;
|
|
||||||
if (container != null) {
|
|
||||||
size = container.size();
|
|
||||||
}
|
|
||||||
if (size == 0) {
|
|
||||||
setData(SPUIDefinitions.NO_DATA);
|
setData(SPUIDefinitions.NO_DATA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract Container createContainer();
|
/**
|
||||||
|
* Sets the standard behavior of columns to be hidable. If implementors
|
||||||
|
* needs other behavior they have to concern about it.
|
||||||
|
*/
|
||||||
|
protected void setColumnsHidable() {
|
||||||
|
// Allow column hiding
|
||||||
|
for (final Column c : getColumns()) {
|
||||||
|
c.setHidable(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables maximize-support for the grid by setting a MaximizeSupport
|
||||||
|
* implementation.
|
||||||
|
*
|
||||||
|
* @param maximizeSupport
|
||||||
|
* encapsulates behavior for minimize and maximize.
|
||||||
|
*/
|
||||||
|
protected void setMaximizeSupport(final AbstractMaximizeSupport maximizeSupport) {
|
||||||
|
this.maximizeSupport = maximizeSupport;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the MaximizeSupport implementation describing behavior for minimize
|
||||||
|
* and maximize.
|
||||||
|
*
|
||||||
|
* @return maximizeSupport that encapsulates behavior for minimize and
|
||||||
|
* maximize.
|
||||||
|
*/
|
||||||
|
protected AbstractMaximizeSupport getMaximizeSupport() {
|
||||||
|
return maximizeSupport;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether maximize-support is enabled.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if maximize-support is enabled, otherwise
|
||||||
|
* <code>false</code>
|
||||||
|
*/
|
||||||
|
protected boolean hasMaximizeSupport() {
|
||||||
|
return maximizeSupport != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables support for generated properties. This implies that the
|
||||||
|
* standard-container has to be decorated and the generators have to be
|
||||||
|
* registered for the generated (aka virtual) properties.
|
||||||
|
*
|
||||||
|
* @param generatedPropertySupport
|
||||||
|
* that encapsulates behavior for generated properties
|
||||||
|
*/
|
||||||
|
protected void setGeneratedPropertySupport(final AbstractGeneratedPropertySupport generatedPropertySupport) {
|
||||||
|
this.generatedPropertySupport = generatedPropertySupport;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the GeneratedPropertySupport implementation describing generated
|
||||||
|
* properties by registering their generators and attaching them to a
|
||||||
|
* wrapper-container.
|
||||||
|
*
|
||||||
|
* @return generatedPropertySupport that encapsulates registration of
|
||||||
|
* generated properties.
|
||||||
|
*/
|
||||||
|
protected AbstractGeneratedPropertySupport getGeneratedPropertySupport() {
|
||||||
|
return generatedPropertySupport;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether support for generated properties is enabled.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if support for generated properties is enabled,
|
||||||
|
* otherwise <code>false</code>
|
||||||
|
*/
|
||||||
|
protected boolean hasGeneratedPropertySupport() {
|
||||||
|
return generatedPropertySupport != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables single-selection-support for the grid by setting
|
||||||
|
* SingleSelectionSupport configuration.
|
||||||
|
*
|
||||||
|
* @param singleSelectionSupport
|
||||||
|
* encapsulates behavior for single-selection and offers some
|
||||||
|
* convenient functionality.
|
||||||
|
*/
|
||||||
|
protected void setSingleSelectionSupport(final SingleSelectionSupport singleSelectionSupport) {
|
||||||
|
this.singleSelectionSupport = singleSelectionSupport;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the SingleSelectionSupport implementation configuring
|
||||||
|
* single-selection.
|
||||||
|
*
|
||||||
|
* @return singleSelectionSupport that configures single-selection.
|
||||||
|
*/
|
||||||
|
protected SingleSelectionSupport getSingleSelectionSupport() {
|
||||||
|
return singleSelectionSupport;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether single-selection-support is enabled.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if single-selection-support is enabled,
|
||||||
|
* otherwise <code>false</code>
|
||||||
|
*/
|
||||||
|
protected boolean hasSingleSelectionSupport() {
|
||||||
|
return singleSelectionSupport != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables details-support for the grid by setting DetailsSupport
|
||||||
|
* configuration. If details-support is enabled, the grid handles
|
||||||
|
* details-data that depends on a master-selection.
|
||||||
|
*
|
||||||
|
* @param detailsSupport
|
||||||
|
* encapsulates behavior for changes of master-selection.
|
||||||
|
*/
|
||||||
|
protected void setDetailsSupport(final DetailsSupport detailsSupport) {
|
||||||
|
this.detailsSupport = detailsSupport;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the DetailsSupport implementation configuring master-details
|
||||||
|
* relation.
|
||||||
|
*
|
||||||
|
* @return detailsSupport that configures master-details relation.
|
||||||
|
*/
|
||||||
|
public DetailsSupport getDetailsSupport() {
|
||||||
|
return detailsSupport;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether details-support is enabled.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if details-support is enabled, otherwise
|
||||||
|
* <code>false</code>
|
||||||
|
*/
|
||||||
|
public boolean hasDetailsSupport() {
|
||||||
|
return detailsSupport != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template method invoked by {@link this#addNewContainerDS()} for creating
|
||||||
|
* a container instance.
|
||||||
|
*
|
||||||
|
* @return new container instance used by the grid.
|
||||||
|
*/
|
||||||
|
protected abstract T createContainer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template method invoked by {@link this#addNewContainerDS()} for adding
|
||||||
|
* properties to the container (usually by invoing
|
||||||
|
* {@link Container#addContainerProperty(Object, Class, Object))})
|
||||||
|
*/
|
||||||
protected abstract void addContainerProperties();
|
protected abstract void addContainerProperties();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template method invoked by {@link this#addNewContainerDS()} for setting
|
||||||
|
* the expand ratio of the columns.
|
||||||
|
*/
|
||||||
protected abstract void setColumnExpandRatio();
|
protected abstract void setColumnExpandRatio();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template method invoked by {@link this#addNewContainerDS()} for setting
|
||||||
|
* the column names.
|
||||||
|
*/
|
||||||
protected abstract void setColumnHeaderNames();
|
protected abstract void setColumnHeaderNames();
|
||||||
|
|
||||||
protected abstract String getGridId();
|
/**
|
||||||
|
* Template method invoked by {@link this#addNewContainerDS()} for setting
|
||||||
|
* the column properties to the grid.
|
||||||
|
*/
|
||||||
protected abstract void setColumnProperties();
|
protected abstract void setColumnProperties();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template method invoked by {@link this#addNewContainerDS()} for adding
|
||||||
|
* special column renderers if needed.
|
||||||
|
*/
|
||||||
protected abstract void addColumnRenderes();
|
protected abstract void addColumnRenderes();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template method invoked by {@link this#addNewContainerDS()} that hides
|
||||||
|
* columns. If a column is hidable and hidden, it can be made visible via
|
||||||
|
* grid column menu.
|
||||||
|
*/
|
||||||
protected abstract void setHiddenColumns();
|
protected abstract void setHiddenColumns();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template method invoked by {@link this#addNewContainerDS()} for adding a
|
||||||
|
* CellDescriptionGenerator to the grid.
|
||||||
|
*/
|
||||||
protected abstract CellDescriptionGenerator getDescriptionGenerator();
|
protected abstract CellDescriptionGenerator getDescriptionGenerator();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets id of the grid.
|
||||||
|
*
|
||||||
|
* @return id of the grid
|
||||||
|
*/
|
||||||
|
protected abstract String getGridId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the default row of the header. This means the current default row
|
||||||
|
* is removed and replaced with a newly created one.
|
||||||
|
*
|
||||||
|
* @return the new and clean header row.
|
||||||
|
*/
|
||||||
|
protected HeaderRow resetHeaderDefaultRow() {
|
||||||
|
getHeader().removeRow(getHeader().getDefaultRow());
|
||||||
|
final HeaderRow newHeaderRow = getHeader().appendRow();
|
||||||
|
getHeader().setDefaultRow(newHeaderRow);
|
||||||
|
return newHeaderRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Support for master-details relation for grid. This means that grid
|
||||||
|
* content (=details) is updated as soon as master-data changes.
|
||||||
|
*/
|
||||||
|
public class DetailsSupport {
|
||||||
|
|
||||||
|
private Long master;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set selected master-data as member of this grid-support (as all
|
||||||
|
* presented grid-data is related to this master-data) and re-calculate
|
||||||
|
* grid-container-content.
|
||||||
|
*
|
||||||
|
* @param master
|
||||||
|
* id of selected action
|
||||||
|
*/
|
||||||
|
public void populateMasterDataAndRecalculateContainer(final Long master) {
|
||||||
|
this.master = master;
|
||||||
|
recalculateContainer();
|
||||||
|
populateSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set selected master-data as member of this grid-support (as all
|
||||||
|
* presented grid-data is related to this master-data) and re-create
|
||||||
|
* grid-container.
|
||||||
|
*
|
||||||
|
* @param master
|
||||||
|
* id of selected action
|
||||||
|
*/
|
||||||
|
public void populateMasterDataAndRecreateContainer(final Long master) {
|
||||||
|
this.master = master;
|
||||||
|
recreateContainer();
|
||||||
|
populateSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Propagates the selection if needed.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void populateSelection() {
|
||||||
|
if (!hasSingleSelectionSupport()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (master == null) {
|
||||||
|
getSingleSelectionSupport().clearSelection();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getSingleSelectionSupport().selectFirstRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the master-data id.
|
||||||
|
*
|
||||||
|
* @return master-data id
|
||||||
|
*/
|
||||||
|
public Long getMasterDataId() {
|
||||||
|
return master;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidates container-data (but reused container) and refreshes it
|
||||||
|
* with new details-data for the new selected master-data.
|
||||||
|
*/
|
||||||
|
private void recalculateContainer() {
|
||||||
|
clearSortOrder();
|
||||||
|
refreshContainer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidates container and replace it with a fresh instance for the
|
||||||
|
* new selected master-data.
|
||||||
|
*/
|
||||||
|
private void recreateContainer() {
|
||||||
|
removeAllColumns();
|
||||||
|
clearSortOrder();
|
||||||
|
addNewContainerDS();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Via implementations of this support capability an expand-mode is provided
|
||||||
|
* that maximizes the grid size.
|
||||||
|
*/
|
||||||
|
protected abstract class AbstractMaximizeSupport {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renews the content for maximized layout.
|
||||||
|
*/
|
||||||
|
public void createMaximizedContent() {
|
||||||
|
setMaximizedColumnProperties();
|
||||||
|
setMaximizedHiddenColumns();
|
||||||
|
setMaximizedHeaders();
|
||||||
|
setMaximizedColumnExpandRatio();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renews the content for minimized layout.
|
||||||
|
*/
|
||||||
|
public void createMinimizedContent() {
|
||||||
|
setColumnProperties();
|
||||||
|
setHiddenColumns();
|
||||||
|
setColumnExpandRatio();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the column properties for maximized-state.
|
||||||
|
*/
|
||||||
|
protected abstract void setMaximizedColumnProperties();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the hidden columns for maximized-state.
|
||||||
|
*/
|
||||||
|
protected abstract void setMaximizedHiddenColumns();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets additional headers for maximized-state.
|
||||||
|
*/
|
||||||
|
protected abstract void setMaximizedHeaders();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets column expand ratio for maximized-state.
|
||||||
|
*/
|
||||||
|
protected abstract void setMaximizedColumnExpandRatio();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grids that are used in conjunction with
|
||||||
|
* {@link GeneratedPropertyContainer}, might use
|
||||||
|
* {@link AbstractGeneratedPropertySupport} to get type-save access to the
|
||||||
|
* raw container as well as the decorated container.
|
||||||
|
*/
|
||||||
|
protected abstract class AbstractGeneratedPropertySupport {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gives type-save access to the wrapper container the grid works on.
|
||||||
|
* This wrapper container attaches generated properties that are not
|
||||||
|
* part of the raw container that encapsulates the database access.
|
||||||
|
*
|
||||||
|
* @return decorated container that includes the generated properties as
|
||||||
|
* well as the native properties.
|
||||||
|
*/
|
||||||
|
public abstract GeneratedPropertyContainer getDecoratedContainer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gives type-save access to the wrapped container that binds to the
|
||||||
|
* database. The grid does not work directly with this container but
|
||||||
|
* with a container that wraps and decorates it with generated
|
||||||
|
* properties.
|
||||||
|
*
|
||||||
|
* @return raw container that gives access to the native properties.
|
||||||
|
*/
|
||||||
|
public abstract T getRawContainer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the generated properties to the decorated container. Each
|
||||||
|
* generated property has to be associated with a property generator
|
||||||
|
* that is capable to calculate the value of the generated (aka virtual)
|
||||||
|
* property.
|
||||||
|
*
|
||||||
|
* @return decorated container that includes the generated properties
|
||||||
|
*/
|
||||||
|
protected abstract GeneratedPropertyContainer addGeneratedContainerProperties();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorates the raw-container by wrapping it.
|
||||||
|
*
|
||||||
|
* @param container
|
||||||
|
* raw-container to be wrapped.
|
||||||
|
* @return decorated container.
|
||||||
|
*/
|
||||||
|
protected GeneratedPropertyContainer decorate(final T container) {
|
||||||
|
return new GeneratedPropertyContainer(container);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Support for single selection on the grid.
|
||||||
|
*/
|
||||||
|
protected class SingleSelectionSupport {
|
||||||
|
|
||||||
|
public SingleSelectionSupport() {
|
||||||
|
enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void enable() {
|
||||||
|
setSelectionMode(SelectionMode.SINGLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void disable() {
|
||||||
|
setSelectionMode(SelectionMode.NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects the first row if available and enabled.
|
||||||
|
*/
|
||||||
|
public void selectFirstRow() {
|
||||||
|
if (!isSingleSelectionModel()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Indexed container = getContainerDataSource();
|
||||||
|
final int size = container.size();
|
||||||
|
if (size > 0) {
|
||||||
|
refreshRows(getContainerDataSource().firstItemId());
|
||||||
|
getSingleSelectionModel().select(getContainerDataSource().firstItemId());
|
||||||
|
} else {
|
||||||
|
getSingleSelectionModel().select(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isSingleSelectionModel() {
|
||||||
|
return getSelectionModel() instanceof SelectionModel.Single;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the selection.
|
||||||
|
*/
|
||||||
|
public void clearSelection() {
|
||||||
|
if (!isSingleSelectionModel()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
getSingleSelectionModel().select(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SelectionModel.Single getSingleSelectionModel() {
|
||||||
|
return (SelectionModel.Single) getSelectionModel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CellStyleGenerator that concerns about alignment in the grid cells.
|
||||||
|
*/
|
||||||
|
protected static class AlignCellStyleGenerator implements CellStyleGenerator {
|
||||||
|
private static final long serialVersionUID = 5573570647129792429L;
|
||||||
|
|
||||||
|
private final String[] left;
|
||||||
|
private final String[] center;
|
||||||
|
private final String[] right;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param left
|
||||||
|
* list of propertyIds that should be left-aligned
|
||||||
|
* @param center
|
||||||
|
* list of propertyIds that should be center-aligned
|
||||||
|
* @param right
|
||||||
|
* list of propertyIds that should be right-aligned
|
||||||
|
*/
|
||||||
|
public AlignCellStyleGenerator(final String[] left, final String[] center, final String[] right) {
|
||||||
|
this.left = left;
|
||||||
|
this.center = center;
|
||||||
|
this.right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStyle(final CellReference cellReference) {
|
||||||
|
if (ArrayUtils.contains(center, cellReference.getPropertyId())) {
|
||||||
|
return "centeralign";
|
||||||
|
} else if (ArrayUtils.contains(right, cellReference.getPropertyId())) {
|
||||||
|
return "rightalign";
|
||||||
|
} else if (ArrayUtils.contains(left, cellReference.getPropertyId())) {
|
||||||
|
return "leftalign";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a tooltip to the 'Date and time' column in detailed format.
|
||||||
|
*/
|
||||||
|
public static class ModifiedTimeTooltipGenerator implements CellDescriptionGenerator {
|
||||||
|
private static final long serialVersionUID = -6617911967167729195L;
|
||||||
|
|
||||||
|
private final String datePropertyId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param datePropertyId
|
||||||
|
*/
|
||||||
|
public ModifiedTimeTooltipGenerator(final String datePropertyId) {
|
||||||
|
this.datePropertyId = datePropertyId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription(final CellReference cell) {
|
||||||
|
if (!datePropertyId.equals(cell.getPropertyId())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final Long timestamp = (Long) cell.getItem().getItemProperty(datePropertyId).getValue();
|
||||||
|
return SPDateTimeUtil.getFormattedDate(timestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converter that gets time-data as input of type <code>Long</code> and
|
||||||
|
* converts to a formatted date string.
|
||||||
|
*/
|
||||||
|
public class LongToFormattedDateStringConverter implements Converter<String, Long> {
|
||||||
|
private static final long serialVersionUID = 1247513913478717845L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long convertToModel(final String value, final Class<? extends Long> targetType, final Locale locale) {
|
||||||
|
// not needed
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String convertToPresentation(final Long value, final Class<? extends String> targetType,
|
||||||
|
final Locale locale) {
|
||||||
|
return SPDateTimeUtil.getFormattedDate(value, SPUIDefinitions.LAST_QUERY_DATE_FORMAT_SHORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<Long> getModelType() {
|
||||||
|
return Long.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<String> getPresentationType() {
|
||||||
|
return String.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,201 @@
|
|||||||
|
/**
|
||||||
|
* 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.common.grid;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
||||||
|
import org.vaadin.spring.events.EventBus;
|
||||||
|
import org.vaadin.spring.events.EventBus.UIEventBus;
|
||||||
|
|
||||||
|
import com.vaadin.ui.AbstractOrderedLayout;
|
||||||
|
import com.vaadin.ui.Alignment;
|
||||||
|
import com.vaadin.ui.Grid;
|
||||||
|
import com.vaadin.ui.HorizontalLayout;
|
||||||
|
import com.vaadin.ui.Label;
|
||||||
|
import com.vaadin.ui.Layout;
|
||||||
|
import com.vaadin.ui.VerticalLayout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract grid layout class which builds layout with grid {@link AbstractGrid}
|
||||||
|
* and grid header {@link DefaultGridHeader}.
|
||||||
|
*/
|
||||||
|
public abstract class AbstractGridComponentLayout extends VerticalLayout {
|
||||||
|
private static final long serialVersionUID = -3766179797384539821L;
|
||||||
|
|
||||||
|
protected final transient EventBus.UIEventBus eventBus;
|
||||||
|
protected final VaadinMessageSource i18n;
|
||||||
|
|
||||||
|
private AbstractOrderedLayout gridHeader;
|
||||||
|
private Grid grid;
|
||||||
|
|
||||||
|
private transient AbstractFooterSupport footerSupport;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param i18n
|
||||||
|
* @param deploymentManagement
|
||||||
|
* @param eventBus
|
||||||
|
* @param notification
|
||||||
|
* @param managementUIState
|
||||||
|
*/
|
||||||
|
public AbstractGridComponentLayout(final VaadinMessageSource i18n, final UIEventBus eventBus) {
|
||||||
|
super();
|
||||||
|
this.i18n = i18n;
|
||||||
|
this.eventBus = eventBus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes this layout that presents a header and a grid.
|
||||||
|
*/
|
||||||
|
protected void init() {
|
||||||
|
this.gridHeader = createGridHeader();
|
||||||
|
this.grid = createGrid();
|
||||||
|
buildLayout();
|
||||||
|
setSizeFull();
|
||||||
|
setImmediate(true);
|
||||||
|
eventBus.subscribe(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Layouts header, grid and optional footer.
|
||||||
|
*/
|
||||||
|
protected void buildLayout() {
|
||||||
|
setSizeFull();
|
||||||
|
setSpacing(true);
|
||||||
|
setMargin(false);
|
||||||
|
setStyleName("group");
|
||||||
|
final VerticalLayout gridHeaderLayout = new VerticalLayout();
|
||||||
|
gridHeaderLayout.setSizeFull();
|
||||||
|
gridHeaderLayout.setSpacing(false);
|
||||||
|
gridHeaderLayout.setMargin(false);
|
||||||
|
|
||||||
|
gridHeaderLayout.setStyleName("table-layout");
|
||||||
|
gridHeaderLayout.addComponent(gridHeader);
|
||||||
|
|
||||||
|
gridHeaderLayout.setComponentAlignment(gridHeader, Alignment.TOP_CENTER);
|
||||||
|
gridHeaderLayout.addComponent(grid);
|
||||||
|
gridHeaderLayout.setComponentAlignment(grid, Alignment.TOP_CENTER);
|
||||||
|
gridHeaderLayout.setExpandRatio(grid, 1.0F);
|
||||||
|
|
||||||
|
addComponent(gridHeaderLayout);
|
||||||
|
setComponentAlignment(gridHeaderLayout, Alignment.TOP_CENTER);
|
||||||
|
setExpandRatio(gridHeaderLayout, 1.0F);
|
||||||
|
if (hasFooterSupport()) {
|
||||||
|
final Layout footerLayout = getFooterSupport().createFooterMessageComponent();
|
||||||
|
addComponent(footerLayout);
|
||||||
|
setComponentAlignment(footerLayout, Alignment.BOTTOM_CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the selection of this grid as master for another grid that
|
||||||
|
* displays the details.
|
||||||
|
*
|
||||||
|
* @param details
|
||||||
|
* the details of another grid the selection of this grid should
|
||||||
|
* be registered for as master.
|
||||||
|
*/
|
||||||
|
public void registerDetails(final AbstractGrid<?>.DetailsSupport details) {
|
||||||
|
grid.addSelectionListener(event -> {
|
||||||
|
final Long masterId = (Long) event.getSelected().stream().findFirst().orElse(null);
|
||||||
|
details.populateMasterDataAndRecalculateContainer(masterId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the grid instance displayed and owned by the layout.
|
||||||
|
*
|
||||||
|
* @return grid instance displayed and owned by the layout.
|
||||||
|
*/
|
||||||
|
public Grid getGrid() {
|
||||||
|
return grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the grid-header instance displayed and owned by the layout.
|
||||||
|
*
|
||||||
|
* @return grid-header instance displayed and owned by the layout.
|
||||||
|
*/
|
||||||
|
public AbstractOrderedLayout getHeader() {
|
||||||
|
return gridHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the grid-header instance the layout is responsible for.
|
||||||
|
*
|
||||||
|
* @return newly created grid-header instance displayed and owned by the
|
||||||
|
* layout.
|
||||||
|
*/
|
||||||
|
public abstract AbstractOrderedLayout createGridHeader();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the grid instance the layout is responsible for.
|
||||||
|
*
|
||||||
|
* @return newly created grid instance displayed and owned by the layout.
|
||||||
|
*/
|
||||||
|
public abstract Grid createGrid();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables footer-support for the grid by setting a FooterSupport
|
||||||
|
* implementation.
|
||||||
|
*
|
||||||
|
* @param footerSupport
|
||||||
|
* encapsulates footer layout.
|
||||||
|
*/
|
||||||
|
public void setFooterSupport(final AbstractFooterSupport footerSupport) {
|
||||||
|
this.footerSupport = footerSupport;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the FooterSupport implementation describing footer layout.
|
||||||
|
*
|
||||||
|
* @return footerSupport that encapsulates footer layout.
|
||||||
|
*/
|
||||||
|
public AbstractFooterSupport getFooterSupport() {
|
||||||
|
return footerSupport;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether footer-support is enabled.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if footer-support is enabled, otherwise
|
||||||
|
* <code>false</code>
|
||||||
|
*/
|
||||||
|
public boolean hasFooterSupport() {
|
||||||
|
return footerSupport != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If footer support is enabled, the footer is placed below the component
|
||||||
|
*/
|
||||||
|
public abstract class AbstractFooterSupport {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a sub-layout for the footer.
|
||||||
|
*
|
||||||
|
* @return the footer sub-layout.
|
||||||
|
*/
|
||||||
|
private Layout createFooterMessageComponent() {
|
||||||
|
final HorizontalLayout footerLayout = new HorizontalLayout();
|
||||||
|
footerLayout.addComponent(getFooterMessageLabel());
|
||||||
|
footerLayout.setStyleName(SPUIStyleDefinitions.FOOTER_LAYOUT);
|
||||||
|
footerLayout.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
return footerLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the count message label.
|
||||||
|
*
|
||||||
|
* @return count message
|
||||||
|
*/
|
||||||
|
protected abstract Label getFooterMessageLabel();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -152,7 +152,7 @@ public abstract class AbstractGridHeader extends VerticalLayout {
|
|||||||
|
|
||||||
private void openSearchTextField() {
|
private void openSearchTextField() {
|
||||||
searchResetIcon.addStyleName(SPUIDefinitions.FILTER_RESET_ICON);
|
searchResetIcon.addStyleName(SPUIDefinitions.FILTER_RESET_ICON);
|
||||||
searchResetIcon.togleIcon(FontAwesome.TIMES);
|
searchResetIcon.toggleIcon(FontAwesome.TIMES);
|
||||||
searchResetIcon.setData(Boolean.TRUE);
|
searchResetIcon.setData(Boolean.TRUE);
|
||||||
searchField.removeStyleName(SPUIDefinitions.FILTER_BOX_HIDE);
|
searchField.removeStyleName(SPUIDefinitions.FILTER_BOX_HIDE);
|
||||||
searchField.setVisible(true);
|
searchField.setVisible(true);
|
||||||
@@ -164,7 +164,7 @@ public abstract class AbstractGridHeader extends VerticalLayout {
|
|||||||
searchField.addStyleName(SPUIDefinitions.FILTER_BOX_HIDE);
|
searchField.addStyleName(SPUIDefinitions.FILTER_BOX_HIDE);
|
||||||
searchField.setVisible(false);
|
searchField.setVisible(false);
|
||||||
searchResetIcon.removeStyleName(SPUIDefinitions.FILTER_RESET_ICON);
|
searchResetIcon.removeStyleName(SPUIDefinitions.FILTER_RESET_ICON);
|
||||||
searchResetIcon.togleIcon(FontAwesome.SEARCH);
|
searchResetIcon.toggleIcon(FontAwesome.SEARCH);
|
||||||
searchResetIcon.setData(Boolean.FALSE);
|
searchResetIcon.setData(Boolean.FALSE);
|
||||||
|
|
||||||
resetSearchText();
|
resetSearchText();
|
||||||
|
|||||||
@@ -1,96 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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.common.grid;
|
|
||||||
|
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
|
||||||
|
|
||||||
import com.vaadin.ui.Alignment;
|
|
||||||
import com.vaadin.ui.HorizontalLayout;
|
|
||||||
import com.vaadin.ui.Label;
|
|
||||||
import com.vaadin.ui.VerticalLayout;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Abstract grid layout class which builds layout with grid {@link AbstractGrid}
|
|
||||||
* and table header {@link AbstractGridHeader}.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public abstract class AbstractGridLayout extends VerticalLayout {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 8611248179949245460L;
|
|
||||||
|
|
||||||
private final AbstractGridHeader tableHeader;
|
|
||||||
|
|
||||||
protected final AbstractGrid grid;
|
|
||||||
|
|
||||||
protected AbstractGridLayout(final AbstractGridHeader tableHeader, final AbstractGrid grid) {
|
|
||||||
this.tableHeader = tableHeader;
|
|
||||||
this.grid = grid;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void buildLayout() {
|
|
||||||
setSizeFull();
|
|
||||||
setSpacing(true);
|
|
||||||
setMargin(false);
|
|
||||||
setStyleName("group");
|
|
||||||
final VerticalLayout tableHeaderLayout = new VerticalLayout();
|
|
||||||
tableHeaderLayout.setSizeFull();
|
|
||||||
tableHeaderLayout.setSpacing(false);
|
|
||||||
tableHeaderLayout.setMargin(false);
|
|
||||||
|
|
||||||
tableHeaderLayout.setStyleName("table-layout");
|
|
||||||
tableHeaderLayout.addComponent(tableHeader);
|
|
||||||
|
|
||||||
tableHeaderLayout.setComponentAlignment(tableHeader, Alignment.TOP_CENTER);
|
|
||||||
tableHeaderLayout.addComponent(grid);
|
|
||||||
tableHeaderLayout.setComponentAlignment(grid, Alignment.TOP_CENTER);
|
|
||||||
tableHeaderLayout.setExpandRatio(grid, 1.0F);
|
|
||||||
|
|
||||||
addComponent(tableHeaderLayout);
|
|
||||||
setComponentAlignment(tableHeaderLayout, Alignment.TOP_CENTER);
|
|
||||||
setExpandRatio(tableHeaderLayout, 1.0F);
|
|
||||||
if (hasCountMessage()) {
|
|
||||||
final HorizontalLayout rolloutGroupTargetsCountLayout = createCountMessageComponent();
|
|
||||||
addComponent(rolloutGroupTargetsCountLayout);
|
|
||||||
setComponentAlignment(rolloutGroupTargetsCountLayout, Alignment.BOTTOM_CENTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private HorizontalLayout createCountMessageComponent() {
|
|
||||||
final HorizontalLayout rolloutGroupTargetsCountLayout = new HorizontalLayout();
|
|
||||||
final Label countMessageLabel = getCountMessageLabel();
|
|
||||||
countMessageLabel.setId(UIComponentIdProvider.ROLLOUT_GROUP_TARGET_LABEL);
|
|
||||||
rolloutGroupTargetsCountLayout.addComponent(getCountMessageLabel());
|
|
||||||
rolloutGroupTargetsCountLayout.setStyleName(SPUIStyleDefinitions.FOOTER_LAYOUT);
|
|
||||||
rolloutGroupTargetsCountLayout.setWidth("100%");
|
|
||||||
return rolloutGroupTargetsCountLayout;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Only in rollout group targets view count message is displayed.
|
|
||||||
*
|
|
||||||
* @return true if count message has to be displayed
|
|
||||||
*/
|
|
||||||
protected abstract boolean hasCountMessage();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the count message label.
|
|
||||||
*
|
|
||||||
* @return count message
|
|
||||||
*/
|
|
||||||
protected abstract Label getCountMessageLabel();
|
|
||||||
|
|
||||||
public AbstractGrid getGrid() {
|
|
||||||
return grid;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,243 @@
|
|||||||
|
/**
|
||||||
|
* 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.common.grid;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
|
||||||
|
import org.eclipse.hawkbit.ui.components.SPUIButton;
|
||||||
|
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||||
|
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
||||||
|
import org.eclipse.hawkbit.ui.management.state.ManagementUIState;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
||||||
|
|
||||||
|
import com.vaadin.server.FontAwesome;
|
||||||
|
import com.vaadin.shared.ui.label.ContentMode;
|
||||||
|
import com.vaadin.ui.Alignment;
|
||||||
|
import com.vaadin.ui.HorizontalLayout;
|
||||||
|
import com.vaadin.ui.Label;
|
||||||
|
import com.vaadin.ui.VerticalLayout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract grid header placed on top of a grid.
|
||||||
|
*/
|
||||||
|
public class DefaultGridHeader extends VerticalLayout {
|
||||||
|
private static final long serialVersionUID = 1921798400953670917L;
|
||||||
|
|
||||||
|
private final ManagementUIState managementUIState;
|
||||||
|
|
||||||
|
private final String titleText;
|
||||||
|
private Label title;
|
||||||
|
private HorizontalLayout titleLayout;
|
||||||
|
private transient AbstractHeaderMaximizeSupport maximizeSupport;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param managementUIState
|
||||||
|
*/
|
||||||
|
public DefaultGridHeader(final ManagementUIState managementUIState) {
|
||||||
|
this(managementUIState, StringUtils.EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param managementUIState
|
||||||
|
* @param titleText
|
||||||
|
*/
|
||||||
|
public DefaultGridHeader(final ManagementUIState managementUIState, final String titleText) {
|
||||||
|
this.managementUIState = managementUIState;
|
||||||
|
this.titleText = titleText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the header.
|
||||||
|
*
|
||||||
|
* @return this DefaultGridHeader in order to allow method chaining
|
||||||
|
*/
|
||||||
|
public DefaultGridHeader init() {
|
||||||
|
buildTitleLabel();
|
||||||
|
buildTitleLayout();
|
||||||
|
buildComponent();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the title label.
|
||||||
|
*
|
||||||
|
* @return title-label
|
||||||
|
*/
|
||||||
|
protected Label buildTitleLabel() {
|
||||||
|
// create default title - even shown when no data is available
|
||||||
|
title = new LabelBuilder().name(titleText).buildCaptionLabel();
|
||||||
|
title.setImmediate(true);
|
||||||
|
title.setContentMode(ContentMode.HTML);
|
||||||
|
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the title layout.
|
||||||
|
*
|
||||||
|
* @return title-layout
|
||||||
|
*/
|
||||||
|
protected HorizontalLayout buildTitleLayout() {
|
||||||
|
titleLayout = new HorizontalLayout();
|
||||||
|
titleLayout.addStyleName(SPUIStyleDefinitions.WIDGET_TITLE);
|
||||||
|
titleLayout.setSpacing(false);
|
||||||
|
titleLayout.setMargin(false);
|
||||||
|
titleLayout.setSizeFull();
|
||||||
|
titleLayout.addComponent(title);
|
||||||
|
titleLayout.setComponentAlignment(title, Alignment.TOP_LEFT);
|
||||||
|
titleLayout.setExpandRatio(title, 0.8F);
|
||||||
|
|
||||||
|
if (hasHeaderMaximizeSupport()) {
|
||||||
|
titleLayout.addComponents(getHeaderMaximizeSupport().maxMinButton);
|
||||||
|
titleLayout.setComponentAlignment(getHeaderMaximizeSupport().maxMinButton, Alignment.TOP_RIGHT);
|
||||||
|
titleLayout.setExpandRatio(getHeaderMaximizeSupport().maxMinButton, 0.2F);
|
||||||
|
}
|
||||||
|
|
||||||
|
return titleLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the layout for the header component.
|
||||||
|
*/
|
||||||
|
protected void buildComponent() {
|
||||||
|
addComponent(titleLayout);
|
||||||
|
setComponentAlignment(titleLayout, Alignment.TOP_LEFT);
|
||||||
|
setWidth(100, Unit.PERCENTAGE);
|
||||||
|
setImmediate(true);
|
||||||
|
addStyleName("action-history-header");
|
||||||
|
addStyleName("bordered-layout");
|
||||||
|
addStyleName("no-border-bottom");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables maximize-support for the header by setting a
|
||||||
|
* HeaderMaximizeSupport implementation.
|
||||||
|
*
|
||||||
|
* @param maximizeSupport
|
||||||
|
* encapsulates layout of min-max-button and behavior for
|
||||||
|
* minimize and maximize.
|
||||||
|
*/
|
||||||
|
public void setHeaderMaximizeSupport(final AbstractHeaderMaximizeSupport maximizeSupport) {
|
||||||
|
this.maximizeSupport = maximizeSupport;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the HeaderMaximizeSupport implementation describing behavior for
|
||||||
|
* minimize and maximize.
|
||||||
|
*
|
||||||
|
* @return maximizeSupport that encapsulates behavior for minimize and
|
||||||
|
* maximize.
|
||||||
|
*/
|
||||||
|
public AbstractHeaderMaximizeSupport getHeaderMaximizeSupport() {
|
||||||
|
return maximizeSupport;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether maximize-support is enabled.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if maximize-support is enabled, otherwise
|
||||||
|
* <code>false</code>
|
||||||
|
*/
|
||||||
|
public boolean hasHeaderMaximizeSupport() {
|
||||||
|
return maximizeSupport != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the title of the header.
|
||||||
|
*
|
||||||
|
* @param newTitle
|
||||||
|
*/
|
||||||
|
public void updateTitle(final String newTitle) {
|
||||||
|
title.setValue(newTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Implemented capability offers a button that triggers minimization and
|
||||||
|
* maximization.
|
||||||
|
*/
|
||||||
|
public abstract class AbstractHeaderMaximizeSupport {
|
||||||
|
|
||||||
|
private final SPUIButton maxMinButton;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param maximizeButtonId
|
||||||
|
*/
|
||||||
|
protected AbstractHeaderMaximizeSupport(final String maximizeButtonId) {
|
||||||
|
maxMinButton = createMinMaxButton(maximizeButtonId);
|
||||||
|
// listener for maximizing action history
|
||||||
|
maxMinButton.addClickListener(event -> maxMinButtonClicked());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked when min-max-button is pressed.
|
||||||
|
*/
|
||||||
|
private void maxMinButtonClicked() {
|
||||||
|
final Boolean flag = (Boolean) maxMinButton.getData();
|
||||||
|
if (flag == null || Boolean.FALSE.equals(flag)) {
|
||||||
|
// Clicked on max Icon
|
||||||
|
showMinIcon();
|
||||||
|
maximize();
|
||||||
|
managementUIState.setActionHistoryMaximized(true);
|
||||||
|
} else {
|
||||||
|
// Clicked on min icon
|
||||||
|
showMaxIcon();
|
||||||
|
minimize();
|
||||||
|
managementUIState.setActionHistoryMaximized(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Additional actions for maximize operation might be performed by this
|
||||||
|
* method.
|
||||||
|
*/
|
||||||
|
protected abstract void maximize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Additional actions for minimize operation might be performed by this
|
||||||
|
* method.
|
||||||
|
*/
|
||||||
|
protected abstract void minimize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a min-max-button instance.
|
||||||
|
*
|
||||||
|
* @param buttonId
|
||||||
|
* the button id for the min-max-button
|
||||||
|
* @return newly cretaed min-max-button
|
||||||
|
*/
|
||||||
|
protected SPUIButton createMinMaxButton(final String buttonId) {
|
||||||
|
return (SPUIButton) SPUIComponentProvider.getButton(buttonId, "", "Maximize", null, true,
|
||||||
|
FontAwesome.EXPAND, SPUIButtonStyleSmallNoBorder.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Styles min-max-button icon with minimize decoration
|
||||||
|
*/
|
||||||
|
public void showMinIcon() {
|
||||||
|
maxMinButton.toggleIcon(FontAwesome.COMPRESS);
|
||||||
|
maxMinButton.setDescription("Minimize");
|
||||||
|
maxMinButton.setData(Boolean.TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Styles min-max-button icon with maximize decoration
|
||||||
|
*/
|
||||||
|
public void showMaxIcon() {
|
||||||
|
maxMinButton.toggleIcon(FontAwesome.EXPAND);
|
||||||
|
maxMinButton.setDescription("Maximize");
|
||||||
|
maxMinButton.setData(Boolean.FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -258,7 +258,7 @@ public abstract class AbstractTableHeader extends VerticalLayout {
|
|||||||
|
|
||||||
private void openSearchTextField() {
|
private void openSearchTextField() {
|
||||||
searchResetIcon.addStyleName(SPUIDefinitions.FILTER_RESET_ICON);
|
searchResetIcon.addStyleName(SPUIDefinitions.FILTER_RESET_ICON);
|
||||||
searchResetIcon.togleIcon(FontAwesome.TIMES);
|
searchResetIcon.toggleIcon(FontAwesome.TIMES);
|
||||||
searchResetIcon.setData(Boolean.TRUE);
|
searchResetIcon.setData(Boolean.TRUE);
|
||||||
searchField.removeStyleName(SPUIDefinitions.FILTER_BOX_HIDE);
|
searchField.removeStyleName(SPUIDefinitions.FILTER_BOX_HIDE);
|
||||||
searchField.focus();
|
searchField.focus();
|
||||||
@@ -268,7 +268,7 @@ public abstract class AbstractTableHeader extends VerticalLayout {
|
|||||||
searchField.setValue("");
|
searchField.setValue("");
|
||||||
searchField.addStyleName(SPUIDefinitions.FILTER_BOX_HIDE);
|
searchField.addStyleName(SPUIDefinitions.FILTER_BOX_HIDE);
|
||||||
searchResetIcon.removeStyleName(SPUIDefinitions.FILTER_RESET_ICON);
|
searchResetIcon.removeStyleName(SPUIDefinitions.FILTER_RESET_ICON);
|
||||||
searchResetIcon.togleIcon(FontAwesome.SEARCH);
|
searchResetIcon.toggleIcon(FontAwesome.SEARCH);
|
||||||
searchResetIcon.setData(Boolean.FALSE);
|
searchResetIcon.setData(Boolean.FALSE);
|
||||||
resetSearchText();
|
resetSearchText();
|
||||||
}
|
}
|
||||||
@@ -297,12 +297,12 @@ public abstract class AbstractTableHeader extends VerticalLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void showMinIcon() {
|
private void showMinIcon() {
|
||||||
maxMinIcon.togleIcon(FontAwesome.COMPRESS);
|
maxMinIcon.toggleIcon(FontAwesome.COMPRESS);
|
||||||
maxMinIcon.setData(Boolean.TRUE);
|
maxMinIcon.setData(Boolean.TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showMaxIcon() {
|
private void showMaxIcon() {
|
||||||
maxMinIcon.togleIcon(FontAwesome.EXPAND);
|
maxMinIcon.toggleIcon(FontAwesome.EXPAND);
|
||||||
maxMinIcon.setData(Boolean.FALSE);
|
maxMinIcon.setData(Boolean.FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public class BaseUIEntityEvent<T extends BaseEntity> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Base entity event
|
* Base entity event
|
||||||
*
|
*
|
||||||
* @param eventType
|
* @param eventType
|
||||||
* the event type
|
* the event type
|
||||||
* @param entity
|
* @param entity
|
||||||
@@ -55,7 +55,7 @@ public class BaseUIEntityEvent<T extends BaseEntity> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Base entity event
|
* Base entity event
|
||||||
*
|
*
|
||||||
* @param eventType
|
* @param eventType
|
||||||
* the event type
|
* the event type
|
||||||
* @param entityIds
|
* @param entityIds
|
||||||
@@ -74,6 +74,10 @@ public class BaseUIEntityEvent<T extends BaseEntity> {
|
|||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<Long> getEntityIds() {
|
||||||
|
return entityIds;
|
||||||
|
}
|
||||||
|
|
||||||
public BaseEntityEventType getEventType() {
|
public BaseEntityEventType getEventType() {
|
||||||
return eventType;
|
return eventType;
|
||||||
}
|
}
|
||||||
@@ -81,7 +85,7 @@ public class BaseUIEntityEvent<T extends BaseEntity> {
|
|||||||
/**
|
/**
|
||||||
* Checks if the remote event is the same as this UI event. Then maybe you
|
* Checks if the remote event is the same as this UI event. Then maybe you
|
||||||
* can skip the remote event because it is already executed.
|
* can skip the remote event because it is already executed.
|
||||||
*
|
*
|
||||||
* @param tenantAwareEvent
|
* @param tenantAwareEvent
|
||||||
* the remote event
|
* the remote event
|
||||||
* @return {@code true} match ; {@code false} not match
|
* @return {@code true} match ; {@code false} not match
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ public class NotificationUnreadButton extends Button {
|
|||||||
notificationsWindow.setClosable(true);
|
notificationsWindow.setClosable(true);
|
||||||
notificationsWindow.setResizable(false);
|
notificationsWindow.setResizable(false);
|
||||||
notificationsWindow.setDraggable(false);
|
notificationsWindow.setDraggable(false);
|
||||||
notificationsWindow.setId(UIComponentIdProvider.NOTIFICATION_UNREAD_POPUP_id);
|
notificationsWindow.setId(UIComponentIdProvider.NOTIFICATION_UNREAD_POPUP_ID);
|
||||||
notificationsWindow.addCloseListener(event -> refreshCaption());
|
notificationsWindow.addCloseListener(event -> refreshCaption());
|
||||||
notificationsWindow.addBlurListener(this::closeWindow);
|
notificationsWindow.addBlurListener(this::closeWindow);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,12 +27,12 @@ public class SPUIButton extends Button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toogle Icon on action.
|
* Toggle Icon on action.
|
||||||
*
|
*
|
||||||
* @param icon
|
* @param icon
|
||||||
* as Resource
|
* as Resource
|
||||||
*/
|
*/
|
||||||
public void togleIcon(final Resource icon) {
|
public void toggleIcon(final Resource icon) {
|
||||||
setIcon(icon);
|
setIcon(icon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* 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.customrenderers.client;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.ui.customrenderers.client.renderers.FontIconData;
|
||||||
|
|
||||||
|
import com.google.web.bindery.event.shared.HandlerRegistration;
|
||||||
|
import com.vaadin.client.connectors.ClickableRendererConnector;
|
||||||
|
import com.vaadin.client.renderers.ClickableRenderer.RendererClickHandler;
|
||||||
|
import com.vaadin.shared.ui.Connect;
|
||||||
|
|
||||||
|
import elemental.json.JsonObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A connector for {@link GridButtonRenderer }.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Connect(org.eclipse.hawkbit.ui.customrenderers.renderers.GridButtonRenderer.class)
|
||||||
|
public class GridButtonRendererConnector extends ClickableRendererConnector<FontIconData> {
|
||||||
|
private static final long serialVersionUID = 7987417436367399331L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public org.eclipse.hawkbit.ui.customrenderers.client.renderers.GridButtonRenderer getRenderer() {
|
||||||
|
return (org.eclipse.hawkbit.ui.customrenderers.client.renderers.GridButtonRenderer) super.getRenderer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected HandlerRegistration addClickHandler(final RendererClickHandler<JsonObject> handler) {
|
||||||
|
return getRenderer().addClickHandler(handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
/**
|
||||||
|
* 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.customrenderers.client.renderers;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data class that transports the icon meta-data to client-side renderer.
|
||||||
|
*/
|
||||||
|
public class FontIconData implements Serializable {
|
||||||
|
|
||||||
|
/** serialVersionUID. */
|
||||||
|
private static final long serialVersionUID = 5823318280700107049L;
|
||||||
|
private String fontIconHtml;
|
||||||
|
private String style;
|
||||||
|
private String title;
|
||||||
|
private String id;
|
||||||
|
private boolean disabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the html representing the icon.
|
||||||
|
*
|
||||||
|
* @return the html representing the icon
|
||||||
|
*/
|
||||||
|
public String getFontIconHtml() {
|
||||||
|
return fontIconHtml;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the html representing the icon.
|
||||||
|
*
|
||||||
|
* @param fontIconHtml
|
||||||
|
* html representing the icon
|
||||||
|
*/
|
||||||
|
public void setFontIconHtml(String fontIconHtml) {
|
||||||
|
this.fontIconHtml = fontIconHtml;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the style.
|
||||||
|
*
|
||||||
|
* @return the style
|
||||||
|
*/
|
||||||
|
public String getStyle() {
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the style.
|
||||||
|
*
|
||||||
|
* @param style
|
||||||
|
* icon style
|
||||||
|
*/
|
||||||
|
public void setStyle(String style) {
|
||||||
|
this.style = style;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the title shown as tooltip.
|
||||||
|
*
|
||||||
|
* @return the title shown as tooltip.
|
||||||
|
*/
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the title shown as tooltip.
|
||||||
|
*
|
||||||
|
* @param title
|
||||||
|
* shown as tooltip.
|
||||||
|
*/
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the id for direct access.
|
||||||
|
*
|
||||||
|
* @return the id for direct access.
|
||||||
|
*/
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the id for direct access.
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* for direct access.
|
||||||
|
*/
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the disabled-state of the icon.
|
||||||
|
*
|
||||||
|
* @return the disabled-state of the icon.
|
||||||
|
*/
|
||||||
|
public boolean isDisabled() {
|
||||||
|
return disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the disabled-state of the icon.
|
||||||
|
*
|
||||||
|
* @param disabled
|
||||||
|
* disabled-state of the icon.
|
||||||
|
*/
|
||||||
|
public void setDisabled(boolean disabled) {
|
||||||
|
this.disabled = disabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/**
|
||||||
|
* 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.customrenderers.client.renderers;
|
||||||
|
|
||||||
|
import com.google.gwt.core.shared.GWT;
|
||||||
|
import com.google.gwt.user.client.ui.Button;
|
||||||
|
import com.vaadin.client.renderers.ClickableRenderer;
|
||||||
|
import com.vaadin.client.ui.VButton;
|
||||||
|
import com.vaadin.client.widget.grid.RendererCellReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders button with provided HTML content. Used to display button with icons.
|
||||||
|
*/
|
||||||
|
public class GridButtonRenderer extends ClickableRenderer<FontIconData, Button> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Button createWidget() {
|
||||||
|
Button b = GWT.create(Button.class);
|
||||||
|
b.addClickHandler(this);
|
||||||
|
b.setStylePrimaryName("v-nativebutton");
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(final RendererCellReference cell, final FontIconData iconMetadata, final Button button) {
|
||||||
|
if (iconMetadata.getFontIconHtml() != null) {
|
||||||
|
button.setHTML(iconMetadata.getFontIconHtml());
|
||||||
|
}
|
||||||
|
applyStyles(button, iconMetadata.isDisabled(), iconMetadata.getStyle());
|
||||||
|
button.getElement().setId(iconMetadata.getId());
|
||||||
|
button.getElement().setTitle(iconMetadata.getTitle());
|
||||||
|
button.setEnabled(!iconMetadata.isDisabled());
|
||||||
|
// this is to allow the button to disappear, if the text is null
|
||||||
|
button.setVisible(iconMetadata.getFontIconHtml() != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void applyStyles(final Button button, final boolean buttonDisabled, final String additionalStyle) {
|
||||||
|
|
||||||
|
button.setStyleName(VButton.CLASSNAME);
|
||||||
|
button.addStyleName(getStyle("tiny"));
|
||||||
|
button.addStyleName(getStyle("borderless"));
|
||||||
|
button.addStyleName(getStyle("button-no-border"));
|
||||||
|
button.addStyleName(getStyle("action-type-padding"));
|
||||||
|
button.addStyleName(getStyle(additionalStyle));
|
||||||
|
|
||||||
|
if (buttonDisabled) {
|
||||||
|
button.addStyleName("v-disabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getStyle(final String style) {
|
||||||
|
return new StringBuilder(style).append(" ").append(VButton.CLASSNAME).append("-").append(style).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -17,7 +17,7 @@ import com.vaadin.client.ui.VLabel;
|
|||||||
import com.vaadin.client.widget.grid.RendererCellReference;
|
import com.vaadin.client.widget.grid.RendererCellReference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Renders label with provided value and style.
|
* Renders label with provided value and style.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@@ -33,6 +33,7 @@ public class HtmlLabelRenderer extends WidgetRenderer<String, VLabel> {
|
|||||||
Map<String, String> map = formatInput(input);
|
Map<String, String> map = formatInput(input);
|
||||||
String value = map.containsKey("value") ? map.get("value") : null;
|
String value = map.containsKey("value") ? map.get("value") : null;
|
||||||
String style = map.containsKey("style") ? map.get("style") : null;
|
String style = map.containsKey("style") ? map.get("style") : null;
|
||||||
|
String title = map.containsKey("title") ? map.get("title") : null;
|
||||||
String id = map.containsKey("id") ? map.get("id") : null;
|
String id = map.containsKey("id") ? map.get("id") : null;
|
||||||
|
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
@@ -42,6 +43,7 @@ public class HtmlLabelRenderer extends WidgetRenderer<String, VLabel> {
|
|||||||
}
|
}
|
||||||
applyStyle(label, style);
|
applyStyle(label, style);
|
||||||
label.getElement().setId(id);
|
label.getElement().setId(id);
|
||||||
|
label.getElement().setTitle(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyStyle(VLabel label, String style) {
|
private void applyStyle(VLabel label, String style) {
|
||||||
@@ -57,7 +59,7 @@ public class HtmlLabelRenderer extends WidgetRenderer<String, VLabel> {
|
|||||||
return new StringBuilder(style).append(" ").append(VLabel.CLASSNAME).append("-").append(style).toString();
|
return new StringBuilder(style).append(" ").append(VLabel.CLASSNAME).append("-").append(style).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, String> formatInput(String input) {
|
private static Map<String, String> formatInput(String input) {
|
||||||
Map<String, String> details = new HashMap<>();
|
Map<String, String> details = new HashMap<>();
|
||||||
String[] tempData = input.split(",");
|
String[] tempData = input.split(",");
|
||||||
for (String statusWithCount : tempData) {
|
for (String statusWithCount : tempData) {
|
||||||
|
|||||||
@@ -0,0 +1,101 @@
|
|||||||
|
/**
|
||||||
|
* 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.customrenderers.renderers;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.ui.customrenderers.client.renderers.FontIconData;
|
||||||
|
import org.eclipse.hawkbit.ui.rollout.StatusFontIcon;
|
||||||
|
|
||||||
|
import com.vaadin.data.util.converter.Converter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converter that adapts to a model and converts to a grid-button presentation.
|
||||||
|
*
|
||||||
|
* @param <T>
|
||||||
|
* The type the converter adapts to
|
||||||
|
*/
|
||||||
|
public abstract class AbstractGridButtonConverter<T> implements Converter<FontIconData, T> {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private GridButtonAdapter<T> adapter;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T convertToModel(final FontIconData meta, final Class<? extends T> targetType, final Locale locale) {
|
||||||
|
// not needed
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FontIconData convertToPresentation(final T status, final Class<? extends FontIconData> targetType,
|
||||||
|
final Locale locale) {
|
||||||
|
if (adapter == null) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Adapter must be set before usage! Convertion without adapter is not possible!");
|
||||||
|
}
|
||||||
|
return createFontIconData(adapter.adapt(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a data transport object for the icon meta data.
|
||||||
|
*
|
||||||
|
* @param meta
|
||||||
|
* icon metadata
|
||||||
|
* @return icon metadata transport object
|
||||||
|
*/
|
||||||
|
private static FontIconData createFontIconData(StatusFontIcon meta) {
|
||||||
|
FontIconData result = new FontIconData();
|
||||||
|
result.setFontIconHtml(meta.getFontIcon().getHtml());
|
||||||
|
result.setTitle(meta.getTitle());
|
||||||
|
result.setStyle(meta.getStyle());
|
||||||
|
result.setId(meta.getId());
|
||||||
|
result.setDisabled(meta.isDisabled());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<FontIconData> getPresentationType() {
|
||||||
|
return FontIconData.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an appropriate adapter to the converter. The adapter is mandatory
|
||||||
|
* for the converter.
|
||||||
|
*
|
||||||
|
* @param adapter
|
||||||
|
* label-adapter that converts from model to label-presentation.
|
||||||
|
* @return self for method-chaining
|
||||||
|
*/
|
||||||
|
public AbstractGridButtonConverter<T> addAdapter(GridButtonAdapter<T> adapter) {
|
||||||
|
this.adapter = adapter;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapts from model data to presentation data.
|
||||||
|
*
|
||||||
|
* @param <T>
|
||||||
|
* The type to adapt to
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface GridButtonAdapter<T> extends Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param status
|
||||||
|
* model data
|
||||||
|
* @return meta representation that is used as input for label
|
||||||
|
* generation.
|
||||||
|
*/
|
||||||
|
StatusFontIcon adapt(final T status);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
/**
|
||||||
|
* 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.customrenderers.renderers;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.ui.rollout.StatusFontIcon;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import com.vaadin.data.util.converter.Converter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converter that adapts to a model and converts to a label presentation.
|
||||||
|
*
|
||||||
|
* @param <T>
|
||||||
|
* The type the converter adapts to
|
||||||
|
*/
|
||||||
|
public abstract class AbstractHtmlLabelConverter<T> implements Converter<String, T> {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private LabelAdapter<T> adapter;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T convertToModel(final String value, final Class<? extends T> targetType, final Locale locale) {
|
||||||
|
// not needed
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String convertToPresentation(final T status, final Class<? extends String> targetType, final Locale locale) {
|
||||||
|
return convert(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<String> getPresentationType() {
|
||||||
|
return String.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an appropriate adapter to the converter. The adapter is mandatory
|
||||||
|
* for the converter.
|
||||||
|
*
|
||||||
|
* @param adapter
|
||||||
|
* label-adapter that converts from model to label-presentation.
|
||||||
|
* @return self for method-chaining
|
||||||
|
*/
|
||||||
|
public AbstractHtmlLabelConverter<T> addAdapter(LabelAdapter<T> adapter) {
|
||||||
|
this.adapter = adapter;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the model data to a string representation of the presentation
|
||||||
|
* label that is used on client-side to style the label.
|
||||||
|
*
|
||||||
|
* @param status
|
||||||
|
* model data
|
||||||
|
* @return string representation of label
|
||||||
|
*/
|
||||||
|
private String convert(final T status) {
|
||||||
|
if (adapter == null) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Adapter must be set before usage! Convertion without adapter is not possible!");
|
||||||
|
}
|
||||||
|
final StatusFontIcon statusProps = adapter.adapt(status);
|
||||||
|
// fail fast
|
||||||
|
if (statusProps == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
final String codePoint = getCodePoint(statusProps);
|
||||||
|
final String title = statusProps.getTitle();
|
||||||
|
return getStatusLabelDetailsInString(codePoint, statusProps.getStyle(), title, statusProps.getId(),
|
||||||
|
statusProps.isDisabled());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a key:value map represented by a comma-separated list.
|
||||||
|
*
|
||||||
|
* @param fontIcon
|
||||||
|
* the font representing the icon
|
||||||
|
* @param style
|
||||||
|
* the style
|
||||||
|
* @param title
|
||||||
|
* the title shown as tooltip
|
||||||
|
* @param id
|
||||||
|
* the id for direct access
|
||||||
|
* @param disabled
|
||||||
|
* disabled-state of the icon
|
||||||
|
* @return string representation of key:value map
|
||||||
|
*/
|
||||||
|
private static String getStatusLabelDetailsInString(final String value, final String style, final String title,
|
||||||
|
final String id, boolean disabled) {
|
||||||
|
final StringBuilder val = new StringBuilder();
|
||||||
|
if (!Strings.isNullOrEmpty(value)) {
|
||||||
|
val.append("value:").append(value).append(",");
|
||||||
|
}
|
||||||
|
if (!Strings.isNullOrEmpty(style)) {
|
||||||
|
val.append("style:").append(style).append(",");
|
||||||
|
}
|
||||||
|
if (!Strings.isNullOrEmpty(title)) {
|
||||||
|
val.append("title:").append(title).append(",");
|
||||||
|
}
|
||||||
|
if (disabled) {
|
||||||
|
val.append("disabled:true").append(",");
|
||||||
|
}
|
||||||
|
return val.append("id:").append(id).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the codepoint from the font-icon.
|
||||||
|
*
|
||||||
|
* @param statusFontIcon
|
||||||
|
* the label-metadata that holds the font-icon
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static String getCodePoint(final StatusFontIcon statusFontIcon) {
|
||||||
|
return statusFontIcon.getFontIcon() != null ? Integer.toString(statusFontIcon.getFontIcon().getCodepoint())
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapts from model data to presentation data.
|
||||||
|
*
|
||||||
|
* @param <T>
|
||||||
|
* The type to adapt to
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface LabelAdapter<T> extends Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param status
|
||||||
|
* model data
|
||||||
|
* @return meta representation that is used as input for label
|
||||||
|
* generation.
|
||||||
|
*/
|
||||||
|
StatusFontIcon adapt(final T status);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/**
|
||||||
|
* 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.customrenderers.renderers;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.ui.customrenderers.client.renderers.FontIconData;
|
||||||
|
import com.vaadin.ui.renderers.ClickableRenderer;
|
||||||
|
import elemental.json.JsonValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders buttons for a grid with provided HTML content based on meta-data.
|
||||||
|
* Used to display button with icons.
|
||||||
|
*/
|
||||||
|
public class GridButtonRenderer extends ClickableRenderer<FontIconData> {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*/
|
||||||
|
public GridButtonRenderer() {
|
||||||
|
super(FontIconData.class, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new custom object renderer and adds the given click listener to
|
||||||
|
* it.
|
||||||
|
*
|
||||||
|
* @param listener
|
||||||
|
* the click listener to register
|
||||||
|
*/
|
||||||
|
public GridButtonRenderer(final RendererClickListener listener) {
|
||||||
|
this();
|
||||||
|
addClickListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize custom object renderer with the given type.
|
||||||
|
*
|
||||||
|
* @param presentationType
|
||||||
|
* Class<CustomObject>
|
||||||
|
*/
|
||||||
|
|
||||||
|
public GridButtonRenderer(final Class<FontIconData> presentationType) {
|
||||||
|
super(presentationType);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonValue encode(final FontIconData resource) {
|
||||||
|
return super.encode(resource, FontIconData.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ package org.eclipse.hawkbit.ui.customrenderers.renderers;
|
|||||||
import com.vaadin.ui.Grid.AbstractRenderer;
|
import com.vaadin.ui.Grid.AbstractRenderer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Renders label with provided value and style.
|
* Renders label with provided value and style.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ public class TargetFilterHeader extends VerticalLayout {
|
|||||||
|
|
||||||
private void openSearchTextField() {
|
private void openSearchTextField() {
|
||||||
searchResetIcon.addStyleName(SPUIDefinitions.FILTER_RESET_ICON);
|
searchResetIcon.addStyleName(SPUIDefinitions.FILTER_RESET_ICON);
|
||||||
searchResetIcon.togleIcon(FontAwesome.TIMES);
|
searchResetIcon.toggleIcon(FontAwesome.TIMES);
|
||||||
searchResetIcon.setData(Boolean.TRUE);
|
searchResetIcon.setData(Boolean.TRUE);
|
||||||
searchField.removeStyleName(SPUIDefinitions.FILTER_BOX_HIDE);
|
searchField.removeStyleName(SPUIDefinitions.FILTER_BOX_HIDE);
|
||||||
searchField.setVisible(true);
|
searchField.setVisible(true);
|
||||||
@@ -165,7 +165,7 @@ public class TargetFilterHeader extends VerticalLayout {
|
|||||||
searchField.setValue("");
|
searchField.setValue("");
|
||||||
searchField.addStyleName(SPUIDefinitions.FILTER_BOX_HIDE);
|
searchField.addStyleName(SPUIDefinitions.FILTER_BOX_HIDE);
|
||||||
searchResetIcon.removeStyleName(SPUIDefinitions.FILTER_RESET_ICON);
|
searchResetIcon.removeStyleName(SPUIDefinitions.FILTER_RESET_ICON);
|
||||||
searchResetIcon.togleIcon(FontAwesome.SEARCH);
|
searchResetIcon.toggleIcon(FontAwesome.SEARCH);
|
||||||
searchResetIcon.setData(Boolean.FALSE);
|
searchResetIcon.setData(Boolean.FALSE);
|
||||||
resetSearchText();
|
resetSearchText();
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,11 @@ import org.eclipse.hawkbit.ui.components.AbstractNotificationView;
|
|||||||
import org.eclipse.hawkbit.ui.components.NotificationUnreadButton;
|
import org.eclipse.hawkbit.ui.components.NotificationUnreadButton;
|
||||||
import org.eclipse.hawkbit.ui.components.RefreshableContainer;
|
import org.eclipse.hawkbit.ui.components.RefreshableContainer;
|
||||||
import org.eclipse.hawkbit.ui.dd.criteria.ManagementViewClientCriterion;
|
import org.eclipse.hawkbit.ui.dd.criteria.ManagementViewClientCriterion;
|
||||||
import org.eclipse.hawkbit.ui.management.actionhistory.ActionHistoryComponent;
|
import org.eclipse.hawkbit.ui.management.actionhistory.ActionHistoryLayout;
|
||||||
|
import org.eclipse.hawkbit.ui.management.actionhistory.ActionStatusGrid;
|
||||||
|
import org.eclipse.hawkbit.ui.management.actionhistory.ActionStatusLayout;
|
||||||
|
import org.eclipse.hawkbit.ui.management.actionhistory.ActionStatusMsgGrid;
|
||||||
|
import org.eclipse.hawkbit.ui.management.actionhistory.ActionStatusMsgLayout;
|
||||||
import org.eclipse.hawkbit.ui.management.dstable.DistributionTableLayout;
|
import org.eclipse.hawkbit.ui.management.dstable.DistributionTableLayout;
|
||||||
import org.eclipse.hawkbit.ui.management.dstag.DistributionTagLayout;
|
import org.eclipse.hawkbit.ui.management.dstag.DistributionTagLayout;
|
||||||
import org.eclipse.hawkbit.ui.management.event.DistributionTableEvent;
|
import org.eclipse.hawkbit.ui.management.event.DistributionTableEvent;
|
||||||
@@ -89,7 +93,11 @@ public class DeploymentView extends AbstractNotificationView implements BrowserW
|
|||||||
|
|
||||||
private final ManagementUIState managementUIState;
|
private final ManagementUIState managementUIState;
|
||||||
|
|
||||||
private final ActionHistoryComponent actionHistoryComponent;
|
private final ActionHistoryLayout actionHistoryLayout;
|
||||||
|
|
||||||
|
private final ActionStatusLayout actionStatusLayout;
|
||||||
|
|
||||||
|
private final ActionStatusMsgLayout actionStatusMsgLayout;
|
||||||
|
|
||||||
private final TargetTagFilterLayout targetTagFilterLayout;
|
private final TargetTagFilterLayout targetTagFilterLayout;
|
||||||
|
|
||||||
@@ -97,7 +105,7 @@ public class DeploymentView extends AbstractNotificationView implements BrowserW
|
|||||||
|
|
||||||
private final DistributionTagLayout distributionTagLayout;
|
private final DistributionTagLayout distributionTagLayout;
|
||||||
|
|
||||||
private final DistributionTableLayout distributionTableLayoutNew;
|
private final DistributionTableLayout distributionTableLayout;
|
||||||
|
|
||||||
private final DeleteActionsLayout deleteAndActionsLayout;
|
private final DeleteActionsLayout deleteAndActionsLayout;
|
||||||
|
|
||||||
@@ -121,8 +129,10 @@ public class DeploymentView extends AbstractNotificationView implements BrowserW
|
|||||||
this.i18n = i18n;
|
this.i18n = i18n;
|
||||||
this.uiNotification = uiNotification;
|
this.uiNotification = uiNotification;
|
||||||
this.managementUIState = managementUIState;
|
this.managementUIState = managementUIState;
|
||||||
this.actionHistoryComponent = new ActionHistoryComponent(i18n, deploymentManagement, eventBus, uiNotification,
|
this.actionHistoryLayout = new ActionHistoryLayout(i18n, deploymentManagement, eventBus, uiNotification,
|
||||||
managementUIState);
|
managementUIState);
|
||||||
|
this.actionStatusLayout = new ActionStatusLayout(i18n, eventBus, managementUIState);
|
||||||
|
this.actionStatusMsgLayout = new ActionStatusMsgLayout(i18n, eventBus, managementUIState);
|
||||||
final CreateUpdateTargetTagLayoutWindow createUpdateTargetTagLayout = new CreateUpdateTargetTagLayoutWindow(
|
final CreateUpdateTargetTagLayoutWindow createUpdateTargetTagLayout = new CreateUpdateTargetTagLayoutWindow(
|
||||||
i18n, tagManagement, entityFactory, eventBus, permChecker, uiNotification);
|
i18n, tagManagement, entityFactory, eventBus, permChecker, uiNotification);
|
||||||
this.targetTagFilterLayout = new TargetTagFilterLayout(i18n, createUpdateTargetTagLayout, managementUIState,
|
this.targetTagFilterLayout = new TargetTagFilterLayout(i18n, createUpdateTargetTagLayout, managementUIState,
|
||||||
@@ -139,7 +149,7 @@ public class DeploymentView extends AbstractNotificationView implements BrowserW
|
|||||||
this.distributionTagLayout = new DistributionTagLayout(eventbus, managementUIState, i18n, permChecker, eventBus,
|
this.distributionTagLayout = new DistributionTagLayout(eventbus, managementUIState, i18n, permChecker, eventBus,
|
||||||
tagManagement, entityFactory, uiNotification, distFilterParameters, distributionSetManagement,
|
tagManagement, entityFactory, uiNotification, distFilterParameters, distributionSetManagement,
|
||||||
managementViewClientCriterion);
|
managementViewClientCriterion);
|
||||||
this.distributionTableLayoutNew = new DistributionTableLayout(i18n, eventBus, permChecker, managementUIState,
|
this.distributionTableLayout = new DistributionTableLayout(i18n, eventBus, permChecker, managementUIState,
|
||||||
distributionSetManagement, managementViewClientCriterion, entityFactory, uiNotification, tagManagement,
|
distributionSetManagement, managementViewClientCriterion, entityFactory, uiNotification, tagManagement,
|
||||||
systemManagement, targetManagement, deploymentManagement);
|
systemManagement, targetManagement, deploymentManagement);
|
||||||
this.deleteAndActionsLayout = new DeleteActionsLayout(i18n, permChecker, eventBus, uiNotification,
|
this.deleteAndActionsLayout = new DeleteActionsLayout(i18n, permChecker, eventBus, uiNotification,
|
||||||
@@ -147,6 +157,9 @@ public class DeploymentView extends AbstractNotificationView implements BrowserW
|
|||||||
deploymentManagement, distributionSetManagement);
|
deploymentManagement, distributionSetManagement);
|
||||||
|
|
||||||
this.deploymentViewMenuItem = deploymentViewMenuItem;
|
this.deploymentViewMenuItem = deploymentViewMenuItem;
|
||||||
|
|
||||||
|
actionHistoryLayout.registerDetails(((ActionStatusGrid) actionStatusLayout.getGrid()).getDetailsSupport());
|
||||||
|
actionStatusLayout.registerDetails(((ActionStatusMsgGrid) actionStatusMsgLayout.getGrid()).getDetailsSupport());
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
@@ -238,11 +251,13 @@ public class DeploymentView extends AbstractNotificationView implements BrowserW
|
|||||||
mainLayout.setRows(2);
|
mainLayout.setRows(2);
|
||||||
mainLayout.addComponent(targetTagFilterLayout, 0, 0);
|
mainLayout.addComponent(targetTagFilterLayout, 0, 0);
|
||||||
mainLayout.addComponent(targetTableLayout, 1, 0);
|
mainLayout.addComponent(targetTableLayout, 1, 0);
|
||||||
mainLayout.addComponent(actionHistoryComponent, 4, 0);
|
mainLayout.addComponent(distributionTableLayout, 2, 0);
|
||||||
mainLayout.addComponent(distributionTableLayoutNew, 2, 0);
|
|
||||||
mainLayout.addComponent(distributionTagLayout, 3, 0);
|
mainLayout.addComponent(distributionTagLayout, 3, 0);
|
||||||
|
mainLayout.addComponent(actionHistoryLayout, 4, 0);
|
||||||
|
mainLayout.setColumnExpandRatio(0, 0F);
|
||||||
mainLayout.setColumnExpandRatio(1, 0.275F);
|
mainLayout.setColumnExpandRatio(1, 0.275F);
|
||||||
mainLayout.setColumnExpandRatio(2, 0.275F);
|
mainLayout.setColumnExpandRatio(2, 0.275F);
|
||||||
|
mainLayout.setColumnExpandRatio(3, 0F);
|
||||||
mainLayout.setColumnExpandRatio(4, 0.45F);
|
mainLayout.setColumnExpandRatio(4, 0.45F);
|
||||||
if (showFooterLayout()) {
|
if (showFooterLayout()) {
|
||||||
mainLayout.addComponent(deleteAndActionsLayout, 1, 1, 2, 1);
|
mainLayout.addComponent(deleteAndActionsLayout, 1, 1, 2, 1);
|
||||||
@@ -253,7 +268,7 @@ public class DeploymentView extends AbstractNotificationView implements BrowserW
|
|||||||
private void displayDistributionWidgetsOnly() {
|
private void displayDistributionWidgetsOnly() {
|
||||||
mainLayout.setColumns(2);
|
mainLayout.setColumns(2);
|
||||||
mainLayout.setRows(2);
|
mainLayout.setRows(2);
|
||||||
mainLayout.addComponent(distributionTableLayoutNew, 0, 0);
|
mainLayout.addComponent(distributionTableLayout, 0, 0);
|
||||||
mainLayout.addComponent(distributionTagLayout, 1, 0);
|
mainLayout.addComponent(distributionTagLayout, 1, 0);
|
||||||
mainLayout.setColumnExpandRatio(0, 1F);
|
mainLayout.setColumnExpandRatio(0, 1F);
|
||||||
if (showFooterLayout()) {
|
if (showFooterLayout()) {
|
||||||
@@ -280,7 +295,7 @@ public class DeploymentView extends AbstractNotificationView implements BrowserW
|
|||||||
mainLayout.setRows(2);
|
mainLayout.setRows(2);
|
||||||
mainLayout.addComponent(targetTagFilterLayout, 0, 0);
|
mainLayout.addComponent(targetTagFilterLayout, 0, 0);
|
||||||
mainLayout.addComponent(targetTableLayout, 1, 0);
|
mainLayout.addComponent(targetTableLayout, 1, 0);
|
||||||
mainLayout.addComponent(actionHistoryComponent, 2, 0);
|
mainLayout.addComponent(actionHistoryLayout, 2, 0);
|
||||||
mainLayout.setColumnExpandRatio(1, 0.4F);
|
mainLayout.setColumnExpandRatio(1, 0.4F);
|
||||||
mainLayout.setColumnExpandRatio(2, 0.6F);
|
mainLayout.setColumnExpandRatio(2, 0.6F);
|
||||||
if (showFooterLayout()) {
|
if (showFooterLayout()) {
|
||||||
@@ -291,10 +306,10 @@ public class DeploymentView extends AbstractNotificationView implements BrowserW
|
|||||||
|
|
||||||
private void maximizeTargetTable() {
|
private void maximizeTargetTable() {
|
||||||
if (permChecker.hasReadDistributionPermission()) {
|
if (permChecker.hasReadDistributionPermission()) {
|
||||||
mainLayout.removeComponent(distributionTableLayoutNew);
|
mainLayout.removeComponent(distributionTableLayout);
|
||||||
mainLayout.removeComponent(distributionTagLayout);
|
mainLayout.removeComponent(distributionTagLayout);
|
||||||
}
|
}
|
||||||
mainLayout.removeComponent(actionHistoryComponent);
|
mainLayout.removeComponent(actionHistoryLayout);
|
||||||
mainLayout.removeComponent(deleteAndActionsLayout);
|
mainLayout.removeComponent(deleteAndActionsLayout);
|
||||||
mainLayout.setColumnExpandRatio(1, 1F);
|
mainLayout.setColumnExpandRatio(1, 1F);
|
||||||
mainLayout.setColumnExpandRatio(2, 0F);
|
mainLayout.setColumnExpandRatio(2, 0F);
|
||||||
@@ -306,7 +321,7 @@ public class DeploymentView extends AbstractNotificationView implements BrowserW
|
|||||||
if (permChecker.hasTargetReadPermission()) {
|
if (permChecker.hasTargetReadPermission()) {
|
||||||
mainLayout.removeComponent(targetTagFilterLayout);
|
mainLayout.removeComponent(targetTagFilterLayout);
|
||||||
mainLayout.removeComponent(targetTableLayout);
|
mainLayout.removeComponent(targetTableLayout);
|
||||||
mainLayout.removeComponent(actionHistoryComponent);
|
mainLayout.removeComponent(actionHistoryLayout);
|
||||||
}
|
}
|
||||||
mainLayout.removeComponent(deleteAndActionsLayout);
|
mainLayout.removeComponent(deleteAndActionsLayout);
|
||||||
mainLayout.setColumnExpandRatio(0, 0F);
|
mainLayout.setColumnExpandRatio(0, 0F);
|
||||||
@@ -316,20 +331,16 @@ public class DeploymentView extends AbstractNotificationView implements BrowserW
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void maximizeActionHistory() {
|
private void maximizeActionHistory() {
|
||||||
mainLayout.setSpacing(false);
|
mainLayout.removeAllComponents();
|
||||||
mainLayout.removeComponent(targetTagFilterLayout);
|
mainLayout.setColumns(3);
|
||||||
mainLayout.removeComponent(targetTableLayout);
|
mainLayout.setRows(1);
|
||||||
if (permChecker.hasReadDistributionPermission()) {
|
mainLayout.addComponent(actionHistoryLayout, 0, 0);
|
||||||
mainLayout.removeComponent(distributionTableLayoutNew);
|
mainLayout.addComponent(actionStatusLayout, 1, 0);
|
||||||
mainLayout.removeComponent(distributionTagLayout);
|
mainLayout.addComponent(actionStatusMsgLayout, 2, 0);
|
||||||
}
|
mainLayout.setColumnExpandRatio(0, 0.55F);
|
||||||
mainLayout.setColumnExpandRatio(0, 0F);
|
mainLayout.setColumnExpandRatio(1, 0.18F);
|
||||||
mainLayout.setColumnExpandRatio(1, 0F);
|
mainLayout.setColumnExpandRatio(2, 0.27F);
|
||||||
mainLayout.setColumnExpandRatio(2, 0F);
|
mainLayout.setComponentAlignment(actionHistoryLayout, Alignment.TOP_LEFT);
|
||||||
mainLayout.setColumnExpandRatio(3, 0F);
|
|
||||||
mainLayout.setColumnExpandRatio(4, 1F);
|
|
||||||
mainLayout.removeComponent(deleteAndActionsLayout);
|
|
||||||
mainLayout.setComponentAlignment(actionHistoryComponent, Alignment.TOP_LEFT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void minimizeTargetTable() {
|
private void minimizeTargetTable() {
|
||||||
@@ -342,7 +353,6 @@ public class DeploymentView extends AbstractNotificationView implements BrowserW
|
|||||||
|
|
||||||
private void minimizeActionHistory() {
|
private void minimizeActionHistory() {
|
||||||
layoutWidgets();
|
layoutWidgets();
|
||||||
mainLayout.setSpacing(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkNoDataAvaialble() {
|
private void checkNoDataAvaialble() {
|
||||||
@@ -362,7 +372,7 @@ public class DeploymentView extends AbstractNotificationView implements BrowserW
|
|||||||
targetTagFilterLayout.setVisible(false);
|
targetTagFilterLayout.setVisible(false);
|
||||||
targetTableLayout.setShowFilterButtonVisible(true);
|
targetTableLayout.setShowFilterButtonVisible(true);
|
||||||
distributionTagLayout.setVisible(false);
|
distributionTagLayout.setVisible(false);
|
||||||
distributionTableLayoutNew.setShowFilterButtonVisible(true);
|
distributionTableLayout.setShowFilterButtonVisible(true);
|
||||||
} else {
|
} else {
|
||||||
if (!managementUIState.isTargetTagFilterClosed()) {
|
if (!managementUIState.isTargetTagFilterClosed()) {
|
||||||
targetTagFilterLayout.setVisible(true);
|
targetTagFilterLayout.setVisible(true);
|
||||||
@@ -371,7 +381,7 @@ public class DeploymentView extends AbstractNotificationView implements BrowserW
|
|||||||
}
|
}
|
||||||
if (!managementUIState.isDistTagFilterClosed()) {
|
if (!managementUIState.isDistTagFilterClosed()) {
|
||||||
distributionTagLayout.setVisible(true);
|
distributionTagLayout.setVisible(true);
|
||||||
distributionTableLayoutNew.setShowFilterButtonVisible(false);
|
distributionTableLayout.setShowFilterButtonVisible(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -383,8 +393,8 @@ public class DeploymentView extends AbstractNotificationView implements BrowserW
|
|||||||
supportedEvents.put(TargetCreatedEventContainer.class, targetTableLayout.getTable());
|
supportedEvents.put(TargetCreatedEventContainer.class, targetTableLayout.getTable());
|
||||||
supportedEvents.put(TargetDeletedEventContainer.class, targetTableLayout.getTable());
|
supportedEvents.put(TargetDeletedEventContainer.class, targetTableLayout.getTable());
|
||||||
|
|
||||||
supportedEvents.put(DistributionCreatedEventContainer.class, distributionTableLayoutNew.getTable());
|
supportedEvents.put(DistributionCreatedEventContainer.class, distributionTableLayout.getTable());
|
||||||
supportedEvents.put(DistributionDeletedEventContainer.class, distributionTableLayoutNew.getTable());
|
supportedEvents.put(DistributionDeletedEventContainer.class, distributionTableLayout.getTable());
|
||||||
|
|
||||||
supportedEvents.put(TargetTagCreatedEventContainer.class, targetTagFilterLayout);
|
supportedEvents.put(TargetTagCreatedEventContainer.class, targetTagFilterLayout);
|
||||||
supportedEvents.put(TargetTagDeletedEventContainer.class, targetTagFilterLayout);
|
supportedEvents.put(TargetTagDeletedEventContainer.class, targetTagFilterLayout);
|
||||||
|
|||||||
@@ -0,0 +1,179 @@
|
|||||||
|
/**
|
||||||
|
* 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.management.actionhistory;
|
||||||
|
|
||||||
|
import static org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil.isNotNullOrEmpty;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
|
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
||||||
|
import org.eclipse.hawkbit.repository.model.Action;
|
||||||
|
import org.eclipse.hawkbit.ui.management.actionhistory.ProxyAction.IsActiveDecoration;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.SpringContextHelper;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
import org.springframework.data.domain.Slice;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
|
import org.springframework.data.domain.Sort.Direction;
|
||||||
|
import org.vaadin.addons.lazyquerycontainer.AbstractBeanQuery;
|
||||||
|
import org.vaadin.addons.lazyquerycontainer.QueryDefinition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple implementation of generics bean query which dynamically loads
|
||||||
|
* {@link ProxyAction} batch of beans.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ActionBeanQuery extends AbstractBeanQuery<ProxyAction> {
|
||||||
|
private static final long serialVersionUID = 3596912494728552516L;
|
||||||
|
|
||||||
|
private Sort sort = new Sort(Direction.DESC, ProxyAction.PXY_ACTION_ID);
|
||||||
|
private transient DeploymentManagement deploymentManagement;
|
||||||
|
|
||||||
|
private String currentSelectedConrollerId;
|
||||||
|
private transient Slice<Action> firstPageActions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parametric Constructor.
|
||||||
|
*
|
||||||
|
* @param definition
|
||||||
|
* QueryDefinition contains the query properties.
|
||||||
|
* @param queryConfig
|
||||||
|
* Implementation specific configuration.
|
||||||
|
* @param sortPropertyIds
|
||||||
|
* The properties participating in sort.
|
||||||
|
* @param sortStates
|
||||||
|
* The ascending or descending state of sort properties.
|
||||||
|
*/
|
||||||
|
public ActionBeanQuery(final QueryDefinition definition, final Map<String, Object> queryConfig,
|
||||||
|
final Object[] sortPropertyIds, final boolean[] sortStates) {
|
||||||
|
super(definition, queryConfig, sortPropertyIds, sortStates);
|
||||||
|
|
||||||
|
if (isNotNullOrEmpty(queryConfig)) {
|
||||||
|
currentSelectedConrollerId = (String) queryConfig.get(SPUIDefinitions.ACTIONS_BY_TARGET);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ArrayUtils.isEmpty(sortStates)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize sort
|
||||||
|
sort = new Sort(sortStates[0] ? Direction.ASC : Direction.DESC, (String) sortPropertyIds[0]);
|
||||||
|
// Add sort
|
||||||
|
for (int distId = 1; distId < sortPropertyIds.length; distId++) {
|
||||||
|
sort.and(new Sort(sortStates[distId] ? Direction.ASC : Direction.DESC, (String) sortPropertyIds[distId]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ProxyAction constructBean() {
|
||||||
|
return new ProxyAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<ProxyAction> loadBeans(final int startIndex, final int count) {
|
||||||
|
Slice<Action> actionBeans;
|
||||||
|
if (startIndex == 0) {
|
||||||
|
if (firstPageActions == null) {
|
||||||
|
firstPageActions = getDeploymentManagement().findActionsByTarget(currentSelectedConrollerId,
|
||||||
|
new PageRequest(0, SPUIDefinitions.PAGE_SIZE, sort));
|
||||||
|
}
|
||||||
|
actionBeans = firstPageActions;
|
||||||
|
} else {
|
||||||
|
actionBeans = getDeploymentManagement().findActionsByTarget(currentSelectedConrollerId,
|
||||||
|
new PageRequest(startIndex / SPUIDefinitions.PAGE_SIZE, SPUIDefinitions.PAGE_SIZE, sort));
|
||||||
|
}
|
||||||
|
return createProxyActions(actionBeans);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a list of {@link ProxyAction}s for presentation layer from slice
|
||||||
|
* of {@link Action}s.
|
||||||
|
*
|
||||||
|
* @param actionBeans
|
||||||
|
* slice of {@link Action}s
|
||||||
|
* @return list of {@link ProxyAction}s
|
||||||
|
*/
|
||||||
|
private static List<ProxyAction> createProxyActions(final Slice<Action> actionBeans) {
|
||||||
|
final List<ProxyAction> proxyActions = new ArrayList<>();
|
||||||
|
for (final Action action : actionBeans) {
|
||||||
|
final ProxyAction proxyAction = new ProxyAction();
|
||||||
|
final String dsNameVersion = action.getDistributionSet().getName() + ":"
|
||||||
|
+ action.getDistributionSet().getVersion();
|
||||||
|
proxyAction.setActive(action.isActive());
|
||||||
|
proxyAction.setIsActiveDecoration(buildIsActiveDecoration(action));
|
||||||
|
proxyAction.setDsNameVersion(dsNameVersion);
|
||||||
|
proxyAction.setAction(action);
|
||||||
|
proxyAction.setId(action.getId());
|
||||||
|
proxyAction.setLastModifiedAt(action.getLastModifiedAt());
|
||||||
|
proxyAction.setRolloutName(action.getRollout() != null ? action.getRollout().getName() : "");
|
||||||
|
proxyAction.setStatus(action.getStatus());
|
||||||
|
|
||||||
|
proxyActions.add(proxyAction);
|
||||||
|
}
|
||||||
|
return proxyActions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a virtual IsActiveDecoration for the presentation layer that is
|
||||||
|
* calculated from {@link Action#isActive()} and
|
||||||
|
* {@link Action#getActionStatus()}.
|
||||||
|
*
|
||||||
|
* @param action
|
||||||
|
* the action combined IsActiveDecoration is calculated from
|
||||||
|
* @return IsActiveDecoration combined decoration for the presentation
|
||||||
|
* layer.
|
||||||
|
*/
|
||||||
|
private static IsActiveDecoration buildIsActiveDecoration(final Action action) {
|
||||||
|
final Action.Status status = action.getStatus();
|
||||||
|
|
||||||
|
if (status == Action.Status.SCHEDULED) {
|
||||||
|
return IsActiveDecoration.SCHEDULED;
|
||||||
|
} else if (status == Action.Status.ERROR) {
|
||||||
|
return IsActiveDecoration.IN_ACTIVE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return action.isActive() ? IsActiveDecoration.ACTIVE : IsActiveDecoration.IN_ACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void saveBeans(final List<ProxyAction> addedBeans, final List<ProxyAction> modifiedBeans,
|
||||||
|
final List<ProxyAction> removedBeans) {
|
||||||
|
// CRUD operations on Target will be done through repository methods
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
long size = 0;
|
||||||
|
|
||||||
|
if (currentSelectedConrollerId != null) {
|
||||||
|
size = getDeploymentManagement().countActionsByTarget(currentSelectedConrollerId);
|
||||||
|
}
|
||||||
|
if (size > Integer.MAX_VALUE) {
|
||||||
|
return Integer.MAX_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lazy gets deploymentManagement.
|
||||||
|
*
|
||||||
|
* @return the deploymentManagement
|
||||||
|
*/
|
||||||
|
public DeploymentManagement getDeploymentManagement() {
|
||||||
|
if (null == deploymentManagement) {
|
||||||
|
deploymentManagement = SpringContextHelper.getBean(DeploymentManagement.class);
|
||||||
|
}
|
||||||
|
return deploymentManagement;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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.management.actionhistory;
|
|
||||||
|
|
||||||
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
|
||||||
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
|
|
||||||
import org.eclipse.hawkbit.ui.management.event.TargetTableEvent;
|
|
||||||
import org.eclipse.hawkbit.ui.management.state.ManagementUIState;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.UINotification;
|
|
||||||
import org.vaadin.spring.events.EventBus.UIEventBus;
|
|
||||||
import org.vaadin.spring.events.EventScope;
|
|
||||||
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
|
|
||||||
|
|
||||||
import com.vaadin.ui.Alignment;
|
|
||||||
import com.vaadin.ui.UI;
|
|
||||||
import com.vaadin.ui.VerticalLayout;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ActionHistoryComponent extends VerticalLayout {
|
|
||||||
private static final long serialVersionUID = -3766179797384539821L;
|
|
||||||
|
|
||||||
private final ActionHistoryHeader actionHistoryHeader;
|
|
||||||
private final ActionHistoryTable actionHistoryTable;
|
|
||||||
|
|
||||||
public ActionHistoryComponent(final VaadinMessageSource i18n, final DeploymentManagement deploymentManagement,
|
|
||||||
final UIEventBus eventBus, final UINotification notification, final ManagementUIState managementUIState) {
|
|
||||||
this.actionHistoryHeader = new ActionHistoryHeader(eventBus, managementUIState);
|
|
||||||
this.actionHistoryTable = new ActionHistoryTable(i18n, deploymentManagement, eventBus, notification,
|
|
||||||
managementUIState);
|
|
||||||
buildLayout();
|
|
||||||
setSizeFull();
|
|
||||||
setImmediate(true);
|
|
||||||
eventBus.subscribe(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventBusListenerMethod(scope = EventScope.UI)
|
|
||||||
void onEvent(final TargetTableEvent targetUIEvent) {
|
|
||||||
if (BaseEntityEventType.SELECTED_ENTITY == targetUIEvent.getEventType()) {
|
|
||||||
setData(SPUIDefinitions.DATA_AVAILABLE);
|
|
||||||
UI.getCurrent().access(() -> populateActionHistoryDetails(targetUIEvent.getEntity()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void buildLayout() {
|
|
||||||
setSizeFull();
|
|
||||||
setSpacing(false);
|
|
||||||
setMargin(false);
|
|
||||||
addStyleName("table-layout");
|
|
||||||
addComponents(actionHistoryHeader, actionHistoryTable);
|
|
||||||
setComponentAlignment(actionHistoryHeader, Alignment.TOP_CENTER);
|
|
||||||
setComponentAlignment(actionHistoryTable, Alignment.TOP_CENTER);
|
|
||||||
setExpandRatio(actionHistoryTable, 1.0F);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* populate action header and table for the target.
|
|
||||||
*
|
|
||||||
* @param target
|
|
||||||
* the target
|
|
||||||
*/
|
|
||||||
public void populateActionHistoryDetails(final Target target) {
|
|
||||||
if (null != target) {
|
|
||||||
actionHistoryHeader.populateHeader(target.getName());
|
|
||||||
actionHistoryTable.setAlreadyHasMessages(false);
|
|
||||||
actionHistoryTable.populateTableData(target);
|
|
||||||
} else {
|
|
||||||
actionHistoryHeader.updateActionHistoryHeader(" ");
|
|
||||||
actionHistoryTable.setAlreadyHasMessages(false);
|
|
||||||
actionHistoryTable.clearContainerData();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,792 @@
|
|||||||
|
/**
|
||||||
|
* 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.management.actionhistory;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
||||||
|
import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException;
|
||||||
|
import org.eclipse.hawkbit.repository.model.Action;
|
||||||
|
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||||
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
|
import org.eclipse.hawkbit.ui.common.ConfirmationDialog;
|
||||||
|
import org.eclipse.hawkbit.ui.common.grid.AbstractGrid;
|
||||||
|
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
|
||||||
|
import org.eclipse.hawkbit.ui.customrenderers.renderers.AbstractGridButtonConverter;
|
||||||
|
import org.eclipse.hawkbit.ui.customrenderers.renderers.AbstractHtmlLabelConverter;
|
||||||
|
import org.eclipse.hawkbit.ui.customrenderers.renderers.GridButtonRenderer;
|
||||||
|
import org.eclipse.hawkbit.ui.customrenderers.renderers.HtmlLabelRenderer;
|
||||||
|
import org.eclipse.hawkbit.ui.management.actionhistory.ProxyAction.IsActiveDecoration;
|
||||||
|
import org.eclipse.hawkbit.ui.management.event.ManagementUIEvent;
|
||||||
|
import org.eclipse.hawkbit.ui.management.event.PinUnpinEvent;
|
||||||
|
import org.eclipse.hawkbit.ui.management.event.TargetTableEvent;
|
||||||
|
import org.eclipse.hawkbit.ui.management.state.ManagementUIState;
|
||||||
|
import org.eclipse.hawkbit.ui.rollout.StatusFontIcon;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.UINotification;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory;
|
||||||
|
import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer;
|
||||||
|
import org.vaadin.addons.lazyquerycontainer.LazyQueryDefinition;
|
||||||
|
import org.vaadin.spring.events.EventBus.UIEventBus;
|
||||||
|
import org.vaadin.spring.events.EventScope;
|
||||||
|
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.vaadin.data.Item;
|
||||||
|
import com.vaadin.data.util.GeneratedPropertyContainer;
|
||||||
|
import com.vaadin.data.util.PropertyValueGenerator;
|
||||||
|
import com.vaadin.server.FontAwesome;
|
||||||
|
import com.vaadin.ui.UI;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This grid presents the action history for a selected target.
|
||||||
|
*/
|
||||||
|
public class ActionHistoryGrid extends AbstractGrid<LazyQueryContainer> {
|
||||||
|
private static final long serialVersionUID = 4324796883957831443L;
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(ActionHistoryGrid.class);
|
||||||
|
private static final String BUTTON_CANCEL = "button.cancel";
|
||||||
|
private static final String BUTTON_OK = "button.ok";
|
||||||
|
private static final double FIXED_PIX_MIN = 29F;
|
||||||
|
private static final double FIXED_PIX_MAX = 32F;
|
||||||
|
|
||||||
|
private static final String STATUS_ICON_GREEN = "statusIconGreen";
|
||||||
|
private static final String STATUS_ICON_RED = "statusIconRed";
|
||||||
|
private static final String STATUS_ICON_ORANGE = "statusIconOrange";
|
||||||
|
private static final String STATUS_ICON_PENDING = "statusIconPending";
|
||||||
|
private static final String STATUS_ICON_NEUTRAL = "statusIconNeutral";
|
||||||
|
private static final String STATUS_ICON_ACTIVE = "statusIconActive";
|
||||||
|
private static final String STATUS_ICON_FORCED = "statusIconForced";
|
||||||
|
|
||||||
|
private static final String VIRT_PROP_FORCED = "forced";
|
||||||
|
private static final String VIRT_PROP_TIMEFORCED = "timeForced";
|
||||||
|
private static final String VIRT_PROP_ACTION_CANCEL = "cancel-aciton";
|
||||||
|
private static final String VIRT_PROP_ACTION_FORCE = "force-action";
|
||||||
|
private static final String VIRT_PROP_ACTION_FORCE_QUIT = "force-quit-action";
|
||||||
|
|
||||||
|
private static final Object[] maxColumnOrder = new Object[] { ProxyAction.PXY_ACTION_IS_ACTIVE_DECO,
|
||||||
|
ProxyAction.PXY_ACTION_ID, ProxyAction.PXY_ACTION_DS_NAME_VERSION, ProxyAction.PXY_ACTION_LAST_MODIFIED_AT,
|
||||||
|
ProxyAction.PXY_ACTION_STATUS, ProxyAction.PXY_ACTION_ROLLOUT_NAME, VIRT_PROP_FORCED, VIRT_PROP_TIMEFORCED,
|
||||||
|
VIRT_PROP_ACTION_CANCEL, VIRT_PROP_ACTION_FORCE, VIRT_PROP_ACTION_FORCE_QUIT };
|
||||||
|
|
||||||
|
private static final Object[] minColumnOrder = new Object[] { ProxyAction.PXY_ACTION_IS_ACTIVE_DECO,
|
||||||
|
ProxyAction.PXY_ACTION_DS_NAME_VERSION, ProxyAction.PXY_ACTION_LAST_MODIFIED_AT,
|
||||||
|
ProxyAction.PXY_ACTION_STATUS, VIRT_PROP_FORCED, VIRT_PROP_TIMEFORCED, VIRT_PROP_ACTION_CANCEL,
|
||||||
|
VIRT_PROP_ACTION_FORCE, VIRT_PROP_ACTION_FORCE_QUIT };
|
||||||
|
|
||||||
|
private static final String[] leftAlignedColumns = new String[] { VIRT_PROP_TIMEFORCED };
|
||||||
|
|
||||||
|
private static final String[] centerAlignedColumns = new String[] { ProxyAction.PXY_ACTION_IS_ACTIVE_DECO,
|
||||||
|
ProxyAction.PXY_ACTION_STATUS };
|
||||||
|
|
||||||
|
private static final String[] rightAlignedColumns = new String[] { VIRT_PROP_FORCED, ProxyAction.PXY_ACTION_ID };
|
||||||
|
|
||||||
|
private final transient DeploymentManagement deploymentManagement;
|
||||||
|
private final UINotification notification;
|
||||||
|
private final ManagementUIState managementUIState;
|
||||||
|
|
||||||
|
private Target selectedTarget;
|
||||||
|
private final AlignCellStyleGenerator alignGenerator;
|
||||||
|
private final ModifiedTimeTooltipGenerator modTimetooltipGenerator;
|
||||||
|
|
||||||
|
private final Map<Action.Status, StatusFontIcon> states;
|
||||||
|
private final Map<IsActiveDecoration, StatusFontIcon> activeStates;
|
||||||
|
|
||||||
|
private final BeanQueryFactory<ActionBeanQuery> targetQF = new BeanQueryFactory<>(ActionBeanQuery.class);
|
||||||
|
|
||||||
|
boolean forceClientRefreshToggle = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param i18n
|
||||||
|
* @param deploymentManagement
|
||||||
|
* @param eventBus
|
||||||
|
* @param notification
|
||||||
|
* @param managementUIState
|
||||||
|
*/
|
||||||
|
protected ActionHistoryGrid(final VaadinMessageSource i18n, final DeploymentManagement deploymentManagement,
|
||||||
|
final UIEventBus eventBus, final UINotification notification, final ManagementUIState managementUIState) {
|
||||||
|
super(i18n, eventBus, null);
|
||||||
|
this.deploymentManagement = deploymentManagement;
|
||||||
|
this.notification = notification;
|
||||||
|
this.managementUIState = managementUIState;
|
||||||
|
|
||||||
|
setMaximizeSupport(new ActionHistoryMaximizeSupport());
|
||||||
|
setSingleSelectionSupport(new SingleSelectionSupport());
|
||||||
|
|
||||||
|
if (!managementUIState.isActionHistoryMaximized()) {
|
||||||
|
getSingleSelectionSupport().disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
setGeneratedPropertySupport(new ActionHistoryGeneratedPropertySupport());
|
||||||
|
setDetailsSupport(new DetailsSupport());
|
||||||
|
|
||||||
|
final LabelConfig conf = new LabelConfig();
|
||||||
|
states = conf.createStatusLabelConfig(i18n, UIComponentIdProvider.ACTION_HISTORY_TABLE_STATUS_LABEL_ID);
|
||||||
|
activeStates = conf
|
||||||
|
.createActiveStatusLabelConfig(UIComponentIdProvider.ACTION_HISTORY_TABLE_ACTIVESTATE_LABEL_ID);
|
||||||
|
alignGenerator = new AlignCellStyleGenerator(leftAlignedColumns, centerAlignedColumns, rightAlignedColumns);
|
||||||
|
modTimetooltipGenerator = new ModifiedTimeTooltipGenerator(ProxyAction.PXY_ACTION_LAST_MODIFIED_AT);
|
||||||
|
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventBusListenerMethod(scope = EventScope.UI)
|
||||||
|
void onEvent(final ManagementUIEvent mgmtUIEvent) {
|
||||||
|
if (mgmtUIEvent == ManagementUIEvent.MAX_ACTION_HISTORY) {
|
||||||
|
UI.getCurrent().access(this::createMaximizedContent);
|
||||||
|
}
|
||||||
|
if (mgmtUIEvent == ManagementUIEvent.MIN_ACTION_HISTORY) {
|
||||||
|
UI.getCurrent().access(this::createMinimizedContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void init() {
|
||||||
|
super.init();
|
||||||
|
restorePreviousState();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set target as member of this grid (as all presented grid-data is related
|
||||||
|
* to this target) and recalculate grid-data for this target.
|
||||||
|
*
|
||||||
|
* @param selectedTarget
|
||||||
|
* reference of target
|
||||||
|
*/
|
||||||
|
public void populateSelectedTarget(final Target selectedTarget) {
|
||||||
|
this.selectedTarget = selectedTarget;
|
||||||
|
getDetailsSupport()
|
||||||
|
.populateMasterDataAndRecalculateContainer(selectedTarget != null ? selectedTarget.getId() : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected LazyQueryContainer createContainer() {
|
||||||
|
configureQueryFactory();
|
||||||
|
return new LazyQueryContainer(
|
||||||
|
new LazyQueryDefinition(true, SPUIDefinitions.PAGE_SIZE, ProxyAction.PXY_ACTION_ID), targetQF);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshContainer() {
|
||||||
|
configureQueryFactory();
|
||||||
|
super.refreshContainer();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void configureQueryFactory() {
|
||||||
|
// ADD all the filters to the query config
|
||||||
|
final Map<String, Object> queryConfig = Maps.newHashMapWithExpectedSize(1);
|
||||||
|
queryConfig.put(SPUIDefinitions.ACTIONS_BY_TARGET,
|
||||||
|
selectedTarget != null ? selectedTarget.getControllerId() : null);
|
||||||
|
// Create ActionBeanQuery factory with the query config.
|
||||||
|
targetQF.setQueryConfiguration(queryConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addContainerProperties() {
|
||||||
|
final LazyQueryContainer rawCont = getGeneratedPropertySupport().getRawContainer();
|
||||||
|
|
||||||
|
rawCont.addContainerProperty(ProxyAction.PXY_ACTION_IS_ACTIVE_DECO, IsActiveDecoration.class, null, true,
|
||||||
|
false);
|
||||||
|
rawCont.addContainerProperty(ProxyAction.PXY_ACTION, Action.class, null, true, false);
|
||||||
|
rawCont.addContainerProperty(ProxyAction.PXY_ACTION_DS_NAME_VERSION, String.class, null, true, false);
|
||||||
|
rawCont.addContainerProperty(ProxyAction.PXY_ACTION_LAST_MODIFIED_AT, Long.class, null, true, true);
|
||||||
|
rawCont.addContainerProperty(ProxyAction.PXY_ACTION_STATUS, Action.Status.class, null, true, false);
|
||||||
|
|
||||||
|
rawCont.addContainerProperty(ProxyAction.PXY_ACTION_ID, Long.class, null, true, true);
|
||||||
|
rawCont.addContainerProperty(ProxyAction.PXY_ACTION_ROLLOUT_NAME, String.class, null, true, true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getGridId() {
|
||||||
|
return UIComponentIdProvider.ACTION_HISTORY_GRID_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addColumnRenderes() {
|
||||||
|
getColumn(ProxyAction.PXY_ACTION_LAST_MODIFIED_AT).setConverter(new LongToFormattedDateStringConverter());
|
||||||
|
getColumn(ProxyAction.PXY_ACTION_STATUS).setRenderer(new HtmlLabelRenderer(),
|
||||||
|
new HtmlStatusLabelConverter(this::createStatusLabelMetadata));
|
||||||
|
getColumn(ProxyAction.PXY_ACTION_IS_ACTIVE_DECO).setRenderer(new HtmlLabelRenderer(),
|
||||||
|
new HtmlIsActiveLabelConverter(this::createIsActiveLabelMetadata));
|
||||||
|
getColumn(VIRT_PROP_FORCED).setRenderer(new HtmlLabelRenderer(),
|
||||||
|
new HtmlVirtPropLabelConverter(ActionHistoryGrid::createForcedLabelMetadata));
|
||||||
|
getColumn(VIRT_PROP_TIMEFORCED).setRenderer(new HtmlLabelRenderer(),
|
||||||
|
new HtmlVirtPropLabelConverter(this::createTimeForcedLabelMetadata));
|
||||||
|
getColumn(VIRT_PROP_ACTION_CANCEL).setRenderer(
|
||||||
|
new GridButtonRenderer(clickEvent -> confirmAndCancelAction((Long) clickEvent.getItemId())),
|
||||||
|
new ActionGridButtonConverter(this::createCancelButtonMetadata));
|
||||||
|
getColumn(VIRT_PROP_ACTION_FORCE).setRenderer(
|
||||||
|
new GridButtonRenderer(clickEvent -> confirmAndForceAction((Long) clickEvent.getItemId())),
|
||||||
|
new ActionGridButtonConverter(this::createForceButtonMetadata));
|
||||||
|
getColumn(VIRT_PROP_ACTION_FORCE_QUIT).setRenderer(
|
||||||
|
new GridButtonRenderer(clickEvent -> confirmAndForceQuitAction((Long) clickEvent.getItemId())),
|
||||||
|
new ActionGridButtonConverter(this::createForceQuitButtonMetadata));
|
||||||
|
}
|
||||||
|
|
||||||
|
private StatusFontIcon createCancelButtonMetadata(final Action action) {
|
||||||
|
final boolean isDisabled = !action.isActive() || action.isCancelingOrCanceled();
|
||||||
|
return new StatusFontIcon(FontAwesome.TIMES, STATUS_ICON_NEUTRAL, i18n.getMessage("message.cancel.action"),
|
||||||
|
UIComponentIdProvider.ACTION_HISTORY_TABLE_CANCEL_ID, isDisabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
private StatusFontIcon createForceButtonMetadata(final Action action) {
|
||||||
|
final boolean isDisabled = !action.isActive() || action.isForce() || action.isCancelingOrCanceled();
|
||||||
|
return new StatusFontIcon(FontAwesome.BOLT, STATUS_ICON_NEUTRAL, i18n.getMessage("message.force.action"),
|
||||||
|
UIComponentIdProvider.ACTION_HISTORY_TABLE_FORCE_ID, isDisabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
private StatusFontIcon createForceQuitButtonMetadata(final Action action) {
|
||||||
|
final boolean isDisabled = !action.isActive() || !action.isCancelingOrCanceled();
|
||||||
|
return new StatusFontIcon(FontAwesome.TIMES, STATUS_ICON_RED, i18n.getMessage("message.forcequit.action"),
|
||||||
|
UIComponentIdProvider.ACTION_HISTORY_TABLE_FORCE_QUIT_ID, isDisabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
private StatusFontIcon createStatusLabelMetadata(final Action.Status status) {
|
||||||
|
return states.get(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
private StatusFontIcon createIsActiveLabelMetadata(final IsActiveDecoration isActiveDeco) {
|
||||||
|
return activeStates.get(isActiveDeco);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static StatusFontIcon createForcedLabelMetadata(final Action action) {
|
||||||
|
StatusFontIcon result = null;
|
||||||
|
if (ActionType.FORCED.equals(action.getActionType()) || ActionType.TIMEFORCED.equals(action.getActionType())) {
|
||||||
|
result = new StatusFontIcon(FontAwesome.BOLT, STATUS_ICON_FORCED, "Forced",
|
||||||
|
UIComponentIdProvider.ACTION_HISTORY_TABLE_FORCED_LABEL_ID);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private StatusFontIcon createTimeForcedLabelMetadata(final Action action) {
|
||||||
|
StatusFontIcon result = null;
|
||||||
|
|
||||||
|
if (ActionType.TIMEFORCED.equals(action.getActionType())) {
|
||||||
|
final long currentTimeMillis = System.currentTimeMillis();
|
||||||
|
String style;
|
||||||
|
String title;
|
||||||
|
if (action.isHitAutoForceTime(currentTimeMillis)) {
|
||||||
|
style = STATUS_ICON_GREEN;
|
||||||
|
title = "auto forced since "
|
||||||
|
+ SPDateTimeUtil.getDurationFormattedString(action.getForcedTime(), currentTimeMillis, i18n);
|
||||||
|
} else {
|
||||||
|
style = STATUS_ICON_PENDING;
|
||||||
|
title = "auto forcing in "
|
||||||
|
+ SPDateTimeUtil.getDurationFormattedString(currentTimeMillis, action.getForcedTime(), i18n);
|
||||||
|
}
|
||||||
|
result = new StatusFontIcon(FontAwesome.HISTORY, style, title,
|
||||||
|
UIComponentIdProvider.ACTION_HISTORY_TABLE_TIMEFORCED_LABEL_ID);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show confirmation window and if ok then only, force the action.
|
||||||
|
*
|
||||||
|
* @param actionId
|
||||||
|
* as Id if the action needs to be forced.
|
||||||
|
*/
|
||||||
|
private void confirmAndForceAction(final Long actionId) {
|
||||||
|
/* Display the confirmation */
|
||||||
|
final ConfirmationDialog confirmDialog = new ConfirmationDialog(
|
||||||
|
i18n.getMessage("caption.force.action.confirmbox"), i18n.getMessage("message.force.action.confirm"),
|
||||||
|
i18n.getMessage(BUTTON_OK), i18n.getMessage(BUTTON_CANCEL), ok -> {
|
||||||
|
if (!ok) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
deploymentManagement.forceTargetAction(actionId);
|
||||||
|
populateAndUpdateTargetDetails(selectedTarget);
|
||||||
|
notification.displaySuccess(i18n.getMessage("message.force.action.success"));
|
||||||
|
});
|
||||||
|
UI.getCurrent().addWindow(confirmDialog.getWindow());
|
||||||
|
|
||||||
|
confirmDialog.getWindow().bringToFront();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show confirmation window and if ok then only, force quit action.
|
||||||
|
*
|
||||||
|
* @param actionId
|
||||||
|
* as Id if the action needs to be forced.
|
||||||
|
*/
|
||||||
|
private void confirmAndForceQuitAction(final Long actionId) {
|
||||||
|
/* Display the confirmation */
|
||||||
|
final ConfirmationDialog confirmDialog = new ConfirmationDialog(
|
||||||
|
i18n.getMessage("caption.forcequit.action.confirmbox"),
|
||||||
|
i18n.getMessage("message.forcequit.action.confirm"), i18n.getMessage(BUTTON_OK),
|
||||||
|
i18n.getMessage(BUTTON_CANCEL), ok -> {
|
||||||
|
if (!ok) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final boolean cancelResult = forceQuitActiveAction(actionId);
|
||||||
|
if (cancelResult) {
|
||||||
|
populateAndUpdateTargetDetails(selectedTarget);
|
||||||
|
notification.displaySuccess(i18n.getMessage("message.forcequit.action.success"));
|
||||||
|
} else {
|
||||||
|
notification.displayValidationError(i18n.getMessage("message.forcequit.action.failed"));
|
||||||
|
}
|
||||||
|
}, FontAwesome.WARNING);
|
||||||
|
UI.getCurrent().addWindow(confirmDialog.getWindow());
|
||||||
|
|
||||||
|
confirmDialog.getWindow().bringToFront();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show confirmation window and if ok then only, cancel the action.
|
||||||
|
*
|
||||||
|
* @param actionId
|
||||||
|
* as Id if the action needs to be cancelled.
|
||||||
|
*/
|
||||||
|
private void confirmAndCancelAction(final Long actionId) {
|
||||||
|
if (actionId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final ConfirmationDialog confirmDialog = new ConfirmationDialog(
|
||||||
|
i18n.getMessage("caption.cancel.action.confirmbox"), i18n.getMessage("message.cancel.action.confirm"),
|
||||||
|
i18n.getMessage(BUTTON_OK), i18n.getMessage(BUTTON_CANCEL), ok -> {
|
||||||
|
if (!ok) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final boolean cancelResult = cancelActiveAction(actionId);
|
||||||
|
if (cancelResult) {
|
||||||
|
populateAndUpdateTargetDetails(selectedTarget);
|
||||||
|
notification.displaySuccess(i18n.getMessage("message.cancel.action.success"));
|
||||||
|
} else {
|
||||||
|
notification.displayValidationError(i18n.getMessage("message.cancel.action.failed"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
UI.getCurrent().addWindow(confirmDialog.getWindow());
|
||||||
|
confirmDialog.getWindow().bringToFront();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void populateAndUpdateTargetDetails(final Target target) {
|
||||||
|
// show the updated target action history details
|
||||||
|
populateSelectedTarget(target);
|
||||||
|
// update the target table and its pinning details
|
||||||
|
updateTargetAndDsTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTargetAndDsTable() {
|
||||||
|
eventBus.publish(this, new TargetTableEvent(BaseEntityEventType.UPDATED_ENTITY, selectedTarget));
|
||||||
|
updateDistributionTableStyle();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the colors of Assigned and installed distribution set in Target
|
||||||
|
* Pinning.
|
||||||
|
*/
|
||||||
|
private void updateDistributionTableStyle() {
|
||||||
|
managementUIState.getDistributionTableFilters().getPinnedTarget().ifPresent((pinnedTarget) -> {
|
||||||
|
if (pinnedTarget.getTargetId().equals(selectedTarget.getId())) {
|
||||||
|
eventBus.publish(this, PinUnpinEvent.PIN_TARGET);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!managementUIState.getDistributionTableFilters().getPinnedTarget().isPresent()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// service call to cancel the active action
|
||||||
|
private boolean cancelActiveAction(final Long actionId) {
|
||||||
|
if (actionId != null) {
|
||||||
|
try {
|
||||||
|
deploymentManagement.cancelAction(actionId);
|
||||||
|
return true;
|
||||||
|
} catch (final CancelActionNotAllowedException e) {
|
||||||
|
LOG.info("Cancel action not allowed exception :{}", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// service call to cancel the active action
|
||||||
|
private boolean forceQuitActiveAction(final Long actionId) {
|
||||||
|
if (actionId != null) {
|
||||||
|
try {
|
||||||
|
deploymentManagement.forceQuitAction(actionId);
|
||||||
|
return true;
|
||||||
|
} catch (final CancelActionNotAllowedException e) {
|
||||||
|
LOG.info("Force Cancel action not allowed exception :{}", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setHiddenColumns() {
|
||||||
|
getColumn(VIRT_PROP_FORCED).setHidable(false);
|
||||||
|
getColumn(VIRT_PROP_TIMEFORCED).setHidable(false);
|
||||||
|
getColumn(VIRT_PROP_ACTION_CANCEL).setHidable(false);
|
||||||
|
getColumn(VIRT_PROP_ACTION_FORCE).setHidable(false);
|
||||||
|
getColumn(VIRT_PROP_ACTION_FORCE_QUIT).setHidable(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected CellDescriptionGenerator getDescriptionGenerator() {
|
||||||
|
return modTimetooltipGenerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setColumnHeaderNames() {
|
||||||
|
final HeaderRow newHeaderRow = resetHeaderDefaultRow();
|
||||||
|
|
||||||
|
getColumn(ProxyAction.PXY_ACTION_IS_ACTIVE_DECO).setHeaderCaption(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE);
|
||||||
|
getColumn(ProxyAction.PXY_ACTION_DS_NAME_VERSION).setHeaderCaption(SPUIDefinitions.ACTION_HIS_TBL_DIST);
|
||||||
|
getColumn(ProxyAction.PXY_ACTION_LAST_MODIFIED_AT).setHeaderCaption(SPUIDefinitions.ACTION_HIS_TBL_DATETIME);
|
||||||
|
getColumn(ProxyAction.PXY_ACTION_STATUS).setHeaderCaption(SPUIDefinitions.ACTION_HIS_TBL_STATUS);
|
||||||
|
getColumn(VIRT_PROP_FORCED).setHeaderCaption(String.valueOf(forceClientRefreshToggle));
|
||||||
|
forceClientRefreshToggle = !forceClientRefreshToggle;
|
||||||
|
|
||||||
|
newHeaderRow.join(VIRT_PROP_FORCED, VIRT_PROP_TIMEFORCED).setText(SPUIDefinitions.ACTION_HIS_TBL_FORCED);
|
||||||
|
newHeaderRow.join(VIRT_PROP_ACTION_CANCEL, VIRT_PROP_ACTION_FORCE, VIRT_PROP_ACTION_FORCE_QUIT)
|
||||||
|
.setText(SPUIDefinitions.ACTIONS_COLUMN);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setColumnExpandRatio() {
|
||||||
|
setColumnsSize(50.0, 50.0, ProxyAction.PXY_ACTION_IS_ACTIVE_DECO);
|
||||||
|
setColumnsSize(107.0, 500.0, ProxyAction.PXY_ACTION_DS_NAME_VERSION);
|
||||||
|
setColumnsSize(100.0, 120.0, ProxyAction.PXY_ACTION_LAST_MODIFIED_AT);
|
||||||
|
setColumnsSize(53.0, 55.0, ProxyAction.PXY_ACTION_STATUS);
|
||||||
|
setColumnsSize(FIXED_PIX_MIN, FIXED_PIX_MIN, VIRT_PROP_FORCED, VIRT_PROP_TIMEFORCED, VIRT_PROP_ACTION_CANCEL,
|
||||||
|
VIRT_PROP_ACTION_FORCE, VIRT_PROP_ACTION_FORCE_QUIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Conveniently sets min- and max-width for a bunch of columns.
|
||||||
|
*
|
||||||
|
* @param min
|
||||||
|
* minimum width
|
||||||
|
* @param max
|
||||||
|
* maximum width
|
||||||
|
* @param columnPropertyIds
|
||||||
|
* all the columns the min and max should be set for.
|
||||||
|
*/
|
||||||
|
private void setColumnsSize(final double min, final double max, final String... columnPropertyIds) {
|
||||||
|
for (final String columnPropertyId : columnPropertyIds) {
|
||||||
|
getColumn(columnPropertyId).setMinimumWidth(min);
|
||||||
|
getColumn(columnPropertyId).setMaximumWidth(max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the grid content for maximized-state.
|
||||||
|
*/
|
||||||
|
private void createMaximizedContent() {
|
||||||
|
getSingleSelectionSupport().enable();
|
||||||
|
getDetailsSupport().populateSelection();
|
||||||
|
getMaximizeSupport().createMaximizedContent();
|
||||||
|
recalculateColumnWidths();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the grid content for normal (minimized) state.
|
||||||
|
*/
|
||||||
|
private void createMinimizedContent() {
|
||||||
|
getSingleSelectionSupport().disable();
|
||||||
|
getMaximizeSupport().createMinimizedContent();
|
||||||
|
recalculateColumnWidths();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setColumnProperties() {
|
||||||
|
clearSortOrder();
|
||||||
|
setColumns(minColumnOrder);
|
||||||
|
alignColumns();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restores the maximized state if the action history was left in
|
||||||
|
* maximized-state and is now re-entered.
|
||||||
|
*/
|
||||||
|
private void restorePreviousState() {
|
||||||
|
if (managementUIState.isActionHistoryMaximized()) {
|
||||||
|
createMaximizedContent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the alignment cell-style-generator that handles the alignment for
|
||||||
|
* the grid cells.
|
||||||
|
*/
|
||||||
|
private void alignColumns() {
|
||||||
|
setCellStyleGenerator(alignGenerator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds support for virtual properties (aka generated properties)
|
||||||
|
*/
|
||||||
|
class ActionHistoryGeneratedPropertySupport extends AbstractGeneratedPropertySupport {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GeneratedPropertyContainer getDecoratedContainer() {
|
||||||
|
return (GeneratedPropertyContainer) getContainerDataSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LazyQueryContainer getRawContainer() {
|
||||||
|
return (LazyQueryContainer) (getDecoratedContainer()).getWrappedContainer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected GeneratedPropertyContainer addGeneratedContainerProperties() {
|
||||||
|
final GeneratedPropertyContainer decoratedContainer = getDecoratedContainer();
|
||||||
|
|
||||||
|
decoratedContainer.addGeneratedProperty(VIRT_PROP_FORCED, new GenericPropertyValueGenerator());
|
||||||
|
decoratedContainer.addGeneratedProperty(VIRT_PROP_TIMEFORCED, new GenericPropertyValueGenerator());
|
||||||
|
decoratedContainer.addGeneratedProperty(VIRT_PROP_ACTION_CANCEL, new GenericPropertyValueGenerator());
|
||||||
|
decoratedContainer.addGeneratedProperty(VIRT_PROP_ACTION_FORCE, new GenericPropertyValueGenerator());
|
||||||
|
decoratedContainer.addGeneratedProperty(VIRT_PROP_ACTION_FORCE_QUIT, new GenericPropertyValueGenerator());
|
||||||
|
|
||||||
|
return decoratedContainer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds support to maximize the grid.
|
||||||
|
*/
|
||||||
|
class ActionHistoryMaximizeSupport extends AbstractMaximizeSupport {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the property-ids available in maximized-state.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void setMaximizedColumnProperties() {
|
||||||
|
clearSortOrder();
|
||||||
|
setColumns(maxColumnOrder);
|
||||||
|
alignColumns();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setMaximizedHiddenColumns() {
|
||||||
|
getColumn(ProxyAction.PXY_ACTION_ID).setHidden(false);
|
||||||
|
getColumn(ProxyAction.PXY_ACTION_ID).setHidable(true);
|
||||||
|
getColumn(ProxyAction.PXY_ACTION_ROLLOUT_NAME).setHidden(false);
|
||||||
|
getColumn(ProxyAction.PXY_ACTION_ROLLOUT_NAME).setHidable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets additional headers for the maximized-state.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void setMaximizedHeaders() {
|
||||||
|
getColumn(ProxyAction.PXY_ACTION_ID).setHeaderCaption(SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID);
|
||||||
|
getColumn(ProxyAction.PXY_ACTION_ROLLOUT_NAME)
|
||||||
|
.setHeaderCaption(SPUIDefinitions.ACTION_HIS_TBL_ROLLOUT_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the expand ratio for the maximized-state.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void setMaximizedColumnExpandRatio() {
|
||||||
|
/* set messages column can expand the rest of the available space */
|
||||||
|
setColumnsSize(50.0, 50.0, ProxyAction.PXY_ACTION_IS_ACTIVE_DECO);
|
||||||
|
setColumnsSize(FIXED_PIX_MIN, 100.0, ProxyAction.PXY_ACTION_ID);
|
||||||
|
setColumnsSize(107.0, 500.0, ProxyAction.PXY_ACTION_DS_NAME_VERSION);
|
||||||
|
setColumnsSize(100.0, 150.0, ProxyAction.PXY_ACTION_LAST_MODIFIED_AT);
|
||||||
|
setColumnsSize(53.0, 55.0, ProxyAction.PXY_ACTION_STATUS);
|
||||||
|
setColumnsSize(FIXED_PIX_MIN, FIXED_PIX_MAX, VIRT_PROP_FORCED, VIRT_PROP_TIMEFORCED,
|
||||||
|
VIRT_PROP_ACTION_CANCEL, VIRT_PROP_ACTION_FORCE, VIRT_PROP_ACTION_FORCE_QUIT);
|
||||||
|
setColumnsSize(FIXED_PIX_MIN, 500.0, ProxyAction.PXY_ACTION_ROLLOUT_NAME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concrete html-label converter that handles IsActiveDecoration enum.
|
||||||
|
*/
|
||||||
|
class HtmlIsActiveLabelConverter extends AbstractHtmlLabelConverter<IsActiveDecoration> {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor that sets the appropriate adapter.
|
||||||
|
*
|
||||||
|
* @param adapter
|
||||||
|
* adapts <code>IsActiveDecoration</code> to
|
||||||
|
* <code>String</code>
|
||||||
|
*/
|
||||||
|
public HtmlIsActiveLabelConverter(final LabelAdapter<IsActiveDecoration> adapter) {
|
||||||
|
addAdapter(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<IsActiveDecoration> getModelType() {
|
||||||
|
return IsActiveDecoration.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concrete html-label converter that handles Booleans. The converter needs
|
||||||
|
* an appropriate adapter that must be set via
|
||||||
|
* {@link AbstractHtmlLabelConverter#addAdapter()} to do the work.
|
||||||
|
*/
|
||||||
|
class HtmlBooleanLabelConverter extends AbstractHtmlLabelConverter<Boolean> {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<Boolean> getModelType() {
|
||||||
|
return Boolean.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concrete html-label converter that handles Actions.
|
||||||
|
*/
|
||||||
|
class HtmlVirtPropLabelConverter extends AbstractHtmlLabelConverter<Action> {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor that sets the appropriate adapter.
|
||||||
|
*
|
||||||
|
* @param adapter
|
||||||
|
* adapts <code>Action</code> to <code>String</code>
|
||||||
|
*/
|
||||||
|
public HtmlVirtPropLabelConverter(final LabelAdapter<Action> adapter) {
|
||||||
|
addAdapter(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<Action> getModelType() {
|
||||||
|
return Action.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concrete grid-button converter that handles Actions.
|
||||||
|
*/
|
||||||
|
class ActionGridButtonConverter extends AbstractGridButtonConverter<Action> {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor that sets the appropriate adapter.
|
||||||
|
*
|
||||||
|
* @param adapter
|
||||||
|
* adapts <code>Action</code> to <code>StatusFontIcon</code>
|
||||||
|
*/
|
||||||
|
public ActionGridButtonConverter(final GridButtonAdapter<Action> adapter) {
|
||||||
|
addAdapter(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<Action> getModelType() {
|
||||||
|
return Action.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generator class responsible to retrieve an Action from the grid data in
|
||||||
|
* order to generate a virtual property.
|
||||||
|
*/
|
||||||
|
class GenericPropertyValueGenerator extends PropertyValueGenerator<Action> {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Action getValue(final Item item, final Object itemId, final Object propertyId) {
|
||||||
|
return (Action) item.getItemProperty(ProxyAction.PXY_ACTION).getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<Action> getType() {
|
||||||
|
return Action.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generator class responsible to generate a button property value for the
|
||||||
|
* grid.
|
||||||
|
*/
|
||||||
|
class ButtonPropertyValueGenerator extends PropertyValueGenerator<String> {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final String buttonLabel;
|
||||||
|
|
||||||
|
public ButtonPropertyValueGenerator(final String buttonLabel) {
|
||||||
|
this.buttonLabel = buttonLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getValue(final Item item, final Object itemId, final Object propertyId) {
|
||||||
|
return buttonLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<String> getType() {
|
||||||
|
return String.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration that holds the styling properties for label- and
|
||||||
|
* button-renderers that are included in grid-cells.
|
||||||
|
*/
|
||||||
|
public static class LabelConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a map with all available status label metadata.
|
||||||
|
*
|
||||||
|
* @param i18n
|
||||||
|
* @param statusLabelId
|
||||||
|
* @return the configured map
|
||||||
|
*/
|
||||||
|
public Map<Action.Status, StatusFontIcon> createStatusLabelConfig(final VaadinMessageSource i18n,
|
||||||
|
final String statusLabelId) {
|
||||||
|
final HashMap<Action.Status, StatusFontIcon> stateMap = Maps.newHashMapWithExpectedSize(9);
|
||||||
|
stateMap.put(Action.Status.FINISHED, new StatusFontIcon(FontAwesome.CHECK_CIRCLE, STATUS_ICON_GREEN,
|
||||||
|
i18n.getMessage("label.finished"), statusLabelId));
|
||||||
|
stateMap.put(Action.Status.ERROR, new StatusFontIcon(FontAwesome.EXCLAMATION_CIRCLE, STATUS_ICON_RED,
|
||||||
|
i18n.getMessage("label.error"), statusLabelId));
|
||||||
|
stateMap.put(Action.Status.WARNING, new StatusFontIcon(FontAwesome.EXCLAMATION_CIRCLE, STATUS_ICON_ORANGE,
|
||||||
|
i18n.getMessage("label.warning"), statusLabelId));
|
||||||
|
stateMap.put(Action.Status.RUNNING, new StatusFontIcon(FontAwesome.ADJUST, STATUS_ICON_PENDING,
|
||||||
|
i18n.getMessage("label.running"), statusLabelId));
|
||||||
|
stateMap.put(Action.Status.CANCELING, new StatusFontIcon(FontAwesome.TIMES_CIRCLE, STATUS_ICON_PENDING,
|
||||||
|
i18n.getMessage("label.cancelling"), statusLabelId));
|
||||||
|
stateMap.put(Action.Status.CANCELED, new StatusFontIcon(FontAwesome.TIMES_CIRCLE, STATUS_ICON_GREEN,
|
||||||
|
i18n.getMessage("label.cancelled"), statusLabelId));
|
||||||
|
stateMap.put(Action.Status.RETRIEVED, new StatusFontIcon(FontAwesome.CIRCLE_O, STATUS_ICON_PENDING,
|
||||||
|
i18n.getMessage("label.retrieved"), statusLabelId));
|
||||||
|
stateMap.put(Action.Status.DOWNLOAD, new StatusFontIcon(FontAwesome.CLOUD_DOWNLOAD, STATUS_ICON_PENDING,
|
||||||
|
i18n.getMessage("label.download"), statusLabelId));
|
||||||
|
stateMap.put(Action.Status.SCHEDULED, new StatusFontIcon(FontAwesome.HOURGLASS_1, STATUS_ICON_PENDING,
|
||||||
|
i18n.getMessage("label.scheduled"), statusLabelId));
|
||||||
|
return stateMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a map with all available active-state metadata.
|
||||||
|
*
|
||||||
|
* @param activeStateId
|
||||||
|
* @return the configured map
|
||||||
|
*/
|
||||||
|
public Map<IsActiveDecoration, StatusFontIcon> createActiveStatusLabelConfig(final String activeStateId) {
|
||||||
|
final HashMap<IsActiveDecoration, StatusFontIcon> activeStateMap = Maps.newHashMapWithExpectedSize(4);
|
||||||
|
activeStateMap.put(IsActiveDecoration.SCHEDULED,
|
||||||
|
new StatusFontIcon(FontAwesome.HOURGLASS_1, STATUS_ICON_PENDING, "Scheduled", activeStateId));
|
||||||
|
activeStateMap.put(IsActiveDecoration.ACTIVE,
|
||||||
|
new StatusFontIcon(null, STATUS_ICON_ACTIVE, "Active", activeStateId));
|
||||||
|
activeStateMap.put(IsActiveDecoration.IN_ACTIVE,
|
||||||
|
new StatusFontIcon(FontAwesome.CHECK_CIRCLE, STATUS_ICON_NEUTRAL, "In-active", activeStateId));
|
||||||
|
activeStateMap.put(IsActiveDecoration.IN_ACTIVE_ERROR,
|
||||||
|
new StatusFontIcon(FontAwesome.CHECK_CIRCLE, STATUS_ICON_RED, "In-active", activeStateId));
|
||||||
|
return activeStateMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,149 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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.management.actionhistory;
|
|
||||||
|
|
||||||
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
|
|
||||||
import org.eclipse.hawkbit.ui.components.SPUIButton;
|
|
||||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
|
||||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
|
||||||
import org.eclipse.hawkbit.ui.management.event.ManagementUIEvent;
|
|
||||||
import org.eclipse.hawkbit.ui.management.state.ManagementUIState;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
|
||||||
import org.vaadin.spring.events.EventBus;
|
|
||||||
import org.vaadin.spring.events.EventBus.UIEventBus;
|
|
||||||
|
|
||||||
import com.vaadin.server.FontAwesome;
|
|
||||||
import com.vaadin.shared.ui.label.ContentMode;
|
|
||||||
import com.vaadin.ui.Alignment;
|
|
||||||
import com.vaadin.ui.HorizontalLayout;
|
|
||||||
import com.vaadin.ui.Label;
|
|
||||||
import com.vaadin.ui.VerticalLayout;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ActionHistoryHeader extends VerticalLayout {
|
|
||||||
private static final long serialVersionUID = -6276188234115774351L;
|
|
||||||
|
|
||||||
private final transient EventBus.UIEventBus eventBus;
|
|
||||||
private final ManagementUIState managementUIState;
|
|
||||||
|
|
||||||
private Label titleOfActionHistory;
|
|
||||||
private SPUIButton maxMinButton;
|
|
||||||
|
|
||||||
ActionHistoryHeader(final UIEventBus eventBus, final ManagementUIState managementUIState) {
|
|
||||||
this.eventBus = eventBus;
|
|
||||||
this.managementUIState = managementUIState;
|
|
||||||
buildComponent();
|
|
||||||
buildLayout();
|
|
||||||
restorePreviousState();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void buildComponent() {
|
|
||||||
// create default title - it will be shown even when no data is
|
|
||||||
// available
|
|
||||||
titleOfActionHistory = new LabelBuilder().name(HawkbitCommonUtil.getArtifactoryDetailsLabelId(""))
|
|
||||||
.buildCaptionLabel();
|
|
||||||
|
|
||||||
titleOfActionHistory.setImmediate(true);
|
|
||||||
titleOfActionHistory.setContentMode(ContentMode.HTML);
|
|
||||||
|
|
||||||
maxMinButton = (SPUIButton) SPUIComponentProvider.getButton(SPUIDefinitions.EXPAND_ACTION_HISTORY, "", "", null,
|
|
||||||
true, FontAwesome.EXPAND, SPUIButtonStyleSmallNoBorder.class);
|
|
||||||
// listener for maximizing action history
|
|
||||||
maxMinButton.addClickListener(event -> maxMinButtonClicked());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void buildLayout() {
|
|
||||||
final HorizontalLayout titleMaxIconsLayout = new HorizontalLayout();
|
|
||||||
titleMaxIconsLayout.addStyleName(SPUIStyleDefinitions.WIDGET_TITLE);
|
|
||||||
titleMaxIconsLayout.setSpacing(false);
|
|
||||||
titleMaxIconsLayout.setMargin(false);
|
|
||||||
titleMaxIconsLayout.setSizeFull();
|
|
||||||
titleMaxIconsLayout.addComponents(titleOfActionHistory, maxMinButton);
|
|
||||||
titleMaxIconsLayout.setComponentAlignment(titleOfActionHistory, Alignment.TOP_LEFT);
|
|
||||||
titleMaxIconsLayout.setComponentAlignment(maxMinButton, Alignment.TOP_RIGHT);
|
|
||||||
titleMaxIconsLayout.setExpandRatio(titleOfActionHistory, 0.8f);
|
|
||||||
titleMaxIconsLayout.setExpandRatio(maxMinButton, 0.2f);
|
|
||||||
|
|
||||||
// Note: here the only purpose of adding drop hints to the layout is to
|
|
||||||
// maintain consistent
|
|
||||||
// height for all widgets headers.
|
|
||||||
addComponent(titleMaxIconsLayout);
|
|
||||||
setComponentAlignment(titleMaxIconsLayout, Alignment.TOP_LEFT);
|
|
||||||
setWidth(100, Unit.PERCENTAGE);
|
|
||||||
setImmediate(true);
|
|
||||||
addStyleName("action-history-header");
|
|
||||||
addStyleName("bordered-layout");
|
|
||||||
addStyleName("no-border-bottom");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Populate Header Data for Target.
|
|
||||||
*
|
|
||||||
* @param targetName
|
|
||||||
* name of the target
|
|
||||||
*/
|
|
||||||
public void populateHeader(final String targetName) {
|
|
||||||
updateActionHistoryHeader(targetName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void maxMinButtonClicked() {
|
|
||||||
final Boolean flag = (Boolean) maxMinButton.getData();
|
|
||||||
if (flag == null || Boolean.FALSE.equals(flag)) {
|
|
||||||
// Clicked on max Icon
|
|
||||||
maximizedTableView();
|
|
||||||
managementUIState.setActionHistoryMaximized(Boolean.TRUE);
|
|
||||||
} else {
|
|
||||||
// Clicked on min icon
|
|
||||||
minimizeTableView();
|
|
||||||
managementUIState.setActionHistoryMaximized(Boolean.FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void maximizedTableView() {
|
|
||||||
showMinIcon();
|
|
||||||
eventBus.publish(this, ManagementUIEvent.MAX_ACTION_HISTORY);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void minimizeTableView() {
|
|
||||||
showMaxIcon();
|
|
||||||
eventBus.publish(this, ManagementUIEvent.MIN_ACTION_HISTORY);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates header with target name.
|
|
||||||
*
|
|
||||||
* @param targetName
|
|
||||||
* name of the target
|
|
||||||
*/
|
|
||||||
public void updateActionHistoryHeader(final String targetName) {
|
|
||||||
titleOfActionHistory.setValue(HawkbitCommonUtil.getActionHistoryLabelId(targetName));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showMinIcon() {
|
|
||||||
maxMinButton.togleIcon(FontAwesome.COMPRESS);
|
|
||||||
maxMinButton.setData(Boolean.TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showMaxIcon() {
|
|
||||||
maxMinButton.togleIcon(FontAwesome.EXPAND);
|
|
||||||
maxMinButton.setData(Boolean.FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void restorePreviousState() {
|
|
||||||
if (managementUIState.isActionHistoryMaximized()) {
|
|
||||||
showMinIcon();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,212 @@
|
|||||||
|
/**
|
||||||
|
* 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.management.actionhistory;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
||||||
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
|
import org.eclipse.hawkbit.ui.common.grid.AbstractGrid;
|
||||||
|
import org.eclipse.hawkbit.ui.common.grid.AbstractGridComponentLayout;
|
||||||
|
import org.eclipse.hawkbit.ui.common.grid.DefaultGridHeader;
|
||||||
|
import org.eclipse.hawkbit.ui.common.grid.DefaultGridHeader.AbstractHeaderMaximizeSupport;
|
||||||
|
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
|
||||||
|
import org.eclipse.hawkbit.ui.management.event.ManagementUIEvent;
|
||||||
|
import org.eclipse.hawkbit.ui.management.event.TargetTableEvent;
|
||||||
|
import org.eclipse.hawkbit.ui.management.state.ManagementUIState;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.UINotification;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
||||||
|
import org.vaadin.spring.events.EventBus.UIEventBus;
|
||||||
|
import org.vaadin.spring.events.EventScope;
|
||||||
|
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
|
||||||
|
|
||||||
|
import com.vaadin.ui.UI;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Layout responsible for action-history-grid and the corresponding header.
|
||||||
|
*/
|
||||||
|
public class ActionHistoryLayout extends AbstractGridComponentLayout {
|
||||||
|
private static final long serialVersionUID = -3766179797384539821L;
|
||||||
|
|
||||||
|
private final transient DeploymentManagement deploymentManagement;
|
||||||
|
private final UINotification notification;
|
||||||
|
private final ManagementUIState managementUIState;
|
||||||
|
|
||||||
|
private transient AbstractGrid<?>.DetailsSupport details;
|
||||||
|
private Long masterForDetails;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param i18n
|
||||||
|
* @param deploymentManagement
|
||||||
|
* @param eventBus
|
||||||
|
* @param notification
|
||||||
|
* @param managementUIState
|
||||||
|
*/
|
||||||
|
public ActionHistoryLayout(final VaadinMessageSource i18n, final DeploymentManagement deploymentManagement,
|
||||||
|
final UIEventBus eventBus, final UINotification notification, final ManagementUIState managementUIState) {
|
||||||
|
super(i18n, eventBus);
|
||||||
|
this.deploymentManagement = deploymentManagement;
|
||||||
|
this.notification = notification;
|
||||||
|
this.managementUIState = managementUIState;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionHistoryHeader createGridHeader() {
|
||||||
|
return new ActionHistoryHeader(managementUIState).init();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionHistoryGrid createGrid() {
|
||||||
|
return new ActionHistoryGrid(i18n, deploymentManagement, eventBus, notification, managementUIState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventBusListenerMethod(scope = EventScope.UI)
|
||||||
|
void onEvent(final TargetTableEvent targetUIEvent) {
|
||||||
|
if (BaseEntityEventType.SELECTED_ENTITY == targetUIEvent.getEventType()) {
|
||||||
|
setData(SPUIDefinitions.DATA_AVAILABLE);
|
||||||
|
UI.getCurrent().access(() -> populateActionHistoryDetails(targetUIEvent.getEntity()));
|
||||||
|
} else if (BaseEntityEventType.REMOVE_ENTITY == targetUIEvent.getEventType()
|
||||||
|
&& targetUIEvent.getEntityIds().contains(managementUIState.getLastSelectedTargetId())) {
|
||||||
|
setData(SPUIDefinitions.NO_DATA);
|
||||||
|
UI.getCurrent().access(this::populateActionHistoryDetails);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override default registration for selection propagation in order to
|
||||||
|
* interrupt update cascade in minimized state to prevent updates on
|
||||||
|
* invisible action-status-grid and message-grid.
|
||||||
|
* <p>
|
||||||
|
* The master selection is stored and propagation is performed as soon as
|
||||||
|
* the state changes to maximize and hence the dependent grids are updated.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void registerDetails(final AbstractGrid<?>.DetailsSupport details) {
|
||||||
|
this.details = details;
|
||||||
|
getGrid().addSelectionListener(event -> {
|
||||||
|
masterForDetails = (Long) event.getSelected().stream().findFirst().orElse(null);
|
||||||
|
if (managementUIState.isActionHistoryMaximized()) {
|
||||||
|
details.populateMasterDataAndRecalculateContainer(masterForDetails);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate action header and table for the target.
|
||||||
|
*
|
||||||
|
* @param target
|
||||||
|
* the target
|
||||||
|
*/
|
||||||
|
public void populateActionHistoryDetails(final Target target) {
|
||||||
|
if (null != target) {
|
||||||
|
((ActionHistoryHeader) getHeader()).updateActionHistoryHeader(target.getName());
|
||||||
|
((ActionHistoryGrid) getGrid()).populateSelectedTarget(target);
|
||||||
|
} else {
|
||||||
|
((ActionHistoryHeader) getHeader()).updateActionHistoryHeader(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate empty action header and empty table for empty selection.
|
||||||
|
*/
|
||||||
|
public void populateActionHistoryDetails() {
|
||||||
|
((ActionHistoryHeader) getHeader()).updateActionHistoryHeader(" ");
|
||||||
|
((ActionHistoryGrid) getGrid()).populateSelectedTarget(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Header for ActionHistory with maximize-support.
|
||||||
|
*/
|
||||||
|
class ActionHistoryHeader extends DefaultGridHeader {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param managementUIState
|
||||||
|
*/
|
||||||
|
ActionHistoryHeader(final ManagementUIState managementUIState) {
|
||||||
|
super(managementUIState);
|
||||||
|
this.setHeaderMaximizeSupport(
|
||||||
|
new ActionHistoryHeaderMaxSupport(this, SPUIDefinitions.EXPAND_ACTION_HISTORY));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the header.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ActionHistoryHeader init() {
|
||||||
|
super.init();
|
||||||
|
restorePreviousState();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates header with target name.
|
||||||
|
*
|
||||||
|
* @param targetName
|
||||||
|
* name of the target
|
||||||
|
*/
|
||||||
|
public void updateActionHistoryHeader(final String targetName) {
|
||||||
|
updateTitle(HawkbitCommonUtil.getActionHistoryLabelId(targetName));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restores the previous min-max state.
|
||||||
|
*/
|
||||||
|
private void restorePreviousState() {
|
||||||
|
if (hasHeaderMaximizeSupport() && managementUIState.isActionHistoryMaximized()) {
|
||||||
|
getHeaderMaximizeSupport().showMinIcon();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Min-max support for header.
|
||||||
|
*/
|
||||||
|
class ActionHistoryHeaderMaxSupport extends AbstractHeaderMaximizeSupport {
|
||||||
|
|
||||||
|
private final DefaultGridHeader abstractGridHeader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param abstractGridHeader
|
||||||
|
* @param maximizeButtonId
|
||||||
|
*/
|
||||||
|
protected ActionHistoryHeaderMaxSupport(final DefaultGridHeader abstractGridHeader,
|
||||||
|
final String maximizeButtonId) {
|
||||||
|
abstractGridHeader.super(maximizeButtonId);
|
||||||
|
this.abstractGridHeader = abstractGridHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void maximize() {
|
||||||
|
details.populateMasterDataAndRecreateContainer(masterForDetails);
|
||||||
|
eventBus.publish(this, ManagementUIEvent.MAX_ACTION_HISTORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void minimize() {
|
||||||
|
eventBus.publish(this, ManagementUIEvent.MIN_ACTION_HISTORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the grid header the maximize support is for.
|
||||||
|
*
|
||||||
|
* @return grid header
|
||||||
|
*/
|
||||||
|
protected DefaultGridHeader getGridHeader() {
|
||||||
|
return abstractGridHeader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,844 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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.management.actionhistory;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.StringJoiner;
|
|
||||||
|
|
||||||
import org.eclipse.hawkbit.repository.ActionStatusFields;
|
|
||||||
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
|
||||||
import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException;
|
|
||||||
import org.eclipse.hawkbit.repository.model.Action;
|
|
||||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
|
||||||
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
|
||||||
import org.eclipse.hawkbit.repository.model.ActionWithStatusCount;
|
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
|
||||||
import org.eclipse.hawkbit.ui.common.ConfirmationDialog;
|
|
||||||
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
|
|
||||||
import org.eclipse.hawkbit.ui.common.entity.TargetIdName;
|
|
||||||
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
|
|
||||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
|
||||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
|
||||||
import org.eclipse.hawkbit.ui.management.event.ManagementUIEvent;
|
|
||||||
import org.eclipse.hawkbit.ui.management.event.PinUnpinEvent;
|
|
||||||
import org.eclipse.hawkbit.ui.management.event.TargetTableEvent;
|
|
||||||
import org.eclipse.hawkbit.ui.management.state.ManagementUIState;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.UINotification;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.data.domain.Page;
|
|
||||||
import org.springframework.data.domain.PageRequest;
|
|
||||||
import org.springframework.data.domain.Pageable;
|
|
||||||
import org.springframework.data.domain.Sort;
|
|
||||||
import org.springframework.data.domain.Sort.Direction;
|
|
||||||
import org.vaadin.spring.events.EventBus;
|
|
||||||
import org.vaadin.spring.events.EventBus.UIEventBus;
|
|
||||||
import org.vaadin.spring.events.EventScope;
|
|
||||||
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
|
|
||||||
|
|
||||||
import com.vaadin.data.Container;
|
|
||||||
import com.vaadin.data.Item;
|
|
||||||
import com.vaadin.data.util.HierarchicalContainer;
|
|
||||||
import com.vaadin.server.FontAwesome;
|
|
||||||
import com.vaadin.shared.ui.label.ContentMode;
|
|
||||||
import com.vaadin.ui.Button;
|
|
||||||
import com.vaadin.ui.Component;
|
|
||||||
import com.vaadin.ui.HorizontalLayout;
|
|
||||||
import com.vaadin.ui.Label;
|
|
||||||
import com.vaadin.ui.Table;
|
|
||||||
import com.vaadin.ui.TextArea;
|
|
||||||
import com.vaadin.ui.TreeTable;
|
|
||||||
import com.vaadin.ui.UI;
|
|
||||||
import com.vaadin.ui.themes.ValoTheme;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Table for {@link Target#getActions()} history.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ActionHistoryTable extends TreeTable {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = -1631514704696786653L;
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ActionHistoryTable.class);
|
|
||||||
private static final String BUTTON_CANCEL = "button.cancel";
|
|
||||||
private static final String BUTTON_OK = "button.ok";
|
|
||||||
|
|
||||||
private final VaadinMessageSource i18n;
|
|
||||||
private final transient DeploymentManagement deploymentManagement;
|
|
||||||
private final transient EventBus.UIEventBus eventBus;
|
|
||||||
private final UINotification notification;
|
|
||||||
private final ManagementUIState managementUIState;
|
|
||||||
|
|
||||||
private Container hierarchicalContainer;
|
|
||||||
private boolean alreadyHasMessages;
|
|
||||||
|
|
||||||
private Target target;
|
|
||||||
|
|
||||||
ActionHistoryTable(final VaadinMessageSource i18n, final DeploymentManagement deploymentManagement, final UIEventBus eventBus,
|
|
||||||
final UINotification notification, final ManagementUIState managementUIState) {
|
|
||||||
this.i18n = i18n;
|
|
||||||
this.deploymentManagement = deploymentManagement;
|
|
||||||
this.eventBus = eventBus;
|
|
||||||
this.notification = notification;
|
|
||||||
this.managementUIState = managementUIState;
|
|
||||||
|
|
||||||
initializeTableSettings();
|
|
||||||
buildComponent();
|
|
||||||
restorePreviousState();
|
|
||||||
setVisibleColumns(getVisbleColumns().toArray());
|
|
||||||
eventBus.subscribe(this);
|
|
||||||
setPageLength(SPUIDefinitions.PAGE_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventBusListenerMethod(scope = EventScope.UI)
|
|
||||||
void onEvent(final ManagementUIEvent mgmtUIEvent) {
|
|
||||||
if (mgmtUIEvent == ManagementUIEvent.MAX_ACTION_HISTORY) {
|
|
||||||
UI.getCurrent().access(this::createTableContentForMax);
|
|
||||||
}
|
|
||||||
if (mgmtUIEvent == ManagementUIEvent.MIN_ACTION_HISTORY) {
|
|
||||||
UI.getCurrent().access(this::normalActionHistoryTable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* this method is called when the target history component is initialized
|
|
||||||
* without any data
|
|
||||||
*/
|
|
||||||
private void buildComponent() {
|
|
||||||
// create an empty container
|
|
||||||
createContainer();
|
|
||||||
setContainerDataSource(hierarchicalContainer);
|
|
||||||
addGeneratedColumns();
|
|
||||||
setColumnExpandRatioForMinimisedTable();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setColumnExpandRatioForMinimisedTable() {
|
|
||||||
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID, 0.1F);
|
|
||||||
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_DIST, 0.3F);
|
|
||||||
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_STATUS, 0.15F);
|
|
||||||
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_DATETIME, 0.3F);
|
|
||||||
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_FORCED, 0.15F);
|
|
||||||
setColumnExpandRatio(SPUIDefinitions.ACTIONS_COLUMN, 0.2F);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initializeTableSettings() {
|
|
||||||
|
|
||||||
setId(UIComponentIdProvider.ACTION_HISTORY_TABLE_ID);
|
|
||||||
setSelectable(false);
|
|
||||||
setMultiSelect(false);
|
|
||||||
setSortEnabled(true);
|
|
||||||
setColumnReorderingAllowed(true);
|
|
||||||
setHeight(100.0F, Unit.PERCENTAGE);
|
|
||||||
setWidth(100.0F, Unit.PERCENTAGE);
|
|
||||||
setImmediate(true);
|
|
||||||
setStyleName("sp-table");
|
|
||||||
addStyleName(ValoTheme.TABLE_NO_VERTICAL_LINES);
|
|
||||||
addStyleName(ValoTheme.TABLE_SMALL);
|
|
||||||
setColumnAlignment(SPUIDefinitions.ACTION_HIS_TBL_FORCED, Align.CENTER);
|
|
||||||
setColumnAlignment(SPUIDefinitions.ACTION_HIS_TBL_STATUS, Align.CENTER);
|
|
||||||
setColumnAlignment(SPUIDefinitions.ACTIONS_COLUMN, Align.CENTER);
|
|
||||||
// listeners for child
|
|
||||||
addExpandListener(event -> {
|
|
||||||
expandParentActionRow(event.getItemId());
|
|
||||||
managementUIState.getExpandParentActionRowId().add(event.getItemId());
|
|
||||||
});
|
|
||||||
addCollapseListener(event -> {
|
|
||||||
collapseParentActionRow(event.getItemId());
|
|
||||||
managementUIState.getExpandParentActionRowId().remove(event.getItemId());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a empty HierarchicalContainer.
|
|
||||||
*/
|
|
||||||
public void createContainer() {
|
|
||||||
/* Create HierarchicalContainer container */
|
|
||||||
hierarchicalContainer = new HierarchicalContainer();
|
|
||||||
hierarchicalContainer.addContainerProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE_HIDDEN, String.class, null);
|
|
||||||
hierarchicalContainer.addContainerProperty(SPUIDefinitions.ACTION_HIS_TBL_FORCED, Action.class, null);
|
|
||||||
hierarchicalContainer.addContainerProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID_HIDDEN, Long.class, null);
|
|
||||||
hierarchicalContainer.addContainerProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID, String.class, null);
|
|
||||||
hierarchicalContainer.addContainerProperty(SPUIDefinitions.ACTION_HIS_TBL_DIST, String.class, null);
|
|
||||||
hierarchicalContainer.addContainerProperty(SPUIDefinitions.ACTION_HIS_TBL_DATETIME, String.class, null);
|
|
||||||
hierarchicalContainer.addContainerProperty(SPUIDefinitions.ACTION_HIS_TBL_STATUS_HIDDEN, Action.Status.class,
|
|
||||||
null);
|
|
||||||
hierarchicalContainer.addContainerProperty(SPUIDefinitions.ACTION_HIS_TBL_MSGS_HIDDEN, List.class, null);
|
|
||||||
hierarchicalContainer.addContainerProperty(SPUIDefinitions.ACTION_HIS_TBL_ROLLOUT_NAME, String.class, null);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Object> getVisbleColumns() {
|
|
||||||
final List<Object> visibleColumnIds = new ArrayList<>();
|
|
||||||
visibleColumnIds.add(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE);
|
|
||||||
visibleColumnIds.add(SPUIDefinitions.ACTION_HIS_TBL_DIST);
|
|
||||||
visibleColumnIds.add(SPUIDefinitions.ACTION_HIS_TBL_DATETIME);
|
|
||||||
visibleColumnIds.add(SPUIDefinitions.ACTION_HIS_TBL_STATUS);
|
|
||||||
visibleColumnIds.add(SPUIDefinitions.ACTION_HIS_TBL_FORCED);
|
|
||||||
visibleColumnIds.add(SPUIDefinitions.ACTIONS_COLUMN);
|
|
||||||
|
|
||||||
if (managementUIState.isActionHistoryMaximized()) {
|
|
||||||
visibleColumnIds.add(SPUIDefinitions.ACTION_HIS_TBL_ROLLOUT_NAME);
|
|
||||||
visibleColumnIds.add(SPUIDefinitions.ACTION_HIS_TBL_MSGS);
|
|
||||||
visibleColumnIds.add(1, SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID);
|
|
||||||
}
|
|
||||||
return visibleColumnIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* fetch the target details using controller id, and set it globally.
|
|
||||||
*
|
|
||||||
* @param selectedTarget
|
|
||||||
* reference of target
|
|
||||||
*/
|
|
||||||
public void populateTableData(final Target selectedTarget) {
|
|
||||||
target = selectedTarget;
|
|
||||||
refreshContainer();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* re -create the container and get the data and set it to the table */
|
|
||||||
private void refreshContainer() {
|
|
||||||
getcontainerData();
|
|
||||||
// to expand parent row , if already expanded.
|
|
||||||
expandParentRow();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void getcontainerData() {
|
|
||||||
hierarchicalContainer.removeAllItems();
|
|
||||||
|
|
||||||
if (target != null) {
|
|
||||||
/* service method to create action history for target */
|
|
||||||
final List<ActionWithStatusCount> actionHistory = deploymentManagement
|
|
||||||
.findActionsWithStatusCountByTargetOrderByIdDesc(target.getControllerId());
|
|
||||||
|
|
||||||
addDetailsToContainer(actionHistory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Populate Container for Action.
|
|
||||||
*
|
|
||||||
* @param isActiveActions
|
|
||||||
* as flag
|
|
||||||
* @param reversedActions
|
|
||||||
* as action
|
|
||||||
* @param startIdx
|
|
||||||
* as sort
|
|
||||||
* @param target2
|
|
||||||
* @param actionHistoryMode
|
|
||||||
* as either {@link ActionHistoryMode.NORMAL} or
|
|
||||||
* {@link ActionHistoryMode.MAXIMIZED}
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private void addDetailsToContainer(final List<ActionWithStatusCount> actions) {
|
|
||||||
for (final ActionWithStatusCount actionWithStatusCount : actions) {
|
|
||||||
|
|
||||||
final Action action = actionWithStatusCount.getAction();
|
|
||||||
|
|
||||||
final Item item = hierarchicalContainer.addItem(actionWithStatusCount.getAction().getId());
|
|
||||||
|
|
||||||
item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_STATUS_HIDDEN)
|
|
||||||
.setValue(actionWithStatusCount.getAction().getStatus());
|
|
||||||
|
|
||||||
/*
|
|
||||||
* add action id.
|
|
||||||
*/
|
|
||||||
item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID)
|
|
||||||
.setValue(actionWithStatusCount.getAction().getId().toString());
|
|
||||||
/*
|
|
||||||
* add active/inactive status to the item which will be used in
|
|
||||||
* Column generator to generate respective icon
|
|
||||||
*/
|
|
||||||
item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE_HIDDEN).setValue(
|
|
||||||
actionWithStatusCount.getAction().isActive() ? SPUIDefinitions.ACTIVE : SPUIDefinitions.IN_ACTIVE);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* add action Id to the item which will be used for fetching child
|
|
||||||
* items ( previous action status ) during expand
|
|
||||||
*/
|
|
||||||
item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID_HIDDEN)
|
|
||||||
.setValue(actionWithStatusCount.getAction().getId());
|
|
||||||
|
|
||||||
/*
|
|
||||||
* add distribution name to the item which will be displayed in the
|
|
||||||
* table. The name should not exceed certain limit.
|
|
||||||
*/
|
|
||||||
item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_DIST)
|
|
||||||
.setValue(actionWithStatusCount.getDsName() + ":" + actionWithStatusCount.getDsVersion());
|
|
||||||
item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_FORCED).setValue(action);
|
|
||||||
|
|
||||||
/* Default no child */
|
|
||||||
((Hierarchical) hierarchicalContainer).setChildrenAllowed(actionWithStatusCount.getAction().getId(), false);
|
|
||||||
|
|
||||||
item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_DATETIME)
|
|
||||||
.setValue(SPDateTimeUtil.getFormattedDate(actionWithStatusCount.getAction().getLastModifiedAt()));
|
|
||||||
|
|
||||||
item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ROLLOUT_NAME)
|
|
||||||
.setValue(actionWithStatusCount.getRolloutName());
|
|
||||||
|
|
||||||
if (actionWithStatusCount.getActionStatusCount() > 0) {
|
|
||||||
((Hierarchical) hierarchicalContainer).setChildrenAllowed(actionWithStatusCount.getAction().getId(),
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addGeneratedColumns() {
|
|
||||||
addGeneratedColumn(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE, new Table.ColumnGenerator() {
|
|
||||||
/* Serial Verion Id */
|
|
||||||
private static final long serialVersionUID = -8673604389011758339L;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Component generateCell(final Table source, final Object itemId, final Object columnId) {
|
|
||||||
return getActiveColumn(itemId);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
addGeneratedColumn(SPUIDefinitions.ACTION_HIS_TBL_STATUS, new Table.ColumnGenerator() {
|
|
||||||
/* Serial Verion Id */
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Component generateCell(final Table source, final Object itemId, final Object columnId) {
|
|
||||||
return getStatusColumn(itemId);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// forced
|
|
||||||
addGeneratedColumn(SPUIDefinitions.ACTION_HIS_TBL_FORCED, new Table.ColumnGenerator() {
|
|
||||||
/* Serial Verion Id */
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Component generateCell(final Table source, final Object itemId, final Object columnId) {
|
|
||||||
return getForcedColumn(itemId);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
addGeneratedColumn(SPUIDefinitions.ACTIONS_COLUMN, new Table.ColumnGenerator() {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Component generateCell(final Table source, final Object itemId, final Object columnId) {
|
|
||||||
return createActionBarColumn(itemId);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private Component getForcedColumn(final Object itemId) {
|
|
||||||
final Action actionWithActiveStatus = (Action) hierarchicalContainer.getItem(itemId)
|
|
||||||
.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_FORCED).getValue();
|
|
||||||
final Label actionLabel = new LabelBuilder().name("").buildCaptionLabel();
|
|
||||||
actionLabel.setContentMode(ContentMode.HTML);
|
|
||||||
actionLabel.setStyleName("action-history-table-col-forced-label");
|
|
||||||
if (actionWithActiveStatus != null && actionWithActiveStatus.getActionType() == ActionType.FORCED) {
|
|
||||||
actionLabel.setValue(FontAwesome.BOLT.getHtml());
|
|
||||||
// setted Id for Forced.
|
|
||||||
actionLabel.setId("action.history.table.forcedId");
|
|
||||||
} else if (actionWithActiveStatus != null && actionWithActiveStatus.getActionType() == ActionType.TIMEFORCED) {
|
|
||||||
return actionLabelWithTimeForceIcon(actionWithActiveStatus, actionLabel);
|
|
||||||
}
|
|
||||||
return actionLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Component getActiveColumn(final Object itemId) {
|
|
||||||
final Action.Status status = (Action.Status) hierarchicalContainer.getItem(itemId)
|
|
||||||
.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_STATUS_HIDDEN).getValue();
|
|
||||||
String activeValue;
|
|
||||||
if (status == Action.Status.SCHEDULED) {
|
|
||||||
activeValue = Action.Status.SCHEDULED.toString().toLowerCase();
|
|
||||||
} else {
|
|
||||||
activeValue = (String) hierarchicalContainer.getItem(itemId)
|
|
||||||
.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE_HIDDEN).getValue();
|
|
||||||
}
|
|
||||||
final String distName = (String) hierarchicalContainer.getItem(itemId)
|
|
||||||
.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_DIST).getValue();
|
|
||||||
final Label activeStatusIcon = createActiveStatusLabel(activeValue,
|
|
||||||
(Action.Status) hierarchicalContainer.getItem(itemId)
|
|
||||||
.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_STATUS_HIDDEN)
|
|
||||||
.getValue() == Action.Status.ERROR);
|
|
||||||
activeStatusIcon.setId(new StringJoiner(".").add(distName).add(itemId.toString())
|
|
||||||
.add(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE).add(activeValue).toString());
|
|
||||||
return activeStatusIcon;
|
|
||||||
}
|
|
||||||
|
|
||||||
private HorizontalLayout createActionBarColumn(final Object itemId) {
|
|
||||||
final HorizontalLayout actionBar = new HorizontalLayout();
|
|
||||||
final Item item = hierarchicalContainer.getItem(itemId);
|
|
||||||
final Long actionId = (Long) item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID_HIDDEN).getValue();
|
|
||||||
final String activeValue = (String) item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE_HIDDEN)
|
|
||||||
.getValue();
|
|
||||||
final Action actionWithActiveStatus = (Action) item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_FORCED)
|
|
||||||
.getValue();
|
|
||||||
|
|
||||||
if (actionWithActiveStatus == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
final boolean isActionActive = target != null && SPUIDefinitions.ACTIVE.equals(activeValue);
|
|
||||||
|
|
||||||
final Button actionCancel = SPUIComponentProvider.getButton(
|
|
||||||
UIComponentIdProvider.ACTION_HISTORY_TABLE_CANCEL_ID, "", i18n.getMessage("message.cancel.action"),
|
|
||||||
ValoTheme.BUTTON_TINY, true, FontAwesome.TIMES, SPUIButtonStyleSmallNoBorder.class);
|
|
||||||
actionCancel.setEnabled(isActionActive && !actionWithActiveStatus.isCancelingOrCanceled());
|
|
||||||
actionCancel.addClickListener(event -> confirmAndCancelAction(actionId));
|
|
||||||
|
|
||||||
final Button actionForce = SPUIComponentProvider.getButton(UIComponentIdProvider.ACTION_HISTORY_TABLE_FORCE_ID,
|
|
||||||
"", i18n.getMessage("message.force.action"), ValoTheme.BUTTON_TINY, true, FontAwesome.BOLT,
|
|
||||||
SPUIButtonStyleSmallNoBorder.class);
|
|
||||||
actionForce.setEnabled(
|
|
||||||
isActionActive && !actionWithActiveStatus.isForce() && !actionWithActiveStatus.isCancelingOrCanceled());
|
|
||||||
actionForce.addClickListener(event -> confirmAndForceAction(actionId));
|
|
||||||
|
|
||||||
final Button actionForceQuit = SPUIComponentProvider.getButton(
|
|
||||||
UIComponentIdProvider.ACTION_HISTORY_TABLE_FORCE_QUIT_ID, "", i18n.getMessage("message.forcequit.action"),
|
|
||||||
ValoTheme.BUTTON_TINY + " redicon", true, FontAwesome.TIMES, SPUIButtonStyleSmallNoBorder.class);
|
|
||||||
actionForceQuit.setEnabled(isActionActive && actionWithActiveStatus.isCancelingOrCanceled());
|
|
||||||
actionForceQuit.addClickListener(event -> confirmAndForceQuitAction(actionId));
|
|
||||||
|
|
||||||
actionBar.addComponents(actionCancel, actionForce, actionForceQuit);
|
|
||||||
|
|
||||||
return actionBar;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Component getStatusColumn(final Object itemId) {
|
|
||||||
final Action.Status status = (Action.Status) hierarchicalContainer.getItem(itemId)
|
|
||||||
.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_STATUS_HIDDEN).getValue();
|
|
||||||
return getStatusIcon(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load the rows of previous status history of the selected action row and
|
|
||||||
* add it next to the selected action row.
|
|
||||||
*
|
|
||||||
* @param parentRowIdx
|
|
||||||
* index of the selected action row.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private void expandParentActionRow(final Object parentRowIdx) {
|
|
||||||
/* Get the item for which the expand is made */
|
|
||||||
final Item item = hierarchicalContainer.getItem(parentRowIdx);
|
|
||||||
if (null != item) {
|
|
||||||
final Long actionId = (Long) item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID_HIDDEN)
|
|
||||||
.getValue();
|
|
||||||
|
|
||||||
final Optional<Action> action = deploymentManagement.findActionWithDetails(actionId);
|
|
||||||
|
|
||||||
if (!action.isPresent()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Pageable pageReq = new PageRequest(0, 1000,
|
|
||||||
new Sort(Direction.DESC, ActionStatusFields.ID.getFieldName()));
|
|
||||||
final Page<ActionStatus> actionStatusList;
|
|
||||||
if (managementUIState.isActionHistoryMaximized()) {
|
|
||||||
actionStatusList = deploymentManagement.findActionStatusByActionWithMessages(pageReq, actionId);
|
|
||||||
} else {
|
|
||||||
actionStatusList = deploymentManagement.findActionStatusByAction(pageReq, actionId);
|
|
||||||
}
|
|
||||||
final List<ActionStatus> content = actionStatusList.getContent();
|
|
||||||
/*
|
|
||||||
* Since the recent action status and messages are already
|
|
||||||
* displaying with parent item, check if more than one action status
|
|
||||||
* available.
|
|
||||||
*/
|
|
||||||
int childIdx = 1;
|
|
||||||
for (final ActionStatus actionStatus : content) {
|
|
||||||
final String childId = parentRowIdx + " -> " + childIdx;
|
|
||||||
final Item childItem = hierarchicalContainer.addItem(childId);
|
|
||||||
if (null != childItem) {
|
|
||||||
/*
|
|
||||||
* For better UI, no need to display active/inactive icon
|
|
||||||
* for child items.
|
|
||||||
*/
|
|
||||||
childItem.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE_HIDDEN).setValue("");
|
|
||||||
|
|
||||||
childItem.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_DIST)
|
|
||||||
.setValue(action.get().getDistributionSet().getName() + ":"
|
|
||||||
+ action.get().getDistributionSet().getVersion());
|
|
||||||
|
|
||||||
childItem.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_DATETIME)
|
|
||||||
.setValue(SPDateTimeUtil.getFormattedDate(actionStatus.getCreatedAt()));
|
|
||||||
childItem.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_STATUS_HIDDEN)
|
|
||||||
.setValue(actionStatus.getStatus());
|
|
||||||
showOrHideMessage(childItem, actionStatus);
|
|
||||||
/* No further child items allowed for the child items */
|
|
||||||
((Hierarchical) hierarchicalContainer).setChildrenAllowed(childId, false);
|
|
||||||
/* Assign this childItem to the parent */
|
|
||||||
((Hierarchical) hierarchicalContainer).setParent(childId, parentRowIdx);
|
|
||||||
childIdx++;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hide the rows of previous status history of the selected action row.
|
|
||||||
*
|
|
||||||
* @param parentRowIdx
|
|
||||||
* index of the selected action row.
|
|
||||||
*/
|
|
||||||
public void collapseParentActionRow(final Object parentRowIdx) {
|
|
||||||
/* Remove all child items for the clear the memory. */
|
|
||||||
final Collection<?> children = ((Hierarchical) hierarchicalContainer).getChildren(parentRowIdx);
|
|
||||||
if (children != null && !children.isEmpty()) {
|
|
||||||
String ids = children.toString().substring(1);
|
|
||||||
ids = ids.substring(0, ids.length() - 1);
|
|
||||||
for (final String childId : ids.split(", ")) {
|
|
||||||
((Hierarchical) hierarchicalContainer).removeItem(childId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get status icon.
|
|
||||||
*
|
|
||||||
* @param status
|
|
||||||
* as Status
|
|
||||||
* @return Label as UI
|
|
||||||
*/
|
|
||||||
private Label getStatusIcon(final Action.Status status) {
|
|
||||||
final Label label = new LabelBuilder().name("").buildLabel();
|
|
||||||
label.setContentMode(ContentMode.HTML);
|
|
||||||
|
|
||||||
final ActionStatusIconMapper mapping = ActionStatusIconMapper.MAPPINGS.get(status);
|
|
||||||
|
|
||||||
if (mapping == null) {
|
|
||||||
label.setDescription("");
|
|
||||||
label.setValue("");
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
|
|
||||||
label.setDescription(i18n.getMessage(mapping.getDescriptionI18N()));
|
|
||||||
label.setStyleName(mapping.getStyleName());
|
|
||||||
label.setValue(mapping.getIcon().getHtml());
|
|
||||||
return label;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// to show forced Icon
|
|
||||||
private Component actionLabelWithTimeForceIcon(final Action actionWithActiveStatus, final Label actionLabel) {
|
|
||||||
final long currentTimeMillis = System.currentTimeMillis();
|
|
||||||
|
|
||||||
final HorizontalLayout hLayout = new HorizontalLayout();
|
|
||||||
final Label autoForceLabel = new LabelBuilder().name("").id("action.history.table.timedforceId").buildLabel();
|
|
||||||
|
|
||||||
actionLabel.setValue(FontAwesome.BOLT.getHtml());
|
|
||||||
autoForceLabel.setContentMode(ContentMode.HTML);
|
|
||||||
autoForceLabel.setValue(FontAwesome.HISTORY.getHtml());
|
|
||||||
|
|
||||||
hLayout.addComponent(actionLabel);
|
|
||||||
hLayout.addComponent(autoForceLabel);
|
|
||||||
|
|
||||||
if (actionWithActiveStatus.isHitAutoForceTime(currentTimeMillis)) {
|
|
||||||
autoForceLabel.setDescription("autoforced");
|
|
||||||
autoForceLabel.setStyleName(SPUIStyleDefinitions.STATUS_ICON_GREEN);
|
|
||||||
autoForceLabel.setDescription("auto forced since " + SPDateTimeUtil
|
|
||||||
.getDurationFormattedString(actionWithActiveStatus.getForcedTime(), currentTimeMillis, i18n));
|
|
||||||
} else {
|
|
||||||
autoForceLabel.setDescription("auto forcing in " + SPDateTimeUtil
|
|
||||||
.getDurationFormattedString(currentTimeMillis, actionWithActiveStatus.getForcedTime(), i18n));
|
|
||||||
autoForceLabel.setStyleName("statusIconPending");
|
|
||||||
autoForceLabel.setValue(FontAwesome.HISTORY.getHtml());
|
|
||||||
}
|
|
||||||
return hLayout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create Status Label.
|
|
||||||
*
|
|
||||||
* @param activeValue
|
|
||||||
* as String
|
|
||||||
* @return Labeal as UI
|
|
||||||
*/
|
|
||||||
private static Label createActiveStatusLabel(final String activeValue, final boolean endedWithError) {
|
|
||||||
final Label label = new LabelBuilder().name("").buildLabel();
|
|
||||||
label.setContentMode(ContentMode.HTML);
|
|
||||||
if (SPUIDefinitions.SCHEDULED.equals(activeValue)) {
|
|
||||||
label.setDescription("Scheduled");
|
|
||||||
label.setValue(FontAwesome.HOURGLASS_1.getHtml());
|
|
||||||
} else if (SPUIDefinitions.ACTIVE.equals(activeValue)) {
|
|
||||||
label.setDescription("Active");
|
|
||||||
label.setStyleName("statusIconActive");
|
|
||||||
} else if (SPUIDefinitions.IN_ACTIVE.equals(activeValue)) {
|
|
||||||
if (endedWithError) {
|
|
||||||
label.setStyleName(SPUIStyleDefinitions.STATUS_ICON_RED);
|
|
||||||
} else {
|
|
||||||
label.setStyleName("statusIconNeutral");
|
|
||||||
}
|
|
||||||
label.setDescription("In-active");
|
|
||||||
label.setValue(FontAwesome.CHECK_CIRCLE.getHtml());
|
|
||||||
} else {
|
|
||||||
label.setValue("");
|
|
||||||
}
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates full sized window for action history with message.
|
|
||||||
*/
|
|
||||||
private void createTableContentForMax() {
|
|
||||||
setColumnCollapsingAllowed(true);
|
|
||||||
if (!alreadyHasMessages) {
|
|
||||||
/*
|
|
||||||
* check to avoid DB call for fetching the messages again and again
|
|
||||||
* if already available in container.
|
|
||||||
*/
|
|
||||||
getcontainerData();
|
|
||||||
// to expand parent row , if already expanded.
|
|
||||||
expandParentRow();
|
|
||||||
alreadyHasMessages = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
addGeneratedColumn(SPUIDefinitions.ACTION_HIS_TBL_MSGS, new Table.ColumnGenerator() {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public Component generateCell(final Table source, final Object itemId, final Object columnId) {
|
|
||||||
final List<String> messages = (List<String>) hierarchicalContainer.getItem(itemId)
|
|
||||||
.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_MSGS_HIDDEN).getValue();
|
|
||||||
return createMessagesBlock(messages);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
setVisibleColumns(getVisbleColumns().toArray());
|
|
||||||
setColumnExpantRatioOnTableMaximize();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setColumnExpantRatioOnTableMaximize() {
|
|
||||||
/* set messages column can expand the rest of the available space */
|
|
||||||
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE, 0.1F);
|
|
||||||
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID, 0.1F);
|
|
||||||
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_STATUS, 0.1F);
|
|
||||||
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_DIST, 0.2F);
|
|
||||||
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_FORCED, 0.1F);
|
|
||||||
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_ROLLOUT_NAME, 0.1F);
|
|
||||||
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_MSGS, 0.35F);
|
|
||||||
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_DATETIME, 0.15F);
|
|
||||||
setColumnExpandRatio(SPUIDefinitions.ACTIONS_COLUMN, 0.2F);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create Message block for Actions.
|
|
||||||
*
|
|
||||||
* @param messages
|
|
||||||
* as List of msg
|
|
||||||
* @return Component as UI
|
|
||||||
*/
|
|
||||||
protected Component createMessagesBlock(final List<String> messages) {
|
|
||||||
|
|
||||||
final TextArea textArea = new TextArea();
|
|
||||||
textArea.addStyleName(ValoTheme.TEXTAREA_BORDERLESS);
|
|
||||||
textArea.addStyleName(ValoTheme.TEXTAREA_TINY);
|
|
||||||
textArea.addStyleName("inline-icon");
|
|
||||||
textArea.setSizeFull();
|
|
||||||
int index = 1;
|
|
||||||
final StringBuilder updateStatusMessages = new StringBuilder();
|
|
||||||
if (messages != null && !messages.isEmpty()) {
|
|
||||||
/* Messages are available */
|
|
||||||
for (final String msg : messages) {
|
|
||||||
updateStatusMessages.append('[').append(index).append("]: ").append(msg).append('\n');
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Messages are not available */
|
|
||||||
updateStatusMessages.append(i18n.getMessage("message.no.available"));
|
|
||||||
}
|
|
||||||
textArea.setValue(updateStatusMessages.toString());
|
|
||||||
textArea.setReadOnly(Boolean.TRUE);
|
|
||||||
return textArea;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show or hide message.
|
|
||||||
*
|
|
||||||
* @param actionHistoryMode
|
|
||||||
* {@link ActionHisTableType}
|
|
||||||
* @param childItem
|
|
||||||
* {@link Item}
|
|
||||||
* @param actionStatus
|
|
||||||
* {@link ActionHisTableType}
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private void showOrHideMessage(final Item childItem, final ActionStatus actionStatus) {
|
|
||||||
if (managementUIState.isActionHistoryMaximized()) {
|
|
||||||
childItem.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_MSGS_HIDDEN).setValue(actionStatus.getMessages());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* View History Table in normal window mode.
|
|
||||||
*/
|
|
||||||
private void normalActionHistoryTable() {
|
|
||||||
setColumnCollapsingAllowed(false);
|
|
||||||
managementUIState.setActionHistoryMaximized(false);
|
|
||||||
removeGeneratedColumn(SPUIDefinitions.ACTION_HIS_TBL_MSGS);
|
|
||||||
setVisibleColumns(getVisbleColumns().toArray());
|
|
||||||
setColumnExpandRatioForMinimisedTable();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show confirmation window and if ok then only, force the action.
|
|
||||||
*
|
|
||||||
* @param actionId
|
|
||||||
* as Id if the action needs to be forced.
|
|
||||||
*/
|
|
||||||
private void confirmAndForceAction(final Long actionId) {
|
|
||||||
/* Display the confirmation */
|
|
||||||
final ConfirmationDialog confirmDialog = new ConfirmationDialog(i18n.getMessage("caption.force.action.confirmbox"),
|
|
||||||
i18n.getMessage("message.force.action.confirm"), i18n.getMessage(BUTTON_OK), i18n.getMessage(BUTTON_CANCEL), ok -> {
|
|
||||||
if (!ok) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
deploymentManagement.forceTargetAction(actionId);
|
|
||||||
populateAndupdateTargetDetails(target);
|
|
||||||
notification.displaySuccess(i18n.getMessage("message.force.action.success"));
|
|
||||||
});
|
|
||||||
UI.getCurrent().addWindow(confirmDialog.getWindow());
|
|
||||||
|
|
||||||
confirmDialog.getWindow().bringToFront();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void confirmAndForceQuitAction(final Long actionId) {
|
|
||||||
/* Display the confirmation */
|
|
||||||
final ConfirmationDialog confirmDialog = new ConfirmationDialog(i18n.getMessage("caption.forcequit.action.confirmbox"),
|
|
||||||
i18n.getMessage("message.forcequit.action.confirm"), i18n.getMessage(BUTTON_OK), i18n.getMessage(BUTTON_CANCEL), ok -> {
|
|
||||||
if (!ok) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final boolean cancelResult = forceQuitActiveAction(actionId);
|
|
||||||
if (cancelResult) {
|
|
||||||
populateAndupdateTargetDetails(target);
|
|
||||||
notification.displaySuccess(i18n.getMessage("message.forcequit.action.success"));
|
|
||||||
} else {
|
|
||||||
notification.displayValidationError(i18n.getMessage("message.forcequit.action.failed"));
|
|
||||||
}
|
|
||||||
}, FontAwesome.WARNING);
|
|
||||||
UI.getCurrent().addWindow(confirmDialog.getWindow());
|
|
||||||
|
|
||||||
confirmDialog.getWindow().bringToFront();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show confirmation window and if ok then only, cancel the action.
|
|
||||||
*
|
|
||||||
* @param actionId
|
|
||||||
* as Id if the action needs to be cancelled.
|
|
||||||
*/
|
|
||||||
private void confirmAndCancelAction(final Long actionId) {
|
|
||||||
if (actionId == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final ConfirmationDialog confirmDialog = new ConfirmationDialog(i18n.getMessage("caption.cancel.action.confirmbox"),
|
|
||||||
i18n.getMessage("message.cancel.action.confirm"), i18n.getMessage(BUTTON_OK), i18n.getMessage(BUTTON_CANCEL), ok -> {
|
|
||||||
if (!ok) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final boolean cancelResult = cancelActiveAction(actionId);
|
|
||||||
if (cancelResult) {
|
|
||||||
populateAndupdateTargetDetails(target);
|
|
||||||
notification.displaySuccess(i18n.getMessage("message.cancel.action.success"));
|
|
||||||
} else {
|
|
||||||
notification.displayValidationError(i18n.getMessage("message.cancel.action.failed"));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
UI.getCurrent().addWindow(confirmDialog.getWindow());
|
|
||||||
confirmDialog.getWindow().bringToFront();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void populateAndupdateTargetDetails(final Target target) {
|
|
||||||
// show the updated target action history details
|
|
||||||
populateTableData(target);
|
|
||||||
// update the target table and its pinning details
|
|
||||||
updateTargetAndDsTable();
|
|
||||||
}
|
|
||||||
|
|
||||||
// service call to cancel the active action
|
|
||||||
private boolean cancelActiveAction(final Long actionId) {
|
|
||||||
if (actionId != null) {
|
|
||||||
try {
|
|
||||||
deploymentManagement.cancelAction(actionId);
|
|
||||||
return true;
|
|
||||||
} catch (final CancelActionNotAllowedException e) {
|
|
||||||
LOG.info("Cancel action not allowed exception :{}", e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// service call to cancel the active action
|
|
||||||
private boolean forceQuitActiveAction(final Long actionId) {
|
|
||||||
if (actionId != null) {
|
|
||||||
try {
|
|
||||||
deploymentManagement.forceQuitAction(actionId);
|
|
||||||
return true;
|
|
||||||
} catch (final CancelActionNotAllowedException e) {
|
|
||||||
LOG.info("Force Cancel action not allowed exception :{}", e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateTargetAndDsTable() {
|
|
||||||
eventBus.publish(this, new TargetTableEvent(BaseEntityEventType.UPDATED_ENTITY, target));
|
|
||||||
updateDistributionTableStyle();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the colors of Assigned and installed distribution set in Target
|
|
||||||
* Pinning.
|
|
||||||
*/
|
|
||||||
private void updateDistributionTableStyle() {
|
|
||||||
if (managementUIState.getDistributionTableFilters().getPinnedTarget().map(TargetIdName::getTargetId)
|
|
||||||
.map(target.getId()::equals).orElse(false)) {
|
|
||||||
eventBus.publish(this, PinUnpinEvent.PIN_TARGET);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* empty the container when there is no data selected in Target Table.
|
|
||||||
*/
|
|
||||||
public void clearContainerData() {
|
|
||||||
getContainerDataSource().removeAllItems();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set messages false.
|
|
||||||
*
|
|
||||||
* @param alreadyHasMessages
|
|
||||||
* the alreadyHasMessages to set
|
|
||||||
*/
|
|
||||||
public void setAlreadyHasMessages(final boolean alreadyHasMessages) {
|
|
||||||
this.alreadyHasMessages = alreadyHasMessages;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void restorePreviousState() {
|
|
||||||
if (managementUIState.isActionHistoryMaximized()) {
|
|
||||||
createTableContentForMax();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void expandParentRow() {
|
|
||||||
if (null != managementUIState.getExpandParentActionRowId()
|
|
||||||
&& !managementUIState.getExpandParentActionRowId().isEmpty()) {
|
|
||||||
for (final Object obj : managementUIState.getExpandParentActionRowId()) {
|
|
||||||
expandParentActionRow(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,153 @@
|
|||||||
|
/**
|
||||||
|
* 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.management.actionhistory;
|
||||||
|
|
||||||
|
import static org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil.isNotNullOrEmpty;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
||||||
|
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.SpringContextHelper;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
|
import org.springframework.data.domain.Sort.Direction;
|
||||||
|
import org.vaadin.addons.lazyquerycontainer.AbstractBeanQuery;
|
||||||
|
import org.vaadin.addons.lazyquerycontainer.QueryDefinition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple implementation of generics bean query which dynamically loads
|
||||||
|
* {@link ProxyActionStatus} batch of beans.
|
||||||
|
*/
|
||||||
|
public class ActionStatusBeanQuery extends AbstractBeanQuery<ProxyActionStatus> {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private Sort sort = new Sort(Direction.DESC, "id");
|
||||||
|
private transient DeploymentManagement deploymentManagement;
|
||||||
|
|
||||||
|
private Long currentSelectedActionId;
|
||||||
|
private transient Page<ActionStatus> firstPageActionStates;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parametric Constructor.
|
||||||
|
*
|
||||||
|
* @param definition
|
||||||
|
* QueryDefinition contains the query properties.
|
||||||
|
* @param queryConfig
|
||||||
|
* Implementation specific configuration.
|
||||||
|
* @param sortPropertyIds
|
||||||
|
* The properties participating in sort.
|
||||||
|
* @param sortStates
|
||||||
|
* The ascending or descending state of sort properties.
|
||||||
|
*/
|
||||||
|
public ActionStatusBeanQuery(final QueryDefinition definition, final Map<String, Object> queryConfig,
|
||||||
|
final Object[] sortPropertyIds, final boolean[] sortStates) {
|
||||||
|
super(definition, queryConfig, sortPropertyIds, sortStates);
|
||||||
|
|
||||||
|
if (isNotNullOrEmpty(queryConfig)) {
|
||||||
|
currentSelectedActionId = (Long) queryConfig.get(SPUIDefinitions.ACTIONSTATES_BY_ACTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sortStates.length > 0) {
|
||||||
|
// Initialize sort
|
||||||
|
sort = new Sort(sortStates[0] ? Direction.ASC : Direction.DESC, (String) sortPropertyIds[0]);
|
||||||
|
// Add sort
|
||||||
|
for (int distId = 1; distId < sortPropertyIds.length; distId++) {
|
||||||
|
sort.and(new Sort(sortStates[distId] ? Direction.ASC : Direction.DESC,
|
||||||
|
(String) sortPropertyIds[distId]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ProxyActionStatus constructBean() {
|
||||||
|
return new ProxyActionStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<ProxyActionStatus> loadBeans(final int startIndex, final int count) {
|
||||||
|
Page<ActionStatus> actionBeans;
|
||||||
|
if (startIndex == 0 && firstPageActionStates != null) {
|
||||||
|
actionBeans = firstPageActionStates;
|
||||||
|
} else {
|
||||||
|
actionBeans = getDeploymentManagement()
|
||||||
|
.findActionStatusByAction(
|
||||||
|
new PageRequest(startIndex / SPUIDefinitions.PAGE_SIZE, SPUIDefinitions.PAGE_SIZE, sort),
|
||||||
|
currentSelectedActionId);
|
||||||
|
}
|
||||||
|
return createProxyActionStates(actionBeans);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a list of {@link ProxyActionStatus} for presentation layer from
|
||||||
|
* page of {@link ActionStatus}.
|
||||||
|
*
|
||||||
|
* @param actionBeans
|
||||||
|
* page of {@link ActionStatus}
|
||||||
|
* @return list of {@link ProxyActionStatus}
|
||||||
|
*/
|
||||||
|
private static List<ProxyActionStatus> createProxyActionStates(final Page<ActionStatus> actionStatusBeans) {
|
||||||
|
final List<ProxyActionStatus> proxyActionStates = new ArrayList<>();
|
||||||
|
for (final ActionStatus actionStatus : actionStatusBeans) {
|
||||||
|
final ProxyActionStatus proxyAS = new ProxyActionStatus();
|
||||||
|
proxyAS.setCreatedAt(actionStatus.getCreatedAt());
|
||||||
|
proxyAS.setStatus(actionStatus.getStatus());
|
||||||
|
proxyAS.setId(actionStatus.getId());
|
||||||
|
|
||||||
|
proxyActionStates.add(proxyAS);
|
||||||
|
}
|
||||||
|
return proxyActionStates;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see
|
||||||
|
* org.vaadin.addons.lazyquerycontainer.AbstractBeanQuery#saveBeans(java
|
||||||
|
* .util.List, java.util.List, java.util.List)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void saveBeans(List<ProxyActionStatus> addedBeans, List<ProxyActionStatus> modifiedBeans,
|
||||||
|
List<ProxyActionStatus> removedBeans) {
|
||||||
|
// CRUD operations on Target will be done through repository methods
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
long size = 0;
|
||||||
|
|
||||||
|
if (currentSelectedActionId != null) {
|
||||||
|
firstPageActionStates = getDeploymentManagement().findActionStatusByAction(
|
||||||
|
new PageRequest(0, SPUIDefinitions.PAGE_SIZE, sort), currentSelectedActionId);
|
||||||
|
size = firstPageActionStates.getTotalElements();
|
||||||
|
}
|
||||||
|
if (size > Integer.MAX_VALUE) {
|
||||||
|
return Integer.MAX_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lazy gets deploymentManagement.
|
||||||
|
*
|
||||||
|
* @return the deploymentManagement
|
||||||
|
*/
|
||||||
|
public DeploymentManagement getDeploymentManagement() {
|
||||||
|
if (null == deploymentManagement) {
|
||||||
|
deploymentManagement = SpringContextHelper.getBean(DeploymentManagement.class);
|
||||||
|
}
|
||||||
|
return deploymentManagement;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,159 @@
|
|||||||
|
/**
|
||||||
|
* 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.management.actionhistory;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.model.Action;
|
||||||
|
import org.eclipse.hawkbit.ui.common.grid.AbstractGrid;
|
||||||
|
import org.eclipse.hawkbit.ui.customrenderers.renderers.HtmlLabelRenderer;
|
||||||
|
import org.eclipse.hawkbit.ui.management.actionhistory.ActionHistoryGrid.LabelConfig;
|
||||||
|
import org.eclipse.hawkbit.ui.rollout.StatusFontIcon;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
||||||
|
import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory;
|
||||||
|
import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer;
|
||||||
|
import org.vaadin.addons.lazyquerycontainer.LazyQueryDefinition;
|
||||||
|
import org.vaadin.spring.events.EventBus.UIEventBus;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This grid presents the action states for a selected action.
|
||||||
|
*/
|
||||||
|
public class ActionStatusGrid extends AbstractGrid<LazyQueryContainer> {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private static final String[] leftAlignedColumns = new String[] { ProxyActionStatus.PXY_AS_CREATED_AT };
|
||||||
|
|
||||||
|
private static final String[] centerAlignedColumns = new String[] { ProxyActionStatus.PXY_AS_STATUS };
|
||||||
|
|
||||||
|
private final AlignCellStyleGenerator alignGenerator;
|
||||||
|
private final ModifiedTimeTooltipGenerator modTimetooltipGenerator;
|
||||||
|
|
||||||
|
private final Map<Action.Status, StatusFontIcon> states;
|
||||||
|
|
||||||
|
private final BeanQueryFactory<ActionStatusBeanQuery> targetQF = new BeanQueryFactory<>(
|
||||||
|
ActionStatusBeanQuery.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param i18n
|
||||||
|
* @param eventBus
|
||||||
|
*/
|
||||||
|
protected ActionStatusGrid(final VaadinMessageSource i18n, final UIEventBus eventBus) {
|
||||||
|
super(i18n, eventBus, null);
|
||||||
|
|
||||||
|
setSingleSelectionSupport(new SingleSelectionSupport());
|
||||||
|
setDetailsSupport(new DetailsSupport());
|
||||||
|
|
||||||
|
final LabelConfig conf = new ActionHistoryGrid.LabelConfig();
|
||||||
|
states = conf.createStatusLabelConfig(i18n, UIComponentIdProvider.ACTION_STATUS_GRID_STATUS_LABEL_ID);
|
||||||
|
alignGenerator = new AlignCellStyleGenerator(leftAlignedColumns, centerAlignedColumns, null);
|
||||||
|
modTimetooltipGenerator = new ModifiedTimeTooltipGenerator(ProxyActionStatus.PXY_AS_CREATED_AT);
|
||||||
|
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected LazyQueryContainer createContainer() {
|
||||||
|
configureQueryFactory();
|
||||||
|
return new LazyQueryContainer(
|
||||||
|
new LazyQueryDefinition(true, SPUIDefinitions.PAGE_SIZE, ProxyActionStatus.PXY_AS_ID), targetQF);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshContainer() {
|
||||||
|
configureQueryFactory();
|
||||||
|
super.refreshContainer();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void configureQueryFactory() {
|
||||||
|
// ADD all the filters to the query config
|
||||||
|
final Map<String, Object> queryConfig = Maps.newHashMapWithExpectedSize(1);
|
||||||
|
queryConfig.put(SPUIDefinitions.ACTIONSTATES_BY_ACTION, getDetailsSupport().getMasterDataId());
|
||||||
|
// Create ActionBeanQuery factory with the query config.
|
||||||
|
targetQF.setQueryConfiguration(queryConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets type-save access to LazyQueryContainer.
|
||||||
|
*
|
||||||
|
* @return LazyQueryContainer
|
||||||
|
*/
|
||||||
|
private LazyQueryContainer getLazyQueryContainer() {
|
||||||
|
return (LazyQueryContainer) getContainerDataSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addContainerProperties() {
|
||||||
|
final LazyQueryContainer lqContainer = getLazyQueryContainer();
|
||||||
|
lqContainer.addContainerProperty(ProxyActionStatus.PXY_AS_CREATED_AT, Long.class, null, true, true);
|
||||||
|
lqContainer.addContainerProperty(ProxyActionStatus.PXY_AS_STATUS, Action.Status.class, null, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setColumnExpandRatio() {
|
||||||
|
getColumn(ProxyActionStatus.PXY_AS_STATUS).setMinimumWidth(53);
|
||||||
|
getColumn(ProxyActionStatus.PXY_AS_STATUS).setMaximumWidth(55);
|
||||||
|
getColumn(ProxyActionStatus.PXY_AS_CREATED_AT).setMinimumWidth(100);
|
||||||
|
getColumn(ProxyActionStatus.PXY_AS_CREATED_AT).setMaximumWidth(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setColumnHeaderNames() {
|
||||||
|
getColumn(ProxyActionStatus.PXY_AS_STATUS).setHeaderCaption(SPUIDefinitions.ACTION_HIS_TBL_STATUS);
|
||||||
|
getColumn(ProxyActionStatus.PXY_AS_CREATED_AT).setHeaderCaption(SPUIDefinitions.ACTION_HIS_TBL_DATETIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getGridId() {
|
||||||
|
return UIComponentIdProvider.ACTION_HISTORY_DETAILS_GRID_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setColumnProperties() {
|
||||||
|
clearSortOrder();
|
||||||
|
setColumns(ProxyActionStatus.PXY_AS_STATUS, ProxyActionStatus.PXY_AS_CREATED_AT);
|
||||||
|
alignColumns();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addColumnRenderes() {
|
||||||
|
getColumn(ProxyActionStatus.PXY_AS_STATUS).setRenderer(new HtmlLabelRenderer(),
|
||||||
|
new HtmlStatusLabelConverter(this::createStatusLabelMetadata));
|
||||||
|
getColumn(ProxyActionStatus.PXY_AS_CREATED_AT).setConverter(new LongToFormattedDateStringConverter());
|
||||||
|
}
|
||||||
|
|
||||||
|
private StatusFontIcon createStatusLabelMetadata(final Action.Status status) {
|
||||||
|
return states.get(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setHiddenColumns() {
|
||||||
|
getColumn(ProxyActionStatus.PXY_AS_STATUS).setHidable(false);
|
||||||
|
getColumn(ProxyActionStatus.PXY_AS_CREATED_AT).setHidable(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the alignment cell-style-generator that handles the alignment for
|
||||||
|
* the grid cells.
|
||||||
|
*/
|
||||||
|
private void alignColumns() {
|
||||||
|
setCellStyleGenerator(alignGenerator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected CellDescriptionGenerator getDescriptionGenerator() {
|
||||||
|
return modTimetooltipGenerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* 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.management.actionhistory;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.ui.common.grid.AbstractGridComponentLayout;
|
||||||
|
import org.eclipse.hawkbit.ui.common.grid.DefaultGridHeader;
|
||||||
|
import org.eclipse.hawkbit.ui.management.state.ManagementUIState;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
||||||
|
import org.vaadin.spring.events.EventBus.UIEventBus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Layout responsible for action-states-grid and the corresponding header.
|
||||||
|
*/
|
||||||
|
public class ActionStatusLayout extends AbstractGridComponentLayout {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
protected final ManagementUIState managementUIState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param i18n
|
||||||
|
* @param eventBus
|
||||||
|
* @param managementUIState
|
||||||
|
*/
|
||||||
|
public ActionStatusLayout(final VaadinMessageSource i18n, final UIEventBus eventBus,
|
||||||
|
final ManagementUIState managementUIState) {
|
||||||
|
super(i18n, eventBus);
|
||||||
|
this.managementUIState = managementUIState;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DefaultGridHeader createGridHeader() {
|
||||||
|
return new DefaultGridHeader(managementUIState, "Action States").init();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionStatusGrid createGrid() {
|
||||||
|
return new ActionStatusGrid(i18n, eventBus);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,161 @@
|
|||||||
|
/**
|
||||||
|
* 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.management.actionhistory;
|
||||||
|
|
||||||
|
import static org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil.isNotNullOrEmpty;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
||||||
|
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.SpringContextHelper;
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
|
import org.springframework.data.domain.Sort.Direction;
|
||||||
|
import org.vaadin.addons.lazyquerycontainer.AbstractBeanQuery;
|
||||||
|
import org.vaadin.addons.lazyquerycontainer.QueryDefinition;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple implementation of generic bean query which dynamically loads
|
||||||
|
* {@link ProxyMessage} batch of beans.
|
||||||
|
*/
|
||||||
|
public class ActionStatusMsgBeanQuery extends AbstractBeanQuery<ProxyMessage> {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private Sort sort = new Sort(Direction.DESC, "id");
|
||||||
|
private transient DeploymentManagement deploymentManagement;
|
||||||
|
|
||||||
|
private Long currentSelectedActionStatusId;
|
||||||
|
private String noMessageText;
|
||||||
|
private transient Page<String> firstPageMessages;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parametric Constructor.
|
||||||
|
*
|
||||||
|
* @param definition
|
||||||
|
* QueryDefinition contains the query properties.
|
||||||
|
* @param queryConfig
|
||||||
|
* Implementation specific configuration.
|
||||||
|
* @param sortPropertyIds
|
||||||
|
* The properties participating in sort.
|
||||||
|
* @param sortStates
|
||||||
|
* The ascending or descending state of sort properties.
|
||||||
|
*/
|
||||||
|
public ActionStatusMsgBeanQuery(final QueryDefinition definition, final Map<String, Object> queryConfig,
|
||||||
|
final Object[] sortPropertyIds, final boolean[] sortStates) {
|
||||||
|
super(definition, queryConfig, sortPropertyIds, sortStates);
|
||||||
|
|
||||||
|
if (isNotNullOrEmpty(queryConfig)) {
|
||||||
|
currentSelectedActionStatusId = (Long) queryConfig.get(SPUIDefinitions.MESSAGES_BY_ACTIONSTATUS);
|
||||||
|
noMessageText = (String) queryConfig.get(SPUIDefinitions.NO_MSG_PROXY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sortStates.length > 0) {
|
||||||
|
// Initialize sort
|
||||||
|
sort = new Sort(sortStates[0] ? Direction.ASC : Direction.DESC, (String) sortPropertyIds[0]);
|
||||||
|
// Add sort
|
||||||
|
for (int distId = 1; distId < sortPropertyIds.length; distId++) {
|
||||||
|
sort.and(new Sort(sortStates[distId] ? Direction.ASC : Direction.DESC,
|
||||||
|
(String) sortPropertyIds[distId]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ProxyMessage constructBean() {
|
||||||
|
return new ProxyMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<ProxyMessage> loadBeans(final int startIndex, final int count) {
|
||||||
|
Page<String> actionBeans;
|
||||||
|
if (startIndex == 0 && firstPageMessages != null) {
|
||||||
|
actionBeans = firstPageMessages;
|
||||||
|
} else {
|
||||||
|
actionBeans = getDeploymentManagement().findMessagesByActionStatusId(
|
||||||
|
new PageRequest(startIndex / SPUIDefinitions.PAGE_SIZE, SPUIDefinitions.PAGE_SIZE, sort),
|
||||||
|
currentSelectedActionStatusId);
|
||||||
|
}
|
||||||
|
return createProxyMessages(actionBeans);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a list of {@link ProxyActionStatus} for presentation layer from
|
||||||
|
* page of {@link ActionStatus}.
|
||||||
|
*
|
||||||
|
* @param actionBeans
|
||||||
|
* page of {@link ActionStatus}
|
||||||
|
* @return list of {@link ProxyActionStatus}
|
||||||
|
*/
|
||||||
|
private List<ProxyMessage> createProxyMessages(final Page<String> messages) {
|
||||||
|
final List<ProxyMessage> proxyMsgs = new ArrayList<>(messages.getNumberOfElements());
|
||||||
|
|
||||||
|
Long idx = messages.getNumber() * ((long) messages.getSize());
|
||||||
|
for (final String msg : messages) {
|
||||||
|
idx++;
|
||||||
|
final ProxyMessage proxyMsg = new ProxyMessage();
|
||||||
|
proxyMsg.setMessage(msg);
|
||||||
|
proxyMsg.setId(String.valueOf(idx));
|
||||||
|
proxyMsgs.add(proxyMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (messages.getTotalElements() == 1L && Strings.isNullOrEmpty(proxyMsgs.get(0).getMessage())) {
|
||||||
|
proxyMsgs.get(0).setMessage(noMessageText);
|
||||||
|
}
|
||||||
|
|
||||||
|
return proxyMsgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see
|
||||||
|
* org.vaadin.addons.lazyquerycontainer.AbstractBeanQuery#saveBeans(java
|
||||||
|
* .util.List, java.util.List, java.util.List)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void saveBeans(List<ProxyMessage> addedBeans, List<ProxyMessage> modifiedBeans,
|
||||||
|
List<ProxyMessage> removedBeans) {
|
||||||
|
// CRUD operations on Target will be done through repository methods
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
long size = 0;
|
||||||
|
|
||||||
|
if (currentSelectedActionStatusId != null) {
|
||||||
|
firstPageMessages = getDeploymentManagement().findMessagesByActionStatusId(
|
||||||
|
new PageRequest(0, SPUIDefinitions.PAGE_SIZE, sort), currentSelectedActionStatusId);
|
||||||
|
size = firstPageMessages.getTotalElements();
|
||||||
|
}
|
||||||
|
if (size > Integer.MAX_VALUE) {
|
||||||
|
return Integer.MAX_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lazy gets deploymentManagement.
|
||||||
|
*
|
||||||
|
* @return the deploymentManagement
|
||||||
|
*/
|
||||||
|
public DeploymentManagement getDeploymentManagement() {
|
||||||
|
if (null == deploymentManagement) {
|
||||||
|
deploymentManagement = SpringContextHelper.getBean(DeploymentManagement.class);
|
||||||
|
}
|
||||||
|
return deploymentManagement;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,210 @@
|
|||||||
|
/**
|
||||||
|
* 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.management.actionhistory;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.ui.common.grid.AbstractGrid;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
||||||
|
import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory;
|
||||||
|
import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer;
|
||||||
|
import org.vaadin.addons.lazyquerycontainer.LazyQueryDefinition;
|
||||||
|
import org.vaadin.spring.events.EventBus.UIEventBus;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.vaadin.data.Item;
|
||||||
|
import com.vaadin.event.ItemClickEvent;
|
||||||
|
import com.vaadin.event.ItemClickEvent.ItemClickListener;
|
||||||
|
import com.vaadin.ui.Component;
|
||||||
|
import com.vaadin.ui.TextArea;
|
||||||
|
import com.vaadin.ui.themes.ValoTheme;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This grid presents the messages for a selected action-status.
|
||||||
|
*/
|
||||||
|
public class ActionStatusMsgGrid extends AbstractGrid<LazyQueryContainer> {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private static final String[] rightAlignedColumns = new String[] { ProxyMessage.PXY_MSG_ID };
|
||||||
|
|
||||||
|
private final String noMsgText;
|
||||||
|
|
||||||
|
private final AlignCellStyleGenerator alignGenerator;
|
||||||
|
|
||||||
|
private final BeanQueryFactory<ActionStatusMsgBeanQuery> targetQF = new BeanQueryFactory<>(
|
||||||
|
ActionStatusMsgBeanQuery.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param i18n
|
||||||
|
* @param eventBus
|
||||||
|
*/
|
||||||
|
protected ActionStatusMsgGrid(final VaadinMessageSource i18n, final UIEventBus eventBus) {
|
||||||
|
super(i18n, eventBus, null);
|
||||||
|
noMsgText = createNoMessageProxy(i18n);
|
||||||
|
|
||||||
|
setSingleSelectionSupport(new SingleSelectionSupport());
|
||||||
|
setDetailsSupport(new DetailsSupport());
|
||||||
|
|
||||||
|
alignGenerator = new AlignCellStyleGenerator(null, null, rightAlignedColumns);
|
||||||
|
addStyleName(SPUIStyleDefinitions.ACTION_HISTORY_MESSAGE_GRID);
|
||||||
|
|
||||||
|
setDetailsGenerator(new MessageDetailsGenerator());
|
||||||
|
|
||||||
|
this.addItemClickListener(new ItemClickListener() {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void itemClick(final ItemClickEvent event) {
|
||||||
|
final Object itemId = event.getItemId();
|
||||||
|
setDetailsVisible(itemId, !isDetailsVisible(itemId));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected LazyQueryContainer createContainer() {
|
||||||
|
configureQueryFactory();
|
||||||
|
return new LazyQueryContainer(new LazyQueryDefinition(true, SPUIDefinitions.PAGE_SIZE, null), targetQF);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshContainer() {
|
||||||
|
for (final Object itemId : getContainerDataSource().getItemIds()) {
|
||||||
|
setDetailsVisible(itemId, false);
|
||||||
|
}
|
||||||
|
configureQueryFactory();
|
||||||
|
super.refreshContainer();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void configureQueryFactory() {
|
||||||
|
// ADD all the filters to the query config
|
||||||
|
final Map<String, Object> queryConfig = Maps.newHashMapWithExpectedSize(2);
|
||||||
|
queryConfig.put(SPUIDefinitions.MESSAGES_BY_ACTIONSTATUS, getDetailsSupport().getMasterDataId());
|
||||||
|
queryConfig.put(SPUIDefinitions.NO_MSG_PROXY, noMsgText);
|
||||||
|
// Create ActionBeanQuery factory with the query config.
|
||||||
|
targetQF.setQueryConfiguration(queryConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets type-save access to LazyQueryContainer.
|
||||||
|
*
|
||||||
|
* @return LazyQueryContainer
|
||||||
|
*/
|
||||||
|
private LazyQueryContainer getLazyQueryContainer() {
|
||||||
|
return (LazyQueryContainer) getContainerDataSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addContainerProperties() {
|
||||||
|
getLazyQueryContainer().addContainerProperty(ProxyMessage.PXY_MSG_ID, String.class, null, true, false);
|
||||||
|
getLazyQueryContainer().addContainerProperty(ProxyMessage.PXY_MSG_VALUE, String.class, null, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setColumnExpandRatio() {
|
||||||
|
getColumn(ProxyMessage.PXY_MSG_ID).setExpandRatio(0);
|
||||||
|
getColumn(ProxyMessage.PXY_MSG_VALUE).setExpandRatio(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setColumnHeaderNames() {
|
||||||
|
getColumn(ProxyMessage.PXY_MSG_ID).setHeaderCaption("##");
|
||||||
|
getColumn(ProxyMessage.PXY_MSG_VALUE).setHeaderCaption(SPUIDefinitions.ACTION_HIS_TBL_MSGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getGridId() {
|
||||||
|
return UIComponentIdProvider.ACTION_HISTORY_MESSAGE_GRID_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setColumnProperties() {
|
||||||
|
clearSortOrder();
|
||||||
|
setColumns(ProxyMessage.PXY_MSG_ID, ProxyMessage.PXY_MSG_VALUE);
|
||||||
|
setFrozenColumnCount(2);
|
||||||
|
alignColumns();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addColumnRenderes() {
|
||||||
|
// no specific column renderers
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setHiddenColumns() {
|
||||||
|
getColumn(ProxyMessage.PXY_MSG_ID).setHidable(false);
|
||||||
|
getColumn(ProxyMessage.PXY_MSG_VALUE).setHidable(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected CellDescriptionGenerator getDescriptionGenerator() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the alignment cell-style-generator that handles the alignment for
|
||||||
|
* the grid cells.
|
||||||
|
*/
|
||||||
|
private void alignColumns() {
|
||||||
|
setCellStyleGenerator(alignGenerator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the default text when no message is available for action-status
|
||||||
|
*
|
||||||
|
* @param i18n
|
||||||
|
* @return default text
|
||||||
|
*/
|
||||||
|
private static String createNoMessageProxy(final VaadinMessageSource i18n) {
|
||||||
|
return i18n.getMessage("message.no.available");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class MessageDetailsGenerator implements DetailsGenerator {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Component getDetails(final RowReference rowReference) {
|
||||||
|
// Find the bean to generate details for
|
||||||
|
final Item item = rowReference.getItem();
|
||||||
|
final String message = (String) item.getItemProperty(ProxyMessage.PXY_MSG_VALUE).getValue();
|
||||||
|
|
||||||
|
final TextArea textArea = new TextArea();
|
||||||
|
textArea.addStyleName(ValoTheme.TEXTAREA_BORDERLESS);
|
||||||
|
textArea.addStyleName(ValoTheme.TEXTAREA_TINY);
|
||||||
|
textArea.addStyleName("inline-icon");
|
||||||
|
textArea.setHeight(120, Unit.PIXELS);
|
||||||
|
textArea.setWidth(100, Unit.PERCENTAGE);
|
||||||
|
textArea.setValue(message);
|
||||||
|
textArea.setReadOnly(Boolean.TRUE);
|
||||||
|
return textArea;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CellStyleGenerator that concerns about cutting text.
|
||||||
|
*/
|
||||||
|
protected static class TextCutCellStyleGenerator implements CellStyleGenerator {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStyle(final CellReference cellReference) {
|
||||||
|
if (ProxyMessage.PXY_MSG_VALUE.equals(cellReference.getPropertyId())) {
|
||||||
|
return "text-cut";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* 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.management.actionhistory;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.ui.common.grid.AbstractGridComponentLayout;
|
||||||
|
import org.eclipse.hawkbit.ui.common.grid.DefaultGridHeader;
|
||||||
|
import org.eclipse.hawkbit.ui.management.state.ManagementUIState;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
||||||
|
import org.vaadin.spring.events.EventBus.UIEventBus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Layout responsible for messages-grid and the corresponding header.
|
||||||
|
*/
|
||||||
|
public class ActionStatusMsgLayout extends AbstractGridComponentLayout {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
protected final ManagementUIState managementUIState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param i18n
|
||||||
|
* @param eventBus
|
||||||
|
* @param managementUIState
|
||||||
|
*/
|
||||||
|
public ActionStatusMsgLayout(final VaadinMessageSource i18n, final UIEventBus eventBus,
|
||||||
|
final ManagementUIState managementUIState) {
|
||||||
|
super(i18n, eventBus);
|
||||||
|
this.managementUIState = managementUIState;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DefaultGridHeader createGridHeader() {
|
||||||
|
return new DefaultGridHeader(managementUIState, "Messages").init();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionStatusMsgGrid createGrid() {
|
||||||
|
return new ActionStatusMsgGrid(i18n, eventBus);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* 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.management.actionhistory;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.model.Action;
|
||||||
|
import org.eclipse.hawkbit.ui.customrenderers.renderers.AbstractHtmlLabelConverter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concrete html-label converter that handles Action.Status.
|
||||||
|
*/
|
||||||
|
public class HtmlStatusLabelConverter extends AbstractHtmlLabelConverter<Action.Status> {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor that sets the appropriate adapter.
|
||||||
|
*
|
||||||
|
* @param adapter
|
||||||
|
* adapts <code>Action.Status</code> to <code>String</code>
|
||||||
|
*/
|
||||||
|
public HtmlStatusLabelConverter(LabelAdapter<Action.Status> adapter) {
|
||||||
|
this.addAdapter(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<Action.Status> getModelType() {
|
||||||
|
return Action.Status.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,223 @@
|
|||||||
|
/**
|
||||||
|
* 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.management.actionhistory;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.model.Action;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proxy for {@link Action}
|
||||||
|
*/
|
||||||
|
public class ProxyAction implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public static final String PXY_ACTION_STATUS = "status";
|
||||||
|
public static final String PXY_ACTION_IS_ACTIVE = "isActive";
|
||||||
|
public static final String PXY_ACTION_IS_ACTIVE_DECO = "isActiveDecoration";
|
||||||
|
public static final String PXY_ACTION_ID = "id";
|
||||||
|
public static final String PXY_ACTION_DS_NAME_VERSION = "dsNameVersion";
|
||||||
|
public static final String PXY_ACTION = "action";
|
||||||
|
public static final String PXY_ACTION_LAST_MODIFIED_AT = "lastModifiedAt";
|
||||||
|
public static final String PXY_ACTION_ROLLOUT_NAME = "rolloutName";
|
||||||
|
|
||||||
|
private Action.Status status;
|
||||||
|
private boolean isActive;
|
||||||
|
private IsActiveDecoration isActiveDecoration;
|
||||||
|
private Long id;
|
||||||
|
private String dsNameVersion;
|
||||||
|
private Action action;
|
||||||
|
private Long lastModifiedAt;
|
||||||
|
private String rolloutName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get id for the entry.
|
||||||
|
*
|
||||||
|
* @return id for the entry.
|
||||||
|
*/
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the id for the entry.
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* of the action entry.
|
||||||
|
*/
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the status literal.
|
||||||
|
*
|
||||||
|
* @return status literal
|
||||||
|
*/
|
||||||
|
public Action.Status getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the status literal.
|
||||||
|
*
|
||||||
|
* @param status
|
||||||
|
* literal
|
||||||
|
*/
|
||||||
|
public void setStatus(Action.Status status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag that indicates if the action is active.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the action is active, otherwise
|
||||||
|
* <code>false</code>
|
||||||
|
*/
|
||||||
|
public boolean isActive() {
|
||||||
|
return isActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the flag that indicates if the action is active.
|
||||||
|
*
|
||||||
|
* @param isActive
|
||||||
|
* <code>true</code> if the action is active, otherwise
|
||||||
|
* <code>false</code>
|
||||||
|
*/
|
||||||
|
public void setActive(boolean isActive) {
|
||||||
|
this.isActive = isActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a pre-calculated literal combining <code>ProxyAction#isActive</code>
|
||||||
|
* and <code>ProxyAction#getStatus</code> states.
|
||||||
|
*
|
||||||
|
* @return pre-calculated literal
|
||||||
|
*/
|
||||||
|
public IsActiveDecoration getIsActiveDecoration() {
|
||||||
|
return isActiveDecoration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the pre-calculated literal combining
|
||||||
|
* <code>ProxyAction#isActive</code> and <code>ProxyAction#getStatus</code>
|
||||||
|
* states.
|
||||||
|
*
|
||||||
|
* @param isActiveDecoration
|
||||||
|
* pre-calculated literal
|
||||||
|
*/
|
||||||
|
public void setIsActiveDecoration(IsActiveDecoration isActiveDecoration) {
|
||||||
|
this.isActiveDecoration = isActiveDecoration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pre-calculated value that is set up by distribution set name and version.
|
||||||
|
*
|
||||||
|
* @return pre-calculated value combining name and version
|
||||||
|
*/
|
||||||
|
public String getDsNameVersion() {
|
||||||
|
return dsNameVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the pre-calculated value combining distribution set name and
|
||||||
|
* version.
|
||||||
|
*
|
||||||
|
* @param dsNameVersion
|
||||||
|
* combined value
|
||||||
|
*/
|
||||||
|
public void setDsNameVersion(String dsNameVersion) {
|
||||||
|
this.dsNameVersion = dsNameVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the action to be evaluated by generators of virtual properties.
|
||||||
|
*
|
||||||
|
* @return action
|
||||||
|
*/
|
||||||
|
public Action getAction() {
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the action to be evaluated by generators of virtual properties.
|
||||||
|
*
|
||||||
|
* @param action
|
||||||
|
*/
|
||||||
|
public void setAction(Action action) {
|
||||||
|
this.action = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get raw long-value for lastModifiedAt-date.
|
||||||
|
*
|
||||||
|
* @return raw long-value for lastModifiedAt-date
|
||||||
|
*/
|
||||||
|
public Long getLastModifiedAt() {
|
||||||
|
return lastModifiedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set raw long-value for lastModifiedAt-date.
|
||||||
|
*
|
||||||
|
* @param lastModifiedAt
|
||||||
|
* raw long-value for lastModifiedAt-date
|
||||||
|
*/
|
||||||
|
public void setLastModifiedAt(Long lastModifiedAt) {
|
||||||
|
this.lastModifiedAt = lastModifiedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the rolloutName.
|
||||||
|
*
|
||||||
|
* @return rolloutName
|
||||||
|
*/
|
||||||
|
public String getRolloutName() {
|
||||||
|
return rolloutName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the rolloutName.
|
||||||
|
*
|
||||||
|
* @param rolloutName
|
||||||
|
*/
|
||||||
|
public void setRolloutName(String rolloutName) {
|
||||||
|
this.rolloutName = rolloutName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pre-calculated decoration value combining
|
||||||
|
* <code>ProxyAction#isActive</code> and <code>ProxyAction#getStatus</code>
|
||||||
|
* states.
|
||||||
|
*/
|
||||||
|
public enum IsActiveDecoration {
|
||||||
|
/**
|
||||||
|
* Active label decoration type for {@code ProxyAction#isActive()==true}
|
||||||
|
*/
|
||||||
|
ACTIVE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Active label decoration type for
|
||||||
|
* {@code ProxyAction#isActive()==false}
|
||||||
|
*/
|
||||||
|
IN_ACTIVE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Active label decoration type for {@code ProxyAction#isActive()==true}
|
||||||
|
* AND {@code ProxyAction#getStatus()==Action.Status.ERROR}
|
||||||
|
*/
|
||||||
|
IN_ACTIVE_ERROR,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code ProxyAction#getStatus()==Action.Status.SCHEDULED}
|
||||||
|
*/
|
||||||
|
SCHEDULED,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
/**
|
||||||
|
* 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.management.actionhistory;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.model.Action;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proxy for {@link ActionStatus}
|
||||||
|
*/
|
||||||
|
public class ProxyActionStatus implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public static final String PXY_AS_STATUS = "status";
|
||||||
|
public static final String PXY_AS_CREATED_AT = "createdAt";
|
||||||
|
public static final String PXY_AS_ID = "id";
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
private Action.Status status;
|
||||||
|
private Long createdAt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get id for the entry.
|
||||||
|
*
|
||||||
|
* @return id for the entry.
|
||||||
|
*/
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the id for the entry.
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* of the status entry.
|
||||||
|
*/
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the status literal.
|
||||||
|
*
|
||||||
|
* @return status literal
|
||||||
|
*/
|
||||||
|
public Action.Status getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the status literal.
|
||||||
|
*
|
||||||
|
* @param status
|
||||||
|
* literal
|
||||||
|
*/
|
||||||
|
public void setStatus(Action.Status status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get raw long-value for createdAt-date.
|
||||||
|
*
|
||||||
|
* @return raw long-value for createdAt-date
|
||||||
|
*/
|
||||||
|
public Long getCreatedAt() {
|
||||||
|
return createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set raw long-value for createdAt-date.
|
||||||
|
*
|
||||||
|
* @param createdAt
|
||||||
|
* raw long-value for createdAt-date
|
||||||
|
*/
|
||||||
|
public void setCreatedAt(Long createdAt) {
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/**
|
||||||
|
* 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.management.actionhistory;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proxy for an entry of {@link ActionStatus#getMessages()}
|
||||||
|
*/
|
||||||
|
public class ProxyMessage implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public static final String PXY_MSG_ID = "id";
|
||||||
|
public static final String PXY_MSG_VALUE = "message";
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get id for the entry.
|
||||||
|
*
|
||||||
|
* @return id for the entry.
|
||||||
|
*/
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the id for the entry.
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* of the message entry.
|
||||||
|
*/
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get message value.
|
||||||
|
*
|
||||||
|
* @return message value
|
||||||
|
*/
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set message value.
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
* value
|
||||||
|
*/
|
||||||
|
public void setMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,15 +25,14 @@ import org.eclipse.hawkbit.ui.UiProperties;
|
|||||||
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
|
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
|
||||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||||
import org.eclipse.hawkbit.ui.menu.DashboardEvent.PostViewChangeEvent;
|
import org.eclipse.hawkbit.ui.menu.DashboardEvent.PostViewChangeEvent;
|
||||||
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
import com.vaadin.server.FontAwesome;
|
import com.vaadin.server.FontAwesome;
|
||||||
import com.vaadin.server.Page;
|
import com.vaadin.server.Page;
|
||||||
import com.vaadin.server.Resource;
|
import com.vaadin.server.Resource;
|
||||||
import com.vaadin.server.ThemeResource;
|
import com.vaadin.server.ThemeResource;
|
||||||
import com.vaadin.shared.ui.label.ContentMode;
|
|
||||||
import com.vaadin.spring.annotation.SpringComponent;
|
import com.vaadin.spring.annotation.SpringComponent;
|
||||||
import com.vaadin.spring.annotation.UIScope;
|
import com.vaadin.spring.annotation.UIScope;
|
||||||
import com.vaadin.ui.Alignment;
|
import com.vaadin.ui.Alignment;
|
||||||
@@ -43,7 +42,6 @@ import com.vaadin.ui.Button.ClickListener;
|
|||||||
import com.vaadin.ui.Component;
|
import com.vaadin.ui.Component;
|
||||||
import com.vaadin.ui.CssLayout;
|
import com.vaadin.ui.CssLayout;
|
||||||
import com.vaadin.ui.CustomComponent;
|
import com.vaadin.ui.CustomComponent;
|
||||||
import com.vaadin.ui.HorizontalLayout;
|
|
||||||
import com.vaadin.ui.Label;
|
import com.vaadin.ui.Label;
|
||||||
import com.vaadin.ui.Link;
|
import com.vaadin.ui.Link;
|
||||||
import com.vaadin.ui.MenuBar;
|
import com.vaadin.ui.MenuBar;
|
||||||
@@ -82,8 +80,9 @@ public final class DashboardMenu extends CustomComponent {
|
|||||||
private boolean accessibleViewsEmpty;
|
private boolean accessibleViewsEmpty;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
DashboardMenu(final VaadinMessageSource i18n, final UiProperties uiProperties, final HawkbitServerProperties serverProperties,
|
DashboardMenu(final VaadinMessageSource i18n, final UiProperties uiProperties,
|
||||||
final PermissionService permissionService, final List<DashboardMenuItem> dashboardVaadinViews) {
|
final HawkbitServerProperties serverProperties, final PermissionService permissionService,
|
||||||
|
final List<DashboardMenuItem> dashboardVaadinViews) {
|
||||||
this.i18n = i18n;
|
this.i18n = i18n;
|
||||||
this.uiProperties = uiProperties;
|
this.uiProperties = uiProperties;
|
||||||
this.serverProperties = serverProperties;
|
this.serverProperties = serverProperties;
|
||||||
@@ -109,7 +108,6 @@ public final class DashboardMenu extends CustomComponent {
|
|||||||
final VerticalLayout dashboardMenuLayout = new VerticalLayout();
|
final VerticalLayout dashboardMenuLayout = new VerticalLayout();
|
||||||
dashboardMenuLayout.setSizeFull();
|
dashboardMenuLayout.setSizeFull();
|
||||||
final VerticalLayout menuContent = getMenuLayout();
|
final VerticalLayout menuContent = getMenuLayout();
|
||||||
menuContent.addComponent(buildTitle());
|
|
||||||
menuContent.addComponent(buildUserMenu());
|
menuContent.addComponent(buildUserMenu());
|
||||||
menuContent.addComponent(buildToggleButton());
|
menuContent.addComponent(buildToggleButton());
|
||||||
|
|
||||||
@@ -137,15 +135,6 @@ public final class DashboardMenu extends CustomComponent {
|
|||||||
return menuContent;
|
return menuContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Component buildTitle() {
|
|
||||||
final Label logo = new Label("<strong>" + i18n.getMessage("menu.title") + "</strong>", ContentMode.HTML);
|
|
||||||
logo.setSizeUndefined();
|
|
||||||
final HorizontalLayout logoWrapper = new HorizontalLayout(logo);
|
|
||||||
logoWrapper.setComponentAlignment(logo, Alignment.TOP_CENTER);
|
|
||||||
logoWrapper.addStyleName("valo-menu-title");
|
|
||||||
return logoWrapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
private VerticalLayout buildLinksAndVersion() {
|
private VerticalLayout buildLinksAndVersion() {
|
||||||
final VerticalLayout links = new VerticalLayout();
|
final VerticalLayout links = new VerticalLayout();
|
||||||
links.setSpacing(true);
|
links.setSpacing(true);
|
||||||
@@ -174,8 +163,8 @@ public final class DashboardMenu extends CustomComponent {
|
|||||||
|
|
||||||
if (!uiProperties.getLinks().getSupport().isEmpty()) {
|
if (!uiProperties.getLinks().getSupport().isEmpty()) {
|
||||||
final Link supportLink = SPUIComponentProvider.getLink(UIComponentIdProvider.LINK_SUPPORT,
|
final Link supportLink = SPUIComponentProvider.getLink(UIComponentIdProvider.LINK_SUPPORT,
|
||||||
i18n.getMessage("link.support.name"), uiProperties.getLinks().getSupport(), FontAwesome.ENVELOPE_O, "",
|
i18n.getMessage("link.support.name"), uiProperties.getLinks().getSupport(), FontAwesome.ENVELOPE_O,
|
||||||
linkStyle);
|
"", linkStyle);
|
||||||
supportLink.setDescription(i18n.getMessage("link.support.name"));
|
supportLink.setDescription(i18n.getMessage("link.support.name"));
|
||||||
supportLink.setSizeFull();
|
supportLink.setSizeFull();
|
||||||
links.addComponent(supportLink);
|
links.addComponent(supportLink);
|
||||||
|
|||||||
@@ -8,35 +8,140 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.ui.rollout;
|
package org.eclipse.hawkbit.ui.rollout;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
import java.io.Serializable;
|
||||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
|
||||||
|
|
||||||
import com.google.gwt.i18n.client.AutoDirectionHandler.Target;
|
|
||||||
import com.vaadin.server.FontAwesome;
|
import com.vaadin.server.FontAwesome;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Helper class which holds the details of font icon to be displayed as
|
||||||
* Helper class which holds the details of font icon to be displayed for
|
* label/button in grid:
|
||||||
* {@link Rollout}/ {@link RolloutGroup} / Rollout {@link Target}
|
* <p>
|
||||||
*
|
* <code>RolloutListGrid</code> / <code>RolloutGroupListGrid</code> /
|
||||||
*
|
* <code>RolloutGroupTargetsListGrid</code> / <code>ActionHistoryGrid</code>
|
||||||
*/
|
*/
|
||||||
public class StatusFontIcon {
|
public class StatusFontIcon implements Serializable {
|
||||||
final FontAwesome fontIcon;
|
/** serialVersionUID. */
|
||||||
final String style;
|
private static final long serialVersionUID = 1L;
|
||||||
|
private FontAwesome fontIcon;
|
||||||
|
private String style;
|
||||||
|
private String title;
|
||||||
|
private String id;
|
||||||
|
private boolean disabled;
|
||||||
|
|
||||||
public StatusFontIcon(final FontAwesome fontIcon, final String style) {
|
/**
|
||||||
super();
|
* NOTE: This constructor is used for (de-)serialization only!!!
|
||||||
this.fontIcon = fontIcon;
|
*/
|
||||||
this.style = style;
|
public StatusFontIcon() {
|
||||||
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor to create icon metadata object.
|
||||||
|
*
|
||||||
|
* @param fontIcon
|
||||||
|
* the font representing the icon
|
||||||
|
* @param style
|
||||||
|
* the style
|
||||||
|
*/
|
||||||
|
public StatusFontIcon(final FontAwesome fontIcon, final String style) {
|
||||||
|
this(fontIcon, style, "", "", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor to create icon metadata object.
|
||||||
|
*
|
||||||
|
* @param fontIcon
|
||||||
|
* the font representing the icon
|
||||||
|
* @param style
|
||||||
|
* the style
|
||||||
|
* @param title
|
||||||
|
* the title shown as tooltip
|
||||||
|
*/
|
||||||
|
public StatusFontIcon(final FontAwesome fontIcon, final String style, final String title) {
|
||||||
|
this(fontIcon, style, title, "", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor to create icon metadata object.
|
||||||
|
*
|
||||||
|
* @param fontIcon
|
||||||
|
* the font representing the icon
|
||||||
|
* @param style
|
||||||
|
* the style
|
||||||
|
* @param title
|
||||||
|
* the title shown as tooltip
|
||||||
|
* @param id
|
||||||
|
* the id for direct access
|
||||||
|
*/
|
||||||
|
public StatusFontIcon(final FontAwesome fontIcon, final String style, final String title, final String id) {
|
||||||
|
this(fontIcon, style, title, id, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor to create icon metadata object.
|
||||||
|
*
|
||||||
|
* @param fontIcon
|
||||||
|
* the font representing the icon
|
||||||
|
* @param style
|
||||||
|
* the style
|
||||||
|
* @param title
|
||||||
|
* the title shown as tooltip
|
||||||
|
* @param id
|
||||||
|
* the id for direct access
|
||||||
|
* @param disabled
|
||||||
|
* disabled-state of the icon
|
||||||
|
*/
|
||||||
|
public StatusFontIcon(final FontAwesome fontIcon, final String style, final String title, final String id,
|
||||||
|
final boolean disabled) {
|
||||||
|
this.fontIcon = fontIcon;
|
||||||
|
this.style = style;
|
||||||
|
this.title = title;
|
||||||
|
this.id = id;
|
||||||
|
this.disabled = disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the font representing the icon.
|
||||||
|
*
|
||||||
|
* @return the font representing the icon
|
||||||
|
*/
|
||||||
public FontAwesome getFontIcon() {
|
public FontAwesome getFontIcon() {
|
||||||
return fontIcon;
|
return fontIcon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the style.
|
||||||
|
*
|
||||||
|
* @return the style
|
||||||
|
*/
|
||||||
public String getStyle() {
|
public String getStyle() {
|
||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the title shown as tooltip.
|
||||||
|
*
|
||||||
|
* @return the title shown as tooltip.
|
||||||
|
*/
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the id for direct access.
|
||||||
|
*
|
||||||
|
* @return the id for direct access.
|
||||||
|
*/
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the disabled-state of the icon.
|
||||||
|
*
|
||||||
|
* @return the disabled-state of the icon.
|
||||||
|
*/
|
||||||
|
public boolean isDisabled() {
|
||||||
|
return disabled;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ import com.vaadin.ui.renderers.HtmlRenderer;
|
|||||||
/**
|
/**
|
||||||
* Rollout list grid component.
|
* Rollout list grid component.
|
||||||
*/
|
*/
|
||||||
public class RolloutListGrid extends AbstractGrid {
|
public class RolloutListGrid extends AbstractGrid<LazyQueryContainer> {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@@ -132,6 +132,8 @@ public class RolloutListGrid extends AbstractGrid {
|
|||||||
uiNotification, uiProperties, entityFactory, i18n, eventBus, targetFilterQueryManagement);
|
uiNotification, uiProperties, entityFactory, i18n, eventBus, targetFilterQueryManagement);
|
||||||
this.uiNotification = uiNotification;
|
this.uiNotification = uiNotification;
|
||||||
this.rolloutUIState = rolloutUIState;
|
this.rolloutUIState = rolloutUIState;
|
||||||
|
|
||||||
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -211,7 +213,7 @@ public class RolloutListGrid extends AbstractGrid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Container createContainer() {
|
protected LazyQueryContainer createContainer() {
|
||||||
final BeanQueryFactory<RolloutBeanQuery> rolloutQf = new BeanQueryFactory<>(RolloutBeanQuery.class);
|
final BeanQueryFactory<RolloutBeanQuery> rolloutQf = new BeanQueryFactory<>(RolloutBeanQuery.class);
|
||||||
return new LazyQueryContainer(
|
return new LazyQueryContainer(
|
||||||
new LazyQueryDefinition(true, SPUIDefinitions.PAGE_SIZE, SPUILabelDefinitions.VAR_ID), rolloutQf);
|
new LazyQueryDefinition(true, SPUIDefinitions.PAGE_SIZE, SPUILabelDefinitions.VAR_ID), rolloutQf);
|
||||||
|
|||||||
@@ -14,43 +14,61 @@ import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
|
|||||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||||
import org.eclipse.hawkbit.ui.SpPermissionChecker;
|
import org.eclipse.hawkbit.ui.SpPermissionChecker;
|
||||||
import org.eclipse.hawkbit.ui.UiProperties;
|
import org.eclipse.hawkbit.ui.UiProperties;
|
||||||
import org.eclipse.hawkbit.ui.common.grid.AbstractGridLayout;
|
import org.eclipse.hawkbit.ui.common.grid.AbstractGrid;
|
||||||
|
import org.eclipse.hawkbit.ui.common.grid.AbstractGridComponentLayout;
|
||||||
import org.eclipse.hawkbit.ui.rollout.state.RolloutUIState;
|
import org.eclipse.hawkbit.ui.rollout.state.RolloutUIState;
|
||||||
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
||||||
import org.eclipse.hawkbit.ui.utils.UINotification;
|
import org.eclipse.hawkbit.ui.utils.UINotification;
|
||||||
|
import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer;
|
||||||
import org.vaadin.spring.events.EventBus.UIEventBus;
|
import org.vaadin.spring.events.EventBus.UIEventBus;
|
||||||
|
|
||||||
import com.vaadin.ui.Label;
|
import com.vaadin.ui.AbstractOrderedLayout;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rollout list view.
|
* Rollout list view.
|
||||||
*/
|
*/
|
||||||
public class RolloutListView extends AbstractGridLayout {
|
public class RolloutListView extends AbstractGridComponentLayout {
|
||||||
|
|
||||||
private static final long serialVersionUID = -2703552177439393208L;
|
private static final long serialVersionUID = -2703552177439393208L;
|
||||||
|
|
||||||
|
private final transient RolloutManagement rolloutManagement;
|
||||||
|
private final transient TargetManagement targetManagement;
|
||||||
|
private final transient EntityFactory entityFactory;
|
||||||
|
private final transient TargetFilterQueryManagement targetFilterQueryManagement;
|
||||||
|
|
||||||
|
private final SpPermissionChecker permissionChecker;
|
||||||
|
private final RolloutUIState rolloutUIState;
|
||||||
|
private final UINotification uiNotification;
|
||||||
|
private final UiProperties uiProperties;
|
||||||
|
|
||||||
|
|
||||||
public RolloutListView(final SpPermissionChecker permissionChecker, final RolloutUIState rolloutUIState,
|
public RolloutListView(final SpPermissionChecker permissionChecker, final RolloutUIState rolloutUIState,
|
||||||
final UIEventBus eventBus, final RolloutManagement rolloutManagement,
|
final UIEventBus eventBus, final RolloutManagement rolloutManagement,
|
||||||
final TargetManagement targetManagement, final UINotification uiNotification,
|
final TargetManagement targetManagement, final UINotification uiNotification,
|
||||||
final UiProperties uiProperties, final EntityFactory entityFactory, final VaadinMessageSource i18n,
|
final UiProperties uiProperties, final EntityFactory entityFactory, final VaadinMessageSource i18n,
|
||||||
final TargetFilterQueryManagement targetFilterQueryManagement) {
|
final TargetFilterQueryManagement targetFilterQueryManagement) {
|
||||||
super(new RolloutListHeader(permissionChecker, rolloutUIState, eventBus, rolloutManagement, targetManagement,
|
super(i18n, eventBus);
|
||||||
uiNotification, uiProperties, entityFactory, i18n, targetFilterQueryManagement),
|
this.permissionChecker = permissionChecker;
|
||||||
new RolloutListGrid(i18n, eventBus, rolloutManagement, uiNotification, rolloutUIState,
|
this.rolloutUIState = rolloutUIState;
|
||||||
permissionChecker, targetManagement, entityFactory, uiProperties, targetFilterQueryManagement));
|
this.rolloutManagement = rolloutManagement;
|
||||||
|
this.targetManagement = targetManagement;
|
||||||
|
this.uiNotification = uiNotification;
|
||||||
|
this.uiProperties = uiProperties;
|
||||||
|
this.entityFactory = entityFactory;
|
||||||
|
this.targetFilterQueryManagement = targetFilterQueryManagement;
|
||||||
|
|
||||||
buildLayout();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean hasCountMessage() {
|
public AbstractOrderedLayout createGridHeader() {
|
||||||
return false;
|
return new RolloutListHeader(permissionChecker, rolloutUIState, eventBus, rolloutManagement, targetManagement,
|
||||||
|
uiNotification, uiProperties, entityFactory, i18n, targetFilterQueryManagement);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Label getCountMessageLabel() {
|
public AbstractGrid<LazyQueryContainer> createGrid() {
|
||||||
|
return new RolloutListGrid(i18n, eventBus, rolloutManagement, uiNotification, rolloutUIState, permissionChecker,
|
||||||
return null;
|
targetManagement, entityFactory, uiProperties, targetFilterQueryManagement);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ import com.vaadin.ui.renderers.HtmlRenderer;
|
|||||||
/**
|
/**
|
||||||
* Rollout group list grid component.
|
* Rollout group list grid component.
|
||||||
*/
|
*/
|
||||||
public class RolloutGroupListGrid extends AbstractGrid {
|
public class RolloutGroupListGrid extends AbstractGrid<LazyQueryContainer> {
|
||||||
private static final long serialVersionUID = 4060904914954370524L;
|
private static final long serialVersionUID = 4060904914954370524L;
|
||||||
|
|
||||||
private static final String ROLLOUT_RENDERER_DATA = "rolloutRendererData";
|
private static final String ROLLOUT_RENDERER_DATA = "rolloutRendererData";
|
||||||
@@ -98,6 +98,8 @@ public class RolloutGroupListGrid extends AbstractGrid {
|
|||||||
super(i18n, eventBus, permissionChecker);
|
super(i18n, eventBus, permissionChecker);
|
||||||
this.rolloutGroupManagement = rolloutGroupManagement;
|
this.rolloutGroupManagement = rolloutGroupManagement;
|
||||||
this.rolloutUIState = rolloutUIState;
|
this.rolloutUIState = rolloutUIState;
|
||||||
|
|
||||||
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventBusListenerMethod(scope = EventScope.UI)
|
@EventBusListenerMethod(scope = EventScope.UI)
|
||||||
@@ -131,7 +133,7 @@ public class RolloutGroupListGrid extends AbstractGrid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Container createContainer() {
|
protected LazyQueryContainer createContainer() {
|
||||||
final BeanQueryFactory<RolloutGroupBeanQuery> rolloutQf = new BeanQueryFactory<>(RolloutGroupBeanQuery.class);
|
final BeanQueryFactory<RolloutGroupBeanQuery> rolloutQf = new BeanQueryFactory<>(RolloutGroupBeanQuery.class);
|
||||||
return new LazyQueryContainer(
|
return new LazyQueryContainer(
|
||||||
new LazyQueryDefinition(true, SPUIDefinitions.PAGE_SIZE, SPUILabelDefinitions.VAR_ID), rolloutQf);
|
new LazyQueryDefinition(true, SPUIDefinitions.PAGE_SIZE, SPUILabelDefinitions.VAR_ID), rolloutQf);
|
||||||
|
|||||||
@@ -10,9 +10,11 @@ package org.eclipse.hawkbit.ui.rollout.rolloutgroup;
|
|||||||
|
|
||||||
import org.eclipse.hawkbit.repository.RolloutGroupManagement;
|
import org.eclipse.hawkbit.repository.RolloutGroupManagement;
|
||||||
import org.eclipse.hawkbit.ui.SpPermissionChecker;
|
import org.eclipse.hawkbit.ui.SpPermissionChecker;
|
||||||
import org.eclipse.hawkbit.ui.common.grid.AbstractGridLayout;
|
import org.eclipse.hawkbit.ui.common.grid.AbstractGrid;
|
||||||
|
import org.eclipse.hawkbit.ui.common.grid.AbstractGridComponentLayout;
|
||||||
import org.eclipse.hawkbit.ui.rollout.state.RolloutUIState;
|
import org.eclipse.hawkbit.ui.rollout.state.RolloutUIState;
|
||||||
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
||||||
|
import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer;
|
||||||
import org.vaadin.spring.events.EventBus.UIEventBus;
|
import org.vaadin.spring.events.EventBus.UIEventBus;
|
||||||
|
|
||||||
import com.vaadin.ui.Label;
|
import com.vaadin.ui.Label;
|
||||||
@@ -20,10 +22,14 @@ import com.vaadin.ui.Label;
|
|||||||
/**
|
/**
|
||||||
* Groups List View.
|
* Groups List View.
|
||||||
*/
|
*/
|
||||||
public class RolloutGroupsListView extends AbstractGridLayout {
|
public class RolloutGroupsListView extends AbstractGridComponentLayout {
|
||||||
|
|
||||||
private static final long serialVersionUID = 7252345838154270259L;
|
private static final long serialVersionUID = 7252345838154270259L;
|
||||||
|
|
||||||
|
private final SpPermissionChecker permissionChecker;
|
||||||
|
private final RolloutUIState rolloutUIState;
|
||||||
|
private final transient RolloutGroupManagement rolloutGroupManagement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for RolloutGroupsListView
|
* Constructor for RolloutGroupsListView
|
||||||
*
|
*
|
||||||
@@ -41,20 +47,21 @@ public class RolloutGroupsListView extends AbstractGridLayout {
|
|||||||
public RolloutGroupsListView(final VaadinMessageSource i18n, final UIEventBus eventBus,
|
public RolloutGroupsListView(final VaadinMessageSource i18n, final UIEventBus eventBus,
|
||||||
final RolloutGroupManagement rolloutGroupManagement, final RolloutUIState rolloutUIState,
|
final RolloutGroupManagement rolloutGroupManagement, final RolloutUIState rolloutUIState,
|
||||||
final SpPermissionChecker permissionChecker) {
|
final SpPermissionChecker permissionChecker) {
|
||||||
super(new RolloutGroupsListHeader(eventBus, rolloutUIState, i18n),
|
super(i18n, eventBus);
|
||||||
new RolloutGroupListGrid(i18n, eventBus, rolloutGroupManagement, rolloutUIState, permissionChecker));
|
this.permissionChecker = permissionChecker;
|
||||||
|
this.rolloutUIState = rolloutUIState;
|
||||||
buildLayout();
|
this.rolloutGroupManagement = rolloutGroupManagement;
|
||||||
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean hasCountMessage() {
|
public RolloutGroupsListHeader createGridHeader() {
|
||||||
return false;
|
return new RolloutGroupsListHeader(eventBus, rolloutUIState, i18n);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Label getCountMessageLabel() {
|
public AbstractGrid<LazyQueryContainer> createGrid() {
|
||||||
return null;
|
return new RolloutGroupListGrid(i18n, eventBus, rolloutGroupManagement, rolloutUIState, permissionChecker);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ import com.vaadin.server.FontAwesome;
|
|||||||
/**
|
/**
|
||||||
* Grid component with targets of rollout group.
|
* Grid component with targets of rollout group.
|
||||||
*/
|
*/
|
||||||
public class RolloutGroupTargetsListGrid extends AbstractGrid {
|
public class RolloutGroupTargetsListGrid extends AbstractGrid<LazyQueryContainer> {
|
||||||
|
|
||||||
private static final long serialVersionUID = -2244756637458984597L;
|
private static final long serialVersionUID = -2244756637458984597L;
|
||||||
|
|
||||||
@@ -85,6 +85,8 @@ public class RolloutGroupTargetsListGrid extends AbstractGrid {
|
|||||||
final RolloutUIState rolloutUIState) {
|
final RolloutUIState rolloutUIState) {
|
||||||
super(i18n, eventBus, null);
|
super(i18n, eventBus, null);
|
||||||
this.rolloutUIState = rolloutUIState;
|
this.rolloutUIState = rolloutUIState;
|
||||||
|
|
||||||
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventBusListenerMethod(scope = EventScope.UI)
|
@EventBusListenerMethod(scope = EventScope.UI)
|
||||||
@@ -97,7 +99,7 @@ public class RolloutGroupTargetsListGrid extends AbstractGrid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Container createContainer() {
|
protected LazyQueryContainer createContainer() {
|
||||||
final BeanQueryFactory<RolloutGroupTargetsBeanQuery> rolloutgrouBeanQueryFactory = new BeanQueryFactory<>(
|
final BeanQueryFactory<RolloutGroupTargetsBeanQuery> rolloutgrouBeanQueryFactory = new BeanQueryFactory<>(
|
||||||
RolloutGroupTargetsBeanQuery.class);
|
RolloutGroupTargetsBeanQuery.class);
|
||||||
return new LazyQueryContainer(
|
return new LazyQueryContainer(
|
||||||
@@ -205,7 +207,7 @@ public class RolloutGroupTargetsListGrid extends AbstractGrid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Converts {@link Status} into string with status icon details.
|
* Converts {@link Status} into string with status icon details.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -8,43 +8,50 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.ui.rollout.rolloutgrouptargets;
|
package org.eclipse.hawkbit.ui.rollout.rolloutgrouptargets;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.ui.common.grid.AbstractGridLayout;
|
import org.eclipse.hawkbit.ui.common.grid.AbstractGridComponentLayout;
|
||||||
import org.eclipse.hawkbit.ui.rollout.state.RolloutUIState;
|
import org.eclipse.hawkbit.ui.rollout.state.RolloutUIState;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||||
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
||||||
import org.vaadin.spring.events.EventBus.UIEventBus;
|
import org.vaadin.spring.events.EventBus.UIEventBus;
|
||||||
|
|
||||||
|
import com.vaadin.ui.AbstractOrderedLayout;
|
||||||
import com.vaadin.ui.Label;
|
import com.vaadin.ui.Label;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rollout Group Targets List View.
|
* Rollout Group Targets List View.
|
||||||
*/
|
*/
|
||||||
public class RolloutGroupTargetsListView extends AbstractGridLayout {
|
public class RolloutGroupTargetsListView extends AbstractGridComponentLayout {
|
||||||
|
|
||||||
private static final long serialVersionUID = 26089134783467012L;
|
private static final long serialVersionUID = 26089134783467012L;
|
||||||
|
|
||||||
private final RolloutGroupTargetsCountLabelMessage rolloutGroupTargetsCountLabelMessage;
|
private final RolloutUIState rolloutUIState;
|
||||||
|
|
||||||
public RolloutGroupTargetsListView(final UIEventBus eventBus, final VaadinMessageSource i18n,
|
public RolloutGroupTargetsListView(final UIEventBus eventBus, final VaadinMessageSource i18n,
|
||||||
final RolloutUIState rolloutUIState) {
|
final RolloutUIState rolloutUIState) {
|
||||||
super(new RolloutGroupTargetsListHeader(eventBus, i18n, rolloutUIState),
|
super(i18n, eventBus);
|
||||||
new RolloutGroupTargetsListGrid(i18n, eventBus, rolloutUIState));
|
this.rolloutUIState = rolloutUIState;
|
||||||
|
this.setFooterSupport(new RolloutTargetsCountFooterSupport());
|
||||||
this.rolloutGroupTargetsCountLabelMessage = new RolloutGroupTargetsCountLabelMessage(rolloutUIState,
|
init();
|
||||||
(RolloutGroupTargetsListGrid) grid, i18n, eventBus);
|
|
||||||
|
|
||||||
buildLayout();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean hasCountMessage() {
|
public AbstractOrderedLayout createGridHeader() {
|
||||||
|
return new RolloutGroupTargetsListHeader(eventBus, i18n, rolloutUIState);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Label getCountMessageLabel() {
|
public RolloutGroupTargetsListGrid createGrid() {
|
||||||
|
return new RolloutGroupTargetsListGrid(i18n, eventBus, rolloutUIState);
|
||||||
return rolloutGroupTargetsCountLabelMessage;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class RolloutTargetsCountFooterSupport extends AbstractFooterSupport {
|
||||||
|
private static final long serialVersionUID = 3300400541786329735L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Label getFooterMessageLabel() {
|
||||||
|
final RolloutGroupTargetsCountLabelMessage countMessageLabel = new RolloutGroupTargetsCountLabelMessage(
|
||||||
|
rolloutUIState, (RolloutGroupTargetsListGrid) getGrid(), i18n, eventBus);
|
||||||
|
countMessageLabel.setId(UIComponentIdProvider.ROLLOUT_GROUP_TARGET_LABEL);
|
||||||
|
return countMessageLabel;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,6 +81,18 @@ public final class SPDateTimeUtil {
|
|||||||
return formatDate(lastQueryDate, null);
|
return formatDate(lastQueryDate, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get formatted date with browser time zone.
|
||||||
|
*
|
||||||
|
* @param lastQueryDate
|
||||||
|
* @param datePattern
|
||||||
|
* pattern how to format the date (cp. {@code SimpleDateFormat})
|
||||||
|
* @return String formatted date
|
||||||
|
*/
|
||||||
|
public static String getFormattedDate(final Long lastQueryDate, final String datePattern) {
|
||||||
|
return formatDate(lastQueryDate, null, datePattern);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get formatted date 'created at' by entity.
|
* Get formatted date 'created at' by entity.
|
||||||
*
|
*
|
||||||
@@ -109,20 +121,40 @@ public final class SPDateTimeUtil {
|
|||||||
return formatDate(baseEntity.getLastModifiedAt(), StringUtils.EMPTY);
|
return formatDate(baseEntity.getLastModifiedAt(), StringUtils.EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String formatDate(final Long lastQueryDate, final String defaultString) {
|
/**
|
||||||
|
* Get formatted date 'last modified at' by entity.
|
||||||
|
*
|
||||||
|
* @param baseEntity
|
||||||
|
* the entity
|
||||||
|
* @param datePattern
|
||||||
|
* pattern how to format the date (cp. {@code SimpleDateFormat})
|
||||||
|
* @return String formatted date
|
||||||
|
*/
|
||||||
|
public static String formatLastModifiedAt(final BaseEntity baseEntity, final String datePattern) {
|
||||||
|
if (baseEntity == null) {
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
|
return formatDate(baseEntity.getLastModifiedAt(), StringUtils.EMPTY, datePattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatDate(final Long lastQueryDate, final String defaultString, final String datePattern) {
|
||||||
if (lastQueryDate != null) {
|
if (lastQueryDate != null) {
|
||||||
final SimpleDateFormat format = new SimpleDateFormat(SPUIDefinitions.LAST_QUERY_DATE_FORMAT);
|
final SimpleDateFormat format = new SimpleDateFormat(datePattern);
|
||||||
format.setTimeZone(getBrowserTimeZone());
|
format.setTimeZone(getBrowserTimeZone());
|
||||||
return format.format(new Date(lastQueryDate));
|
return format.format(new Date(lastQueryDate));
|
||||||
}
|
}
|
||||||
return defaultString;
|
return defaultString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String formatDate(final Long lastQueryDate, final String defaultString) {
|
||||||
|
return formatDate(lastQueryDate, defaultString, SPUIDefinitions.LAST_QUERY_DATE_FORMAT);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a formatted string of a duration in format '1 year 2 months 3
|
* Creates a formatted string of a duration in format '1 year 2 months 3
|
||||||
* days 4 hours 5 minutes 6 seconds' zero values will be ignored in the
|
* days 4 hours 5 minutes 6 seconds' zero values will be ignored in the
|
||||||
* formatted string.
|
* formatted string.
|
||||||
*
|
*
|
||||||
* @param startMillis
|
* @param startMillis
|
||||||
* the start milliseconds of the duration
|
* the start milliseconds of the duration
|
||||||
* @param endMillis
|
* @param endMillis
|
||||||
@@ -158,34 +190,34 @@ public final class SPDateTimeUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Enum to get the i18n key for single or plural calendar labels.
|
* Enum to get the i18n key for single or plural calendar labels.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private enum CalendarI18N {
|
private enum CalendarI18N {
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
YEAR("calendar.year", "calendar.years"),
|
YEAR("calendar.year", "calendar.years"),
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
MONTH("calendar.month", "calendar.months"),
|
MONTH("calendar.month", "calendar.months"),
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
DAY("calendar.days", "calendar.days"),
|
DAY("calendar.days", "calendar.days"),
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
HOUR("calendar.hour", "calendar.hours"),
|
HOUR("calendar.hour", "calendar.hours"),
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
MINUTE("calendar.minute", "calendar.minutes"),
|
MINUTE("calendar.minute", "calendar.minutes"),
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
SECOND("calendar.second", "calendar.seconds");
|
SECOND("calendar.second", "calendar.seconds");
|
||||||
|
|
||||||
@@ -193,7 +225,7 @@ public final class SPDateTimeUtil {
|
|||||||
private final String plural;
|
private final String plural;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
CalendarI18N(final String single, final String plural) {
|
CalendarI18N(final String single, final String plural) {
|
||||||
this.single = single;
|
this.single = single;
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public final class SPUIDefinitions {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Action history active hidden column. This is using to generate active
|
* Action history active hidden column. This is using to generate active
|
||||||
* icons under active coloumn.
|
* icons under active column.
|
||||||
*/
|
*/
|
||||||
public static final String ACTION_HIS_TBL_ACTIVE_HIDDEN = "Active_Hidden";
|
public static final String ACTION_HIS_TBL_ACTIVE_HIDDEN = "Active_Hidden";
|
||||||
|
|
||||||
@@ -108,6 +108,11 @@ public final class SPUIDefinitions {
|
|||||||
*/
|
*/
|
||||||
public static final String ACTION_HIS_TBL_FORCED = "Forced";
|
public static final String ACTION_HIS_TBL_FORCED = "Forced";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action history action type column.
|
||||||
|
*/
|
||||||
|
public static final String ACTION_HIS_TBL_TIMEFORCED = "Time-Forced";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action history helping constant.
|
* Action history helping constant.
|
||||||
*/
|
*/
|
||||||
@@ -244,6 +249,22 @@ public final class SPUIDefinitions {
|
|||||||
* Text field style.
|
* Text field style.
|
||||||
*/
|
*/
|
||||||
public static final String TEXT_STYLE = "text-style";
|
public static final String TEXT_STYLE = "text-style";
|
||||||
|
/**
|
||||||
|
* Show actions for a target.
|
||||||
|
*/
|
||||||
|
public static final String ACTIONS_BY_TARGET = "ActionsByTarget";
|
||||||
|
/**
|
||||||
|
* Show action-states for a action.
|
||||||
|
*/
|
||||||
|
public static final String ACTIONSTATES_BY_ACTION = "ActionStatesByAction";
|
||||||
|
/**
|
||||||
|
* Show messages for a action-status.
|
||||||
|
*/
|
||||||
|
public static final String MESSAGES_BY_ACTIONSTATUS = "MessagesByActionStatus";
|
||||||
|
/**
|
||||||
|
* Key for no-message MessageProxy.
|
||||||
|
*/
|
||||||
|
public static final String NO_MSG_PROXY = "NoMessageProxy";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Style to highlight row in orange color.
|
* Style to highlight row in orange color.
|
||||||
@@ -353,6 +374,10 @@ public final class SPUIDefinitions {
|
|||||||
* Target last query date format .
|
* Target last query date format .
|
||||||
*/
|
*/
|
||||||
public static final String LAST_QUERY_DATE_FORMAT = "EEE MMM d HH:mm:ss z yyyy";
|
public static final String LAST_QUERY_DATE_FORMAT = "EEE MMM d HH:mm:ss z yyyy";
|
||||||
|
/**
|
||||||
|
* Target last query date format .
|
||||||
|
*/
|
||||||
|
public static final String LAST_QUERY_DATE_FORMAT_SHORT = "MMM d HH:mm z ''yy";
|
||||||
/**
|
/**
|
||||||
* Item Id used in drop comparisons.
|
* Item Id used in drop comparisons.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -25,6 +25,11 @@ public final class SPUIStyleDefinitions {
|
|||||||
|
|
||||||
public static final String SP_TEXTFIELD_LAYOUT_ERROR_HIGHTLIGHT = "v-textfield-error";
|
public static final String SP_TEXTFIELD_LAYOUT_ERROR_HIGHTLIGHT = "v-textfield-error";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action history message grid style.
|
||||||
|
*/
|
||||||
|
public static final String ACTION_HISTORY_MESSAGE_GRID = "action-history-message-grid";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Style for accordion tab button.
|
* Style for accordion tab button.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.eclipse.hawkbit.ui.utils;
|
package org.eclipse.hawkbit.ui.utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,17 +53,14 @@ public final class UIComponentIdProvider {
|
|||||||
* ID-Targ.PIN.
|
* ID-Targ.PIN.
|
||||||
*/
|
*/
|
||||||
public static final String TARGET_PIN_ICON = "target.pin.icon.";
|
public static final String TARGET_PIN_ICON = "target.pin.icon.";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Target search text id.
|
* Target search text id.
|
||||||
*/
|
*/
|
||||||
public static final String TARGET_TEXT_FIELD = "target.search.textfield";
|
public static final String TARGET_TEXT_FIELD = "target.search.textfield";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID for target filter search
|
* ID for target filter search
|
||||||
*/
|
*/
|
||||||
public static final String TARGET_FILTER_SEARCH_TEXT = "target.filter.search.text.Id";
|
public static final String TARGET_FILTER_SEARCH_TEXT = "target.filter.search.text.Id";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID for add target filter icon
|
* ID for add target filter icon
|
||||||
*/
|
*/
|
||||||
@@ -121,7 +119,6 @@ public final class UIComponentIdProvider {
|
|||||||
* ID-Dist.PIN.
|
* ID-Dist.PIN.
|
||||||
*/
|
*/
|
||||||
public static final String DIST_PIN_BUTTON = "dist.pin.button";
|
public static final String DIST_PIN_BUTTON = "dist.pin.button";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID for distribution set tag icon
|
* ID for distribution set tag icon
|
||||||
*/
|
*/
|
||||||
@@ -134,27 +131,22 @@ public final class UIComponentIdProvider {
|
|||||||
* ID - soft.module.version.
|
* ID - soft.module.version.
|
||||||
*/
|
*/
|
||||||
public static final String SOFT_MODULE_VERSION = "soft.module.version";
|
public static final String SOFT_MODULE_VERSION = "soft.module.version";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID - soft.module.vendor.
|
* ID - soft.module.vendor.
|
||||||
*/
|
*/
|
||||||
public static final String SOFT_MODULE_VENDOR = "soft.module.vendor";
|
public static final String SOFT_MODULE_VENDOR = "soft.module.vendor";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID - Save Assign.
|
* ID - Save Assign.
|
||||||
*/
|
*/
|
||||||
public static final String SAVE_ASSIGNMENT = "save.actions.popup.assign";
|
public static final String SAVE_ASSIGNMENT = "save.actions.popup.assign";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID - Discard Assign.
|
* ID - Discard Assign.
|
||||||
*/
|
*/
|
||||||
public static final String DISCARD_ASSIGNMENT = "discard.actions.popup.assign";
|
public static final String DISCARD_ASSIGNMENT = "discard.actions.popup.assign";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID - Delete Distribution SetType Save.
|
* ID - Delete Distribution SetType Save.
|
||||||
*/
|
*/
|
||||||
public static final String SAVE_DELETE_DIST_SET_TYPE = "save.actions.popup.delete.dist.set.type";
|
public static final String SAVE_DELETE_DIST_SET_TYPE = "save.actions.popup.delete.dist.set.type";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID - Discard Distribution SetType.
|
* ID - Discard Distribution SetType.
|
||||||
*/
|
*/
|
||||||
@@ -163,17 +155,14 @@ public final class UIComponentIdProvider {
|
|||||||
* ID Delete Software Module Type save.
|
* ID Delete Software Module Type save.
|
||||||
*/
|
*/
|
||||||
public static final String SAVE_DELETE_SW_MODULE_TYPE = "save.actions.popup.delete.sw.module.type";
|
public static final String SAVE_DELETE_SW_MODULE_TYPE = "save.actions.popup.delete.sw.module.type";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID - Discard SW Module Type.
|
* ID - Discard SW Module Type.
|
||||||
*/
|
*/
|
||||||
public static final String DISCARD_SW_MODULE_TYPE = "save.actions.popup.discard.sw.module.type";
|
public static final String DISCARD_SW_MODULE_TYPE = "save.actions.popup.discard.sw.module.type";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action history table cancel Id.
|
* Action history table cancel Id.
|
||||||
*/
|
*/
|
||||||
public static final String ACTION_DETAILS_SOFT_ID = "action.details.soft.group";
|
public static final String ACTION_DETAILS_SOFT_ID = "action.details.soft.group";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start type of rollout manual radio button
|
* Start type of rollout manual radio button
|
||||||
*/
|
*/
|
||||||
@@ -231,24 +220,53 @@ public final class UIComponentIdProvider {
|
|||||||
*/
|
*/
|
||||||
public static final String PENDING_ACTION_BUTTON = "pending.action.button";
|
public static final String PENDING_ACTION_BUTTON = "pending.action.button";
|
||||||
/**
|
/**
|
||||||
* Action history table Id.
|
* Action history grid Id.
|
||||||
*/
|
*/
|
||||||
public static final String ACTION_HISTORY_TABLE_ID = "action.history.tableId";
|
public static final String ACTION_HISTORY_GRID_ID = "action.history.gridId";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action history table cancel Id.
|
* Action history details grid Id.
|
||||||
|
*/
|
||||||
|
public static final String ACTION_HISTORY_DETAILS_GRID_ID = "action.history.details.gridId";
|
||||||
|
/**
|
||||||
|
* Action history message grid Id.
|
||||||
|
*/
|
||||||
|
public static final String ACTION_HISTORY_MESSAGE_GRID_ID = "action.history.message.gridId";
|
||||||
|
/**
|
||||||
|
* Action history table cancel button Id.
|
||||||
*/
|
*/
|
||||||
public static final String ACTION_HISTORY_TABLE_CANCEL_ID = "action.history.table.action.cancel";
|
public static final String ACTION_HISTORY_TABLE_CANCEL_ID = "action.history.table.action.cancel";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action history table force Id.
|
* Action history table force button Id.
|
||||||
*/
|
*/
|
||||||
public static final String ACTION_HISTORY_TABLE_FORCE_ID = "action.history.table.action.force";
|
public static final String ACTION_HISTORY_TABLE_FORCE_ID = "action.history.table.action.force";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action history table force quit Id.
|
* Action history table force quit button Id.
|
||||||
*/
|
*/
|
||||||
public static final String ACTION_HISTORY_TABLE_FORCE_QUIT_ID = "action.history.table.action.force.quit";
|
public static final String ACTION_HISTORY_TABLE_FORCE_QUIT_ID = "action.history.table.action.force.quit";
|
||||||
|
/**
|
||||||
|
* Action history table forced label Id.
|
||||||
|
*/
|
||||||
|
public static final String ACTION_HISTORY_TABLE_FORCED_LABEL_ID = "action.history.table.forcedId";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action history table time-forced label Id.
|
||||||
|
*/
|
||||||
|
public static final String ACTION_HISTORY_TABLE_TIMEFORCED_LABEL_ID = "action.history.table.timedforceId";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action history table status label Id.
|
||||||
|
*/
|
||||||
|
public static final String ACTION_HISTORY_TABLE_STATUS_LABEL_ID = "action.history.table.statusId";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action history table active-state label Id.
|
||||||
|
*/
|
||||||
|
public static final String ACTION_HISTORY_TABLE_ACTIVESTATE_LABEL_ID = "action.history.table.activeStateId";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action status grid status label Id.
|
||||||
|
*/
|
||||||
|
public static final String ACTION_STATUS_GRID_STATUS_LABEL_ID = "action.status.grid.statusId";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID for option group save timeforced
|
* ID for option group save timeforced
|
||||||
@@ -985,7 +1003,7 @@ public final class UIComponentIdProvider {
|
|||||||
/**
|
/**
|
||||||
* Id of the unread notification popup
|
* Id of the unread notification popup
|
||||||
*/
|
*/
|
||||||
public static final String NOTIFICATION_UNREAD_POPUP_id = "notification.unread.popup";
|
public static final String NOTIFICATION_UNREAD_POPUP_ID = "notification.unread.popup";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Id of the unread notification icon in the menu
|
* Id of the unread notification icon in the menu
|
||||||
|
|||||||
@@ -18,9 +18,21 @@
|
|||||||
padding-bottom: 25px;
|
padding-bottom: 25px;
|
||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Color of forced label
|
.action-history-message-grid {
|
||||||
.action-history-table-col-forced-label {
|
.v-grid-cell {
|
||||||
color: $hawkbit-primary-color;
|
border: none !important;
|
||||||
|
cursor: move;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
-o-text-overflow: ellipsis;
|
||||||
|
-icab-text-overflow: ellipsis;
|
||||||
|
-khtml-text-overflow: ellipsis;
|
||||||
|
-moz-text-overflow: ellipsis;
|
||||||
|
-webkit-text-overflow: ellipsis;
|
||||||
|
font-size: $v-font-size--small !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,8 +23,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.view-header-layout{
|
.view-header-layout{
|
||||||
width: 100%;
|
width: 100% !important;
|
||||||
padding-right: 20px;
|
padding-right: 20px;
|
||||||
|
padding-bottom: 0.3em
|
||||||
}
|
}
|
||||||
|
|
||||||
.v-ui {
|
.v-ui {
|
||||||
@@ -51,10 +52,10 @@
|
|||||||
padding-right: 20px;
|
padding-right: 20px;
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
min-width: 1000px;
|
min-width: 1000px;
|
||||||
min-height: 400px;
|
min-height: 500px;
|
||||||
border: 0px;
|
border: 0px;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
box-shadow: none;
|
box-shadow: none
|
||||||
}
|
}
|
||||||
|
|
||||||
//View background styles
|
//View background styles
|
||||||
@@ -65,7 +66,7 @@
|
|||||||
background-position: bottom;
|
background-position: bottom;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
border-left: 0 solid #fff;
|
border-left: 0 solid #fff;
|
||||||
padding-top: 80px;
|
padding-top: 70px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +77,7 @@
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
padding-bottom: 5px;
|
padding-bottom: 0px;
|
||||||
padding-left: 15px;
|
padding-left: 15px;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -103,7 +104,7 @@
|
|||||||
background: $logo-image no-repeat right top;
|
background: $logo-image no-repeat right top;
|
||||||
background-position: $logo-position;
|
background-position: $logo-position;
|
||||||
content: "";
|
content: "";
|
||||||
height: 80px;
|
height: 70px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -316,5 +317,11 @@
|
|||||||
.form-lastrow {
|
.form-lastrow {
|
||||||
padding-bottom: 12px !important;
|
padding-bottom: 12px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-cut {
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
@mixin grid {
|
||||||
|
.v-grid-cell.centeralign {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-grid-cell.leftalign {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-grid-cell.rightalign {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-grid-cell {
|
||||||
|
font-size: $v-font-size--small !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-grid-cell.frozen{
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-grid-cell.frozen + th {
|
||||||
|
border-left: $v-grid-border-size solid $widget-border-color ;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -92,7 +92,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Pin style - when hovered on pin and when row is selected
|
//Pin style - when hovered on pin and when row is selected
|
||||||
tr.v-selected .v-button-targetStatusPinToggle:hover:after {
|
widget-bg .v-button-targetStatusPinToggle:hover:after {
|
||||||
background-color: $widget-bg;
|
background-color: $widget-bg;
|
||||||
color: $hawkbit-primary-color !important;
|
color: $hawkbit-primary-color !important;
|
||||||
}
|
}
|
||||||
@@ -195,56 +195,97 @@
|
|||||||
content: "\f08d";
|
content: "\f08d";
|
||||||
color: $widget-bg;
|
color: $widget-bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
.statusIconPending {
|
// pending status label not selected
|
||||||
|
tr:not(.v-selected) .statusIconForced:after {
|
||||||
color: $hawkbit-primary-color;
|
color: $hawkbit-primary-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.statusIconActive {
|
// pending status label selected
|
||||||
|
tr.v-selected .statusIconForced:after {
|
||||||
|
color: $widget-bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pending status label not selected
|
||||||
|
tr:not(.v-selected) .statusIconPending:after {
|
||||||
|
color: $hawkbit-primary-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pending status label selected
|
||||||
|
tr.v-selected .statusIconPending:after {
|
||||||
|
color: $widget-bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// active status label not selected
|
||||||
|
tr:not(.v-grid-row-selected) .statusIconActive {
|
||||||
@include valo-spinner($size:16px,$speed:1200ms);
|
@include valo-spinner($size:16px,$speed:1200ms);
|
||||||
color: $hawkbit-primary-color;
|
color: $hawkbit-primary-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.statusIconNeutral {
|
// active status label selected
|
||||||
color: $hawkbit-primary-color;
|
tr.v-grid-row-selected .statusIconActive {
|
||||||
|
@include valo-spinner($size:16px,$speed:1200ms,$color: $grey-light);
|
||||||
|
color: $grey-light;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// neutral status label not selected
|
||||||
|
tr:not(.v-selected) .statusIconNeutral:after {
|
||||||
|
color: $hawkbit-primary-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
// neutral status label selected
|
||||||
|
tr.v-selected .statusIconNeutral:after {
|
||||||
|
color: $widget-bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// red status label not selected
|
||||||
|
tr:not(.v-selected) .borderless.statusIconRed:after {
|
||||||
|
color: $hawkbit-primary-color;
|
||||||
|
content: '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// red status label not selected
|
||||||
|
tr.v-selected .borderless.statusIconRed:after {
|
||||||
|
color: $widget-bg;
|
||||||
|
content: '';
|
||||||
|
}
|
||||||
|
|
||||||
.redSpinner{
|
.redSpinner{
|
||||||
@include valo-spinner($size: $v-font-size--small,$color: $red-color);
|
@include valo-spinner($size: $v-font-size--small,$color: $red-color);
|
||||||
pointer-events: auto !important;
|
pointer-events: auto !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.greySpinner{
|
.greySpinner{
|
||||||
@include valo-spinner($size: $v-font-size--small,$color: $grey-color);
|
@include valo-spinner($size: $v-font-size--small,$color: $grey-color);
|
||||||
pointer-events: auto !important;
|
pointer-events: auto !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.yellowSpinner{
|
.yellowSpinner{
|
||||||
@include valo-spinner($size: $v-font-size--small,$color: $signal-yellow-color);
|
@include valo-spinner($size: $v-font-size--small,$color: $signal-yellow-color);
|
||||||
pointer-events: auto !important;
|
pointer-events: auto !important;
|
||||||
}
|
}
|
||||||
.blueSpinner{
|
|
||||||
@include valo-spinner($size: $v-font-size--small,$color: $signal-light-blue-color);
|
.blueSpinner{
|
||||||
pointer-events: auto !important;
|
@include valo-spinner($size: $v-font-size--small,$color: $signal-light-blue-color);
|
||||||
}
|
pointer-events: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
// Disabled row style when distribution is incomplete
|
// Disabled row style when distribution is incomplete
|
||||||
.v-table-row-incomplete-distribution {
|
.v-table-row-incomplete-distribution {
|
||||||
color: $disabled-row-color-grey !important;
|
color: $disabled-row-color-grey !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.v-link {
|
.v-link {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
}
|
}
|
||||||
|
|
||||||
.v-tooltip{
|
.v-tooltip{
|
||||||
max-width:43em;
|
max-width:43em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breadcrumbPaddingLeft{
|
.breadcrumbPaddingLeft{
|
||||||
padding-left: 3px !important;
|
padding-left: 3px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,97 +7,76 @@
|
|||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*/
|
*/
|
||||||
@mixin rollout {
|
@mixin rollout {
|
||||||
.rollout-option-group {
|
.rollout-option-group{
|
||||||
font-size: 12px;
|
font-size:12px;
|
||||||
font-weight: 400;
|
font-weight:400;
|
||||||
margin-left: 8px;
|
margin-left:8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rollout-action-type-layout {
|
.rollout-action-type-layout {
|
||||||
.v-caption-padding-right-style {
|
.v-caption-padding-right-style{
|
||||||
padding-right: 0px !important;
|
padding-right:0px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.v-context-menu .v-context-menu-item-basic-icon-container {
|
|
||||||
height: 0px !important;
|
.v-context-menu .v-context-menu-item-basic-icon-container{
|
||||||
width: 0px !important;
|
height:0px !important;
|
||||||
}
|
width:0px !important;
|
||||||
|
}
|
||||||
.v-context-menu .v-context-menu-item-basic {
|
|
||||||
background-color: #feffff !important;
|
.v-context-menu .v-context-menu-item-basic{
|
||||||
border-radius: 4px;
|
background-color: #feffff !important;
|
||||||
font-family: $app-font-family;
|
border-radius: 4px;
|
||||||
font-size: $app-text-font-size;
|
font-family : $app-font-family;
|
||||||
font-weight: normal;
|
font-size : $app-text-font-size;
|
||||||
font-style: normal;
|
font-weight : normal;
|
||||||
}
|
font-style : normal;
|
||||||
|
}
|
||||||
.v-context-menu {
|
|
||||||
background-color: #feffff !important;
|
|
||||||
border-radius: 4px;
|
.v-context-menu{
|
||||||
}
|
background-color: #feffff !important;
|
||||||
|
border-radius: 4px;
|
||||||
.v-context-menu .v-context-menu-item-basic:focus, .v-context-menu .v-context-menu-item-basic-submenu:focus, .v-context-menu .v-context-menu-item-basic-open {
|
}
|
||||||
@include valo-gradient($color: $hawkbit-primary-color);
|
|
||||||
background-color: $hawkbit-primary-color !important;
|
.v-context-menu .v-context-menu-item-basic:focus, .v-context-menu .v-context-menu-item-basic-submenu:focus, .v-context-menu .v-context-menu-item-basic-open {
|
||||||
color: #e8eef3;
|
@include valo-gradient($color: $hawkbit-primary-color);
|
||||||
height: 30px;
|
background-color: $hawkbit-primary-color !important;
|
||||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.05);
|
color: #e8eef3;
|
||||||
}
|
height: 30px;
|
||||||
|
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.05);
|
||||||
.disable-action-type-layout {
|
}
|
||||||
opacity: 0.5;
|
|
||||||
}
|
.disable-action-type-layout{
|
||||||
|
opacity: 0.5;
|
||||||
.action-type-padding {
|
}
|
||||||
padding: 0 0px !important;
|
|
||||||
}
|
.action-type-padding{
|
||||||
|
padding: 0 0px !important;
|
||||||
.rollout-caption-links {
|
}
|
||||||
font-weight: 400;
|
|
||||||
height: 25px;
|
.rollout-caption-links{
|
||||||
padding: 0px 4px;
|
font-weight: 400;
|
||||||
}
|
height: 25px ;
|
||||||
|
padding: 0px 4px ;
|
||||||
.rollout-target-count-message {
|
}
|
||||||
color: $info-message-color-grey;
|
|
||||||
}
|
.rollout-target-count-message{
|
||||||
|
color: $info-message-color-grey;
|
||||||
.rollout-table {
|
}
|
||||||
.v-table-cell-wrapper {
|
|
||||||
cursor: default;
|
.rollout-table{
|
||||||
}
|
.v-table-cell-wrapper {
|
||||||
}
|
cursor: default;
|
||||||
|
}
|
||||||
.v-grid-cell.centeralign {
|
}
|
||||||
text-align: center;
|
|
||||||
}
|
.v-button-boldhide{
|
||||||
|
text-decoration:none;
|
||||||
.v-grid-cell {
|
}
|
||||||
font-size: $v-font-size--small !important;
|
|
||||||
height: 34px !important;
|
.groups-pie-chart {
|
||||||
}
|
|
||||||
|
|
||||||
.v-grid-row {
|
|
||||||
height: 34px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v-grid-cell.frozen {
|
|
||||||
box-shadow: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v-grid-cell.frozen + th {
|
|
||||||
border-left: $v-grid-border-size solid $widget-border-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v-button-boldhide {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.groups-pie-chart {
|
|
||||||
float: right;
|
float: right;
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
@@ -209,5 +188,6 @@
|
|||||||
.v-slot:nth-child(16n+15) .rollout-group-count { border-left-color: #BBDE8F }
|
.v-slot:nth-child(16n+15) .rollout-group-count { border-left-color: #BBDE8F }
|
||||||
.v-slot:nth-child(16n+16) .rollout-group-count { border-left-color: #7FB0A4 }
|
.v-slot:nth-child(16n+16) .rollout-group-count { border-left-color: #7FB0A4 }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,7 +36,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.v-table-resizer {
|
.v-table-resizer {
|
||||||
height: 37px !important;
|
|
||||||
margin-left: -8px !important;
|
margin-left: -8px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,10 +38,13 @@ $v-grid-cell-horizontal-border: 0px ;
|
|||||||
$v-grid-cell-focused-border: 0px ;
|
$v-grid-cell-focused-border: 0px ;
|
||||||
$v-grid-cell-padding-horizontal:6px;
|
$v-grid-cell-padding-horizontal:6px;
|
||||||
|
|
||||||
|
$v-table-row-height: 31px;
|
||||||
|
|
||||||
$v-animations-enabled: true;
|
$v-animations-enabled: true;
|
||||||
|
|
||||||
@import '../valo/valo';
|
@import '../valo/valo';
|
||||||
@import 'customstyles/table';
|
@import 'customstyles/table';
|
||||||
|
@import 'customstyles/grid';
|
||||||
@import 'customstyles/filter-status';
|
@import 'customstyles/filter-status';
|
||||||
@import 'customstyles/colorpicker';
|
@import 'customstyles/colorpicker';
|
||||||
@import 'customstyles/tags';
|
@import 'customstyles/tags';
|
||||||
@@ -79,6 +82,7 @@ $v-included-components: remove($v-included-components, form);
|
|||||||
@include valo;
|
@include valo;
|
||||||
@include generic-styles;
|
@include generic-styles;
|
||||||
@include table;
|
@include table;
|
||||||
|
@include grid;
|
||||||
@include filter-status;
|
@include filter-status;
|
||||||
@include colorpicker;
|
@include colorpicker;
|
||||||
@include tags;
|
@include tags;
|
||||||
|
|||||||
@@ -213,7 +213,6 @@ textfield.vendor = Vendor
|
|||||||
textfield.description = Description
|
textfield.description = Description
|
||||||
textfield.customfiltername = Filter name
|
textfield.customfiltername = Filter name
|
||||||
textfield.value = Value
|
textfield.value = Value
|
||||||
ui.version = Powered by Bosch IoT Software Provisioning
|
|
||||||
prompt.target.id = Controller ID
|
prompt.target.id = Controller ID
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
20
pom.xml
20
pom.xml
@@ -105,7 +105,7 @@
|
|||||||
<snapshotDependencyAllowed>true</snapshotDependencyAllowed>
|
<snapshotDependencyAllowed>true</snapshotDependencyAllowed>
|
||||||
|
|
||||||
<!-- Spring boot version overrides (should be reviewed with every boot upgrade) - START -->
|
<!-- Spring boot version overrides (should be reviewed with every boot upgrade) - START -->
|
||||||
<!-- Newer versions needed than defined in Boot -->
|
<!-- Newer versions needed than defined in Boot -->
|
||||||
<spring-hateoas.version>0.23.0.RELEASE</spring-hateoas.version>
|
<spring-hateoas.version>0.23.0.RELEASE</spring-hateoas.version>
|
||||||
<assertj.version>3.6.2</assertj.version>
|
<assertj.version>3.6.2</assertj.version>
|
||||||
<!-- Older versions needed than defined in Boot -->
|
<!-- Older versions needed than defined in Boot -->
|
||||||
@@ -152,7 +152,7 @@
|
|||||||
<feign.extension.version>9.3.1</feign.extension.version>
|
<feign.extension.version>9.3.1</feign.extension.version>
|
||||||
<jayway.awaitility.version>1.7.0</jayway.awaitility.version>
|
<jayway.awaitility.version>1.7.0</jayway.awaitility.version>
|
||||||
<io-protostuff.version>1.5.2</io-protostuff.version>
|
<io-protostuff.version>1.5.2</io-protostuff.version>
|
||||||
|
|
||||||
<!-- Misc libraries versions - END -->
|
<!-- Misc libraries versions - END -->
|
||||||
|
|
||||||
<!-- Release - START -->
|
<!-- Release - START -->
|
||||||
@@ -218,7 +218,7 @@
|
|||||||
<version>1.4.1</version>
|
<version>1.4.1</version>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<!-- Make sure that only non-snapshot versions are used for the dependencies. Only active when property 'snapshotDependencyAllowed' is
|
<!-- Make sure that only non-snapshot versions are used for the dependencies. Only active when property 'snapshotDependencyAllowed' is
|
||||||
false. -->
|
false. -->
|
||||||
<id>enforce-no-snapshots</id>
|
<id>enforce-no-snapshots</id>
|
||||||
<goals>
|
<goals>
|
||||||
@@ -415,10 +415,10 @@
|
|||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<!-- Use the Nexus Staging plugin as a full replacement for the standard Maven Deploy plugin. See https://github.com/sonatype/nexus-maven-plugins/tree/master/staging/maven-plugin
|
<!-- Use the Nexus Staging plugin as a full replacement for the standard Maven Deploy plugin. See https://github.com/sonatype/nexus-maven-plugins/tree/master/staging/maven-plugin
|
||||||
why this makes sense :-) We can control whether we want to deploy to the Eclipse repo or Maven Central by a combination of the version being a SNAPSHOT
|
why this makes sense :-) We can control whether we want to deploy to the Eclipse repo or Maven Central by a combination of the version being a SNAPSHOT
|
||||||
or RELEASE version and property skipStaging=true/false. In any case we can take advantage of the plugin's "deferred deploy" feature which makes sure that
|
or RELEASE version and property skipStaging=true/false. In any case we can take advantage of the plugin's "deferred deploy" feature which makes sure that
|
||||||
all artifacts of a multi-module project are deployed as a whole at the end of the build process instead of deploying each module's artifacts individually
|
all artifacts of a multi-module project are deployed as a whole at the end of the build process instead of deploying each module's artifacts individually
|
||||||
as part of building the module. -->
|
as part of building the module. -->
|
||||||
<groupId>org.sonatype.plugins</groupId>
|
<groupId>org.sonatype.plugins</groupId>
|
||||||
<artifactId>nexus-staging-maven-plugin</artifactId>
|
<artifactId>nexus-staging-maven-plugin</artifactId>
|
||||||
@@ -629,7 +629,7 @@
|
|||||||
<artifactId>feign-jaxrs</artifactId>
|
<artifactId>feign-jaxrs</artifactId>
|
||||||
<version>${feign.extension.version}</version>
|
<version>${feign.extension.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Protostuff Io -->
|
<!-- Protostuff Io -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.protostuff</groupId>
|
<groupId>io.protostuff</groupId>
|
||||||
@@ -641,7 +641,7 @@
|
|||||||
<artifactId>protostuff-runtime</artifactId>
|
<artifactId>protostuff-runtime</artifactId>
|
||||||
<version>${io-protostuff.version}</version>
|
<version>${io-protostuff.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- RSQL / FIQL parser -->
|
<!-- RSQL / FIQL parser -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cz.jirutka.rsql</groupId>
|
<groupId>cz.jirutka.rsql</groupId>
|
||||||
@@ -740,4 +740,4 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
Reference in New Issue
Block a user