diff --git a/3rd-dependencies/listDeps.sh b/3rd-dependencies/listDeps.sh old mode 100755 new mode 100644 diff --git a/examples/hawkbit-device-simulator/pom.xml b/examples/hawkbit-device-simulator/pom.xml index a23051124..c74eace3e 100644 --- a/examples/hawkbit-device-simulator/pom.xml +++ b/examples/hawkbit-device-simulator/pom.xml @@ -139,7 +139,7 @@ com.vaadin vaadin-bom - 7.6.3 + ${vaadin.version} pom import diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulationController.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulationController.java index 426860d8b..649d88477 100644 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulationController.java +++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulationController.java @@ -86,7 +86,10 @@ public class SimulationController { final String deviceId = name + i; repository.add(deviceFactory.createSimulatedDevice(deviceId, tenant, protocol, pollDelay, new URL(endpoint), gatewayToken)); - spSenderService.createOrUpdateThing(tenant, deviceId); + + if (protocol == Protocol.DMF_AMQP) { + spSenderService.createOrUpdateThing(tenant, deviceId); + } } return ResponseEntity.ok("Updated " + amount + " DMF connected targets!"); diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulatorStartup.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulatorStartup.java index 60f3055bd..19367a9d4 100644 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulatorStartup.java +++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulatorStartup.java @@ -11,10 +11,12 @@ package org.eclipse.hawkbit.simulator; import java.net.MalformedURLException; import java.net.URL; +import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol; import org.eclipse.hawkbit.simulator.amqp.SpSenderService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.stereotype.Component; @@ -24,6 +26,7 @@ import org.springframework.stereotype.Component; * */ @Component +@ConditionalOnProperty(prefix = "hawkbit.device.simulator", name = "autostart", matchIfMissing = true) public class SimulatorStartup implements ApplicationListener { private static final Logger LOGGER = LoggerFactory.getLogger(SimulatorStartup.class); @@ -52,7 +55,9 @@ public class SimulatorStartup implements ApplicationListener getDeadLetterExchangeArgs() { - final Map args = new HashMap<>(); - args.put("x-dead-letter-exchange", amqpProperties.getDeadLetterExchange()); - return args; - } - } diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpDeadletterProperties.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpDeadletterProperties.java new file mode 100644 index 000000000..7ed5e90c1 --- /dev/null +++ b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpDeadletterProperties.java @@ -0,0 +1,69 @@ +/** + * 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.amqp; + +import java.time.Duration; +import java.util.HashMap; +import java.util.Map; + +import org.springframework.amqp.core.Queue; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * Bean which holds the necessary properties for configuring the AMQP deadletter + * queue. + */ +@ConfigurationProperties("hawkbit.dmf.rabbitmq.deadLetter") +public class AmqpDeadletterProperties { + + /** + * Message time to live (ttl) for the deadletter queue. Default ttl is 3 + * weeks. + */ + private long ttl = Duration.ofDays(21).toMillis(); + + /** + * Return the deadletter arguments. + * + * @param exchange + * the deadletter exchange + * @return map which holds the properties + */ + public Map getDeadLetterExchangeArgs(final String exchange) { + final Map args = new HashMap<>(); + args.put("x-dead-letter-exchange", exchange); + return args; + } + + /** + * Create a deadletter queue with ttl for messages + * + * @param queueName + * the deadlette queue name + * @return the deadletter queue + */ + public Queue createDeadletterQueue(final String queueName) { + return new Queue(queueName, true, false, false, getTTLArgs()); + } + + private Map getTTLArgs() { + final Map args = new HashMap<>(); + args.put("x-message-ttl", getTtl()); + return args; + } + + public long getTtl() { + return ttl; + } + + public void setTtl(final long ttl) { + this.ttl = ttl; + } + +} diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java index 41e70f91f..447a8ffca 100644 --- a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java +++ b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java @@ -166,20 +166,12 @@ public class AmqpMessageHandlerService extends BaseAmqpService { final LocalArtifact localArtifact = findLocalArtifactByFileResource(fileResource); if (localArtifact == null) { + LOG.info("target {} requested file resource {} which does not exists to download", + secruityToken.getControllerId(), fileResource); throw new EntityNotFoundException(); } - // check action for this download purposes, the method will throw an - // EntityNotFoundException in case the controller is not allowed to - // download this file because it's not assigned to an action and not - // assigned to this controller. Otherwise no controllerId is set = - // anonymous download - if (secruityToken.getControllerId() != null) { - final Action action = controllerManagement.getActionForDownloadByTargetAndSoftwareModule( - secruityToken.getControllerId(), localArtifact.getSoftwareModule()); - LOG.info("Found action for download authentication request action: {}, resource: {}", action, - secruityToken.getFileResource()); - } + checkIfArtifactIsAssignedToTarget(secruityToken, localArtifact); final Artifact artifact = convertDbArtifact(artifactManagement.loadLocalArtifactBinary(localArtifact)); if (artifact == null) { @@ -213,6 +205,35 @@ public class AmqpMessageHandlerService extends BaseAmqpService { return getMessageConverter().toMessage(authentificationResponse, messageProperties); } + /** + * check action for this download purposes, the method will throw an + * EntityNotFoundException in case the controller is not allowed to download + * this file because it's not assigned to an action and not assigned to this + * controller. Otherwise no controllerId is set = anonymous download + * + * @param secruityToken + * the security token which holds the target ID to check on + * @param localArtifact + * the local artifact to verify if the given target is allowed to + * download this artifact + */ + private void checkIfArtifactIsAssignedToTarget(final TenantSecurityToken secruityToken, + final LocalArtifact localArtifact) { + final String controllerId = secruityToken.getControllerId(); + if (controllerId == null) { + LOG.info("anonymous download no authentication check for artifact {}", localArtifact); + return; + } + LOG.debug("no anonymous download request, doing authentication check for target {} and artifact {}", + controllerId, localArtifact); + if (!controllerManagement.hasTargetArtifactAssigned(controllerId, localArtifact)) { + LOG.info("target {} tried to download artifact {} which is not assigned to the target", controllerId, + localArtifact); + throw new EntityNotFoundException(); + } + LOG.info("download security check for target {} and artifact {} granted", controllerId, localArtifact); + } + private LocalArtifact findLocalArtifactByFileResource(final FileResource fileResource) { if (fileResource.getSha1() != null) { return artifactManagement.findFirstLocalArtifactsBySHA1(fileResource.getSha1()); diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpProperties.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpProperties.java index 38c6d34b3..ce6068ce8 100644 --- a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpProperties.java +++ b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpProperties.java @@ -21,7 +21,7 @@ public class AmqpProperties { /** * DMF API dead letter queue. */ - private String deadLetterQueue = "dmf_connector_deadletter"; + private String deadLetterQueue = "dmf_connector_deadletter_ttl"; /** * DMF API dead letter exchange. diff --git a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java index 930ca02ad..19a7be3bc 100644 --- a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java +++ b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java @@ -313,11 +313,10 @@ public class AmqpMessageHandlerServiceTest { // mock final LocalArtifact localArtifactMock = mock(LocalArtifact.class); - final Action actionMock = mock(Action.class); final DbArtifact dbArtifactMock = mock(DbArtifact.class); when(artifactManagementMock.findFirstLocalArtifactsBySHA1(anyString())).thenReturn(localArtifactMock); - when(controllerManagementMock.getActionForDownloadByTargetAndSoftwareModule(anyObject(), anyObject())) - .thenReturn(actionMock); + when(controllerManagementMock.hasTargetArtifactAssigned(securityToken.getControllerId(), localArtifactMock)) + .thenReturn(true); when(artifactManagementMock.loadLocalArtifactBinary(localArtifactMock)).thenReturn(dbArtifactMock); when(dbArtifactMock.getArtifactId()).thenReturn("artifactId"); when(dbArtifactMock.getSize()).thenReturn(1L); diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/MultiTenantJpaTransactionManager.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/MultiTenantJpaTransactionManager.java index 7b97f5037..b3821e5f3 100644 --- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/MultiTenantJpaTransactionManager.java +++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/MultiTenantJpaTransactionManager.java @@ -11,9 +11,6 @@ package org.eclipse.hawkbit; import javax.persistence.EntityManager; import javax.transaction.Transaction; -import org.eclipse.hawkbit.repository.RolloutManagement; -import org.eclipse.hawkbit.repository.SystemManagement; -import org.eclipse.hawkbit.repository.exception.TenantNotExistException; import org.eclipse.hawkbit.tenancy.TenantAware; import org.eclipse.persistence.config.PersistenceUnitProperties; import org.springframework.beans.factory.annotation.Autowired; @@ -38,38 +35,12 @@ public class MultiTenantJpaTransactionManager extends JpaTransactionManager { protected void doBegin(final Object transaction, final TransactionDefinition definition) { super.doBegin(transaction, definition); - final EntityManagerHolder emHolder = (EntityManagerHolder) TransactionSynchronizationManager - .getResource(getEntityManagerFactory()); - final EntityManager em = emHolder.getEntityManager(); - - if (notTenantManagement(definition) && notCurrentTenantKeyGenerator(definition) - && notRolloutScheduler(definition) && notGetOrCreateTenantMetadata(definition)) { - - final String currentTenant = tenantAware.getCurrentTenant(); - if (currentTenant == null) { - throw new TenantNotExistException("Tenant Unknown. Canceling transaction."); - } - + final String currentTenant = tenantAware.getCurrentTenant(); + if (currentTenant != null) { + final EntityManagerHolder emHolder = (EntityManagerHolder) TransactionSynchronizationManager + .getResource(getEntityManagerFactory()); + final EntityManager em = emHolder.getEntityManager(); em.setProperty(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT, currentTenant.toUpperCase()); } } - - private boolean notGetOrCreateTenantMetadata(final TransactionDefinition definition) { - return !definition.getName() - .startsWith(SystemManagement.class.getCanonicalName() + ".getOrCreateTenantMetadata"); - } - - private boolean notRolloutScheduler(final TransactionDefinition definition) { - return !definition.getName().startsWith(RolloutManagement.class.getCanonicalName() + ".rolloutScheduler"); - } - - private boolean notCurrentTenantKeyGenerator(final TransactionDefinition definition) { - return !definition.getName() - .startsWith(SystemManagement.class.getCanonicalName() + ".currentTenantKeyGenerator"); - } - - private boolean notTenantManagement(final TransactionDefinition definition) { - return !definition.getName().startsWith(SystemManagement.class.getCanonicalName() + ".deleteTenant") - && !definition.getName().startsWith(SystemManagement.class.getCanonicalName() + ".findTenants"); - } } diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java index 0bb94bd72..dc097a7e3 100644 --- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java +++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java @@ -28,12 +28,14 @@ import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.ActionStatus_; import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.repository.model.LocalArtifact; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetInfo; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.Target_; import org.eclipse.hawkbit.repository.model.TenantConfiguration; +import org.eclipse.hawkbit.repository.specifications.ActionSpecifications; import org.eclipse.hawkbit.security.HawkbitSecurityProperties; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey; import org.hibernate.validator.constraints.NotEmpty; @@ -166,6 +168,31 @@ public class ControllerManagement { return action.get(0); } + /** + * Checks if a given target has currently or has even been assigned to the + * given artifact through the action history list. This can e.g. indicate if + * a target is allowed to download a given artifact because it has currently + * assigned or had ever been assigned to the target and so it's visible to a + * specific target e.g. for downloading. + * + * @param targetId + * the ID of the target to check + * @param localArtifact + * the artifact to verify if the given target had even been + * assigned to + * @return {@code true} if the given target has currently or had ever a + * relation to the given artifact through the action history, + * otherwise {@code false} + */ + public boolean hasTargetArtifactAssigned(@NotNull final String targetId, + @NotNull final LocalArtifact localArtifact) { + final Target target = targetRepository.findByControllerId(targetId); + if (target == null) { + return false; + } + return actionRepository.count(ActionSpecifications.hasTargetAssignedArtifact(target, localArtifact)) > 0; + } + /** * Refreshes the time of the last time the controller has been connected to * the server. diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java index 1573048ec..9508a6aeb 100644 --- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java +++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java @@ -58,6 +58,8 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Service; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionDefinition; +import org.springframework.transaction.annotation.Isolation; +import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.DefaultTransactionDefinition; import org.springframework.transaction.support.TransactionTemplate; @@ -259,13 +261,7 @@ public class RolloutManagement { entityManager.flush(); executor.execute(() -> { try { - final DefaultTransactionDefinition def = new DefaultTransactionDefinition(); - def.setName("creatingRollout"); - def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); - new TransactionTemplate(txManager, def).execute(status -> { - createRolloutGroups(amountGroup, conditions, savedRollout); - return null; - }); + createRolloutGroupsInNewTransaction(amountGroup, conditions, savedRollout); } finally { creatingRollouts.remove(savedRollout.getName()); } @@ -288,13 +284,22 @@ public class RolloutManagement { } } + private Rollout createRolloutGroupsInNewTransaction(final int amountOfGroups, final RolloutGroupConditions conditions, + final Rollout savedRollout) { + final DefaultTransactionDefinition def = new DefaultTransactionDefinition(); + def.setName("creatingRollout"); + def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); + return new TransactionTemplate(txManager, def) + .execute(status -> createRolloutGroups(amountOfGroups, conditions, savedRollout)); + } + /** * Method for creating rollout groups and calculating group sizes. Group * sizes are calculated by dividing the total count of targets through the * amount of given groups. In same cases this will lead to less rollout * groups than given by client. * - * @param amountGroup + * @param amountOfGroups * the amount of groups * @param conditions * the rollout group conditions @@ -302,17 +307,17 @@ public class RolloutManagement { * the rollout * @return the rollout with created groups */ - private Rollout createRolloutGroups(final int amountGroup, final RolloutGroupConditions conditions, + private Rollout createRolloutGroups(final int amountOfGroups, final RolloutGroupConditions conditions, final Rollout savedRollout) { int pageIndex = 0; int groupIndex = 0; final Long totalCount = savedRollout.getTotalTargets(); - final int groupSize = (int) Math.ceil((double) totalCount / (double) amountGroup); + final int groupSize = (int) Math.ceil((double) totalCount / (double) amountOfGroups); // validate if the amount of groups that will be created are the amount // of groups that the client what's to have created. - int amountGroupValidated = amountGroup; + int amountGroupValidated = amountOfGroups; final int amountGroupCreation = (int) (Math.ceil((double) totalCount / (double) groupSize)); - if (amountGroupCreation == (amountGroup - 1)) { + if (amountGroupCreation == (amountOfGroups - 1)) { amountGroupValidated--; } RolloutGroup lastSavedGroup = null; @@ -540,7 +545,7 @@ public class RolloutManagement { * this check. This check is only applied if the last check is * less than (lastcheck-delay). */ - @Transactional + @Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_UNCOMMITTED) @Modifying @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE + SpringEvalExpressions.HAS_AUTH_OR + SpringEvalExpressions.IS_SYSTEM_CODE) diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java index 5577e1d61..be370cf2d 100644 --- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java +++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java @@ -164,6 +164,7 @@ public class SystemManagement { * @return the {@link CurrentTenantKeyGenerator} */ @Bean + @Transactional(propagation = Propagation.SUPPORTS) public CurrentTenantKeyGenerator currentTenantKeyGenerator() { return new CurrentTenantKeyGenerator(); } @@ -206,7 +207,6 @@ public class SystemManagement { @NotNull @PreAuthorize(SpringEvalExpressions.HAS_AUTH_SYSTEM_ADMIN + SpringEvalExpressions.HAS_AUTH_OR + SpringEvalExpressions.IS_SYSTEM_CODE) - // tenant independent public List findTenants() { return tenantMetaDataRepository.findAll().stream().map(md -> md.getTenant()).collect(Collectors.toList()); } @@ -221,7 +221,6 @@ public class SystemManagement { @Transactional @Modifying @PreAuthorize(SpringEvalExpressions.HAS_AUTH_SYSTEM_ADMIN) - // tenant independent public void deleteTenant(@NotNull final String tenant) { cacheManager.evictCaches(tenant); cacheManager.getCache("currentTenant").evict(currentTenantKeyGenerator().generate(null, null)); diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/model/RolloutTargetGroup.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/model/RolloutTargetGroup.java index f1d4fe718..7a46b15b1 100644 --- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/model/RolloutTargetGroup.java +++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/model/RolloutTargetGroup.java @@ -24,13 +24,18 @@ import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.Table; +import org.eclipse.persistence.annotations.ExistenceChecking; +import org.eclipse.persistence.annotations.ExistenceType; + /** - * @author Michael Hirsch - * + * Entity with JPA annotation to store the information which {@link Target} is + * in a specific {@link RolloutGroup}. + * */ @IdClass(RolloutTargetGroupId.class) @Entity @Table(name = "sp_rollouttargetgroup") +@ExistenceChecking(ExistenceType.ASSUME_NON_EXISTENCE) public class RolloutTargetGroup implements Serializable { private static final long serialVersionUID = 1L; diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/specifications/ActionSpecifications.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/specifications/ActionSpecifications.java new file mode 100644 index 000000000..62e7167f1 --- /dev/null +++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/specifications/ActionSpecifications.java @@ -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.repository.specifications; + +import javax.persistence.criteria.Join; +import javax.persistence.criteria.ListJoin; +import javax.persistence.criteria.SetJoin; + +import org.eclipse.hawkbit.repository.model.Action; +import org.eclipse.hawkbit.repository.model.Action_; +import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.repository.model.DistributionSet_; +import org.eclipse.hawkbit.repository.model.LocalArtifact; +import org.eclipse.hawkbit.repository.model.LocalArtifact_; +import org.eclipse.hawkbit.repository.model.SoftwareModule; +import org.eclipse.hawkbit.repository.model.SoftwareModule_; +import org.eclipse.hawkbit.repository.model.Target; +import org.springframework.data.jpa.domain.Specification; + +/** + * Utility class for {@link Action}s {@link Specification}s. The class provides + * Spring Data JPQL Specifications. + * + */ +public class ActionSpecifications { + + private ActionSpecifications() { + // utility class + } + + /** + * Specification which joins all necessary tables to retrieve the dependency + * between a target and a local file assignment through the assigen action + * of the target. All actions are included, not only active actions. + * + * @param target + * the target to verfiy if the given artifact is currently + * assigned or had been assigned + * @param localArtifact + * the local artifact to check wherever the target had ever been + * assigned + * @return a specification to use with spring JPA + */ + public static Specification hasTargetAssignedArtifact(final Target target, + final LocalArtifact localArtifact) { + return (actionRoot, query, criteriaBuilder) -> { + final Join dsJoin = actionRoot.join(Action_.distributionSet); + final SetJoin modulesJoin = dsJoin.join(DistributionSet_.modules); + final ListJoin artifactsJoin = modulesJoin.join(SoftwareModule_.artifacts); + return criteriaBuilder.and( + criteriaBuilder.equal(artifactsJoin.get(LocalArtifact_.filename), localArtifact.getFilename()), + criteriaBuilder.equal(actionRoot.get(Action_.target), target)); + }; + } +} diff --git a/hawkbit-repository/src/test/java/org/eclipse/hawkbit/tenancy/MultiTenancyEntityTest.java b/hawkbit-repository/src/test/java/org/eclipse/hawkbit/tenancy/MultiTenancyEntityTest.java index 1dd4c9823..67b9b5a26 100644 --- a/hawkbit-repository/src/test/java/org/eclipse/hawkbit/tenancy/MultiTenancyEntityTest.java +++ b/hawkbit-repository/src/test/java/org/eclipse/hawkbit/tenancy/MultiTenancyEntityTest.java @@ -78,6 +78,22 @@ public class MultiTenancyEntityTest extends AbstractIntegrationTest { assertThat(findTargetsForTenant).hasSize(1); } + @Test + @Description(value = "Ensures that tenant with proper permissions can read and delete other tenants.") + @WithUser(tenantId = "mytenant", allSpPermissions = true) + public void deleteAnotherTenantPossible() throws Exception { + // create target for another tenant + final String anotherTenant = "anotherTenant"; + final String controllerAnotherTenant = "anotherController"; + createTargetForTenant(controllerAnotherTenant, anotherTenant); + + assertThat(systemManagement.findTenants()).as("Expected number if tenants before deletion is").hasSize(3); + + systemManagement.deleteTenant(anotherTenant); + + assertThat(systemManagement.findTenants()).as("Expected number if tenants after deletion is").hasSize(2); + } + @Test @Description(value = "Ensures that tenant metadata is retrieved for the current tenant.") @WithUser(tenantId = "mytenant", autoCreateTenant = false, allSpPermissions = true) diff --git a/hawkbit-ui/README.md b/hawkbit-ui/README.md new file mode 100644 index 000000000..4bf9d67da --- /dev/null +++ b/hawkbit-ui/README.md @@ -0,0 +1,34 @@ +# hawkBit User Interface + +The hawkBit user interface is based on the Vaadin and Vaadin-Spring framework and allows to manage software updates and large scale roll-outs via a user interface. + +## Debugging client-side code +### Debug using SuperDevMode +The SuperDevMode can be used to debug client side code without any browser plugin. + +#### Using SuperDevMode with chrome : + +- Add required maven dependencies + - Add vaadin-client-compiler dependency + - Add jetty dependencies (version : 8.1x) +- Set redirect property in the AppWidgetSet.gwt.xml module descriptor as follows + - < set-configuration-property name="devModeRedirectEnabled" value="true" /> +- Create launch configuration for the SuperDevMode + - The main class to execute should be com.google.gwt.dev.codeserver.CodeServer. + - Add fully-qualified class name of widgetset (org.eclipse.hawkbit.ui.AppWidgetSet) as parameter +- Enable debug in chrome + - Chrome inspector window ▸ Click on settings icon ▸ Scripts ▸ Enable source maps option +- Run the SuperDevMode Code Server with the launch configuration created above +- Open http://localhost:8080/UI/?debug .Click on "SuperDev" button in debug console (Alternatively can directly add ?superdevmode parameter to URL) +- Widgetset is compiled and you can see the java code files loaded in 'Chrome inspector window ▸ Source tab' + + +#### Using SuperDevMode with Eclipse : + +- Install the plugin from http://sdbg.github.io/p2 +- Start the server and Super Dev Mode as mentioned above +- Create a new launch configuration in Eclipse + - Type is "Launch Chrome" + - http://localhost:8080/UI/?superdevmode +- Launch the new configuration in debug mode +- Now breakpoints in eclipse can be set diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/HawkbitEventProvider.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/HawkbitEventProvider.java index 12bcaacbc..842cfcab5 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/HawkbitEventProvider.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/HawkbitEventProvider.java @@ -21,6 +21,7 @@ import org.eclipse.hawkbit.eventbus.event.TargetCreatedEvent; import org.eclipse.hawkbit.eventbus.event.TargetDeletedEvent; import org.eclipse.hawkbit.eventbus.event.TargetInfoUpdateEvent; import org.eclipse.hawkbit.eventbus.event.TargetTagCreatedBulkEvent; +import org.eclipse.hawkbit.eventbus.event.TargetTagDeletedEvent; /** * The default hawkbit event provider. @@ -34,6 +35,7 @@ public class HawkbitEventProvider implements UIEventProvider { SINGLE_EVENTS.add(TargetTagCreatedBulkEvent.class); SINGLE_EVENTS.add(DistributionSetTagCreatedBulkEvent.class); SINGLE_EVENTS.add(DistributionSetTagDeletedEvent.class); + SINGLE_EVENTS.add(TargetTagDeletedEvent.class); SINGLE_EVENTS.add(DistributionSetTagUpdateEvent.class); SINGLE_EVENTS.add(RolloutGroupChangeEvent.class); SINGLE_EVENTS.add(RolloutChangeEvent.class); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/footer/SMDeleteActionsLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/footer/SMDeleteActionsLayout.java index ee2fc356f..4cb28c2c3 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/footer/SMDeleteActionsLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/footer/SMDeleteActionsLayout.java @@ -8,16 +8,15 @@ */ package org.eclipse.hawkbit.ui.artifacts.footer; -import java.util.HashSet; import java.util.Set; import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent; import org.eclipse.hawkbit.ui.artifacts.event.UploadViewAcceptCriteria; import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState; import org.eclipse.hawkbit.ui.common.footer.AbstractDeleteActionsLayout; +import org.eclipse.hawkbit.ui.common.table.AbstractTable; import org.eclipse.hawkbit.ui.management.event.DragEvent; import org.eclipse.hawkbit.ui.utils.SPUIComponetIdProvider; -import org.eclipse.hawkbit.ui.utils.SPUIDefinitions; import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions; import org.springframework.beans.factory.annotation.Autowired; import org.vaadin.spring.events.EventScope; @@ -155,13 +154,9 @@ public class SMDeleteActionsLayout extends AbstractDeleteActionsLayout { private void addToDeleteList(final Table sourceTable, final TableTransferable transferable) { @SuppressWarnings("unchecked") - final Set swModuleSelected = (Set) sourceTable.getValue(); - final Set swModuleIdNameSet = new HashSet<>(); - if (!swModuleSelected.contains(transferable.getData(SPUIDefinitions.ITEMID))) { - swModuleIdNameSet.add((Long) transferable.getData(SPUIDefinitions.ITEMID)); - } else { - swModuleIdNameSet.addAll(swModuleSelected); - } + final AbstractTable swTable = (AbstractTable) sourceTable; + final Set swModuleIdNameSet = swTable.getDeletedEntityByTransferable(transferable); + swModuleIdNameSet.forEach(id -> { final String swModuleName = (String) sourceTable.getContainerDataSource().getItem(id) .getItemProperty(SPUILabelDefinitions.NAME_VERSION).getValue(); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/BaseSwModuleBeanQuery.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/BaseSwModuleBeanQuery.java index bb48c515a..29bea30eb 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/BaseSwModuleBeanQuery.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/BaseSwModuleBeanQuery.java @@ -16,6 +16,7 @@ import org.eclipse.hawkbit.repository.OffsetBasedPageRequest; import org.eclipse.hawkbit.repository.SoftwareManagement; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; +import org.eclipse.hawkbit.ui.common.UserDetailsFormatter; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil; import org.eclipse.hawkbit.ui.utils.SPUIDefinitions; @@ -101,8 +102,8 @@ public class BaseSwModuleBeanQuery extends AbstractBeanQuery getTableVisibleColumns() { final List columnList = super.getTableVisibleColumns(); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtype/CreateUpdateSoftwareTypeLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtype/CreateUpdateSoftwareTypeLayout.java index dc6d1081e..fe1fa9024 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtype/CreateUpdateSoftwareTypeLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtype/CreateUpdateSoftwareTypeLayout.java @@ -257,6 +257,7 @@ public class CreateUpdateSoftwareTypeLayout extends CustomComponent implements C mainLayout = new HorizontalLayout(); mainLayout.addComponent(fieldButtonLayout); setCompositionRoot(mainLayout); + typeName.focus(); } private void addListeners() { diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/UserDetailsFormatter.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/UserDetailsFormatter.java new file mode 100644 index 000000000..d4a733de3 --- /dev/null +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/UserDetailsFormatter.java @@ -0,0 +1,185 @@ +/** + * 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; + +import java.util.Collections; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.hawkbit.im.authentication.UserPrincipal; +import org.eclipse.hawkbit.repository.model.BaseEntity; +import org.eclipse.hawkbit.ui.utils.SpringContextHelper; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.web.context.HttpSessionSecurityContextRepository; + +import com.vaadin.server.VaadinService; + +/** + * A Utility class to user details e.g. username + */ +public final class UserDetailsFormatter { + + private static final String TRIM_APPENDIX = "..."; + private static final String DETAIL_SEPERATOR = ", "; + + private UserDetailsFormatter() { + } + + /** + * Load user details by the user name and format the user name to max 100 + * characters. + * + * @see {@link UserDetailsFormatter#loadAndFormatUsername(String, int)} + * + * @param username + * the user name + * @return the formatted user name (max 100 characters) cannot be + */ + public static String loadAndFormatUsername(final String username) { + return loadAndFormatUsername(username, 100); + } + + /** + * Load user details by {@link BaseEntity#getCreatedBy()} and format the + * user name. Use {@link UserDetailsFormatter#loadAndFormatUsername(String)} + * + * @param baseEntity + * the entity + * @return the formatted 'created at user name' (max 100 characters) cannot + * be + */ + public static String loadAndFormatCreatedBy(final BaseEntity baseEntity) { + if (baseEntity == null || baseEntity.getCreatedBy() == null) { + return StringUtils.EMPTY; + } + + return loadAndFormatUsername(baseEntity.getCreatedBy()); + } + + /** + * Load user details by {@link BaseEntity#getLastModifiedBy()} and format + * the user name. Use + * {@link UserDetailsFormatter#loadAndFormatUsername(String)} + * + * @param baseEntity + * the entity + * @return the formatted 'last modefied by user name' (max 100 characters) + * cannot be + */ + public static String loadAndFormatLastModifiedBy(final BaseEntity baseEntity) { + if (baseEntity == null || baseEntity.getLastModifiedBy() == null) { + return StringUtils.EMPTY; + } + + return loadAndFormatUsername(baseEntity.getLastModifiedBy()); + } + + /** + * Load user details by the current session information and format the user + * name to max 12 characters. @see + * {@link UserDetailsFormatter#loadAndFormatUsername(String, int)} + * + * @return the formatted user name (max 12 characters) cannot be + */ + public static String formatCurrentUsername() { + return loadAndFormatUsername(getCurrentUser().getUsername(), 5); + } + + /** + * Load user details by the user name and format the user name. If the + * loaded {@link UserDetails} is not an instance of a {@link UserPrincipal}, + * then just the {@link UserDetails#getUsername()} will return. + * + * If first and last name available, they will combined. Otherwise the + * {@link UserPrincipal#getLoginname()} will formatted. The formatted name + * is reduced to 100 characters. + * + * @param username + * the user name + * @param expectedNameLength + * the name size of each name part + * @return the formatted user name (max expectedNameLength characters) + * cannot be + */ + public static String loadAndFormatUsername(final String username, final int expectedNameLength) { + final UserDetails userDetails = loadUserByUsername(username); + return formatUserName(expectedNameLength, userDetails); + } + + private static String formatUserName(final int expectedNameLength, final UserDetails userDetails) { + if (!(userDetails instanceof UserPrincipal)) { + return userDetails.getUsername(); + } + + final UserPrincipal userPrincipal = (UserPrincipal) userDetails; + + String firstname = StringUtils.defaultIfEmpty(userPrincipal.getFirstname(), StringUtils.EMPTY); + + if (!StringUtils.isEmpty(firstname)) { + firstname += DETAIL_SEPERATOR; + } + + final String firstAndLastname = firstname + + StringUtils.defaultIfEmpty(userPrincipal.getLastname(), StringUtils.EMPTY); + + final String trimmedUsername = trimAndFormatDetail(firstAndLastname, expectedNameLength); + + if (StringUtils.isEmpty(trimmedUsername)) { + return trimAndFormatDetail(userPrincipal.getLoginname(), expectedNameLength); + } + return trimmedUsername; + } + + /** + * Format the current tenant. The information is loaded by the current + * session information. + * + * @return the formatted user name (max 8 characters) can be + */ + public static String formatCurrentTenant() { + final UserDetails userDetails = getCurrentUser(); + if (!(userDetails instanceof UserPrincipal)) { + return null; + } + + final UserPrincipal userPrincipal = (UserPrincipal) userDetails; + return trimAndFormatDetail(userPrincipal.getTenant(), 8); + } + + private static UserDetails getCurrentUser() { + final SecurityContext context = (SecurityContext) VaadinService.getCurrentRequest().getWrappedSession() + .getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY); + return (UserDetails) context.getAuthentication().getPrincipal(); + } + + private static String trimAndFormatDetail(final String formatString, final int expectedDetailLength) { + final String detail = StringUtils.defaultIfEmpty(formatString, StringUtils.EMPTY); + final String trimmedDetail = StringUtils.substring(detail, 0, expectedDetailLength); + if (StringUtils.length(detail) > expectedDetailLength) { + return trimmedDetail + TRIM_APPENDIX; + } + return trimmedDetail; + } + + private static UserDetails loadUserByUsername(final String username) { + final UserDetailsService userDetailsService = SpringContextHelper.getBean(UserDetailsService.class); + try { + final UserDetails loadUserByUsername = userDetailsService.loadUserByUsername(username); + if (loadUserByUsername == null) { + throw new UsernameNotFoundException("User not found " + username); + } + return loadUserByUsername; + } catch (final UsernameNotFoundException e) { + return new User(username, "", Collections.emptyList()); + } + } +} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/AbstractTableDetailsLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/AbstractTableDetailsLayout.java index 969436904..360a9f925 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/AbstractTableDetailsLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/AbstractTableDetailsLayout.java @@ -171,9 +171,7 @@ public abstract class AbstractTableDetailsLayout extends } private Label createHeaderCaption() { - final Label captionLabel = SPUIComponentProvider.getLabel(getDefaultCaption(), - SPUILabelDefinitions.SP_WIDGET_CAPTION); - return captionLabel; + return SPUIComponentProvider.getLabel(getDefaultCaption(), SPUILabelDefinitions.SP_WIDGET_CAPTION); } protected VerticalLayout getTabLayout() { @@ -213,22 +211,22 @@ public abstract class AbstractTableDetailsLayout extends populateDetailsWidget(); } - protected void updateLogLayout(final VerticalLayout changeLogLayout, final Long lastModifiedAt, - final String lastModifiedBy, final Long createdAt, final String createdBy, final I18N i18n) { - changeLogLayout.removeAllComponents(); - changeLogLayout.addComponent(SPUIComponentProvider.createNameValueLabel(i18n.get("label.created.at"), - createdAt == null ? "" : SPDateTimeUtil.getFormattedDate(createdAt))); + protected void populateLog() { + logLayout.removeAllComponents(); - changeLogLayout.addComponent(SPUIComponentProvider.createNameValueLabel(i18n.get("label.created.by"), - createdBy == null ? "" : HawkbitCommonUtil.getIMUser(createdBy))); + logLayout.addComponent(SPUIComponentProvider.createNameValueLabel(i18n.get("label.created.at"), + SPDateTimeUtil.formatCreatedAt(selectedBaseEntity))); - if (null != lastModifiedAt) { - changeLogLayout.addComponent(SPUIComponentProvider.createNameValueLabel(i18n.get("label.modified.date"), - SPDateTimeUtil.getFormattedDate(lastModifiedAt))); + logLayout.addComponent(SPUIComponentProvider.createCreatedByLabel(i18n, selectedBaseEntity)); - changeLogLayout.addComponent(SPUIComponentProvider.createNameValueLabel(i18n.get("label.modified.by"), - lastModifiedBy == null ? "" : HawkbitCommonUtil.getIMUser(lastModifiedBy))); + if (selectedBaseEntity == null || selectedBaseEntity.getLastModifiedAt() == null) { + return; } + + logLayout.addComponent(SPUIComponentProvider.createNameValueLabel(i18n.get("label.modified.date"), + SPDateTimeUtil.formatLastModifiedAt(selectedBaseEntity))); + + logLayout.addComponent(SPUIComponentProvider.createLastModifiedByLabel(i18n, selectedBaseEntity)); } protected void updateDescriptionLayout(final String descriptionLabel, final String description) { @@ -320,19 +318,6 @@ public abstract class AbstractTableDetailsLayout extends return detailsLayout; } - public VerticalLayout getLogLayout() { - return logLayout; - } - - private void populateLog() { - if (selectedBaseEntity == null) { - updateLogLayout(getLogLayout(), null, StringUtils.EMPTY, null, null, i18n); - return; - } - updateLogLayout(getLogLayout(), selectedBaseEntity.getLastModifiedAt(), selectedBaseEntity.getLastModifiedBy(), - selectedBaseEntity.getCreatedAt(), selectedBaseEntity.getCreatedBy(), i18n); - } - private void populateDescription() { if (selectedBaseEntity != null) { updateDescriptionLayout(i18n.get("label.description"), selectedBaseEntity.getDescription()); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTable.java index eb1951d27..1808cf070 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTable.java @@ -10,6 +10,7 @@ package org.eclipse.hawkbit.ui.common.table; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Set; @@ -19,7 +20,7 @@ import javax.annotation.PreDestroy; import org.eclipse.hawkbit.repository.model.NamedEntity; import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent; import org.eclipse.hawkbit.ui.common.ManagmentEntityState; -import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; +import org.eclipse.hawkbit.ui.common.UserDetailsFormatter; import org.eclipse.hawkbit.ui.utils.I18N; import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil; import org.eclipse.hawkbit.ui.utils.SPUIDefinitions; @@ -211,9 +212,9 @@ public abstract class AbstractTable extends Table { item.getItemProperty(SPUILabelDefinitions.VAR_ID).setValue(baseEntity.getId()); item.getItemProperty(SPUILabelDefinitions.VAR_DESC).setValue(baseEntity.getDescription()); item.getItemProperty(SPUILabelDefinitions.VAR_CREATED_BY) - .setValue(HawkbitCommonUtil.getIMUser(baseEntity.getCreatedBy())); + .setValue(UserDetailsFormatter.loadAndFormatCreatedBy(baseEntity)); item.getItemProperty(SPUILabelDefinitions.VAR_LAST_MODIFIED_BY) - .setValue(HawkbitCommonUtil.getIMUser(baseEntity.getLastModifiedBy())); + .setValue(UserDetailsFormatter.loadAndFormatLastModifiedBy(baseEntity)); item.getItemProperty(SPUILabelDefinitions.VAR_CREATED_DATE) .setValue(SPDateTimeUtil.getFormattedDate(baseEntity.getCreatedAt())); item.getItemProperty(SPUILabelDefinitions.VAR_LAST_MODIFIED_DATE) @@ -231,6 +232,30 @@ public abstract class AbstractTable extends Table { } } + /** + * Return the entity which should be deleted by a transferable + * + * @param transferable + * the table transferable + * @return set of entities id which will deleted + */ + @SuppressWarnings("unchecked") + public Set getDeletedEntityByTransferable(final TableTransferable transferable) { + final Set selectedEntities = (Set) getTableValue(this); + final Set ids = new HashSet<>(); + final Object tranferableData = transferable.getData(SPUIDefinitions.ITEMID); + if (tranferableData == null) { + return ids; + } + + if (!selectedEntities.contains(tranferableData)) { + ids.add((I) tranferableData); + } else { + ids.addAll(selectedEntities); + } + return ids; + } + protected abstract E findEntityByTableValue(I lastSelectedId); protected abstract void publishEntityAfterValueChange(E selectedLastEntity); @@ -304,6 +329,17 @@ public abstract class AbstractTable extends Table { columnList.add( new TableColumn(SPUILabelDefinitions.VAR_LAST_MODIFIED_DATE, i18n.get("header.modifiedDate"), 0.1F)); columnList.add(new TableColumn(SPUILabelDefinitions.VAR_DESC, i18n.get("header.description"), 0.2F)); + setItemDescriptionGenerator((source, itemId, propertyId) -> { + + if (SPUILabelDefinitions.VAR_CREATED_BY.equals(propertyId)) { + return getItem(itemId).getItemProperty(SPUILabelDefinitions.VAR_CREATED_BY).getValue().toString(); + } + if (SPUILabelDefinitions.VAR_LAST_MODIFIED_BY.equals(propertyId)) { + return getItem(itemId).getItemProperty(SPUILabelDefinitions.VAR_LAST_MODIFIED_BY).getValue().toString(); + } + return null; + }); + return columnList; } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/ProxyTarget.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/ProxyTarget.java index d85b2bc71..9ac39616d 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/ProxyTarget.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/ProxyTarget.java @@ -36,6 +36,8 @@ public class ProxyTarget extends Target { private DistributionSet installedDistributionSet; + private DistributionSet assignedDistributionSet; + private TargetIdName targetIdName; private String assignedDistNameVersion; @@ -249,6 +251,21 @@ public class ProxyTarget extends Target { this.installedDistributionSet = installedDistributionSet; } + /** + * @return the assignedDistributionSet + */ + public DistributionSet getAssignedDistributionSet() { + return assignedDistributionSet; + } + + /** + * @param assignedDistributionSet + * the assignedDistributionSet to set + */ + public void setAssignedDistributionSet(DistributionSet assignedDistributionSet) { + this.assignedDistributionSet = assignedDistributionSet; + } + /** * @return the targetIdName */ @@ -297,4 +314,5 @@ public class ProxyTarget extends Target { public void setStatus(final Status status) { this.status = status; } + } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/SPUIComponentProvider.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/SPUIComponentProvider.java index f5008eb31..d8e5e31d1 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/SPUIComponentProvider.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/SPUIComponentProvider.java @@ -12,7 +12,9 @@ import java.util.Arrays; import java.util.Map; import org.apache.commons.lang3.StringUtils; +import org.eclipse.hawkbit.repository.model.BaseEntity; import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.ui.common.UserDetailsFormatter; import org.eclipse.hawkbit.ui.decorators.SPUIButtonDecorator; import org.eclipse.hawkbit.ui.decorators.SPUIComboBoxDecorator; import org.eclipse.hawkbit.ui.decorators.SPUIHeaderLayoutDecorator; @@ -20,6 +22,7 @@ import org.eclipse.hawkbit.ui.decorators.SPUILabelDecorator; import org.eclipse.hawkbit.ui.decorators.SPUITextAreaDecorator; import org.eclipse.hawkbit.ui.decorators.SPUITextFieldDecorator; import org.eclipse.hawkbit.ui.decorators.SPUIWindowDecorator; +import org.eclipse.hawkbit.ui.utils.I18N; import org.eclipse.hawkbit.ui.utils.SPUIDefinitions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -328,6 +331,50 @@ public final class SPUIComponentProvider { return nameValueLabel; } + private static Label createUsernameLabel(final String label, final String username) { + String loadAndFormatUsername = StringUtils.EMPTY; + if (!StringUtils.isEmpty(username)) { + loadAndFormatUsername = UserDetailsFormatter.loadAndFormatUsername(username); + } + + final Label nameValueLabel = new Label(getBoldHTMLText(label) + loadAndFormatUsername, ContentMode.HTML); + nameValueLabel.setSizeFull(); + nameValueLabel.addStyleName(SPUIDefinitions.TEXT_STYLE); + nameValueLabel.addStyleName("label-style"); + nameValueLabel.setDescription(loadAndFormatUsername); + return nameValueLabel; + } + + /** + * Create label which represents the {@link BaseEntity#getCreatedBy()} by + * user name + * + * @param i18n + * the i18n + * @param baseEntity + * the entity + * @return the label + */ + public static Label createCreatedByLabel(final I18N i18n, final BaseEntity baseEntity) { + return createUsernameLabel(i18n.get("label.created.by"), + baseEntity == null ? StringUtils.EMPTY : baseEntity.getCreatedBy()); + } + + /** + * Create label which represents the + * {@link BaseEntity#getLastModifiedBy()()} by user name + * + * @param i18n + * the i18n + * @param baseEntity + * the entity + * @return the label + */ + public static Label createLastModifiedByLabel(final I18N i18n, final BaseEntity baseEntity) { + return createUsernameLabel(i18n.get("label.modified.by"), + baseEntity == null ? StringUtils.EMPTY : baseEntity.getLastModifiedBy()); + } + /** * Get Bold Text. * diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/customrenderers/client/LinkRendererConnector.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/customrenderers/client/LinkRendererConnector.java deleted file mode 100644 index bc48d64d7..000000000 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/customrenderers/client/LinkRendererConnector.java +++ /dev/null @@ -1,29 +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.customrenderers.client; - -import org.eclipse.hawkbit.ui.customrenderers.renderers.LinkRenderer; - -import com.vaadin.client.connectors.ButtonRendererConnector; -import com.vaadin.shared.ui.Connect; - -/** - * - * A connector for {@link LinkRenderer}. - * - */ -@Connect(org.eclipse.hawkbit.ui.customrenderers.renderers.LinkRenderer.class) -public class LinkRendererConnector extends ButtonRendererConnector { - private static final long serialVersionUID = 7987417436367399331L; - - @Override - public org.eclipse.hawkbit.ui.customrenderers.client.renderers.LinkRenderer getRenderer() { - return (org.eclipse.hawkbit.ui.customrenderers.client.renderers.LinkRenderer) super.getRenderer(); - } -} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/customrenderers/client/RolloutRendererConnector.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/customrenderers/client/RolloutRendererConnector.java new file mode 100644 index 000000000..2175dea29 --- /dev/null +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/customrenderers/client/RolloutRendererConnector.java @@ -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.RolloutRendererData; + +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 CustomObjectRenderer }. + * + */ +@Connect(org.eclipse.hawkbit.ui.customrenderers.renderers.RolloutRenderer.class) +public class RolloutRendererConnector extends ClickableRendererConnector { + private static final long serialVersionUID = 7734682321931830566L; + + public org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRenderer getRenderer() { + return (org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRenderer) super.getRenderer(); + } + + @Override + protected HandlerRegistration addClickHandler( + RendererClickHandler handler) { + return getRenderer().addClickHandler(handler); + } +} \ No newline at end of file diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/customrenderers/client/renderers/LinkRenderer.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/customrenderers/client/renderers/LinkRenderer.java deleted file mode 100644 index 0abe4044b..000000000 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/customrenderers/client/renderers/LinkRenderer.java +++ /dev/null @@ -1,42 +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.customrenderers.client.renderers; - -import com.google.gwt.user.client.ui.Button; -import com.vaadin.client.renderers.ButtonRenderer; -import com.vaadin.client.ui.VButton; -import com.vaadin.client.widget.grid.RendererCellReference; - -/** - * - * Renders link with provided text. - * - */ -public class LinkRenderer extends ButtonRenderer { - @Override - public void render(RendererCellReference cell, String text, Button button) { - button.setText(text); - applystyle(button); - // this is to allow the button to disappear, if the text is null - button.setVisible(text != null); - button.getElement().setId(new StringBuilder("link").append(".").append(text).toString()); - } - - private void applystyle(Button button) { - button.setStyleName(VButton.CLASSNAME); - button.addStyleName(getStyle("borderless")); - button.addStyleName(getStyle("small")); - button.addStyleName(getStyle("on-focus-no-border")); - button.addStyleName(getStyle("link")); - } - - private String getStyle(final String style) { - return new StringBuilder(style).append(" ").append(VButton.CLASSNAME).append("-").append(style).toString(); - } -} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/customrenderers/client/renderers/RolloutRenderer.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/customrenderers/client/renderers/RolloutRenderer.java new file mode 100644 index 000000000..da8fc2544 --- /dev/null +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/customrenderers/client/renderers/RolloutRenderer.java @@ -0,0 +1,65 @@ +/** + * 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.vaadin.client.renderers.ClickableRenderer; +import com.vaadin.client.ui.VButton; +import com.vaadin.client.widget.grid.RendererCellReference; + +/** + * Renders button with provided CustomObject. + * Used to display button with link. + * + */ +public class RolloutRenderer extends ClickableRenderer { + + @Override + public VButton createWidget() { + VButton b = GWT.create(VButton.class); + b.addClickHandler(this); + b.setStylePrimaryName("v-nativebutton"); + return b; + } + + @Override + public void render(RendererCellReference cell, RolloutRendererData text, VButton button) { + final String creating = "CREATING"; + button.setText(text.getName()); + applystyle(button); + // this is to allow the button to disappear, if the text is null + button.setVisible(text.getName() != null); + button.getElement().setId(new StringBuilder("link").append(".").append(text.getName()).toString()); + /* + * checking Rollout Status for applying button style. If Rollout status + * is not "CREATING", then the Rollout button is applying hyperlink + * style + */ + final boolean isStatusCreate = text.getStatus() != null && creating.equalsIgnoreCase(text.getStatus()); + if (isStatusCreate) { + button.addStyleName(getStyle("boldhide")); + button.setEnabled(false); + } else { + button.setEnabled(true); + } + } + + private void applystyle(VButton button) { + button.setStyleName(VButton.CLASSNAME); + button.addStyleName(getStyle("borderless")); + button.addStyleName(getStyle("small")); + button.addStyleName(getStyle("on-focus-no-border")); + button.addStyleName(getStyle("link")); + } + + private String getStyle(final String style) { + return new StringBuilder(style).append(" ").append(VButton.CLASSNAME).append("-").append(style).toString(); + } + +} \ No newline at end of file diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/customrenderers/client/renderers/RolloutRendererData.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/customrenderers/client/renderers/RolloutRendererData.java new file mode 100644 index 000000000..6c751e6a2 --- /dev/null +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/customrenderers/client/renderers/RolloutRendererData.java @@ -0,0 +1,62 @@ +/** + * 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; + +/** + * RendererData class with Name and Status. + * + */ + +public class RolloutRendererData implements Serializable { + private static final long serialVersionUID = -5018181529953620263L; + + private String name; + + private String status; + + /** + * Initialize the RendererData. + */ + public RolloutRendererData() { + + } + + /** + * Initialize the RendererData. + * + * @param name + * Name of the Rollout. + * @param status + * Status of Rollout. + */ + public RolloutRendererData(String name, String status) { + super(); + this.name = name; + this.status = status; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + +} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/customrenderers/renderers/LinkRenderer.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/customrenderers/renderers/LinkRenderer.java deleted file mode 100644 index d913ca380..000000000 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/customrenderers/renderers/LinkRenderer.java +++ /dev/null @@ -1,37 +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.customrenderers.renderers; - -import com.vaadin.ui.renderers.ButtonRenderer; - -/** - * - * Renders link with provided text. - * - */ -public class LinkRenderer extends ButtonRenderer { - private static final long serialVersionUID = -1242995370043404892L; - - /** - * Intialise link renderer. - */ - public LinkRenderer() { - super(); - } - - /** - * Intialise link renderer with {@link RendererClickListener} - * - * @param listener - * RendererClickListener - */ - public LinkRenderer(RendererClickListener listener) { - super(listener); - } -} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/customrenderers/renderers/RolloutRenderer.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/customrenderers/renderers/RolloutRenderer.java new file mode 100644 index 000000000..29663dd9d --- /dev/null +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/customrenderers/renderers/RolloutRenderer.java @@ -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.renderers; + +import org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRendererData; + +import com.vaadin.ui.renderers.ClickableRenderer; + +import elemental.json.JsonValue; + +/** + * Renders button with provided CustomObject. + * Used to display button with link. + * + */ + +public class RolloutRenderer extends ClickableRenderer { + + private static final long serialVersionUID = -8754180585906263554L; + + /** + * Creates a new custom object renderer. + */ + public RolloutRenderer() { + super(RolloutRendererData.class, null); + } + + /** + * Initialize custom object renderer with {@link Class} + * + * @param presentationType + * Class + */ + + public RolloutRenderer(Class presentationType) { + super(presentationType); + } + + /** + * Creates a new custom object renderer and adds the given click listener to it. + * + * @param listener + * the click listener to register + */ + public RolloutRenderer(RendererClickListener listener) { + this(); + addClickListener(listener); + } + + @Override + public JsonValue encode(RolloutRendererData resource) { + return super.encode(resource, RolloutRendererData.class); + } +} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/disttype/CreateUpdateDistSetTypeLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/disttype/CreateUpdateDistSetTypeLayout.java index 8d609f628..64a06bd38 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/disttype/CreateUpdateDistSetTypeLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/disttype/CreateUpdateDistSetTypeLayout.java @@ -284,7 +284,7 @@ public class CreateUpdateDistSetTypeLayout extends CustomComponent implements Co mainLayout.addComponent(fieldLayout); mainLayout.addComponent(twinTableLayout); - + colorLayout = new HorizontalLayout(); sliderLayout = new VerticalLayout(); final HorizontalLayout chooseColorLayout = new HorizontalLayout(); @@ -299,6 +299,7 @@ public class CreateUpdateDistSetTypeLayout extends CustomComponent implements Co mainWindowLayout.addComponent(colorLayout); mainWindowLayout.addComponent(buttonLayout); setCompositionRoot(mainWindowLayout); + typeName.focus(); } private HorizontalLayout createTwinColumnLayout() { diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTable.java index 1cd89b30f..01c242247 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTable.java @@ -29,6 +29,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleIdName; import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent; import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent.SoftwareModuleEventType; import org.eclipse.hawkbit.ui.common.table.AbstractNamedVersionTable; +import org.eclipse.hawkbit.ui.common.table.AbstractTable; import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; import org.eclipse.hawkbit.ui.distributions.event.DistributionsUIEvent; import org.eclipse.hawkbit.ui.distributions.event.DistributionsViewAcceptCriteria; @@ -210,15 +211,9 @@ public class DistributionSetTable extends AbstractNamedVersionTable softwareModuleSelected = (Set) source.getValue(); - final Set softwareModulesIdList = new HashSet<>(); - - if (!softwareModuleSelected.contains(transferable.getData("itemId"))) { - softwareModulesIdList.add((Long) transferable.getData("itemId")); - } else { - softwareModulesIdList.addAll(softwareModuleSelected); - } + @SuppressWarnings("unchecked") + final AbstractTable source = (AbstractTable) transferable.getSourceComponent(); + final Set softwareModulesIdList = source.getDeletedEntityByTransferable(transferable); final AbstractSelectTargetDetails dropData = (AbstractSelectTargetDetails) event.getTargetDetails(); @@ -229,11 +224,6 @@ public class DistributionSetTable extends AbstractNamedVersionTable softwareModulesIdList, final Item item) { final Long distId = (Long) item.getItemProperty("id").getValue(); final String distName = (String) item.getItemProperty("name").getValue(); @@ -459,12 +449,8 @@ public class DistributionSetTable extends AbstractNamedVersionTable { proxyDistribution.setCreatedDate(SPDateTimeUtil.getFormattedDate(distributionSet.getCreatedAt())); proxyDistribution.setLastModifiedDate(SPDateTimeUtil.getFormattedDate(distributionSet.getLastModifiedAt())); proxyDistribution.setDescription(distributionSet.getDescription()); - proxyDistribution.setCreatedByUser(HawkbitCommonUtil.getIMUser(distributionSet.getCreatedBy())); - proxyDistribution.setModifiedByUser(HawkbitCommonUtil.getIMUser(distributionSet.getLastModifiedBy())); + proxyDistribution.setCreatedByUser(UserDetailsFormatter.loadAndFormatCreatedBy(distributionSet)); + proxyDistribution.setModifiedByUser(UserDetailsFormatter.loadAndFormatLastModifiedBy(distributionSet)); proxyDistribution.setIsComplete(distributionSet.isComplete()); proxyDistributions.add(proxyDistribution); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/footer/DSDeleteActionsLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/footer/DSDeleteActionsLayout.java index dba8155db..5bc1627a9 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/footer/DSDeleteActionsLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/footer/DSDeleteActionsLayout.java @@ -20,6 +20,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSetIdName; import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.SoftwareModuleIdName; import org.eclipse.hawkbit.ui.common.footer.AbstractDeleteActionsLayout; +import org.eclipse.hawkbit.ui.common.table.AbstractTable; import org.eclipse.hawkbit.ui.distributions.event.DistributionsUIEvent; import org.eclipse.hawkbit.ui.distributions.event.DistributionsViewAcceptCriteria; import org.eclipse.hawkbit.ui.distributions.event.DragEvent; @@ -188,13 +189,8 @@ public class DSDeleteActionsLayout extends AbstractDeleteActionsLayout { private void addInDeleteDistributionList(final Table sourceTable, final TableTransferable transferable) { @SuppressWarnings("unchecked") - final Set distSelected = (Set) sourceTable.getValue(); - final Set distributionIdNameSet = new HashSet<>(); - if (!distSelected.contains(transferable.getData(SPUIDefinitions.ITEMID))) { - distributionIdNameSet.add((DistributionSetIdName) transferable.getData(SPUIDefinitions.ITEMID)); - } else { - distributionIdNameSet.addAll(distSelected); - } + final AbstractTable table = (AbstractTable) sourceTable; + final Set distributionIdNameSet = table.getDeletedEntityByTransferable(transferable); /* * Flags to identify whether all dropped distributions are already in * the deleted list (or) some distributions are already in the deleted @@ -224,15 +220,10 @@ public class DSDeleteActionsLayout extends AbstractDeleteActionsLayout { } private void addToSWDeleteList(final Table sourceTable, final TableTransferable transferable) { - @SuppressWarnings("unchecked") - final Set swModuleSelected = (Set) sourceTable.getValue(); - final Set swModuleIdNameSet = new HashSet<>(); - if (!swModuleSelected.contains(transferable.getData(SPUIDefinitions.ITEMID))) { - swModuleIdNameSet.add((Long) transferable.getData(SPUIDefinitions.ITEMID)); - } else { - swModuleIdNameSet.addAll(swModuleSelected); - } + final AbstractTable swTable = (AbstractTable) sourceTable; + final Set swModuleIdNameSet = swTable.getDeletedEntityByTransferable(transferable); + swModuleIdNameSet.forEach(id -> { final String swModuleName = (String) sourceTable.getContainerDataSource().getItem(id) .getItemProperty(SPUILabelDefinitions.NAME_VERSION).getValue(); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleBeanQuery.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleBeanQuery.java index 5419cc1bf..21ce01347 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleBeanQuery.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleBeanQuery.java @@ -17,6 +17,7 @@ import org.eclipse.hawkbit.repository.SoftwareManagement; import org.eclipse.hawkbit.repository.model.CustomSoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; +import org.eclipse.hawkbit.ui.common.UserDetailsFormatter; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil; import org.eclipse.hawkbit.ui.utils.SPUIDefinitions; @@ -99,8 +100,8 @@ public class SwModuleBeanQuery extends AbstractBeanQuery proxyItem.setVersion(bean.getVersion()); proxyItem.setVendor(bean.getVendor()); proxyItem.setDescription(bean.getDescription()); - proxyItem.setCreatedByUser(HawkbitCommonUtil.getIMUser(bean.getCreatedBy())); - proxyItem.setModifiedByUser(HawkbitCommonUtil.getIMUser(bean.getLastModifiedBy())); + proxyItem.setCreatedByUser(UserDetailsFormatter.loadAndFormatCreatedBy(bean)); + proxyItem.setModifiedByUser(UserDetailsFormatter.loadAndFormatLastModifiedBy(bean)); proxyItem.setAssigned(customSoftwareModule.isAssigned()); proxyItem.setColour(bean.getType().getColour()); proxyItem.setTypeId(bean.getType().getId()); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleTable.java index a9a4562ce..eeea33723 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleTable.java @@ -324,17 +324,9 @@ public class SwModuleTable extends AbstractNamedVersionTable getVisbleColumns() { @@ -186,12 +200,12 @@ public class CreateOrUpdateFilterTable extends Table { columnList.add(new TableColumn(SPUILabelDefinitions.VAR_LAST_MODIFIED_BY, i18n.get("header.modifiedBy"), 0.1F)); columnList.add( new TableColumn(SPUILabelDefinitions.VAR_LAST_MODIFIED_DATE, i18n.get("header.modifiedDate"), 0.1F)); + columnList.add(new TableColumn(SPUILabelDefinitions.VAR_DESC, i18n.get("header.description"), 0.1F)); + columnList.add(new TableColumn(SPUILabelDefinitions.STATUS_ICON, i18n.get("header.status"), 0.1F)); columnList.add(new TableColumn(SPUILabelDefinitions.ASSIGNED_DISTRIBUTION_NAME_VER, i18n.get("header.assigned.ds"), 0.125F)); columnList.add(new TableColumn(SPUILabelDefinitions.INSTALLED_DISTRIBUTION_NAME_VER, i18n.get("header.installed.ds"), 0.125F)); - columnList.add(new TableColumn(SPUILabelDefinitions.VAR_DESC, i18n.get("header.description"), 0.1F)); - columnList.add(new TableColumn(SPUILabelDefinitions.STATUS_ICON, i18n.get("header.status"), 0.1F)); return columnList; } @@ -244,4 +258,5 @@ public class CreateOrUpdateFilterTable extends Table { populateTableData(); eventBus.publish(this, CustomFilterUIEvent.UPDATE_TARGET_FILTER_SEARCH_ICON); } + } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/CustomTargetBeanQuery.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/CustomTargetBeanQuery.java index bf5fdbe54..2cc572245 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/CustomTargetBeanQuery.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/CustomTargetBeanQuery.java @@ -15,6 +15,7 @@ import java.util.Map; import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Target; +import org.eclipse.hawkbit.ui.common.UserDetailsFormatter; import org.eclipse.hawkbit.ui.components.ProxyTarget; import org.eclipse.hawkbit.ui.filtermanagement.state.FilterManagementUIState; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; @@ -118,8 +119,8 @@ public class CustomTargetBeanQuery extends AbstractBeanQuery { prxyTarget.setLastModifiedDate(SPDateTimeUtil.getFormattedDate(targ.getLastModifiedAt())); prxyTarget.setCreatedDate(SPDateTimeUtil.getFormattedDate(targ.getCreatedAt())); prxyTarget.setCreatedAt(targ.getCreatedAt()); - prxyTarget.setCreatedByUser(HawkbitCommonUtil.getIMUser(targ.getCreatedBy())); - prxyTarget.setModifiedByUser(HawkbitCommonUtil.getIMUser(targ.getLastModifiedBy())); + prxyTarget.setCreatedByUser(UserDetailsFormatter.loadAndFormatCreatedBy(targ)); + prxyTarget.setModifiedByUser(UserDetailsFormatter.loadAndFormatLastModifiedBy(targ)); final Target target = getTargetManagement().findTargetByControllerIDWithDetails(targ.getControllerId()); final DistributionSet installedDistributionSet = target.getTargetInfo().getInstalledDistributionSet(); prxyTarget.setInstalledDistributionSet(installedDistributionSet); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/TargetFilterBeanQuery.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/TargetFilterBeanQuery.java index 9c50640cd..4a2d6da6c 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/TargetFilterBeanQuery.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/TargetFilterBeanQuery.java @@ -14,6 +14,7 @@ import java.util.Map; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.model.TargetFilterQuery; +import org.eclipse.hawkbit.ui.common.UserDetailsFormatter; import org.eclipse.hawkbit.ui.components.ProxyTargetFilter; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil; @@ -93,9 +94,9 @@ public class TargetFilterBeanQuery extends AbstractBeanQuery proxyTarFilter.setName(tarFilterQuery.getName()); proxyTarFilter.setId(tarFilterQuery.getId()); proxyTarFilter.setCreatedDate(SPDateTimeUtil.getFormattedDate(tarFilterQuery.getCreatedAt())); - proxyTarFilter.setCreatedBy(HawkbitCommonUtil.getIMUser(tarFilterQuery.getCreatedBy())); + proxyTarFilter.setCreatedBy(UserDetailsFormatter.loadAndFormatCreatedBy(tarFilterQuery)); proxyTarFilter.setModifiedDate(SPDateTimeUtil.getFormattedDate(tarFilterQuery.getLastModifiedAt())); - proxyTarFilter.setLastModifiedBy(HawkbitCommonUtil.getIMUser(tarFilterQuery.getLastModifiedBy())); + proxyTarFilter.setLastModifiedBy(UserDetailsFormatter.loadAndFormatLastModifiedBy(tarFilterQuery)); proxyTarFilter.setQuery(tarFilterQuery.getQuery()); proxyTargetFilter.add(proxyTarFilter); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionAddUpdateWindowLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionAddUpdateWindowLayout.java index 80c1b5700..5d9304191 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionAddUpdateWindowLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionAddUpdateWindowLayout.java @@ -145,11 +145,12 @@ public class DistributionAddUpdateWindowLayout extends VerticalLayout { setSizeUndefined(); addComponents(madatoryLabel, distsetTypeNameComboBox, distNameTextField, distVersionTextField, descTextArea, reqMigStepCheckbox); - + addComponent(buttonsLayout); setComponentAlignment(madatoryLabel, Alignment.MIDDLE_LEFT); - - } + distNameTextField.focus(); + + } /** * Create required UI components. diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionBeanQuery.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionBeanQuery.java index 7b49ddcb2..7909a3850 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionBeanQuery.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionBeanQuery.java @@ -18,6 +18,7 @@ import org.eclipse.hawkbit.repository.DistributionSetFilter.DistributionSetFilte import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.OffsetBasedPageRequest; import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.ui.common.UserDetailsFormatter; import org.eclipse.hawkbit.ui.components.ProxyDistribution; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil; @@ -129,8 +130,8 @@ public class DistributionBeanQuery extends AbstractBeanQuery proxyDistribution.setCreatedDate(SPDateTimeUtil.getFormattedDate(distributionSet.getCreatedAt())); proxyDistribution.setLastModifiedDate(SPDateTimeUtil.getFormattedDate(distributionSet.getLastModifiedAt())); proxyDistribution.setDescription(distributionSet.getDescription()); - proxyDistribution.setCreatedByUser(HawkbitCommonUtil.getIMUser(distributionSet.getCreatedBy())); - proxyDistribution.setModifiedByUser(HawkbitCommonUtil.getIMUser(distributionSet.getLastModifiedBy())); + proxyDistribution.setCreatedByUser(UserDetailsFormatter.loadAndFormatCreatedBy(distributionSet)); + proxyDistribution.setModifiedByUser(UserDetailsFormatter.loadAndFormatLastModifiedBy(distributionSet)); proxyDistribution.setNameVersion( HawkbitCommonUtil.getFormattedNameVersion(distributionSet.getName(), distributionSet.getVersion())); proxyDistributions.add(proxyDistribution); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTable.java index 1b856277e..0df1b0ea5 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTable.java @@ -26,6 +26,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSetTagAssignmentResult; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetIdName; import org.eclipse.hawkbit.ui.common.table.AbstractNamedVersionTable; +import org.eclipse.hawkbit.ui.common.table.AbstractTable; import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.management.event.DistributionTableEvent; @@ -350,17 +351,12 @@ public class DistributionTable extends AbstractNamedVersionTable targetsSelected = getTableValue(source); - final Set targetDetailsList = new HashSet<>(); - - if (!targetsSelected.contains(transferable.getData("itemId"))) { - targetDetailsList.add((TargetIdName) transferable.getData("itemId")); - } else { - targetDetailsList.addAll(targetsSelected); - } + final AbstractTable source = (AbstractTable) transferable + .getSourceComponent(); + final Set targetDetailsList = source.getDeletedEntityByTransferable(transferable); final AbstractSelectTargetDetails dropData = (AbstractSelectTargetDetails) event.getTargetDetails(); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/event/DistributionTagDropEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/event/DistributionTagDropEvent.java index 5b1e09282..2b6acbf68 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/event/DistributionTagDropEvent.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/event/DistributionTagDropEvent.java @@ -8,7 +8,6 @@ */ package org.eclipse.hawkbit.ui.management.event; -import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -17,6 +16,7 @@ import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.SpPermissionChecker; import org.eclipse.hawkbit.repository.model.DistributionSetIdName; import org.eclipse.hawkbit.repository.model.DistributionSetTagAssignmentResult; +import org.eclipse.hawkbit.ui.common.table.AbstractTable; import org.eclipse.hawkbit.ui.management.state.DistributionTableFilters; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.I18N; @@ -68,8 +68,6 @@ public class DistributionTagDropEvent implements DropHandler { @Autowired private ManagementViewAcceptCriteria managementViewAcceptCriteria; - private static final String ITEMID = "itemId"; - @Override public void drop(final DragAndDropEvent event) { if (validate(event) && isNoTagAssigned(event)) { @@ -132,23 +130,20 @@ public class DistributionTagDropEvent implements DropHandler { final com.vaadin.event.dd.TargetDetails targetDetails = event.getTargetDetails(); final TableTransferable transferable = (TableTransferable) event.getTransferable(); - final Table source = transferable.getSourceComponent(); - @SuppressWarnings("unchecked") - final Set distSelected = (Set) source.getValue(); - final Set distributionList = new HashSet<>(); - if (!distSelected.contains(transferable.getData(ITEMID))) { - distributionList.add(((DistributionSetIdName) transferable.getData(ITEMID)).getId()); - } else { - distributionList.addAll(distSelected.stream().map(t -> t.getId()).collect(Collectors.toList())); - } + final AbstractTable source = (AbstractTable) transferable + .getSourceComponent(); + + final Set distSelected = source.getDeletedEntityByTransferable(transferable); + final Set distributionList = distSelected.stream().map(entity -> entity.getId()) + .collect(Collectors.toSet()); final String distTagName = HawkbitCommonUtil.removePrefix(targetDetails.getTarget().getId(), SPUIDefinitions.DISTRIBUTION_TAG_ID_PREFIXS); final List tagsClickedList = distFilterParameters.getDistSetTags(); - final DistributionSetTagAssignmentResult result = distributionSetManagement.toggleTagAssignment(distributionList, - distTagName); + final DistributionSetTagAssignmentResult result = distributionSetManagement + .toggleTagAssignment(distributionList, distTagName); notification.displaySuccess(HawkbitCommonUtil.createAssignmentMessage(distTagName, result, i18n)); if (result.getUnassigned() >= 1 && !tagsClickedList.isEmpty()) { diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/footer/DeleteActionsLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/footer/DeleteActionsLayout.java index 678a5704f..ad537e626 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/footer/DeleteActionsLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/footer/DeleteActionsLayout.java @@ -8,7 +8,6 @@ */ package org.eclipse.hawkbit.ui.management.footer; -import java.util.HashSet; import java.util.Set; import org.eclipse.hawkbit.repository.TagManagement; @@ -258,14 +257,9 @@ public class DeleteActionsLayout extends AbstractDeleteActionsLayout { } private void addInDeleteDistributionList(final Table sourceTable, final TableTransferable transferable) { - final Set distSelected = AbstractTable.getTableValue(sourceTable); - final Set distributionIdNameSet = new HashSet<>(); - - if (!distSelected.contains(transferable.getData(SPUIDefinitions.ITEMID))) { - distributionIdNameSet.add((DistributionSetIdName) transferable.getData(SPUIDefinitions.ITEMID)); - } else { - distributionIdNameSet.addAll(distSelected); - } + @SuppressWarnings("unchecked") + final AbstractTable distTable = (AbstractTable) sourceTable; + final Set distributionIdNameSet = distTable.getDeletedEntityByTransferable(transferable); final DistributionSetIdName dsInBulkUpload = managementUIState.getTargetTableFilters().getBulkUpload() .getDsNameAndVersion(); @@ -273,32 +267,38 @@ public class DeleteActionsLayout extends AbstractDeleteActionsLayout { distributionIdNameSet.remove(dsInBulkUpload); } - if (!distributionIdNameSet.isEmpty()) { - - /* - * Flags to identify whether all dropped distributions are already - * in the deleted list (or) some distributions are already in the - * deleted distribution list. - */ - final int existingDeletedDistributionsSize = managementUIState.getDeletedDistributionList().size(); - managementUIState.getDeletedDistributionList().addAll(distributionIdNameSet); - final int newDeletedDistributionsSize = managementUIState.getDeletedDistributionList().size(); - if (newDeletedDistributionsSize == existingDeletedDistributionsSize) { - /* - * No new distributions are added, all distributions dropped now - * are already available in the delete list. Hence display - * warning message accordingly. - */ - notification.displayValidationError(i18n.get("message.targets.already.deleted")); - } else if (newDeletedDistributionsSize - existingDeletedDistributionsSize != distributionIdNameSet.size()) { - /* - * Not the all distributions dropped now are added to the delete - * list. There are some distributions are already there in the - * delete list. Hence display warning message accordingly. - */ - notification.displayValidationError(i18n.get("message.dist.deleted.pending")); - } + if (distributionIdNameSet.isEmpty()) { + return; } + checkDeletedDistributionSets(distributionIdNameSet); + } + + private void checkDeletedDistributionSets(final Set distributionIdNameSet) { + final int existingDeletedDistributionsSize = managementUIState.getDeletedDistributionList().size(); + managementUIState.getDeletedDistributionList().addAll(distributionIdNameSet); + final int newDeletedDistributionsSize = managementUIState.getDeletedDistributionList().size(); + + showAlreadyDeletedDistributionSetNotfication(existingDeletedDistributionsSize, newDeletedDistributionsSize, + "message.dists.already.deleted"); + showPendingDeletedNotifaction(distributionIdNameSet, existingDeletedDistributionsSize, + newDeletedDistributionsSize, "message.dist.deleted.pending"); + } + + private void showPendingDeletedNotifaction(final Set currentValues, final int existingDeletedSize, + final int newDeletedSize, final String messageKey) { + if (newDeletedSize - existingDeletedSize == currentValues.size()) { + return; + } + notification.displayValidationError(i18n.get(messageKey)); + } + + private void showAlreadyDeletedDistributionSetNotfication(final int existingDeletedSize, final int newDeletedSize, + final String messageKey) { + + if (newDeletedSize != existingDeletedSize) { + return; + } + notification.displayValidationError(i18n.get(messageKey)); } private boolean isDsInUseInBulkUpload(final Set distributionIdNameSet, @@ -312,38 +312,23 @@ public class DeleteActionsLayout extends AbstractDeleteActionsLayout { } private void addInDeleteTargetList(final Table sourceTable, final TableTransferable transferable) { - final Set targetSelected = AbstractTable.getTableValue(sourceTable); + @SuppressWarnings("unchecked") + final AbstractTable targetTable = (AbstractTable) sourceTable; + final Set targetIdNameSet = targetTable.getDeletedEntityByTransferable(transferable); - final Set targetIdNameSet = new HashSet<>(); - if (!targetSelected.contains(transferable.getData(SPUIDefinitions.ITEMID))) { - targetIdNameSet.add((TargetIdName) transferable.getData(SPUIDefinitions.ITEMID)); - } else { - targetIdNameSet.addAll(targetSelected); - } + checkDeletedTargets(targetIdNameSet); + } - /* - * Flags to identify whether all dropped targets are already in the - * deleted list (or) some target are already in the deleted distribution - * list. - */ + private void checkDeletedTargets(final Set targetIdNameSet) { final int existingDeletedTargetsSize = managementUIState.getDeletedTargetList().size(); managementUIState.getDeletedTargetList().addAll(targetIdNameSet); final int newDeletedTargetsSize = managementUIState.getDeletedTargetList().size(); - if (newDeletedTargetsSize == existingDeletedTargetsSize) { - /* - * No new targets are added, all targets dropped now are already - * available in the delete list. Hence display warning message - * accordingly. - */ - notification.displayValidationError(i18n.get("message.targets.already.deleted")); - } else if (newDeletedTargetsSize - existingDeletedTargetsSize != targetIdNameSet.size()) { - /* - * Not the all targets dropped now are added to the delete list. - * There are some targets are already there in the delete list. - * Hence display warning message accordingly. - */ - notification.displayValidationError(i18n.get("message.target.deleted.pending")); - } + + showAlreadyDeletedDistributionSetNotfication(existingDeletedTargetsSize, newDeletedTargetsSize, + "message.targets.already.deleted"); + + showPendingDeletedNotifaction(targetIdNameSet, existingDeletedTargetsSize, newDeletedTargetsSize, + "message.target.deleted.pending"); } private void updateActionCount() { diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/tag/CreateUpdateTagLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/tag/CreateUpdateTagLayout.java index b78db6b4f..6bed7dd4f 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/tag/CreateUpdateTagLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/tag/CreateUpdateTagLayout.java @@ -171,7 +171,7 @@ public abstract class CreateUpdateTagLayout extends CustomComponent implements C tagName = SPUIComponentProvider.getTextField("", ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TAG_NAME, true, "", i18n.get("textfield.name"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH); tagName.setId(SPUIDefinitions.NEW_TARGET_TAG_NAME); - + tagDesc = SPUIComponentProvider.getTextArea("", ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TAG_DESC, false, "", i18n.get("textfield.description"), SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH); @@ -237,7 +237,8 @@ public abstract class CreateUpdateTagLayout extends CustomComponent implements C fieldLayout.addComponent(madatoryLabel); fieldLayout.addComponent(tagName); fieldLayout.addComponent(tagDesc); - + + final HorizontalLayout colorLabelLayout = new HorizontalLayout(); colorLabelLayout.addComponents(colorLabel, tagColorPreviewBtn); fieldLayout.addComponent(colorLabelLayout); @@ -257,8 +258,8 @@ public abstract class CreateUpdateTagLayout extends CustomComponent implements C mainLayout = new HorizontalLayout(); mainLayout.addComponent(fieldButtonLayout); - setCompositionRoot(mainLayout); + tagName.focus(); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetAddUpdateWindowLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetAddUpdateWindowLayout.java index 973d61857..e54911d86 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetAddUpdateWindowLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetAddUpdateWindowLayout.java @@ -152,7 +152,7 @@ public class TargetAddUpdateWindowLayout extends CustomComponent { madatoryLabel.setVisible(Boolean.FALSE); } mainLayout.addComponents(madatoryLabel, controllerIDTextField, nameTextField, descTextArea, buttonsLayout); - + nameTextField.focus(); } private void addListeners() { diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetBeanQuery.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetBeanQuery.java index dac50ab0d..e48004d7a 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetBeanQuery.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetBeanQuery.java @@ -19,6 +19,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; +import org.eclipse.hawkbit.ui.common.UserDetailsFormatter; import org.eclipse.hawkbit.ui.components.ProxyTarget; import org.eclipse.hawkbit.ui.management.state.ManagementUIState; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; @@ -130,20 +131,24 @@ public class TargetBeanQuery extends AbstractBeanQuery { prxyTarget.setLastModifiedDate(SPDateTimeUtil.getFormattedDate(targ.getLastModifiedAt())); prxyTarget.setCreatedDate(SPDateTimeUtil.getFormattedDate(targ.getCreatedAt())); prxyTarget.setCreatedAt(targ.getCreatedAt()); - prxyTarget.setCreatedByUser(HawkbitCommonUtil.getIMUser(targ.getCreatedBy())); - prxyTarget.setModifiedByUser(HawkbitCommonUtil.getIMUser(targ.getLastModifiedBy())); + prxyTarget.setCreatedByUser(UserDetailsFormatter.loadAndFormatCreatedBy(targ)); + prxyTarget.setModifiedByUser(UserDetailsFormatter.loadAndFormatLastModifiedBy(targ)); - if (pinnedDistId == null) { - prxyTarget.setInstalledDistributionSet(null); - prxyTarget.setAssignedDistributionSet(null); - } else { - final Target target = getTargetManagement().findTargetByControllerIDWithDetails(targ.getControllerId()); - final DistributionSet installedDistributionSet = target.getTargetInfo().getInstalledDistributionSet(); - prxyTarget.setInstalledDistributionSet(installedDistributionSet); - final DistributionSet assignedDistributionSet = target.getAssignedDistributionSet(); - prxyTarget.setAssignedDistributionSet(assignedDistributionSet); + final Target target = getTargetManagement().findTargetByControllerIDWithDetails(targ.getControllerId()); + final DistributionSet installedDistributionSet = target.getTargetInfo().getInstalledDistributionSet(); + final DistributionSet assignedDistributionSet = target.getAssignedDistributionSet(); + + prxyTarget.setInstalledDistributionSet(installedDistributionSet); + prxyTarget.setAssignedDistributionSet(assignedDistributionSet); + + if (installedDistributionSet != null) { + prxyTarget.setInstalledDistNameVersion(HawkbitCommonUtil.getFormattedNameVersion( + installedDistributionSet.getName(), installedDistributionSet.getVersion())); + } + if (assignedDistributionSet != null) { + prxyTarget.setAssignedDistNameVersion(HawkbitCommonUtil.getFormattedNameVersion( + assignedDistributionSet.getName(), assignedDistributionSet.getVersion())); } - prxyTarget.setUpdateStatus(targ.getTargetInfo().getUpdateStatus()); prxyTarget.setLastTargetQuery(targ.getTargetInfo().getLastTargetQuery()); prxyTarget.setTargetInfo(targ.getTargetInfo()); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTable.java index e73bf2e4a..6232ebcf8 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTable.java @@ -24,7 +24,9 @@ import org.eclipse.hawkbit.eventbus.event.TargetInfoUpdateEvent; import org.eclipse.hawkbit.repository.OffsetBasedPageRequest; import org.eclipse.hawkbit.repository.SpPermissionChecker; import org.eclipse.hawkbit.repository.TargetManagement; +import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetIdName; +import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.repository.model.TargetIdName; @@ -32,6 +34,7 @@ import org.eclipse.hawkbit.repository.model.TargetInfo; import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.ui.common.ManagmentEntityState; +import org.eclipse.hawkbit.ui.common.UserDetailsFormatter; import org.eclipse.hawkbit.ui.common.table.AbstractTable; import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; import org.eclipse.hawkbit.ui.filter.FilterExpression; @@ -51,6 +54,7 @@ import org.eclipse.hawkbit.ui.management.event.TargetTableEvent; import org.eclipse.hawkbit.ui.management.event.TargetTableEvent.TargetComponentEvent; import org.eclipse.hawkbit.ui.management.state.ManagementUIState; import org.eclipse.hawkbit.ui.management.state.TargetTableFilters; +import org.eclipse.hawkbit.ui.utils.AssignInstalledDSTooltipGenerator; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil; import org.eclipse.hawkbit.ui.utils.SPUIComponetIdProvider; @@ -107,9 +111,9 @@ public class TargetTable extends AbstractTable implements private static final long serialVersionUID = -2300392868806614568L; private static final int PROPERTY_DEPT = 3; - private static final String ITEMID = "itemId"; private static final String ACTION_NOT_ALLOWED_MSG = "message.action.not.allowed"; + @Autowired private transient TargetManagement targetManagement; @@ -137,6 +141,7 @@ public class TargetTable extends AbstractTable implements addActionHandler(this); actionSelectAll = new ShortcutAction(i18n.get("action.target.table.selectall")); actionUnSelectAll = new ShortcutAction(i18n.get("action.target.table.clear")); + setItemDescriptionGenerator(new AssignInstalledDSTooltipGenerator()); } /** @@ -330,6 +335,11 @@ public class TargetTable extends AbstractTable implements if (!isMaximized()) { columnList.add(new TableColumn(SPUIDefinitions.TARGET_STATUS_POLL_TIME, "", 0.0F)); columnList.add(new TableColumn(SPUIDefinitions.TARGET_STATUS_PIN_TOGGLE_ICON, "", 0.0F)); + }else{ + columnList.add(new TableColumn(SPUILabelDefinitions.ASSIGNED_DISTRIBUTION_NAME_VER, + i18n.get("header.assigned.ds"), 0.1F)); + columnList.add(new TableColumn(SPUILabelDefinitions.INSTALLED_DISTRIBUTION_NAME_VER, + i18n.get("header.installed.ds"), 0.1F)); } return columnList; @@ -634,14 +644,9 @@ public class TargetTable extends AbstractTable implements private static Set getDraggedDistributionSet(final TableTransferable transferable, final Table source) { - final Set distSelected = getTableValue(source); - final Set distributionIdSet = new HashSet<>(); - if (!distSelected.contains(transferable.getData(ITEMID))) { - distributionIdSet.add((DistributionSetIdName) transferable.getData(ITEMID)); - } else { - distributionIdSet.addAll(distSelected); - } - return distributionIdSet; + @SuppressWarnings("unchecked") + final AbstractTable distTable = (AbstractTable) source; + return distTable.getDeletedEntityByTransferable(transferable); } private Boolean validateDragAndDropWrapper(final Component compsource) { @@ -745,7 +750,7 @@ public class TargetTable extends AbstractTable implements .setValue(updatedTarget.getTargetInfo().getLastTargetQuery()); item.getItemProperty(SPUILabelDefinitions.VAR_LAST_MODIFIED_BY) - .setValue(HawkbitCommonUtil.getIMUser(updatedTarget.getLastModifiedBy())); + .setValue(UserDetailsFormatter.loadAndFormatLastModifiedBy(updatedTarget)); item.getItemProperty(SPUILabelDefinitions.VAR_LAST_MODIFIED_DATE) .setValue(SPDateTimeUtil.getFormattedDate(updatedTarget.getLastModifiedAt())); item.getItemProperty(SPUILabelDefinitions.VAR_DESC).setValue(updatedTarget.getDescription()); @@ -858,6 +863,7 @@ public class TargetTable extends AbstractTable implements eventBus.publish(this, new TargetTableEvent(TargetComponentEvent.REFRESH_TARGETS)); } + @SuppressWarnings("unchecked") private void updateVisibleItemOnEvent(final TargetInfo targetInfo, final Target target, final TargetIdName targetIdName) { final LazyQueryContainer targetContainer = (LazyQueryContainer) getContainerDataSource(); @@ -880,8 +886,8 @@ public class TargetTable extends AbstractTable implements * @param targetInfoUpdateEvents * list of target info update event */ - @SuppressWarnings("unchecked") private void onTargetInfoUpdateEvents(final List targetInfoUpdateEvents) { + @SuppressWarnings("unchecked") final List visibleItemIds = (List) getVisibleItemIds(); boolean shoulTargetsUpdated = false; Target lastSelectedTarget = null; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTableHeader.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTableHeader.java index cb00c2338..09c9bf499 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTableHeader.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTableHeader.java @@ -8,7 +8,6 @@ */ package org.eclipse.hawkbit.ui.management.targettable; -import java.util.HashSet; import java.util.Set; import org.eclipse.hawkbit.repository.model.DistributionSetIdName; @@ -379,15 +378,9 @@ public class TargetTableHeader extends AbstractTableHeader { } private Set getDropppedDistributionDetails(final TableTransferable transferable) { - final Set distSelected = AbstractTable.getTableValue(transferable.getSourceComponent()); - final Set distributionIdSet = new HashSet<>(); - if (!distSelected.contains(transferable.getData("itemId"))) { - distributionIdSet.add((DistributionSetIdName) transferable.getData("itemId")); - } else { - distributionIdSet.addAll(distSelected); - } - - return distributionIdSet; + @SuppressWarnings("unchecked") + final AbstractTable distTable = (AbstractTable) transferable.getSourceComponent(); + return distTable.getDeletedEntityByTransferable(transferable); } private void addFilterTextField(final DistributionSetIdName distributionSetIdName) { diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettag/TargetTagFilterButtons.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettag/TargetTagFilterButtons.java index c60ab37ca..4e5246703 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettag/TargetTagFilterButtons.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettag/TargetTagFilterButtons.java @@ -8,7 +8,6 @@ */ package org.eclipse.hawkbit.ui.management.targettag; -import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -79,8 +78,6 @@ public class TargetTagFilterButtons extends AbstractFilterButtons { @Autowired private transient TargetManagement targetManagement; - private static final String ITEMID = "itemId"; - TargetTagFilterButtonClick filterButtonClickBehaviour; /** @@ -213,35 +210,46 @@ public class TargetTagFilterButtons extends AbstractFilterButtons { } private void processTargetDrop(final DragAndDropEvent event) { - final com.vaadin.event.dd.TargetDetails targetDetails = event.getTargetDetails(); final TableTransferable transferable = (TableTransferable) event.getTransferable(); - final Table source = transferable.getSourceComponent(); + @SuppressWarnings("unchecked") + final AbstractTable targetTable = (AbstractTable) transferable + .getSourceComponent(); - final Set targetSelected = AbstractTable.getTableValue(source); - final Set targetList = new HashSet<>(); - if (transferable.getData(ITEMID) != null) { - if (!targetSelected.contains(transferable.getData(ITEMID))) { - targetList.add(((TargetIdName) transferable.getData(ITEMID)).getControllerId()); - } else { - targetList.addAll(targetSelected.stream().map(t -> t.getControllerId()).collect(Collectors.toList())); - } + final Set targetSelected = targetTable.getDeletedEntityByTransferable(transferable); + final Set targetList = targetSelected.stream().map(t -> t.getControllerId()) + .collect(Collectors.toSet()); - final String targTagName = HawkbitCommonUtil.removePrefix(targetDetails.getTarget().getId(), - SPUIDefinitions.TARGET_TAG_ID_PREFIXS); + final String targTagName = HawkbitCommonUtil.removePrefix(targetDetails.getTarget().getId(), + SPUIDefinitions.TARGET_TAG_ID_PREFIXS); - final List tagsClickedList = managementUIState.getTargetTableFilters().getClickedTargetTags(); + final TargetTagAssignmentResult result = targetManagement.toggleTagAssignment(targetList, targTagName); + notification.displaySuccess(HawkbitCommonUtil.createAssignmentMessage(targTagName, result, i18n)); - final TargetTagAssignmentResult result = targetManagement.toggleTagAssignment(targetList, targTagName); - notification.displaySuccess(HawkbitCommonUtil.createAssignmentMessage(targTagName, result, i18n)); + publishAssignTargetTagEvent(result); - if (result.getAssigned() >= 1 && managementUIState.getTargetTableFilters().isNoTagSelected()) { - eventBus.publish(this, ManagementUIEvent.ASSIGN_TARGET_TAG); - } - if (result.getUnassigned() >= 1 && !tagsClickedList.isEmpty() && tagsClickedList.contains(targTagName)) { - eventBus.publish(this, ManagementUIEvent.UNASSIGN_TARGET_TAG); - } + publishUnAssignTargetTagEvent(targTagName, result); + + } + + private void publishUnAssignTargetTagEvent(final String targTagName, final TargetTagAssignmentResult result) { + final List tagsClickedList = managementUIState.getTargetTableFilters().getClickedTargetTags(); + final boolean isTargetTagUnAssigned = result.getUnassigned() >= 1 && !tagsClickedList.isEmpty() + && tagsClickedList.contains(targTagName); + + if (!isTargetTagUnAssigned) { + return; } + eventBus.publish(this, ManagementUIEvent.UNASSIGN_TARGET_TAG); + } + + private void publishAssignTargetTagEvent(final TargetTagAssignmentResult result) { + final boolean isNewTargetTagAssigned = result.getAssigned() >= 1 + && managementUIState.getTargetTableFilters().isNoTagSelected(); + if (!isNewTargetTagAssigned) { + return; + } + eventBus.publish(this, ManagementUIEvent.ASSIGN_TARGET_TAG); } private boolean validateIfSourceisTargetTable(final Table source) { @@ -288,6 +296,7 @@ public class TargetTagFilterButtons extends AbstractFilterButtons { } } + @SuppressWarnings("unchecked") private void addNewTargetTag(final TargetTag newTargetTag) { final LazyQueryContainer targetTagContainer = (LazyQueryContainer) getContainerDataSource(); final Object addItem = targetTagContainer.addItem(); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/menu/DashboardMenu.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/menu/DashboardMenu.java index 84da2baf8..5938535ad 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/menu/DashboardMenu.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/menu/DashboardMenu.java @@ -18,23 +18,20 @@ import java.util.List; import java.util.Optional; import java.util.stream.Collectors; +import org.apache.commons.lang3.StringUtils; import org.eclipse.hawkbit.HawkbitServerProperties; import org.eclipse.hawkbit.im.authentication.PermissionService; -import org.eclipse.hawkbit.im.authentication.UserPrincipal; import org.eclipse.hawkbit.ui.UiProperties; +import org.eclipse.hawkbit.ui.common.UserDetailsFormatter; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.menu.DashboardEvent.PostViewChangeEvent; import org.eclipse.hawkbit.ui.utils.I18N; import org.eclipse.hawkbit.ui.utils.SPUIComponetIdProvider; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.core.context.SecurityContext; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.web.context.HttpSessionSecurityContextRepository; import com.vaadin.server.FontAwesome; import com.vaadin.server.Page; import com.vaadin.server.ThemeResource; -import com.vaadin.server.VaadinService; import com.vaadin.shared.ui.label.ContentMode; import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.UIScope; @@ -189,63 +186,27 @@ public final class DashboardMenu extends CustomComponent { return links; } - private UserDetails getCurrentUser() { - final SecurityContext context = (SecurityContext) VaadinService.getCurrentRequest().getWrappedSession() - .getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY); - return (UserDetails) context.getAuthentication().getPrincipal(); - } - private Component buildUserMenu() { final MenuBar settings = new MenuBar(); settings.addStyleName("user-menu"); - final UserDetails user = getCurrentUser(); + settings.setHtmlContentAllowed(true); final MenuItem settingsItem = settings.addItem("", new ThemeResource("images/profile-pic-57px.jpg"), null); - if (user instanceof UserPrincipal - && (((UserPrincipal) user).getFirstname() != null || ((UserPrincipal) user).getLastname() != null)) { - settingsItem.setText(trimTanent(((UserPrincipal) user).getTenant()) + "\n" - + concateFNameLName(((UserPrincipal) user).getFirstname(), ((UserPrincipal) user).getLastname())); - settingsItem.setDescription( - ((UserPrincipal) user).getFirstname() + " / " + ((UserPrincipal) user).getLastname()); - } else if (user instanceof UserPrincipal) { - if (((UserPrincipal) user).getLoginname().length() > 10) { - settingsItem.setText(trimTanent(((UserPrincipal) user).getTenant()) + "\n" - + ((UserPrincipal) user).getLoginname().substring(0, 10) + ".."); - } else { - settingsItem.setText( - trimTanent(((UserPrincipal) user).getTenant()) + "\n" + ((UserPrincipal) user).getLoginname()); - } - settingsItem.setDescription(((UserPrincipal) user).getLoginname()); - } else if (user != null) { - settingsItem.setText(user.getUsername()); - settingsItem.setDescription(user.getUsername()); + + final String formattedTenant = UserDetailsFormatter.formatCurrentTenant(); + final String formattedUsername = UserDetailsFormatter.formatCurrentUsername(); + String tenantAndUsernameHtml = ""; + if (!StringUtils.isEmpty(formattedTenant)) { + tenantAndUsernameHtml += formattedTenant + "
"; } + tenantAndUsernameHtml += formattedUsername; + settingsItem.setText(tenantAndUsernameHtml); + settingsItem.setDescription(formattedUsername); + settingsItem.setStyleName("user-menuitem"); settingsItem.addItem("Sign Out", selectedItem -> Page.getCurrent().setLocation("/UI/logout")); return settings; } - private String concateFNameLName(final String fName, final String lName) { - final StringBuilder userName = new StringBuilder(); - if (fName != null && fName.length() > 6) { - userName.append(fName.substring(0, 6) + ".." + ", "); - } else { - userName.append(fName).append(", "); - } - if (lName != null && lName.length() > 6) { - userName.append(lName.substring(0, 6) + ".."); - } else { - userName.append(lName); - } - return userName.toString(); - } - - private String trimTanent(final String tanent) { - if (tanent != null && tanent.length() > 8) { - return tanent.substring(0, 8) + ".."; - } - return tanent; - } - private Component buildToggleButton() { final Button valoMenuToggleButton = new Button("Menu", (ClickListener) event -> { if (getCompositionRoot().getStyleName().contains(STYLE_VISIBLE)) { diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/AddUpdateRolloutWindowLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/AddUpdateRolloutWindowLayout.java index e5e86c520..7e8d45e1b 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/AddUpdateRolloutWindowLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/AddUpdateRolloutWindowLayout.java @@ -209,6 +209,7 @@ public class AddUpdateRolloutWindowLayout extends CustomComponent { actionTypeOptionGroupLayout, linkToHelp, getSaveDiscardButtonLayout()); mainLayout.setComponentAlignment(linkToHelp, Alignment.BOTTOM_RIGHT); setCompositionRoot(mainLayout); + rolloutName.focus(); } private HorizontalLayout getGroupDetailsLayout() { diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/DistributionBeanQuery.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/DistributionBeanQuery.java index 74daf89d8..75d2741af 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/DistributionBeanQuery.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/DistributionBeanQuery.java @@ -18,6 +18,7 @@ import org.eclipse.hawkbit.repository.DistributionSetFilter; import org.eclipse.hawkbit.repository.DistributionSetFilter.DistributionSetFilterBuilder; import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.ui.common.UserDetailsFormatter; import org.eclipse.hawkbit.ui.components.ProxyDistribution; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil; @@ -62,7 +63,8 @@ public class DistributionBeanQuery extends AbstractBeanQuery 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])); + sort.and(new Sort(sortStates[distId] ? Direction.ASC : Direction.DESC, + (String) sortPropertyIds[distId])); } } } @@ -103,8 +105,8 @@ public class DistributionBeanQuery extends AbstractBeanQuery final List proxyDistributions = new ArrayList<>(); for (final DistributionSet distributionSet : distBeans) { final ProxyDistribution proxyDistribution = new ProxyDistribution(); - proxyDistribution.setName(HawkbitCommonUtil.getFormattedNameVersion(distributionSet.getName(), - distributionSet.getVersion())); + proxyDistribution.setName( + HawkbitCommonUtil.getFormattedNameVersion(distributionSet.getName(), distributionSet.getVersion())); proxyDistribution.setDescription(distributionSet.getDescription()); proxyDistribution.setDistId(distributionSet.getId()); proxyDistribution.setId(distributionSet.getId()); @@ -112,8 +114,8 @@ public class DistributionBeanQuery extends AbstractBeanQuery proxyDistribution.setCreatedDate(SPDateTimeUtil.getFormattedDate(distributionSet.getCreatedAt())); proxyDistribution.setLastModifiedDate(SPDateTimeUtil.getFormattedDate(distributionSet.getLastModifiedAt())); proxyDistribution.setDescription(distributionSet.getDescription()); - proxyDistribution.setCreatedByUser(HawkbitCommonUtil.getIMUser(distributionSet.getCreatedBy())); - proxyDistribution.setModifiedByUser(HawkbitCommonUtil.getIMUser(distributionSet.getLastModifiedBy())); + proxyDistribution.setCreatedByUser(UserDetailsFormatter.loadAndFormatCreatedBy(distributionSet)); + proxyDistribution.setModifiedByUser(UserDetailsFormatter.loadAndFormatLastModifiedBy(distributionSet)); proxyDistribution.setIsComplete(distributionSet.isComplete()); proxyDistributions.add(proxyDistribution); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/ProxyRollout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/ProxyRollout.java index b1309f8b9..04c6659a5 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/ProxyRollout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/ProxyRollout.java @@ -8,12 +8,16 @@ */ package org.eclipse.hawkbit.ui.rollout.rollout; +import java.util.Set; + import org.eclipse.hawkbit.repository.model.Rollout; +import org.eclipse.hawkbit.repository.model.SoftwareModule; +import org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRendererData; import com.vaadin.server.FontAwesome; /** - * Proxy rollout with suctome properties. + * Proxy rollout with custom properties. * */ public class ProxyRollout extends Rollout { @@ -30,8 +34,92 @@ public class ProxyRollout extends Rollout { private Boolean isActionRecieved = Boolean.FALSE; + private Boolean isRequiredMigrationStep = Boolean.FALSE; + private String totalTargetsCount; - + + private RolloutRendererData rolloutRendererData; + + private String discription; + + private String type; + + private Set swModules; + + /** + * @return the isRequiredMigrationStep + */ + + public Boolean getIsRequiredMigrationStep() { + return isRequiredMigrationStep; + } + + /** + * @param isRequiredMigrationStep + * the isRequiredMigrationStep to set + */ + + public void setIsRequiredMigrationStep(Boolean isRequiredMigrationStep) { + this.isRequiredMigrationStep = isRequiredMigrationStep; + } + + /** + * @return the discription + */ + + public String getDiscription() { + return discription; + } + + /** + * @param discription + * the discription to set + */ + + public void setDiscription(String discription) { + this.discription = discription; + } + + /** + * @return the type + */ + public String getType() { + return type; + } + + /** + * @param type + * the type to set + */ + + public void setType(String type) { + this.type = type; + } + + /** + * + * @return the Set of Software modules + */ + public Set getSwModules() { + return swModules; + } + + /** + * @param swModules + * Set to set + */ + public void setSwModules(Set swModules) { + this.swModules = swModules; + } + + public RolloutRendererData getRolloutRendererData() { + return rolloutRendererData; + } + + public void setRolloutRendererData(RolloutRendererData rendererData) { + this.rolloutRendererData = rendererData; + } + /** * @return the distributionSetNameVersion */ @@ -121,10 +209,9 @@ public class ProxyRollout extends Rollout { public void setTotalTargetsCount(final String totalTargetsCount) { this.totalTargetsCount = totalTargetsCount; } - - - public String getAction() { + + public String getAction() { return FontAwesome.CIRCLE_O.getHtml(); } - + } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutBeanQuery.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutBeanQuery.java index 5ab6f6a97..8a9675564 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutBeanQuery.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutBeanQuery.java @@ -17,6 +17,8 @@ import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus; +import org.eclipse.hawkbit.ui.common.UserDetailsFormatter; +import org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRendererData; import org.eclipse.hawkbit.ui.rollout.state.RolloutUIState; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil; @@ -119,22 +121,29 @@ public class RolloutBeanQuery extends AbstractBeanQuery { proxyRollout.setName(rollout.getName()); proxyRollout.setDescription(rollout.getDescription()); final DistributionSet distributionSet = rollout.getDistributionSet(); - proxyRollout.setDistributionSetNameVersion(HawkbitCommonUtil.getFormattedNameVersion( - distributionSet.getName(), distributionSet.getVersion())); + proxyRollout.setDistributionSetNameVersion( + HawkbitCommonUtil.getFormattedNameVersion(distributionSet.getName(), distributionSet.getVersion())); proxyRollout.setDistributionSet(distributionSet); proxyRollout.setNumberOfGroups(Long.valueOf(rollout.getRolloutGroups().size())); proxyRollout.setCreatedDate(SPDateTimeUtil.getFormattedDate(rollout.getCreatedAt())); proxyRollout.setModifiedDate(SPDateTimeUtil.getFormattedDate(rollout.getLastModifiedAt())); - proxyRollout.setCreatedBy(HawkbitCommonUtil.getIMUser(rollout.getCreatedBy())); - proxyRollout.setLastModifiedBy(HawkbitCommonUtil.getIMUser(rollout.getLastModifiedBy())); + proxyRollout.setCreatedBy(UserDetailsFormatter.loadAndFormatCreatedBy(rollout)); + proxyRollout.setLastModifiedBy(UserDetailsFormatter.loadAndFormatLastModifiedBy(rollout)); proxyRollout.setForcedTime(rollout.getForcedTime()); proxyRollout.setId(rollout.getId()); proxyRollout.setStatus(rollout.getStatus()); + proxyRollout + .setRolloutRendererData(new RolloutRendererData(rollout.getName(), rollout.getStatus().toString())); final TotalTargetCountStatus totalTargetCountActionStatus = rollout.getTotalTargetCountStatus(); proxyRollout.setTotalTargetCountStatus(totalTargetCountActionStatus); proxyRollout.setTotalTargetsCount(String.valueOf(rollout.getTotalTargets())); - + + proxyRollout.setDescription(distributionSet.getDescription()); + proxyRollout.setType(distributionSet.getType().getName()); + proxyRollout.setIsRequiredMigrationStep(distributionSet.isRequiredMigrationStep()); + proxyRollout.setSwModules(distributionSet.getModules()); + proxyRolloutList.add(proxyRollout); } return proxyRolloutList; @@ -148,7 +157,8 @@ public class RolloutBeanQuery extends AbstractBeanQuery { * .util.List, java.util.List, java.util.List) */ @Override - protected void saveBeans(final List arg0, final List arg1, final List arg2) { + protected void saveBeans(final List arg0, final List arg1, + final List arg2) { /** * CRUD operations on Target will be done through repository methods */ diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutListGrid.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutListGrid.java index 9c3e1992b..7f3877a9a 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutListGrid.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutListGrid.java @@ -8,23 +8,31 @@ */ package org.eclipse.hawkbit.ui.rollout.rollout; +import static org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil.HTML_LI_CLOSE_TAG; +import static org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil.HTML_LI_OPEN_TAG; +import static org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil.HTML_UL_CLOSE_TAG; +import static org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil.HTML_UL_OPEN_TAG; + import java.util.ArrayList; import java.util.Arrays; import java.util.EnumMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; import org.eclipse.hawkbit.eventbus.event.RolloutChangeEvent; import org.eclipse.hawkbit.repository.RolloutManagement; import org.eclipse.hawkbit.repository.SpPermissionChecker; import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus; +import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus; import org.eclipse.hawkbit.ui.common.grid.AbstractGrid; +import org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRendererData; import org.eclipse.hawkbit.ui.customrenderers.renderers.HtmlButtonRenderer; import org.eclipse.hawkbit.ui.customrenderers.renderers.HtmlLabelRenderer; -import org.eclipse.hawkbit.ui.customrenderers.renderers.LinkRenderer; +import org.eclipse.hawkbit.ui.customrenderers.renderers.RolloutRenderer; import org.eclipse.hawkbit.ui.rollout.DistributionBarHelper; import org.eclipse.hawkbit.ui.rollout.StatusFontIcon; import org.eclipse.hawkbit.ui.rollout.event.RolloutEvent; @@ -77,6 +85,13 @@ public class RolloutListGrid extends AbstractGrid { private static final String START_OPTION = "Start"; + private static final String DS_TYPE = "type"; + + private static final String SW_MODULES = "swModules"; + + private static final String IS_REQUIRED_MIGRATION_STEP = "isRequiredMigrationStep"; + + private static final String ROLLOUT_RENDERER_DATA = "rolloutRendererData"; @Autowired private transient RolloutManagement rolloutManagement; @@ -95,7 +110,10 @@ public class RolloutListGrid extends AbstractGrid { private transient Map statusIconMap = new EnumMap<>(RolloutStatus.class); - + /** + * Handles the RolloutEvent to refresh Grid. + * + */ @EventBusListenerMethod(scope = EventScope.SESSION) void onEvent(final RolloutEvent event) { switch (event) { @@ -132,10 +150,16 @@ public class RolloutListGrid extends AbstractGrid { item.getItemProperty(SPUILabelDefinitions.VAR_STATUS).setValue(rollout.getStatus()); item.getItemProperty(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS).setValue(totalTargetCountStatus); final Long groupCount = (Long) item.getItemProperty(SPUILabelDefinitions.VAR_NUMBER_OF_GROUPS).getValue(); - if (rollout.getRolloutGroups() != null && groupCount != rollout.getRolloutGroups().size()) { + final int groupsCreated = rollout.getRolloutGroupsCreated(); + if (groupsCreated != 0) { + item.getItemProperty(SPUILabelDefinitions.VAR_NUMBER_OF_GROUPS).setValue(Long.valueOf(groupsCreated)); + } else if (rollout.getRolloutGroups() != null && groupCount != rollout.getRolloutGroups().size()) { item.getItemProperty(SPUILabelDefinitions.VAR_NUMBER_OF_GROUPS) .setValue(Long.valueOf(rollout.getRolloutGroups().size())); } + item.getItemProperty(ROLLOUT_RENDERER_DATA) + .setValue(new RolloutRendererData(rollout.getName(), rollout.getStatus().toString())); + } @Override @@ -149,7 +173,11 @@ public class RolloutListGrid extends AbstractGrid { protected void addContainerProperties() { final LazyQueryContainer rolloutGridContainer = (LazyQueryContainer) getContainerDataSource(); rolloutGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_NAME, String.class, "", false, false); + rolloutGridContainer.addContainerProperty(DS_TYPE, String.class, null, false, false); + rolloutGridContainer.addContainerProperty(SW_MODULES, Set.class, null, false, false); + rolloutGridContainer.addContainerProperty(ROLLOUT_RENDERER_DATA, RolloutRendererData.class, null, false, false); rolloutGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_DESC, String.class, null, false, false); + rolloutGridContainer.addContainerProperty(IS_REQUIRED_MIGRATION_STEP, boolean.class, null, false, false); rolloutGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_STATUS, RolloutStatus.class, null, false, false); rolloutGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_DIST_NAME_VERSION, String.class, null, false, @@ -163,7 +191,7 @@ public class RolloutListGrid extends AbstractGrid { false); rolloutGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_MODIFIED_BY, String.class, null, false, false); - rolloutGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_NUMBER_OF_GROUPS, Integer.class, 0, false, + rolloutGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_NUMBER_OF_GROUPS, Long.class, 0, false, false); rolloutGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_TOTAL_TARGETS, String.class, "0", false, false); @@ -177,8 +205,9 @@ public class RolloutListGrid extends AbstractGrid { @Override protected void setColumnExpandRatio() { - getColumn(SPUILabelDefinitions.VAR_NAME).setMinimumWidth(40); - getColumn(SPUILabelDefinitions.VAR_NAME).setMaximumWidth(150); + + getColumn(ROLLOUT_RENDERER_DATA).setMinimumWidth(40); + getColumn(ROLLOUT_RENDERER_DATA).setMaximumWidth(150); getColumn(SPUILabelDefinitions.VAR_DIST_NAME_VERSION).setMinimumWidth(40); getColumn(SPUILabelDefinitions.VAR_DIST_NAME_VERSION).setMaximumWidth(150); @@ -202,7 +231,10 @@ public class RolloutListGrid extends AbstractGrid { @Override protected void setColumnHeaderNames() { - getColumn(SPUILabelDefinitions.VAR_NAME).setHeaderCaption(i18n.get("header.name")); + getColumn(ROLLOUT_RENDERER_DATA).setHeaderCaption(i18n.get("header.name")); + getColumn(DS_TYPE).setHeaderCaption("Type"); + getColumn(SW_MODULES).setHeaderCaption("swModules"); + getColumn(IS_REQUIRED_MIGRATION_STEP).setHeaderCaption("IsRequiredMigrationStep"); getColumn(SPUILabelDefinitions.VAR_DIST_NAME_VERSION).setHeaderCaption(i18n.get("header.distributionset")); getColumn(SPUILabelDefinitions.VAR_NUMBER_OF_GROUPS).setHeaderCaption(i18n.get("header.numberofgroups")); getColumn(SPUILabelDefinitions.VAR_TOTAL_TARGETS).setHeaderCaption(i18n.get("header.total.targets")); @@ -225,8 +257,11 @@ public class RolloutListGrid extends AbstractGrid { @Override protected void setColumnProperties() { final List columnList = new ArrayList<>(); - columnList.add(SPUILabelDefinitions.VAR_NAME); + columnList.add(ROLLOUT_RENDERER_DATA); columnList.add(SPUILabelDefinitions.VAR_DIST_NAME_VERSION); + columnList.add(DS_TYPE); + columnList.add(SW_MODULES); + columnList.add(IS_REQUIRED_MIGRATION_STEP); columnList.add(SPUILabelDefinitions.VAR_STATUS); columnList.add(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS); columnList.add(SPUILabelDefinitions.VAR_NUMBER_OF_GROUPS); @@ -245,11 +280,15 @@ public class RolloutListGrid extends AbstractGrid { @Override protected void setHiddenColumns() { final List columnsToBeHidden = new ArrayList<>(); + columnsToBeHidden.add(SPUILabelDefinitions.VAR_NAME); columnsToBeHidden.add(SPUILabelDefinitions.VAR_CREATED_DATE); columnsToBeHidden.add(SPUILabelDefinitions.VAR_CREATED_USER); columnsToBeHidden.add(SPUILabelDefinitions.VAR_MODIFIED_DATE); columnsToBeHidden.add(SPUILabelDefinitions.VAR_MODIFIED_BY); columnsToBeHidden.add(SPUILabelDefinitions.VAR_DESC); + columnsToBeHidden.add(IS_REQUIRED_MIGRATION_STEP); + columnsToBeHidden.add(DS_TYPE); + columnsToBeHidden.add(SW_MODULES); for (final Object propertyId : columnsToBeHidden) { getColumn(propertyId).setHidden(true); } @@ -263,6 +302,8 @@ public class RolloutListGrid extends AbstractGrid { @Override protected void addColumnRenderes() { + getColumn(SPUILabelDefinitions.VAR_NUMBER_OF_GROUPS).setRenderer(new HtmlRenderer(), + new TotalTargetGroupsConverter()); getColumn(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS).setRenderer(new HtmlRenderer(), new TotalTargetCountStatusConverter()); @@ -270,7 +311,11 @@ public class RolloutListGrid extends AbstractGrid { getColumn(SPUILabelDefinitions.VAR_STATUS).setRenderer(new HtmlLabelRenderer(), new RolloutStatusConverter()); getColumn(SPUILabelDefinitions.ACTION).setRenderer(new HtmlButtonRenderer(event -> onClickOfActionBtn(event))); - getColumn(SPUILabelDefinitions.VAR_NAME).setRenderer(new LinkRenderer(event -> onClickOfRolloutName(event))); + + final RolloutRenderer customObjectRenderer = new RolloutRenderer(RolloutRendererData.class); + customObjectRenderer.addClickListener(event -> onClickOfRolloutName(event)); + getColumn(ROLLOUT_RENDERER_DATA).setRenderer(customObjectRenderer); + } private void createRolloutStatusToFontMap() { @@ -403,6 +448,9 @@ public class RolloutListGrid extends AbstractGrid { ((LazyQueryContainer) getContainerDataSource()).refresh(); } + /** + * Generator to generate fontIcon by String. + */ public final class FontIconGenerator extends PropertyValueGenerator { private static final long serialVersionUID = 2544026030795375748L; @@ -428,15 +476,54 @@ public class RolloutListGrid extends AbstractGrid { return cell.getProperty().getValue().toString().toLowerCase(); } else if (SPUILabelDefinitions.ACTION.equals(cell.getPropertyId())) { return SPUILabelDefinitions.ACTION.toLowerCase(); - } else if (SPUILabelDefinitions.VAR_NAME.equals(cell.getPropertyId())) { - return cell.getProperty().getValue().toString(); + } else if (ROLLOUT_RENDERER_DATA.equals(cell.getPropertyId())) { + return ((RolloutRendererData) cell.getProperty().getValue()).getName(); } else if (SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS.equals(cell.getPropertyId())) { return DistributionBarHelper .getTooltip(((TotalTargetCountStatus) cell.getValue()).getStatusTotalCountMap()); + } else if (SPUILabelDefinitions.VAR_DIST_NAME_VERSION.equals(cell.getPropertyId())) { + return getDSDetails(cell.getItem()); } return null; } + private String getDSDetails(final Item rolloutItem) { + final StringBuilder swModuleNames = new StringBuilder(); + final StringBuilder swModuleVendors = new StringBuilder(); + final Set swModules = (Set) rolloutItem.getItemProperty(SW_MODULES).getValue(); + swModules.forEach(swModule -> { + swModuleNames.append(swModule.getName()); + swModuleNames.append(" , "); + swModuleVendors.append(swModule.getVendor()); + swModuleVendors.append(" , "); + }); + final StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(HTML_UL_OPEN_TAG); + stringBuilder.append(HTML_LI_OPEN_TAG); + stringBuilder.append(" DistributionSet Description : ") + .append((String) rolloutItem.getItemProperty(SPUILabelDefinitions.VAR_DESC).getValue()); + stringBuilder.append(HTML_LI_CLOSE_TAG); + stringBuilder.append(HTML_LI_OPEN_TAG); + stringBuilder.append(" DistributionSet Type : ") + .append((String) rolloutItem.getItemProperty(DS_TYPE).getValue()); + stringBuilder.append(HTML_LI_CLOSE_TAG); + stringBuilder.append(HTML_LI_OPEN_TAG); + stringBuilder.append("Required Migration step : ") + .append((boolean) rolloutItem.getItemProperty(IS_REQUIRED_MIGRATION_STEP).getValue() ? "Yes" : "No"); + stringBuilder.append(HTML_LI_CLOSE_TAG); + + stringBuilder.append(HTML_LI_OPEN_TAG); + stringBuilder.append("SoftWare Modules : ").append(swModuleNames.toString()); + stringBuilder.append(HTML_LI_CLOSE_TAG); + + stringBuilder.append(HTML_LI_OPEN_TAG); + stringBuilder.append("Vendor(s) : ").append(swModuleVendors.toString()); + stringBuilder.append(HTML_LI_CLOSE_TAG); + + stringBuilder.append(HTML_UL_CLOSE_TAG); + return stringBuilder.toString(); + } + enum ACTION { PAUSE, RESUME, START, UPDATE } @@ -568,4 +655,39 @@ public class RolloutListGrid extends AbstractGrid { } } + /** + * Converter to convert 0 to empty, if total target groups is zero. + * + */ + class TotalTargetGroupsConverter implements Converter { + + private static final long serialVersionUID = 6589305227035220369L; + + @Override + public Long convertToModel(final String value, final Class targetType, final Locale locale) + throws com.vaadin.data.util.converter.Converter.ConversionException { + return null; + } + + @Override + public String convertToPresentation(final Long value, final Class targetType, + final Locale locale) throws com.vaadin.data.util.converter.Converter.ConversionException { + if (value == 0) { + return ""; + } + return value.toString(); + } + + @Override + public Class getModelType() { + return Long.class; + } + + @Override + public Class getPresentationType() { + return String.class; + } + + } + } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgroup/ProxyRolloutGroup.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgroup/ProxyRolloutGroup.java index bb802c123..08f2c0a0b 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgroup/ProxyRolloutGroup.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgroup/ProxyRolloutGroup.java @@ -9,200 +9,211 @@ package org.eclipse.hawkbit.ui.rollout.rolloutgroup; import org.eclipse.hawkbit.repository.model.RolloutGroup; +import org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRendererData; /** - * Proxy rollout group with suctome properties. + * Proxy rollout group with renderer properties. * */ public class ProxyRolloutGroup extends RolloutGroup { - private static final long serialVersionUID = -2745056813306692356L; + private static final long serialVersionUID = -2745056813306692356L; - private String createdDate; + private String createdDate; - private String modifiedDate; + private String modifiedDate; - private String finishedPercentage; + private String finishedPercentage; - private Long runningTargetsCount; + private Long runningTargetsCount; - private Long scheduledTargetsCount; + private Long scheduledTargetsCount; - private Long cancelledTargetsCount; + private Long cancelledTargetsCount; - private Long errorTargetsCount; + private Long errorTargetsCount; - private Long finishedTargetsCount; + private Long finishedTargetsCount; - private Long notStartedTargetsCount; + private Long notStartedTargetsCount; - private Boolean isActionRecieved = Boolean.FALSE; + private Boolean isActionRecieved = Boolean.FALSE; - private String totalTargetsCount; + private String totalTargetsCount; - /** - * @return the createdDate - */ - public String getCreatedDate() { - return createdDate; - } + private RolloutRendererData rolloutRendererData; - /** - * @param createdDate - * the createdDate to set - */ - public void setCreatedDate(final String createdDate) { - this.createdDate = createdDate; - } + public RolloutRendererData getRolloutRendererData() { + return rolloutRendererData; + } - /** - * @return the modifiedDate - */ - public String getModifiedDate() { - return modifiedDate; - } + public void setRolloutRendererData(RolloutRendererData rendererData) { + this.rolloutRendererData = rendererData; + } - /** - * @param modifiedDate - * the modifiedDate to set - */ - public void setModifiedDate(final String modifiedDate) { - this.modifiedDate = modifiedDate; - } + /** + * @return the createdDate + */ + public String getCreatedDate() { + return createdDate; + } - /** - * @return the finishedPercentage - */ - public String getFinishedPercentage() { - return finishedPercentage; - } + /** + * @param createdDate + * the createdDate to set + */ + public void setCreatedDate(final String createdDate) { + this.createdDate = createdDate; + } - /** - * @param finishedPercentage - * the finishedPercentage to set - */ - public void setFinishedPercentage(final String finishedPercentage) { - this.finishedPercentage = finishedPercentage; - } + /** + * @return the modifiedDate + */ + public String getModifiedDate() { + return modifiedDate; + } - /** - * @return the runningTargetsCount - */ - public Long getRunningTargetsCount() { - return runningTargetsCount; - } + /** + * @param modifiedDate + * the modifiedDate to set + */ + public void setModifiedDate(final String modifiedDate) { + this.modifiedDate = modifiedDate; + } - /** - * @param runningTargetsCount - * the runningTargetsCount to set - */ - public void setRunningTargetsCount(final Long runningTargetsCount) { - this.runningTargetsCount = runningTargetsCount; - } + /** + * @return the finishedPercentage + */ + public String getFinishedPercentage() { + return finishedPercentage; + } - /** - * @return the scheduledTargetsCount - */ - public Long getScheduledTargetsCount() { - return scheduledTargetsCount; - } + /** + * @param finishedPercentage + * the finishedPercentage to set + */ + public void setFinishedPercentage(final String finishedPercentage) { + this.finishedPercentage = finishedPercentage; + } - /** - * @param scheduledTargetsCount - * the scheduledTargetsCount to set - */ - public void setScheduledTargetsCount(final Long scheduledTargetsCount) { - this.scheduledTargetsCount = scheduledTargetsCount; - } + /** + * @return the runningTargetsCount + */ + public Long getRunningTargetsCount() { + return runningTargetsCount; + } - /** - * @return the cancelledTargetsCount - */ - public Long getCancelledTargetsCount() { - return cancelledTargetsCount; - } + /** + * @param runningTargetsCount + * the runningTargetsCount to set + */ + public void setRunningTargetsCount(final Long runningTargetsCount) { + this.runningTargetsCount = runningTargetsCount; + } - /** - * @param cancelledTargetsCount - * the cancelledTargetsCount to set - */ - public void setCancelledTargetsCount(final Long cancelledTargetsCount) { - this.cancelledTargetsCount = cancelledTargetsCount; - } + /** + * @return the scheduledTargetsCount + */ + public Long getScheduledTargetsCount() { + return scheduledTargetsCount; + } - /** - * @return the errorTargetsCount - */ - public Long getErrorTargetsCount() { - return errorTargetsCount; - } + /** + * @param scheduledTargetsCount + * the scheduledTargetsCount to set + */ + public void setScheduledTargetsCount(final Long scheduledTargetsCount) { + this.scheduledTargetsCount = scheduledTargetsCount; + } - /** - * @param errorTargetsCount - * the errorTargetsCount to set - */ - public void setErrorTargetsCount(final Long errorTargetsCount) { - this.errorTargetsCount = errorTargetsCount; - } + /** + * @return the cancelledTargetsCount + */ + public Long getCancelledTargetsCount() { + return cancelledTargetsCount; + } - /** - * @return the finishedTargetsCount - */ - public Long getFinishedTargetsCount() { - return finishedTargetsCount; - } + /** + * @param cancelledTargetsCount + * the cancelledTargetsCount to set + */ + public void setCancelledTargetsCount(final Long cancelledTargetsCount) { + this.cancelledTargetsCount = cancelledTargetsCount; + } - /** - * @param finishedTargetsCount - * the finishedTargetsCount to set - */ - public void setFinishedTargetsCount(final Long finishedTargetsCount) { - this.finishedTargetsCount = finishedTargetsCount; - } + /** + * @return the errorTargetsCount + */ + public Long getErrorTargetsCount() { + return errorTargetsCount; + } - /** - * @return the notStartedTargetsCount - */ - public Long getNotStartedTargetsCount() { - return notStartedTargetsCount; - } + /** + * @param errorTargetsCount + * the errorTargetsCount to set + */ + public void setErrorTargetsCount(final Long errorTargetsCount) { + this.errorTargetsCount = errorTargetsCount; + } - /** - * @param notStartedTargetsCount - * the notStartedTargetsCount to set - */ - public void setNotStartedTargetsCount(final Long notStartedTargetsCount) { - this.notStartedTargetsCount = notStartedTargetsCount; - } + /** + * @return the finishedTargetsCount + */ + public Long getFinishedTargetsCount() { + return finishedTargetsCount; + } - /** - * @return the isActionRecieved - */ - public Boolean getIsActionRecieved() { - return isActionRecieved; - } + /** + * @param finishedTargetsCount + * the finishedTargetsCount to set + */ + public void setFinishedTargetsCount(final Long finishedTargetsCount) { + this.finishedTargetsCount = finishedTargetsCount; + } - /** - * @param isActionRecieved - * the isActionRecieved to set - */ - public void setIsActionRecieved(final Boolean isActionRecieved) { - this.isActionRecieved = isActionRecieved; - } + /** + * @return the notStartedTargetsCount + */ + public Long getNotStartedTargetsCount() { + return notStartedTargetsCount; + } - /** - * @return the totalTargetsCount - */ - public String getTotalTargetsCount() { - return totalTargetsCount; - } + /** + * @param notStartedTargetsCount + * the notStartedTargetsCount to set + */ + public void setNotStartedTargetsCount(final Long notStartedTargetsCount) { + this.notStartedTargetsCount = notStartedTargetsCount; + } - /** - * @param totalTargetsCount - * the totalTargetsCount to set - */ - public void setTotalTargetsCount(final String totalTargetsCount) { - this.totalTargetsCount = totalTargetsCount; - } + /** + * @return the isActionRecieved + */ + public Boolean getIsActionRecieved() { + return isActionRecieved; + } + + /** + * @param isActionRecieved + * the isActionRecieved to set + */ + public void setIsActionRecieved(final Boolean isActionRecieved) { + this.isActionRecieved = isActionRecieved; + } + + /** + * @return the totalTargetsCount + */ + public String getTotalTargetsCount() { + return totalTargetsCount; + } + + /** + * @param totalTargetsCount + * the totalTargetsCount to set + */ + public void setTotalTargetsCount(final String totalTargetsCount) { + this.totalTargetsCount = totalTargetsCount; + } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgroup/RolloutGroupBeanQuery.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgroup/RolloutGroupBeanQuery.java index 0dabb18fc..5a37d1341 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgroup/RolloutGroupBeanQuery.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgroup/RolloutGroupBeanQuery.java @@ -15,6 +15,8 @@ import java.util.Map; import org.eclipse.hawkbit.repository.RolloutGroupManagement; import org.eclipse.hawkbit.repository.RolloutManagement; import org.eclipse.hawkbit.repository.model.RolloutGroup; +import org.eclipse.hawkbit.ui.common.UserDetailsFormatter; +import org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRendererData; import org.eclipse.hawkbit.ui.rollout.state.RolloutUIState; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil; @@ -110,8 +112,8 @@ public class RolloutGroupBeanQuery extends AbstractBeanQuery proxyRolloutGroup.setDescription(rolloutGroup.getDescription()); proxyRolloutGroup.setCreatedDate(SPDateTimeUtil.getFormattedDate(rolloutGroup.getCreatedAt())); proxyRolloutGroup.setModifiedDate(SPDateTimeUtil.getFormattedDate(rolloutGroup.getLastModifiedAt())); - proxyRolloutGroup.setCreatedBy(HawkbitCommonUtil.getIMUser(rolloutGroup.getCreatedBy())); - proxyRolloutGroup.setLastModifiedBy(HawkbitCommonUtil.getIMUser(rolloutGroup.getLastModifiedBy())); + proxyRolloutGroup.setCreatedBy(UserDetailsFormatter.loadAndFormatCreatedBy(rolloutGroup)); + proxyRolloutGroup.setLastModifiedBy(UserDetailsFormatter.loadAndFormatLastModifiedBy(rolloutGroup)); proxyRolloutGroup.setId(rolloutGroup.getId()); proxyRolloutGroup.setStatus(rolloutGroup.getStatus()); proxyRolloutGroup.setErrorAction(rolloutGroup.getErrorAction()); @@ -122,6 +124,8 @@ public class RolloutGroupBeanQuery extends AbstractBeanQuery proxyRolloutGroup.setSuccessConditionExp(rolloutGroup.getSuccessConditionExp()); proxyRolloutGroup.setFinishedPercentage(calculateFinishedPercentage(rolloutGroup)); + proxyRolloutGroup.setRolloutRendererData(new RolloutRendererData(rolloutGroup.getName(), null)); + proxyRolloutGroup.setTotalTargetsCount(String.valueOf(rolloutGroup.getTotalTargets())); proxyRolloutGroup.setTotalTargetCountStatus(rolloutGroup.getTotalTargetCountStatus()); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgroup/RolloutGroupListGrid.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgroup/RolloutGroupListGrid.java index 4ae74c545..f09b02cfc 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgroup/RolloutGroupListGrid.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgroup/RolloutGroupListGrid.java @@ -17,13 +17,15 @@ import java.util.Map; import org.eclipse.hawkbit.eventbus.event.RolloutGroupChangeEvent; import org.eclipse.hawkbit.repository.RolloutGroupManagement; +import org.eclipse.hawkbit.repository.RolloutManagement; import org.eclipse.hawkbit.repository.SpPermissionChecker; import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupStatus; import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus; import org.eclipse.hawkbit.ui.common.grid.AbstractGrid; +import org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRendererData; import org.eclipse.hawkbit.ui.customrenderers.renderers.HtmlLabelRenderer; -import org.eclipse.hawkbit.ui.customrenderers.renderers.LinkRenderer; +import org.eclipse.hawkbit.ui.customrenderers.renderers.RolloutRenderer; import org.eclipse.hawkbit.ui.rollout.DistributionBarHelper; import org.eclipse.hawkbit.ui.rollout.StatusFontIcon; import org.eclipse.hawkbit.ui.rollout.event.RolloutEvent; @@ -59,9 +61,14 @@ import com.vaadin.ui.renderers.HtmlRenderer; public class RolloutGroupListGrid extends AbstractGrid { private static final long serialVersionUID = 4060904914954370524L; + private static final String ROLLOUT_RENDERER_DATA = "rolloutRendererData"; + @Autowired private transient RolloutGroupManagement rolloutGroupManagement; + @Autowired + private transient RolloutManagement rolloutManagement; + @Autowired private transient RolloutUIState rolloutUIState; @@ -103,6 +110,13 @@ public class RolloutGroupListGrid extends AbstractGrid { item.getItemProperty(SPUILabelDefinitions.VAR_STATUS).setValue(rolloutGroup.getStatus()); item.getItemProperty(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS) .setValue(rolloutGroup.getTotalTargetCountStatus()); + item.getItemProperty(SPUILabelDefinitions.ROLLOUT_GROUP_INSTALLED_PERCENTAGE) + .setValue(calculateFinishedPercentage(rolloutGroup)); + } + + private String calculateFinishedPercentage(final RolloutGroup rolloutGroup) { + return HawkbitCommonUtil.formattingFinishedPercentage(rolloutGroup, + rolloutManagement.getFinishedPercentForRunningGroup(rolloutGroup.getRollout().getId(), rolloutGroup)); } @Override @@ -116,6 +130,9 @@ public class RolloutGroupListGrid extends AbstractGrid { protected void addContainerProperties() { final LazyQueryContainer rolloutGroupGridContainer = (LazyQueryContainer) getContainerDataSource(); rolloutGroupGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_NAME, String.class, "", false, false); + + rolloutGroupGridContainer.addContainerProperty(ROLLOUT_RENDERER_DATA, RolloutRendererData.class, null, false, + false); rolloutGroupGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_DESC, String.class, null, false, false); rolloutGroupGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_STATUS, RolloutGroupStatus.class, null, false, false); @@ -145,8 +162,8 @@ public class RolloutGroupListGrid extends AbstractGrid { @Override protected void setColumnExpandRatio() { - getColumn(SPUILabelDefinitions.VAR_NAME).setMinimumWidth(40); - getColumn(SPUILabelDefinitions.VAR_NAME).setMaximumWidth(200); + getColumn(ROLLOUT_RENDERER_DATA).setMinimumWidth(40); + getColumn(ROLLOUT_RENDERER_DATA).setMaximumWidth(200); getColumn(SPUILabelDefinitions.VAR_TOTAL_TARGETS).setMinimumWidth(40); getColumn(SPUILabelDefinitions.VAR_TOTAL_TARGETS).setMaximumWidth(100); @@ -170,7 +187,7 @@ public class RolloutGroupListGrid extends AbstractGrid { @Override protected void setColumnHeaderNames() { - getColumn(SPUILabelDefinitions.VAR_NAME).setHeaderCaption(i18n.get("header.name")); + getColumn(ROLLOUT_RENDERER_DATA).setHeaderCaption(i18n.get("header.name")); getColumn(SPUILabelDefinitions.VAR_STATUS).setHeaderCaption(i18n.get("header.status")); getColumn(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS) .setHeaderCaption(i18n.get("header.detail.status")); @@ -196,7 +213,7 @@ public class RolloutGroupListGrid extends AbstractGrid { @Override protected void setColumnProperties() { final List columnList = new ArrayList<>(); - columnList.add(SPUILabelDefinitions.VAR_NAME); + columnList.add(ROLLOUT_RENDERER_DATA); columnList.add(SPUILabelDefinitions.VAR_STATUS); columnList.add(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS); columnList.add(SPUILabelDefinitions.VAR_TOTAL_TARGETS); @@ -221,14 +238,15 @@ public class RolloutGroupListGrid extends AbstractGrid { getColumn(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS).setRenderer(new HtmlRenderer(), new TotalTargetCountStatusConverter()); if (permissionChecker.hasRolloutTargetsReadPermission()) { - getColumn(SPUILabelDefinitions.VAR_NAME) - .setRenderer(new LinkRenderer(event -> onClickOfRolloutGroupName(event))); + getColumn(ROLLOUT_RENDERER_DATA) + .setRenderer(new RolloutRenderer(event -> onClickOfRolloutGroupName(event))); } } @Override protected void setHiddenColumns() { final List columnsToBeHidden = new ArrayList<>(); + columnsToBeHidden.add(SPUILabelDefinitions.VAR_NAME); columnsToBeHidden.add(SPUILabelDefinitions.VAR_CREATED_DATE); columnsToBeHidden.add(SPUILabelDefinitions.VAR_CREATED_USER); columnsToBeHidden.add(SPUILabelDefinitions.VAR_MODIFIED_DATE); @@ -268,8 +286,8 @@ public class RolloutGroupListGrid extends AbstractGrid { return cell.getProperty().getValue().toString().toLowerCase(); } else if (SPUILabelDefinitions.ACTION.equals(cell.getPropertyId())) { return SPUILabelDefinitions.ACTION.toLowerCase(); - } else if (SPUILabelDefinitions.VAR_NAME.equals(cell.getPropertyId())) { - return cell.getProperty().getValue().toString(); + } else if (ROLLOUT_RENDERER_DATA.equals(cell.getPropertyId())) { + return ((RolloutRendererData) cell.getProperty().getValue()).getName(); } else if (SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS.equals(cell.getPropertyId())) { return DistributionBarHelper .getTooltip(((TotalTargetCountStatus) cell.getValue()).getStatusTotalCountMap()); @@ -306,14 +324,14 @@ public class RolloutGroupListGrid extends AbstractGrid { @Override public TotalTargetCountStatus convertToModel(final String value, final Class targetType, final Locale locale) - throws com.vaadin.data.util.converter.Converter.ConversionException { + throws com.vaadin.data.util.converter.Converter.ConversionException { return null; } @Override public String convertToPresentation(final TotalTargetCountStatus value, final Class targetType, final Locale locale) - throws com.vaadin.data.util.converter.Converter.ConversionException { + throws com.vaadin.data.util.converter.Converter.ConversionException { return DistributionBarHelper.getDistributionBarAsHTMLString(value.getStatusTotalCountMap()); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgrouptargets/RolloutGroupTargetsBeanQuery.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgrouptargets/RolloutGroupTargetsBeanQuery.java index 097e076be..685be685e 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgrouptargets/RolloutGroupTargetsBeanQuery.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgrouptargets/RolloutGroupTargetsBeanQuery.java @@ -17,6 +17,7 @@ import org.eclipse.hawkbit.repository.RolloutManagement; import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetWithActionStatus; +import org.eclipse.hawkbit.ui.common.UserDetailsFormatter; import org.eclipse.hawkbit.ui.components.ProxyTarget; import org.eclipse.hawkbit.ui.rollout.state.RolloutUIState; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; @@ -105,8 +106,8 @@ public class RolloutGroupTargetsBeanQuery extends AbstractBeanQuery prxyTarget.setLastModifiedDate(SPDateTimeUtil.getFormattedDate(targ.getLastModifiedAt())); prxyTarget.setCreatedDate(SPDateTimeUtil.getFormattedDate(targ.getCreatedAt())); prxyTarget.setCreatedAt(targ.getCreatedAt()); - prxyTarget.setCreatedByUser(HawkbitCommonUtil.getIMUser(targ.getCreatedBy())); - prxyTarget.setModifiedByUser(HawkbitCommonUtil.getIMUser(targ.getLastModifiedBy())); + prxyTarget.setCreatedByUser(UserDetailsFormatter.loadAndFormatCreatedBy(targ)); + prxyTarget.setModifiedByUser(UserDetailsFormatter.loadAndFormatLastModifiedBy(targ)); if (targetWithActionStatus.getStatus() != null) { prxyTarget.setStatus(targetWithActionStatus.getStatus()); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/AuthenticationConfigurationView.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/AuthenticationConfigurationView.java index 616acaf3f..329318b0f 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/AuthenticationConfigurationView.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/AuthenticationConfigurationView.java @@ -113,7 +113,7 @@ public class AuthenticationConfigurationView extends BaseConfigurationView downloadAnonymousCheckBox = SPUIComponentProvider.getCheckBox("", DIST_CHECKBOX_STYLE, null, false, ""); downloadAnonymousCheckBox.setId("downloadanonymouscheckbox"); - downloadAnonymousCheckBox.setValue(targetSecurityTokenAuthenticationConfigurationItem.isConfigEnabled()); + downloadAnonymousCheckBox.setValue(anonymousDownloadAuthenticationConfigurationItem.isConfigEnabled()); downloadAnonymousCheckBox.addValueChangeListener(this); anonymousDownloadAuthenticationConfigurationItem.addChangeListener(this); gridLayout.addComponent(downloadAnonymousCheckBox, 0, 3); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/AssignInstalledDSTooltipGenerator.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/AssignInstalledDSTooltipGenerator.java new file mode 100644 index 000000000..c4e78b3e5 --- /dev/null +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/AssignInstalledDSTooltipGenerator.java @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2015 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ + +package org.eclipse.hawkbit.ui.utils; + +import static org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil.HTML_LI_CLOSE_TAG; +import static org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil.HTML_LI_OPEN_TAG; +import static org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil.HTML_UL_CLOSE_TAG; +import static org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil.HTML_UL_OPEN_TAG; + +import java.util.Set; + +import org.eclipse.hawkbit.repository.model.DistributionSet; +import org.eclipse.hawkbit.repository.model.SoftwareModule; + +import com.vaadin.data.Item; +import com.vaadin.ui.AbstractSelect.ItemDescriptionGenerator; +import com.vaadin.ui.Component; +import com.vaadin.ui.Table; + +public class AssignInstalledDSTooltipGenerator implements ItemDescriptionGenerator { + private static final long serialVersionUID = 688730421728162456L; + + private static final String ASSIGN_DIST_SET = "assignedDistributionSet"; + private static final String INSTALL_DIST_SET = "installedDistributionSet"; + + @Override + public String generateDescription(final Component source, final Object itemId, final Object propertyId) { + final DistributionSet distributionSet; + final Item item = ((Table) source).getItem(itemId); + if (propertyId != null) { + if (propertyId.equals(SPUILabelDefinitions.ASSIGNED_DISTRIBUTION_NAME_VER)) { + distributionSet = (DistributionSet) item.getItemProperty(ASSIGN_DIST_SET).getValue(); + return getDSDetails(distributionSet); + } else if (propertyId.equals(SPUILabelDefinitions.INSTALLED_DISTRIBUTION_NAME_VER)) { + distributionSet = (DistributionSet) item.getItemProperty(INSTALL_DIST_SET).getValue(); + return getDSDetails(distributionSet); + } + } + return null; + } + + private String getDSDetails(final DistributionSet distributionSet) { + if (distributionSet == null) { + return null; + } + final StringBuilder swModuleNames = new StringBuilder(); + final StringBuilder swModuleVendors = new StringBuilder(); + final Set swModules = distributionSet.getModules(); + swModules.forEach(swModule -> { + swModuleNames.append(swModule.getName()); + swModuleNames.append(" , "); + swModuleVendors.append(swModule.getVendor()); + swModuleVendors.append(" , "); + }); + final StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(HTML_UL_OPEN_TAG); + stringBuilder.append(HTML_LI_OPEN_TAG); + stringBuilder.append(" DistributionSet Description : ").append(distributionSet.getDescription()); + stringBuilder.append(HTML_LI_CLOSE_TAG); + stringBuilder.append(HTML_LI_OPEN_TAG); + stringBuilder.append(" DistributionSet Type : ").append((distributionSet.getType()).getName()); + stringBuilder.append(HTML_LI_CLOSE_TAG); + stringBuilder.append(HTML_LI_OPEN_TAG); + stringBuilder.append(" Required Migration step : ") + .append(distributionSet.isRequiredMigrationStep() ? "Yes" : "No"); + stringBuilder.append(HTML_LI_CLOSE_TAG); + stringBuilder.append(HTML_LI_OPEN_TAG); + stringBuilder.append("SoftWare Modules : ").append(swModuleNames.toString()); + stringBuilder.append(HTML_LI_CLOSE_TAG); + stringBuilder.append(HTML_LI_OPEN_TAG); + stringBuilder.append("Vendor(s) : ").append(swModuleVendors.toString()); + stringBuilder.append(HTML_LI_CLOSE_TAG); + stringBuilder.append(HTML_UL_CLOSE_TAG); + return stringBuilder.toString(); + } +} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/HawkbitCommonUtil.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/HawkbitCommonUtil.java index 117b5bcb8..0e71567af 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/HawkbitCommonUtil.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/HawkbitCommonUtil.java @@ -20,9 +20,9 @@ import java.util.Map.Entry; import java.util.TimeZone; import org.apache.commons.lang3.StringUtils; -import org.eclipse.hawkbit.im.authentication.UserPrincipal; import org.eclipse.hawkbit.repository.SoftwareManagement; import org.eclipse.hawkbit.repository.model.AssignmentResult; +import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.NamedEntity; import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.SoftwareModule; @@ -34,9 +34,6 @@ import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus.Status; import org.eclipse.hawkbit.ui.rollout.StatusFontIcon; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.vaadin.addons.lazyquerycontainer.AbstractBeanQuery; import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory; import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer; @@ -76,6 +73,11 @@ public final class HawkbitCommonUtil { */ public static final String SPAN_CLOSE = ""; + public static final String HTML_LI_CLOSE_TAG = ""; + public static final String HTML_LI_OPEN_TAG = "
  • "; + public static final String HTML_UL_CLOSE_TAG = ""; + public static final String HTML_UL_OPEN_TAG = "
      "; + private static final Logger LOG = LoggerFactory.getLogger(HawkbitCommonUtil.class); private static final String JS_DRAG_COUNT_REM_CHILD = " if(x) { document.head.removeChild(x); } "; @@ -107,6 +109,9 @@ public final class HawkbitCommonUtil { private static final String DELETE_DROP_CREATE_SCRIPT = "var q = document.getElementById('show-delete-drop-hint'); if(q) { } else { showDeleteDrop = document.createElement('style'); showDeleteDrop.id=\"show-delete-drop-hint\"; document.head.appendChild(showDeleteDrop); }"; private static final String DELETE_TAG_DROP_REMOVE_SCRIPT = "var o = document.getElementById('show-delete-drop-hint'); if(o) { document.head.removeChild(o); } "; + private static final String ASSIGN_DIST_SET = "assignedDistributionSet"; + private static final String INSTALL_DIST_SET = "installedDistributionSet"; + /** * Define empty string. */ @@ -605,31 +610,6 @@ public final class HawkbitCommonUtil { return requiredExtraWidth + minTableWidth; } - /** - * get formatted name - lastname,firstname. - * - * @param user - * user name - * @return String formatted name - */ - public static String getFormattedName(final UserDetails user) { - final StringBuilder formattedName = new StringBuilder(); - if (user instanceof UserPrincipal) { - if (trimAndNullIfEmpty(((UserPrincipal) user).getLastname()) != null) { - formattedName.append(((UserPrincipal) user).getLastname()); - } - if (trimAndNullIfEmpty(((UserPrincipal) user).getFirstname()) != null) { - if (formattedName.length() > 0) { - formattedName.append(", "); - } - formattedName.append(((UserPrincipal) user).getFirstname()); - } - } else if (user != null) { - formattedName.append(user.getUsername()); - } - return formattedName.toString(); - } - /** * get the Last sequence of string which is after last dot in String. * @@ -686,30 +666,6 @@ public final class HawkbitCommonUtil { return exeJS.toString(); } - /** - * Get IM User for user UUID. - * - * @param uuid - * @return imReslovedUser user details - */ - public static String getIMUser(final String uuid) { - // Get modifed user - String imReslovedUser = HawkbitCommonUtil.SP_STRING_SPACE; - if (HawkbitCommonUtil.trimAndNullIfEmpty(uuid) != null) { - final UserDetailsService idManagement = SpringContextHelper.getBean(UserDetailsService.class); - try { - imReslovedUser = HawkbitCommonUtil.getFormattedName(idManagement.loadUserByUsername(uuid)); - } catch (final UsernameNotFoundException e) { // NOSONAR - // nope not need to handle - } - // If Null display the UID - if (HawkbitCommonUtil.trimAndNullIfEmpty(imReslovedUser) == null) { - imReslovedUser = uuid; - } - } - return imReslovedUser; - } - /** * Get formatted label.Appends ellipses if content does not fit the label. * @@ -1090,6 +1046,10 @@ public final class HawkbitCommonUtil { targetTableContainer.addContainerProperty(SPUILabelDefinitions.VAR_POLL_STATUS_TOOL_TIP, String.class, null, false, true); targetTableContainer.addContainerProperty(SPUILabelDefinitions.VAR_DESC, String.class, "", false, true); + + targetTableContainer.addContainerProperty(ASSIGN_DIST_SET, DistributionSet.class, null, false, true); + targetTableContainer.addContainerProperty(INSTALL_DIST_SET, DistributionSet.class, null, false, true); + } /** diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPDateTimeUtil.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPDateTimeUtil.java index 532dd010d..49bae86e1 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPDateTimeUtil.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPDateTimeUtil.java @@ -15,7 +15,9 @@ import java.util.HashMap; import java.util.Map; import java.util.TimeZone; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DurationFormatUtils; +import org.eclipse.hawkbit.repository.model.BaseEntity; import com.vaadin.server.WebBrowser; @@ -80,14 +82,45 @@ public final class SPDateTimeUtil { * @param lastQueryDate * @return String formatted date */ - public static String getFormattedDate(final Long lastQueryDate) { + return formatDate(lastQueryDate, null); + } + + /** + * Get formatted date 'created at' by entity. + * + * @param baseEntity + * the entity + * @return String formatted date + */ + public static String formatCreatedAt(final BaseEntity baseEntity) { + if (baseEntity == null) { + return StringUtils.EMPTY; + } + return formatDate(baseEntity.getCreatedAt(), StringUtils.EMPTY); + } + + /** + * Get formatted date 'last modified at' by entity. + * + * @param baseEntity + * the entity + * @return String formatted date + */ + public static String formatLastModifiedAt(final BaseEntity baseEntity) { + if (baseEntity == null) { + return StringUtils.EMPTY; + } + return formatDate(baseEntity.getLastModifiedAt(), StringUtils.EMPTY); + } + + private static String formatDate(final Long lastQueryDate, final String defaultString) { if (lastQueryDate != null) { final SimpleDateFormat format = new SimpleDateFormat(SPUIDefinitions.LAST_QUERY_DATE_FORMAT); format.setTimeZone(getBrowserTimeZone()); return format.format(new Date(lastQueryDate)); } - return null; + return defaultString; } /** diff --git a/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/common.scss b/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/common.scss index 87ea5b0b9..beb405c30 100644 --- a/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/common.scss +++ b/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/common.scss @@ -143,9 +143,15 @@ .valo-menu-title { line-height: 1.2; } + .v-menubar-user-menu:after { display: none; } + + .v-menubar-menuitem-user-menuitem { + width: 100%; + } + .v-menubar-user-menu > .v-menubar-menuitem { white-space: normal !important; .v-icon { diff --git a/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/rollout.scss b/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/rollout.scss index 712e04ec1..b9049068e 100644 --- a/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/rollout.scss +++ b/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/rollout.scss @@ -19,20 +19,32 @@ } } + .v-context-menu .v-context-menu-item-basic-icon-container{ height:0px !important; width:0px !important; } - .v-context-menu, .v-context-menu .v-context-menu-item-basic{ + .v-context-menu .v-context-menu-item-basic{ background-color: #feffff !important; border-radius: 4px; + font-family : $app-font-family; + font-size : $app-text-font-size; + font-weight : normal; + font-style : normal; } + + .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; color: #e8eef3; + height: 30px; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.05); } @@ -77,5 +89,9 @@ border-left: $v-grid-border-size solid $widget-border-color ; } + .v-button-boldhide{ + text-decoration:none; + } + } \ No newline at end of file diff --git a/pom.xml b/pom.xml index 0c3207c13..b6d09758e 100644 --- a/pom.xml +++ b/pom.xml @@ -74,7 +74,7 @@ 1.0.0 0.0.6.RELEASE - 7.6.4 + 7.6.5 ${vaadin.version} 7.4.0.1 2.2.0 @@ -94,7 +94,7 @@ 0.9.1 1.8.5 19.0 - 1.3.5 + 1.4.3 1.50.2 1.18.1 2.2.4