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, Long> swTable = (AbstractTable, Long>) 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, Long> 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, DistributionSetIdName> table = (AbstractTable, DistributionSetIdName>) 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, Long> swTable = (AbstractTable, Long>) 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, TargetIdName> source = (AbstractTable, TargetIdName>) 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, DistributionSetIdName> source = (AbstractTable, DistributionSetIdName>) 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, DistributionSetIdName> distTable = (AbstractTable, DistributionSetIdName>) 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, TargetIdName> targetTable = (AbstractTable, TargetIdName>) 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, DistributionSetIdName> distTable = (AbstractTable, DistributionSetIdName>) 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