Merge branch 'master' into feature_boot_13_sec_41

Conflicts:
	hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiArtifactDownloadTest.java
	hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/RepositoryApplicationConfiguration.java
	hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/SpPermission.java
	pom.xml


Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
This commit is contained in:
kaizimmerm
2016-07-27 15:29:54 +02:00
108 changed files with 3726 additions and 1844 deletions

View File

@@ -1,5 +1,7 @@
Build: [![Circle CI](https://circleci.com/gh/eclipse/hawkbit.svg?style=svg)](https://circleci.com/gh/eclipse/hawkbit) Build: [![Circle CI](https://circleci.com/gh/eclipse/hawkbit.svg?style=svg)](https://circleci.com/gh/eclipse/hawkbit)
<img src=hawkbit_logo.png width=533 height=246 />
# Eclipse.IoT hawkBit - Update Server # Eclipse.IoT hawkBit - Update Server
[hawkBit](https://projects.eclipse.org/projects/iot.hawkbit) is an domain independent back end solution for rolling out software updates to constrained edge devices as well as more powerful controllers and gateways connected to IP based networking infrastructure. [hawkBit](https://projects.eclipse.org/projects/iot.hawkbit) is an domain independent back end solution for rolling out software updates to constrained edge devices as well as more powerful controllers and gateways connected to IP based networking infrastructure.

View File

@@ -25,6 +25,7 @@ import org.springframework.cache.interceptor.CacheOperationInvocationContext;
import org.springframework.cache.interceptor.SimpleCacheResolver; import org.springframework.cache.interceptor.SimpleCacheResolver;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
/** /**
* A configuration for configuring the spring {@link CacheManager} for specific * A configuration for configuring the spring {@link CacheManager} for specific
@@ -33,9 +34,6 @@ import org.springframework.context.annotation.Configuration;
* *
* This is done by providing a special {@link TenantCacheResolver} which * This is done by providing a special {@link TenantCacheResolver} which
* generates a cache name included the current tenant. * generates a cache name included the current tenant.
*
*
*
*/ */
@Configuration @Configuration
@EnableCaching @EnableCaching
@@ -51,18 +49,27 @@ public class CacheAutoConfiguration extends CachingConfigurerSupport {
@Override @Override
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
@Primary
public TenancyCacheManager cacheManager() { public TenancyCacheManager cacheManager() {
return new TenantAwareCacheManager(new GuavaCacheManager(), tenantAware); return new TenantAwareCacheManager(directCacheManager(), tenantAware);
}
/**
* @return the direct cache manager to access without tenant aware check,
* cause in sometimes it's necessary to access the cache directly
* without having the current tenant, e.g. initial creation of
* tenant
*/
@Bean(name = "directCacheManager")
@ConditionalOnMissingBean(name = "directCacheManager")
public CacheManager directCacheManager() {
return new GuavaCacheManager();
} }
/** /**
* A {@link SimpleCacheResolver} implementation which includes the * A {@link SimpleCacheResolver} implementation which includes the
* {@link TenantAware#getCurrentTenant()} into the cache name before * {@link TenantAware#getCurrentTenant()} into the cache name before
* resolving it. * resolving it.
*
*
*
*
*/ */
public class TenantCacheResolver extends SimpleCacheResolver { public class TenantCacheResolver extends SimpleCacheResolver {

View File

@@ -31,7 +31,7 @@ public class DownloadIdCacheAutoConfiguration {
private CacheManager cacheManager; private CacheManager cacheManager;
/** /**
* Bean for the downlod id cache. * Bean for the download id cache.
* *
* @return the cache * @return the cache
*/ */

View File

@@ -45,6 +45,12 @@
<!-- Test --> <!-- Test -->
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-repository-api</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>

View File

@@ -15,6 +15,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.cache.CacheManager; import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
@@ -50,8 +51,14 @@ public class RedisConfiguration {
* @return the spring redis cache manager. * @return the spring redis cache manager.
*/ */
@Bean @Bean
@Primary
public CacheManager cacheManager() { public CacheManager cacheManager() {
return new TenantAwareCacheManager(new RedisCacheManager(redisTemplate()), tenantAware); return new TenantAwareCacheManager(directCacheManager(), tenantAware);
}
@Bean(name = "directCacheManager")
public CacheManager directCacheManager() {
return new RedisCacheManager(redisTemplate());
} }
/** /**

View File

@@ -16,8 +16,8 @@ import static org.mockito.Mockito.verify;
import java.util.Collection; import java.util.Collection;
import org.eclipse.hawkbit.eventbus.event.DownloadProgressEvent;
import org.eclipse.hawkbit.eventbus.event.EntityEvent; import org.eclipse.hawkbit.eventbus.event.EntityEvent;
import org.eclipse.hawkbit.repository.eventbus.event.DownloadProgressEvent;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@@ -56,7 +56,7 @@ public class EventDistributorTest {
@Test @Test
public void distributeDistributedEventSendsToRedis() { public void distributeDistributedEventSendsToRedis() {
final DownloadProgressEvent event = new DownloadProgressEvent("tenant", 123L, 10); final DownloadProgressEvent event = new DownloadProgressEvent("tenant", 123L, 500L, 100L, 200L);
underTest.distribute(event); underTest.distribute(event);
// origin node ID should be set by distributing the event // origin node ID should be set by distributing the event
@@ -67,7 +67,7 @@ public class EventDistributorTest {
@Test @Test
public void dontDistributeDistributedEventIfSameNode() { public void dontDistributeDistributedEventIfSameNode() {
final String knownNodeId = EventDistributor.getNodeId(); final String knownNodeId = EventDistributor.getNodeId();
final DownloadProgressEvent event = new DownloadProgressEvent("tenant", 123L, 10); final DownloadProgressEvent event = new DownloadProgressEvent("tenant", 123L, 500L, 100L, 200L);
event.setNodeId(knownNodeId); event.setNodeId(knownNodeId);
// test // test
@@ -79,7 +79,7 @@ public class EventDistributorTest {
@Test @Test
public void handleDistributedMessageFromRedis() { public void handleDistributedMessageFromRedis() {
final DownloadProgressEvent event = new DownloadProgressEvent("tenant", 123L, 10); final DownloadProgressEvent event = new DownloadProgressEvent("tenant", 123L, 500L, 100L, 200L);
final String knownChannel = "someChannel"; final String knownChannel = "someChannel";
underTest.handleMessage(event, knownChannel); underTest.handleMessage(event, knownChannel);
@@ -90,7 +90,7 @@ public class EventDistributorTest {
@Test @Test
public void handleDistributedMessageFilteredIfSameNodeId() { public void handleDistributedMessageFilteredIfSameNodeId() {
final DownloadProgressEvent event = new DownloadProgressEvent("tenant", 123L, 10); final DownloadProgressEvent event = new DownloadProgressEvent("tenant", 123L, 500L, 100L, 200L);
final String knownChannel = "someChannel"; final String knownChannel = "someChannel";
event.setOriginNodeId(EventDistributor.getNodeId()); event.setOriginNodeId(EventDistributor.getNodeId());

View File

@@ -1,57 +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.eventbus.event;
/**
* Event that contains an updated download progress for a given Action.
*
*
*
*
*/
public class DownloadProgressEvent extends AbstractDistributedEvent {
private static final long serialVersionUID = 1L;
private final Long statusId;
private final int progressPercent;
/**
* Constructor.
*
* @param tenant
* the tenant for this event
* @param statusId
* of {@link UpdateActionStatus}
* @param progressPercent
* number (1-100)
*/
public DownloadProgressEvent(final String tenant, final Long statusId, final int progressPercent) {
// the revision of the DownloadProgressEvent is just equal the
// progressPercentage due the
// percentage is going from 0 to 100.
super(statusId, tenant);
this.statusId = statusId;
this.progressPercent = progressPercent;
}
/**
* @return the statusId
*/
public Long getStatusId() {
return statusId;
}
/**
* @return the progressPercent
*/
public int getProgressPercent() {
return progressPercent;
}
}

View File

@@ -64,7 +64,12 @@ public enum TargetFields implements FieldNameProvider {
/** /**
* The tags field. * The tags field.
*/ */
TAG("tags.name"); TAG("tags.name"),
/**
* Last time the target or DMF client polled.
*/
LASTCONTROLLERREQUESTAT("targetInfo.lastTargetQuery");
private final String fieldName; private final String fieldName;
private List<String> subEntityAttribues; private List<String> subEntityAttribues;

View File

@@ -93,12 +93,12 @@ public class DdiArtifactStoreController implements DdiDlArtifactStoreControllerR
// we set a download status only if we are aware of the // we set a download status only if we are aware of the
// targetid, i.e. authenticated and not anonymous // targetid, i.e. authenticated and not anonymous
if (targetid != null && !"anonymous".equals(targetid)) { if (targetid != null && !"anonymous".equals(targetid)) {
final Action action = checkAndReportDownloadByTarget( final ActionStatus actionStatus = checkAndReportDownloadByTarget(
requestResponseContextHolder.getHttpServletRequest(), targetid, artifact); requestResponseContextHolder.getHttpServletRequest(), targetid, artifact);
result = RestResourceConversionHelper.writeFileResponse(artifact, result = RestResourceConversionHelper.writeFileResponse(artifact,
requestResponseContextHolder.getHttpServletResponse(), requestResponseContextHolder.getHttpServletResponse(),
requestResponseContextHolder.getHttpServletRequest(), file, controllerManagement, requestResponseContextHolder.getHttpServletRequest(), file, controllerManagement,
action.getId()); actionStatus.getId());
} else { } else {
result = RestResourceConversionHelper.writeFileResponse(artifact, result = RestResourceConversionHelper.writeFileResponse(artifact,
requestResponseContextHolder.getHttpServletResponse(), requestResponseContextHolder.getHttpServletResponse(),
@@ -131,7 +131,7 @@ public class DdiArtifactStoreController implements DdiDlArtifactStoreControllerR
return new ResponseEntity<>(HttpStatus.OK); return new ResponseEntity<>(HttpStatus.OK);
} }
private Action checkAndReportDownloadByTarget(final HttpServletRequest request, final String targetid, private ActionStatus checkAndReportDownloadByTarget(final HttpServletRequest request, final String targetid,
final LocalArtifact artifact) { final LocalArtifact artifact) {
final Target target = controllerManagement.updateLastTargetQuery(targetid, final Target target = controllerManagement.updateLastTargetQuery(targetid,
IpUtil.getClientIpFromRequest(request, securityProperties)); IpUtil.getClientIpFromRequest(request, securityProperties));
@@ -152,8 +152,8 @@ public class DdiArtifactStoreController implements DdiDlArtifactStoreControllerR
actionStatus.addMessage( actionStatus.addMessage(
RepositoryConstants.SERVER_MESSAGE_PREFIX + "Target downloads: " + request.getRequestURI()); RepositoryConstants.SERVER_MESSAGE_PREFIX + "Target downloads: " + request.getRequestURI());
} }
controllerManagement.addInformationalActionStatus(actionStatus);
return action; return controllerManagement.addInformationalActionStatus(actionStatus);
} }
} }

View File

@@ -156,8 +156,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
if (ifMatch != null && !RestResourceConversionHelper.matchesHttpHeader(ifMatch, artifact.getSha1Hash())) { if (ifMatch != null && !RestResourceConversionHelper.matchesHttpHeader(ifMatch, artifact.getSha1Hash())) {
result = new ResponseEntity<>(HttpStatus.PRECONDITION_FAILED); result = new ResponseEntity<>(HttpStatus.PRECONDITION_FAILED);
} else { } else {
final Action action = checkAndLogDownload(requestResponseContextHolder.getHttpServletRequest(), target, final ActionStatus action = checkAndLogDownload(requestResponseContextHolder.getHttpServletRequest(),
module); target, module);
result = RestResourceConversionHelper.writeFileResponse(artifact, result = RestResourceConversionHelper.writeFileResponse(artifact,
requestResponseContextHolder.getHttpServletResponse(), requestResponseContextHolder.getHttpServletResponse(),
requestResponseContextHolder.getHttpServletRequest(), file, controllerManagement, requestResponseContextHolder.getHttpServletRequest(), file, controllerManagement,
@@ -167,7 +167,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
return result; return result;
} }
private Action checkAndLogDownload(final HttpServletRequest request, final Target target, private ActionStatus checkAndLogDownload(final HttpServletRequest request, final Target target,
final SoftwareModule module) { final SoftwareModule module) {
final Action action = controllerManagement final Action action = controllerManagement
.getActionForDownloadByTargetAndSoftwareModule(target.getControllerId(), module); .getActionForDownloadByTargetAndSoftwareModule(target.getControllerId(), module);
@@ -185,8 +185,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
statusMessage.addMessage( statusMessage.addMessage(
RepositoryConstants.SERVER_MESSAGE_PREFIX + "Target downloads " + request.getRequestURI()); RepositoryConstants.SERVER_MESSAGE_PREFIX + "Target downloads " + request.getRequestURI());
} }
controllerManagement.addInformationalActionStatus(statusMessage);
return action; return controllerManagement.addInformationalActionStatus(statusMessage);
} }
private static boolean checkModule(final String fileName, final SoftwareModule module) { private static boolean checkModule(final String fileName, final SoftwareModule module) {

View File

@@ -29,7 +29,7 @@ import java.util.List;
import java.util.TimeZone; import java.util.TimeZone;
import org.apache.commons.lang3.RandomUtils; import org.apache.commons.lang3.RandomUtils;
import org.eclipse.hawkbit.eventbus.event.DownloadProgressEvent; import org.eclipse.hawkbit.repository.eventbus.event.DownloadProgressEvent;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.Artifact;
@@ -63,11 +63,15 @@ import ru.yandex.qatools.allure.annotations.Stories;
@Stories("Artifact Download Resource") @Stories("Artifact Download Resource")
public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMongoDB { public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMongoDB {
private static final int ARTIFACT_SIZE = 5 * 1024 * 1024;
public DdiArtifactDownloadTest() { public DdiArtifactDownloadTest() {
LOG = LoggerFactory.getLogger(DdiArtifactDownloadTest.class); LOG = LoggerFactory.getLogger(DdiArtifactDownloadTest.class);
} }
private volatile int downLoadProgress = 0; private volatile int downLoadProgress = 0;
private volatile long shippedBytes = 0;
private volatile long shippedBytesTotal = 0;
private final SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz"); private final SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
@@ -247,6 +251,8 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
@Description("Tests valid downloads through the artifact resource by identifying the artifact not by ID but file name.") @Description("Tests valid downloads through the artifact resource by identifying the artifact not by ID but file name.")
public void downloadArtifactThroughFileName() throws Exception { public void downloadArtifactThroughFileName() throws Exception {
downLoadProgress = 1; downLoadProgress = 1;
shippedBytes = 0;
shippedBytesTotal = 0;
eventBus.register(this); eventBus.register(this);
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0); assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
@@ -260,7 +266,7 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
final DistributionSet ds = testdataFactory.createDistributionSet(""); final DistributionSet ds = testdataFactory.createDistributionSet("");
// create artifact // create artifact
final byte random[] = RandomUtils.nextBytes(5 * 1024 * 1024); final byte random[] = RandomUtils.nextBytes(ARTIFACT_SIZE);
final LocalArtifact artifact = artifactManagement.createLocalArtifact(new ByteArrayInputStream(random), final LocalArtifact artifact = artifactManagement.createLocalArtifact(new ByteArrayInputStream(random),
ds.findFirstModuleByType(osType).getId(), "file1", false); ds.findFirstModuleByType(osType).getId(), "file1", false);
@@ -287,6 +293,7 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
// download complete // download complete
assertThat(downLoadProgress).isEqualTo(10); assertThat(downLoadProgress).isEqualTo(10);
assertThat(shippedBytes).isEqualTo(shippedBytesTotal).isEqualTo(ARTIFACT_SIZE);
} }
@Test @Test
@@ -324,35 +331,8 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
+ "anonymous as authorization is notpossible, e.g. chekc if the controller has the artifact assigned.") + "anonymous as authorization is notpossible, e.g. chekc if the controller has the artifact assigned.")
public void downloadArtifactByNameFailsIfNotAuthenticated() throws Exception { public void downloadArtifactByNameFailsIfNotAuthenticated() throws Exception {
downLoadProgress = 1; downLoadProgress = 1;
eventBus.register(this); shippedBytes = 0;
shippedBytesTotal = 0;
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
// create target
Target target = entityFactory.generateTarget("4712");
target = targetManagement.createTarget(target);
final List<Target> targets = new ArrayList();
targets.add(target);
// create ds
final DistributionSet ds = testdataFactory.createDistributionSet("");
// create artifact
final byte random[] = RandomUtils.nextBytes(5 * 1024);
final Artifact artifact = artifactManagement.createLocalArtifact(new ByteArrayInputStream(random),
ds.findFirstModuleByType(osType).getId(), "file1.tar.bz2", false);
// download fails as artifact is not yet assigned to target
deploymentManagement.assignDistributionSet(ds, targets);
mvc.perform(get("/controller/artifacts/v1/filename/{filename}", "file1.tar.bz2"))
.andExpect(status().isNotFound());
}
@Test
@WithUser(principal = "4712", authorities = "ROLE_CONTROLLER", allSpPermissions = true)
@Description("Ensures that an authenticated and named controller is permitted to download.")
public void downloadArtifactByNameByNamedController() throws Exception {
downLoadProgress = 1;
eventBus.register(this); eventBus.register(this);
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0); assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
@@ -367,7 +347,41 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
final DistributionSet ds = testdataFactory.createDistributionSet(""); final DistributionSet ds = testdataFactory.createDistributionSet("");
// create artifact // create artifact
final byte random[] = RandomUtils.nextBytes(5 * 1024 * 1024); final byte random[] = RandomUtils.nextBytes(ARTIFACT_SIZE);
artifactManagement.createLocalArtifact(new ByteArrayInputStream(random),
ds.findFirstModuleByType(osType).getId(), "file1.tar.bz2", false);
// download fails as artifact is not yet assigned to target
deploymentManagement.assignDistributionSet(ds, targets);
mvc.perform(get("/controller/artifacts/v1/filename/{filename}", "file1.tar.bz2"))
.andExpect(status().isNotFound());
assertThat(downLoadProgress).isEqualTo(1);
assertThat(shippedBytes).isEqualTo(shippedBytesTotal).isEqualTo(0L);
}
@Test
@WithUser(principal = "4712", authorities = "ROLE_CONTROLLER", allSpPermissions = true)
@Description("Ensures that an authenticated and named controller is permitted to download.")
public void downloadArtifactByNameByNamedController() throws Exception {
downLoadProgress = 1;
shippedBytes = 0;
shippedBytesTotal = 0;
eventBus.register(this);
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
// create target
Target target = entityFactory.generateTarget("4712");
target = targetManagement.createTarget(target);
final List<Target> targets = new ArrayList<>();
targets.add(target);
// create ds
final DistributionSet ds = testdataFactory.createDistributionSet("");
// create artifact
final byte random[] = RandomUtils.nextBytes(ARTIFACT_SIZE);
final Artifact artifact = artifactManagement.createLocalArtifact(new ByteArrayInputStream(random), final Artifact artifact = artifactManagement.createLocalArtifact(new ByteArrayInputStream(random),
ds.findFirstModuleByType(osType).getId(), "file1", false); ds.findFirstModuleByType(osType).getId(), "file1", false);
@@ -400,6 +414,7 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
// download complete // download complete
assertThat(downLoadProgress).isEqualTo(10); assertThat(downLoadProgress).isEqualTo(10);
assertThat(shippedBytes).isEqualTo(shippedBytesTotal).isEqualTo(ARTIFACT_SIZE);
} }
@Test @Test
@@ -561,5 +576,8 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
@Subscribe @Subscribe
public void listen(final DownloadProgressEvent event) { public void listen(final DownloadProgressEvent event) {
downLoadProgress++; downLoadProgress++;
shippedBytes += event.getShippedBytesSinceLast();
shippedBytesTotal = event.getShippedBytesOverall();
} }
} }

View File

@@ -32,7 +32,6 @@ public class MgmtSystemTenantServiceUsage {
* @param tenantName * @param tenantName
*/ */
public MgmtSystemTenantServiceUsage(final String tenantName) { public MgmtSystemTenantServiceUsage(final String tenantName) {
super();
this.tenantName = tenantName; this.tenantName = tenantName;
} }

View File

@@ -8,12 +8,14 @@
*/ */
package org.eclipse.hawkbit.mgmt.rest.resource; package org.eclipse.hawkbit.mgmt.rest.resource;
import static com.google.common.collect.Lists.newArrayList;
import static org.fest.assertions.api.Assertions.assertThat; import static org.fest.assertions.api.Assertions.assertThat;
import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasKey; import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.notNullValue;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
@@ -33,7 +35,6 @@ import org.eclipse.hawkbit.exception.SpServerError;
import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.repository.ActionFields; import org.eclipse.hawkbit.repository.ActionFields;
import org.eclipse.hawkbit.repository.ActionStatusFields;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo;
@@ -90,6 +91,7 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest {
private static final String JSON_PATH_FIELD_CONTENT = ".content"; private static final String JSON_PATH_FIELD_CONTENT = ".content";
private static final String JSON_PATH_FIELD_SIZE = ".size"; private static final String JSON_PATH_FIELD_SIZE = ".size";
private static final String JSON_PATH_FIELD_TOTAL = ".total"; private static final String JSON_PATH_FIELD_TOTAL = ".total";
private static final String JSON_PATH_FIELD_LAST_REQUEST_AT = ".lastControllerRequestAt";
// target // target
// $.field // $.field
@@ -101,6 +103,7 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest {
private static final String JSON_PATH_ID = JSON_PATH_ROOT + JSON_PATH_FIELD_ID; private static final String JSON_PATH_ID = JSON_PATH_ROOT + JSON_PATH_FIELD_ID;
private static final String JSON_PATH_CONTROLLERID = JSON_PATH_ROOT + JSON_PATH_FIELD_CONTROLLERID; private static final String JSON_PATH_CONTROLLERID = JSON_PATH_ROOT + JSON_PATH_FIELD_CONTROLLERID;
private static final String JSON_PATH_DESCRIPTION = JSON_PATH_ROOT + JSON_PATH_FIELD_DESCRIPTION; private static final String JSON_PATH_DESCRIPTION = JSON_PATH_ROOT + JSON_PATH_FIELD_DESCRIPTION;
private static final String JSON_PATH_LAST_REQUEST_AT = JSON_PATH_ROOT + JSON_PATH_FIELD_LAST_REQUEST_AT;
@Test @Test
@Description("Ensures that actions list is in exptected order.") @Description("Ensures that actions list is in exptected order.")
@@ -425,6 +428,7 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest {
.andExpect(jsonPath("$content.[?(@.name==" + idA + ")][0].controllerId", equalTo(idA))) .andExpect(jsonPath("$content.[?(@.name==" + idA + ")][0].controllerId", equalTo(idA)))
.andExpect(jsonPath("$content.[?(@.name==" + idA + ")][0].createdBy", equalTo("bumlux"))) .andExpect(jsonPath("$content.[?(@.name==" + idA + ")][0].createdBy", equalTo("bumlux")))
.andExpect(jsonPath("$content.[?(@.name==" + idA + ")][0].updateStatus", equalTo("unknown"))) .andExpect(jsonPath("$content.[?(@.name==" + idA + ")][0].updateStatus", equalTo("unknown")))
.andExpect(jsonPath("$content.[?(@.name==" + idA + ")][0].lastControllerRequestAt", notNullValue()))
// idB // idB
.andExpect(jsonPath("$content.[?(@.name==" + idB + ")][0]._links.self.href", .andExpect(jsonPath("$content.[?(@.name==" + idB + ")][0]._links.self.href",
equalTo(linksHrefPrefix + idB))) equalTo(linksHrefPrefix + idB)))
@@ -433,6 +437,7 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest {
.andExpect(jsonPath("$content.[?(@.name==" + idB + ")][0].controllerId", equalTo(idB))) .andExpect(jsonPath("$content.[?(@.name==" + idB + ")][0].controllerId", equalTo(idB)))
.andExpect(jsonPath("$content.[?(@.name==" + idB + ")][0].createdBy", equalTo("bumlux"))) .andExpect(jsonPath("$content.[?(@.name==" + idB + ")][0].createdBy", equalTo("bumlux")))
.andExpect(jsonPath("$content.[?(@.name==" + idB + ")][0].updateStatus", equalTo("unknown"))) .andExpect(jsonPath("$content.[?(@.name==" + idB + ")][0].updateStatus", equalTo("unknown")))
.andExpect(jsonPath("$content.[?(@.name==" + idA + ")][0].lastControllerRequestAt", notNullValue()))
// idC // idC
.andExpect(jsonPath("$content.[?(@.name==" + idC + ")][0]._links.self.href", .andExpect(jsonPath("$content.[?(@.name==" + idC + ")][0]._links.self.href",
equalTo(linksHrefPrefix + idC))) equalTo(linksHrefPrefix + idC)))
@@ -440,7 +445,8 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest {
.andExpect(jsonPath("$content.[?(@.name==" + idC + ")][0].description", equalTo(idC))) .andExpect(jsonPath("$content.[?(@.name==" + idC + ")][0].description", equalTo(idC)))
.andExpect(jsonPath("$content.[?(@.name==" + idC + ")][0].controllerId", equalTo(idC))) .andExpect(jsonPath("$content.[?(@.name==" + idC + ")][0].controllerId", equalTo(idC)))
.andExpect(jsonPath("$content.[?(@.name==" + idC + ")][0].createdBy", equalTo("bumlux"))) .andExpect(jsonPath("$content.[?(@.name==" + idC + ")][0].createdBy", equalTo("bumlux")))
.andExpect(jsonPath("$content.[?(@.name==" + idC + ")][0].updateStatus", equalTo("unknown"))); .andExpect(jsonPath("$content.[?(@.name==" + idC + ")][0].updateStatus", equalTo("unknown")))
.andExpect(jsonPath("$content.[?(@.name==" + idA + ")][0].lastControllerRequestAt", notNullValue()));
} }
@Test @Test
@@ -518,7 +524,7 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest {
// create first a target which can be retrieved by rest interface // create first a target which can be retrieved by rest interface
final String knownControllerId = "1"; final String knownControllerId = "1";
final String knownName = "someName"; final String knownName = "someName";
createSingleTarget(knownControllerId, knownName); final Target target = createSingleTarget(knownControllerId, knownName);
final String hrefPrefix = "http://localhost/rest/v1/targets/" + knownControllerId + "/"; final String hrefPrefix = "http://localhost/rest/v1/targets/" + knownControllerId + "/";
// test // test
mvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownControllerId)) mvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownControllerId))
@@ -526,6 +532,7 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest {
.andExpect(jsonPath(JSON_PATH_NAME, equalTo(knownName))) .andExpect(jsonPath(JSON_PATH_NAME, equalTo(knownName)))
.andExpect(jsonPath(JSON_PATH_CONTROLLERID, equalTo(knownControllerId))) .andExpect(jsonPath(JSON_PATH_CONTROLLERID, equalTo(knownControllerId)))
.andExpect(jsonPath(JSON_PATH_DESCRIPTION, equalTo(TARGET_DESCRIPTION_TEST))) .andExpect(jsonPath(JSON_PATH_DESCRIPTION, equalTo(TARGET_DESCRIPTION_TEST)))
.andExpect(jsonPath(JSON_PATH_LAST_REQUEST_AT, equalTo(target.getTargetInfo().getLastTargetQuery())))
.andExpect(jsonPath("$.pollStatus", hasKey("lastRequestAt"))) .andExpect(jsonPath("$.pollStatus", hasKey("lastRequestAt")))
.andExpect(jsonPath("$.pollStatus", hasKey("nextExpectedRequestAt"))) .andExpect(jsonPath("$.pollStatus", hasKey("nextExpectedRequestAt")))
.andExpect(jsonPath("$.pollStatus.overdue", equalTo(false))) .andExpect(jsonPath("$.pollStatus.overdue", equalTo(false)))
@@ -1075,8 +1082,6 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest {
private List<Action> generateTargetWithTwoUpdatesWithOneOverride(final String knownTargetId) private List<Action> generateTargetWithTwoUpdatesWithOneOverride(final String knownTargetId)
throws InterruptedException { throws InterruptedException {
final PageRequest pageRequest = new PageRequest(0, 100, Direction.ASC, ActionStatusFields.ID.getFieldName());
Target target = entityFactory.generateTarget(knownTargetId); Target target = entityFactory.generateTarget(knownTargetId);
target = targetManagement.createTarget(target); target = targetManagement.createTarget(target);
final List<Target> targets = new ArrayList<>(); final List<Target> targets = new ArrayList<>();
@@ -1122,7 +1127,7 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest {
@Test @Test
public void assignDistributionSetToTarget() throws Exception { public void assignDistributionSetToTarget() throws Exception {
final Target target = targetManagement.createTarget(entityFactory.generateTarget("fsdfsd")); targetManagement.createTarget(entityFactory.generateTarget("fsdfsd"));
final DistributionSet set = testdataFactory.createDistributionSet("one"); final DistributionSet set = testdataFactory.createDistributionSet("one");
mvc.perform(post(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/fsdfsd/assignedDS") mvc.perform(post(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/fsdfsd/assignedDS")
@@ -1299,19 +1304,20 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest {
+ "\"}]"; + "\"}]";
} }
private void createSingleTarget(final String controllerId, final String name) { private Target createSingleTarget(final String controllerId, final String name) {
final Target target = entityFactory.generateTarget(controllerId); final Target target = entityFactory.generateTarget(controllerId);
target.setName(name); target.setName(name);
target.setDescription(TARGET_DESCRIPTION_TEST); target.setDescription(TARGET_DESCRIPTION_TEST);
targetManagement.createTarget(target); targetManagement.createTarget(target);
controllerManagament.updateLastTargetQuery(controllerId, null); return controllerManagament.updateLastTargetQuery(controllerId, null);
} }
/** /**
* creating targets with the given amount by setting name, id etc from the * Creating targets with the given amount by setting name, id etc from the
* alphabet [a-z] using the ASCII. * alphabet [a-z] using ASCII.
* *
* @param amount * @param amount
* The number of targets to create
*/ */
private void createTargetsAlphabetical(final int amount) { private void createTargetsAlphabetical(final int amount) {
char character = 'a'; char character = 'a';
@@ -1320,14 +1326,14 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest {
final Target target = entityFactory.generateTarget(str); final Target target = entityFactory.generateTarget(str);
target.setName(str); target.setName(str);
target.setDescription(str); target.setDescription(str);
final Target savedTarget = targetManagement.createTarget(target); targetManagement.createTarget(target);
assertThat(savedTarget.getLastModifiedBy()).isNotNull(); controllerManagament.updateLastTargetQuery(str, null);
character++; character++;
} }
} }
/** /**
* helper method to give feedback mark an target IN_SNCY * helper method to give feedback mark an target IN_SYNC
* *
*/ */
private void feedbackToByInSync(final Long actionId) { private void feedbackToByInSync(final Long actionId) {
@@ -1348,7 +1354,7 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest {
final Target tA = targetManagement final Target tA = targetManagement
.createTarget(testdataFactory.generateTarget("target-id-A", "first description")); .createTarget(testdataFactory.generateTarget("target-id-A", "first description"));
// assign a distribution set so we get an active update action // assign a distribution set so we get an active update action
deploymentManagement.assignDistributionSet(dsA, Lists.newArrayList(tA)); deploymentManagement.assignDistributionSet(dsA, newArrayList(tA));
// verify active action // verify active action
final Slice<Action> actionsByTarget = deploymentManagement.findActionsByTarget(new PageRequest(0, 100), tA); final Slice<Action> actionsByTarget = deploymentManagement.findActionsByTarget(new PageRequest(0, 100), tA);
assertThat(actionsByTarget.getContent()).hasSize(1); assertThat(actionsByTarget.getContent()).hasSize(1);

View File

@@ -14,8 +14,8 @@ import java.util.Map;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.eventbus.event.DownloadProgressEvent;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.eventbus.event.DownloadProgressEvent;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.ToManyAttributeEntriesException; import org.eclipse.hawkbit.repository.exception.ToManyAttributeEntriesException;
@@ -58,16 +58,20 @@ public interface ControllerManagement {
Action addCancelActionStatus(@NotNull ActionStatus actionStatus); Action addCancelActionStatus(@NotNull ActionStatus actionStatus);
/** /**
* Sends the download progress in percentage and notifies the * Sends the download progress and notifies the {@link EventBus} with a
* {@link EventBus} with a {@link DownloadProgressEvent}. * {@link DownloadProgressEvent}.
* *
* @param statusId * @param statusId
* the ID of the {@link ActionStatus} * the ID of the {@link ActionStatus}
* @param progressPercent * @param requestedBytes
* the progress in percentage which must be between 0-100 * requested bytes of the request
* @param shippedBytesSinceLast
* since the last report
* @param shippedBytesOverall
* for the {@link ActionStatus}
*/ */
@PreAuthorize(SpringEvalExpressions.IS_CONTROLLER) @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
void downloadProgressPercent(long statusId, int progressPercent); void downloadProgress(Long statusId, Long requestedBytes, Long shippedBytesSinceLast, Long shippedBytesOverall);
/** /**
* Simple addition of a new {@link ActionStatus} entry to the {@link Action} * Simple addition of a new {@link ActionStatus} entry to the {@link Action}
@@ -75,9 +79,11 @@ public interface ControllerManagement {
* *
* @param statusMessage * @param statusMessage
* to add to the action * to add to the action
*
* @return create {@link ActionStatus} entity
*/ */
@PreAuthorize(SpringEvalExpressions.IS_CONTROLLER) @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
void addInformationalActionStatus(@NotNull ActionStatus statusMessage); ActionStatus addInformationalActionStatus(@NotNull ActionStatus statusMessage);
/** /**
* Adds an {@link ActionStatus} entry for an update {@link Action} including * Adds an {@link ActionStatus} entry for an update {@link Action} including

View File

@@ -269,8 +269,7 @@ public interface DeploymentManagement {
* @return the actions referring a specific rollout and a specific parent * @return the actions referring a specific rollout and a specific parent
* rollout group in a specific status * rollout group in a specific status
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
List<Action> findActionsByRolloutGroupParentAndStatus(@NotNull Rollout rollout, List<Action> findActionsByRolloutGroupParentAndStatus(@NotNull Rollout rollout,
@NotNull RolloutGroup rolloutGroupParent, @NotNull Action.Status actionStatus); @NotNull RolloutGroup rolloutGroupParent, @NotNull Action.Status actionStatus);
@@ -496,8 +495,7 @@ public interface DeploymentManagement {
* the action to start now. * the action to start now.
* @return the action which has been started * @return the action which has been started
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
Action startScheduledAction(@NotNull Action action); Action startScheduledAction(@NotNull Action action);
/** /**

View File

@@ -61,8 +61,7 @@ public interface RolloutManagement {
* this check. This check is only applied if the last check is * this check. This check is only applied if the last check is
* less than (lastcheck-delay). * less than (lastcheck-delay).
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
void checkRunningRollouts(long delayBetweenChecks); void checkRunningRollouts(long delayBetweenChecks);
/** /**
@@ -266,8 +265,7 @@ public interface RolloutManagement {
* if given rollout is not in {@link RolloutStatus#RUNNING}. * if given rollout is not in {@link RolloutStatus#RUNNING}.
* Only running rollouts can be paused. * Only running rollouts can be paused.
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
void pauseRollout(@NotNull Rollout rollout); void pauseRollout(@NotNull Rollout rollout);
/** /**
@@ -281,8 +279,7 @@ public interface RolloutManagement {
* if given rollout is not in {@link RolloutStatus#PAUSED}. Only * if given rollout is not in {@link RolloutStatus#PAUSED}. Only
* paused rollouts can be resumed. * paused rollouts can be resumed.
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
void resumeRollout(@NotNull Rollout rollout); void resumeRollout(@NotNull Rollout rollout);
/** /**
@@ -303,8 +300,7 @@ public interface RolloutManagement {
* if given rollout is not in {@link RolloutStatus#READY}. Only * if given rollout is not in {@link RolloutStatus#READY}. Only
* ready rollouts can be started. * ready rollouts can be started.
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
Rollout startRollout(@NotNull Rollout rollout); Rollout startRollout(@NotNull Rollout rollout);
/** /**
@@ -326,8 +322,7 @@ public interface RolloutManagement {
* if given rollout is not in {@link RolloutStatus#READY}. Only * if given rollout is not in {@link RolloutStatus#READY}. Only
* ready rollouts can be started. * ready rollouts can be started.
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
Rollout startRolloutAsync(@NotNull Rollout rollout); Rollout startRolloutAsync(@NotNull Rollout rollout);
/** /**

View File

@@ -39,16 +39,14 @@ public interface SystemManagement {
* @param tenant * @param tenant
* to delete * to delete
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_SYSTEM_ADMIN + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(SpringEvalExpressions.HAS_AUTH_SYSTEM_ADMIN)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
void deleteTenant(@NotNull String tenant); void deleteTenant(@NotNull String tenant);
/** /**
* *
* @return list of all tenant names in the system. * @return list of all tenant names in the system.
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_SYSTEM_ADMIN + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(SpringEvalExpressions.HAS_AUTH_SYSTEM_ADMIN)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
List<String> findTenants(); List<String> findTenants();
/** /**
@@ -68,8 +66,8 @@ public interface SystemManagement {
/** /**
* Returns {@link TenantMetaData} of given and current tenant. Creates for * Returns {@link TenantMetaData} of given and current tenant. Creates for
* new tenants also two {@link SoftwareModuleType} (os and app) and * new tenants also two {@link SoftwareModuleType} (os and app) and
* {@link RepositoryConstants#DEFAULT_DS_TYPES_IN_TENANT} {@link DistributionSetType}s * {@link RepositoryConstants#DEFAULT_DS_TYPES_IN_TENANT}
* (os and os_app). * {@link DistributionSetType}s (os and os_app).
* *
* DISCLAIMER: this variant is used during initial login (where the tenant * DISCLAIMER: this variant is used during initial login (where the tenant
* is not yet in the session). Please user {@link #getTenantMetadata()} for * is not yet in the session). Please user {@link #getTenantMetadata()} for

View File

@@ -54,8 +54,7 @@ public interface TenantConfigurationManagement {
* @return <null> if no default value is set and no database value available * @return <null> if no default value is set and no database value available
* or returns the tenant configuration value * or returns the tenant configuration value
*/ */
@PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
<T> TenantConfigurationValue<T> buildTenantConfigurationValueByKey(TenantConfigurationKey configurationKey, <T> TenantConfigurationValue<T> buildTenantConfigurationValueByKey(TenantConfigurationKey configurationKey,
Class<T> propertyType, TenantConfiguration tenantConfiguration); Class<T> propertyType, TenantConfiguration tenantConfiguration);
@@ -87,8 +86,7 @@ public interface TenantConfigurationManagement {
* if the property cannot be converted to the given * if the property cannot be converted to the given
* {@code propertyType} * {@code propertyType}
*/ */
@PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
<T> TenantConfigurationValue<T> getConfigurationValue(TenantConfigurationKey configurationKey); <T> TenantConfigurationValue<T> getConfigurationValue(TenantConfigurationKey configurationKey);
/** /**
@@ -114,8 +112,7 @@ public interface TenantConfigurationManagement {
* if the property cannot be converted to the given * if the property cannot be converted to the given
* {@code propertyType} * {@code propertyType}
*/ */
@PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
<T> TenantConfigurationValue<T> getConfigurationValue(TenantConfigurationKey configurationKey, <T> TenantConfigurationValue<T> getConfigurationValue(TenantConfigurationKey configurationKey,
Class<T> propertyType); Class<T> propertyType);
@@ -139,7 +136,6 @@ public interface TenantConfigurationManagement {
* if the property cannot be converted to the given * if the property cannot be converted to the given
* {@code propertyType} * {@code propertyType}
*/ */
@PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION + SpringEvalExpressions.HAS_AUTH_OR @PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION)
+ SpringEvalExpressions.IS_SYSTEM_CODE)
<T> T getGlobalConfigurationValue(TenantConfigurationKey configurationKey, Class<T> propertyType); <T> T getGlobalConfigurationValue(TenantConfigurationKey configurationKey, Class<T> propertyType);
} }

View File

@@ -20,15 +20,14 @@ import org.springframework.security.access.prepost.PreAuthorize;
public interface TenantStatsManagement { public interface TenantStatsManagement {
/** /**
* Service for stats of a single tenant. Opens a new transaction and as a * Service for stats of the current tenant.
* result can an be used for multiple tenants, i.e. to allow in one session
* to collect data of all tenants in the system.
* *
* @param tenant
* to collect for
* @return collected statistics * @return collected statistics
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_SYSTEM_ADMIN) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
TenantUsage getStatsOfTenant(String tenant); + SpringEvalExpressions.HAS_AUTH_READ_TARGET + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.IS_SYSTEM_CODE)
TenantUsage getStatsOfTenant();
} }

View File

@@ -0,0 +1,67 @@
/**
* 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.eventbus.event;
import org.eclipse.hawkbit.eventbus.event.AbstractDistributedEvent;
/**
* Event that contains an updated download progress for a given ActionStatus
* that was written for a download request.
*
*/
public class DownloadProgressEvent extends AbstractDistributedEvent {
private static final long serialVersionUID = 1L;
private final Long statusId;
private final long requestedBytes;
private final long shippedBytesSinceLast;
private final long shippedBytesOverall;
/**
* Constructor.
*
* @param tenant
* the tenant for this event
* @param statusId
* of ActionStatus that was written for the download request
* @param requestedBytes
* bytes requested
* @param shippedBytesSinceLast
* bytes since last event
* @param shippedBytesOverall
* on the download request
*/
public DownloadProgressEvent(final String tenant, final Long statusId, final Long requestedBytes,
final Long shippedBytesSinceLast, final Long shippedBytesOverall) {
// the revision of the DownloadProgressEvent is just equal the
// shippedBytesOverall as this is a growing number.
super(shippedBytesOverall, tenant);
this.statusId = statusId;
this.requestedBytes = requestedBytes;
this.shippedBytesSinceLast = shippedBytesSinceLast;
this.shippedBytesOverall = shippedBytesOverall;
}
public Long getStatusId() {
return statusId;
}
public long getRequestedBytes() {
return requestedBytes;
}
public long getShippedBytesSinceLast() {
return shippedBytesSinceLast;
}
public long getShippedBytesOverall() {
return shippedBytesOverall;
}
}

View File

@@ -39,12 +39,6 @@ public interface Action extends TenantAwareBaseEntity {
return Status.CANCELING.equals(getStatus()) || Status.CANCELED.equals(getStatus()); return Status.CANCELING.equals(getStatus()) || Status.CANCELED.equals(getStatus());
} }
/**
* @return current {@link Status#DOWNLOAD} progress if known by the update
* server.
*/
int getDownloadProgressPercent();
/** /**
* @return current {@link Status} of the {@link Action}. * @return current {@link Status} of the {@link Action}.
*/ */

View File

@@ -43,6 +43,12 @@ public interface ActionStatus extends TenantAwareBaseEntity {
*/ */
void addMessage(String message); void addMessage(String message);
/**
* @return current {@link Status#DOWNLOAD} progress if known by the update
* server.
*/
int getDownloadProgressPercent();
/** /**
* @return list of message entries that can be added to the * @return list of message entries that can be added to the
* {@link ActionStatus}. * {@link ActionStatus}.

View File

@@ -106,7 +106,7 @@ public class TenantUsage {
} }
@Override @Override
public int hashCode() { // NOSONAR - as this is generated code public int hashCode() {
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
result = prime * result + (int) (actions ^ (actions >>> 32)); result = prime * result + (int) (actions ^ (actions >>> 32));
@@ -118,15 +118,14 @@ public class TenantUsage {
} }
@Override @Override
public boolean equals(final Object obj) { // NOSONAR - as this is generated public boolean equals(final Object obj) {
// code
if (this == obj) { if (this == obj) {
return true; return true;
} }
if (obj == null) { if (obj == null) {
return false; return false;
} }
if (getClass() != obj.getClass()) { if (!(obj instanceof TenantUsage)) {
return false; return false;
} }
final TenantUsage other = (TenantUsage) obj; final TenantUsage other = (TenantUsage) obj;
@@ -154,7 +153,7 @@ public class TenantUsage {
@Override @Override
public String toString() { public String toString() {
return "SystemUsage [tenantName=" + tenantName + ", targets=" + targets + ", artifacts=" + artifacts return "TenantUsage [tenantName=" + tenantName + ", targets=" + targets + ", artifacts=" + artifacts
+ ", actions=" + actions + ", overallArtifactVolumeInBytes=" + overallArtifactVolumeInBytes + "]"; + ", actions=" + actions + ", overallArtifactVolumeInBytes=" + overallArtifactVolumeInBytes + "]";
} }

View File

@@ -54,6 +54,7 @@ import org.eclipse.hawkbit.repository.jpa.model.helper.TenantConfigurationManage
import org.eclipse.hawkbit.security.SecurityTokenGenerator; import org.eclipse.hawkbit.security.SecurityTokenGenerator;
import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.TenantAware; import org.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration; import org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
@@ -71,6 +72,8 @@ import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor; import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
import com.google.common.eventbus.EventBus;
/** /**
* General configuration for hawkBit's Repository. * General configuration for hawkBit's Repository.
* *
@@ -85,6 +88,9 @@ import org.springframework.validation.beanvalidation.MethodValidationPostProcess
@EnableScheduling @EnableScheduling
@EntityScan("org.eclipse.hawkbit.repository.jpa.model") @EntityScan("org.eclipse.hawkbit.repository.jpa.model")
public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
@Autowired
private EventBus eventBus;
/** /**
* @return the {@link SystemSecurityContext} singleton bean which make it * @return the {@link SystemSecurityContext} singleton bean which make it
* accessible in beans which cannot access the service directly, * accessible in beans which cannot access the service directly,
@@ -249,7 +255,9 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public TenantStatsManagement tenantStatsManagement() { public TenantStatsManagement tenantStatsManagement() {
return new JpaTenantStatsManagement(); final TenantStatsManagement mgmt = new JpaTenantStatsManagement();
eventBus.register(mgmt);
return mgmt;
} }
/** /**

View File

@@ -451,8 +451,8 @@ public class JpaControllerManagement implements ControllerManagement {
@Override @Override
@Modifying @Modifying
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void addInformationalActionStatus(final ActionStatus statusMessage) { public ActionStatus addInformationalActionStatus(final ActionStatus statusMessage) {
actionStatusRepository.save((JpaActionStatus) statusMessage); return actionStatusRepository.save((JpaActionStatus) statusMessage);
} }
@Override @Override
@@ -469,8 +469,9 @@ public class JpaControllerManagement implements ControllerManagement {
} }
@Override @Override
public void downloadProgressPercent(final long statusId, final int progressPercent) { public void downloadProgress(final Long statusId, final Long requestedBytes, final Long shippedBytesSinceLast,
cacheWriteNotify.downloadProgressPercent(statusId, progressPercent); final Long shippedBytesOverall) {
cacheWriteNotify.downloadProgress(statusId, requestedBytes, shippedBytesSinceLast, shippedBytesOverall);
} }
} }

View File

@@ -132,7 +132,7 @@ public class JpaSoftwareManagement implements SoftwareManagement {
final JpaSoftwareModuleType type = softwareModuleTypeRepository.findOne(sm.getId()); final JpaSoftwareModuleType type = softwareModuleTypeRepository.findOne(sm.getId());
boolean updated = false; boolean updated = false;
if (sm.getDescription() != null && !sm.getDescription().equals(type.getDescription())) { if (sm.getDescription() == null || !sm.getDescription().equals(type.getDescription())) {
type.setDescription(sm.getDescription()); type.setDescription(sm.getDescription());
updated = true; updated = true;
} }

View File

@@ -19,6 +19,7 @@ import org.eclipse.hawkbit.repository.Constants;
import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.TenantStatsManagement; import org.eclipse.hawkbit.repository.TenantStatsManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.jpa.configuration.MultiTenantJpaTransactionManager;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType;
import org.eclipse.hawkbit.repository.jpa.model.JpaTenantMetaData; import org.eclipse.hawkbit.repository.jpa.model.JpaTenantMetaData;
@@ -26,18 +27,20 @@ import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.model.TenantMetaData; import org.eclipse.hawkbit.repository.model.TenantMetaData;
import org.eclipse.hawkbit.repository.report.model.SystemUsageReport; import org.eclipse.hawkbit.repository.report.model.SystemUsageReport;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.TenantAware; import org.eclipse.hawkbit.tenancy.TenantAware;
import org.eclipse.persistence.config.PersistenceUnitProperties; import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.ApplicationContext;
import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Modifying;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
/** /**
@@ -108,7 +111,10 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
private SystemManagementCacheKeyGenerator currentTenantCacheKeyGenerator; private SystemManagementCacheKeyGenerator currentTenantCacheKeyGenerator;
@Autowired @Autowired
private ApplicationContext applicationContext; private SystemSecurityContext systemSecurityContext;
@Autowired
private PlatformTransactionManager txManager;
@Override @Override
public SystemUsageReport getSystemUsageStatistics() { public SystemUsageReport getSystemUsageStatistics() {
@@ -147,7 +153,7 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
final List<String> tenants = findTenants(); final List<String> tenants = findTenants();
tenants.forEach(tenant -> tenantAware.runAsTenant(tenant, () -> { tenants.forEach(tenant -> tenantAware.runAsTenant(tenant, () -> {
report.addTenantData(systemStatsManagement.getStatsOfTenant(tenant)); report.addTenantData(systemStatsManagement.getStatsOfTenant());
return null; return null;
})); }));
} }
@@ -159,39 +165,57 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
} }
@Override @Override
@Cacheable(value = "tenantMetadata", key = "#tenant.toUpperCase()")
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Modifying @Modifying
public TenantMetaData getTenantMetadata(final String tenant) { public TenantMetaData getTenantMetadata(final String tenant) {
final TenantMetaData result = tenantMetaDataRepository.findByTenantIgnoreCase(tenant); final TenantMetaData result = tenantMetaDataRepository.findByTenantIgnoreCase(tenant);
// Create if it does not exist // Create if it does not exist
if (result == null) { if (result == null) {
try { try {
currentTenantCacheKeyGenerator.getCreateInitialTenant().set(tenant); currentTenantCacheKeyGenerator.getCreateInitialTenant().set(tenant);
cacheManager.getCache("currentTenant").evict(currentTenantKeyGenerator().generate(null, null)); return createInitialTenantMetaData(tenant);
applicationContext.getBean("currentTenantKeyGenerator");
return tenantMetaDataRepository.save(new JpaTenantMetaData(createStandardSoftwareDataSetup(), tenant));
} finally { } finally {
currentTenantCacheKeyGenerator.getCreateInitialTenant().remove(); currentTenantCacheKeyGenerator.getCreateInitialTenant().remove();
} }
} }
return result; return result;
} }
/**
* Creating the initial tenant meta-data in a new transaction. Due the
* {@link MultiTenantJpaTransactionManager} is using the current tenant to
* set the necessary tenant discriminator to the query. This is not working
* if we don't have a current tenant set. Due the
* {@link #getTenantMetadata(String)} is maybe called without having a
* current tenant we need to re-open a new transaction so the
* {@link MultiTenantJpaTransactionManager} is called again and set the
* tenant for this transaction.
*
* @param tenant
* the tenant to be created
* @return the initial created {@link TenantMetaData}
*/
private TenantMetaData createInitialTenantMetaData(final String tenant) {
final DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setName("initial-tenant-creation");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
return systemSecurityContext.runAsSystemAsTenant(
() -> new TransactionTemplate(txManager, def).execute(status -> tenantMetaDataRepository
.save(new JpaTenantMetaData(createStandardSoftwareDataSetup(), tenant))),
tenant);
}
@Override @Override
public List<String> findTenants() { public List<String> findTenants() {
return tenantMetaDataRepository.findAll().stream().map(md -> md.getTenant()).collect(Collectors.toList()); return tenantMetaDataRepository.findAll().stream().map(md -> md.getTenant()).collect(Collectors.toList());
} }
@Override @Override
@CacheEvict(value = { "tenantMetadata" }, key = "#tenant.toUpperCase()")
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Modifying @Modifying
public void deleteTenant(final String tenant) { public void deleteTenant(final String tenant) {
cacheManager.evictCaches(tenant); cacheManager.evictCaches(tenant);
cacheManager.getCache("currentTenant").evict(currentTenantKeyGenerator().generate(null, null));
tenantAware.runAsTenant(tenant, () -> { tenantAware.runAsTenant(tenant, () -> {
entityManager.setProperty(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT, tenant.toUpperCase()); entityManager.setProperty(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT, tenant.toUpperCase());
tenantMetaDataRepository.deleteByTenantIgnoreCase(tenant); tenantMetaDataRepository.deleteByTenantIgnoreCase(tenant);
@@ -214,7 +238,6 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
} }
@Override @Override
@Cacheable(value = "tenantMetadata", keyGenerator = "tenantKeyGenerator")
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Modifying @Modifying
public TenantMetaData getTenantMetadata() { public TenantMetaData getTenantMetadata() {
@@ -226,7 +249,7 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
} }
@Override @Override
@Cacheable(value = "currentTenant", keyGenerator = "currentTenantKeyGenerator") @Cacheable(value = "currentTenant", keyGenerator = "currentTenantKeyGenerator", cacheManager = "directCacheManager")
// set transaction to not supported, due we call this in // set transaction to not supported, due we call this in
// BaseEntity#prePersist methods // BaseEntity#prePersist methods
// and it seems that JPA committing the transaction when executing this // and it seems that JPA committing the transaction when executing this
@@ -249,7 +272,6 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
} }
@Override @Override
@CachePut(value = "tenantMetadata", key = "#metaData.tenant.toUpperCase()")
@Transactional(isolation = Isolation.READ_UNCOMMITTED) @Transactional(isolation = Isolation.READ_UNCOMMITTED)
@Modifying @Modifying
public TenantMetaData updateTenantMetadata(final TenantMetaData metaData) { public TenantMetaData updateTenantMetadata(final TenantMetaData metaData) {

View File

@@ -12,8 +12,8 @@ import java.util.Optional;
import org.eclipse.hawkbit.repository.TenantStatsManagement; import org.eclipse.hawkbit.repository.TenantStatsManagement;
import org.eclipse.hawkbit.repository.report.model.TenantUsage; import org.eclipse.hawkbit.repository.report.model.TenantUsage;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -35,9 +35,14 @@ public class JpaTenantStatsManagement implements TenantStatsManagement {
@Autowired @Autowired
private ActionRepository actionRepository; private ActionRepository actionRepository;
@Autowired
private TenantAware tenantAware;
@Override @Override
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_UNCOMMITTED) @Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_UNCOMMITTED)
public TenantUsage getStatsOfTenant(final String tenant) { public TenantUsage getStatsOfTenant() {
final String tenant = tenantAware.getCurrentTenant();
final TenantUsage result = new TenantUsage(tenant); final TenantUsage result = new TenantUsage(tenant);
result.setTargets(targetRepository.count()); result.setTargets(targetRepository.count());

View File

@@ -8,9 +8,10 @@
*/ */
package org.eclipse.hawkbit.repository.jpa.cache; package org.eclipse.hawkbit.repository.jpa.cache;
import org.eclipse.hawkbit.eventbus.event.DownloadProgressEvent; import java.math.RoundingMode;
import org.eclipse.hawkbit.repository.eventbus.event.DownloadProgressEvent;
import org.eclipse.hawkbit.repository.eventbus.event.RolloutGroupCreatedEvent; import org.eclipse.hawkbit.repository.eventbus.event.RolloutGroupCreatedEvent;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.ActionStatus;
import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.tenancy.TenantAware; import org.eclipse.hawkbit.tenancy.TenantAware;
@@ -20,6 +21,7 @@ import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.google.common.eventbus.EventBus; import com.google.common.eventbus.EventBus;
import com.google.common.math.DoubleMath;
/** /**
* An service which combines the functionality for functional use cases to write * An service which combines the functionality for functional use cases to write
@@ -30,10 +32,6 @@ import com.google.common.eventbus.EventBus;
*/ */
@Service @Service
public class CacheWriteNotify { public class CacheWriteNotify {
/**
*
*/
private static final int DOWNLOAD_PROGRESS_MAX = 100; private static final int DOWNLOAD_PROGRESS_MAX = 100;
@Autowired @Autowired
@@ -46,20 +44,29 @@ public class CacheWriteNotify {
private TenantAware tenantAware; private TenantAware tenantAware;
/** /**
* writes the download progress in percentage into the cache * writes the download progress into the cache
* {@link CacheKeys#DOWNLOAD_PROGRESS_PERCENT} and notifies the * {@link CacheKeys#DOWNLOAD_PROGRESS_PERCENT} and notifies the
* {@link EventBus} with a {@link DownloadProgressEvent}. * {@link EventBus} with a {@link DownloadProgressEvent}.
* *
* @param statusId * @param statusId
* the ID of the {@link ActionStatus} * the ID of the {@link ActionStatus}
* @param progressPercent * @param requestedBytes
* the progress in percentage which must be between 0-100 * requested bytes of the request
* @param shippedBytesSinceLast
* since last event
* @param shippedBytesOverall
* for the download request
*/ */
public void downloadProgressPercent(final long statusId, final int progressPercent) { public void downloadProgress(final Long statusId, final Long requestedBytes, final Long shippedBytesSinceLast,
final Long shippedBytesOverall) {
final Cache cache = cacheManager.getCache(Action.class.getName()); final Cache cache = cacheManager.getCache(ActionStatus.class.getName());
final String cacheKey = CacheKeys.entitySpecificCacheKey(String.valueOf(statusId), final String cacheKey = CacheKeys.entitySpecificCacheKey(String.valueOf(statusId),
CacheKeys.DOWNLOAD_PROGRESS_PERCENT); CacheKeys.DOWNLOAD_PROGRESS_PERCENT);
final int progressPercent = DoubleMath.roundToInt(shippedBytesOverall * 100.0 / requestedBytes,
RoundingMode.DOWN);
if (progressPercent < DOWNLOAD_PROGRESS_MAX) { if (progressPercent < DOWNLOAD_PROGRESS_MAX) {
cache.put(cacheKey, progressPercent); cache.put(cacheKey, progressPercent);
} else { } else {
@@ -69,7 +76,8 @@ public class CacheWriteNotify {
cache.evict(cacheKey); cache.evict(cacheKey);
} }
eventBus.post(new DownloadProgressEvent(tenantAware.getCurrentTenant(), statusId, progressPercent)); eventBus.post(new DownloadProgressEvent(tenantAware.getCurrentTenant(), statusId, requestedBytes,
shippedBytesSinceLast, shippedBytesOverall));
} }
/** /**

View File

@@ -27,10 +27,7 @@ import javax.persistence.NamedEntityGraphs;
import javax.persistence.NamedSubgraph; import javax.persistence.NamedSubgraph;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.Transient;
import org.eclipse.hawkbit.repository.jpa.cache.CacheField;
import org.eclipse.hawkbit.repository.jpa.cache.CacheKeys;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
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.DistributionSet;
@@ -89,13 +86,6 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio
@JoinColumn(name = "rollout", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_action_rollout")) @JoinColumn(name = "rollout", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_action_rollout"))
private JpaRollout rollout; private JpaRollout rollout;
/**
* Note: filled only in {@link Status#DOWNLOAD}.
*/
@Transient
@CacheField(key = CacheKeys.DOWNLOAD_PROGRESS_PERCENT)
private int downloadProgressPercent;
@Override @Override
public DistributionSet getDistributionSet() { public DistributionSet getDistributionSet() {
return distributionSet; return distributionSet;
@@ -120,15 +110,6 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio
this.status = status; this.status = status;
} }
@Override
public int getDownloadProgressPercent() {
return downloadProgressPercent;
}
public void setDownloadProgressPercent(final int downloadProgressPercent) {
this.downloadProgressPercent = downloadProgressPercent;
}
@Override @Override
public boolean isActive() { public boolean isActive() {
return active; return active;

View File

@@ -24,7 +24,10 @@ import javax.persistence.ManyToOne;
import javax.persistence.NamedAttributeNode; import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph; import javax.persistence.NamedEntityGraph;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.Transient;
import org.eclipse.hawkbit.repository.jpa.cache.CacheField;
import org.eclipse.hawkbit.repository.jpa.cache.CacheKeys;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.ActionStatus;
@@ -63,6 +66,13 @@ public class JpaActionStatus extends AbstractJpaTenantAwareBaseEntity implements
@Column(name = "detail_message", length = 512) @Column(name = "detail_message", length = 512)
private final List<String> messages = new ArrayList<>(); private final List<String> messages = new ArrayList<>();
/**
* Note: filled only in {@link Status#DOWNLOAD}.
*/
@Transient
@CacheField(key = CacheKeys.DOWNLOAD_PROGRESS_PERCENT)
private int downloadProgressPercent;
/** /**
* Creates a new {@link ActionStatus} object. * Creates a new {@link ActionStatus} object.
* *
@@ -105,6 +115,11 @@ public class JpaActionStatus extends AbstractJpaTenantAwareBaseEntity implements
// JPA default constructor. // JPA default constructor.
} }
@Override
public int getDownloadProgressPercent() {
return downloadProgressPercent;
}
@Override @Override
public Long getOccurredAt() { public Long getOccurredAt() {
return occurredAt; return occurredAt;

View File

@@ -83,6 +83,7 @@ public final class DistributionSetSpecification {
targetRoot.fetch(JpaDistributionSet_.modules, JoinType.LEFT); targetRoot.fetch(JpaDistributionSet_.modules, JoinType.LEFT);
targetRoot.fetch(JpaDistributionSet_.tags, JoinType.LEFT); targetRoot.fetch(JpaDistributionSet_.tags, JoinType.LEFT);
targetRoot.fetch(JpaDistributionSet_.type, JoinType.LEFT); targetRoot.fetch(JpaDistributionSet_.type, JoinType.LEFT);
targetRoot.fetch(JpaDistributionSet_.metadata, JoinType.LEFT);
query.distinct(true); query.distinct(true);
return predicate; return predicate;

View File

@@ -8,6 +8,7 @@
*/ */
package org.eclipse.hawkbit.repository.jpa.specifications; package org.eclipse.hawkbit.repository.jpa.specifications;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Predicate;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
@@ -38,6 +39,8 @@ public final class SoftwareModuleSpecification {
return (targetRoot, query, cb) -> { return (targetRoot, query, cb) -> {
final Predicate predicate = cb.equal(targetRoot.<Long> get(JpaSoftwareModule_.id), moduleId); final Predicate predicate = cb.equal(targetRoot.<Long> get(JpaSoftwareModule_.id), moduleId);
targetRoot.fetch(JpaSoftwareModule_.type); targetRoot.fetch(JpaSoftwareModule_.type);
targetRoot.fetch(JpaSoftwareModule_.metadata,JoinType.LEFT);
query.distinct(true);
return predicate; return predicate;
}; };
} }

View File

@@ -17,6 +17,7 @@ import java.util.Random;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TenantMetaData;
import org.eclipse.hawkbit.repository.report.model.TenantUsage; import org.eclipse.hawkbit.repository.report.model.TenantUsage;
import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule; import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule;
import org.junit.Test; import org.junit.Test;
@@ -29,6 +30,15 @@ import ru.yandex.qatools.allure.annotations.Stories;
@Stories("System Management") @Stories("System Management")
public class SystemManagementTest extends AbstractJpaIntegrationTestWithMongoDB { public class SystemManagementTest extends AbstractJpaIntegrationTestWithMongoDB {
@Test
@Description("Ensures that you can create a tenant without setting the necessary security context which holds a current tenant")
public void createInitialTenantWithoutSecurityContext() {
securityRule.clear();
final String tenantToBeCreated = "newTenantToCreate";
final TenantMetaData tenantMetadata = systemManagement.getTenantMetadata(tenantToBeCreated);
assertThat(tenantMetadata).isNotNull();
}
@Test @Test
@Description("Ensures that findTenants returns all tenants and not only restricted to the tenant which currently is logged in") @Description("Ensures that findTenants returns all tenants and not only restricted to the tenant which currently is logged in")
public void findTenantsReturnsAllTenantsNotOnlyWhichLoggedIn() throws Exception { public void findTenantsReturnsAllTenantsNotOnlyWhichLoggedIn() throws Exception {

View File

@@ -13,8 +13,8 @@ import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import org.eclipse.hawkbit.eventbus.event.DownloadProgressEvent; import org.eclipse.hawkbit.repository.eventbus.event.DownloadProgressEvent;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.ActionStatus;
import org.eclipse.hawkbit.tenancy.TenantAware; import org.eclipse.hawkbit.tenancy.TenantAware;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -59,15 +59,14 @@ public class CacheWriteNotifyTest {
@Test @Test
public void downloadgProgressIsCachedAndEventSent() { public void downloadgProgressIsCachedAndEventSent() {
final long knownStatusId = 1; final long knownStatusId = 1;
final int knownPercentage = 23;
when(cacheManagerMock.getCache(Action.class.getName())).thenReturn(cacheMock); when(cacheManagerMock.getCache(ActionStatus.class.getName())).thenReturn(cacheMock);
when(tenantAwareMock.getCurrentTenant()).thenReturn("default"); when(tenantAwareMock.getCurrentTenant()).thenReturn("default");
underTest.downloadProgressPercent(knownStatusId, knownPercentage); underTest.downloadProgress(knownStatusId, 500L, 100L, 100L);
verify(cacheManagerMock).getCache(eq(Action.class.getName())); verify(cacheManagerMock).getCache(eq(ActionStatus.class.getName()));
verify(cacheMock).put(knownStatusId + "." + CacheKeys.DOWNLOAD_PROGRESS_PERCENT, knownPercentage); verify(cacheMock).put(knownStatusId + "." + CacheKeys.DOWNLOAD_PROGRESS_PERCENT, 20);
verify(eventBusMock).post(any(DownloadProgressEvent.class)); verify(eventBusMock).post(any(DownloadProgressEvent.class));
} }

View File

@@ -37,6 +37,8 @@ import ru.yandex.qatools.allure.annotations.Stories;
@Features("Component Tests - Repository") @Features("Component Tests - Repository")
@Stories("RSQL filter target") @Stories("RSQL filter target")
public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest { public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
private static final long LAST_TARGET_QUERY = 10000;
private static final long LAST_TARGET_QUERY_SMALLER = 1000;
@Before @Before
public void seuptBeforeTest() { public void seuptBeforeTest() {
@@ -48,14 +50,16 @@ public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
final TargetInfo targetInfo = target.getTargetInfo(); final TargetInfo targetInfo = target.getTargetInfo();
targetInfo.getControllerAttributes().put("revision", "1.1"); targetInfo.getControllerAttributes().put("revision", "1.1");
((JpaTargetInfo) target.getTargetInfo()).setUpdateStatus(TargetUpdateStatus.PENDING); ((JpaTargetInfo) target.getTargetInfo()).setUpdateStatus(TargetUpdateStatus.PENDING);
((JpaTargetInfo) target.getTargetInfo()).setLastTargetQuery(LAST_TARGET_QUERY);
targetManagement.createTarget(target); targetManagement.createTarget(target);
final JpaTarget target2 = new JpaTarget("targetId1234"); final JpaTarget target2 = new JpaTarget("targetId1234");
target2.setDescription("targetId1234"); target2.setDescription("targetId1234");
final TargetInfo targetInfo2 = new JpaTargetInfo(target2); final TargetInfo targetInfo2 = target2.getTargetInfo();
targetInfo2.getControllerAttributes().put("revision", "1.2"); targetInfo2.getControllerAttributes().put("revision", "1.2");
target2.setTargetInfo(targetInfo2); ((JpaTargetInfo) target2.getTargetInfo()).setLastTargetQuery(LAST_TARGET_QUERY_SMALLER);
targetManagement.createTarget(target2); targetManagement.createTarget(target2);
targetManagement.createTarget(new JpaTarget("targetId1235")); targetManagement.createTarget(new JpaTarget("targetId1235"));
targetManagement.createTarget(new JpaTarget("targetId1236")); targetManagement.createTarget(new JpaTarget("targetId1236"));
@@ -166,6 +170,17 @@ public class RSQLTargetFieldTest extends AbstractJpaIntegrationTest {
assertRSQLQuery(TargetFields.TAG.name() + "=out=(Tag1,notexist)", 0); assertRSQLQuery(TargetFields.TAG.name() + "=out=(Tag1,notexist)", 0);
} }
@Test
@Description("Test filter target by lastTargetQuery")
public void testFilterByLastTargetQuery() {
assertRSQLQuery(TargetFields.LASTCONTROLLERREQUESTAT.name() + "==" + LAST_TARGET_QUERY, 1);
assertRSQLQuery(TargetFields.LASTCONTROLLERREQUESTAT.name() + "!=" + LAST_TARGET_QUERY, 1);
assertRSQLQuery(TargetFields.LASTCONTROLLERREQUESTAT.name() + "=lt=" + LAST_TARGET_QUERY, 1);
assertRSQLQuery(TargetFields.LASTCONTROLLERREQUESTAT.name() + "=lt=" + LAST_TARGET_QUERY_SMALLER, 0);
assertRSQLQuery(TargetFields.LASTCONTROLLERREQUESTAT.name() + "=gt=" + LAST_TARGET_QUERY_SMALLER, 1);
assertRSQLQuery(TargetFields.LASTCONTROLLERREQUESTAT.name() + "=gt=" + LAST_TARGET_QUERY, 0);
}
private void assertRSQLQuery(final String rsqlParam, final long expcetedTargets) { private void assertRSQLQuery(final String rsqlParam, final long expcetedTargets) {
final Page<Target> findTargetPage = targetManagement.findTargetsAll(rsqlParam, new PageRequest(0, 100)); final Page<Target> findTargetPage = targetManagement.findTargetsAll(rsqlParam, new PageRequest(0, 100));
final long countTargetsAll = findTargetPage.getTotalElements(); final long countTargetsAll = findTargetPage.getTotalElements();

View File

@@ -130,6 +130,14 @@ public class WithSpringAuthorityRule implements TestRule {
SecurityContextHolder.setContext(oldContext); SecurityContextHolder.setContext(oldContext);
} }
/**
* Clears the current security context.
*/
public void clear()
{
SecurityContextHolder.clearContext();
}
/** /**
* @param callable * @param callable
* @return * @return

View File

@@ -23,6 +23,7 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact; import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
import org.eclipse.hawkbit.repository.ControllerManagement; import org.eclipse.hawkbit.repository.ControllerManagement;
import org.eclipse.hawkbit.repository.model.ActionStatus;
import org.eclipse.hawkbit.repository.model.LocalArtifact; import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -87,7 +88,7 @@ public final class RestResourceConversionHelper {
* @param controllerManagement * @param controllerManagement
* to write progress updates to * to write progress updates to
* @param statusId * @param statusId
* of the UpdateActionStatus * of the {@link ActionStatus}
* *
* @return http code * @return http code
* *
@@ -293,6 +294,7 @@ public final class RestResourceConversionHelper {
long toRead = length; long toRead = length;
boolean toContinue = true; boolean toContinue = true;
long shippedSinceLastEvent = 0;
while (toContinue) { while (toContinue) {
final int r = from.read(buf); final int r = from.read(buf);
@@ -304,9 +306,11 @@ public final class RestResourceConversionHelper {
if (toRead > 0) { if (toRead > 0) {
to.write(buf, 0, r); to.write(buf, 0, r);
total += r; total += r;
shippedSinceLastEvent += r;
} else { } else {
to.write(buf, 0, (int) toRead + r); to.write(buf, 0, (int) toRead + r);
total += toRead + r; total += toRead + r;
shippedSinceLastEvent += toRead + r;
toContinue = false; toContinue = false;
} }
@@ -316,7 +320,8 @@ public final class RestResourceConversionHelper {
// every 10 percent an event // every 10 percent an event
if (newPercent == 100 || newPercent > progressPercent + 10) { if (newPercent == 100 || newPercent > progressPercent + 10) {
progressPercent = newPercent; progressPercent = newPercent;
controllerManagement.downloadProgressPercent(statusId, progressPercent); controllerManagement.downloadProgress(statusId, length, shippedSinceLastEvent, total);
shippedSinceLastEvent = 0;
} }
} }
} }

View File

@@ -224,8 +224,10 @@ public final class SpPermission {
/* /*
* Spring security eval expressions. * Spring security eval expressions.
*/ */
private static final String HAS_AUTH_PREFIX = "hasAuthority('"; private static final String BRACKET_OPEN = "(";
private static final String HAS_AUTH_SUFFIX = "')"; private static final String BRACKET_CLOSE = ")";
private static final String HAS_AUTH_PREFIX = "hasAuthority" + BRACKET_OPEN + "'";
private static final String HAS_AUTH_SUFFIX = "'" + BRACKET_CLOSE;
private static final String HAS_AUTH_AND = " and "; private static final String HAS_AUTH_AND = " and ";
/** /**
@@ -257,99 +259,6 @@ public final class SpPermission {
*/ */
public static final String HAS_AUTH_OR = " or "; public static final String HAS_AUTH_OR = " or ";
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#UPDATE_TARGET}.
*/
public static final String HAS_AUTH_UPDATE_TARGET = HAS_AUTH_PREFIX + UPDATE_TARGET + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#SYSTEM_ADMIN}.
*/
public static final String HAS_AUTH_SYSTEM_ADMIN = HAS_AUTH_PREFIX + SYSTEM_ADMIN + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_TARGET}.
*/
public static final String HAS_AUTH_READ_TARGET = HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#CREATE_TARGET}.
*/
public static final String HAS_AUTH_CREATE_TARGET = HAS_AUTH_PREFIX + CREATE_TARGET + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#DELETE_TARGET}.
*/
public static final String HAS_AUTH_DELETE_TARGET = HAS_AUTH_PREFIX + DELETE_TARGET + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_REPOSITORY} and
* {@link SpPermission#UPDATE_TARGET}.
*/
public static final String HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET = HAS_AUTH_PREFIX + READ_REPOSITORY
+ HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + UPDATE_TARGET + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#CREATE_REPOSITORY}.
*/
public static final String HAS_AUTH_CREATE_REPOSITORY = HAS_AUTH_PREFIX + CREATE_REPOSITORY + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#DELETE_REPOSITORY}.
*/
public static final String HAS_AUTH_DELETE_REPOSITORY = HAS_AUTH_PREFIX + DELETE_REPOSITORY + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_REPOSITORY}.
*/
public static final String HAS_AUTH_READ_REPOSITORY = HAS_AUTH_PREFIX + READ_REPOSITORY + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#UPDATE_REPOSITORY}.
*/
public static final String HAS_AUTH_UPDATE_REPOSITORY = HAS_AUTH_PREFIX + UPDATE_REPOSITORY + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_REPOSITORY} and
* {@link SpPermission#READ_TARGET}.
*/
public static final String HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET = HAS_AUTH_PREFIX + READ_REPOSITORY
+ HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#DOWNLOAD_REPOSITORY_ARTIFACT}.
*/
public static final String HAS_AUTH_DOWNLOAD_ARTIFACT = HAS_AUTH_PREFIX + DOWNLOAD_REPOSITORY_ARTIFACT
+ HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAnyRole expression to check if the spring
* context contains the anoynmous role or the controller specific role
* {@link SpPermission#CONTROLLER_ROLE}.
*/
public static final String IS_CONTROLLER = "hasAnyRole('" + CONTROLLER_ROLE_ANONYMOUS + "', '" + CONTROLLER_ROLE
+ "')";
/**
* Spring security eval hasAuthority expression to check if the spring
* context contains the role to allow controllers to download specific
* role {@link SpPermission#CONTROLLER_DOWNLOAD_ROLE}.
*/
public static final String HAS_CONTROLLER_DOWNLOAD = HAS_AUTH_PREFIX + CONTROLLER_DOWNLOAD_ROLE
+ HAS_AUTH_SUFFIX;
/** /**
* Spring security eval hasAnyRole expression to check if the spring * Spring security eval hasAnyRole expression to check if the spring
* context contains system code role * context contains system code role
@@ -359,47 +268,168 @@ public final class SpPermission {
/** /**
* Spring security eval hasAuthority expression to check if spring * Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#CREATE_REPOSITORY} and * context contains {@link SpPermission#UPDATE_TARGET} or
* {@link SpPermission#CREATE_TARGET}. * {@link #IS_SYSTEM_CODE}.
*/ */
public static final String HAS_AUTH_CREATE_REPOSITORY_AND_CREATE_TARGET = HAS_AUTH_PREFIX + CREATE_REPOSITORY public static final String HAS_AUTH_UPDATE_TARGET = HAS_AUTH_PREFIX + UPDATE_TARGET + HAS_AUTH_SUFFIX
+ HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + CREATE_TARGET + HAS_AUTH_SUFFIX; + HAS_AUTH_OR + IS_SYSTEM_CODE;
/** /**
* Spring security eval hasAuthority expression to check if spring * Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#ROLLOUT_MANAGEMENT} * context contains {@link SpPermission#SYSTEM_ADMIN} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_SYSTEM_ADMIN = HAS_AUTH_PREFIX + SYSTEM_ADMIN + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_TARGET} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_READ_TARGET = HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX + HAS_AUTH_OR
+ IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#CREATE_TARGET} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_CREATE_TARGET = HAS_AUTH_PREFIX + CREATE_TARGET + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#DELETE_TARGET} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_DELETE_TARGET = HAS_AUTH_PREFIX + DELETE_TARGET + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_REPOSITORY} and
* {@link SpPermission#UPDATE_TARGET} or {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET = BRACKET_OPEN + HAS_AUTH_PREFIX
+ READ_REPOSITORY + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + UPDATE_TARGET + HAS_AUTH_SUFFIX
+ BRACKET_CLOSE + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#CREATE_REPOSITORY} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_CREATE_REPOSITORY = HAS_AUTH_PREFIX + CREATE_REPOSITORY + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#DELETE_REPOSITORY} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_DELETE_REPOSITORY = HAS_AUTH_PREFIX + DELETE_REPOSITORY + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_REPOSITORY} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_READ_REPOSITORY = HAS_AUTH_PREFIX + READ_REPOSITORY + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#UPDATE_REPOSITORY} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_UPDATE_REPOSITORY = HAS_AUTH_PREFIX + UPDATE_REPOSITORY + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#READ_REPOSITORY} and
* {@link SpPermission#READ_TARGET} or {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET = BRACKET_OPEN + HAS_AUTH_PREFIX
+ READ_REPOSITORY + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX
+ BRACKET_CLOSE + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#DOWNLOAD_REPOSITORY_ARTIFACT} or
* {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_DOWNLOAD_ARTIFACT = HAS_AUTH_PREFIX + DOWNLOAD_REPOSITORY_ARTIFACT
+ HAS_AUTH_SUFFIX + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAnyRole expression to check if the spring
* context contains the anoynmous role or the controller specific role
* {@link SpringEvalExpressions#CONTROLLER_ROLE}.
*/
public static final String IS_CONTROLLER = "hasAnyRole('" + CONTROLLER_ROLE_ANONYMOUS + "', '" + CONTROLLER_ROLE
+ "')";
/**
* Spring security eval hasAuthority expression to check if the spring
* context contains the role to allow controllers to download specific
* role {@link SpringEvalExpressions#CONTROLLER_DOWNLOAD_ROLE}
*/
public static final String HAS_CONTROLLER_DOWNLOAD = HAS_AUTH_PREFIX + CONTROLLER_DOWNLOAD_ROLE
+ HAS_AUTH_SUFFIX;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#CREATE_REPOSITORY} and
* {@link SpPermission#CREATE_TARGET} or {@link #IS_SYSTEM_CODE}.
*/
public static final String HAS_AUTH_CREATE_REPOSITORY_AND_CREATE_TARGET = BRACKET_OPEN + HAS_AUTH_PREFIX
+ CREATE_REPOSITORY + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + CREATE_TARGET + HAS_AUTH_SUFFIX
+ BRACKET_CLOSE + HAS_AUTH_OR + IS_SYSTEM_CODE;
/**
* Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#ROLLOUT_MANAGEMENT} or
* {@link #IS_SYSTEM_CODE}.
*/ */
public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_READ = HAS_AUTH_PREFIX + ROLLOUT_MANAGEMENT public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_READ = HAS_AUTH_PREFIX + ROLLOUT_MANAGEMENT
+ HAS_AUTH_SUFFIX; + HAS_AUTH_SUFFIX + HAS_AUTH_OR + IS_SYSTEM_CODE;
/** /**
* Spring security eval hasAuthority expression to check if spring * Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#ROLLOUT_MANAGEMENT} and * context contains {@link SpPermission#ROLLOUT_MANAGEMENT} and
* {@link SpPermission#READ_TARGET} * {@link SpPermission#READ_TARGET} or {@link #IS_SYSTEM_CODE}.
*/ */
public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_READ_AND_TARGET_READ = HAS_AUTH_PREFIX public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_READ_AND_TARGET_READ = BRACKET_OPEN + HAS_AUTH_PREFIX
+ ROLLOUT_MANAGEMENT + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX; + ROLLOUT_MANAGEMENT + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX
+ BRACKET_CLOSE + HAS_AUTH_OR + IS_SYSTEM_CODE;
/** /**
* Spring security eval hasAuthority expression to check if spring * Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#ROLLOUT_MANAGEMENT} and * context contains {@link SpPermission#ROLLOUT_MANAGEMENT} and
* {@link SpPermission#UPDATE_TARGET}. * {@link SpPermission#UPDATE_TARGET} or {@link #IS_SYSTEM_CODE}.
*/ */
public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE = HAS_AUTH_PREFIX + ROLLOUT_MANAGEMENT public static final String HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE = BRACKET_OPEN + HAS_AUTH_PREFIX
+ HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + UPDATE_TARGET + HAS_AUTH_SUFFIX; + ROLLOUT_MANAGEMENT + HAS_AUTH_SUFFIX + HAS_AUTH_AND + HAS_AUTH_PREFIX + UPDATE_TARGET
+ HAS_AUTH_SUFFIX + BRACKET_CLOSE + HAS_AUTH_OR + IS_SYSTEM_CODE;
/** /**
* Spring security eval hasAuthority expression to check if spring * Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#TENANT_CONFIGURATION} * context contains {@link SpPermission#TENANT_CONFIGURATION} or
* {@link #IS_SYSTEM_CODE}.
*/ */
public static final String HAS_AUTH_TENANT_CONFIGURATION = HAS_AUTH_PREFIX + TENANT_CONFIGURATION public static final String HAS_AUTH_TENANT_CONFIGURATION = HAS_AUTH_PREFIX + TENANT_CONFIGURATION
+ HAS_AUTH_SUFFIX; + HAS_AUTH_SUFFIX + HAS_AUTH_OR + IS_SYSTEM_CODE;
/** /**
* Spring security eval hasAuthority expression to check if spring * Spring security eval hasAuthority expression to check if spring
* context contains {@link SpPermission#SYSTEM_MONITOR} * context contains {@link SpPermission#SYSTEM_MONITOR} or
* {@link #IS_SYSTEM_CODE}.
*/ */
public static final String HAS_AUTH_SYSTEM_MONITOR = HAS_AUTH_PREFIX + SYSTEM_MONITOR + HAS_AUTH_SUFFIX; public static final String HAS_AUTH_SYSTEM_MONITOR = HAS_AUTH_PREFIX + SYSTEM_MONITOR + HAS_AUTH_SUFFIX
+ HAS_AUTH_OR + IS_SYSTEM_CODE;
private SpringEvalExpressions() { private SpringEvalExpressions() {
// utility class // utility class

View File

@@ -9,6 +9,7 @@
package org.eclipse.hawkbit.security; package org.eclipse.hawkbit.security;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails; import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
import org.eclipse.hawkbit.tenancy.TenantAware; import org.eclipse.hawkbit.tenancy.TenantAware;
@@ -80,32 +81,37 @@ public class SecurityContextTenantAware implements TenantAware {
@Override @Override
public boolean equals(final Object another) { public boolean equals(final Object another) {
if (delegate != null) {
return delegate.equals(another); return delegate.equals(another);
} else if (another == null) {
return true;
}
return false;
} }
@Override @Override
public String toString() { public String toString() {
return delegate.toString(); return (delegate != null) ? delegate.toString() : null;
} }
@Override @Override
public int hashCode() { public int hashCode() {
return delegate.hashCode(); return (delegate != null) ? delegate.hashCode() : -1;
} }
@Override @Override
public String getName() { public String getName() {
return delegate.getName(); return (delegate != null) ? delegate.getName() : null;
} }
@Override @Override
public Collection<? extends GrantedAuthority> getAuthorities() { public Collection<? extends GrantedAuthority> getAuthorities() {
return delegate.getAuthorities(); return (delegate != null) ? delegate.getAuthorities() : Collections.emptyList();
} }
@Override @Override
public Object getCredentials() { public Object getCredentials() {
return delegate.getCredentials(); return (delegate != null) ? delegate.getCredentials() : null;
} }
@Override @Override
@@ -115,16 +121,19 @@ public class SecurityContextTenantAware implements TenantAware {
@Override @Override
public Object getPrincipal() { public Object getPrincipal() {
return delegate.getPrincipal(); return (delegate != null) ? delegate.getPrincipal() : null;
} }
@Override @Override
public boolean isAuthenticated() { public boolean isAuthenticated() {
return delegate.isAuthenticated(); return (delegate != null) ? delegate.isAuthenticated() : true;
} }
@Override @Override
public void setAuthenticated(final boolean isAuthenticated) throws IllegalArgumentException { public void setAuthenticated(final boolean isAuthenticated) {
if (delegate == null) {
return;
}
delegate.setAuthenticated(isAuthenticated); delegate.setAuthenticated(isAuthenticated);
} }
} }

View File

@@ -60,6 +60,9 @@ public class SystemSecurityContext {
* The security context will be switched to the system code and back after * The security context will be switched to the system code and back after
* the callable is called. * the callable is called.
* *
* The system code is executed for a current tenant by using the
* {@link TenantAware#getCurrentTenant()}.
*
* @param callable * @param callable
* the callable to call within the system security context * the callable to call within the system security context
* @return the return value of the {@link Callable#call()} method. * @return the return value of the {@link Callable#call()} method.
@@ -67,12 +70,36 @@ public class SystemSecurityContext {
// Exception squid:S2221 - Callable declares Exception // Exception squid:S2221 - Callable declares Exception
@SuppressWarnings("squid:S2221") @SuppressWarnings("squid:S2221")
public <T> T runAsSystem(final Callable<T> callable) { public <T> T runAsSystem(final Callable<T> callable) {
return runAsSystemAsTenant(callable, tenantAware.getCurrentTenant());
}
/**
* Runs a given {@link Callable} within a system security context, which is
* permitted to call secured system code. Often the system needs to call
* secured methods by it's own without relying on the current security
* context e.g. if the current security context does not contain the
* necessary permission it's necessary to execute code as system code to
* execute necessary methods and functionality.
*
* The security context will be switched to the system code and back after
* the callable is called.
*
* The system code is executed for a specific given tenant by using the
* {@link TenantAware}.
*
* @param callable
* the callable to call within the system security context
* @param tenant
* the tenant to act as system code
* @return the return value of the {@link Callable#call()} method.
*/
public <T> T runAsSystemAsTenant(final Callable<T> callable, final String tenant) {
final SecurityContext oldContext = SecurityContextHolder.getContext(); final SecurityContext oldContext = SecurityContextHolder.getContext();
try { try {
logger.debug("entering system code execution"); logger.debug("entering system code execution");
return tenantAware.runAsTenant(tenantAware.getCurrentTenant(), () -> { return tenantAware.runAsTenant(tenant, () -> {
try { try {
setSystemContext(oldContext); setSystemContext(SecurityContextHolder.getContext());
return callable.call(); return callable.call();
} catch (final Exception e) { } catch (final Exception e) {
throw Throwables.propagate(e); throw Throwables.propagate(e);
@@ -100,6 +127,13 @@ public class SystemSecurityContext {
SecurityContextHolder.setContext(securityContextImpl); SecurityContextHolder.setContext(securityContextImpl);
} }
/**
* An implementation of the Spring's {@link Authentication} object which is
* used within a system security code block and wraps the original
* authentication object. The wrapped object contains the necessary
* {@link SpringEvalExpressions#SYSTEM_ROLE} which is allowed to execute all
* secured methods.
*/
public static class SystemCodeAuthentication implements Authentication { public static class SystemCodeAuthentication implements Authentication {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@@ -200,6 +200,10 @@
<groupId>org.springframework.security</groupId> <groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId> <artifactId>spring-security-web</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
</dependency>
<dependency> <dependency>
<groupId>com.vaadin</groupId> <groupId>com.vaadin</groupId>

View File

@@ -10,6 +10,8 @@ package org.eclipse.hawkbit.ui.artifacts.smtable;
import java.io.Serializable; import java.io.Serializable;
import javax.annotation.PostConstruct;
import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareManagement; import org.eclipse.hawkbit.repository.SoftwareManagement;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
@@ -18,18 +20,17 @@ import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.common.SoftwareModuleTypeBeanQuery; import org.eclipse.hawkbit.ui.common.SoftwareModuleTypeBeanQuery;
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIWindowDecorator;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.I18N; import org.eclipse.hawkbit.ui.utils.I18N;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider; import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions; import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions; import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.UINotification; import org.eclipse.hawkbit.ui.utils.UINotification;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory; import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory;
import org.vaadin.spring.events.EventBus; import org.vaadin.spring.events.EventBus;
import com.vaadin.event.FieldEvents.TextChangeEvent;
import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope; import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.ComboBox; import com.vaadin.ui.ComboBox;
@@ -38,8 +39,6 @@ import com.vaadin.ui.FormLayout;
import com.vaadin.ui.Label; import com.vaadin.ui.Label;
import com.vaadin.ui.TextArea; import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField; import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.Window;
import com.vaadin.ui.themes.ValoTheme; import com.vaadin.ui.themes.ValoTheme;
/** /**
@@ -66,8 +65,6 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
@Autowired @Autowired
private transient EntityFactory entityFactory; private transient EntityFactory entityFactory;
private Label mandatoryLabel;
private TextField nameTextField; private TextField nameTextField;
private TextField versionTextField; private TextField versionTextField;
@@ -80,14 +77,20 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
private CommonDialogWindow window; private CommonDialogWindow window;
private String oldDescriptionValue;
private String oldVendorValue;
private Boolean editSwModule = Boolean.FALSE; private Boolean editSwModule = Boolean.FALSE;
private Long baseSwModuleId; private Long baseSwModuleId;
private FormLayout formLayout;
/**
* Initialize Distribution Add and Edit Window.
*/
@PostConstruct
void init() {
createRequiredComponents();
}
/** /**
* Create window for new software module. * Create window for new software module.
* *
@@ -95,11 +98,7 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
* module. * module.
*/ */
public CommonDialogWindow createAddSoftwareModuleWindow() { public CommonDialogWindow createAddSoftwareModuleWindow() {
return createUpdateSoftwareModuleWindow(null);
editSwModule = Boolean.FALSE;
createRequiredComponents();
createWindow();
return window;
} }
/** /**
@@ -110,17 +109,11 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
* @return reference of {@link com.vaadin.ui.Window} to update software * @return reference of {@link com.vaadin.ui.Window} to update software
* module. * module.
*/ */
public Window createUpdateSoftwareModuleWindow(final Long baseSwModuleId) { public CommonDialogWindow createUpdateSoftwareModuleWindow(final Long baseSwModuleId) {
editSwModule = Boolean.TRUE;
this.baseSwModuleId = baseSwModuleId; this.baseSwModuleId = baseSwModuleId;
createRequiredComponents(); resetComponents();
createWindow();
/* populate selected target values to edit. */
populateValuesOfSwModule(); populateValuesOfSwModule();
nameTextField.setEnabled(false); createWindow();
versionTextField.setEnabled(false);
typeComboBox.setEnabled(false);
return window; return window;
} }
@@ -145,13 +138,6 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
ValoTheme.TEXTAREA_TINY, false, null, i18n.get("textfield.description"), ValoTheme.TEXTAREA_TINY, false, null, i18n.get("textfield.description"),
SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH); SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
descTextArea.setId(SPUIComponentIdProvider.ADD_SW_MODULE_DESCRIPTION); descTextArea.setId(SPUIComponentIdProvider.ADD_SW_MODULE_DESCRIPTION);
addDescriptionTextChangeListener();
addVendorTextChangeListener();
/* Label for mandatory symbol */
mandatoryLabel = new Label(i18n.get("label.mandatory.field"));
mandatoryLabel.setStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR);
mandatoryLabel.addStyleName(ValoTheme.LABEL_SMALL);
typeComboBox = SPUIComponentProvider.getComboBox(i18n.get("upload.swmodule.type"), "", "", null, null, true, typeComboBox = SPUIComponentProvider.getComboBox(i18n.get("upload.swmodule.type"), "", "", null, null, true,
null, i18n.get("upload.swmodule.type")); null, i18n.get("upload.swmodule.type"));
@@ -159,46 +145,34 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
typeComboBox.setStyleName(SPUIDefinitions.COMBO_BOX_SPECIFIC_STYLE + " " + ValoTheme.COMBOBOX_TINY); typeComboBox.setStyleName(SPUIDefinitions.COMBO_BOX_SPECIFIC_STYLE + " " + ValoTheme.COMBOBOX_TINY);
typeComboBox.setNewItemsAllowed(Boolean.FALSE); typeComboBox.setNewItemsAllowed(Boolean.FALSE);
typeComboBox.setImmediate(Boolean.TRUE); typeComboBox.setImmediate(Boolean.TRUE);
populateTypeNameCombo(); populateTypeNameCombo();
resetOldValues();
} }
/**
*
*/
private void populateTypeNameCombo() { private void populateTypeNameCombo() {
typeComboBox.setContainerDataSource(HawkbitCommonUtil.createLazyQueryContainer( typeComboBox.setContainerDataSource(HawkbitCommonUtil.createLazyQueryContainer(
new BeanQueryFactory<SoftwareModuleTypeBeanQuery>(SoftwareModuleTypeBeanQuery.class))); new BeanQueryFactory<SoftwareModuleTypeBeanQuery>(SoftwareModuleTypeBeanQuery.class)));
typeComboBox.setItemCaptionPropertyId(SPUILabelDefinitions.VAR_NAME); typeComboBox.setItemCaptionPropertyId(SPUILabelDefinitions.VAR_NAME);
} }
private void resetOldValues() { private void resetComponents() {
oldDescriptionValue = null;
oldVendorValue = null; vendorTextField.clear();
nameTextField.clear();
versionTextField.clear();
descTextArea.clear();
typeComboBox.clear();
editSwModule = Boolean.FALSE;
} }
/**
* Build the window content and get an instance of customDialogWindow
*
*/
private void createWindow() { private void createWindow() {
final Label madatoryStarLabel = new Label("*"); final Label madatoryStarLabel = new Label("*");
madatoryStarLabel.setStyleName("v-caption v-required-field-indicator"); madatoryStarLabel.setStyleName("v-caption v-required-field-indicator");
madatoryStarLabel.setWidth(null); madatoryStarLabel.setWidth(null);
/*
* The main layout of the window contains mandatory info, textboxes
* (controller Id, name & description) and action buttons layout
*/
addStyleName("lay-color"); addStyleName("lay-color");
setSizeUndefined(); setSizeUndefined();
final FormLayout formLayout = new FormLayout(); formLayout = new FormLayout();
formLayout.addComponent(mandatoryLabel); formLayout.setCaption(null);
formLayout.addComponent(typeComboBox); formLayout.addComponent(typeComboBox);
formLayout.addComponent(nameTextField); formLayout.addComponent(nameTextField);
formLayout.addComponent(versionTextField); formLayout.addComponent(versionTextField);
@@ -207,24 +181,17 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
setCompositionRoot(formLayout); setCompositionRoot(formLayout);
/* add main layout to the window */ window = SPUIWindowDecorator.getWindow(i18n.get("upload.caption.add.new.swmodule"), null,
window = SPUIComponentProvider.getWindow(i18n.get("upload.caption.add.new.swmodule"), null, SPUIDefinitions.CREATE_UPDATE_WINDOW, this, event -> saveOrUpdate(), null, null, formLayout, i18n);
SPUIDefinitions.CREATE_UPDATE_WINDOW, this, event -> saveOrUpdate(), event -> closeThisWindow(), null);
window.getButtonsLayout().removeStyleName("actionButtonsMargin"); window.getButtonsLayout().removeStyleName("actionButtonsMargin");
nameTextField.focus();
nameTextField.setEnabled(!editSwModule);
versionTextField.setEnabled(!editSwModule);
typeComboBox.setEnabled(!editSwModule);
typeComboBox.focus();
} }
private void addDescriptionTextChangeListener() {
descTextArea.addTextChangeListener(event -> window.setSaveButtonEnabled(hasDescriptionChanged(event)));
}
private void addVendorTextChangeListener() {
vendorTextField.addTextChangeListener(event -> window.setSaveButtonEnabled(hasVendorChanged(event)));
}
/**
* Add new SW module.
*/
private void addNewBaseSoftware() { private void addNewBaseSoftware() {
final String name = HawkbitCommonUtil.trimAndNullIfEmpty(nameTextField.getValue()); final String name = HawkbitCommonUtil.trimAndNullIfEmpty(nameTextField.getValue());
final String version = HawkbitCommonUtil.trimAndNullIfEmpty(versionTextField.getValue()); final String version = HawkbitCommonUtil.trimAndNullIfEmpty(versionTextField.getValue());
@@ -232,10 +199,6 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
final String description = HawkbitCommonUtil.trimAndNullIfEmpty(descTextArea.getValue()); final String description = HawkbitCommonUtil.trimAndNullIfEmpty(descTextArea.getValue());
final String type = typeComboBox.getValue() != null ? typeComboBox.getValue().toString() : null; final String type = typeComboBox.getValue() != null ? typeComboBox.getValue().toString() : null;
if (!mandatoryCheck(name, version, type)) {
return;
}
if (HawkbitCommonUtil.isDuplicate(name, version, type)) { if (HawkbitCommonUtil.isDuplicate(name, version, type)) {
uiNotifcation.displayValidationError( uiNotifcation.displayValidationError(
i18n.get("message.duplicate.softwaremodule", new Object[] { name, version })); i18n.get("message.duplicate.softwaremodule", new Object[] { name, version }));
@@ -248,8 +211,6 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
new Object[] { newBaseSoftwareModule.getName() + ":" + newBaseSoftwareModule.getVersion() })); new Object[] { newBaseSoftwareModule.getName() + ":" + newBaseSoftwareModule.getVersion() }));
eventBus.publish(this, new SoftwareModuleEvent(BaseEntityEventType.NEW_ENTITY, newBaseSoftwareModule)); eventBus.publish(this, new SoftwareModuleEvent(BaseEntityEventType.NEW_ENTITY, newBaseSoftwareModule));
} }
// close the window
closeThisWindow();
} }
} }
@@ -269,13 +230,16 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
eventBus.publish(this, new SoftwareModuleEvent(BaseEntityEventType.UPDATED_ENTITY, newSWModule)); eventBus.publish(this, new SoftwareModuleEvent(BaseEntityEventType.UPDATED_ENTITY, newSWModule));
} }
closeThisWindow();
} }
/** /**
* fill the data of a softwareModule in the content of the window * fill the data of a softwareModule in the content of the window
*/ */
private void populateValuesOfSwModule() { private void populateValuesOfSwModule() {
if (baseSwModuleId == null) {
return;
}
editSwModule = Boolean.TRUE;
final SoftwareModule swModle = softwareManagement.findSoftwareModuleById(baseSwModuleId); final SoftwareModule swModle = softwareManagement.findSoftwareModuleById(baseSwModuleId);
nameTextField.setValue(swModle.getName()); nameTextField.setValue(swModle.getName());
versionTextField.setValue(swModle.getVersion()); versionTextField.setValue(swModle.getVersion());
@@ -283,49 +247,10 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
: HawkbitCommonUtil.trimAndNullIfEmpty(swModle.getVendor())); : HawkbitCommonUtil.trimAndNullIfEmpty(swModle.getVendor()));
descTextArea.setValue(swModle.getDescription() == null ? HawkbitCommonUtil.SP_STRING_EMPTY descTextArea.setValue(swModle.getDescription() == null ? HawkbitCommonUtil.SP_STRING_EMPTY
: HawkbitCommonUtil.trimAndNullIfEmpty(swModle.getDescription())); : HawkbitCommonUtil.trimAndNullIfEmpty(swModle.getDescription()));
oldDescriptionValue = descTextArea.getValue();
oldVendorValue = vendorTextField.getValue();
if (swModle.getType().isDeleted()) { if (swModle.getType().isDeleted()) {
typeComboBox.addItem(swModle.getType().getName()); typeComboBox.addItem(swModle.getType().getName());
} }
typeComboBox.setValue(swModle.getType().getName()); typeComboBox.setValue(swModle.getType().getName());
window.setSaveButtonEnabled(Boolean.FALSE);
}
/**
* Method to close window.
*/
private void closeThisWindow() {
window.close();
UI.getCurrent().removeWindow(window);
}
/**
* Validation check - Mandatory.
*
* @param name
* as String
* @param version
* as version
* @return boolena as flag
*/
private boolean mandatoryCheck(final String name, final String version, final String type) {
boolean isValid = true;
if (name == null || version == null || type == null) {
if (name == null) {
nameTextField.addStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR);
}
if (version == null) {
versionTextField.addStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR);
}
if (type == null) {
typeComboBox.addStyleName(SPUIStyleDefinitions.SP_COMBOFIELD_ERROR);
}
uiNotifcation.displayValidationError(i18n.get("message.mandatory.check"));
isValid = false;
}
return isValid;
} }
private void saveOrUpdate() { private void saveOrUpdate() {
@@ -336,12 +261,8 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
} }
} }
private boolean hasDescriptionChanged(final TextChangeEvent event) { public FormLayout getFormLayout() {
return !(event.getText().equals(oldDescriptionValue) && vendorTextField.getValue().equals(oldVendorValue)); return formLayout;
}
private boolean hasVendorChanged(final TextChangeEvent event) {
return !(event.getText().equals(oldVendorValue) && descTextArea.getValue().equals(oldDescriptionValue));
} }
} }

View File

@@ -8,11 +8,17 @@
*/ */
package org.eclipse.hawkbit.ui.artifacts.smtable; package org.eclipse.hawkbit.ui.artifacts.smtable;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareManagement;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent; import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent;
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState; import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
import org.eclipse.hawkbit.ui.common.detailslayout.AbstractNamedVersionedEntityTableDetailsLayout; import org.eclipse.hawkbit.ui.common.detailslayout.AbstractNamedVersionedEntityTableDetailsLayout;
import org.eclipse.hawkbit.ui.common.detailslayout.SoftwareModuleMetadatadetailslayout;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.distributions.event.MetadataEvent;
import org.eclipse.hawkbit.ui.distributions.smtable.SwMetadataPopupLayout;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider; import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -45,6 +51,44 @@ public class SoftwareModuleDetails extends AbstractNamedVersionedEntityTableDeta
@Autowired @Autowired
private ArtifactUploadState artifactUploadState; private ArtifactUploadState artifactUploadState;
@Autowired
private transient SoftwareManagement softwareManagement;
@Autowired
private SwMetadataPopupLayout swMetadataPopupLayout;
@Autowired
private EntityFactory entityFactory;
private SoftwareModuleMetadatadetailslayout swmMetadataTable;
/**
* softwareLayout Initialize the component.
*/
@Override
protected void init() {
swmMetadataTable = new SoftwareModuleMetadatadetailslayout();
swmMetadataTable.init(getI18n(), getPermissionChecker(),softwareManagement,swMetadataPopupLayout,entityFactory);
super.init();
}
@EventBusListenerMethod(scope = EventScope.SESSION)
void onEvent(final MetadataEvent event) {
UI.getCurrent()
.access(() -> {
SoftwareModuleMetadata softwareModuleMetadata = event.getSoftwareModuleMetadata();
if (softwareModuleMetadata != null
&& isSoftwareModuleSelected(softwareModuleMetadata.getSoftwareModule())) {
if (event.getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.CREATE_SOFTWARE_MODULE_METADATA) {
swmMetadataTable.createMetadata(event.getSoftwareModuleMetadata().getKey());
} else if (event.getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.DELETE_SOFTWARE_MODULE_METADATA) {
swmMetadataTable.deleteMetadata(event.getSoftwareModuleMetadata().getKey());
}
}
});
}
@Override @Override
protected String getEditButtonId() { protected String getEditButtonId() {
return SPUIComponentIdProvider.UPLOAD_SW_MODULE_EDIT_BUTTON; return SPUIComponentIdProvider.UPLOAD_SW_MODULE_EDIT_BUTTON;
@@ -55,6 +99,7 @@ public class SoftwareModuleDetails extends AbstractNamedVersionedEntityTableDeta
detailsTab.addTab(createDetailsLayout(), getI18n().get("caption.tab.details"), null); detailsTab.addTab(createDetailsLayout(), getI18n().get("caption.tab.details"), null);
detailsTab.addTab(createDescriptionLayout(), getI18n().get("caption.tab.description"), null); detailsTab.addTab(createDescriptionLayout(), getI18n().get("caption.tab.description"), null);
detailsTab.addTab(createLogLayout(), getI18n().get("caption.logs.tab"), null); detailsTab.addTab(createLogLayout(), getI18n().get("caption.logs.tab"), null);
detailsTab.addTab(swmMetadataTable, getI18n().get("caption.metadata"), null);
} }
@Override @Override
@@ -81,6 +126,8 @@ public class SoftwareModuleDetails extends AbstractNamedVersionedEntityTableDeta
updateSoftwareModuleDetailsLayout(HawkbitCommonUtil.SP_STRING_EMPTY, HawkbitCommonUtil.SP_STRING_EMPTY, updateSoftwareModuleDetailsLayout(HawkbitCommonUtil.SP_STRING_EMPTY, HawkbitCommonUtil.SP_STRING_EMPTY,
maxAssign); maxAssign);
} }
populateMetadataDetails();
} }
private void updateSoftwareModuleDetailsLayout(final String type, final String vendor, final String maxAssign) { private void updateSoftwareModuleDetailsLayout(final String type, final String vendor, final String maxAssign) {
@@ -141,4 +188,38 @@ public class SoftwareModuleDetails extends AbstractNamedVersionedEntityTableDeta
protected String getDetailsHeaderCaptionId() { protected String getDetailsHeaderCaptionId() {
return SPUIComponentIdProvider.TARGET_DETAILS_HEADER_LABEL_ID; return SPUIComponentIdProvider.TARGET_DETAILS_HEADER_LABEL_ID;
} }
@Override
protected void populateMetadataDetails(){
swmMetadataTable.populateSMMetadata(getSelectedBaseEntity());
}
private boolean isSoftwareModuleSelected(SoftwareModule softwareModule) {
final SoftwareModule selectedUploadSWModule = artifactUploadState.getSelectedBaseSoftwareModule().isPresent() ? artifactUploadState
.getSelectedBaseSoftwareModule().get() : null;
return softwareModule != null && selectedUploadSWModule != null
&& selectedUploadSWModule.getName().equals(softwareModule.getName())
&& selectedUploadSWModule.getVersion().equals(softwareModule.getVersion());
}
@Override
protected Boolean isMetadataIconToBeDisplayed() {
return true;
}
@Override
protected String getShowMetadataButtonId() {
SoftwareModule selectedBaseEntity = getSelectedBaseEntity();
return SPUIComponentIdProvider.SW_TABLE_MANAGE_METADATA_ID + "." + selectedBaseEntity.getName() + "."
+ selectedBaseEntity.getVersion();
}
@Override
protected void showMetadata(ClickEvent event) {
SoftwareModule swmodule = softwareManagement.findSoftwareModuleWithDetails(getSelectedBaseEntityId());
/* display the window */
UI.getCurrent().addWindow(swMetadataPopupLayout.getWindow(swmodule,null));
}
} }

View File

@@ -21,10 +21,14 @@ import org.eclipse.hawkbit.ui.artifacts.event.UploadViewAcceptCriteria;
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState; import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
import org.eclipse.hawkbit.ui.common.table.AbstractNamedVersionTable; import org.eclipse.hawkbit.ui.common.table.AbstractNamedVersionTable;
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.distributions.smtable.SwMetadataPopupLayout;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider; import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions; import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions; import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.TableColumn; import org.eclipse.hawkbit.ui.utils.TableColumn;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory; import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory;
@@ -38,13 +42,15 @@ import com.vaadin.data.Item;
import com.vaadin.event.dd.DragAndDropEvent; import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DropHandler; import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.acceptcriteria.AcceptCriterion; import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
import com.vaadin.server.FontAwesome;
import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope; import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.Button;
import com.vaadin.ui.Table;
import com.vaadin.ui.UI; import com.vaadin.ui.UI;
/** /**
* Header of Software module table. * Header of Software module table.
*
*/ */
@SpringComponent @SpringComponent
@ViewScope @ViewScope
@@ -61,6 +67,9 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable<SoftwareModul
@Autowired @Autowired
private UploadViewAcceptCriteria uploadViewAcceptCriteria; private UploadViewAcceptCriteria uploadViewAcceptCriteria;
@Autowired
private SwMetadataPopupLayout swMetadataPopupLayout;
@EventBusListenerMethod(scope = EventScope.SESSION) @EventBusListenerMethod(scope = EventScope.SESSION)
void onEvent(final SMFilterEvent filterEvent) { void onEvent(final SMFilterEvent filterEvent) {
UI.getCurrent().access(() -> { UI.getCurrent().access(() -> {
@@ -179,10 +188,26 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable<SoftwareModul
super.updateEntity(baseEntity, item); super.updateEntity(baseEntity, item);
} }
@Override
protected void addCustomGeneratedColumns() {
addGeneratedColumn(SPUILabelDefinitions.METADATA_ICON, new ColumnGenerator() {
private static final long serialVersionUID = 117186282275044399L;
@Override
public Object generateCell(final Table source, final Object itemId, final Object columnId) {
final String nameVersionStr = getNameAndVerion(itemId);
final Button manageMetaDataBtn = createManageMetadataButton(nameVersionStr);
manageMetaDataBtn.addClickListener(event -> showMetadataDetails((Long) itemId, nameVersionStr));
return manageMetaDataBtn;
}
});
}
@Override @Override
protected List<TableColumn> getTableVisibleColumns() { protected List<TableColumn> getTableVisibleColumns() {
final List<TableColumn> columnList = super.getTableVisibleColumns(); final List<TableColumn> columnList = super.getTableVisibleColumns();
if (!isMaximized()) { if (!isMaximized()) {
columnList.add(new TableColumn(SPUILabelDefinitions.METADATA_ICON, "", 0.1F));
return columnList; return columnList;
} }
columnList.add(new TableColumn(SPUILabelDefinitions.VAR_VENDOR, i18n.get("header.vendor"), 0.1F)); columnList.add(new TableColumn(SPUILabelDefinitions.VAR_VENDOR, i18n.get("header.vendor"), 0.1F));
@@ -212,4 +237,26 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable<SoftwareModul
artifactUploadState.setNoDataAvilableSoftwareModule(!available); artifactUploadState.setNoDataAvilableSoftwareModule(!available);
} }
private Button createManageMetadataButton(String nameVersionStr) {
final Button manageMetadataBtn = SPUIComponentProvider.getButton(
SPUIComponentIdProvider.SW_TABLE_MANAGE_METADATA_ID + "." + nameVersionStr, "", "", null, false,
FontAwesome.LIST_ALT, SPUIButtonStyleSmallNoBorder.class);
manageMetadataBtn.addStyleName(SPUIStyleDefinitions.ARTIFACT_DTLS_ICON);
manageMetadataBtn.setDescription(i18n.get("tooltip.metadata.icon"));
return manageMetadataBtn;
}
private String getNameAndVerion(final Object itemId) {
final Item item = getItem(itemId);
final String name = (String) item.getItemProperty(SPUILabelDefinitions.VAR_NAME).getValue();
final String version = (String) item.getItemProperty(SPUILabelDefinitions.VAR_VERSION).getValue();
return name + "." + version;
}
private void showMetadataDetails(Long itemId, String nameVersionStr) {
SoftwareModule swmodule = softwareManagement.findSoftwareModuleWithDetails(itemId);
/* display the window */
UI.getCurrent().addWindow(swMetadataPopupLayout.getWindow(swmodule,null));
}
} }

View File

@@ -11,13 +11,11 @@ package org.eclipse.hawkbit.ui.artifacts.smtype;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareManagement; import org.eclipse.hawkbit.repository.SoftwareManagement;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent; import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent.SoftwareModuleTypeEnum; import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent.SoftwareModuleTypeEnum;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerConstants;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper; import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper;
import org.eclipse.hawkbit.ui.common.SoftwareModuleTypeBeanQuery; import org.eclipse.hawkbit.ui.common.SoftwareModuleTypeBeanQuery;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
@@ -34,12 +32,10 @@ import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.shared.ui.colorpicker.Color; import com.vaadin.shared.ui.colorpicker.Color;
import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope; import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Label; import com.vaadin.ui.Label;
import com.vaadin.ui.OptionGroup; import com.vaadin.ui.OptionGroup;
import com.vaadin.ui.components.colorpicker.ColorChangeListener; import com.vaadin.ui.components.colorpicker.ColorChangeListener;
import com.vaadin.ui.components.colorpicker.ColorSelector;
import com.vaadin.ui.themes.ValoTheme; import com.vaadin.ui.themes.ValoTheme;
/** /**
@@ -48,8 +44,7 @@ import com.vaadin.ui.themes.ValoTheme;
*/ */
@SpringComponent @SpringComponent
@ViewScope @ViewScope
public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout {
implements ColorChangeListener, ColorSelector {
private static final long serialVersionUID = -5169398523815919367L; private static final long serialVersionUID = -5169398523815919367L;
private static final Logger LOG = LoggerFactory.getLogger(CreateUpdateSoftwareTypeLayout.class); private static final Logger LOG = LoggerFactory.getLogger(CreateUpdateSoftwareTypeLayout.class);
@@ -69,7 +64,7 @@ public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout
@Override @Override
protected void addListeners() { protected void addListeners() {
super.addListeners(); super.addListeners();
optiongroup.addValueChangeListener(this::createOptionValueChanged); optiongroup.addValueChangeListener(this::optionValueChanged);
} }
@Override @Override
@@ -95,7 +90,6 @@ public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout
tagDesc = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "", tagDesc = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "",
ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TYPE_DESC, false, "", ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TYPE_DESC, false, "",
i18n.get("textfield.description"), SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH); i18n.get("textfield.description"), SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
tagDesc.setId(SPUIDefinitions.NEW_SOFTWARE_TYPE_DESC); tagDesc.setId(SPUIDefinitions.NEW_SOFTWARE_TYPE_DESC);
tagDesc.setImmediate(true); tagDesc.setImmediate(true);
tagDesc.setNullRepresentation(""); tagDesc.setNullRepresentation("");
@@ -113,10 +107,8 @@ public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout
} }
@Override @Override
public void createWindow() { protected String getWindowCaption() {
reset(); return i18n.get("caption.add.type");
window = SPUIComponentProvider.getWindow(i18n.get("caption.add.type"), null,
SPUIDefinitions.CREATE_UPDATE_WINDOW, this, this::save, this::discard, null);
} }
/** /**
@@ -126,15 +118,16 @@ public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout
* ValueChangeEvent * ValueChangeEvent
*/ */
@Override @Override
protected void createOptionValueChanged(final ValueChangeEvent event) { protected void optionValueChanged(final ValueChangeEvent event) {
super.createOptionValueChanged(event); super.optionValueChanged(event);
if (updateTypeStr.equals(event.getProperty().getValue())) { if (updateTypeStr.equals(event.getProperty().getValue())) {
assignOptiongroup.setEnabled(false); assignOptiongroup.setEnabled(false);
} else { } else {
assignOptiongroup.setEnabled(true); assignOptiongroup.setEnabled(true);
} }
assignOptiongroup.select(singleAssignStr);
} }
/** /**
@@ -171,12 +164,11 @@ public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout
if (null != selectedTypeTag) { if (null != selectedTypeTag) {
tagDesc.setValue(selectedTypeTag.getDescription()); tagDesc.setValue(selectedTypeTag.getDescription());
typeKey.setValue(selectedTypeTag.getKey()); typeKey.setValue(selectedTypeTag.getKey());
if (selectedTypeTag.getMaxAssignments() == Integer.MAX_VALUE) { if (selectedTypeTag.getMaxAssignments() == 1) {
assignOptiongroup.setValue(multiAssignStr);
} else {
assignOptiongroup.setValue(singleAssignStr); assignOptiongroup.setValue(singleAssignStr);
} else {
assignOptiongroup.setValue(multiAssignStr);
} }
setColorPickerComponentsColor(selectedTypeTag.getColour()); setColorPickerComponentsColor(selectedTypeTag.getColour());
} }
} }
@@ -198,10 +190,6 @@ public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout
@Override @Override
protected void save(final ClickEvent event) { protected void save(final ClickEvent event) {
if (!mandatoryValuesPresent()) {
return;
}
final SoftwareModuleType existingSMTypeByKey = swTypeManagementService final SoftwareModuleType existingSMTypeByKey = swTypeManagementService
.findSoftwareModuleTypeByKey(typeKey.getValue()); .findSoftwareModuleTypeByKey(typeKey.getValue());
final SoftwareModuleType existingSMTypeByName = swTypeManagementService final SoftwareModuleType existingSMTypeByName = swTypeManagementService
@@ -211,7 +199,6 @@ public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout
createNewSWModuleType(); createNewSWModuleType();
} }
} else { } else {
updateSWModuleType(existingSMTypeByName); updateSWModuleType(existingSMTypeByName);
} }
} }
@@ -233,22 +220,14 @@ public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout
SoftwareModuleType newSWType = entityFactory.generateSoftwareModuleType(typeKeyValue, typeNameValue, SoftwareModuleType newSWType = entityFactory.generateSoftwareModuleType(typeKeyValue, typeNameValue,
typeDescValue, assignNumber); typeDescValue, assignNumber);
newSWType.setColour(colorPicked); newSWType.setColour(colorPicked);
if (null != typeDescValue) {
newSWType.setDescription(typeDescValue); newSWType.setDescription(typeDescValue);
}
newSWType.setColour(colorPicked); newSWType.setColour(colorPicked);
newSWType = swTypeManagementService.createSoftwareModuleType(newSWType); newSWType = swTypeManagementService.createSoftwareModuleType(newSWType);
uiNotification.displaySuccess(i18n.get("message.save.success", new Object[] { newSWType.getName() })); uiNotification.displaySuccess(i18n.get("message.save.success", new Object[] { newSWType.getName() }));
closeWindow();
eventBus.publish(this, eventBus.publish(this,
new SoftwareModuleTypeEvent(SoftwareModuleTypeEnum.ADD_SOFTWARE_MODULE_TYPE, newSWType)); new SoftwareModuleTypeEvent(SoftwareModuleTypeEnum.ADD_SOFTWARE_MODULE_TYPE, newSWType));
} else { } else {
uiNotification.displayValidationError(i18n.get("message.error.missing.typenameorkey")); uiNotification.displayValidationError(i18n.get("message.error.missing.typenameorkey"));
} }
} }
@@ -258,51 +237,15 @@ public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout
final String typeDescValue = HawkbitCommonUtil.trimAndNullIfEmpty(tagDesc.getValue()); final String typeDescValue = HawkbitCommonUtil.trimAndNullIfEmpty(tagDesc.getValue());
if (null != typeNameValue) { if (null != typeNameValue) {
existingType.setName(typeNameValue); existingType.setName(typeNameValue);
existingType.setDescription(typeDescValue);
existingType.setDescription(null != typeDescValue ? typeDescValue : null);
existingType.setColour(ColorPickerHelper.getColorPickedString(getColorPickerLayout().getSelPreview())); existingType.setColour(ColorPickerHelper.getColorPickedString(getColorPickerLayout().getSelPreview()));
swTypeManagementService.updateSoftwareModuleType(existingType); swTypeManagementService.updateSoftwareModuleType(existingType);
uiNotification.displaySuccess(i18n.get("message.update.success", new Object[] { existingType.getName() })); uiNotification.displaySuccess(i18n.get("message.update.success", new Object[] { existingType.getName() }));
closeWindow();
eventBus.publish(this, eventBus.publish(this,
new SoftwareModuleTypeEvent(SoftwareModuleTypeEnum.UPDATE_SOFTWARE_MODULE_TYPE, existingType)); new SoftwareModuleTypeEvent(SoftwareModuleTypeEnum.UPDATE_SOFTWARE_MODULE_TYPE, existingType));
} else { } else {
uiNotification.displayValidationError(i18n.get("message.tag.update.mandatory")); uiNotification.displayValidationError(i18n.get("message.tag.update.mandatory"));
} }
}
/**
* Open color picker on click of preview button. Auto select the color based
* on target tag if already selected.
*/
@Override
protected void previewButtonClicked() {
if (!tagPreviewBtnClicked) {
final String selectedOption = (String) optiongroup.getValue();
if (StringUtils.isNotEmpty(selectedOption) && selectedOption.equalsIgnoreCase(updateTypeStr)) {
if (null != tagNameComboBox.getValue()) {
final SoftwareModuleType typeSelected = swTypeManagementService
.findSoftwareModuleTypeByName(tagNameComboBox.getValue().toString());
if (null != typeSelected) {
getColorPickerLayout().setSelectedColor(typeSelected.getColour() != null
? ColorPickerHelper.rgbToColorConverter(typeSelected.getColour())
: ColorPickerHelper.rgbToColorConverter(ColorPickerConstants.DEFAULT_COLOR));
}
} else {
getColorPickerLayout().setSelectedColor(
ColorPickerHelper.rgbToColorConverter(ColorPickerConstants.DEFAULT_COLOR));
}
}
getColorPickerLayout().getSelPreview().setColor(getColorPickerLayout().getSelectedColor());
mainLayout.addComponent(colorPickerLayout, 1, 0);
mainLayout.setComponentAlignment(colorPickerLayout, Alignment.MIDDLE_CENTER);
} else {
mainLayout.removeComponent(colorPickerLayout);
}
tagPreviewBtnClicked = !tagPreviewBtnClicked;
} }
@Override @Override

View File

@@ -13,6 +13,7 @@ import java.util.Set;
import org.eclipse.hawkbit.ui.common.CoordinatesToColor; import org.eclipse.hawkbit.ui.common.CoordinatesToColor;
import org.eclipse.hawkbit.ui.management.tag.SpColorPickerPreview; import org.eclipse.hawkbit.ui.management.tag.SpColorPickerPreview;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
import com.vaadin.shared.ui.colorpicker.Color; import com.vaadin.shared.ui.colorpicker.Color;
import com.vaadin.ui.AbstractColorPicker.Coordinates2Color; import com.vaadin.ui.AbstractColorPicker.Coordinates2Color;
@@ -47,6 +48,7 @@ public class ColorPickerLayout extends GridLayout {
setColumns(2); setColumns(2);
setRows(4); setRows(4);
setId(SPUIComponentIdProvider.COLOR_PICKER_LAYOUT);
init(); init();
@@ -71,6 +73,7 @@ public class ColorPickerLayout extends GridLayout {
colorSelect.setWidth("220px"); colorSelect.setWidth("220px");
redSlider = createRGBSlider("", "red"); redSlider = createRGBSlider("", "red");
redSlider.setId(SPUIComponentIdProvider.COLOR_PICKER_RED_SLIDER);
greenSlider = createRGBSlider("", "green"); greenSlider = createRGBSlider("", "green");
blueSlider = createRGBSlider("", "blue"); blueSlider = createRGBSlider("", "blue");

View File

@@ -0,0 +1,487 @@
/**
* 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.List;
import java.util.Set;
import javax.annotation.PostConstruct;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.MetaData;
import org.eclipse.hawkbit.repository.model.NamedVersionedEntity;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.customrenderers.renderers.HtmlButtonRenderer;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.decorators.SPUIWindowDecorator;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.I18N;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.spring.events.EventBus;
import com.vaadin.data.Item;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.event.FieldEvents.TextChangeEvent;
import com.vaadin.event.SelectionEvent;
import com.vaadin.server.FontAwesome;
import com.vaadin.ui.AbstractTextField.TextChangeEventMode;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Grid.SelectionMode;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.renderers.ClickableRenderer.RendererClickEvent;
import com.vaadin.ui.themes.ValoTheme;
/**
*
* Abstract pop up layout
*
* @param <E>
* E id the entity for which metadata is displayed
* @param <M>
* M is the metadata
*
*/
public abstract class AbstractMetadataPopupLayout<E extends NamedVersionedEntity, M extends MetaData>
extends CustomComponent {
private static final String DELETE_BUTTON = "DELETE_BUTTON";
private static final long serialVersionUID = -1491218218453167613L;
private static final String VALUE = "value";
private static final String KEY = "key";
@Autowired
protected I18N i18n;
@Autowired
private UINotification uiNotification;
@Autowired
protected transient EventBus.SessionEventBus eventBus;
private TextField keyTextField;
private TextArea valueTextArea;
private Button addIcon;
private Grid metaDataGrid;
private Label headerCaption;
private CommonDialogWindow metadataWindow;
private E selectedEntity;
private HorizontalLayout mainLayout;
@PostConstruct
private void init() {
createComponents();
buildLayout();
}
/**
* Returns metadata popup.
*
* @param entity
* entity for which metadata data is displayed
* @param metaData
* metadata to be selected
* @return @link{CommonDialogWindow}
*/
public CommonDialogWindow getWindow(final E entity, final M metaData) {
selectedEntity = entity;
final String nameVersion = HawkbitCommonUtil.getFormattedNameVersion(entity.getName(), entity.getVersion());
metadataWindow = SPUIWindowDecorator.getWindow(getMetadataCaption(nameVersion), null,
SPUIDefinitions.CUSTOM_METADATA_WINDOW, this, event -> onSave(), event -> onCancel(), null, mainLayout,
i18n);
metadataWindow.setId(SPUIComponentIdProvider.METADATA_POPUP_ID);
metadataWindow.setHeight(550, Unit.PIXELS);
metadataWindow.setWidth(800, Unit.PIXELS);
metadataWindow.getMainLayout().setSizeFull();
metadataWindow.getButtonsLayout().setHeight("45px");
setUpDetails(entity.getId(), metaData);
return metadataWindow;
}
public E getSelectedEntity() {
return selectedEntity;
}
public void setSelectedEntity(final E selectedEntity) {
this.selectedEntity = selectedEntity;
}
protected abstract void checkForDuplicate(E entity, String value);
protected abstract M createMetadata(E entity, String key, String value);
protected abstract M updateMetadata(E entity, String key, String value);
protected abstract List<M> getMetadataList();
protected abstract void deleteMetadata(E entity, String key, String value);
protected abstract boolean hasCreatePermission();
protected abstract boolean hasUpdatePermission();
private void createComponents() {
keyTextField = createKeyTextField();
valueTextArea = createValueTextField();
metaDataGrid = createMetadataGrid();
addIcon = createAddIcon();
headerCaption = createHeaderCaption();
}
private void buildLayout() {
final HorizontalLayout headerLayout = new HorizontalLayout();
headerLayout.addStyleName(SPUIStyleDefinitions.WIDGET_TITLE);
headerLayout.setSpacing(false);
headerLayout.setMargin(false);
headerLayout.setSizeFull();
headerLayout.addComponent(headerCaption);
if (hasCreatePermission()) {
headerLayout.addComponents(addIcon);
headerLayout.setComponentAlignment(addIcon, Alignment.MIDDLE_RIGHT);
}
headerLayout.setExpandRatio(headerCaption, 1.0F);
final HorizontalLayout headerWrapperLayout = new HorizontalLayout();
headerWrapperLayout.addStyleName("bordered-layout" + " " + "no-border-bottom" + " " + "metadata-table-margin");
headerWrapperLayout.addComponent(headerLayout);
headerWrapperLayout.setWidth("100%");
headerLayout.setHeight("30px");
final VerticalLayout tableLayout = new VerticalLayout();
tableLayout.setSizeFull();
tableLayout.setHeight("100%");
tableLayout.addComponent(headerWrapperLayout);
tableLayout.addComponent(metaDataGrid);
tableLayout.addStyleName("table-layout");
tableLayout.setExpandRatio(metaDataGrid, 1.0F);
final VerticalLayout metadataFieldsLayout = new VerticalLayout();
metadataFieldsLayout.setSizeFull();
metadataFieldsLayout.setHeight("100%");
metadataFieldsLayout.addComponent(keyTextField);
metadataFieldsLayout.addComponent(valueTextArea);
metadataFieldsLayout.setSpacing(true);
metadataFieldsLayout.setExpandRatio(valueTextArea, 1F);
mainLayout = new HorizontalLayout();
mainLayout.addComponent(tableLayout);
mainLayout.addComponent(metadataFieldsLayout);
mainLayout.setExpandRatio(tableLayout, 0.5F);
mainLayout.setExpandRatio(metadataFieldsLayout, 0.5F);
mainLayout.setSizeFull();
mainLayout.setSpacing(true);
setCompositionRoot(mainLayout);
setSizeFull();
}
private TextField createKeyTextField() {
final TextField keyField = SPUIComponentProvider.getTextField(i18n.get("textfield.key"), "",
ValoTheme.TEXTFIELD_TINY, true, "", i18n.get("textfield.key"), true, 128);
keyField.setId(SPUIComponentIdProvider.METADATA_KEY_FIELD_ID);
keyField.addTextChangeListener(event -> onKeyChange(event));
keyField.setTextChangeEventMode(TextChangeEventMode.EAGER);
keyField.setWidth("100%");
return keyField;
}
private TextArea createValueTextField() {
valueTextArea = SPUIComponentProvider.getTextArea(i18n.get("textfield.value"), null, ValoTheme.TEXTAREA_TINY,
true, null, i18n.get("textfield.value"), 4000);
valueTextArea.setId(SPUIComponentIdProvider.METADATA_VALUE_ID);
valueTextArea.setNullRepresentation("");
valueTextArea.setSizeFull();
valueTextArea.setHeight(100, Unit.PERCENTAGE);
valueTextArea.addTextChangeListener(event -> onValueChange(event));
valueTextArea.setTextChangeEventMode(TextChangeEventMode.EAGER);
return valueTextArea;
}
private Grid createMetadataGrid() {
final Grid metadataGrid = new Grid();
metadataGrid.addStyleName(SPUIStyleDefinitions.METADATA_GRID);
metadataGrid.setImmediate(true);
metadataGrid.setHeight("100%");
metadataGrid.setWidth("100%");
metadataGrid.setId(SPUIComponentIdProvider.METDATA_TABLE_ID);
metadataGrid.setSelectionMode(SelectionMode.SINGLE);
metadataGrid.setColumnReorderingAllowed(true);
metadataGrid.setContainerDataSource(getMetadataContainer());
metadataGrid.getColumn(KEY).setHeaderCaption(i18n.get("header.key"));
metadataGrid.getColumn(VALUE).setHeaderCaption(i18n.get("header.value"));
metadataGrid.getColumn(VALUE).setHidden(true);
metadataGrid.addSelectionListener(event -> onRowClick(event));
metadataGrid.getColumn(DELETE_BUTTON).setHeaderCaption("");
metadataGrid.getColumn(DELETE_BUTTON).setRenderer(new HtmlButtonRenderer(event -> onDelete(event)));
metadataGrid.getColumn(DELETE_BUTTON).setWidth(50);
metadataGrid.getColumn(KEY).setExpandRatio(1);
return metadataGrid;
}
private void onDelete(final RendererClickEvent event) {
final Item item = metaDataGrid.getContainerDataSource().getItem(event.getItemId());
final String key = (String) item.getItemProperty(KEY).getValue();
final String value = (String) item.getItemProperty(VALUE).getValue();
final ConfirmationDialog confirmDialog = new ConfirmationDialog(
i18n.get("caption.metadata.delete.action.confirmbox"), i18n.get("message.confirm.delete.metadata", key),
i18n.get("button.ok"), i18n.get("button.cancel"), ok -> {
if (ok) {
deleteMetadata(getSelectedEntity(), key, value);
uiNotification.displaySuccess(i18n.get("message.metadata.deleted.successfully", key));
final Object selectedRow = metaDataGrid.getSelectedRow();
metaDataGrid.getContainerDataSource().removeItem(event.getItemId());
// force grid to refresh
metaDataGrid.clearSortOrder();
if (!metaDataGrid.getContainerDataSource().getItemIds().isEmpty()) {
if (selectedRow != null) {
if (selectedRow.equals(event.getItemId())) {
metaDataGrid.select(metaDataGrid.getContainerDataSource().getIdByIndex(0));
} else {
metaDataGrid.select(selectedRow);
}
}
} else {
keyTextField.clear();
valueTextArea.clear();
metaDataGrid.select(null);
if (hasCreatePermission()) {
keyTextField.setEnabled(true);
valueTextArea.setEnabled(true);
addIcon.setEnabled(false);
}
}
}
});
UI.getCurrent().addWindow(confirmDialog.getWindow());
confirmDialog.getWindow().bringToFront();
}
private Button createAddIcon() {
addIcon = SPUIComponentProvider.getButton(SPUIComponentIdProvider.METADTA_ADD_ICON_ID, i18n.get("button.save"),
null, null, false, FontAwesome.PLUS, SPUIButtonStyleSmallNoBorder.class);
addIcon.addClickListener(event -> onAdd(event));
return addIcon;
}
private Label createHeaderCaption() {
final Label captionLabel = SPUIComponentProvider.getLabel(i18n.get("caption.metadata"),
SPUILabelDefinitions.SP_WIDGET_CAPTION);
return captionLabel;
}
private IndexedContainer getMetadataContainer() {
final IndexedContainer swcontactContainer = new IndexedContainer();
swcontactContainer.addContainerProperty(KEY, String.class, "");
swcontactContainer.addContainerProperty(VALUE, String.class, "");
swcontactContainer.addContainerProperty(DELETE_BUTTON, String.class, FontAwesome.TRASH_O.getHtml());
return swcontactContainer;
}
private void popualateKeyValue(final Object metadataCompositeKey) {
if (metadataCompositeKey != null) {
final Item item = metaDataGrid.getContainerDataSource().getItem(metadataCompositeKey);
keyTextField.setValue((String) item.getItemProperty(KEY).getValue());
valueTextArea.setValue((String) item.getItemProperty(VALUE).getValue());
keyTextField.setEnabled(false);
if (hasUpdatePermission()) {
valueTextArea.setEnabled(true);
}
}
}
private void populateGrid() {
final List<M> metadataList = getMetadataList();
for (final M metaData : metadataList) {
addItemToGrid(metaData.getKey(), metaData.getValue());
}
}
private void addItemToGrid(final String key, final String value) {
final IndexedContainer metadataContainer = (IndexedContainer) metaDataGrid.getContainerDataSource();
final Item item = metadataContainer.addItem(key);
item.getItemProperty(VALUE).setValue(value);
item.getItemProperty(KEY).setValue(key);
}
private void updateItemInGrid(final String key) {
final IndexedContainer metadataContainer = (IndexedContainer) metaDataGrid.getContainerDataSource();
final Item item = metadataContainer.getItem(key);
item.getItemProperty(VALUE).setValue(valueTextArea.getValue());
}
private void onAdd(final ClickEvent event) {
metaDataGrid.deselect(metaDataGrid.getSelectedRow());
valueTextArea.clear();
keyTextField.clear();
keyTextField.setEnabled(true);
valueTextArea.setEnabled(true);
addIcon.setEnabled(true);
}
private void onSave() {
final String key = keyTextField.getValue();
final String value = valueTextArea.getValue();
if (mandatoryCheck()) {
final E entity = selectedEntity;
if (metaDataGrid.getSelectedRow() == null) {
if (!duplicateCheck(entity)) {
final M metadata = createMetadata(entity, key, value);
uiNotification.displaySuccess(i18n.get("message.metadata.saved", metadata.getKey()));
addItemToGrid(metadata.getKey(), metadata.getValue());
metaDataGrid.scrollToEnd();
metaDataGrid.select(metadata.getKey());
addIcon.setEnabled(true);
metadataWindow.setSaveButtonEnabled(false);
if (!hasUpdatePermission()) {
valueTextArea.setEnabled(false);
}
}
} else {
final M metadata = updateMetadata(entity, key, value);
uiNotification.displaySuccess(i18n.get("message.metadata.updated", metadata.getKey()));
updateItemInGrid(metadata.getKey());
metaDataGrid.select(metadata.getKey());
addIcon.setEnabled(true);
metadataWindow.setSaveButtonEnabled(false);
}
}
}
private boolean mandatoryCheck() {
if (keyTextField.getValue().isEmpty()) {
uiNotification.displayValidationError(i18n.get("message.key.missing"));
return false;
}
if (valueTextArea.getValue().isEmpty()) {
uiNotification.displayValidationError(i18n.get("message.value.missing"));
return false;
}
return true;
}
private boolean duplicateCheck(final E entity) {
try {
checkForDuplicate(entity, keyTextField.getValue());
} catch (final EntityNotFoundException exception) {
return false;
}
uiNotification.displayValidationError(i18n.get("message.metadata.duplicate.check", keyTextField.getValue()));
return true;
}
private String getMetadataCaption(final String nameVersionStr) {
final StringBuilder caption = new StringBuilder();
caption.append(HawkbitCommonUtil.DIV_DESCRIPTION + i18n.get("caption.metadata.popup") + " "
+ HawkbitCommonUtil.getBoldHTMLText(nameVersionStr));
caption.append(HawkbitCommonUtil.DIV_CLOSE);
return caption.toString();
}
private void onCancel() {
metadataWindow.close();
UI.getCurrent().removeWindow(metadataWindow);
}
private void onKeyChange(final TextChangeEvent event) {
if (hasCreatePermission() || hasUpdatePermission()) {
if (!valueTextArea.getValue().isEmpty() && !event.getText().isEmpty()) {
metadataWindow.setSaveButtonEnabled(true);
} else {
metadataWindow.setSaveButtonEnabled(false);
}
}
}
private void onRowClick(final SelectionEvent event) {
final Set<Object> itemsSelected = event.getSelected();
if (!itemsSelected.isEmpty()) {
final Object itemSelected = itemsSelected.stream().findFirst().isPresent()
? itemsSelected.stream().findFirst().get() : null;
popualateKeyValue(itemSelected);
addIcon.setEnabled(true);
} else {
keyTextField.clear();
valueTextArea.clear();
if (hasCreatePermission()) {
keyTextField.setEnabled(true);
valueTextArea.setEnabled(true);
addIcon.setEnabled(false);
} else {
keyTextField.setEnabled(false);
valueTextArea.setEnabled(false);
}
}
metadataWindow.setSaveButtonEnabled(false);
}
private void onValueChange(final TextChangeEvent event) {
if (hasCreatePermission() || hasUpdatePermission()) {
if (!keyTextField.getValue().isEmpty() && !event.getText().isEmpty()) {
metadataWindow.setSaveButtonEnabled(true);
} else {
metadataWindow.setSaveButtonEnabled(false);
}
}
}
private void setUpDetails(final Long swId, final M metaData) {
resetDetails();
if (swId != null) {
metaDataGrid.getContainerDataSource().removeAllItems();
populateGrid();
metaDataGrid.getSelectionModel().reset();
if (!metaDataGrid.getContainerDataSource().getItemIds().isEmpty()) {
if (metaData == null) {
metaDataGrid.select(metaDataGrid.getContainerDataSource().getIdByIndex(0));
} else {
metaDataGrid.select(metaData.getKey());
}
} else if (hasCreatePermission()) {
keyTextField.setEnabled(true);
valueTextArea.setEnabled(true);
addIcon.setEnabled(false);
}
}
}
private void resetDetails() {
keyTextField.clear();
valueTextArea.clear();
keyTextField.setEnabled(false);
valueTextArea.setEnabled(false);
metadataWindow.setSaveButtonEnabled(false);
addIcon.setEnabled(true);
}
}

View File

@@ -10,32 +10,69 @@ package org.eclipse.hawkbit.ui.common;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import org.apache.commons.lang3.StringUtils; import java.io.Serializable;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import java.util.ArrayList;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleBorderWithIcon; import java.util.Collection;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider; import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.hawkbit.ui.artifacts.smtable.SoftwareModuleAddUpdateWindow;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleNoBorderWithIcon;
import org.eclipse.hawkbit.ui.layouts.AbstractCreateUpdateTagLayout;
import org.eclipse.hawkbit.ui.management.targettable.TargetAddUpdateWindowLayout;
import org.eclipse.hawkbit.ui.utils.I18N;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.vaadin.hene.flexibleoptiongroup.FlexibleOptionGroupItemComponent;
import com.google.common.base.Strings;
import com.google.common.collect.Sets;
import com.vaadin.data.Container.ItemSetChangeEvent;
import com.vaadin.data.Container.ItemSetChangeListener;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener; import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.data.Validator;
import com.vaadin.data.validator.NullValidator;
import com.vaadin.event.FieldEvents.TextChangeEvent;
import com.vaadin.event.FieldEvents.TextChangeListener;
import com.vaadin.event.FieldEvents.TextChangeNotifier;
import com.vaadin.server.FontAwesome; import com.vaadin.server.FontAwesome;
import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.AbstractField;
import com.vaadin.ui.AbstractLayout;
import com.vaadin.ui.AbstractOrderedLayout; import com.vaadin.ui.AbstractOrderedLayout;
import com.vaadin.ui.Alignment; import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button; import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickListener; import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.Component; import com.vaadin.ui.Component;
import com.vaadin.ui.Field;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Link; import com.vaadin.ui.Link;
import com.vaadin.ui.Table;
import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window; import com.vaadin.ui.Window;
import com.vaadin.ui.themes.ValoTheme;
/** /**
* *
* Superclass for pop-up-windows including a minimize and close icon in the * Table pop-up-windows including a minimize and close icon in the upper right
* upper right corner and a save and cancel button at the bottom. * corner and a save and cancel button at the bottom. Is not intended to reuse.
* *
*/ */
public class CommonDialogWindow extends Window { public class CommonDialogWindow extends Window implements Serializable {
private static final long serialVersionUID = -1321949234316858703L; private static final long serialVersionUID = 1L;
private final VerticalLayout mainLayout = new VerticalLayout(); private final VerticalLayout mainLayout = new VerticalLayout();
@@ -57,6 +94,14 @@ public class CommonDialogWindow extends Window {
private final ClickListener cancelButtonClickListener; private final ClickListener cancelButtonClickListener;
private final ClickListener close = event -> close();
private final transient Map<Component, Object> orginalValues;
private final List<AbstractField<?>> allComponents;
private final I18N i18n;
/** /**
* Constructor. * Constructor.
* *
@@ -72,38 +117,273 @@ public class CommonDialogWindow extends Window {
* the cancelButtonClickListener * the cancelButtonClickListener
*/ */
public CommonDialogWindow(final String caption, final Component content, final String helpLink, public CommonDialogWindow(final String caption, final Component content, final String helpLink,
final ClickListener saveButtonClickListener, final ClickListener cancelButtonClickListener) { final ClickListener saveButtonClickListener, final ClickListener cancelButtonClickListener,
final AbstractLayout layout, final I18N i18n) {
checkNotNull(saveButtonClickListener); checkNotNull(saveButtonClickListener);
checkNotNull(cancelButtonClickListener);
this.caption = caption; this.caption = caption;
this.content = content; this.content = content;
this.helpLink = helpLink; this.helpLink = helpLink;
this.saveButtonClickListener = saveButtonClickListener; this.saveButtonClickListener = saveButtonClickListener;
this.cancelButtonClickListener = cancelButtonClickListener; this.cancelButtonClickListener = cancelButtonClickListener;
this.orginalValues = new HashMap<>();
this.allComponents = getAllComponents(layout);
this.i18n = i18n;
init(); init();
} }
@Override
public void close() {
super.close();
orginalValues.clear();
removeListeners();
allComponents.clear();
this.saveButton.setEnabled(false);
}
private void removeListeners() {
for (final AbstractField<?> field : allComponents) {
removeTextListener(field);
removeValueChangeListener(field);
removeItemSetChangeistener(field);
}
}
private void removeItemSetChangeistener(final AbstractField<?> field) {
if (!(field instanceof Table)) {
return;
}
for (final Object listener : field.getListeners(ItemSetChangeEvent.class)) {
if (listener instanceof ChangeListener) {
((Table) field).removeItemSetChangeListener((ChangeListener) listener);
}
}
}
private void removeTextListener(final AbstractField<?> field) {
if (!(field instanceof TextChangeNotifier)) {
return;
}
for (final Object listener : field.getListeners(TextChangeEvent.class)) {
if (listener instanceof ChangeListener) {
((TextChangeNotifier) field).removeTextChangeListener((ChangeListener) listener);
}
}
}
private void removeValueChangeListener(final AbstractField<?> field) {
for (final Object listener : field.getListeners(ValueChangeEvent.class)) {
if (listener instanceof ChangeListener) {
field.removeValueChangeListener((ChangeListener) listener);
}
}
}
private final void init() { private final void init() {
if (content instanceof AbstractOrderedLayout) { if (content instanceof AbstractOrderedLayout) {
((AbstractOrderedLayout) content).setSpacing(true); ((AbstractOrderedLayout) content).setSpacing(true);
((AbstractOrderedLayout) content).setMargin(true); ((AbstractOrderedLayout) content).setMargin(true);
} }
if (content instanceof GridLayout) {
addStyleName("marginTop");
}
if (null != content) { if (null != content) {
mainLayout.addComponent(content); mainLayout.addComponent(content);
mainLayout.setExpandRatio(content, 1.0F);
} }
createMandatoryLabel();
final HorizontalLayout buttonLayout = createActionButtonsLayout(); final HorizontalLayout buttonLayout = createActionButtonsLayout();
mainLayout.addComponent(buttonLayout); mainLayout.addComponent(buttonLayout);
mainLayout.setComponentAlignment(buttonLayout, Alignment.TOP_CENTER); mainLayout.setComponentAlignment(buttonLayout, Alignment.TOP_CENTER);
setCaption(caption); setCaption(caption);
setCaptionAsHtml(true);
setContent(mainLayout); setContent(mainLayout);
setResizable(false); setResizable(false);
center(); center();
setModal(true); setModal(true);
addStyleName("fontsize"); addStyleName("fontsize");
setOrginaleValues();
addListeners();
}
/**
* saves the original values in a Map so we can use them for detecting
* changes
*/
public final void setOrginaleValues() {
for (final AbstractField<?> field : allComponents) {
Object value = field.getValue();
if (field instanceof Table) {
value = Sets.newHashSet(((Table) field).getContainerDataSource().getItemIds());
}
orginalValues.put(field, value);
}
saveButton.setEnabled(isSaveButtonEnabledAfterValueChange(null, null));
}
protected void addListeners() {
addComponenetListeners();
addCloseListenerForSaveButton();
addCloseListenerForCancelButton();
}
protected void addCloseListenerForSaveButton() {
saveButton.addClickListener(close);
}
protected void addCloseListenerForCancelButton() {
cancelButton.addClickListener(close);
}
protected void addComponenetListeners() {
for (final AbstractField<?> field : allComponents) {
if (field instanceof TextChangeNotifier) {
((TextChangeNotifier) field).addTextChangeListener(new ChangeListener(field));
}
if (field instanceof Table) {
((Table) field).addItemSetChangeListener(new ChangeListener(field));
} else {
field.addValueChangeListener(new ChangeListener(field));
}
}
}
private boolean isSaveButtonEnabledAfterValueChange(final Component currentChangedComponent,
final Object newValue) {
return isMandatoryFieldNotEmptyAndValid(currentChangedComponent, newValue)
&& isValuesChanged(currentChangedComponent, newValue);
}
private boolean isValuesChanged(final Component currentChangedComponent, final Object newValue) {
for (final AbstractField<?> field : allComponents) {
Object originalValue = orginalValues.get(field);
if (field instanceof CheckBox && originalValue == null) {
originalValue = Boolean.FALSE;
}
final Object currentValue = getCurrentVaue(currentChangedComponent, newValue, field);
if (!isValueEquals(field, originalValue, currentValue)) {
return true;
}
}
return false;
}
private boolean isValueEquals(final AbstractField<?> field, final Object orginalValue, final Object currentValue) {
if (Set.class.equals(field.getType())) {
return CollectionUtils.isEqualCollection(CollectionUtils.emptyIfNull((Collection<?>) orginalValue),
CollectionUtils.emptyIfNull((Collection<?>) currentValue));
}
if (String.class.equals(field.getType())) {
return Objects.equals(Strings.emptyToNull((String) orginalValue),
Strings.emptyToNull((String) currentValue));
}
return Objects.equals(orginalValue, currentValue);
}
private Object getCurrentVaue(final Component currentChangedComponent, final Object newValue,
final AbstractField<?> field) {
Object currentValue = field.getValue();
if (field instanceof Table) {
currentValue = ((Table) field).getContainerDataSource().getItemIds();
}
if (field.equals(currentChangedComponent)) {
currentValue = newValue;
}
return currentValue;
}
private boolean shouldMandatoryLabelShown() {
for (final AbstractField<?> field : allComponents) {
if (field.isRequired()) {
return true;
}
}
return false;
}
private boolean isMandatoryFieldNotEmptyAndValid(final Component currentChangedComponent, final Object newValue) {
boolean valid = true;
final List<AbstractField<?>> requiredComponents = allComponents.stream().filter(field -> field.isRequired())
.collect(Collectors.toList());
requiredComponents.addAll(allComponents.stream().filter(this::hasNullValidator).collect(Collectors.toList()));
for (final AbstractField field : requiredComponents) {
Object value = getCurrentVaue(currentChangedComponent, newValue, field);
if (String.class.equals(field.getType())) {
value = Strings.emptyToNull((String) value);
}
if (Set.class.equals(field.getType())) {
value = emptyToNull((Collection<?>) value);
}
if (value == null) {
return false;
}
// We need to loop through the entire loop for validity testing.
// Otherwise the UI will only mark the
// first field with errors and then stop. If there are several
// fields with errors, this is bad.
field.setValue(value);
if (!field.isValid()) {
valid = false;
}
}
return valid;
}
private static Object emptyToNull(final Collection<?> c) {
return (c == null || c.isEmpty()) ? null : c;
}
private boolean hasNullValidator(final Component component) {
if (component instanceof AbstractField<?>) {
final AbstractField<?> fieldComponent = (AbstractField<?>) component;
for (final Validator validator : fieldComponent.getValidators()) {
if (validator instanceof NullValidator) {
return true;
}
}
}
return false;
}
private List<AbstractField<?>> getAllComponents(final AbstractLayout abstractLayout) {
final List<AbstractField<?>> components = new ArrayList<>();
final Iterator<Component> iterate = abstractLayout.iterator();
while (iterate.hasNext()) {
final Component c = iterate.next();
if (c instanceof AbstractLayout) {
components.addAll(getAllComponents((AbstractLayout) c));
}
if (c instanceof AbstractField) {
components.add((AbstractField<?>) c);
}
if (c instanceof FlexibleOptionGroupItemComponent) {
components.add(((FlexibleOptionGroupItemComponent) c).getOwner());
}
}
return components;
} }
private HorizontalLayout createActionButtonsLayout() { private HorizontalLayout createActionButtonsLayout() {
@@ -111,23 +391,45 @@ public class CommonDialogWindow extends Window {
buttonsLayout = new HorizontalLayout(); buttonsLayout = new HorizontalLayout();
buttonsLayout.setSizeFull(); buttonsLayout.setSizeFull();
buttonsLayout.setSpacing(true); buttonsLayout.setSpacing(true);
buttonsLayout.setSpacing(true);
buttonsLayout.addStyleName("actionButtonsMargin");
createSaveButton(); createSaveButton();
createCancelButton(); createCancelButton();
buttonsLayout.addStyleName("actionButtonsMargin");
addHelpLink(); addHelpLink();
return buttonsLayout; return buttonsLayout;
} }
private void createMandatoryLabel() {
if (!shouldMandatoryLabelShown()) {
return;
}
final Label mandatoryLabel = new Label(i18n.get("label.mandatory.field"));
mandatoryLabel.addStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR + " " + ValoTheme.LABEL_TINY);
if (content instanceof TargetAddUpdateWindowLayout) {
((TargetAddUpdateWindowLayout) content).getFormLayout().addComponent(mandatoryLabel);
} else if (content instanceof SoftwareModuleAddUpdateWindow) {
((SoftwareModuleAddUpdateWindow) content).getFormLayout().addComponent(mandatoryLabel);
} else if (content instanceof AbstractCreateUpdateTagLayout) {
((AbstractCreateUpdateTagLayout) content).getMainLayout().addComponent(mandatoryLabel);
}
mainLayout.addComponent(mandatoryLabel);
}
private void createCancelButton() { private void createCancelButton() {
cancelButton = SPUIComponentProvider.getButton(SPUIComponentIdProvider.CANCEL_BUTTON, "Cancel", "", "", true, cancelButton = SPUIComponentProvider.getButton(SPUIComponentIdProvider.CANCEL_BUTTON, "Cancel", "", "", true,
FontAwesome.TIMES, SPUIButtonStyleBorderWithIcon.class); FontAwesome.TIMES, SPUIButtonStyleNoBorderWithIcon.class);
cancelButton.setSizeUndefined(); cancelButton.setSizeUndefined();
cancelButton.addStyleName("default-color"); cancelButton.addStyleName("default-color");
if (cancelButtonClickListener != null) {
cancelButton.addClickListener(cancelButtonClickListener); cancelButton.addClickListener(cancelButtonClickListener);
}
buttonsLayout.addComponent(cancelButton); buttonsLayout.addComponent(cancelButton);
buttonsLayout.setComponentAlignment(cancelButton, Alignment.MIDDLE_LEFT); buttonsLayout.setComponentAlignment(cancelButton, Alignment.MIDDLE_LEFT);
@@ -136,10 +438,11 @@ public class CommonDialogWindow extends Window {
private void createSaveButton() { private void createSaveButton() {
saveButton = SPUIComponentProvider.getButton(SPUIComponentIdProvider.SAVE_BUTTON, "Save", "", "", true, saveButton = SPUIComponentProvider.getButton(SPUIComponentIdProvider.SAVE_BUTTON, "Save", "", "", true,
FontAwesome.SAVE, SPUIButtonStyleBorderWithIcon.class); FontAwesome.SAVE, SPUIButtonStyleNoBorderWithIcon.class);
saveButton.setSizeUndefined(); saveButton.setSizeUndefined();
saveButton.addStyleName("default-color"); saveButton.addStyleName("default-color");
saveButton.addClickListener(saveButtonClickListener); saveButton.addClickListener(saveButtonClickListener);
saveButton.setEnabled(false);
buttonsLayout.addComponent(saveButton); buttonsLayout.addComponent(saveButton);
buttonsLayout.setComponentAlignment(saveButton, Alignment.MIDDLE_RIGHT); buttonsLayout.setComponentAlignment(saveButton, Alignment.MIDDLE_RIGHT);
buttonsLayout.setExpandRatio(saveButton, 1.0F); buttonsLayout.setExpandRatio(saveButton, 1.0F);
@@ -155,6 +458,58 @@ public class CommonDialogWindow extends Window {
buttonsLayout.setComponentAlignment(helpLinkComponent, Alignment.MIDDLE_RIGHT); buttonsLayout.setComponentAlignment(helpLinkComponent, Alignment.MIDDLE_RIGHT);
} }
public AbstractComponent getButtonsLayout() {
return this.buttonsLayout;
}
private class ChangeListener implements ValueChangeListener, TextChangeListener, ItemSetChangeListener {
private final Field<?> field;
public ChangeListener(final Field<?> field) {
super();
this.field = field;
}
@Override
public void textChange(final TextChangeEvent event) {
saveButton.setEnabled(isSaveButtonEnabledAfterValueChange(field, event.getText()));
}
@Override
public void valueChange(final ValueChangeEvent event) {
saveButton.setEnabled(isSaveButtonEnabledAfterValueChange(field, field.getValue()));
}
@Override
public void containerItemSetChange(final ItemSetChangeEvent event) {
if (!(field instanceof Table)) {
return;
}
final Table table = (Table) field;
saveButton.setEnabled(
isSaveButtonEnabledAfterValueChange(table, table.getContainerDataSource().getItemIds()));
}
}
/**
* Adds the component manually to the allComponents-List and adds a
* ValueChangeListener to it. Necessary in Update Distribution Type as the
* CheckBox concerned is an ItemProperty...
*
* @param component
* AbstractField
*/
public void updateAllComponents(final AbstractField component) {
allComponents.add(component);
component.addValueChangeListener(new ChangeListener(component));
}
public VerticalLayout getMainLayout() {
return mainLayout;
}
public void setSaveButtonEnabled(final boolean enabled) { public void setSaveButtonEnabled(final boolean enabled) {
saveButton.setEnabled(enabled); saveButton.setEnabled(enabled);
} }
@@ -162,9 +517,4 @@ public class CommonDialogWindow extends Window {
public void setCancelButtonEnabled(final boolean enabled) { public void setCancelButtonEnabled(final boolean enabled) {
cancelButton.setEnabled(enabled); cancelButton.setEnabled(enabled);
} }
public HorizontalLayout getButtonsLayout() {
return buttonsLayout;
}
} }

View File

@@ -89,6 +89,7 @@ public class ConfirmationDialog implements Button.ClickListener {
final Button cancelButton = SPUIComponentProvider.getButton(null, cancelLabel, "", null, false, null, final Button cancelButton = SPUIComponentProvider.getButton(null, cancelLabel, "", null, false, null,
SPUIButtonStyleTiny.class); SPUIButtonStyleTiny.class);
cancelButton.addClickListener(this); cancelButton.addClickListener(this);
cancelButton.setId(SPUIComponentIdProvider.CANCEL_BUTTON);
window.setModal(true); window.setModal(true);
window.addStyleName(SPUIStyleDefinitions.CONFIRMBOX_WINDOW_SYLE); window.addStyleName(SPUIStyleDefinitions.CONFIRMBOX_WINDOW_SYLE);
if (this.callback == null) { if (this.callback == null) {

View File

@@ -0,0 +1,33 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.ui.common;
import org.eclipse.hawkbit.ui.utils.I18N;
import com.vaadin.ui.AbstractLayout;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Component;
public class CustomCommonDialogWindow extends CommonDialogWindow {
private static final long serialVersionUID = -4453608850403359992L;
public CustomCommonDialogWindow(final String caption, final Component content, final String helpLink,
final ClickListener saveButtonClickListener, final ClickListener cancelButtonClickListener,
final AbstractLayout layout, final I18N i18n) {
super(caption, content, helpLink, saveButtonClickListener, cancelButtonClickListener, layout, i18n);
}
@Override
protected void addListeners() {
addComponenetListeners();
addCloseListenerForCancelButton();
}
}

View File

@@ -63,6 +63,8 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
private Button editButton; private Button editButton;
private Button manageMetadataBtn;
private TabSheet detailsTab; private TabSheet detailsTab;
private VerticalLayout detailsLayout; private VerticalLayout detailsLayout;
@@ -136,9 +138,15 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
SPUIButtonStyleSmallNoBorder.class); SPUIButtonStyleSmallNoBorder.class);
editButton.setId(getEditButtonId()); editButton.setId(getEditButtonId());
editButton.addClickListener(this::onEdit); editButton.addClickListener(this::onEdit);
editButton.setEnabled(false); editButton.setEnabled(false);
manageMetadataBtn = SPUIComponentProvider.getButton("", "", "", null, false,
FontAwesome.LIST_ALT, SPUIButtonStyleSmallNoBorder.class);
manageMetadataBtn.setId(getEditButtonId());
manageMetadataBtn.setDescription(i18n.get("tooltip.metadata.icon"));
manageMetadataBtn.addClickListener(this::showMetadata);
manageMetadataBtn.setEnabled(false);
detailsTab = SPUIComponentProvider.getDetailsTabSheet(); detailsTab = SPUIComponentProvider.getDetailsTabSheet();
detailsTab.setImmediate(true); detailsTab.setImmediate(true);
detailsTab.setWidth(98, Unit.PERCENTAGE); detailsTab.setWidth(98, Unit.PERCENTAGE);
@@ -156,6 +164,10 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
if (hasEditPermission()) { if (hasEditPermission()) {
nameEditLayout.addComponent(editButton); nameEditLayout.addComponent(editButton);
nameEditLayout.setComponentAlignment(editButton, Alignment.TOP_RIGHT); nameEditLayout.setComponentAlignment(editButton, Alignment.TOP_RIGHT);
if (isMetadataIconToBeDisplayed()) {
nameEditLayout.addComponent(manageMetadataBtn);
nameEditLayout.setComponentAlignment(manageMetadataBtn, Alignment.TOP_RIGHT);
}
} }
nameEditLayout.setExpandRatio(caption, 1.0F); nameEditLayout.setExpandRatio(caption, 1.0F);
nameEditLayout.addStyleName(SPUIStyleDefinitions.WIDGET_TITLE); nameEditLayout.addStyleName(SPUIStyleDefinitions.WIDGET_TITLE);
@@ -201,6 +213,7 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
private void populateData(final T selectedBaseEntity) { private void populateData(final T selectedBaseEntity) {
this.selectedBaseEntity = selectedBaseEntity; this.selectedBaseEntity = selectedBaseEntity;
editButton.setEnabled(selectedBaseEntity != null); editButton.setEnabled(selectedBaseEntity != null);
manageMetadataBtn.setEnabled(selectedBaseEntity != null);
if (selectedBaseEntity == null) { if (selectedBaseEntity == null) {
setName(getDefaultCaption(), StringUtils.EMPTY); setName(getDefaultCaption(), StringUtils.EMPTY);
} else { } else {
@@ -209,6 +222,7 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
populateLog(); populateLog();
populateDescription(); populateDescription();
populateDetailsWidget(); populateDetailsWidget();
populateMetadataDetails();
} }
protected void populateLog() { protected void populateLog() {
@@ -328,6 +342,8 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
protected abstract void populateDetailsWidget(); protected abstract void populateDetailsWidget();
protected abstract void populateMetadataDetails();
protected Long getSelectedBaseEntityId() { protected Long getSelectedBaseEntityId() {
return selectedBaseEntity == null ? null : selectedBaseEntity.getId(); return selectedBaseEntity == null ? null : selectedBaseEntity.getId();
} }
@@ -336,4 +352,10 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
protected abstract String getName(); protected abstract String getName();
protected abstract String getShowMetadataButtonId();
protected abstract Boolean isMetadataIconToBeDisplayed();
protected abstract void showMetadata(Button.ClickEvent event);
} }

View File

@@ -0,0 +1,192 @@
/**
* 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.detailslayout;
import java.util.List;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SpPermissionChecker;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.distributions.dstable.DsMetadataPopupLayout;
import org.eclipse.hawkbit.ui.utils.I18N;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import com.vaadin.data.Item;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.VaadinSessionScope;
import com.vaadin.ui.Button;
import com.vaadin.ui.Label;
import com.vaadin.ui.Table;
import com.vaadin.ui.UI;
import com.vaadin.ui.themes.ValoTheme;
/**
*
* DistributionSet Metadata details layout.
*
*/
@SpringComponent
@VaadinSessionScope
public class DistributionSetMetadatadetailslayout extends Table{
private static final long serialVersionUID = 2913758299611837718L;
private DistributionSetManagement distributionSetManagement;
private DsMetadataPopupLayout dsMetadataPopupLayout;
private static final String METADATA_KEY = "Key";
private static final String VIEW ="view";
private SpPermissionChecker permissionChecker;
private transient EntityFactory entityFactory;
private I18N i18n;
private Long selectedDistSetId;
/**
*
* @param i18n
* @param permissionChecker
* @param distributionSetManagement
* @param dsMetadataPopupLayout
*/
public void init(final I18N i18n, final SpPermissionChecker permissionChecker,
final DistributionSetManagement distributionSetManagement,
final DsMetadataPopupLayout dsMetadataPopupLayout,
final EntityFactory entityFactory) {
this.i18n = i18n;
this.permissionChecker = permissionChecker;
this.distributionSetManagement = distributionSetManagement;
this.dsMetadataPopupLayout = dsMetadataPopupLayout;
this.entityFactory = entityFactory;
createDSMetadataTable();
addCustomGeneratedColumns();
}
/**
* Populate software module metadata.
*
* @param distributionSet
*/
public void populateDSMetadata(final DistributionSet distributionSet) {
removeAllItems();
if (null == distributionSet) {
return;
}
selectedDistSetId = distributionSet.getId();
final List<DistributionSetMetadata> dsMetadataList = distributionSet.getMetadata();
if (null != dsMetadataList && !dsMetadataList.isEmpty()) {
dsMetadataList.forEach(dsMetadata -> setDSMetadataProperties(dsMetadata));
}
}
/**
* Create metadata .
*
* @param metadataKeyName
*/
public void createMetadata(final String metadataKeyName){
final IndexedContainer metadataContainer = (IndexedContainer) getContainerDataSource();
final Item item = metadataContainer.addItem(metadataKeyName);
item.getItemProperty(METADATA_KEY).setValue(metadataKeyName);
}
/**
* Delete metadata.
*
* @param metadataKeyName
*/
public void deleteMetadata(final String metadataKeyName){
final IndexedContainer metadataContainer = (IndexedContainer) getContainerDataSource();
metadataContainer.removeItem(metadataKeyName);
}
private void createDSMetadataTable() {
addStyleName(ValoTheme.TABLE_NO_HORIZONTAL_LINES);
addStyleName(ValoTheme.TABLE_NO_STRIPES);
addStyleName(SPUIStyleDefinitions.SW_MODULE_TABLE);
addStyleName("details-layout");
setSelectable(false);
setImmediate(true);
setContainerDataSource(getDistSetContainer());
setColumnHeaderMode(ColumnHeaderMode.EXPLICIT);
addDSMetadataTableHeader();
setSizeFull();
//same as height of other tabs in details tabsheet
setHeight(116,Unit.PIXELS);
}
private IndexedContainer getDistSetContainer() {
final IndexedContainer container = new IndexedContainer();
container.addContainerProperty(METADATA_KEY, String.class, "");
setColumnExpandRatio(METADATA_KEY, 0.7f);
setColumnAlignment(METADATA_KEY, Align.LEFT);
if (permissionChecker.hasUpdateDistributionPermission()) {
container.addContainerProperty(VIEW, Label.class, "");
setColumnExpandRatio(VIEW, 0.2F);
setColumnAlignment(VIEW, Align.RIGHT);
}
return container;
}
private void addDSMetadataTableHeader() {
setColumnHeader(METADATA_KEY, i18n.get("header.key"));
}
private void setDSMetadataProperties(final DistributionSetMetadata dsMetadata){
final Item item = getContainerDataSource().addItem(dsMetadata.getKey());
item.getItemProperty(METADATA_KEY).setValue(dsMetadata.getKey());
}
private void addCustomGeneratedColumns() {
addGeneratedColumn(METADATA_KEY,
(source, itemId, columnId) -> customMetadataDetailButton((String) itemId));
}
private Button customMetadataDetailButton(final String metadataKey) {
final Button viewIcon = SPUIComponentProvider.getButton(getDetailLinkId(metadataKey), metadataKey, "View "
+ metadataKey + " Metadata details", null, false, null, SPUIButtonStyleSmallNoBorder.class);
viewIcon.setData(metadataKey);
viewIcon.addStyleName(ValoTheme.BUTTON_TINY + " " + ValoTheme.BUTTON_LINK + " " + "on-focus-no-border link"
+ " " + "text-style");
viewIcon.addClickListener(event -> showMetadataDetails(selectedDistSetId, metadataKey));
return viewIcon;
}
private static String getDetailLinkId(final String name) {
return new StringBuilder(SPUIComponentIdProvider.DS_METADATA_DETAIL_LINK).append('.').append(name)
.toString();
}
private void showMetadataDetails(final Long selectedDistSetId , final String metadataKey) {
DistributionSet distSet = distributionSetManagement.findDistributionSetById(selectedDistSetId);
/* display the window */
UI.getCurrent().addWindow(dsMetadataPopupLayout.getWindow(distSet,
entityFactory.generateDistributionSetMetadata(distSet, metadataKey, "") ));
}
}

View File

@@ -0,0 +1,170 @@
/**
* 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.detailslayout;
import java.util.List;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareManagement;
import org.eclipse.hawkbit.repository.SpPermissionChecker;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.distributions.smtable.SwMetadataPopupLayout;
import org.eclipse.hawkbit.ui.utils.I18N;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import com.vaadin.data.Item;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.Button;
import com.vaadin.ui.Table;
import com.vaadin.ui.UI;
import com.vaadin.ui.themes.ValoTheme;
/**
*
* SoftwareModule Metadata details layout.
*
*/
@SpringComponent
@ViewScope
public class SoftwareModuleMetadatadetailslayout extends Table {
private static final long serialVersionUID = 2913758299611838818L;
private static final String METADATA_KEY = "Key";
private SpPermissionChecker permissionChecker;
private SoftwareManagement softwareManagement;
private SwMetadataPopupLayout swMetadataPopupLayout;
private I18N i18n;
private Long selectedSWModuleId;
private transient EntityFactory entityFactory;
public void init(final I18N i18n, final SpPermissionChecker permissionChecker,
final SoftwareManagement softwareManagement, final SwMetadataPopupLayout swMetadataPopupLayout,
final EntityFactory entityFactory) {
this.i18n = i18n;
this.permissionChecker = permissionChecker;
this.softwareManagement = softwareManagement;
this.swMetadataPopupLayout = swMetadataPopupLayout;
this.entityFactory = entityFactory;
createSWMMetadataTable();
addCustomGeneratedColumns();
}
/**
* Populate software module metadata table.
*
* @param swModule
*/
public void populateSMMetadata(final SoftwareModule swModule) {
removeAllItems();
if (null == swModule) {
return;
}
selectedSWModuleId = swModule.getId();
final List<SoftwareModuleMetadata> swMetadataList = swModule.getMetadata();
if (null != swMetadataList && !swMetadataList.isEmpty()) {
swMetadataList.forEach(swMetadata -> setSWMetadataProperties(swMetadata));
}
}
/**
* Create metadata.
*
* @param metadataKeyName
*/
public void createMetadata(final String metadataKeyName) {
final IndexedContainer metadataContainer = (IndexedContainer) getContainerDataSource();
final Item item = metadataContainer.addItem(metadataKeyName);
item.getItemProperty(METADATA_KEY).setValue(metadataKeyName);
}
/**
* Delete metadata.
*
* @param metadataKeyName
*/
public void deleteMetadata(final String metadataKeyName) {
final IndexedContainer metadataContainer = (IndexedContainer) getContainerDataSource();
metadataContainer.removeItem(metadataKeyName);
}
private void createSWMMetadataTable() {
addStyleName(ValoTheme.TABLE_NO_HORIZONTAL_LINES);
addStyleName(ValoTheme.TABLE_NO_STRIPES);
addStyleName(SPUIStyleDefinitions.SW_MODULE_TABLE);
setSelectable(false);
setImmediate(true);
setContainerDataSource(getSwModuleMetadataContainer());
setColumnHeaderMode(ColumnHeaderMode.EXPLICIT);
addSMMetadataTableHeader();
setSizeFull();
//same as height of other tabs in details tabsheet
setHeight(116,Unit.PIXELS);
}
private IndexedContainer getSwModuleMetadataContainer() {
final IndexedContainer container = new IndexedContainer();
container.addContainerProperty(METADATA_KEY, String.class, "");
setColumnAlignment(METADATA_KEY, Align.LEFT);
return container;
}
private void addSMMetadataTableHeader() {
setColumnHeader(METADATA_KEY, i18n.get("header.key"));
}
private void setSWMetadataProperties(final SoftwareModuleMetadata swMetadata) {
final Item item = getContainerDataSource().addItem(swMetadata.getKey());
item.getItemProperty(METADATA_KEY).setValue(swMetadata.getKey());
}
private void addCustomGeneratedColumns() {
addGeneratedColumn(METADATA_KEY, (source, itemId, columnId) -> customMetadataDetailButton((String) itemId));
}
private Button customMetadataDetailButton(final String metadataKey) {
final Button viewLink = SPUIComponentProvider.getButton(getDetailLinkId(metadataKey), metadataKey, "View"
+ metadataKey + " Metadata details", null, false, null, SPUIButtonStyleSmallNoBorder.class);
viewLink.setData(metadataKey);
if (permissionChecker.hasUpdateDistributionPermission()) {
viewLink.addStyleName(ValoTheme.BUTTON_TINY + " " + ValoTheme.BUTTON_LINK + " " + "on-focus-no-border link"
+ " " + "text-style");
viewLink.addClickListener(event -> showMetadataDetails(selectedSWModuleId, metadataKey));
}
return viewLink;
}
private static String getDetailLinkId(final String name) {
return new StringBuilder(SPUIComponentIdProvider.SW_METADATA_DETAIL_LINK).append('.').append(name).toString();
}
private void showMetadataDetails(final Long selectedSWModuleId, final String metadataKey) {
SoftwareModule swmodule = softwareManagement.findSoftwareModuleById(selectedSWModuleId);
/* display the window */
UI.getCurrent().addWindow(
swMetadataPopupLayout.getWindow(swmodule,
entityFactory.generateSoftwareModuleMetadata(swmodule, metadataKey, "")));
}
}

View File

@@ -22,7 +22,8 @@ import com.vaadin.ui.Button.ClickEvent;
*/ */
public abstract class AbstractFilterMultiButtonClick extends AbstractFilterButtonClickBehaviour { public abstract class AbstractFilterMultiButtonClick extends AbstractFilterButtonClickBehaviour {
protected final Set<Button> alreadyClickedButtons = new HashSet<>(); private static final long serialVersionUID = 1L;
protected final transient Set<Button> alreadyClickedButtons = new HashSet<>();
/* /*
* (non-Javadoc) * (non-Javadoc)

View File

@@ -95,9 +95,6 @@ public abstract class AbstractTable<E extends NamedEntity, I> extends Table {
if (values == null) { if (values == null) {
values = Collections.emptySet(); values = Collections.emptySet();
} }
if (values.contains(null)) {
LOG.warn("Null values in table content. How could this happen?");
}
return values; return values;
} }

View File

@@ -43,10 +43,6 @@ import com.vaadin.ui.themes.ValoTheme;
/** /**
* Abstract class for target/ds tag token layout. * Abstract class for target/ds tag token layout.
*
*
*
*
*/ */
public abstract class AbstractTagToken<T extends BaseEntity> implements Serializable { public abstract class AbstractTagToken<T extends BaseEntity> implements Serializable {
@@ -58,9 +54,9 @@ public abstract class AbstractTagToken<T extends BaseEntity> implements Serializ
protected IndexedContainer container; protected IndexedContainer container;
protected final Map<Long, TagData> tagDetails = new HashMap<>(); protected final transient Map<Long, TagData> tagDetails = new HashMap<>();
protected final Map<Long, TagData> tokensAdded = new HashMap<>(); protected final transient Map<Long, TagData> tokensAdded = new HashMap<>();
protected CssLayout tokenLayout = new CssLayout(); protected CssLayout tokenLayout = new CssLayout();

View File

@@ -14,7 +14,6 @@ import java.util.Map;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.eclipse.hawkbit.repository.model.BaseEntity; import org.eclipse.hawkbit.repository.model.BaseEntity;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter; import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonDecorator; import org.eclipse.hawkbit.ui.decorators.SPUIButtonDecorator;
import org.eclipse.hawkbit.ui.decorators.SPUIComboBoxDecorator; import org.eclipse.hawkbit.ui.decorators.SPUIComboBoxDecorator;
@@ -33,10 +32,8 @@ import com.vaadin.server.FontAwesome;
import com.vaadin.server.Resource; import com.vaadin.server.Resource;
import com.vaadin.shared.ui.label.ContentMode; import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.Button; import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.CheckBox; import com.vaadin.ui.CheckBox;
import com.vaadin.ui.ComboBox; import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label; import com.vaadin.ui.Label;
import com.vaadin.ui.Link; import com.vaadin.ui.Link;
@@ -140,24 +137,6 @@ public final class SPUIComponentProvider {
return SPUILabelDecorator.getDeocratedLabel(name, type); return SPUILabelDecorator.getDeocratedLabel(name, type);
} }
/**
* Get window component.
*
* @param caption
* window caption
* @param id
* window id
* @param type
* type of window
* @return Window
*/
public static CommonDialogWindow getWindow(final String caption, final String id, final String type,
final Component content, final ClickListener saveButtonClickListener,
final ClickListener cancelButtonClickListener, final String helpLink) {
return SPUIWindowDecorator.getDeocratedWindow(caption, id, type, content, saveButtonClickListener,
cancelButtonClickListener, helpLink);
}
/** /**
* Get window component. * Get window component.
* *
@@ -204,6 +183,8 @@ public final class SPUIComponentProvider {
/** /**
* Get Label UI component. * * Get Label UI component. *
* *
* @param caption
* set the caption of the textArea
* @param style * @param style
* set style * set style
* @param styleName * @param styleName

View File

@@ -8,39 +8,60 @@
*/ */
package org.eclipse.hawkbit.ui.customrenderers.client.renderers; package org.eclipse.hawkbit.ui.customrenderers.client.renderers;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.Button;
import com.vaadin.client.renderers.ButtonRenderer; import com.vaadin.client.renderers.ButtonRenderer;
import com.vaadin.client.ui.VButton; import com.vaadin.client.ui.VButton;
import com.vaadin.client.widget.grid.RendererCellReference; import com.vaadin.client.widget.grid.RendererCellReference;
/** /**
* * Renders button with provided HTML content. Used to display button with icons.
* Renders button with provided HTML content.
* Used to display button with icons.
*
*/ */
public class HtmlButtonRenderer extends ButtonRenderer { public class HtmlButtonRenderer extends ButtonRenderer {
public static final String DISABLE_VALUE = "_Disabled_";
@Override @Override
public void render(RendererCellReference cell, String text, Button button) { public void render(final RendererCellReference cell, final String text, final Button button) {
final boolean buttonEnable = isButtonEnable(cell.getElement().getClassName());
if (text != null) { if (text != null) {
button.setHTML(text); button.setHTML(text);
} }
applystyles(button); applystyles(button, buttonEnable);
// this is to allow the button to disappear, if the text is null // this is to allow the button to disappear, if the text is null
button.setVisible(text != null); button.setVisible(text != null);
button.getElement().setId("rollout.action.button.id"); button.getElement().setId(SPUIComponentIdProvider.ROLLOUT_ACTION_ID + "." + cell.getColumnIndex());
button.setEnabled(buttonEnable);
} }
private void applystyles(Button button) { /**
* see here https://vaadin.com/forum#!/thread/9418390/9765924
*
* @param text
* the button text
* @return is button enable.
*/
private static boolean isButtonEnable(final String text) {
return !text.contains(DISABLE_VALUE);
}
private void applystyles(final Button button, final boolean buttonEnable) {
button.setStyleName(VButton.CLASSNAME); button.setStyleName(VButton.CLASSNAME);
button.addStyleName(getStyle("tiny")); button.addStyleName(getStyle("tiny"));
button.addStyleName(getStyle("borderless")); button.addStyleName(getStyle("borderless-colored"));
button.addStyleName(getStyle("icon-only"));
button.addStyleName(getStyle("button-no-border")); button.addStyleName(getStyle("button-no-border"));
} button.addStyleName(getStyle("action-type-padding"));
if (buttonEnable) {
return;
}
button.addStyleName("v-disabled");
}
private String getStyle(final String style) { private String getStyle(final String style) {
return new StringBuilder(style).append(" ").append(VButton.CLASSNAME).append("-").append(style).toString(); return new StringBuilder(style).append(" ").append(VButton.CLASSNAME).append("-").append(style).toString();
} }
} }

View File

@@ -31,7 +31,7 @@ public class HtmlButtonRenderer extends ButtonRenderer {
* @param listener * @param listener
* RendererClickListener * RendererClickListener
*/ */
public HtmlButtonRenderer(RendererClickListener listener) { public HtmlButtonRenderer(final RendererClickListener listener) {
super(listener); super(listener);
} }
} }

View File

@@ -8,15 +8,16 @@
*/ */
package org.eclipse.hawkbit.ui.decorators; package org.eclipse.hawkbit.ui.decorators;
import org.apache.commons.lang3.StringUtils;
import com.vaadin.server.Resource; import com.vaadin.server.Resource;
import com.vaadin.ui.Button; import com.vaadin.ui.Button;
import com.vaadin.ui.themes.ValoTheme; import com.vaadin.ui.themes.ValoTheme;
/** /**
* Button with icon decorator. * Decorator class for a borderless Button with an icon.
*
*/ */
public class SPUIButtonStyleBorderWithIcon implements SPUIButtonDecorator { public class SPUIButtonStyleNoBorderWithIcon implements SPUIButtonDecorator {
private Button button; private Button button;
@@ -24,23 +25,25 @@ public class SPUIButtonStyleBorderWithIcon implements SPUIButtonDecorator {
public Button decorate(final Button button, final String style, final boolean setStyle, final Resource icon) { public Button decorate(final Button button, final String style, final boolean setStyle, final Resource icon) {
this.button = button; this.button = button;
button.setSizeFull();
setButtonStyle(style, setStyle);
setButtonIcon(icon);
button.addStyleName(ValoTheme.LABEL_SMALL); button.addStyleName(ValoTheme.LABEL_SMALL);
button.setSizeFull(); button.addStyleName(ValoTheme.BUTTON_BORDERLESS_COLORED);
setOrAddButtonStyle(style, setStyle);
setButtonIcon(icon);
return button; return button;
} }
private void setButtonStyle(final String style, final boolean setStyle) { private void setOrAddButtonStyle(final String style, final boolean setStyle) {
if (style == null) { if (StringUtils.isEmpty(style)) {
return; return;
} }
if (setStyle) { if (setStyle) {
// overwrite all other styles
button.setStyleName(style); button.setStyleName(style);
} else { } else {
button.addStyleName(style); button.addStyleName(style);

View File

@@ -9,9 +9,12 @@
package org.eclipse.hawkbit.ui.decorators; package org.eclipse.hawkbit.ui.decorators;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow; import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.common.CustomCommonDialogWindow;
import org.eclipse.hawkbit.ui.utils.I18N;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions; import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions; import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import com.vaadin.ui.AbstractLayout;
import com.vaadin.ui.Button.ClickListener; import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Component; import com.vaadin.ui.Component;
import com.vaadin.ui.Window; import com.vaadin.ui.Window;
@@ -42,12 +45,19 @@ public final class SPUIWindowDecorator {
* window type * window type
* @return Window * @return Window
*/ */
public static CommonDialogWindow getDeocratedWindow(final String caption, final String id, final String type, public static CommonDialogWindow getWindow(final String caption, final String id, final String type,
final Component content, final ClickListener saveButtonClickListener, final Component content, final ClickListener saveButtonClickListener,
final ClickListener cancelButtonClickListener, final String helpLink) { final ClickListener cancelButtonClickListener, final String helpLink, final AbstractLayout layout,
final I18N i18n) {
final CommonDialogWindow window = new CommonDialogWindow(caption, content, helpLink, saveButtonClickListener, CommonDialogWindow window = null;
cancelButtonClickListener); if (SPUIDefinitions.CUSTOM_METADATA_WINDOW.equals(type)) {
window = new CustomCommonDialogWindow(caption, content, helpLink, saveButtonClickListener,
cancelButtonClickListener, layout, i18n);
window.setDraggable(true);
window.setClosable(true);
} else {
window = new CommonDialogWindow(caption, content, helpLink, saveButtonClickListener,
cancelButtonClickListener, layout, i18n);
if (null != id) { if (null != id) {
window.setId(id); window.setId(id);
} }
@@ -60,9 +70,11 @@ public final class SPUIWindowDecorator {
window.setDraggable(true); window.setDraggable(true);
window.setClosable(true); window.setClosable(true);
} }
}
return window; return window;
} }
/** /**
* Decorates window based on type. * Decorates window based on type.
* *

View File

@@ -9,6 +9,7 @@
package org.eclipse.hawkbit.ui.distributions.disttype; package org.eclipse.hawkbit.ui.distributions.disttype;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement;
@@ -16,7 +17,6 @@ import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareManagement; import org.eclipse.hawkbit.repository.SoftwareManagement;
import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerConstants;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper; import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper;
import org.eclipse.hawkbit.ui.common.DistributionSetTypeBeanQuery; import org.eclipse.hawkbit.ui.common.DistributionSetTypeBeanQuery;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
@@ -49,8 +49,6 @@ import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Table; import com.vaadin.ui.Table;
import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.components.colorpicker.ColorChangeListener;
import com.vaadin.ui.components.colorpicker.ColorSelector;
import com.vaadin.ui.themes.ValoTheme; import com.vaadin.ui.themes.ValoTheme;
/** /**
@@ -58,8 +56,7 @@ import com.vaadin.ui.themes.ValoTheme;
*/ */
@SpringComponent @SpringComponent
@ViewScope @ViewScope
public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout {
implements ColorChangeListener, ColorSelector {
private static final long serialVersionUID = -5169398523815877767L; private static final long serialVersionUID = -5169398523815877767L;
private static final Logger LOG = LoggerFactory.getLogger(CreateUpdateDistSetTypeLayout.class); private static final Logger LOG = LoggerFactory.getLogger(CreateUpdateDistSetTypeLayout.class);
@@ -82,8 +79,12 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
private Table sourceTable; private Table sourceTable;
private Table selectedTable; private Table selectedTable;
private IndexedContainer selectedTablecontainer; private IndexedContainer selectedTableContainer;
private IndexedContainer sourceTablecontainer; private IndexedContainer sourceTableContainer;
private IndexedContainer originalSelectedTableContainer;
private Map<CheckBox, Boolean> mandatoryCheckboxMap;
@Override @Override
protected void createRequiredComponents() { protected void createRequiredComponents() {
@@ -103,7 +104,6 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
tagDesc = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "", tagDesc = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "",
ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.DIST_SET_TYPE_DESC, false, "", ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.DIST_SET_TYPE_DESC, false, "",
i18n.get("textfield.description"), SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH); i18n.get("textfield.description"), SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
tagDesc.setId(SPUIDefinitions.NEW_DISTRIBUTION_TYPE_DESC); tagDesc.setId(SPUIDefinitions.NEW_DISTRIBUTION_TYPE_DESC);
tagDesc.setImmediate(true); tagDesc.setImmediate(true);
tagDesc.setNullRepresentation(""); tagDesc.setNullRepresentation("");
@@ -159,9 +159,6 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
return twinColumnLayout; return twinColumnLayout;
} }
/**
*
*/
private void buildSelectedTable() { private void buildSelectedTable() {
selectedTable = new Table(); selectedTable = new Table();
@@ -176,13 +173,14 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
selectedTable.addStyleName("dist_type_twin-table"); selectedTable.addStyleName("dist_type_twin-table");
selectedTable.setSizeFull(); selectedTable.setSizeFull();
createSelectedTableContainer(); createSelectedTableContainer();
selectedTable.setContainerDataSource(selectedTablecontainer); selectedTable.setContainerDataSource(selectedTableContainer);
addTooltTipToSelectedTable(); addTooltTipToSelectedTable();
selectedTable.setImmediate(true); selectedTable.setImmediate(true);
selectedTable.setVisibleColumns(DIST_TYPE_NAME, DIST_TYPE_MANDATORY); selectedTable.setVisibleColumns(DIST_TYPE_NAME, DIST_TYPE_MANDATORY);
selectedTable.setColumnHeaders(i18n.get("header.dist.twintable.selected"), STAR); selectedTable.setColumnHeaders(i18n.get("header.dist.twintable.selected"), STAR);
selectedTable.setColumnExpandRatio(DIST_TYPE_NAME, 0.75f); selectedTable.setColumnExpandRatio(DIST_TYPE_NAME, 0.75F);
selectedTable.setColumnExpandRatio(DIST_TYPE_MANDATORY, 0.25f); selectedTable.setColumnExpandRatio(DIST_TYPE_MANDATORY, 0.25F);
selectedTable.setRequired(true);
} }
private void addTooltTipToSelectedTable() { private void addTooltTipToSelectedTable() {
@@ -218,14 +216,13 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
sourceTable.addStyleName(ValoTheme.TABLE_NO_VERTICAL_LINES); sourceTable.addStyleName(ValoTheme.TABLE_NO_VERTICAL_LINES);
sourceTable.addStyleName(ValoTheme.TABLE_SMALL); sourceTable.addStyleName(ValoTheme.TABLE_SMALL);
sourceTable.setImmediate(true); sourceTable.setImmediate(true);
// sourceTable
sourceTable.setSizeFull(); sourceTable.setSizeFull();
sourceTable.addStyleName("dist_type_twin-table"); sourceTable.addStyleName("dist_type_twin-table");
sourceTable.setSortEnabled(false); sourceTable.setSortEnabled(false);
sourceTablecontainer = new IndexedContainer(); sourceTableContainer = new IndexedContainer();
sourceTablecontainer.addContainerProperty(DIST_TYPE_NAME, String.class, ""); sourceTableContainer.addContainerProperty(DIST_TYPE_NAME, String.class, "");
sourceTablecontainer.addContainerProperty(DIST_TYPE_DESCRIPTION, String.class, ""); sourceTableContainer.addContainerProperty(DIST_TYPE_DESCRIPTION, String.class, "");
sourceTable.setContainerDataSource(sourceTablecontainer); sourceTable.setContainerDataSource(sourceTableContainer);
sourceTable.setVisibleColumns(new Object[] { DIST_TYPE_NAME }); sourceTable.setVisibleColumns(new Object[] { DIST_TYPE_NAME });
sourceTable.setColumnHeaders(i18n.get("header.dist.twintable.available")); sourceTable.setColumnHeaders(i18n.get("header.dist.twintable.available"));
@@ -237,44 +234,54 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
private void createSelectedTableContainer() { private void createSelectedTableContainer() {
selectedTablecontainer = new IndexedContainer(); selectedTableContainer = new IndexedContainer();
selectedTablecontainer.addContainerProperty(DIST_TYPE_NAME, String.class, ""); selectedTableContainer.addContainerProperty(DIST_TYPE_NAME, String.class, "");
selectedTablecontainer.addContainerProperty(DIST_TYPE_DESCRIPTION, String.class, ""); selectedTableContainer.addContainerProperty(DIST_TYPE_DESCRIPTION, String.class, "");
selectedTablecontainer.addContainerProperty(DIST_TYPE_MANDATORY, CheckBox.class, null); selectedTableContainer.addContainerProperty(DIST_TYPE_MANDATORY, CheckBox.class, null);
}
private void createOriginalSelectedTableContainer() {
originalSelectedTableContainer = new IndexedContainer();
originalSelectedTableContainer.addContainerProperty(DIST_TYPE_NAME, String.class, "");
originalSelectedTableContainer.addContainerProperty(DIST_TYPE_DESCRIPTION, String.class, "");
originalSelectedTableContainer.addContainerProperty(DIST_TYPE_MANDATORY, CheckBox.class, null);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void addSMType() { private void addSMType() {
final Set<Long> selectedIds = (Set<Long>) sourceTable.getValue(); final Set<Long> selectedIds = (Set<Long>) sourceTable.getValue();
if (null != selectedIds && !selectedIds.isEmpty()) { if (selectedIds == null) {
return;
}
for (final Long id : selectedIds) { for (final Long id : selectedIds) {
addTargetTableData(id); addTargetTableData(id);
} }
} }
}
private void removeSMType() { private void removeSMType() {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Set<Long> selectedIds = (Set<Long>) selectedTable.getValue(); final Set<Long> selectedIds = (Set<Long>) selectedTable.getValue();
if (null != selectedIds && !selectedIds.isEmpty()) { if (selectedIds == null) {
return;
}
for (final Long id : selectedIds) { for (final Long id : selectedIds) {
addSourceTableData(id); addSourceTableData(id);
selectedTable.removeItem(id); selectedTable.removeItem(id);
} }
} }
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void getSourceTableData() { private void getSourceTableData() {
sourceTablecontainer.removeAllItems(); sourceTableContainer.removeAllItems();
final Iterable<SoftwareModuleType> moduleTypeBeans = softwareManagement final Iterable<SoftwareModuleType> moduleTypeBeans = softwareManagement
.findSoftwareModuleTypesAll(new PageRequest(0, 1_000)); .findSoftwareModuleTypesAll(new PageRequest(0, 1_000));
Item saveTblitem; Item saveTblitem;
for (final SoftwareModuleType swTypeTag : moduleTypeBeans) { for (final SoftwareModuleType swTypeTag : moduleTypeBeans) {
saveTblitem = sourceTablecontainer.addItem(swTypeTag.getId()); saveTblitem = sourceTableContainer.addItem(swTypeTag.getId());
saveTblitem.getItemProperty(DIST_TYPE_NAME).setValue(swTypeTag.getName()); saveTblitem.getItemProperty(DIST_TYPE_NAME).setValue(swTypeTag.getName());
saveTblitem.getItemProperty(DIST_TYPE_DESCRIPTION).setValue(swTypeTag.getDescription()); saveTblitem.getItemProperty(DIST_TYPE_DESCRIPTION).setValue(swTypeTag.getDescription());
} }
@@ -307,11 +314,13 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
private void getSelectedTableItemData(final Long id) { private void getSelectedTableItemData(final Long id) {
Item saveTblitem; Item saveTblitem;
if (null != selectedTablecontainer) { if (selectedTableContainer != null) {
saveTblitem = selectedTablecontainer.addItem(id); saveTblitem = selectedTableContainer.addItem(id);
saveTblitem.getItemProperty(DIST_TYPE_NAME).setValue( saveTblitem.getItemProperty(DIST_TYPE_NAME).setValue(
sourceTable.getContainerDataSource().getItem(id).getItemProperty(DIST_TYPE_NAME).getValue()); sourceTable.getContainerDataSource().getItem(id).getItemProperty(DIST_TYPE_NAME).getValue());
saveTblitem.getItemProperty(DIST_TYPE_MANDATORY).setValue(new CheckBox()); final CheckBox mandatoryCheckBox = new CheckBox();
window.updateAllComponents(mandatoryCheckBox);
saveTblitem.getItemProperty(DIST_TYPE_MANDATORY).setValue(mandatoryCheckBox);
saveTblitem.getItemProperty(DIST_TYPE_DESCRIPTION).setValue( saveTblitem.getItemProperty(DIST_TYPE_DESCRIPTION).setValue(
sourceTable.getContainerDataSource().getItem(id).getItemProperty(DIST_TYPE_DESCRIPTION).getValue()); sourceTable.getContainerDataSource().getItem(id).getItemProperty(DIST_TYPE_DESCRIPTION).getValue());
} }
@@ -320,10 +329,9 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void addSourceTableData(final Long selectedId) { private void addSourceTableData(final Long selectedId) {
if (null != sourceTablecontainer) { if (sourceTableContainer != null) {
Item saveTblitem; Item saveTblitem;
saveTblitem = sourceTablecontainer.addItem(selectedId); saveTblitem = sourceTableContainer.addItem(selectedId);
selectedTable.getContainerDataSource().getItem(selectedId).getItemProperty(DIST_TYPE_NAME);
saveTblitem.getItemProperty(DIST_TYPE_NAME).setValue(selectedTable.getContainerDataSource() saveTblitem.getItemProperty(DIST_TYPE_NAME).setValue(selectedTable.getContainerDataSource()
.getItem(selectedId).getItemProperty(DIST_TYPE_NAME).getValue()); .getItem(selectedId).getItemProperty(DIST_TYPE_NAME).getValue());
saveTblitem.getItemProperty(DIST_TYPE_DESCRIPTION).setValue(selectedTable.getContainerDataSource() saveTblitem.getItemProperty(DIST_TYPE_DESCRIPTION).setValue(selectedTable.getContainerDataSource()
@@ -353,20 +361,14 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
final SoftwareModuleType swModuleType = softwareManagement.findSoftwareModuleTypeByName(distTypeName); final SoftwareModuleType swModuleType = softwareManagement.findSoftwareModuleTypeByName(distTypeName);
checkMandatoryAndAddMandatoryModuleType(newDistType, isMandatory, swModuleType); checkMandatoryAndAddMandatoryModuleType(newDistType, isMandatory, swModuleType);
} }
if (null != typeDescValue) {
newDistType.setDescription(typeDescValue); newDistType.setDescription(typeDescValue);
}
newDistType.setColour(colorPicked); newDistType.setColour(colorPicked);
newDistType = distributionSetManagement.createDistributionSetType(newDistType); newDistType = distributionSetManagement.createDistributionSetType(newDistType);
uiNotification.displaySuccess(i18n.get("message.save.success", new Object[] { newDistType.getName() })); uiNotification.displaySuccess(i18n.get("message.save.success", new Object[] { newDistType.getName() }));
closeWindow();
eventBus.publish(this, eventBus.publish(this,
new DistributionSetTypeEvent(DistributionSetTypeEnum.ADD_DIST_SET_TYPE, newDistType)); new DistributionSetTypeEvent(DistributionSetTypeEnum.ADD_DIST_SET_TYPE, newDistType));
} else { } else {
uiNotification.displayValidationError(i18n.get("message.error.missing.typenameorkey")); uiNotification.displayValidationError(i18n.get("message.error.missing.typenameorkey"));
} }
} }
@@ -386,7 +388,7 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
if (null != typeNameValue) { if (null != typeNameValue) {
updateDistSetType.setName(typeNameValue); updateDistSetType.setName(typeNameValue);
updateDistSetType.setKey(typeKeyValue); updateDistSetType.setKey(typeKeyValue);
updateDistSetType.setDescription(null != typeDescValue ? typeDescValue : null); updateDistSetType.setDescription(typeDescValue);
if (distributionSetManagement.countDistributionSetsByType(existingType) <= 0 && null != itemIds if (distributionSetManagement.countDistributionSetsByType(existingType) <= 0 && null != itemIds
&& !itemIds.isEmpty()) { && !itemIds.isEmpty()) {
@@ -404,21 +406,17 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
distributionSetManagement.updateDistributionSetType(updateDistSetType); distributionSetManagement.updateDistributionSetType(updateDistSetType);
uiNotification uiNotification
.displaySuccess(i18n.get("message.update.success", new Object[] { updateDistSetType.getName() })); .displaySuccess(i18n.get("message.update.success", new Object[] { updateDistSetType.getName() }));
closeWindow();
eventBus.publish(this, eventBus.publish(this,
new DistributionSetTypeEvent(DistributionSetTypeEnum.UPDATE_DIST_SET_TYPE, updateDistSetType)); new DistributionSetTypeEvent(DistributionSetTypeEnum.UPDATE_DIST_SET_TYPE, updateDistSetType));
} else { } else {
uiNotification.displayValidationError(i18n.get("message.tag.update.mandatory")); uiNotification.displayValidationError(i18n.get("message.tag.update.mandatory"));
} }
} }
private void checkMandatoryAndAddMandatoryModuleType(final DistributionSetType updateDistSetType, private void checkMandatoryAndAddMandatoryModuleType(final DistributionSetType updateDistSetType,
final Boolean isMandatory, final SoftwareModuleType swModuleType) { final Boolean isMandatory, final SoftwareModuleType swModuleType) {
if (isMandatory) { if (isMandatory) {
updateDistSetType.addMandatoryModuleType(swModuleType); updateDistSetType.addMandatoryModuleType(swModuleType);
} else { } else {
updateDistSetType.addOptionalModuleType(swModuleType); updateDistSetType.addOptionalModuleType(swModuleType);
} }
@@ -440,32 +438,6 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
return distSetType; return distSetType;
} }
/*
* (non-Javadoc)
*
* @see com.vaadin.ui.components.colorpicker.HasColorChangeListener#
* addColorChangeListener(com.vaadin
* .ui.components.colorpicker.ColorChangeListener)
*/
@Override
public void addColorChangeListener(final ColorChangeListener listener) {
LOG.info("in side addColorChangeListener() ");
}
/*
* (non-Javadoc)
*
* @see com.vaadin.ui.components.colorpicker.HasColorChangeListener#
* removeColorChangeListener(com.
* vaadin.ui.components.colorpicker.ColorChangeListener)
*/
@Override
public void removeColorChangeListener(final ColorChangeListener listener) {
LOG.info("in side removeColorChangeListener() ");
}
/** /**
* reset the components. * reset the components.
*/ */
@@ -484,9 +456,9 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
* ValueChangeEvent * ValueChangeEvent
*/ */
@Override @Override
protected void createOptionValueChanged(final ValueChangeEvent event) { protected void optionValueChanged(final ValueChangeEvent event) {
super.createOptionValueChanged(event); super.optionValueChanged(event);
if (updateTypeStr.equals(event.getProperty().getValue())) { if (updateTypeStr.equals(event.getProperty().getValue())) {
selectedTable.getContainerDataSource().removeAllItems(); selectedTable.getContainerDataSource().removeAllItems();
@@ -552,18 +524,17 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
if (null != selectedTypeTag) { if (null != selectedTypeTag) {
tagDesc.setValue(selectedTypeTag.getDescription()); tagDesc.setValue(selectedTypeTag.getDescription());
typeKey.setValue(selectedTypeTag.getKey()); typeKey.setValue(selectedTypeTag.getKey());
if (distributionSetManagement.countDistributionSetsByType(selectedTypeTag) <= 0) { if (distributionSetManagement.countDistributionSetsByType(selectedTypeTag) <= 0) {
distTypeSelectLayout.setEnabled(true); distTypeSelectLayout.setEnabled(true);
selectedTable.setEnabled(true); selectedTable.setEnabled(true);
window.setSaveButtonEnabled(true);
} else { } else {
uiNotification.displayValidationError( uiNotification.displayValidationError(
selectedTypeTag.getName() + " " + i18n.get("message.error.dist.set.type.update")); selectedTypeTag.getName() + " " + i18n.get("message.error.dist.set.type.update"));
distTypeSelectLayout.setEnabled(false); distTypeSelectLayout.setEnabled(false);
selectedTable.setEnabled(false); selectedTable.setEnabled(false);
window.setSaveButtonEnabled(false);
} }
createOriginalSelectedTableContainer();
for (final SoftwareModuleType swModuleType : selectedTypeTag.getOptionalModuleTypes()) { for (final SoftwareModuleType swModuleType : selectedTypeTag.getOptionalModuleTypes()) {
addTargetTableforUpdate(swModuleType, false); addTargetTableforUpdate(swModuleType, false);
} }
@@ -583,19 +554,25 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void addTargetTableforUpdate(final SoftwareModuleType swModuleType, final boolean mandatory) { private void addTargetTableforUpdate(final SoftwareModuleType swModuleType, final boolean mandatory) {
Item saveTblitem; if (selectedTableContainer == null) {
if (null != selectedTablecontainer) { return;
saveTblitem = selectedTablecontainer.addItem(swModuleType.getId()); }
final Item saveTblitem = selectedTableContainer.addItem(swModuleType.getId());
sourceTable.removeItem(swModuleType.getId()); sourceTable.removeItem(swModuleType.getId());
saveTblitem.getItemProperty(DIST_TYPE_NAME).setValue(swModuleType.getName()); saveTblitem.getItemProperty(DIST_TYPE_NAME).setValue(swModuleType.getName());
saveTblitem.getItemProperty(DIST_TYPE_MANDATORY).setValue(new CheckBox("", mandatory)); final CheckBox mandatoryCheckbox = new CheckBox("", mandatory);
} mandatoryCheckbox.setId(swModuleType.getName());
saveTblitem.getItemProperty(DIST_TYPE_MANDATORY).setValue(mandatoryCheckbox);
final Item originalItem = originalSelectedTableContainer.addItem(swModuleType.getId());
originalItem.getItemProperty(DIST_TYPE_NAME).setValue(swModuleType.getName());
originalItem.getItemProperty(DIST_TYPE_MANDATORY).setValue(mandatoryCheckbox);
window.updateAllComponents(mandatoryCheckbox);
} }
@Override @Override
protected void save(final ClickEvent event) { protected void save(final ClickEvent event) {
if (mandatoryValuesPresent()) {
final DistributionSetType existingDistTypeByKey = distributionSetManagement final DistributionSetType existingDistTypeByKey = distributionSetManagement
.findDistributionSetTypeByKey(typeKey.getValue()); .findDistributionSetTypeByKey(typeKey.getValue());
final DistributionSetType existingDistTypeByName = distributionSetManagement final DistributionSetType existingDistTypeByName = distributionSetManagement
@@ -608,40 +585,10 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout
updateDistributionSetType(existingDistTypeByKey); updateDistributionSetType(existingDistTypeByKey);
} }
} }
}
@Override @Override
public void createWindow() { protected String getWindowCaption() {
reset(); return i18n.get("caption.add.type");
window = SPUIComponentProvider.getWindow(i18n.get("caption.add.type"), null,
SPUIDefinitions.CREATE_UPDATE_WINDOW, this, this::save, this::discard, null);
}
@Override
protected void previewButtonClicked() {
if (!tagPreviewBtnClicked) {
final String selectedOption = (String) optiongroup.getValue();
if (null != selectedOption && selectedOption.equalsIgnoreCase(updateTypeStr)
&& null != tagNameComboBox.getValue()) {
final DistributionSetType existedDistType = distributionSetManagement
.findDistributionSetTypeByKey(tagNameComboBox.getValue().toString());
if (null != existedDistType) {
getColorPickerLayout().setSelectedColor(existedDistType.getColour() != null
? ColorPickerHelper.rgbToColorConverter(existedDistType.getColour())
: ColorPickerHelper.rgbToColorConverter(ColorPickerConstants.DEFAULT_COLOR));
} else {
getColorPickerLayout().setSelectedColor(
ColorPickerHelper.rgbToColorConverter(ColorPickerConstants.DEFAULT_COLOR));
}
}
getColorPickerLayout().getSelPreview().setColor(getColorPickerLayout().getSelectedColor());
mainLayout.addComponent(colorPickerLayout, 1, 0);
mainLayout.setComponentAlignment(colorPickerLayout, Alignment.MIDDLE_CENTER);
} else {
mainLayout.removeComponent(colorPickerLayout);
}
tagPreviewBtnClicked = !tagPreviewBtnClicked;
} }
@Override @Override

View File

@@ -14,18 +14,22 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareManagement; import org.eclipse.hawkbit.repository.SoftwareManagement;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleIdName; import org.eclipse.hawkbit.repository.model.SoftwareModuleIdName;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent; import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent.SoftwareModuleEventType; import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent.SoftwareModuleEventType;
import org.eclipse.hawkbit.ui.common.DistributionSetIdName; import org.eclipse.hawkbit.ui.common.DistributionSetIdName;
import org.eclipse.hawkbit.ui.common.detailslayout.AbstractNamedVersionedEntityTableDetailsLayout; import org.eclipse.hawkbit.ui.common.detailslayout.AbstractNamedVersionedEntityTableDetailsLayout;
import org.eclipse.hawkbit.ui.common.detailslayout.DistributionSetMetadatadetailslayout;
import org.eclipse.hawkbit.ui.common.detailslayout.SoftwareModuleDetailsTable; import org.eclipse.hawkbit.ui.common.detailslayout.SoftwareModuleDetailsTable;
import org.eclipse.hawkbit.ui.common.tagdetails.DistributionTagToken; import org.eclipse.hawkbit.ui.common.tagdetails.DistributionTagToken;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder; import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.distributions.event.MetadataEvent;
import org.eclipse.hawkbit.ui.distributions.event.SaveActionWindowEvent; import org.eclipse.hawkbit.ui.distributions.event.SaveActionWindowEvent;
import org.eclipse.hawkbit.ui.distributions.event.SoftwareModuleAssignmentDiscardEvent; import org.eclipse.hawkbit.ui.distributions.event.SoftwareModuleAssignmentDiscardEvent;
import org.eclipse.hawkbit.ui.distributions.state.ManageDistUIState; import org.eclipse.hawkbit.ui.distributions.state.ManageDistUIState;
@@ -80,11 +84,36 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet
@Autowired @Autowired
private transient DistributionSetManagement distributionSetManagement; private transient DistributionSetManagement distributionSetManagement;
@Autowired
private DsMetadataPopupLayout dsMetadataPopupLayout;
@Autowired
private EntityFactory entityFactory;
private SoftwareModuleDetailsTable softwareModuleTable; private SoftwareModuleDetailsTable softwareModuleTable;
private DistributionSetMetadatadetailslayout dsMetadataTable;
private VerticalLayout tagsLayout; private VerticalLayout tagsLayout;
Map<String, StringBuilder> assignedSWModule = new HashMap<>(); private final Map<String, StringBuilder> assignedSWModule = new HashMap<>();
@EventBusListenerMethod(scope = EventScope.SESSION)
void onEvent(final MetadataEvent event) {
UI.getCurrent()
.access(() -> {
DistributionSetMetadata dsMetadata = event.getDistributionSetMetadata();
if (dsMetadata != null && isDistributionSetSelected(dsMetadata.getDistributionSet())) {
if (event.getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.CREATE_DISTRIBUTION_SET_METADATA) {
dsMetadataTable.createMetadata(event.getDistributionSetMetadata().getKey());
} else if (event.getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.DELETE_DISTRIBUTION_SET_METADATA) {
dsMetadataTable.deleteMetadata(event.getDistributionSetMetadata().getKey());
}
}
});
}
/** /**
* softwareLayout Initialize the component. * softwareLayout Initialize the component.
@@ -94,6 +123,9 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet
softwareModuleTable = new SoftwareModuleDetailsTable(); softwareModuleTable = new SoftwareModuleDetailsTable();
softwareModuleTable.init(getI18n(), true, getPermissionChecker(), distributionSetManagement, getEventBus(), softwareModuleTable.init(getI18n(), true, getPermissionChecker(), distributionSetManagement, getEventBus(),
manageDistUIState); manageDistUIState);
dsMetadataTable = new DistributionSetMetadatadetailslayout();
dsMetadataTable.init(getI18n(), getPermissionChecker(),distributionSetManagement,
dsMetadataPopupLayout,entityFactory);
super.init(); super.init();
} }
@@ -107,6 +139,7 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet
populateDetails(); populateDetails();
populateModule(); populateModule();
populateTags(); populateTags();
populateMetadataDetails();
} }
private void populateModule() { private void populateModule() {
@@ -239,6 +272,11 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet
} }
} }
@Override
protected void populateMetadataDetails(){
dsMetadataTable.populateDSMetadata(getSelectedBaseEntity());
}
private void updateDistributionSetDetailsLayout(final String type, final Boolean isMigrationRequired) { private void updateDistributionSetDetailsLayout(final String type, final Boolean isMigrationRequired) {
final VerticalLayout detailsTabLayout = getDetailsLayout(); final VerticalLayout detailsTabLayout = getDetailsLayout();
detailsTabLayout.removeAllComponents(); detailsTabLayout.removeAllComponents();
@@ -259,8 +297,7 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet
@Override @Override
protected void onEdit(final ClickEvent event) { protected void onEdit(final ClickEvent event) {
final Window newDistWindow = distributionAddUpdateWindowLayout.getWindow(); final Window newDistWindow = distributionAddUpdateWindowLayout.getWindow(getSelectedBaseEntityId());
distributionAddUpdateWindowLayout.populateValuesOfDistribution(getSelectedBaseEntityId());
newDistWindow.setCaption(getI18n().get("caption.update.dist")); newDistWindow.setCaption(getI18n().get("caption.update.dist"));
UI.getCurrent().addWindow(newDistWindow); UI.getCurrent().addWindow(newDistWindow);
newDistWindow.setVisible(Boolean.TRUE); newDistWindow.setVisible(Boolean.TRUE);
@@ -294,6 +331,7 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet
detailsTab.addTab(createSoftwareModuleTab(), getI18n().get("caption.softwares.distdetail.tab"), null); detailsTab.addTab(createSoftwareModuleTab(), getI18n().get("caption.softwares.distdetail.tab"), null);
detailsTab.addTab(createTagsLayout(), getI18n().get("caption.tags.tab"), null); detailsTab.addTab(createTagsLayout(), getI18n().get("caption.tags.tab"), null);
detailsTab.addTab(createLogLayout(), getI18n().get("caption.logs.tab"), null); detailsTab.addTab(createLogLayout(), getI18n().get("caption.logs.tab"), null);
detailsTab.addTab(dsMetadataTable, getI18n().get("caption.metadata"), null);
} }
@Override @Override
@@ -353,7 +391,7 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet
@Override @Override
protected String getTabSheetId() { protected String getTabSheetId() {
return null; return SPUIComponentIdProvider.DISTRIBUTIONSET_DETAILS_TABSHEET_ID;
} }
@Override @Override
@@ -361,4 +399,30 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet
return SPUIComponentIdProvider.DISTRIBUTION_DETAILS_HEADER_LABEL_ID; return SPUIComponentIdProvider.DISTRIBUTION_DETAILS_HEADER_LABEL_ID;
} }
@Override
protected Boolean isMetadataIconToBeDisplayed() {
return true;
}
@Override
protected String getShowMetadataButtonId() {
DistributionSetIdName lastselectedDistDS = manageDistUIState.getLastSelectedDistribution().isPresent() ? manageDistUIState
.getLastSelectedDistribution().get() : null;
return SPUIComponentIdProvider.DS_TABLE_MANAGE_METADATA_ID + "." + lastselectedDistDS.getName() + "."
+ lastselectedDistDS.getVersion();
}
private boolean isDistributionSetSelected(DistributionSet ds) {
DistributionSetIdName lastselectedDistDS = manageDistUIState.getLastSelectedDistribution().isPresent() ? manageDistUIState
.getLastSelectedDistribution().get() : null;
return ds != null && lastselectedDistDS != null && lastselectedDistDS.getName().equals(ds.getName())
&& lastselectedDistDS.getVersion().endsWith(ds.getVersion());
}
@Override
protected void showMetadata(ClickEvent event) {
DistributionSet ds = distributionSetManagement.findDistributionSetByIdWithDetails(getSelectedBaseEntityId());
UI.getCurrent().addWindow(dsMetadataPopupLayout.getWindow(ds,null));
}
} }

View File

@@ -30,6 +30,8 @@ import org.eclipse.hawkbit.ui.common.DistributionSetIdName;
import org.eclipse.hawkbit.ui.common.table.AbstractNamedVersionTable; import org.eclipse.hawkbit.ui.common.table.AbstractNamedVersionTable;
import org.eclipse.hawkbit.ui.common.table.AbstractTable; import org.eclipse.hawkbit.ui.common.table.AbstractTable;
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.distributions.event.DistributionsUIEvent; import org.eclipse.hawkbit.ui.distributions.event.DistributionsUIEvent;
import org.eclipse.hawkbit.ui.distributions.event.DistributionsViewAcceptCriteria; import org.eclipse.hawkbit.ui.distributions.event.DistributionsViewAcceptCriteria;
import org.eclipse.hawkbit.ui.distributions.event.DragEvent; import org.eclipse.hawkbit.ui.distributions.event.DragEvent;
@@ -42,6 +44,7 @@ import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions; import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions; import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions; import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.TableColumn;
import org.eclipse.hawkbit.ui.utils.UINotification; import org.eclipse.hawkbit.ui.utils.UINotification;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -57,8 +60,10 @@ import com.vaadin.data.Item;
import com.vaadin.event.dd.DragAndDropEvent; import com.vaadin.event.dd.DragAndDropEvent;
import com.vaadin.event.dd.DropHandler; import com.vaadin.event.dd.DropHandler;
import com.vaadin.event.dd.acceptcriteria.AcceptCriterion; import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
import com.vaadin.server.FontAwesome;
import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope; import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component; import com.vaadin.ui.Component;
import com.vaadin.ui.Table; import com.vaadin.ui.Table;
import com.vaadin.ui.UI; import com.vaadin.ui.UI;
@@ -98,6 +103,9 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
@Autowired @Autowired
private transient TargetManagement targetManagement; private transient TargetManagement targetManagement;
@Autowired
private DsMetadataPopupLayout dsMetadataPopupLayout;
/** /**
* Initialize the component. * Initialize the component.
*/ */
@@ -181,6 +189,10 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
protected void publishEntityAfterValueChange(final DistributionSet distributionSet) { protected void publishEntityAfterValueChange(final DistributionSet distributionSet) {
eventBus.publish(this, new DistributionTableEvent(BaseEntityEventType.SELECTED_ENTITY, distributionSet)); eventBus.publish(this, new DistributionTableEvent(BaseEntityEventType.SELECTED_ENTITY, distributionSet));
eventBus.publish(this, DistributionsUIEvent.ORDER_BY_DISTRIBUTION); eventBus.publish(this, DistributionsUIEvent.ORDER_BY_DISTRIBUTION);
if(distributionSet!=null){
manageDistUIState.setLastSelectedEntity(new DistributionSetIdName(distributionSet.getId(),
distributionSet.getName(),distributionSet.getVersion()));
}
} }
@Override @Override
@@ -469,4 +481,50 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
manageDistUIState.setNoDataAvailableDist(!available); manageDistUIState.setNoDataAvailableDist(!available);
} }
@Override
protected void addCustomGeneratedColumns() {
addGeneratedColumn(SPUILabelDefinitions.METADATA_ICON, new ColumnGenerator() {
private static final long serialVersionUID = 117186282275065399L;
@Override
public Object generateCell(final Table source, final Object itemId, final Object columnId) {
final String nameVersionStr = getNameAndVerion(itemId);
final Button manageMetaDataBtn = createManageMetadataButton(nameVersionStr);
manageMetaDataBtn.addClickListener(event -> showMetadataDetails(((DistributionSetIdName) itemId).getId()));
return manageMetaDataBtn;
}
});
}
@Override
protected List<TableColumn> getTableVisibleColumns() {
final List<TableColumn> columnList = super.getTableVisibleColumns();
if (!isMaximized()) {
columnList.add(new TableColumn(SPUILabelDefinitions.METADATA_ICON, "", 0.1F));
}
return columnList;
}
private Button createManageMetadataButton(String nameVersionStr) {
final Button manageMetadataBtn = SPUIComponentProvider.getButton(
SPUIComponentIdProvider.DS_TABLE_MANAGE_METADATA_ID + "." + nameVersionStr, "", "", null, false,
FontAwesome.LIST_ALT, SPUIButtonStyleSmallNoBorder.class);
manageMetadataBtn.addStyleName(SPUIStyleDefinitions.ARTIFACT_DTLS_ICON);
manageMetadataBtn.setDescription(i18n.get("tooltip.metadata.icon"));
return manageMetadataBtn;
}
private void showMetadataDetails(Long itemId) {
DistributionSet ds = distributionSetManagement.findDistributionSetByIdWithDetails(itemId);
UI.getCurrent().addWindow(dsMetadataPopupLayout.getWindow(ds,null));
}
private String getNameAndVerion(final Object itemId) {
final Item item = getItem(itemId);
final String name = (String) item.getItemProperty(SPUILabelDefinitions.VAR_NAME).getValue();
final String version = (String) item.getItemProperty(SPUILabelDefinitions.VAR_VERSION).getValue();
return name + "." + version;
}
} }

View File

@@ -152,7 +152,7 @@ public class DistributionSetTableHeader extends AbstractTableHeader {
@Override @Override
protected void addNewItem(final ClickEvent event) { protected void addNewItem(final ClickEvent event) {
final Window newDistWindow = addUpdateWindowLayout.getWindow(); final Window newDistWindow = addUpdateWindowLayout.getWindow(null);
newDistWindow.setCaption(i18n.get("caption.add.new.dist")); newDistWindow.setCaption(i18n.get("caption.add.new.dist"));
UI.getCurrent().addWindow(newDistWindow); UI.getCurrent().addWindow(newDistWindow);
newDistWindow.setVisible(Boolean.TRUE); newDistWindow.setVisible(Boolean.TRUE);

View File

@@ -0,0 +1,97 @@
/**
* 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.distributions.dstable;
import java.util.List;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SpPermissionChecker;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
import org.eclipse.hawkbit.ui.common.AbstractMetadataPopupLayout;
import org.eclipse.hawkbit.ui.distributions.event.MetadataEvent;
import org.eclipse.hawkbit.ui.distributions.event.MetadataEvent.MetadataUIEvent;
import org.springframework.beans.factory.annotation.Autowired;
import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope;
/**
* Pop up layout to display distribution metadata.
*/
@SpringComponent
@ViewScope
public class DsMetadataPopupLayout extends AbstractMetadataPopupLayout<DistributionSet, DistributionSetMetadata> {
private static final long serialVersionUID = -7778944849012048106L;
@Autowired
private transient DistributionSetManagement distributionSetManagement;
@Autowired
private EntityFactory entityFactory;
@Autowired
protected SpPermissionChecker permChecker;
@Override
protected void checkForDuplicate(DistributionSet entity, String value) {
distributionSetManagement.findOne(entity, value);
}
/**
* Create metadata for DistributionSet.
*/
@Override
protected DistributionSetMetadata createMetadata(DistributionSet entity, String key, String value) {
DistributionSetMetadata dsMetaData = distributionSetManagement.createDistributionSetMetadata(entityFactory
.generateDistributionSetMetadata(entity, key, value));
setSelectedEntity(dsMetaData.getDistributionSet());
eventBus.publish(this, new MetadataEvent(MetadataUIEvent.CREATE_DISTRIBUTION_SET_METADATA, dsMetaData));
return dsMetaData;
}
/**
* Update metadata for DistributionSet.
*/
@Override
protected DistributionSetMetadata updateMetadata(DistributionSet entity, String key, String value) {
DistributionSetMetadata dsMetaData = distributionSetManagement.updateDistributionSetMetadata(entityFactory
.generateDistributionSetMetadata(entity, key, value));
setSelectedEntity(dsMetaData.getDistributionSet());
return dsMetaData;
}
@Override
protected List<DistributionSetMetadata> getMetadataList() {
return getSelectedEntity().getMetadata();
}
/**
* Update metadata for DistributionSet.
*/
@Override
protected void deleteMetadata(DistributionSet entity, String key, String value) {
DistributionSetMetadata dsMetaData = entityFactory.generateDistributionSetMetadata(entity, key, value);
distributionSetManagement.deleteDistributionSetMetadata(entity, key);
eventBus.publish(this, new MetadataEvent(MetadataUIEvent.DELETE_DISTRIBUTION_SET_METADATA, dsMetaData));
}
@Override
protected boolean hasCreatePermission() {
return permChecker.hasCreateDistributionPermission();
}
@Override
protected boolean hasUpdatePermission() {
return permChecker.hasUpdateDistributionPermission();
}
}

View File

@@ -0,0 +1,52 @@
/**
* 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.distributions.event;
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
/**
*
* Metadata Events.
*
*/
public class MetadataEvent {
public enum MetadataUIEvent {
CREATE_DISTRIBUTION_SET_METADATA, DELETE_DISTRIBUTION_SET_METADATA, DELETE_SOFTWARE_MODULE_METADATA, CREATE_SOFTWARE_MODULE_METADATA;
}
private MetadataUIEvent metadataUIEvent;
private DistributionSetMetadata distributionSetMetadata;
private SoftwareModuleMetadata softwareModuleMetadata;
public MetadataEvent(MetadataUIEvent metadataUIEvent, final DistributionSetMetadata distributionSetMetadata) {
this.metadataUIEvent = metadataUIEvent;
this.distributionSetMetadata = distributionSetMetadata;
}
public MetadataEvent(MetadataUIEvent metadataUIEvent, final SoftwareModuleMetadata softwareModuleMetadata) {
this.metadataUIEvent = metadataUIEvent;
this.softwareModuleMetadata = softwareModuleMetadata;
}
public MetadataUIEvent getMetadataUIEvent() {
return metadataUIEvent;
}
public DistributionSetMetadata getDistributionSetMetadata() {
return distributionSetMetadata;
}
public SoftwareModuleMetadata getSoftwareModuleMetadata() {
return softwareModuleMetadata;
}
}

View File

@@ -1,18 +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.distributions.event;
/**
*
*
*/
public enum SwModuleUIEvent {
HIDE_FILTER_BY_TYPE, SHOW_FILTER_BY_TYPE, DELETED_ALL_SOFWARE;
}

View File

@@ -0,0 +1,104 @@
/**
* 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.distributions.smtable;
import java.util.List;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareManagement;
import org.eclipse.hawkbit.repository.SpPermissionChecker;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
import org.eclipse.hawkbit.ui.common.AbstractMetadataPopupLayout;
import org.eclipse.hawkbit.ui.distributions.event.MetadataEvent;
import org.eclipse.hawkbit.ui.distributions.event.MetadataEvent.MetadataUIEvent;
import org.eclipse.hawkbit.ui.distributions.state.ManageDistUIState;
import org.springframework.beans.factory.annotation.Autowired;
import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope;
/**
* Pop up layout to display software module metadata.
*
*/
@SpringComponent
@ViewScope
public class SwMetadataPopupLayout extends AbstractMetadataPopupLayout<SoftwareModule, SoftwareModuleMetadata> {
private static final long serialVersionUID = -1252090014161012563L;
@Autowired
private transient SoftwareManagement softwareManagement;
@Autowired
private ArtifactUploadState artifactUploadState;
@Autowired
private EntityFactory entityFactory;
@Autowired
private ManageDistUIState manageDistUIState;
@Autowired
protected SpPermissionChecker permChecker;
@Override
protected void checkForDuplicate(SoftwareModule entity, String value) {
softwareManagement.findSoftwareModuleMetadata(entity, value);
}
/**
* Create metadata for SWModule.
*/
@Override
protected SoftwareModuleMetadata createMetadata(SoftwareModule entity, String key, String value) {
SoftwareModuleMetadata swMetadata = softwareManagement.createSoftwareModuleMetadata(entityFactory
.generateSoftwareModuleMetadata(entity, key, value));
setSelectedEntity(swMetadata.getSoftwareModule());
eventBus.publish(this, new MetadataEvent(MetadataUIEvent.CREATE_SOFTWARE_MODULE_METADATA, swMetadata));
return swMetadata;
}
/**
* Update metadata for SWModule.
*/
@Override
protected SoftwareModuleMetadata updateMetadata(SoftwareModule entity, String key, String value) {
SoftwareModuleMetadata swMetadata = softwareManagement.updateSoftwareModuleMetadata(entityFactory
.generateSoftwareModuleMetadata(entity, key, value));
setSelectedEntity(swMetadata.getSoftwareModule());
return swMetadata;
}
@Override
protected List<SoftwareModuleMetadata> getMetadataList() {
return getSelectedEntity().getMetadata();
}
/**
* delete metadata for SWModule.
*/
@Override
protected void deleteMetadata(SoftwareModule entity, String key, String value) {
SoftwareModuleMetadata swMetadata = entityFactory.generateSoftwareModuleMetadata(entity, key, value);
softwareManagement.deleteSoftwareModuleMetadata(entity, key);
eventBus.publish(this, new MetadataEvent(MetadataUIEvent.DELETE_SOFTWARE_MODULE_METADATA, swMetadata));
}
@Override
protected boolean hasCreatePermission() {
return permChecker.hasCreateDistributionPermission();
}
@Override
protected boolean hasUpdatePermission() {
return permChecker.hasUpdateDistributionPermission();
}
}

View File

@@ -8,11 +8,16 @@
*/ */
package org.eclipse.hawkbit.ui.distributions.smtable; package org.eclipse.hawkbit.ui.distributions.smtable;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareManagement;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent; import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent;
import org.eclipse.hawkbit.ui.artifacts.smtable.SoftwareModuleAddUpdateWindow; import org.eclipse.hawkbit.ui.artifacts.smtable.SoftwareModuleAddUpdateWindow;
import org.eclipse.hawkbit.ui.common.detailslayout.AbstractNamedVersionedEntityTableDetailsLayout; import org.eclipse.hawkbit.ui.common.detailslayout.AbstractNamedVersionedEntityTableDetailsLayout;
import org.eclipse.hawkbit.ui.common.detailslayout.SoftwareModuleMetadatadetailslayout;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.distributions.event.MetadataEvent;
import org.eclipse.hawkbit.ui.distributions.state.ManageDistUIState; import org.eclipse.hawkbit.ui.distributions.state.ManageDistUIState;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider; import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
@@ -45,6 +50,50 @@ public class SwModuleDetails extends AbstractNamedVersionedEntityTableDetailsLay
@Autowired @Autowired
private ManageDistUIState manageDistUIState; private ManageDistUIState manageDistUIState;
@Autowired
private transient SoftwareManagement softwareManagement;
@Autowired
private SwMetadataPopupLayout swMetadataPopupLayout;
@Autowired
private EntityFactory entityFactory;
private SoftwareModuleMetadatadetailslayout swmMetadataTable;
/**
* softwareLayout Initialize the component.
*/
@Override
protected void init() {
swmMetadataTable = new SoftwareModuleMetadatadetailslayout();
swmMetadataTable.init(getI18n(), getPermissionChecker(),softwareManagement,swMetadataPopupLayout,entityFactory);
super.init();
}
/**
* MetadataEvent.
*
* @param event
* as instance of {@link MetadataEvent}
*/
@EventBusListenerMethod(scope = EventScope.SESSION)
void onEvent(final MetadataEvent event) {
UI.getCurrent()
.access(() -> {
SoftwareModuleMetadata softwareModuleMetadata = event.getSoftwareModuleMetadata();
if (softwareModuleMetadata != null
&& isSoftwareModuleSelected(softwareModuleMetadata.getSoftwareModule())) {
if (event.getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.CREATE_SOFTWARE_MODULE_METADATA) {
swmMetadataTable.createMetadata(event.getSoftwareModuleMetadata().getKey());
} else if (event.getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.DELETE_SOFTWARE_MODULE_METADATA) {
swmMetadataTable.deleteMetadata(event.getSoftwareModuleMetadata().getKey());
}
}
});
}
@EventBusListenerMethod(scope = EventScope.SESSION) @EventBusListenerMethod(scope = EventScope.SESSION)
void onEvent(final SoftwareModuleEvent softwareModuleEvent) { void onEvent(final SoftwareModuleEvent softwareModuleEvent) {
onBaseEntityEvent(softwareModuleEvent); onBaseEntityEvent(softwareModuleEvent);
@@ -69,6 +118,7 @@ public class SwModuleDetails extends AbstractNamedVersionedEntityTableDetailsLay
detailsTab.addTab(createDetailsLayout(), getI18n().get("caption.tab.details"), null); detailsTab.addTab(createDetailsLayout(), getI18n().get("caption.tab.details"), null);
detailsTab.addTab(createDescriptionLayout(), getI18n().get("caption.tab.description"), null); detailsTab.addTab(createDescriptionLayout(), getI18n().get("caption.tab.description"), null);
detailsTab.addTab(createLogLayout(), getI18n().get("caption.logs.tab"), null); detailsTab.addTab(createLogLayout(), getI18n().get("caption.logs.tab"), null);
detailsTab.addTab(swmMetadataTable, getI18n().get("caption.metadata"), null);
} }
@Override @Override
@@ -93,7 +143,7 @@ public class SwModuleDetails extends AbstractNamedVersionedEntityTableDetailsLay
@Override @Override
protected String getTabSheetId() { protected String getTabSheetId() {
return null; return SPUIComponentIdProvider.DIST_SW_MODULE_DETAILS_TABSHEET_ID;
} }
private void populateDetails() { private void populateDetails() {
@@ -139,6 +189,7 @@ public class SwModuleDetails extends AbstractNamedVersionedEntityTableDetailsLay
@Override @Override
protected void populateDetailsWidget() { protected void populateDetailsWidget() {
populateDetails(); populateDetails();
populateMetadataDetails();
} }
@Override @Override
@@ -146,4 +197,33 @@ public class SwModuleDetails extends AbstractNamedVersionedEntityTableDetailsLay
return SPUIComponentIdProvider.TARGET_DETAILS_HEADER_LABEL_ID; return SPUIComponentIdProvider.TARGET_DETAILS_HEADER_LABEL_ID;
} }
@Override
protected void populateMetadataDetails() {
swmMetadataTable.populateSMMetadata(getSelectedBaseEntity());
}
private boolean isSoftwareModuleSelected(SoftwareModule softwareModule) {
final Long selectedDistSWModuleId = manageDistUIState.getSelectedBaseSwModuleId().isPresent() ? manageDistUIState
.getSelectedBaseSwModuleId().get() : null;
return softwareModule != null && selectedDistSWModuleId != null
&& selectedDistSWModuleId.equals(softwareModule.getId());
}
@Override
protected Boolean isMetadataIconToBeDisplayed() {
return true;
}
@Override
protected String getShowMetadataButtonId() {
SoftwareModule selectedBaseEntity = getSelectedBaseEntity();
return SPUIComponentIdProvider.SW_TABLE_MANAGE_METADATA_ID + "." + selectedBaseEntity.getName() + "."
+ selectedBaseEntity.getVersion();
}
@Override
protected void showMetadata(ClickEvent event) {
SoftwareModule swmodule = softwareManagement.findSoftwareModuleWithDetails(getSelectedBaseEntityId());
UI.getCurrent().addWindow(swMetadataPopupLayout.getWindow(swmodule, null));
}
} }

View File

@@ -51,6 +51,7 @@ import com.vaadin.shared.ui.window.WindowMode;
import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope; import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.Button; import com.vaadin.ui.Button;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.JavaScript; import com.vaadin.ui.JavaScript;
import com.vaadin.ui.Table; import com.vaadin.ui.Table;
import com.vaadin.ui.UI; import com.vaadin.ui.UI;
@@ -78,6 +79,9 @@ public class SwModuleTable extends AbstractNamedVersionTable<SoftwareModule, Lon
@Autowired @Autowired
private ArtifactDetailsLayout artifactDetailsLayout; private ArtifactDetailsLayout artifactDetailsLayout;
@Autowired
private SwMetadataPopupLayout swMetadataPopupLayout;
/** /**
* Initialize the filter layout. * Initialize the filter layout.
*/ */
@@ -175,16 +179,19 @@ public class SwModuleTable extends AbstractNamedVersionTable<SoftwareModule, Lon
protected void addCustomGeneratedColumns() { protected void addCustomGeneratedColumns() {
addGeneratedColumn(SPUILabelDefinitions.ARTIFACT_ICON, new ColumnGenerator() { addGeneratedColumn(SPUILabelDefinitions.ARTIFACT_ICON, new ColumnGenerator() {
private static final long serialVersionUID = -5982361782989980277L; private static final long serialVersionUID = -5982361782989980277L;
@Override @Override
public Object generateCell(final Table source, final Object itemId, final Object columnId) { public Object generateCell(final Table source, final Object itemId, final Object columnId) {
HorizontalLayout iconLayout = new HorizontalLayout();
// add artifactory details popup // add artifactory details popup
final String nameVersionStr = getNameAndVerion(itemId); final String nameVersionStr = getNameAndVerion(itemId);
final Button showArtifactDtlsBtn = createShowArtifactDtlsButton(nameVersionStr); final Button showArtifactDtlsBtn = createShowArtifactDtlsButton(nameVersionStr);
final Button manageMetaDataBtn = createManageMetadataButton(nameVersionStr);
showArtifactDtlsBtn.addClickListener(event -> showArtifactDetailsWindow((Long) itemId, nameVersionStr)); showArtifactDtlsBtn.addClickListener(event -> showArtifactDetailsWindow((Long) itemId, nameVersionStr));
return showArtifactDtlsBtn; manageMetaDataBtn.addClickListener(event -> showMetadataDetails((Long) itemId));
iconLayout.addComponent(showArtifactDtlsBtn);
iconLayout.addComponent(manageMetaDataBtn);
return iconLayout;
} }
}); });
} }
@@ -207,6 +214,9 @@ public class SwModuleTable extends AbstractNamedVersionTable<SoftwareModule, Lon
@Override @Override
protected void publishEntityAfterValueChange(final SoftwareModule selectedLastEntity) { protected void publishEntityAfterValueChange(final SoftwareModule selectedLastEntity) {
eventBus.publish(this, new SoftwareModuleEvent(BaseEntityEventType.SELECTED_ENTITY, selectedLastEntity)); eventBus.publish(this, new SoftwareModuleEvent(BaseEntityEventType.SELECTED_ENTITY, selectedLastEntity));
if(selectedLastEntity!=null){
manageDistUIState.setSelectedBaseSwModuleId(selectedLastEntity.getId());
}
} }
@Override @Override
@@ -310,12 +320,21 @@ public class SwModuleTable extends AbstractNamedVersionTable<SoftwareModule, Lon
private Button createShowArtifactDtlsButton(final String nameVersionStr) { private Button createShowArtifactDtlsButton(final String nameVersionStr) {
final Button showArtifactDtlsBtn = SPUIComponentProvider.getButton( final Button showArtifactDtlsBtn = SPUIComponentProvider.getButton(
SPUIComponentIdProvider.SW_TABLE_ATRTIFACT_DETAILS_ICON + "." + nameVersionStr, "", "", null, false, SPUIComponentIdProvider.SW_TABLE_ATRTIFACT_DETAILS_ICON + "." + nameVersionStr, "", "", null, false,
FontAwesome.LIST_ALT, SPUIButtonStyleSmallNoBorder.class); FontAwesome.FILE_O, SPUIButtonStyleSmallNoBorder.class);
showArtifactDtlsBtn.addStyleName(SPUIStyleDefinitions.ARTIFACT_DTLS_ICON); showArtifactDtlsBtn.addStyleName(SPUIStyleDefinitions.ARTIFACT_DTLS_ICON);
showArtifactDtlsBtn.setDescription(i18n.get("tooltip.artifact.icon")); showArtifactDtlsBtn.setDescription(i18n.get("tooltip.artifact.icon"));
return showArtifactDtlsBtn; return showArtifactDtlsBtn;
} }
private Button createManageMetadataButton(String nameVersionStr) {
final Button manageMetadataBtn = SPUIComponentProvider.getButton(
SPUIComponentIdProvider.SW_TABLE_MANAGE_METADATA_ID + "." + nameVersionStr, "", "", null, false,
FontAwesome.LIST_ALT, SPUIButtonStyleSmallNoBorder.class);
manageMetadataBtn.addStyleName(SPUIStyleDefinitions.ARTIFACT_DTLS_ICON);
manageMetadataBtn.setDescription(i18n.get("tooltip.metadata.icon"));
return manageMetadataBtn;
}
private String getNameAndVerion(final Object itemId) { private String getNameAndVerion(final Object itemId) {
final Item item = getItem(itemId); final Item item = getItem(itemId);
final String name = (String) item.getItemProperty(SPUILabelDefinitions.VAR_NAME).getValue(); final String name = (String) item.getItemProperty(SPUILabelDefinitions.VAR_NAME).getValue();
@@ -388,4 +407,9 @@ public class SwModuleTable extends AbstractNamedVersionTable<SoftwareModule, Lon
} }
private void showMetadataDetails(Long itemId) {
SoftwareModule swmodule = softwareManagement.findSoftwareModuleWithDetails(itemId);
UI.getCurrent().addWindow(swMetadataPopupLayout.getWindow(swmodule,null));
}
} }

View File

@@ -87,7 +87,7 @@ public class TargetFilterTable extends Table {
setStyleName("sp-table"); setStyleName("sp-table");
setSizeFull(); setSizeFull();
setImmediate(true); setImmediate(true);
setHeight(100.0f, Unit.PERCENTAGE); setHeight(100.0F, Unit.PERCENTAGE);
addStyleName(ValoTheme.TABLE_NO_VERTICAL_LINES); addStyleName(ValoTheme.TABLE_NO_VERTICAL_LINES);
addStyleName(ValoTheme.TABLE_SMALL); addStyleName(ValoTheme.TABLE_SMALL);
addCustomGeneratedColumns(); addCustomGeneratedColumns();

View File

@@ -20,17 +20,16 @@ import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerLayout; import org.eclipse.hawkbit.ui.colorpicker.ColorPickerLayout;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow; import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIWindowDecorator;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.I18N; import org.eclipse.hawkbit.ui.utils.I18N;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider; import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions; import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions; import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.UINotification; import org.eclipse.hawkbit.ui.utils.UINotification;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.spring.events.EventBus; import org.vaadin.spring.events.EventBus;
import com.google.common.base.Strings;
import com.vaadin.data.Property.ValueChangeEvent; import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener; import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.server.Page; import com.vaadin.server.Page;
@@ -87,7 +86,6 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
protected CommonDialogWindow window; protected CommonDialogWindow window;
protected Label colorLabel; protected Label colorLabel;
protected Label madatoryLabel;
protected TextField tagName; protected TextField tagName;
protected TextArea tagDesc; protected TextArea tagDesc;
protected Button tagColorPreviewBtn; protected Button tagColorPreviewBtn;
@@ -99,17 +97,13 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
protected GridLayout mainLayout; protected GridLayout mainLayout;
protected VerticalLayout contentLayout; protected VerticalLayout contentLayout;
protected boolean tagPreviewBtnClicked = false; protected boolean tagPreviewBtnClicked;
private String colorPicked; private String colorPicked;
protected String tagNameValue; protected String tagNameValue;
protected String tagDescValue; protected String tagDescValue;
protected void createWindow() { protected abstract String getWindowCaption();
reset();
setWindow(SPUIComponentProvider.getWindow(i18n.get("caption.add.tag"), null,
SPUIDefinitions.CREATE_UPDATE_WINDOW, this, this::save, this::discard, null));
}
/** /**
* Save new tag / update new tag. * Save new tag / update new tag.
@@ -142,7 +136,6 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
setSizeUndefined(); setSizeUndefined();
createRequiredComponents(); createRequiredComponents();
buildLayout(); buildLayout();
createWindow();
addListeners(); addListeners();
eventBus.subscribe(this); eventBus.subscribe(this);
} }
@@ -157,7 +150,6 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
createTagStr = i18n.get("label.create.tag"); createTagStr = i18n.get("label.create.tag");
updateTagStr = i18n.get("label.update.tag"); updateTagStr = i18n.get("label.update.tag");
comboLabel = SPUIComponentProvider.getLabel(i18n.get("label.choose.tag"), null); comboLabel = SPUIComponentProvider.getLabel(i18n.get("label.choose.tag"), null);
madatoryLabel = getMandatoryLabel();
colorLabel = SPUIComponentProvider.getLabel(i18n.get("label.choose.tag.color"), null); colorLabel = SPUIComponentProvider.getLabel(i18n.get("label.choose.tag.color"), null);
colorLabel.addStyleName(SPUIDefinitions.COLOR_LABEL_STYLE); colorLabel.addStyleName(SPUIDefinitions.COLOR_LABEL_STYLE);
@@ -169,7 +161,6 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
tagDesc = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "", tagDesc = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "",
ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TAG_DESC, false, "", i18n.get("textfield.description"), ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TAG_DESC, false, "", i18n.get("textfield.description"),
SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH); SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
tagDesc.setId(SPUIDefinitions.NEW_TARGET_TAG_DESC); tagDesc.setId(SPUIDefinitions.NEW_TARGET_TAG_DESC);
tagDesc.setImmediate(true); tagDesc.setImmediate(true);
tagDesc.setNullRepresentation(""); tagDesc.setNullRepresentation("");
@@ -178,6 +169,7 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
i18n.get("label.combobox.tag")); i18n.get("label.combobox.tag"));
tagNameComboBox.addStyleName(SPUIDefinitions.FILTER_TYPE_COMBO_STYLE); tagNameComboBox.addStyleName(SPUIDefinitions.FILTER_TYPE_COMBO_STYLE);
tagNameComboBox.setImmediate(true); tagNameComboBox.setImmediate(true);
tagNameComboBox.setId(SPUIComponentIdProvider.DIST_TAG_COMBO);
tagColorPreviewBtn = new Button(); tagColorPreviewBtn = new Button();
tagColorPreviewBtn.setId(SPUIComponentIdProvider.TAG_COLOR_PREVIEW_ID); tagColorPreviewBtn.setId(SPUIComponentIdProvider.TAG_COLOR_PREVIEW_ID);
@@ -200,7 +192,6 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
formLayout.addComponent(optiongroup); formLayout.addComponent(optiongroup);
formLayout.addComponent(comboLayout); formLayout.addComponent(comboLayout);
formLayout.addComponent(madatoryLabel);
formLayout.addComponent(tagName); formLayout.addComponent(tagName);
formLayout.addComponent(tagDesc); formLayout.addComponent(tagDesc);
formLayout.addStyleName("form-lastrow"); formLayout.addStyleName("form-lastrow");
@@ -215,6 +206,10 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
mainLayout.setSizeFull(); mainLayout.setSizeFull();
mainLayout.addComponent(contentLayout, 0, 0); mainLayout.addComponent(contentLayout, 0, 0);
colorPickerLayout.setVisible(false);
mainLayout.addComponent(colorPickerLayout, 1, 0);
mainLayout.setComponentAlignment(colorPickerLayout, Alignment.MIDDLE_CENTER);
setCompositionRoot(mainLayout); setCompositionRoot(mainLayout);
tagName.focus(); tagName.focus();
} }
@@ -234,13 +229,10 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
protected void previewButtonClicked() { protected void previewButtonClicked() {
if (!tagPreviewBtnClicked) { if (!tagPreviewBtnClicked) {
setColor(); setColor();
mainLayout.getComponent(1, 0);
mainLayout.addComponent(colorPickerLayout, 1, 0);
mainLayout.setComponentAlignment(colorPickerLayout, Alignment.MIDDLE_CENTER);
} else {
mainLayout.removeComponent(colorPickerLayout);
} }
tagPreviewBtnClicked = !tagPreviewBtnClicked; tagPreviewBtnClicked = !tagPreviewBtnClicked;
colorPickerLayout.setVisible(tagPreviewBtnClicked);
} }
private void setColor() { private void setColor() {
@@ -270,12 +262,6 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
} }
} }
protected Label getMandatoryLabel() {
final Label label = new Label(i18n.get("label.mandatory.field"));
label.setStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR + " " + ValoTheme.LABEL_SMALL);
return label;
}
private void tagNameChosen(final ValueChangeEvent event) { private void tagNameChosen(final ValueChangeEvent event) {
final String tagSelected = (String) event.getProperty().getValue(); final String tagSelected = (String) event.getProperty().getValue();
if (null != tagSelected) { if (null != tagSelected) {
@@ -283,6 +269,7 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
} else { } else {
resetTagNameField(); resetTagNameField();
} }
window.setOrginaleValues();
} }
protected void resetTagNameField() { protected void resetTagNameField() {
@@ -290,7 +277,6 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
tagName.clear(); tagName.clear();
tagDesc.clear(); tagDesc.clear();
restoreComponentStyles(); restoreComponentStyles();
mainLayout.removeComponent(colorPickerLayout);
colorPickerLayout.setSelectedColor(colorPickerLayout.getDefaultColor()); colorPickerLayout.setSelectedColor(colorPickerLayout.getDefaultColor());
colorPickerLayout.getSelPreview().setColor(colorPickerLayout.getSelectedColor()); colorPickerLayout.getSelPreview().setColor(colorPickerLayout.getSelectedColor());
tagPreviewBtnClicked = false; tagPreviewBtnClicked = false;
@@ -327,7 +313,7 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
getPreviewButtonColor(ColorPickerConstants.DEFAULT_COLOR); getPreviewButtonColor(ColorPickerConstants.DEFAULT_COLOR);
colorPickerLayout.getSelPreview() colorPickerLayout.getSelPreview()
.setColor(ColorPickerHelper.rgbToColorConverter(ColorPickerConstants.DEFAULT_COLOR)); .setColor(ColorPickerHelper.rgbToColorConverter(ColorPickerConstants.DEFAULT_COLOR));
mainLayout.removeComponent(colorPickerLayout); window.setOrginaleValues();
} }
/** /**
@@ -342,9 +328,9 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
// hide target name combo // hide target name combo
comboLayout.removeComponent(comboLabel); comboLayout.removeComponent(comboLabel);
comboLayout.removeComponent(tagNameComboBox); comboLayout.removeComponent(tagNameComboBox);
mainLayout.removeComponent(colorPickerLayout);
// Default green color // Default green color
colorPickerLayout.setVisible(false);
colorPickerLayout.setSelectedColor(colorPickerLayout.getDefaultColor()); colorPickerLayout.setSelectedColor(colorPickerLayout.getDefaultColor());
colorPickerLayout.getSelPreview().setColor(colorPickerLayout.getSelectedColor()); colorPickerLayout.getSelPreview().setColor(colorPickerLayout.getSelectedColor());
tagPreviewBtnClicked = false; tagPreviewBtnClicked = false;
@@ -389,6 +375,7 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
*/ */
protected void createDynamicStyleForComponents(final TextField tagName, final TextArea tagDesc, protected void createDynamicStyleForComponents(final TextField tagName, final TextArea tagDesc,
final String taregtTagColor) { final String taregtTagColor) {
tagName.removeStyleName(SPUIDefinitions.TAG_NAME); tagName.removeStyleName(SPUIDefinitions.TAG_NAME);
tagDesc.removeStyleName(SPUIDefinitions.TAG_DESC); tagDesc.removeStyleName(SPUIDefinitions.TAG_DESC);
getTargetDynamicStyles(taregtTagColor); getTargetDynamicStyles(taregtTagColor);
@@ -435,11 +422,7 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
createDynamicStyleForComponents(tagName, tagDesc, colorPickedPreview); createDynamicStyleForComponents(tagName, tagDesc, colorPickedPreview);
colorPickerLayout.getColorSelect().setColor(colorPickerLayout.getSelPreview().getColor()); colorPickerLayout.getColorSelect().setColor(colorPickerLayout.getSelPreview().getColor());
} }
}
protected void closeWindow() {
window.close();
UI.getCurrent().removeWindow(window);
} }
/** /**
@@ -448,6 +431,7 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
protected void createOptionGroup(final boolean hasCreatePermission, final boolean hasUpdatePermission) { protected void createOptionGroup(final boolean hasCreatePermission, final boolean hasUpdatePermission) {
optiongroup = new OptionGroup("Select Action"); optiongroup = new OptionGroup("Select Action");
optiongroup.setId(SPUIComponentIdProvider.OPTION_GROUP);
optiongroup.addStyleName(ValoTheme.OPTIONGROUP_SMALL); optiongroup.addStyleName(ValoTheme.OPTIONGROUP_SMALL);
optiongroup.addStyleName("custom-option-group"); optiongroup.addStyleName("custom-option-group");
optiongroup.setNullSelectionAllowed(false); optiongroup.setNullSelectionAllowed(false);
@@ -472,27 +456,17 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
} }
} }
@Override
public void addColorChangeListener(final ColorChangeListener listener) {
}
@Override
public void removeColorChangeListener(final ColorChangeListener listener) {
}
public ColorPickerLayout getColorPickerLayout() { public ColorPickerLayout getColorPickerLayout() {
return colorPickerLayout; return colorPickerLayout;
} }
public CommonDialogWindow getWindow() { public CommonDialogWindow getWindow() {
reset(); reset();
window = SPUIWindowDecorator.getWindow(getWindowCaption(), null, SPUIDefinitions.CREATE_UPDATE_WINDOW, this,
this::save, this::discard, null, mainLayout, i18n);
return window; return window;
} }
public void setWindow(final CommonDialogWindow window) {
this.window = window;
}
/** /**
* Value change listeners implementations of sliders. * Value change listeners implementations of sliders.
*/ */
@@ -565,7 +539,6 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
tagManagement.updateDistributionSetTag((DistributionSetTag) targetObj); tagManagement.updateDistributionSetTag((DistributionSetTag) targetObj);
} }
uiNotification.displaySuccess(i18n.get("message.update.success", new Object[] { targetObj.getName() })); uiNotification.displaySuccess(i18n.get("message.update.success", new Object[] { targetObj.getName() }));
closeWindow();
} else { } else {
uiNotification.displayValidationError(i18n.get("message.tag.update.mandatory")); uiNotification.displayValidationError(i18n.get("message.tag.update.mandatory"));
} }
@@ -587,27 +560,6 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
getPreviewButtonColor(previewColor); getPreviewButtonColor(previewColor);
} }
/**
*
* @return
*/
protected Boolean mandatoryValuesPresent() {
if (Strings.isNullOrEmpty(tagName.getValue())) {
if (optiongroup.getValue().equals(createTagStr)) {
displayValidationError(SPUILabelDefinitions.MISSING_TAG_NAME);
}
if (optiongroup.getValue().equals(updateTagStr)) {
if (null == tagNameComboBox.getValue()) {
displayValidationError(i18n.get(MESSAGE_ERROR_MISSING_TAGNAME));
} else {
displayValidationError(SPUILabelDefinitions.MISSING_TAG_NAME);
}
}
return Boolean.FALSE;
}
return Boolean.TRUE;
}
protected Boolean checkIsDuplicate(final Tag existingTag) { protected Boolean checkIsDuplicate(final Tag existingTag) {
if (existingTag != null) { if (existingTag != null) {
displayValidationError(i18n.get("message.tag.duplicate.check", new Object[] { existingTag.getName() })); displayValidationError(i18n.get("message.tag.duplicate.check", new Object[] { existingTag.getName() }));
@@ -644,4 +596,16 @@ public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
return formLayout; return formLayout;
} }
public GridLayout getMainLayout() {
return mainLayout;
}
@Override
public void addColorChangeListener(final ColorChangeListener listener) {
}
@Override
public void removeColorChangeListener(final ColorChangeListener listener) {
}
} }

View File

@@ -17,9 +17,7 @@ import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider; import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions; import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import com.google.common.base.Strings;
import com.vaadin.data.Property.ValueChangeEvent; import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.server.Page; import com.vaadin.server.Page;
import com.vaadin.shared.ui.colorpicker.Color; import com.vaadin.shared.ui.colorpicker.Color;
@@ -33,12 +31,10 @@ import com.vaadin.ui.components.colorpicker.ColorSelector;
import com.vaadin.ui.themes.ValoTheme; import com.vaadin.ui.themes.ValoTheme;
/** /**
*
* Superclass defining common properties and methods for creating/updating * Superclass defining common properties and methods for creating/updating
* types. * types.
*
*/ */
public class CreateUpdateTypeLayout extends AbstractCreateUpdateTagLayout { public abstract class CreateUpdateTypeLayout extends AbstractCreateUpdateTagLayout {
private static final long serialVersionUID = 5732904956185988397L; private static final long serialVersionUID = 5732904956185988397L;
@@ -52,7 +48,7 @@ public class CreateUpdateTypeLayout extends AbstractCreateUpdateTagLayout {
@Override @Override
protected void addListeners() { protected void addListeners() {
super.addListeners(); super.addListeners();
optiongroup.addValueChangeListener(this::createOptionValueChanged); optiongroup.addValueChangeListener(this::optionValueChanged);
} }
@Override @Override
@@ -61,7 +57,6 @@ public class CreateUpdateTypeLayout extends AbstractCreateUpdateTagLayout {
createTypeStr = i18n.get("label.create.type"); createTypeStr = i18n.get("label.create.type");
updateTypeStr = i18n.get("label.update.type"); updateTypeStr = i18n.get("label.update.type");
comboLabel = SPUIComponentProvider.getLabel(i18n.get("label.choose.type"), null); comboLabel = SPUIComponentProvider.getLabel(i18n.get("label.choose.type"), null);
madatoryLabel = getMandatoryLabel();
colorLabel = SPUIComponentProvider.getLabel(i18n.get("label.choose.type.color"), null); colorLabel = SPUIComponentProvider.getLabel(i18n.get("label.choose.type.color"), null);
colorLabel.addStyleName(SPUIDefinitions.COLOR_LABEL_STYLE); colorLabel.addStyleName(SPUIDefinitions.COLOR_LABEL_STYLE);
@@ -137,7 +132,8 @@ public class CreateUpdateTypeLayout extends AbstractCreateUpdateTagLayout {
* @param event * @param event
* ValueChangeEvent * ValueChangeEvent
*/ */
protected void createOptionValueChanged(final ValueChangeEvent event) { @Override
protected void optionValueChanged(final ValueChangeEvent event) {
if (updateTypeStr.equals(event.getProperty().getValue())) { if (updateTypeStr.equals(event.getProperty().getValue())) {
tagName.clear(); tagName.clear();
@@ -151,7 +147,6 @@ public class CreateUpdateTypeLayout extends AbstractCreateUpdateTagLayout {
} else { } else {
typeKey.setEnabled(true); typeKey.setEnabled(true);
tagName.setEnabled(true); tagName.setEnabled(true);
window.setSaveButtonEnabled(true);
tagName.clear(); tagName.clear();
tagDesc.clear(); tagDesc.clear();
typeKey.clear(); typeKey.clear();
@@ -203,6 +198,7 @@ public class CreateUpdateTypeLayout extends AbstractCreateUpdateTagLayout {
protected void createOptionGroup(final boolean hasCreatePermission, final boolean hasUpdatePermission) { protected void createOptionGroup(final boolean hasCreatePermission, final boolean hasUpdatePermission) {
optiongroup = new OptionGroup("Select Action"); optiongroup = new OptionGroup("Select Action");
optiongroup.setId(SPUIComponentIdProvider.OPTION_GROUP);
optiongroup.addStyleName(ValoTheme.OPTIONGROUP_SMALL); optiongroup.addStyleName(ValoTheme.OPTIONGROUP_SMALL);
optiongroup.addStyleName("custom-option-group"); optiongroup.addStyleName("custom-option-group");
optiongroup.setNullSelectionAllowed(false); optiongroup.setNullSelectionAllowed(false);
@@ -285,24 +281,6 @@ public class CreateUpdateTypeLayout extends AbstractCreateUpdateTagLayout {
return Boolean.FALSE; return Boolean.FALSE;
} }
@Override
protected Boolean mandatoryValuesPresent() {
if (Strings.isNullOrEmpty(tagName.getValue()) || Strings.isNullOrEmpty(typeKey.getValue())) {
if (optiongroup.getValue().equals(createTypeStr)) {
displayValidationError(SPUILabelDefinitions.MISSING_TYPE_NAME_KEY);
}
if (optiongroup.getValue().equals(updateTypeStr)) {
if (null == tagNameComboBox.getValue()) {
displayValidationError(i18n.get("message.error.missing.tagName"));
} else {
displayValidationError(SPUILabelDefinitions.MISSING_TAG_NAME);
}
}
return Boolean.FALSE;
}
return Boolean.TRUE;
}
@Override @Override
protected void save(final ClickEvent event) { protected void save(final ClickEvent event) {
// is implemented in the inherited class // is implemented in the inherited class

View File

@@ -27,11 +27,11 @@ import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.ui.common.ConfirmationDialog; import org.eclipse.hawkbit.ui.common.ConfirmationDialog;
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.management.event.ManagementUIEvent; import org.eclipse.hawkbit.ui.management.event.ManagementUIEvent;
import org.eclipse.hawkbit.ui.management.event.PinUnpinEvent; import org.eclipse.hawkbit.ui.management.event.PinUnpinEvent;
import org.eclipse.hawkbit.ui.management.event.TargetTableEvent; import org.eclipse.hawkbit.ui.management.event.TargetTableEvent;
import org.eclipse.hawkbit.ui.management.state.ManagementUIState; import org.eclipse.hawkbit.ui.management.state.ManagementUIState;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.I18N; import org.eclipse.hawkbit.ui.utils.I18N;
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil; import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider; import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
@@ -50,15 +50,14 @@ import org.vaadin.spring.events.EventBus;
import org.vaadin.spring.events.EventScope; import org.vaadin.spring.events.EventScope;
import org.vaadin.spring.events.annotation.EventBusListenerMethod; import org.vaadin.spring.events.annotation.EventBusListenerMethod;
import com.google.common.collect.Lists;
import com.vaadin.data.Container; import com.vaadin.data.Container;
import com.vaadin.data.Item; import com.vaadin.data.Item;
import com.vaadin.data.util.HierarchicalContainer; import com.vaadin.data.util.HierarchicalContainer;
import com.vaadin.event.Action.Handler;
import com.vaadin.server.FontAwesome; import com.vaadin.server.FontAwesome;
import com.vaadin.shared.ui.label.ContentMode; import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope; import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component; import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label; import com.vaadin.ui.Label;
@@ -74,11 +73,13 @@ import com.vaadin.ui.themes.ValoTheme;
*/ */
@SpringComponent @SpringComponent
@ViewScope @ViewScope
public class ActionHistoryTable extends TreeTable implements Handler { public class ActionHistoryTable extends TreeTable {
private static final long serialVersionUID = -1631514704696786653L;
private static final Logger LOG = LoggerFactory.getLogger(ActionHistoryTable.class);
private static final String BUTTON_CANCEL = "button.cancel"; private static final String BUTTON_CANCEL = "button.cancel";
private static final String BUTTON_OK = "button.ok"; private static final String BUTTON_OK = "button.ok";
private static final long serialVersionUID = -1631514704696786653L;
@Autowired @Autowired
private I18N i18n; private I18N i18n;
@@ -95,14 +96,10 @@ public class ActionHistoryTable extends TreeTable implements Handler {
private ManagementUIState managementUIState; private ManagementUIState managementUIState;
private Container hierarchicalContainer; private Container hierarchicalContainer;
private boolean alreadyHasMessages = false; private boolean alreadyHasMessages;
private Target target; private Target target;
com.vaadin.event.Action actionCancel;
com.vaadin.event.Action actionForce;
com.vaadin.event.Action actionForceQuit;
private static final Logger LOG = LoggerFactory.getLogger(ActionHistoryTable.class);
private static final String STATUS_ICON_GREEN = "statusIconGreen"; private static final String STATUS_ICON_GREEN = "statusIconGreen";
/** /**
@@ -110,10 +107,6 @@ public class ActionHistoryTable extends TreeTable implements Handler {
*/ */
@PostConstruct @PostConstruct
public void init() { public void init() {
actionCancel = new com.vaadin.event.Action(i18n.get("message.cancel.action"));
actionForceQuit = new com.vaadin.event.Action(i18n.get("message.forcequit.action"));
actionForceQuit.setIcon(FontAwesome.WARNING);
actionForce = new com.vaadin.event.Action(i18n.get("message.force.action"));
initializeTableSettings(); initializeTableSettings();
buildComponent(); buildComponent();
restorePreviousState(); restorePreviousState();
@@ -150,11 +143,12 @@ public class ActionHistoryTable extends TreeTable implements Handler {
} }
private void setColumnExpandRatioForMinimisedTable() { private void setColumnExpandRatioForMinimisedTable() {
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID, 0.1f); setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID, 0.1F);
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_DIST, 0.3f); setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_DIST, 0.3F);
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_STATUS, 0.15f); setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_STATUS, 0.15F);
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_DATETIME, 0.3f); setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_DATETIME, 0.3F);
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_FORCED, 0.15f); setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_FORCED, 0.15F);
setColumnExpandRatio(SPUIDefinitions.ACTIONS_COLUMN, 0.2F);
} }
private void initializeTableSettings() { private void initializeTableSettings() {
@@ -164,14 +158,15 @@ public class ActionHistoryTable extends TreeTable implements Handler {
setMultiSelect(false); setMultiSelect(false);
setSortEnabled(true); setSortEnabled(true);
setColumnReorderingAllowed(true); setColumnReorderingAllowed(true);
setHeight(100.0f, Unit.PERCENTAGE); setHeight(100.0F, Unit.PERCENTAGE);
setWidth(100.0f, Unit.PERCENTAGE); setWidth(100.0F, Unit.PERCENTAGE);
setImmediate(true); setImmediate(true);
setStyleName("sp-table"); setStyleName("sp-table");
addStyleName(ValoTheme.TABLE_NO_VERTICAL_LINES); addStyleName(ValoTheme.TABLE_NO_VERTICAL_LINES);
addStyleName(ValoTheme.TABLE_SMALL); addStyleName(ValoTheme.TABLE_SMALL);
setColumnAlignment(SPUIDefinitions.ACTION_HIS_TBL_FORCED, Align.CENTER); setColumnAlignment(SPUIDefinitions.ACTION_HIS_TBL_FORCED, Align.CENTER);
setColumnAlignment(SPUIDefinitions.ACTION_HIS_TBL_STATUS, Align.CENTER); setColumnAlignment(SPUIDefinitions.ACTION_HIS_TBL_STATUS, Align.CENTER);
setColumnAlignment(SPUIDefinitions.ACTIONS_COLUMN, Align.CENTER);
// listeners for child // listeners for child
addExpandListener(event -> { addExpandListener(event -> {
expandParentActionRow(event.getItemId()); expandParentActionRow(event.getItemId());
@@ -181,11 +176,6 @@ public class ActionHistoryTable extends TreeTable implements Handler {
collapseParentActionRow(event.getItemId()); collapseParentActionRow(event.getItemId());
managementUIState.getExpandParentActionRowId().remove(event.getItemId()); managementUIState.getExpandParentActionRowId().remove(event.getItemId());
}); });
/*
* Add the cancel action handler for active actions. To be used to
* cancel the action.
*/
addActionHandler(this);
} }
/** /**
@@ -204,6 +194,7 @@ public class ActionHistoryTable extends TreeTable implements Handler {
null); null);
hierarchicalContainer.addContainerProperty(SPUIDefinitions.ACTION_HIS_TBL_MSGS_HIDDEN, List.class, null); hierarchicalContainer.addContainerProperty(SPUIDefinitions.ACTION_HIS_TBL_MSGS_HIDDEN, List.class, null);
hierarchicalContainer.addContainerProperty(SPUIDefinitions.ACTION_HIS_TBL_ROLLOUT_NAME, String.class, null); hierarchicalContainer.addContainerProperty(SPUIDefinitions.ACTION_HIS_TBL_ROLLOUT_NAME, String.class, null);
} }
private List<Object> getVisbleColumns() { private List<Object> getVisbleColumns() {
@@ -213,6 +204,8 @@ public class ActionHistoryTable extends TreeTable implements Handler {
visibleColumnIds.add(SPUIDefinitions.ACTION_HIS_TBL_DATETIME); visibleColumnIds.add(SPUIDefinitions.ACTION_HIS_TBL_DATETIME);
visibleColumnIds.add(SPUIDefinitions.ACTION_HIS_TBL_STATUS); visibleColumnIds.add(SPUIDefinitions.ACTION_HIS_TBL_STATUS);
visibleColumnIds.add(SPUIDefinitions.ACTION_HIS_TBL_FORCED); visibleColumnIds.add(SPUIDefinitions.ACTION_HIS_TBL_FORCED);
visibleColumnIds.add(SPUIDefinitions.ACTIONS_COLUMN);
if (managementUIState.isActionHistoryMaximized()) { if (managementUIState.isActionHistoryMaximized()) {
visibleColumnIds.add(SPUIDefinitions.ACTION_HIS_TBL_ROLLOUT_NAME); visibleColumnIds.add(SPUIDefinitions.ACTION_HIS_TBL_ROLLOUT_NAME);
visibleColumnIds.add(SPUIDefinitions.ACTION_HIS_TBL_MSGS); visibleColumnIds.add(SPUIDefinitions.ACTION_HIS_TBL_MSGS);
@@ -300,23 +293,22 @@ public class ActionHistoryTable extends TreeTable implements Handler {
* add distribution name to the item which will be displayed in the * add distribution name to the item which will be displayed in the
* table. The name should not exceed certain limit. * table. The name should not exceed certain limit.
*/ */
item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_DIST).setValue(actionWithStatusCount.getDsName() + ":" + item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_DIST)
actionWithStatusCount.getDsVersion()); .setValue(actionWithStatusCount.getDsName() + ":" + actionWithStatusCount.getDsVersion());
item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_FORCED).setValue(action); item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_FORCED).setValue(action);
/* Default no child */ /* Default no child */
((Hierarchical) hierarchicalContainer).setChildrenAllowed(actionWithStatusCount.getAction().getId(), false); ((Hierarchical) hierarchicalContainer).setChildrenAllowed(actionWithStatusCount.getAction().getId(), false);
item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_DATETIME) item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_DATETIME)
.setValue(SPDateTimeUtil.getFormattedDate((actionWithStatusCount.getAction().getLastModifiedAt() != null) .setValue(SPDateTimeUtil.getFormattedDate(actionWithStatusCount.getAction().getLastModifiedAt()));
? actionWithStatusCount.getAction().getLastModifiedAt()
: actionWithStatusCount.getAction().getLastModifiedAt()));
item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ROLLOUT_NAME) item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ROLLOUT_NAME)
.setValue(actionWithStatusCount.getRolloutName()); .setValue(actionWithStatusCount.getRolloutName());
if (actionWithStatusCount.getActionStatusCount() > 0) { if (actionWithStatusCount.getActionStatusCount() > 0) {
((Hierarchical) hierarchicalContainer).setChildrenAllowed(actionWithStatusCount.getAction().getId(), true); ((Hierarchical) hierarchicalContainer).setChildrenAllowed(actionWithStatusCount.getAction().getId(),
true);
} }
} }
} }
@@ -350,12 +342,18 @@ public class ActionHistoryTable extends TreeTable implements Handler {
return getForcedColumn(itemId); return getForcedColumn(itemId);
} }
}); });
addGeneratedColumn(SPUIDefinitions.ACTIONS_COLUMN, new Table.ColumnGenerator() {
private static final long serialVersionUID = 1L;
@Override
public Component generateCell(final Table source, final Object itemId, final Object columnId) {
return createActionBarColumn(itemId);
}
});
} }
/**
* @param itemId
* @return
*/
private Component getForcedColumn(final Object itemId) { private Component getForcedColumn(final Object itemId) {
final Action actionWithActiveStatus = (Action) hierarchicalContainer.getItem(itemId) final Action actionWithActiveStatus = (Action) hierarchicalContainer.getItem(itemId)
.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_FORCED).getValue(); .getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_FORCED).getValue();
@@ -372,10 +370,6 @@ public class ActionHistoryTable extends TreeTable implements Handler {
return actionLabel; return actionLabel;
} }
/**
* @param itemId
* @return
*/
private Component getActiveColumn(final Object itemId) { private Component getActiveColumn(final Object itemId) {
final Action.Status status = (Action.Status) hierarchicalContainer.getItem(itemId) final Action.Status status = (Action.Status) hierarchicalContainer.getItem(itemId)
.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_STATUS_HIDDEN).getValue(); .getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_STATUS_HIDDEN).getValue();
@@ -397,10 +391,44 @@ public class ActionHistoryTable extends TreeTable implements Handler {
return activeStatusIcon; return activeStatusIcon;
} }
/** private HorizontalLayout createActionBarColumn(final Object itemId) {
* @param itemId final HorizontalLayout actionBar = new HorizontalLayout();
* @return final Item item = hierarchicalContainer.getItem(itemId);
*/ final Long actionId = (Long) item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID_HIDDEN).getValue();
final String activeValue = (String) item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE_HIDDEN)
.getValue();
final Action actionWithActiveStatus = (Action) item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_FORCED)
.getValue();
if (actionWithActiveStatus == null) {
return null;
}
final boolean isActionActive = target != null && SPUIDefinitions.ACTIVE.equals(activeValue);
final Button actionCancel = SPUIComponentProvider.getButton(
SPUIComponentIdProvider.ACTION_HISTORY_TABLE_CANCEL_ID, "", i18n.get("message.cancel.action"),
ValoTheme.BUTTON_TINY, true, FontAwesome.TIMES, SPUIButtonStyleSmallNoBorder.class);
actionCancel.setEnabled(isActionActive && !actionWithActiveStatus.isCancelingOrCanceled());
actionCancel.addClickListener(event -> confirmAndCancelAction(actionId));
final Button actionForce = SPUIComponentProvider.getButton(
SPUIComponentIdProvider.ACTION_HISTORY_TABLE_FORCE_ID, "", i18n.get("message.force.action"),
ValoTheme.BUTTON_TINY, true, FontAwesome.BOLT, SPUIButtonStyleSmallNoBorder.class);
actionForce.setEnabled(
isActionActive && !actionWithActiveStatus.isForce() && !actionWithActiveStatus.isCancelingOrCanceled());
actionForce.addClickListener(event -> confirmAndForceAction(actionId));
final Button actionForceQuit = SPUIComponentProvider.getButton(
SPUIComponentIdProvider.ACTION_HISTORY_TABLE_FORCE_QUIT_ID, "", i18n.get("message.forcequit.action"),
ValoTheme.BUTTON_TINY + " redicon", true, FontAwesome.TIMES, SPUIButtonStyleSmallNoBorder.class);
actionForceQuit.setEnabled(isActionActive && actionWithActiveStatus.isCancelingOrCanceled());
actionForceQuit.addClickListener(event -> confirmAndForceQuitAction(actionId));
actionBar.addComponents(actionCancel, actionForce, actionForceQuit);
return actionBar;
}
private Component getStatusColumn(final Object itemId) { private Component getStatusColumn(final Object itemId) {
final Action.Status status = (Action.Status) hierarchicalContainer.getItem(itemId) final Action.Status status = (Action.Status) hierarchicalContainer.getItem(itemId)
.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_STATUS_HIDDEN).getValue(); .getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_STATUS_HIDDEN).getValue();
@@ -449,9 +477,8 @@ public class ActionHistoryTable extends TreeTable implements Handler {
*/ */
childItem.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE_HIDDEN).setValue(""); childItem.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE_HIDDEN).setValue("");
childItem.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_DIST) childItem.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_DIST).setValue(
.setValue(action.getDistributionSet().getName() + ":" action.getDistributionSet().getName() + ":" + action.getDistributionSet().getVersion());
+ action.getDistributionSet().getVersion());
childItem.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_DATETIME) childItem.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_DATETIME)
.setValue(SPDateTimeUtil.getFormattedDate(actionStatus.getCreatedAt())); .setValue(SPDateTimeUtil.getFormattedDate(actionStatus.getCreatedAt()));
@@ -637,14 +664,15 @@ public class ActionHistoryTable extends TreeTable implements Handler {
private void setColumnExpantRatioOnTableMaximize() { private void setColumnExpantRatioOnTableMaximize() {
/* set messages column can expand the rest of the available space */ /* set messages column can expand the rest of the available space */
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE, 0.1f); setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE, 0.1F);
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID, 0.1f); setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID, 0.1F);
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_STATUS, 0.1f); setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_STATUS, 0.1F);
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_DIST, 0.2f); setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_DIST, 0.2F);
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_FORCED, 0.1f); setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_FORCED, 0.1F);
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_ROLLOUT_NAME, 0.1f); setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_ROLLOUT_NAME, 0.1F);
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_MSGS, 0.35f); setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_MSGS, 0.35F);
setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_DATETIME, 0.15f); setColumnExpandRatio(SPUIDefinitions.ACTION_HIS_TBL_DATETIME, 0.15F);
setColumnExpandRatio(SPUIDefinitions.ACTIONS_COLUMN, 0.2F);
} }
/** /**
@@ -706,46 +734,6 @@ public class ActionHistoryTable extends TreeTable implements Handler {
setColumnExpandRatioForMinimisedTable(); setColumnExpandRatioForMinimisedTable();
} }
@Override
public void handleAction(final com.vaadin.event.Action action, final Object sender, final Object target) {
/* Get the actionId details of the cancel item or row */
final Item item = hierarchicalContainer.getItem(target);
final Long actionId = (Long) item.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTION_ID_HIDDEN).getValue();
if (action.equals(actionCancel)) {
if (actionId != null) {
confirmAndCancelAction(actionId);
}
} else if (action.equals(actionForce)) {
confirmAndForceAction(actionId);
} else if (action.equals(actionForceQuit)) {
confirmAndForceQuitAction(actionId);
}
}
@Override
public com.vaadin.event.Action[] getActions(final Object target, final Object sender) {
final List<com.vaadin.event.Action> actions = Lists.newArrayList();
if (target != null) {
/* Check if the row or item belongs to active action */
final String activeValue = (String) hierarchicalContainer.getItem(target)
.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_ACTIVE_HIDDEN).getValue();
if (SPUIDefinitions.ACTIVE.equals(activeValue)) {
final Action actionWithActiveStatus = (Action) hierarchicalContainer.getItem(target)
.getItemProperty(SPUIDefinitions.ACTION_HIS_TBL_FORCED).getValue();
if (!actionWithActiveStatus.isForce()) {
actions.add(actionForce);
}
if (!actionWithActiveStatus.isCancelingOrCanceled()) {
actions.add(actionCancel);
} else {
actions.add(actionForceQuit);
}
}
}
return actions.toArray(new com.vaadin.event.Action[actions.size()]);
}
/** /**
* Show confirmation window and if ok then only, force the action. * Show confirmation window and if ok then only, force the action.
* *
@@ -756,21 +744,15 @@ public class ActionHistoryTable extends TreeTable implements Handler {
/* Display the confirmation */ /* Display the confirmation */
final ConfirmationDialog confirmDialog = new ConfirmationDialog(i18n.get("caption.force.action.confirmbox"), final ConfirmationDialog confirmDialog = new ConfirmationDialog(i18n.get("caption.force.action.confirmbox"),
i18n.get("message.force.action.confirm"), i18n.get(BUTTON_OK), i18n.get(BUTTON_CANCEL), ok -> { i18n.get("message.force.action.confirm"), i18n.get(BUTTON_OK), i18n.get(BUTTON_CANCEL), ok -> {
if (ok) { if (!ok) {
/* cancel the action */ return;
}
deploymentManagement.forceTargetAction(actionId); deploymentManagement.forceTargetAction(actionId);
/*
* Refresh the action history table to show latest
* change of the action cancellation and update the
* Target Details
*/
populateAndupdateTargetDetails(target); populateAndupdateTargetDetails(target);
notification.displaySuccess(i18n.get("message.force.action.success")); notification.displaySuccess(i18n.get("message.force.action.success"));
}
}); });
UI.getCurrent().addWindow(confirmDialog.getWindow()); UI.getCurrent().addWindow(confirmDialog.getWindow());
confirmDialog.getWindow().bringToFront(); confirmDialog.getWindow().bringToFront();
} }
@@ -778,22 +760,19 @@ public class ActionHistoryTable extends TreeTable implements Handler {
/* Display the confirmation */ /* Display the confirmation */
final ConfirmationDialog confirmDialog = new ConfirmationDialog(i18n.get("caption.forcequit.action.confirmbox"), final ConfirmationDialog confirmDialog = new ConfirmationDialog(i18n.get("caption.forcequit.action.confirmbox"),
i18n.get("message.forcequit.action.confirm"), i18n.get(BUTTON_OK), i18n.get(BUTTON_CANCEL), ok -> { i18n.get("message.forcequit.action.confirm"), i18n.get(BUTTON_OK), i18n.get(BUTTON_CANCEL), ok -> {
if (ok) { if (!ok) {
return;
}
final boolean cancelResult = forceQuitActiveAction(actionId); final boolean cancelResult = forceQuitActiveAction(actionId);
if (cancelResult) { if (cancelResult) {
/*
* Refresh the action history table to show latest
* change of the action cancellation and update the
* Target Details
*/
populateAndupdateTargetDetails(target); populateAndupdateTargetDetails(target);
notification.displaySuccess(i18n.get("message.forcequit.action.success")); notification.displaySuccess(i18n.get("message.forcequit.action.success"));
} else { } else {
notification.displayValidationError(i18n.get("message.forcequit.action.failed")); notification.displayValidationError(i18n.get("message.forcequit.action.failed"));
} }
}
}, FontAwesome.WARNING); }, FontAwesome.WARNING);
UI.getCurrent().addWindow(confirmDialog.getWindow()); UI.getCurrent().addWindow(confirmDialog.getWindow());
confirmDialog.getWindow().bringToFront(); confirmDialog.getWindow().bringToFront();
} }
@@ -804,22 +783,22 @@ public class ActionHistoryTable extends TreeTable implements Handler {
* as Id if the action needs to be cancelled. * as Id if the action needs to be cancelled.
*/ */
private void confirmAndCancelAction(final Long actionId) { private void confirmAndCancelAction(final Long actionId) {
if (actionId == null) {
return;
}
final ConfirmationDialog confirmDialog = new ConfirmationDialog(i18n.get("caption.cancel.action.confirmbox"), final ConfirmationDialog confirmDialog = new ConfirmationDialog(i18n.get("caption.cancel.action.confirmbox"),
i18n.get("message.cancel.action.confirm"), i18n.get(BUTTON_OK), i18n.get(BUTTON_CANCEL), ok -> { i18n.get("message.cancel.action.confirm"), i18n.get(BUTTON_OK), i18n.get(BUTTON_CANCEL), ok -> {
if (ok) { if (!ok) {
return;
}
final boolean cancelResult = cancelActiveAction(actionId); final boolean cancelResult = cancelActiveAction(actionId);
if (cancelResult) { if (cancelResult) {
/*
* Refresh the action history table to show latest
* change of the action cancellation and update the
* Target Details
*/
populateAndupdateTargetDetails(target); populateAndupdateTargetDetails(target);
notification.displaySuccess(i18n.get("message.cancel.action.success")); notification.displaySuccess(i18n.get("message.cancel.action.success"));
} else { } else {
notification.displayValidationError(i18n.get("message.cancel.action.failed")); notification.displayValidationError(i18n.get("message.cancel.action.failed"));
} }
}
}); });
UI.getCurrent().addWindow(confirmDialog.getWindow()); UI.getCurrent().addWindow(confirmDialog.getWindow());
confirmDialog.getWindow().bringToFront(); confirmDialog.getWindow().bringToFront();

View File

@@ -8,9 +8,7 @@
*/ */
package org.eclipse.hawkbit.ui.management.dstable; package org.eclipse.hawkbit.ui.management.dstable;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
@@ -26,6 +24,7 @@ import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.common.DistributionSetTypeBeanQuery; import org.eclipse.hawkbit.ui.common.DistributionSetTypeBeanQuery;
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIWindowDecorator;
import org.eclipse.hawkbit.ui.management.event.DistributionTableEvent; import org.eclipse.hawkbit.ui.management.event.DistributionTableEvent;
import org.eclipse.hawkbit.ui.management.event.DragEvent; import org.eclipse.hawkbit.ui.management.event.DragEvent;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
@@ -43,26 +42,18 @@ import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer;
import org.vaadin.addons.lazyquerycontainer.LazyQueryDefinition; import org.vaadin.addons.lazyquerycontainer.LazyQueryDefinition;
import org.vaadin.spring.events.EventBus; import org.vaadin.spring.events.EventBus;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.event.FieldEvents.TextChangeEvent;
import com.vaadin.event.FieldEvents.TextChangeListener;
import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope; import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.CheckBox; import com.vaadin.ui.CheckBox;
import com.vaadin.ui.ComboBox; import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomComponent; import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.FormLayout; import com.vaadin.ui.FormLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.TextArea; import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField; import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.themes.ValoTheme; import com.vaadin.ui.themes.ValoTheme;
/** /**
* * WindowContent for adding/editing a Distribution
*
*/ */
@SpringComponent @SpringComponent
@ViewScope @ViewScope
@@ -92,24 +83,12 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
private TextField distNameTextField; private TextField distNameTextField;
private TextField distVersionTextField; private TextField distVersionTextField;
private Label madatoryLabel;
private TextArea descTextArea; private TextArea descTextArea;
private CheckBox reqMigStepCheckbox; private CheckBox reqMigStepCheckbox;
private ComboBox distsetTypeNameComboBox; private ComboBox distsetTypeNameComboBox;
private boolean editDistribution = Boolean.FALSE; private boolean editDistribution = Boolean.FALSE;
private Long editDistId; private Long editDistId;
private CommonDialogWindow addDistributionWindow; private CommonDialogWindow window;
private String originalDistName;
private String originalDistVersion;
private String originalDistDescription;
private Boolean originalReqMigStep;
private String originalDistSetType;
private final List<Component> changedComponents = new ArrayList<>();
private ValueChangeListener reqMigStepCheckboxListerner;
private TextChangeListener descTextAreaListener;
private TextChangeListener distNameTextFieldListener;
private TextChangeListener distVersionTextFieldListener;
private ValueChangeListener distsetTypeNameComboBoxListener;
private FormLayout formLayout; private FormLayout formLayout;
@@ -123,16 +102,10 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
} }
private void buildLayout() { private void buildLayout() {
/*
* The main layout of the window contains mandatory info, textboxes
* (controller Id, name & description) and action buttons layout
*/
addStyleName("lay-color"); addStyleName("lay-color");
setSizeUndefined(); setSizeUndefined();
formLayout = new FormLayout(); formLayout = new FormLayout();
formLayout.addComponent(madatoryLabel);
formLayout.addComponent(distsetTypeNameComboBox); formLayout.addComponent(distsetTypeNameComboBox);
formLayout.addComponent(distNameTextField); formLayout.addComponent(distNameTextField);
formLayout.addComponent(distVersionTextField); formLayout.addComponent(distVersionTextField);
@@ -140,7 +113,6 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
formLayout.addComponent(reqMigStepCheckbox); formLayout.addComponent(reqMigStepCheckbox);
setCompositionRoot(formLayout); setCompositionRoot(formLayout);
distNameTextField.focus(); distNameTextField.focus();
} }
@@ -164,6 +136,7 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
distsetTypeNameComboBox.setImmediate(true); distsetTypeNameComboBox.setImmediate(true);
distsetTypeNameComboBox.setNullSelectionAllowed(false); distsetTypeNameComboBox.setNullSelectionAllowed(false);
distsetTypeNameComboBox.setId(SPUIComponentIdProvider.DIST_ADD_DISTSETTYPE); distsetTypeNameComboBox.setId(SPUIComponentIdProvider.DIST_ADD_DISTSETTYPE);
populateDistSetTypeNameCombo();
descTextArea = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "text-area-style", descTextArea = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "text-area-style",
ValoTheme.TEXTAREA_TINY, false, null, i18n.get("textfield.description"), ValoTheme.TEXTAREA_TINY, false, null, i18n.get("textfield.description"),
@@ -171,10 +144,6 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
descTextArea.setId(SPUIComponentIdProvider.DIST_ADD_DESC); descTextArea.setId(SPUIComponentIdProvider.DIST_ADD_DESC);
descTextArea.setNullRepresentation(""); descTextArea.setNullRepresentation("");
/* Label for mandatory symbol */
madatoryLabel = new Label(i18n.get("label.mandatory.field"));
madatoryLabel.setStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR + " " + ValoTheme.LABEL_SMALL);
reqMigStepCheckbox = SPUIComponentProvider.getCheckBox(i18n.get("checkbox.dist.required.migration.step"), reqMigStepCheckbox = SPUIComponentProvider.getCheckBox(i18n.get("checkbox.dist.required.migration.step"),
"dist-checkbox-style", null, false, ""); "dist-checkbox-style", null, false, "");
reqMigStepCheckbox.addStyleName(ValoTheme.CHECKBOX_SMALL); reqMigStepCheckbox.addStyleName(ValoTheme.CHECKBOX_SMALL);
@@ -200,27 +169,17 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
return disttypeContainer; return disttypeContainer;
} }
private void enableSaveButton() {
addDistributionWindow.setSaveButtonEnabled(true);
}
private DistributionSetType getDefaultDistributionSetType() { private DistributionSetType getDefaultDistributionSetType() {
final TenantMetaData tenantMetaData = systemManagement.getTenantMetadata(); final TenantMetaData tenantMetaData = systemManagement.getTenantMetadata();
return tenantMetaData.getDefaultDsType(); return tenantMetaData.getDefaultDsType();
} }
private void disableSaveButton() {
addDistributionWindow.setSaveButtonEnabled(false);
}
private void saveDistribution() { private void saveDistribution() {
/* add new or update target */
if (editDistribution) { if (editDistribution) {
updateDistribution(); updateDistribution();
} else { } else {
addNewDistribution(); addNewDistribution();
} }
} }
/** /**
@@ -232,7 +191,7 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
final String distSetTypeName = HawkbitCommonUtil final String distSetTypeName = HawkbitCommonUtil
.trimAndNullIfEmpty((String) distsetTypeNameComboBox.getValue()); .trimAndNullIfEmpty((String) distsetTypeNameComboBox.getValue());
if (mandatoryCheck(name, version, distSetTypeName) && duplicateCheck(name, version)) { if (duplicateCheck(name, version)) {
final DistributionSet currentDS = distributionSetManagement.findDistributionSetByIdWithDetails(editDistId); final DistributionSet currentDS = distributionSetManagement.findDistributionSetByIdWithDetails(editDistId);
final String desc = HawkbitCommonUtil.trimAndNullIfEmpty(descTextArea.getValue()); final String desc = HawkbitCommonUtil.trimAndNullIfEmpty(descTextArea.getValue());
final boolean isMigStepReq = reqMigStepCheckbox.getValue(); final boolean isMigStepReq = reqMigStepCheckbox.getValue();
@@ -250,23 +209,9 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
notificationMessage.displayValidationError( notificationMessage.displayValidationError(
i18n.get("message.distribution.no.update", currentDS.getName() + ":" + currentDS.getVersion())); i18n.get("message.distribution.no.update", currentDS.getName() + ":" + currentDS.getVersion()));
} }
closeThisWindow();
} }
} }
private void addListeners() {
reqMigStepCheckboxListerner = event -> checkValueChanged(originalReqMigStep, event);
descTextAreaListener = event -> checkValueChanged(originalDistDescription, event);
distNameTextFieldListener = event -> checkValueChanged(originalDistName, event);
distVersionTextFieldListener = event -> checkValueChanged(originalDistVersion, event);
distsetTypeNameComboBoxListener = event -> checkValueChanged(originalDistSetType, event);
reqMigStepCheckbox.addValueChangeListener(reqMigStepCheckboxListerner);
descTextArea.addTextChangeListener(descTextAreaListener);
distNameTextField.addTextChangeListener(distNameTextFieldListener);
distVersionTextField.addTextChangeListener(distVersionTextFieldListener);
distsetTypeNameComboBox.addValueChangeListener(distsetTypeNameComboBoxListener);
}
/** /**
* Add new Distribution set. * Add new Distribution set.
*/ */
@@ -277,7 +222,7 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
final String distSetTypeName = HawkbitCommonUtil final String distSetTypeName = HawkbitCommonUtil
.trimAndNullIfEmpty((String) distsetTypeNameComboBox.getValue()); .trimAndNullIfEmpty((String) distsetTypeNameComboBox.getValue());
if (mandatoryCheck(name, version, distSetTypeName) && duplicateCheck(name, version)) { if (duplicateCheck(name, version)) {
final String desc = HawkbitCommonUtil.trimAndNullIfEmpty(descTextArea.getValue()); final String desc = HawkbitCommonUtil.trimAndNullIfEmpty(descTextArea.getValue());
final boolean isMigStepReq = reqMigStepCheckbox.getValue(); final boolean isMigStepReq = reqMigStepCheckbox.getValue();
DistributionSet newDist = entityFactory.generateDistributionSet(); DistributionSet newDist = entityFactory.generateDistributionSet();
@@ -287,21 +232,11 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
notificationMessage.displaySuccess(i18n.get("message.new.dist.save.success", notificationMessage.displaySuccess(i18n.get("message.new.dist.save.success",
new Object[] { newDist.getName(), newDist.getVersion() })); new Object[] { newDist.getName(), newDist.getVersion() }));
/* close the window */
closeThisWindow();
eventBus.publish(this, new DistributionTableEvent(BaseEntityEventType.NEW_ENTITY, newDist)); eventBus.publish(this, new DistributionTableEvent(BaseEntityEventType.NEW_ENTITY, newDist));
} }
} }
/**
* Close window.
*/
private void closeThisWindow() {
addDistributionWindow.close();
UI.getCurrent().removeWindow(addDistributionWindow);
}
/** /**
* Set Values for Distribution set. * Set Values for Distribution set.
* *
@@ -345,47 +280,6 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
} }
} }
/**
* Mandatory Check.
*
* @param name
* as String
* @param version
* as String
* @param selectedJVM
* as String
* @param selectedAgentHub
* as String
* @param selectedOs
* as String
* @return boolean as flag
*/
private boolean mandatoryCheck(final String name, final String version, final String distSetTypeName) {
if (name == null || version == null || distSetTypeName == null) {
if (name == null) {
distNameTextField.addStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR);
}
if (version == null) {
distVersionTextField.addStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR);
}
if (distSetTypeName == null) {
distsetTypeNameComboBox.addStyleName(SPUIStyleDefinitions.SP_COMBOFIELD_ERROR);
}
notificationMessage.displayValidationError(i18n.get("message.mandatory.check"));
return false;
}
return true;
}
private void discardDistribution() {
/* Just close this window */
distsetTypeNameComboBox.removeValueChangeListener(distsetTypeNameComboBoxListener);
closeThisWindow();
}
/** /**
* clear all the fields. * clear all the fields.
*/ */
@@ -398,93 +292,22 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
distsetTypeNameComboBox.removeStyleName(SPUIStyleDefinitions.SP_COMBOFIELD_ERROR); distsetTypeNameComboBox.removeStyleName(SPUIStyleDefinitions.SP_COMBOFIELD_ERROR);
descTextArea.clear(); descTextArea.clear();
reqMigStepCheckbox.clear(); reqMigStepCheckbox.clear();
if (addDistributionWindow != null) {
addDistributionWindow.setSaveButtonEnabled(true);
}
removeListeners();
changedComponents.clear();
} }
private void populateRequiredComponents() { private void populateValuesOfDistribution(final Long editDistId) {
populateDistSetTypeNameCombo();
}
private void removeListeners() {
reqMigStepCheckbox.removeValueChangeListener(reqMigStepCheckboxListerner);
descTextArea.removeTextChangeListener(descTextAreaListener);
distNameTextField.removeTextChangeListener(distNameTextFieldListener);
distVersionTextField.removeTextChangeListener(distVersionTextFieldListener);
}
public void setOriginalDistName(final String originalDistName) {
this.originalDistName = originalDistName;
}
public void setOriginalDistVersion(final String originalDistVersion) {
this.originalDistVersion = originalDistVersion;
}
public void setOriginalDistDescription(final String originalDistDescription) {
this.originalDistDescription = originalDistDescription;
}
private void checkValueChanged(final String originalValue, final TextChangeEvent event) {
if (editDistribution) {
final String newValue = event.getText();
if (!originalValue.equalsIgnoreCase(newValue)) {
changedComponents.add(event.getComponent());
} else {
changedComponents.remove(event.getComponent());
}
enableDisableSaveButton();
}
}
private void checkValueChanged(final Boolean originalValue, final ValueChangeEvent event) {
if (editDistribution) {
if (!originalValue.equals(event.getProperty().getValue())) {
changedComponents.add(reqMigStepCheckbox);
} else {
changedComponents.remove(reqMigStepCheckbox);
}
enableDisableSaveButton();
}
}
private void checkValueChanged(final String originalValue, final ValueChangeEvent event) {
if (editDistribution) {
if (!originalValue.equals(event.getProperty().getValue())) {
changedComponents.add(distsetTypeNameComboBox);
} else {
changedComponents.remove(distsetTypeNameComboBox);
}
enableDisableSaveButton();
}
}
private void enableDisableSaveButton() {
if (changedComponents.isEmpty()) {
disableSaveButton();
} else {
enableSaveButton();
}
}
private void setOriginalReqMigStep(final Boolean originalReqMigStep) {
this.originalReqMigStep = originalReqMigStep;
}
/**
* populate data.
*
* @param editDistId
*/
public void populateValuesOfDistribution(final Long editDistId) {
this.editDistId = editDistId; this.editDistId = editDistId;
editDistribution = Boolean.TRUE;
addDistributionWindow.setSaveButtonEnabled(false); if (editDistId == null) {
return;
}
final DistributionSet distSet = distributionSetManagement.findDistributionSetByIdWithDetails(editDistId); final DistributionSet distSet = distributionSetManagement.findDistributionSetByIdWithDetails(editDistId);
if (distSet != null) { if (distSet == null) {
return;
}
editDistribution = Boolean.TRUE;
distNameTextField.setValue(distSet.getName()); distNameTextField.setValue(distSet.getName());
distVersionTextField.setValue(distSet.getVersion()); distVersionTextField.setValue(distSet.getVersion());
if (distSet.getType().isDeleted()) { if (distSet.getType().isDeleted()) {
@@ -495,42 +318,26 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
if (distSet.getDescription() != null) { if (distSet.getDescription() != null) {
descTextArea.setValue(distSet.getDescription()); descTextArea.setValue(distSet.getDescription());
} }
setOriginalDistName(distSet.getName());
setOriginalDistVersion(distSet.getVersion());
setOriginalDistDescription(distSet.getDescription());
setOriginalReqMigStep(distSet.isRequiredMigrationStep());
setOriginalDistSetTYpe(distSet.getType().getName());
addListeners();
}
} }
public CommonDialogWindow getWindow() { public CommonDialogWindow getWindow(final Long editDistId) {
eventBus.publish(this, DragEvent.HIDE_DROP_HINT); eventBus.publish(this, DragEvent.HIDE_DROP_HINT);
populateRequiredComponents();
resetComponents(); resetComponents();
addDistributionWindow = SPUIComponentProvider.getWindow(i18n.get("caption.add.new.dist"), null, populateDistSetTypeNameCombo();
SPUIDefinitions.CREATE_UPDATE_WINDOW, this, event -> saveDistribution(), event -> discardDistribution(), populateValuesOfDistribution(editDistId);
null); window = SPUIWindowDecorator.getWindow(i18n.get("caption.add.new.dist"), null,
addDistributionWindow.getButtonsLayout().removeStyleName("actionButtonsMargin"); SPUIDefinitions.CREATE_UPDATE_WINDOW, this, event -> saveDistribution(), null, null, formLayout, i18n);
window.getButtonsLayout().removeStyleName("actionButtonsMargin");
return addDistributionWindow; return window;
} }
/** /**
* Populate DistributionSet Type name combo. * Populate DistributionSet Type name combo.
*/ */
public void populateDistSetTypeNameCombo() { private void populateDistSetTypeNameCombo() {
distsetTypeNameComboBox.setContainerDataSource(getDistSetTypeLazyQueryContainer()); distsetTypeNameComboBox.setContainerDataSource(getDistSetTypeLazyQueryContainer());
distsetTypeNameComboBox.setItemCaptionPropertyId(SPUILabelDefinitions.VAR_NAME); distsetTypeNameComboBox.setItemCaptionPropertyId(SPUILabelDefinitions.VAR_NAME);
distsetTypeNameComboBox.setValue(getDefaultDistributionSetType().getName()); distsetTypeNameComboBox.setValue(getDefaultDistributionSetType().getName());
} }
/**
* @param originalDistSetTYpe
* the originalDistSetTYpe to set
*/
public void setOriginalDistSetTYpe(final String originalDistSetType) {
this.originalDistSetType = originalDistSetType;
}
} }

View File

@@ -8,11 +8,18 @@
*/ */
package org.eclipse.hawkbit.ui.management.dstable; package org.eclipse.hawkbit.ui.management.dstable;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
import org.eclipse.hawkbit.ui.common.DistributionSetIdName;
import org.eclipse.hawkbit.ui.common.detailslayout.AbstractNamedVersionedEntityTableDetailsLayout; import org.eclipse.hawkbit.ui.common.detailslayout.AbstractNamedVersionedEntityTableDetailsLayout;
import org.eclipse.hawkbit.ui.common.detailslayout.DistributionSetMetadatadetailslayout;
import org.eclipse.hawkbit.ui.common.detailslayout.SoftwareModuleDetailsTable; import org.eclipse.hawkbit.ui.common.detailslayout.SoftwareModuleDetailsTable;
import org.eclipse.hawkbit.ui.common.tagdetails.DistributionTagToken; import org.eclipse.hawkbit.ui.common.tagdetails.DistributionTagToken;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.distributions.dstable.DsMetadataPopupLayout;
import org.eclipse.hawkbit.ui.distributions.event.MetadataEvent;
import org.eclipse.hawkbit.ui.management.event.DistributionTableEvent; import org.eclipse.hawkbit.ui.management.event.DistributionTableEvent;
import org.eclipse.hawkbit.ui.management.state.ManagementUIState; import org.eclipse.hawkbit.ui.management.state.ManagementUIState;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider; import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
@@ -47,15 +54,47 @@ public class DistributionDetails extends AbstractNamedVersionedEntityTableDetail
@Autowired @Autowired
private DistributionTagToken distributionTagToken; private DistributionTagToken distributionTagToken;
@Autowired
private transient DistributionSetManagement distributionSetManagement;
@Autowired
private DsMetadataPopupLayout dsMetadataPopupLayout;
@Autowired
private EntityFactory entityFactory;
private SoftwareModuleDetailsTable softwareModuleTable; private SoftwareModuleDetailsTable softwareModuleTable;
private DistributionSetMetadatadetailslayout dsMetadataTable;
@Override @Override
protected void init() { protected void init() {
softwareModuleTable = new SoftwareModuleDetailsTable(); softwareModuleTable = new SoftwareModuleDetailsTable();
softwareModuleTable.init(getI18n(), false, getPermissionChecker(), null, null, null); softwareModuleTable.init(getI18n(), false, getPermissionChecker(), null, null, null);
dsMetadataTable = new DistributionSetMetadatadetailslayout();
dsMetadataTable.init(getI18n(), getPermissionChecker(),distributionSetManagement,
dsMetadataPopupLayout,entityFactory);
super.init(); super.init();
} }
@EventBusListenerMethod(scope = EventScope.SESSION)
void onEvent(final MetadataEvent event) {
UI.getCurrent()
.access(() -> {
DistributionSetMetadata dsMetadata = event.getDistributionSetMetadata();
if (dsMetadata != null && isDistributionSetSelected(dsMetadata.getDistributionSet())) {
if (event.getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.CREATE_DISTRIBUTION_SET_METADATA) {
dsMetadataTable.createMetadata(event.getDistributionSetMetadata().getKey());
} else if (event.getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.DELETE_DISTRIBUTION_SET_METADATA) {
dsMetadataTable.deleteMetadata(event.getDistributionSetMetadata().getKey());
}
}
});
}
@EventBusListenerMethod(scope = EventScope.SESSION) @EventBusListenerMethod(scope = EventScope.SESSION)
void onEvent(final DistributionTableEvent distributionTableEvent) { void onEvent(final DistributionTableEvent distributionTableEvent) {
onBaseEntityEvent(distributionTableEvent); onBaseEntityEvent(distributionTableEvent);
@@ -73,12 +112,12 @@ public class DistributionDetails extends AbstractNamedVersionedEntityTableDetail
detailsTab.addTab(createSoftwareModuleTab(), getI18n().get("caption.softwares.distdetail.tab"), null); detailsTab.addTab(createSoftwareModuleTab(), getI18n().get("caption.softwares.distdetail.tab"), null);
detailsTab.addTab(createTagsLayout(), getI18n().get("caption.tags.tab"), null); detailsTab.addTab(createTagsLayout(), getI18n().get("caption.tags.tab"), null);
detailsTab.addTab(createLogLayout(), getI18n().get("caption.logs.tab"), null); detailsTab.addTab(createLogLayout(), getI18n().get("caption.logs.tab"), null);
detailsTab.addTab(dsMetadataTable, getI18n().get("caption.metadata"), null);
} }
@Override @Override
protected void onEdit(final ClickEvent event) { protected void onEdit(final ClickEvent event) {
final Window newDistWindow = distributionAddUpdateWindowLayout.getWindow(); final Window newDistWindow = distributionAddUpdateWindowLayout.getWindow(getSelectedBaseEntityId());
distributionAddUpdateWindowLayout.populateValuesOfDistribution(getSelectedBaseEntityId());
newDistWindow.setCaption(getI18n().get("caption.update.dist")); newDistWindow.setCaption(getI18n().get("caption.update.dist"));
UI.getCurrent().addWindow(newDistWindow); UI.getCurrent().addWindow(newDistWindow);
newDistWindow.setVisible(Boolean.TRUE); newDistWindow.setVisible(Boolean.TRUE);
@@ -114,9 +153,16 @@ public class DistributionDetails extends AbstractNamedVersionedEntityTableDetail
protected void populateDetailsWidget() { protected void populateDetailsWidget() {
softwareModuleTable.populateModule(getSelectedBaseEntity()); softwareModuleTable.populateModule(getSelectedBaseEntity());
populateDetails(getSelectedBaseEntity()); populateDetails(getSelectedBaseEntity());
populateMetadataDetails();
} }
@Override
protected void populateMetadataDetails(){
dsMetadataTable.populateDSMetadata(getSelectedBaseEntity());
}
private void populateDetails(final DistributionSet ds) { private void populateDetails(final DistributionSet ds) {
if (ds != null) { if (ds != null) {
updateDistributionDetailsLayout(ds.getType().getName(), ds.isRequiredMigrationStep()); updateDistributionDetailsLayout(ds.getType().getName(), ds.isRequiredMigrationStep());
@@ -161,4 +207,29 @@ public class DistributionDetails extends AbstractNamedVersionedEntityTableDetail
return SPUIComponentIdProvider.DISTRIBUTION_DETAILS_HEADER_LABEL_ID; return SPUIComponentIdProvider.DISTRIBUTION_DETAILS_HEADER_LABEL_ID;
} }
@Override
protected Boolean isMetadataIconToBeDisplayed() {
return true;
}
@Override
protected String getShowMetadataButtonId() {
DistributionSetIdName lastselectedDistDS = managementUIState.getLastSelectedDistribution().isPresent() ? managementUIState
.getLastSelectedDistribution().get() : null;
return SPUIComponentIdProvider.DS_TABLE_MANAGE_METADATA_ID + "." + lastselectedDistDS.getName() + "."
+ lastselectedDistDS.getVersion();
}
private boolean isDistributionSetSelected(DistributionSet ds) {
DistributionSetIdName lastselectedManageDS = managementUIState.getLastSelectedDistribution().isPresent() ? managementUIState
.getLastSelectedDistribution().get() : null;
return ds!=null && lastselectedManageDS != null && lastselectedManageDS.getName().equals(ds.getName())
&& lastselectedManageDS.getVersion().endsWith(ds.getVersion());
}
@Override
protected void showMetadata(ClickEvent event) {
DistributionSet ds = distributionSetManagement.findDistributionSetByIdWithDetails(getSelectedBaseEntityId());
UI.getCurrent().addWindow(dsMetadataPopupLayout.getWindow(ds,null));
}
} }

View File

@@ -18,6 +18,7 @@ import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SpPermissionChecker; import org.eclipse.hawkbit.repository.SpPermissionChecker;
import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
@@ -29,6 +30,8 @@ import org.eclipse.hawkbit.ui.common.table.AbstractNamedVersionTable;
import org.eclipse.hawkbit.ui.common.table.AbstractTable; import org.eclipse.hawkbit.ui.common.table.AbstractTable;
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.distributions.dstable.DsMetadataPopupLayout;
import org.eclipse.hawkbit.ui.management.event.DistributionTableEvent; import org.eclipse.hawkbit.ui.management.event.DistributionTableEvent;
import org.eclipse.hawkbit.ui.management.event.DistributionTableFilterEvent; import org.eclipse.hawkbit.ui.management.event.DistributionTableFilterEvent;
import org.eclipse.hawkbit.ui.management.event.DragEvent; import org.eclipse.hawkbit.ui.management.event.DragEvent;
@@ -63,6 +66,7 @@ import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Component; import com.vaadin.ui.Component;
import com.vaadin.ui.DragAndDropWrapper; import com.vaadin.ui.DragAndDropWrapper;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Table; import com.vaadin.ui.Table;
import com.vaadin.ui.UI; import com.vaadin.ui.UI;
@@ -90,9 +94,15 @@ public class DistributionTable extends AbstractNamedVersionTable<DistributionSet
@Autowired @Autowired
private transient TargetManagement targetService; private transient TargetManagement targetService;
@Autowired
private DsMetadataPopupLayout dsMetadataPopupLayout;
@Autowired @Autowired
private transient DistributionSetManagement distributionSetManagement; private transient DistributionSetManagement distributionSetManagement;
@Autowired
private EntityFactory entityFactory;
private String notAllowedMsg; private String notAllowedMsg;
private Boolean isDistPinned = false; private Boolean isDistPinned = false;
@@ -219,11 +229,36 @@ public class DistributionTable extends AbstractNamedVersionTable<DistributionSet
@Override @Override
public Object generateCell(final Table source, final Object itemId, final Object columnId) { public Object generateCell(final Table source, final Object itemId, final Object columnId) {
return getPinButton(itemId); HorizontalLayout iconLayout = new HorizontalLayout();
final String nameVersionStr = getNameAndVerion(itemId);
final Button manageMetaDataBtn = createManageMetadataButton(nameVersionStr);
manageMetaDataBtn.addClickListener(event -> showMetadataDetails(itemId));
iconLayout.addComponent((Button)getPinButton(itemId));
iconLayout.addComponent(manageMetaDataBtn);
return iconLayout;
} }
}); });
} }
private String getNameAndVerion(final Object itemId) {
final Item item = getItem(itemId);
final String name = (String) item.getItemProperty(SPUILabelDefinitions.VAR_NAME).getValue();
final String version = (String) item.getItemProperty(SPUILabelDefinitions.VAR_VERSION).getValue();
return name + "." + version;
}
private Button createManageMetadataButton(String nameVersionStr) {
final Button manageMetadataBtn = SPUIComponentProvider.getButton(
SPUIComponentIdProvider.DS_TABLE_MANAGE_METADATA_ID + "." + nameVersionStr, "", "", null, false,
FontAwesome.LIST_ALT, SPUIButtonStyleSmallNoBorder.class);
manageMetadataBtn.addStyleName(SPUIStyleDefinitions.ARTIFACT_DTLS_ICON);
manageMetadataBtn.addStyleName(SPUIStyleDefinitions.DS_METADATA_ICON);
manageMetadataBtn.setDescription(i18n.get("tooltip.metadata.icon"));
return manageMetadataBtn;
}
@Override @Override
protected boolean isFirstRowSelectedOnLoad() { protected boolean isFirstRowSelectedOnLoad() {
return !managementUIState.getSelectedDsIdName().isPresent() return !managementUIState.getSelectedDsIdName().isPresent()
@@ -246,6 +281,10 @@ public class DistributionTable extends AbstractNamedVersionTable<DistributionSet
@Override @Override
protected void publishEntityAfterValueChange(final DistributionSet selectedLastEntity) { protected void publishEntityAfterValueChange(final DistributionSet selectedLastEntity) {
eventBus.publish(this, new DistributionTableEvent(BaseEntityEventType.SELECTED_ENTITY, selectedLastEntity)); eventBus.publish(this, new DistributionTableEvent(BaseEntityEventType.SELECTED_ENTITY, selectedLastEntity));
if(selectedLastEntity!=null){
managementUIState.setLastSelectedDistribution(new DistributionSetIdName(selectedLastEntity.getId(),
selectedLastEntity.getName(),selectedLastEntity.getVersion()));
}
} }
@Override @Override
@@ -264,7 +303,7 @@ public class DistributionTable extends AbstractNamedVersionTable<DistributionSet
if (isMaximized()) { if (isMaximized()) {
return columnList; return columnList;
} }
columnList.add(new TableColumn(SPUILabelDefinitions.PIN_COLUMN, StringUtils.EMPTY, 0.1F)); columnList.add(new TableColumn(SPUILabelDefinitions.PIN_COLUMN, StringUtils.EMPTY, 0.2F));
return columnList; return columnList;
} }
@@ -658,4 +697,11 @@ public class DistributionTable extends AbstractNamedVersionTable<DistributionSet
} }
private void showMetadataDetails(Object itemId) {
final DistributionSetIdName distIdName = (DistributionSetIdName) getContainerDataSource().getItem(itemId)
.getItemProperty(SPUILabelDefinitions.VAR_DIST_ID_NAME).getValue();
DistributionSet ds = distributionSetManagement.findDistributionSetByIdWithDetails(distIdName.getId());
UI.getCurrent().addWindow(dsMetadataPopupLayout.getWindow(ds, null));
}
} }

View File

@@ -154,7 +154,7 @@ public class DistributionTableHeader extends AbstractTableHeader {
@Override @Override
protected void addNewItem(final ClickEvent event) { protected void addNewItem(final ClickEvent event) {
final Window newDistWindow = distributionAddUpdateWindowLayout.getWindow(); final Window newDistWindow = distributionAddUpdateWindowLayout.getWindow(null);
newDistWindow.setCaption(i18n.get("caption.add.new.dist")); newDistWindow.setCaption(i18n.get("caption.add.new.dist"));
UI.getCurrent().addWindow(newDistWindow); UI.getCurrent().addWindow(newDistWindow);
newDistWindow.setVisible(Boolean.TRUE); newDistWindow.setVisible(Boolean.TRUE);

View File

@@ -32,9 +32,7 @@ import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.UI; import com.vaadin.ui.UI;
/** /**
*
* Class for Create/Update Tag Layout of distribution set * Class for Create/Update Tag Layout of distribution set
*
*/ */
@SpringComponent @SpringComponent
@ViewScope @ViewScope
@@ -87,18 +85,15 @@ public class CreateUpdateDistributionTagLayoutWindow extends AbstractCreateUpdat
*/ */
@Override @Override
public void save(final ClickEvent event) { public void save(final ClickEvent event) {
if (mandatoryValuesPresent()) {
final DistributionSetTag existingDistTag = tagManagement.findDistributionSetTag(tagName.getValue()); final DistributionSetTag existingDistTag = tagManagement.findDistributionSetTag(tagName.getValue());
if (optiongroup.getValue().equals(createTagStr)) { if (optiongroup.getValue().equals(createTagStr)) {
if (!checkIsDuplicate(existingDistTag)) { if (!checkIsDuplicate(existingDistTag)) {
createNewTag(); createNewTag();
} }
} else { } else {
updateExistingTag(existingDistTag); updateExistingTag(existingDistTag);
} }
} }
}
/** /**
* Create new tag. * Create new tag.
@@ -181,4 +176,9 @@ public class CreateUpdateDistributionTagLayoutWindow extends AbstractCreateUpdat
setOptionGroupDefaultValue(permChecker.hasCreateDistributionPermission(), setOptionGroupDefaultValue(permChecker.hasCreateDistributionPermission(),
permChecker.hasUpdateDistributionPermission()); permChecker.hasUpdateDistributionPermission());
} }
@Override
protected String getWindowCaption() {
return i18n.get("caption.add.tag");
}
} }

View File

@@ -17,6 +17,7 @@ import javax.annotation.PostConstruct;
import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.ui.utils.I18N; import org.eclipse.hawkbit.ui.utils.I18N;
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil; import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.hene.flexibleoptiongroup.FlexibleOptionGroup; import org.vaadin.hene.flexibleoptiongroup.FlexibleOptionGroup;
import org.vaadin.hene.flexibleoptiongroup.FlexibleOptionGroupItemComponent; import org.vaadin.hene.flexibleoptiongroup.FlexibleOptionGroupItemComponent;
@@ -98,6 +99,7 @@ public class ActionTypeOptionGroupLayout extends HorizontalLayout {
addComponent(forceLabel); addComponent(forceLabel);
final FlexibleOptionGroupItemComponent softItem = actionTypeOptionGroup.getItemComponent(ActionTypeOption.SOFT); final FlexibleOptionGroupItemComponent softItem = actionTypeOptionGroup.getItemComponent(ActionTypeOption.SOFT);
softItem.setId(SPUIComponentIdProvider.ACTION_DETAILS_SOFT_ID);
softItem.setStyleName(STYLE_DIST_WINDOW_ACTIONTYPE); softItem.setStyleName(STYLE_DIST_WINDOW_ACTIONTYPE);
addComponent(softItem); addComponent(softItem);
final Label softLabel = new Label(); final Label softLabel = new Label();

View File

@@ -88,6 +88,22 @@ public class ManagementUIState implements ManagmentEntityState<DistributionSetId
private boolean bulkUploadWindowMinimised; private boolean bulkUploadWindowMinimised;
private DistributionSetIdName lastSelectedDistribution;
/**
* @return the lastSelectedDistribution
*/
public Optional<DistributionSetIdName> getLastSelectedDistribution() {
return Optional.ofNullable(lastSelectedDistribution);
}
public void setLastSelectedDistribution(final DistributionSetIdName value) {
this.lastSelectedDistribution = value;
}
/** /**
* @return the bulkUploadWindowMinimised * @return the bulkUploadWindowMinimised
*/ */

View File

@@ -10,6 +10,8 @@ package org.eclipse.hawkbit.ui.management.tag;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.vaadin.data.Property; import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent; import com.vaadin.data.Property.ValueChangeEvent;
@@ -44,7 +46,7 @@ public final class SpColorPickerPreview extends ColorPickerPreview implements Te
try { try {
final Field textField = ColorPickerPreview.class.getDeclaredField("field"); final Field textField = ColorPickerPreview.class.getDeclaredField("field");
textField.setAccessible(true); textField.setAccessible(true);
((TextField) textField.get(this)).setId("color-preview-field"); ((TextField) textField.get(this)).setId(SPUIComponentIdProvider.COLOR_PREVIEW_FIELD);
((TextField) textField.get(this)).addTextChangeListener(this); ((TextField) textField.get(this)).addTextChangeListener(this);
} catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) { } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
Throwables.propagate(e); Throwables.propagate(e);

View File

@@ -18,6 +18,7 @@ import org.eclipse.hawkbit.repository.model.TargetIdName;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow; import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIWindowDecorator;
import org.eclipse.hawkbit.ui.management.event.DragEvent; import org.eclipse.hawkbit.ui.management.event.DragEvent;
import org.eclipse.hawkbit.ui.management.event.TargetTableEvent; import org.eclipse.hawkbit.ui.management.event.TargetTableEvent;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
@@ -31,24 +32,17 @@ import org.eclipse.hawkbit.ui.utils.UINotification;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.spring.events.EventBus; import org.vaadin.spring.events.EventBus;
import com.vaadin.event.FieldEvents.TextChangeEvent;
import com.vaadin.event.FieldEvents.TextChangeListener;
import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.VaadinSessionScope; import com.vaadin.spring.annotation.VaadinSessionScope;
import com.vaadin.ui.CustomComponent; import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.FormLayout; import com.vaadin.ui.FormLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.TextArea; import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField; import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.Window; import com.vaadin.ui.Window;
import com.vaadin.ui.themes.ValoTheme; import com.vaadin.ui.themes.ValoTheme;
/** /**
* Add and Update Target. * Add and Update Target.
*
*
*
*/ */
@SpringComponent @SpringComponent
@VaadinSessionScope @VaadinSessionScope
@@ -73,48 +67,37 @@ public class TargetAddUpdateWindowLayout extends CustomComponent {
private TextField controllerIDTextField; private TextField controllerIDTextField;
private TextField nameTextField; private TextField nameTextField;
private TextArea descTextArea; private TextArea descTextArea;
private Label madatoryLabel;
private boolean editTarget = Boolean.FALSE; private boolean editTarget = Boolean.FALSE;
private String controllerId; private String controllerId;
private FormLayout formLayout; private FormLayout formLayout;
private CommonDialogWindow window; private CommonDialogWindow window;
private String oldTargetName;
private String oldTargetDesc;
/** /**
* Initialize the Add Update Window Component for Target. * Initialize the Add Update Window Component for Target.
*/ */
public void init() { public void init() {
/* create components */
createRequiredComponents(); createRequiredComponents();
/* display components in layout */
buildLayout(); buildLayout();
/* register all listeners related to the Window */
addListeners();
setCompositionRoot(formLayout); setCompositionRoot(formLayout);
} }
private void createRequiredComponents() { private void createRequiredComponents() {
/* Textfield for controller Id */ /* Textfield for controller Id */
controllerIDTextField = SPUIComponentProvider.getTextField( i18n.get("prompt.target.id"), "", ValoTheme.TEXTFIELD_TINY, true, null, controllerIDTextField = SPUIComponentProvider.getTextField(i18n.get("prompt.target.id"), "",
i18n.get("prompt.target.id"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH); ValoTheme.TEXTFIELD_TINY, true, null, i18n.get("prompt.target.id"), true,
SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
controllerIDTextField.setId(SPUIComponentIdProvider.TARGET_ADD_CONTROLLER_ID); controllerIDTextField.setId(SPUIComponentIdProvider.TARGET_ADD_CONTROLLER_ID);
/* Textfield for target name */ /* Textfield for target name */
nameTextField = SPUIComponentProvider.getTextField( i18n.get("textfield.name"), "", ValoTheme.TEXTFIELD_TINY, false, null, nameTextField = SPUIComponentProvider.getTextField(i18n.get("textfield.name"), "", ValoTheme.TEXTFIELD_TINY,
i18n.get("textfield.name"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH); false, null, i18n.get("textfield.name"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
nameTextField.setId(SPUIComponentIdProvider.TARGET_ADD_NAME); nameTextField.setId(SPUIComponentIdProvider.TARGET_ADD_NAME);
/* Textarea for target description */ /* Textarea for target description */
descTextArea = SPUIComponentProvider.getTextArea( i18n.get("textfield.description"), "text-area-style", ValoTheme.TEXTFIELD_TINY, false, null, descTextArea = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "text-area-style",
i18n.get("textfield.description"), SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH); ValoTheme.TEXTFIELD_TINY, false, null, i18n.get("textfield.description"),
SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
descTextArea.setId(SPUIComponentIdProvider.TARGET_ADD_DESC); descTextArea.setId(SPUIComponentIdProvider.TARGET_ADD_DESC);
descTextArea.setNullRepresentation(HawkbitCommonUtil.SP_STRING_EMPTY); descTextArea.setNullRepresentation(HawkbitCommonUtil.SP_STRING_EMPTY);
/* Label for mandatory symbol */
madatoryLabel = new Label(i18n.get("label.mandatory.field"));
madatoryLabel.setStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR + " " + ValoTheme.LABEL_SMALL);
} }
private void buildLayout() { private void buildLayout() {
@@ -125,63 +108,13 @@ public class TargetAddUpdateWindowLayout extends CustomComponent {
*/ */
setSizeUndefined(); setSizeUndefined();
formLayout = new FormLayout(); formLayout = new FormLayout();
formLayout.addComponent(madatoryLabel);
formLayout.addComponent(controllerIDTextField); formLayout.addComponent(controllerIDTextField);
formLayout.addComponent(nameTextField); formLayout.addComponent(nameTextField);
formLayout.addComponent(descTextArea); formLayout.addComponent(descTextArea);
if (Boolean.TRUE.equals(editTarget)) {
madatoryLabel.setVisible(Boolean.FALSE);
}
controllerIDTextField.focus(); controllerIDTextField.focus();
} }
private void addListeners() {
addTargetNameChangeListner();
addTargetDescChangeListner();
}
private void addTargetNameChangeListner() {
nameTextField.addTextChangeListener(new TextChangeListener() {
/**
*
*/
private static final long serialVersionUID = 1761855781481115921L;
@Override
public void textChange(final TextChangeEvent event) {
if (event.getText().equals(oldTargetName) && descTextArea.getValue().equals(oldTargetDesc)) {
window.setSaveButtonEnabled(false);
} else {
window.setSaveButtonEnabled(true);
}
}
});
}
private void addTargetDescChangeListner() {
descTextArea.addTextChangeListener(new TextChangeListener() {
/**
*
*/
private static final long serialVersionUID = 5770734934988115068L;
@Override
public void textChange(final TextChangeEvent event) {
if (event.getText().equals(oldTargetDesc) && nameTextField.getValue().equals(oldTargetName)) {
window.setSaveButtonEnabled(false);
} else {
window.setSaveButtonEnabled(true);
}
}
});
}
/** /**
* Update the Target if modified. * Update the Target if modified.
*/ */
@@ -199,10 +132,6 @@ public class TargetAddUpdateWindowLayout extends CustomComponent {
uINotification.displaySuccess(i18n.get("message.update.success", new Object[] { latestTarget.getName() })); uINotification.displaySuccess(i18n.get("message.update.success", new Object[] { latestTarget.getName() }));
// publishing through event bus // publishing through event bus
eventBus.publish(this, new TargetTableEvent(BaseEntityEventType.UPDATED_ENTITY, latestTarget)); eventBus.publish(this, new TargetTableEvent(BaseEntityEventType.UPDATED_ENTITY, latestTarget));
/* close the window */
closeThisWindow();
/* update details in table */
} }
private void saveTargetListner() { private void saveTargetListner() {
@@ -213,13 +142,9 @@ public class TargetAddUpdateWindowLayout extends CustomComponent {
} }
} }
private void discardTargetListner() {
closeThisWindow();
}
private void addNewTarget() { private void addNewTarget() {
final String newControlllerId = HawkbitCommonUtil.trimAndNullIfEmpty(controllerIDTextField.getValue()); final String newControlllerId = HawkbitCommonUtil.trimAndNullIfEmpty(controllerIDTextField.getValue());
if (mandatoryCheck(newControlllerId) && duplicateCheck(newControlllerId)) { if (duplicateCheck(newControlllerId)) {
final String newName = HawkbitCommonUtil.trimAndNullIfEmpty(nameTextField.getValue()); final String newName = HawkbitCommonUtil.trimAndNullIfEmpty(nameTextField.getValue());
final String newDesc = HawkbitCommonUtil.trimAndNullIfEmpty(descTextArea.getValue()); final String newDesc = HawkbitCommonUtil.trimAndNullIfEmpty(descTextArea.getValue());
@@ -236,15 +161,20 @@ public class TargetAddUpdateWindowLayout extends CustomComponent {
/* display success msg */ /* display success msg */
uINotification.displaySuccess(i18n.get("message.save.success", new Object[] { newTarget.getName() })); uINotification.displaySuccess(i18n.get("message.save.success", new Object[] { newTarget.getName() }));
/* close the window */
closeThisWindow();
} }
} }
public Window getWindow() { public Window getWindow() {
eventBus.publish(this, DragEvent.HIDE_DROP_HINT); eventBus.publish(this, DragEvent.HIDE_DROP_HINT);
window = SPUIComponentProvider.getWindow(i18n.get("caption.add.new.target"), null, window = SPUIWindowDecorator.getWindow(i18n.get("caption.add.new.target"), null,
SPUIDefinitions.CREATE_UPDATE_WINDOW, this, event -> saveTargetListner(), event -> discardTargetListner(), null); SPUIDefinitions.CREATE_UPDATE_WINDOW, this, event -> saveTargetListner(), null, null, formLayout, i18n);
return window;
}
public Window getWindow(final String entityId) {
populateValuesOfTarget(entityId);
getWindow();
window.addStyleName("target-update-window");
return window; return window;
} }
@@ -254,39 +184,23 @@ public class TargetAddUpdateWindowLayout extends CustomComponent {
public void resetComponents() { public void resetComponents() {
nameTextField.clear(); nameTextField.clear();
nameTextField.removeStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR); nameTextField.removeStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR);
controllerIDTextField.setEnabled(true); controllerIDTextField.setEnabled(Boolean.TRUE);
controllerIDTextField.setReadOnly(false);
controllerIDTextField.removeStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR); controllerIDTextField.removeStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR);
controllerIDTextField.clear(); controllerIDTextField.clear();
descTextArea.clear(); descTextArea.clear();
editTarget = Boolean.FALSE; editTarget = Boolean.FALSE;
} }
private void closeThisWindow() {
editTarget = Boolean.FALSE;
window.close();
UI.getCurrent().removeWindow(window);
}
private void setTargetValues(final Target target, final String name, final String description) { private void setTargetValues(final Target target, final String name, final String description) {
target.setName(name == null ? target.getControllerId() : name); target.setName(name == null ? target.getControllerId() : name);
target.setDescription(description); target.setDescription(description);
} }
private boolean mandatoryCheck(final String newControlllerId) {
if (newControlllerId == null) {
controllerIDTextField.addStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR);
uINotification.displayValidationError("Mandatory details are missing");
return false;
} else {
return true;
}
}
private boolean duplicateCheck(final String newControlllerId) { private boolean duplicateCheck(final String newControlllerId) {
final Target existingTarget = targetManagement.findTargetByControllerID(newControlllerId.trim()); final Target existingTarget = targetManagement.findTargetByControllerID(newControlllerId.trim());
if (existingTarget != null) { if (existingTarget != null) {
uINotification.displayValidationError(i18n.get("message.target.duplicate.check")); uINotification.displayValidationError(
i18n.get("message.target.duplicate.check", new Object[] { newControlllerId }));
return false; return false;
} else { } else {
return true; return true;
@@ -296,22 +210,21 @@ public class TargetAddUpdateWindowLayout extends CustomComponent {
/** /**
* @param controllerId * @param controllerId
*/ */
public void populateValuesOfTarget(final String controllerId) { private void populateValuesOfTarget(final String controllerId) {
resetComponents(); resetComponents();
this.controllerId = controllerId; this.controllerId = controllerId;
editTarget = Boolean.TRUE; editTarget = Boolean.TRUE;
final Target target = targetManagement.findTargetByControllerID(controllerId); final Target target = targetManagement.findTargetByControllerID(controllerId);
controllerIDTextField.setValue(target.getControllerId()); controllerIDTextField.setValue(target.getControllerId());
controllerIDTextField.setReadOnly(Boolean.TRUE); controllerIDTextField.setEnabled(Boolean.FALSE);
nameTextField.setValue(target.getName()); nameTextField.setValue(target.getName());
if (target.getDescription() != null) { if (target.getDescription() != null) {
descTextArea.setValue(target.getDescription()); descTextArea.setValue(target.getDescription());
} }
window.setSaveButtonEnabled(Boolean.FALSE); }
oldTargetDesc = descTextArea.getValue(); public FormLayout getFormLayout() {
oldTargetName = nameTextField.getValue(); return formLayout;
window.addStyleName("target-update-window");
} }
} }

View File

@@ -44,7 +44,7 @@ import com.google.common.base.Strings;
public class TargetBeanQuery extends AbstractBeanQuery<ProxyTarget> { public class TargetBeanQuery extends AbstractBeanQuery<ProxyTarget> {
private static final long serialVersionUID = -5645680058303167558L; private static final long serialVersionUID = -5645680058303167558L;
private Sort sort = new Sort(SPUIDefinitions.TARGET_TABLE_CREATE_AT_SORT_ORDER, "createdAt"); private Sort sort = new Sort(SPUIDefinitions.TARGET_TABLE_CREATE_AT_SORT_ORDER, "createdAt");
private Collection<TargetUpdateStatus> status = null; private transient Collection<TargetUpdateStatus> status = null;
private String[] targetTags = null; private String[] targetTags = null;
private Long distributionId = null; private Long distributionId = null;
private String searchText = null; private String searchText = null;

View File

@@ -106,8 +106,13 @@ public class TargetDetails extends AbstractTableDetailsLayout<Target> {
if (getSelectedBaseEntity() == null) { if (getSelectedBaseEntity() == null) {
return; return;
} }
targetAddUpdateWindowLayout.getWindow(getSelectedBaseEntity().getControllerId());
// targetAddUpdateWindowLayout.populateValuesOfTarget(getSelectedBaseEntity().getControllerId());
openWindow();
}
private void openWindow() {
final Window newDistWindow = targetAddUpdateWindowLayout.getWindow(); final Window newDistWindow = targetAddUpdateWindowLayout.getWindow();
targetAddUpdateWindowLayout.populateValuesOfTarget(getSelectedBaseEntity().getControllerId());
newDistWindow.setCaption(getI18n().get("caption.update.dist")); newDistWindow.setCaption(getI18n().get("caption.update.dist"));
UI.getCurrent().addWindow(newDistWindow); UI.getCurrent().addWindow(newDistWindow);
newDistWindow.setVisible(Boolean.TRUE); newDistWindow.setVisible(Boolean.TRUE);
@@ -248,4 +253,24 @@ public class TargetDetails extends AbstractTableDetailsLayout<Target> {
return SPUIComponentIdProvider.TARGET_DETAILS_HEADER_LABEL_ID; return SPUIComponentIdProvider.TARGET_DETAILS_HEADER_LABEL_ID;
} }
@Override
protected String getShowMetadataButtonId() {
return null;
}
@Override
protected Boolean isMetadataIconToBeDisplayed() {
return false;
}
@Override
protected void showMetadata(ClickEvent event) {
//No implementation required
}
@Override
protected void populateMetadataDetails() {
//No implementation required
}
} }

View File

@@ -102,7 +102,6 @@ public class CreateUpdateTargetTagLayoutWindow extends AbstractCreateUpdateTagLa
@Override @Override
public void save(final ClickEvent event) { public void save(final ClickEvent event) {
if (mandatoryValuesPresent()) {
final TargetTag existingTag = tagManagement.findTargetTag(tagName.getValue()); final TargetTag existingTag = tagManagement.findTargetTag(tagName.getValue());
if (optiongroup.getValue().equals(createTagStr)) { if (optiongroup.getValue().equals(createTagStr)) {
if (!checkIsDuplicate(existingTag)) { if (!checkIsDuplicate(existingTag)) {
@@ -112,7 +111,6 @@ public class CreateUpdateTargetTagLayoutWindow extends AbstractCreateUpdateTagLa
updateExistingTag(existingTag); updateExistingTag(existingTag);
} }
} }
}
/** /**
* Create new tag. * Create new tag.
@@ -131,7 +129,6 @@ public class CreateUpdateTargetTagLayoutWindow extends AbstractCreateUpdateTagLa
} }
newTargetTag = tagManagement.createTargetTag(newTargetTag); newTargetTag = tagManagement.createTargetTag(newTargetTag);
displaySuccess(newTargetTag.getName()); displaySuccess(newTargetTag.getName());
closeWindow();
} else { } else {
displayValidationError(i18n.get(MESSAGE_ERROR_MISSING_TAGNAME)); displayValidationError(i18n.get(MESSAGE_ERROR_MISSING_TAGNAME));
} }
@@ -150,4 +147,9 @@ public class CreateUpdateTargetTagLayoutWindow extends AbstractCreateUpdateTagLa
setOptionGroupDefaultValue(permChecker.hasCreateTargetPermission(), permChecker.hasUpdateTargetPermission()); setOptionGroupDefaultValue(permChecker.hasCreateTargetPermission(), permChecker.hasUpdateTargetPermission());
} }
@Override
protected String getWindowCaption() {
return i18n.get("caption.add.tag");
}
} }

View File

@@ -31,6 +31,7 @@ import org.eclipse.hawkbit.ui.UiProperties;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow; import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.common.DistributionSetIdName; import org.eclipse.hawkbit.ui.common.DistributionSetIdName;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIWindowDecorator;
import org.eclipse.hawkbit.ui.filtermanagement.TargetFilterBeanQuery; import org.eclipse.hawkbit.ui.filtermanagement.TargetFilterBeanQuery;
import org.eclipse.hawkbit.ui.management.footer.ActionTypeOptionGroupLayout; import org.eclipse.hawkbit.ui.management.footer.ActionTypeOptionGroupLayout;
import org.eclipse.hawkbit.ui.management.footer.ActionTypeOptionGroupLayout.ActionTypeOption; import org.eclipse.hawkbit.ui.management.footer.ActionTypeOptionGroupLayout.ActionTypeOption;
@@ -56,8 +57,10 @@ import com.vaadin.data.Container;
import com.vaadin.data.Item; import com.vaadin.data.Item;
import com.vaadin.data.Property.ValueChangeEvent; import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Validator; import com.vaadin.data.Validator;
import com.vaadin.data.util.converter.StringToIntegerConverter;
import com.vaadin.data.validator.IntegerRangeValidator; import com.vaadin.data.validator.IntegerRangeValidator;
import com.vaadin.data.validator.RegexpValidator; import com.vaadin.data.validator.NullValidator;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope; import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.ComboBox; import com.vaadin.ui.ComboBox;
@@ -66,13 +69,10 @@ import com.vaadin.ui.Label;
import com.vaadin.ui.OptionGroup; import com.vaadin.ui.OptionGroup;
import com.vaadin.ui.TextArea; import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField; import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.themes.ValoTheme; import com.vaadin.ui.themes.ValoTheme;
/** /**
*
* Rollout add or update popup layout. * Rollout add or update popup layout.
*
*/ */
@SpringComponent @SpringComponent
@ViewScope @ViewScope
@@ -86,8 +86,6 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
private static final String MESSAGE_ENTER_NUMBER = "message.enter.number"; private static final String MESSAGE_ENTER_NUMBER = "message.enter.number";
private static final String NUMBER_REGEXP = "[-]?[0-9]*\\.?,?[0-9]+";
@Autowired @Autowired
private ActionTypeOptionGroupLayout actionTypeOptionGroupLayout; private ActionTypeOptionGroupLayout actionTypeOptionGroupLayout;
@@ -115,8 +113,6 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
@Autowired @Autowired
private transient EventBus.SessionEventBus eventBus; private transient EventBus.SessionEventBus eventBus;
private Label mandatoryLabel;
private TextField rolloutName; private TextField rolloutName;
private ComboBox distributionSet; private ComboBox distributionSet;
@@ -135,7 +131,7 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
private OptionGroup errorThresholdOptionGroup; private OptionGroup errorThresholdOptionGroup;
private CommonDialogWindow addUpdateRolloutWindow; private CommonDialogWindow window;
private Boolean editRolloutEnabled; private Boolean editRolloutEnabled;
@@ -147,22 +143,28 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
private TextArea targetFilterQuery; private TextArea targetFilterQuery;
private final NullValidator nullValidator = new NullValidator(null, false);
/** /**
* Create components and layout. * Create components and layout.
*/ */
public void init() { public void init() {
setSizeUndefined(); setSizeUndefined();
createRequiredComponents(); createRequiredComponents();
buildLayout(); buildLayout();
} }
public CommonDialogWindow getWindow() { public CommonDialogWindow getWindow(final Long rolloutId) {
window = getWindow();
populateData(rolloutId);
return window;
}
addUpdateRolloutWindow = SPUIComponentProvider.getWindow(i18n.get("caption.configure.rollout"), null, public CommonDialogWindow getWindow() {
SPUIDefinitions.CREATE_UPDATE_WINDOW, this, event -> onRolloutSave(), event -> onDiscard(), resetComponents();
uiProperties.getLinks().getDocumentation().getRolloutView()); return SPUIWindowDecorator.getWindow(i18n.get("caption.configure.rollout"), null,
return addUpdateRolloutWindow; SPUIDefinitions.CREATE_UPDATE_WINDOW, this, event -> onRolloutSave(), null,
uiProperties.getLinks().getDocumentation().getRolloutView(), this, i18n);
} }
/** /**
@@ -179,10 +181,8 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
setDefaultSaveStartGroupOption(); setDefaultSaveStartGroupOption();
totalTargetsLabel.setVisible(false); totalTargetsLabel.setVisible(false);
groupSizeLabel.setVisible(false); groupSizeLabel.setVisible(false);
removeComponent(targetFilterQuery); removeComponent(1, 2);
if (getComponent(1, 3) == null) { addComponent(targetFilterQueryCombo, 1, 2);
addComponent(targetFilterQueryCombo, 1, 3);
}
actionTypeOptionGroupLayout.selectDefaultOption(); actionTypeOptionGroupLayout.selectDefaultOption();
totalTargetsCount = 0L; totalTargetsCount = 0L;
rolloutForEdit = null; rolloutForEdit = null;
@@ -206,37 +206,60 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
setSizeUndefined(); setSizeUndefined();
setRows(9); setRows(9);
setColumns(3); setColumns(3);
setStyleName("marginTop");
addComponent(mandatoryLabel, 1, 0, 2, 0); addComponent(getMandatoryLabel("textfield.name"), 0, 0);
addComponent(getLabel("textfield.name"), 0, 1); addComponent(rolloutName, 1, 0);
addComponent(rolloutName, 1, 1); rolloutName.addValidator(nullValidator);
addComponent(getLabel("prompt.distribution.set"), 0, 2);
addComponent(distributionSet, 1, 2); addComponent(getMandatoryLabel("prompt.distribution.set"), 0, 1);
addComponent(getLabel("prompt.target.filter"), 0, 3); addComponent(distributionSet, 1, 1);
addComponent(targetFilterQueryCombo, 1, 3); distributionSet.addValidator(nullValidator);
addComponent(totalTargetsLabel, 2, 3);
addComponent(getLabel("prompt.number.of.groups"), 0, 4); addComponent(getMandatoryLabel("prompt.target.filter"), 0, 2);
addComponent(noOfGroups, 1, 4); addComponent(targetFilterQueryCombo, 1, 2);
addComponent(groupSizeLabel, 2, 4); targetFilterQueryCombo.addValidator(nullValidator);
addComponent(getLabel("prompt.tigger.threshold"), 0, 5); targetFilterQuery.removeValidator(nullValidator);
addComponent(triggerThreshold, 1, 5);
addComponent(getPercentHintLabel(), 2, 5); addComponent(totalTargetsLabel, 2, 2);
addComponent(getLabel("prompt.error.threshold"), 0, 6);
addComponent(errorThreshold, 1, 6); addComponent(getMandatoryLabel("prompt.number.of.groups"), 0, 3);
addComponent(errorThresholdOptionGroup, 2, 6); addComponent(noOfGroups, 1, 3);
addComponent(getLabel("textfield.description"), 0, 7); noOfGroups.addValidator(nullValidator);
addComponent(description, 1, 7, 2, 7);
addComponent(actionTypeOptionGroupLayout, 0, 8, 2, 8); addComponent(groupSizeLabel, 2, 3);
addComponent(getMandatoryLabel("prompt.tigger.threshold"), 0, 4);
addComponent(triggerThreshold, 1, 4);
triggerThreshold.addValidator(nullValidator);
addComponent(getPercentHintLabel(), 2, 4);
addComponent(getMandatoryLabel("prompt.error.threshold"), 0, 5);
addComponent(errorThreshold, 1, 5);
errorThreshold.addValidator(nullValidator);
addComponent(errorThresholdOptionGroup, 2, 5);
addComponent(getLabel("textfield.description"), 0, 6);
addComponent(description, 1, 6, 2, 6);
addComponent(actionTypeOptionGroupLayout, 0, 7, 2, 7);
rolloutName.focus(); rolloutName.focus();
} }
private Label getMandatoryLabel(final String key) {
final Label mandatoryLabel = getLabel(i18n.get(key));
mandatoryLabel.setContentMode(ContentMode.HTML);
mandatoryLabel.setValue(mandatoryLabel.getValue().concat(" <span style='color:#ed473b'>*</span>"));
return mandatoryLabel;
}
private Label getLabel(final String key) { private Label getLabel(final String key) {
return SPUIComponentProvider.getLabel(i18n.get(key), SPUILabelDefinitions.SP_LABEL_SIMPLE); return SPUIComponentProvider.getLabel(i18n.get(key), SPUILabelDefinitions.SP_LABEL_SIMPLE);
} }
private TextField getTextfield(final String key) { private TextField getTextfield(final String key) {
return SPUIComponentProvider.getTextField(null, "", ValoTheme.TEXTFIELD_TINY, true, null, i18n.get(key), true, return SPUIComponentProvider.getTextField(null, "", ValoTheme.TEXTFIELD_TINY, false, null, i18n.get(key), true,
SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH); SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
} }
@@ -248,7 +271,6 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
} }
private void createRequiredComponents() { private void createRequiredComponents() {
mandatoryLabel = createMandatoryLabel();
rolloutName = createRolloutNameField(); rolloutName = createRolloutNameField();
distributionSet = createDistributionSetCombo(); distributionSet = createDistributionSetCombo();
populateDistributionSet(); populateDistributionSet();
@@ -258,7 +280,7 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
noOfGroups = createNoOfGroupsField(); noOfGroups = createNoOfGroupsField();
groupSizeLabel = createGroupSizeLabel(); groupSizeLabel = createGroupSizeLabel();
triggerThreshold = createTriggerThresold(); triggerThreshold = createTriggerThreshold();
errorThreshold = createErrorThreshold(); errorThreshold = createErrorThreshold();
description = createDescription(); description = createDescription();
errorThresholdOptionGroup = createErrorThresholdOptionGroup(); errorThresholdOptionGroup = createErrorThresholdOptionGroup();
@@ -307,11 +329,11 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
errorThresoldOptions.addStyleName(ValoTheme.OPTIONGROUP_HORIZONTAL); errorThresoldOptions.addStyleName(ValoTheme.OPTIONGROUP_HORIZONTAL);
errorThresoldOptions.addStyleName(SPUIStyleDefinitions.ROLLOUT_OPTION_GROUP); errorThresoldOptions.addStyleName(SPUIStyleDefinitions.ROLLOUT_OPTION_GROUP);
errorThresoldOptions.setSizeUndefined(); errorThresoldOptions.setSizeUndefined();
errorThresoldOptions.addValueChangeListener(this::onErrorThresoldOptionChange); errorThresoldOptions.addValueChangeListener(this::listenerOnErrorThresoldOptionChange);
return errorThresoldOptions; return errorThresoldOptions;
} }
private void onErrorThresoldOptionChange(final ValueChangeEvent event) { private void listenerOnErrorThresoldOptionChange(final ValueChangeEvent event) {
errorThreshold.clear(); errorThreshold.clear();
errorThreshold.removeAllValidators(); errorThreshold.removeAllValidators();
if (event.getProperty().getValue().equals(ERRORTHRESOLDOPTIONS.COUNT.getValue())) { if (event.getProperty().getValue().equals(ERRORTHRESOLDOPTIONS.COUNT.getValue())) {
@@ -324,17 +346,17 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
private ComboBox createTargetFilterQueryCombo() { private ComboBox createTargetFilterQueryCombo() {
final ComboBox targetFilter = SPUIComponentProvider.getComboBox(null, "", "", null, ValoTheme.COMBOBOX_SMALL, final ComboBox targetFilter = SPUIComponentProvider.getComboBox(null, "", "", null, ValoTheme.COMBOBOX_SMALL,
true, "", i18n.get("prompt.target.filter")); false, "", i18n.get("prompt.target.filter"));
targetFilter.setImmediate(true); targetFilter.setImmediate(true);
targetFilter.setPageLength(7); targetFilter.setPageLength(7);
targetFilter.setItemCaptionPropertyId(SPUILabelDefinitions.VAR_NAME); targetFilter.setItemCaptionPropertyId(SPUILabelDefinitions.VAR_NAME);
targetFilter.setId(SPUIComponentIdProvider.ROLLOUT_TARGET_FILTER_COMBO_ID); targetFilter.setId(SPUIComponentIdProvider.ROLLOUT_TARGET_FILTER_COMBO_ID);
targetFilter.setSizeUndefined(); targetFilter.setSizeUndefined();
targetFilter.addValueChangeListener(event -> onTargetFilterChange()); targetFilter.addValueChangeListener(this::onTargetFilterChange);
return targetFilter; return targetFilter;
} }
private void onTargetFilterChange() { private void onTargetFilterChange(final ValueChangeEvent event) {
final String filterQueryString = getTargetFilterQuery(); final String filterQueryString = getTargetFilterQuery();
if (!Strings.isNullOrEmpty(filterQueryString)) { if (!Strings.isNullOrEmpty(filterQueryString)) {
totalTargetsCount = targetManagement.countTargetByTargetFilterQuery(filterQueryString); totalTargetsCount = targetManagement.countTargetByTargetFilterQuery(filterQueryString);
@@ -344,7 +366,7 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
totalTargetsCount = 0L; totalTargetsCount = 0L;
totalTargetsLabel.setVisible(false); totalTargetsLabel.setVisible(false);
} }
onGroupNumberChange(); onGroupNumberChange(event);
} }
private String getTotalTargetMessage() { private String getTotalTargetMessage() {
@@ -368,10 +390,6 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
targetFilterQF); targetFilterQF);
} }
private void onDiscard() {
closeThisWindow();
}
private void onRolloutSave() { private void onRolloutSave() {
if (editRolloutEnabled) { if (editRolloutEnabled) {
editRollout(); editRollout();
@@ -381,7 +399,7 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
} }
private void editRollout() { private void editRollout() {
if (mandatoryCheckForEdit() && validateFields() && duplicateCheckForEdit() && null != rolloutForEdit) { if (duplicateCheckForEdit() && rolloutForEdit != null) {
rolloutForEdit.setName(rolloutName.getValue()); rolloutForEdit.setName(rolloutName.getValue());
rolloutForEdit.setDescription(description.getValue()); rolloutForEdit.setDescription(description.getValue());
final DistributionSetIdName distributionSetIdName = (DistributionSetIdName) distributionSet.getValue(); final DistributionSetIdName distributionSetIdName = (DistributionSetIdName) distributionSet.getValue();
@@ -399,7 +417,6 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
final Rollout updatedRollout = rolloutManagement.updateRollout(rolloutForEdit); final Rollout updatedRollout = rolloutManagement.updateRollout(rolloutForEdit);
uiNotification uiNotification
.displaySuccess(i18n.get("message.update.success", new Object[] { updatedRollout.getName() })); .displaySuccess(i18n.get("message.update.success", new Object[] { updatedRollout.getName() }));
closeThisWindow();
eventBus.publish(this, RolloutEvent.UPDATE_ROLLOUT); eventBus.publish(this, RolloutEvent.UPDATE_ROLLOUT);
} }
} }
@@ -427,11 +444,10 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
} }
private void createRollout() { private void createRollout() {
if (mandatoryCheck() && validateFields() && duplicateCheck()) { if (duplicateCheck()) {
final Rollout rolloutToCreate = saveRollout(); final Rollout rolloutToCreate = saveRollout();
uiNotification.displaySuccess(i18n.get("message.save.success", new Object[] { rolloutToCreate.getName() })); uiNotification.displaySuccess(i18n.get("message.save.success", new Object[] { rolloutToCreate.getName() }));
eventBus.publish(this, RolloutEvent.CREATE_ROLLOUT); eventBus.publish(this, RolloutEvent.CREATE_ROLLOUT);
closeThisWindow();
} }
} }
@@ -488,48 +504,6 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
return true; return true;
} }
private void closeThisWindow() {
addUpdateRolloutWindow.close();
UI.getCurrent().removeWindow(addUpdateRolloutWindow);
}
private boolean mandatoryCheck() {
final DistributionSetIdName ds = getDistributionSetSelected();
final String targetFilter = (String) targetFilterQueryCombo.getValue();
final String triggerThresoldValue = triggerThreshold.getValue();
final String errorThresoldValue = errorThreshold.getValue();
if (hasNoNameOrTargetFilter(targetFilter) || ds == null
|| HawkbitCommonUtil.trimAndNullIfEmpty(noOfGroups.getValue()) == null
|| isThresholdValueMissing(triggerThresoldValue, errorThresoldValue)) {
uiNotification.displayValidationError(i18n.get("message.mandatory.check"));
return false;
}
return true;
}
private boolean mandatoryCheckForEdit() {
final DistributionSetIdName ds = getDistributionSetSelected();
final String targetFilter = targetFilterQuery.getValue();
final String triggerThresoldValue = triggerThreshold.getValue();
final String errorThresoldValue = errorThreshold.getValue();
if (hasNoNameOrTargetFilter(targetFilter) || ds == null
|| HawkbitCommonUtil.trimAndNullIfEmpty(noOfGroups.getValue()) == null
|| isThresholdValueMissing(triggerThresoldValue, errorThresoldValue)) {
uiNotification.displayValidationError(i18n.get("message.mandatory.check"));
return false;
}
return true;
}
private boolean hasNoNameOrTargetFilter(final String targetFilter) {
return getRolloutName() == null || targetFilter == null;
}
private boolean isThresholdValueMissing(final String triggerThresoldValue, final String errorThresoldValue) {
return HawkbitCommonUtil.trimAndNullIfEmpty(triggerThresoldValue) == null
|| HawkbitCommonUtil.trimAndNullIfEmpty(errorThresoldValue) == null;
}
private boolean duplicateCheck() { private boolean duplicateCheck() {
if (rolloutManagement.findRolloutByName(getRolloutName()) != null) { if (rolloutManagement.findRolloutByName(getRolloutName()) != null) {
uiNotification.displayValidationError( uiNotification.displayValidationError(
@@ -555,17 +529,23 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
private TextField createErrorThreshold() { private TextField createErrorThreshold() {
final TextField errorField = getTextfield("prompt.error.threshold"); final TextField errorField = getTextfield("prompt.error.threshold");
errorField.setNullRepresentation("");
errorField.addValidator(new ThresholdFieldValidator()); errorField.addValidator(new ThresholdFieldValidator());
errorField.setConverter(new StringToIntegerConverter());
errorField.setConversionError(i18n.get(MESSAGE_ENTER_NUMBER));
errorField.setId(SPUIComponentIdProvider.ROLLOUT_ERROR_THRESOLD_ID); errorField.setId(SPUIComponentIdProvider.ROLLOUT_ERROR_THRESOLD_ID);
errorField.setMaxLength(7); errorField.setMaxLength(7);
errorField.setSizeUndefined(); errorField.setSizeUndefined();
return errorField; return errorField;
} }
private TextField createTriggerThresold() { private TextField createTriggerThreshold() {
final TextField thresholdField = getTextfield("prompt.tigger.threshold"); final TextField thresholdField = getTextfield("prompt.tigger.threshold");
thresholdField.setId(SPUIComponentIdProvider.ROLLOUT_TRIGGER_THRESOLD_ID); thresholdField.setId(SPUIComponentIdProvider.ROLLOUT_TRIGGER_THRESOLD_ID);
thresholdField.setNullRepresentation("");
thresholdField.addValidator(new ThresholdFieldValidator()); thresholdField.addValidator(new ThresholdFieldValidator());
thresholdField.setConverter(new StringToIntegerConverter());
thresholdField.setConversionError(i18n.get(MESSAGE_ENTER_NUMBER));
thresholdField.setSizeUndefined(); thresholdField.setSizeUndefined();
thresholdField.setMaxLength(3); thresholdField.setMaxLength(3);
return thresholdField; return thresholdField;
@@ -577,12 +557,15 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
noOfGroupsField.addValidator(new GroupNumberValidator()); noOfGroupsField.addValidator(new GroupNumberValidator());
noOfGroupsField.setSizeUndefined(); noOfGroupsField.setSizeUndefined();
noOfGroupsField.setMaxLength(3); noOfGroupsField.setMaxLength(3);
noOfGroupsField.addValueChangeListener(evevt -> onGroupNumberChange()); noOfGroupsField.setConverter(new StringToIntegerConverter());
noOfGroupsField.setConversionError(i18n.get(MESSAGE_ENTER_NUMBER));
noOfGroupsField.addValueChangeListener(this::onGroupNumberChange);
noOfGroupsField.setNullRepresentation("");
return noOfGroupsField; return noOfGroupsField;
} }
private void onGroupNumberChange() { private void onGroupNumberChange(final ValueChangeEvent event) {
if (noOfGroups.isValid() && !Strings.isNullOrEmpty(noOfGroups.getValue())) { if (event.getProperty().getValue() != null && noOfGroups.isValid()) {
groupSizeLabel.setValue(getTargetPerGroupMessage(String.valueOf(getGroupSize()))); groupSizeLabel.setValue(getTargetPerGroupMessage(String.valueOf(getGroupSize())));
groupSizeLabel.setVisible(true); groupSizeLabel.setVisible(true);
} else { } else {
@@ -591,8 +574,8 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
} }
private ComboBox createDistributionSetCombo() { private ComboBox createDistributionSetCombo() {
final ComboBox dsSet = SPUIComponentProvider.getComboBox(null, "", "", null, ValoTheme.COMBOBOX_SMALL, true, "", final ComboBox dsSet = SPUIComponentProvider.getComboBox(null, "", "", null, ValoTheme.COMBOBOX_SMALL, false,
i18n.get("prompt.distribution.set")); "", i18n.get("prompt.distribution.set"));
dsSet.setImmediate(true); dsSet.setImmediate(true);
dsSet.setPageLength(7); dsSet.setPageLength(7);
dsSet.setItemCaptionPropertyId(SPUILabelDefinitions.VAR_NAME); dsSet.setItemCaptionPropertyId(SPUILabelDefinitions.VAR_NAME);
@@ -612,7 +595,6 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
return new LazyQueryContainer( return new LazyQueryContainer(
new LazyQueryDefinition(true, SPUIDefinitions.PAGE_SIZE, SPUILabelDefinitions.VAR_DIST_ID_NAME), new LazyQueryDefinition(true, SPUIDefinitions.PAGE_SIZE, SPUILabelDefinitions.VAR_DIST_ID_NAME),
distributionQF); distributionQF);
} }
private TextField createRolloutNameField() { private TextField createRolloutNameField() {
@@ -622,44 +604,42 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
return rolloutNameField; return rolloutNameField;
} }
private Label createMandatoryLabel() {
final Label madatoryLbl = new Label(i18n.get("label.mandatory.field"));
madatoryLbl.addStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR + " " + ValoTheme.LABEL_SMALL);
return madatoryLbl;
}
private String getRolloutName() { private String getRolloutName() {
return HawkbitCommonUtil.trimAndNullIfEmpty(rolloutName.getValue()); return HawkbitCommonUtil.trimAndNullIfEmpty(rolloutName.getValue());
} }
private DistributionSetIdName getDistributionSetSelected() {
return (DistributionSetIdName) distributionSet.getValue();
}
class ErrorThresoldOptionValidator implements Validator { class ErrorThresoldOptionValidator implements Validator {
private static final long serialVersionUID = 9049939751976326550L; private static final long serialVersionUID = 9049939751976326550L;
@Override @Override
public void validate(final Object value) { public void validate(final Object value) {
try { try {
if (HawkbitCommonUtil.trimAndNullIfEmpty(noOfGroups.getValue()) == null if (isNoOfGroupsOrTargetFilterEmpty()) {
|| HawkbitCommonUtil.trimAndNullIfEmpty((String) targetFilterQueryCombo.getValue()) == null) {
uiNotification uiNotification
.displayValidationError(i18n.get("message.rollout.noofgroups.or.targetfilter.missing")); .displayValidationError(i18n.get("message.rollout.noofgroups.or.targetfilter.missing"));
} else { } else {
new RegexpValidator(NUMBER_REGEXP, i18n.get(MESSAGE_ENTER_NUMBER)).validate(value); if (value != null) {
final int groupSize = getGroupSize(); final int groupSize = getGroupSize();
new IntegerRangeValidator(i18n.get(MESSAGE_ROLLOUT_FIELD_VALUE_RANGE, 0, groupSize), 0, groupSize) new IntegerRangeValidator(i18n.get(MESSAGE_ROLLOUT_FIELD_VALUE_RANGE, 0, groupSize), 0,
.validate(Integer.valueOf(value.toString())); groupSize).validate(Integer.valueOf(value.toString()));
}
} }
} }
// suppress the need of preserve original exception, will blow // suppress the need of preserve original exception, will blow
// up the // up the
// log and not necessary here // log and not necessary here
catch (@SuppressWarnings("squid:S1166") final InvalidValueException ex) { catch (final InvalidValueException ex) {
LOG.error(ex.getMessage()); // we have to throw the exception here, otherwise the UI won't
// show the vaadin validation error!
throw ex;
} }
} }
private boolean isNoOfGroupsOrTargetFilterEmpty() {
return HawkbitCommonUtil.trimAndNullIfEmpty(noOfGroups.getValue()) == null
|| (HawkbitCommonUtil.trimAndNullIfEmpty((String) targetFilterQueryCombo.getValue()) == null
&& targetFilterQuery.getValue() == null);
}
} }
private int getGroupSize() { private int getGroupSize() {
@@ -672,15 +652,18 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
@Override @Override
public void validate(final Object value) { public void validate(final Object value) {
try { try {
new RegexpValidator(NUMBER_REGEXP, i18n.get(MESSAGE_ENTER_NUMBER)).validate(value); if (value != null) {
new IntegerRangeValidator(i18n.get(MESSAGE_ROLLOUT_FIELD_VALUE_RANGE, 0, 100), 0, 100) new IntegerRangeValidator(i18n.get(MESSAGE_ROLLOUT_FIELD_VALUE_RANGE, 0, 100), 0, 100)
.validate(Integer.valueOf(value.toString())); .validate(Integer.valueOf(value.toString()));
} }
}
// suppress the need of preserve original exception, will blow // suppress the need of preserve original exception, will blow
// up the // up the
// log and not necessary here // log and not necessary here
catch (@SuppressWarnings("squid:S1166") final InvalidValueException ex) { catch (final InvalidValueException ex) {
LOG.error(ex.getMessage()); // we have to throw the exception here, otherwise the UI won't
// show the vaadin validation error!
throw ex;
} }
} }
} }
@@ -691,15 +674,18 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
@Override @Override
public void validate(final Object value) { public void validate(final Object value) {
try { try {
new RegexpValidator(NUMBER_REGEXP, i18n.get(MESSAGE_ENTER_NUMBER)).validate(value); if (value != null) {
new IntegerRangeValidator(i18n.get(MESSAGE_ROLLOUT_FIELD_VALUE_RANGE, 0, 500), 0, 500) new IntegerRangeValidator(i18n.get(MESSAGE_ROLLOUT_FIELD_VALUE_RANGE, 0, 500), 0, 500)
.validate(Integer.valueOf(value.toString())); .validate(Integer.valueOf(value.toString()));
} }
}
// suppress the need of preserve original exception, will blow // suppress the need of preserve original exception, will blow
// up the // up the
// log and not necessary here // log and not necessary here
catch (@SuppressWarnings("squid:S1166") final InvalidValueException ex) { catch (final InvalidValueException ex) {
LOG.error(ex.getMessage()); // we have to throw the exception here, otherwise the UI won't
// show the vaadin validation error!
throw ex;
} }
} }
} }
@@ -711,15 +697,18 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
* @param rolloutId * @param rolloutId
* rollout id * rollout id
*/ */
public void populateData(final Long rolloutId) { private void populateData(final Long rolloutId) {
resetComponents(); if (rolloutId == null) {
return;
}
editRolloutEnabled = Boolean.TRUE; editRolloutEnabled = Boolean.TRUE;
rolloutForEdit = rolloutManagement.findRolloutById(rolloutId); rolloutForEdit = rolloutManagement.findRolloutById(rolloutId);
rolloutName.setValue(rolloutForEdit.getName()); rolloutName.setValue(rolloutForEdit.getName());
description.setValue(rolloutForEdit.getDescription()); description.setValue(rolloutForEdit.getDescription());
distributionSet.setValue(DistributionSetIdName.generate(rolloutForEdit.getDistributionSet())); distributionSet.setValue(DistributionSetIdName.generate(rolloutForEdit.getDistributionSet()));
final List<RolloutGroup> rolloutGroups = rolloutForEdit.getRolloutGroups(); final List<RolloutGroup> rolloutGroups = rolloutForEdit.getRolloutGroups();
setThresoldValues(rolloutGroups); setThresholdValues(rolloutGroups);
setActionType(rolloutForEdit); setActionType(rolloutForEdit);
if (rolloutForEdit.getStatus() != RolloutStatus.READY) { if (rolloutForEdit.getStatus() != RolloutStatus.READY) {
disableRequiredFieldsOnEdit(); disableRequiredFieldsOnEdit();
@@ -727,12 +716,16 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
noOfGroups.setEnabled(false); noOfGroups.setEnabled(false);
targetFilterQuery.setValue(rolloutForEdit.getTargetFilterQuery()); targetFilterQuery.setValue(rolloutForEdit.getTargetFilterQuery());
removeComponent(targetFilterQueryCombo); removeComponent(1, 2);
addComponent(targetFilterQuery, 1, 3); targetFilterQueryCombo.removeValidator(nullValidator);
addComponent(targetFilterQuery, 1, 2);
targetFilterQuery.addValidator(nullValidator);
totalTargetsCount = targetManagement.countTargetByTargetFilterQuery(rolloutForEdit.getTargetFilterQuery()); totalTargetsCount = targetManagement.countTargetByTargetFilterQuery(rolloutForEdit.getTargetFilterQuery());
totalTargetsLabel.setValue(getTotalTargetMessage()); totalTargetsLabel.setValue(getTotalTargetMessage());
totalTargetsLabel.setVisible(true); totalTargetsLabel.setVisible(true);
window.setOrginaleValues();
} }
private void disableRequiredFieldsOnEdit() { private void disableRequiredFieldsOnEdit() {
@@ -771,8 +764,8 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
/** /**
* @param rolloutGroups * @param rolloutGroups
*/ */
private void setThresoldValues(final List<RolloutGroup> rolloutGroups) { private void setThresholdValues(final List<RolloutGroup> rolloutGroups) {
if (null != rolloutGroups && !rolloutGroups.isEmpty()) { if (rolloutGroups != null && !rolloutGroups.isEmpty()) {
errorThreshold.setValue(rolloutGroups.get(0).getErrorConditionExp()); errorThreshold.setValue(rolloutGroups.get(0).getErrorConditionExp());
triggerThreshold.setValue(rolloutGroups.get(0).getSuccessConditionExp()); triggerThreshold.setValue(rolloutGroups.get(0).getSuccessConditionExp());
noOfGroups.setValue(String.valueOf(rolloutGroups.size())); noOfGroups.setValue(String.valueOf(rolloutGroups.size()));
@@ -798,7 +791,6 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
public String getValue() { public String getValue() {
return value; return value;
} }
} }
enum ERRORTHRESOLDOPTIONS { enum ERRORTHRESOLDOPTIONS {
@@ -816,6 +808,6 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
public String getValue() { public String getValue() {
return value; return value;
} }
}
} }
}

View File

@@ -16,6 +16,7 @@ import static org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil.HTML_UL_OPEN_TAG;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
@@ -28,6 +29,7 @@ import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus; import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus; import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.common.grid.AbstractGrid; import org.eclipse.hawkbit.ui.common.grid.AbstractGrid;
import org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRendererData; import org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRendererData;
import org.eclipse.hawkbit.ui.customrenderers.renderers.HtmlButtonRenderer; import org.eclipse.hawkbit.ui.customrenderers.renderers.HtmlButtonRenderer;
@@ -47,29 +49,21 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory; import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory;
import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer; import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer;
import org.vaadin.addons.lazyquerycontainer.LazyQueryDefinition; import org.vaadin.addons.lazyquerycontainer.LazyQueryDefinition;
import org.vaadin.peter.contextmenu.ContextMenu;
import org.vaadin.peter.contextmenu.ContextMenu.ContextMenuItem;
import org.vaadin.peter.contextmenu.ContextMenu.ContextMenuItemClickEvent;
import org.vaadin.spring.events.EventScope; import org.vaadin.spring.events.EventScope;
import org.vaadin.spring.events.annotation.EventBusListenerMethod; import org.vaadin.spring.events.annotation.EventBusListenerMethod;
import com.vaadin.data.Container; import com.vaadin.data.Container;
import com.vaadin.data.Item; import com.vaadin.data.Item;
import com.vaadin.data.util.PropertyValueGenerator;
import com.vaadin.data.util.converter.Converter; import com.vaadin.data.util.converter.Converter;
import com.vaadin.server.AbstractClientConnector;
import com.vaadin.server.FontAwesome; import com.vaadin.server.FontAwesome;
import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope; import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.UI; import com.vaadin.ui.UI;
import com.vaadin.ui.Window;
import com.vaadin.ui.renderers.ClickableRenderer.RendererClickEvent; import com.vaadin.ui.renderers.ClickableRenderer.RendererClickEvent;
import com.vaadin.ui.renderers.HtmlRenderer; import com.vaadin.ui.renderers.HtmlRenderer;
/** /**
*
* Rollout list grid component. * Rollout list grid component.
*
*/ */
@SpringComponent @SpringComponent
@ViewScope @ViewScope
@@ -79,11 +73,9 @@ public class RolloutListGrid extends AbstractGrid {
private static final String UPDATE_OPTION = "Update"; private static final String UPDATE_OPTION = "Update";
private static final String RESUME_OPTION = "Resume";
private static final String PAUSE_OPTION = "Pause"; private static final String PAUSE_OPTION = "Pause";
private static final String START_OPTION = "Start"; private static final String RUN_OPTION = "Run";
private static final String DS_TYPE = "type"; private static final String DS_TYPE = "type";
@@ -145,6 +137,7 @@ public class RolloutListGrid extends AbstractGrid {
final LazyQueryContainer rolloutContainer = (LazyQueryContainer) getContainerDataSource(); final LazyQueryContainer rolloutContainer = (LazyQueryContainer) getContainerDataSource();
final Item item = rolloutContainer.getItem(rolloutChangeEvent.getRolloutId()); final Item item = rolloutContainer.getItem(rolloutChangeEvent.getRolloutId());
if (item == null) { if (item == null) {
refreshGrid();
return; return;
} }
item.getItemProperty(SPUILabelDefinitions.VAR_STATUS).setValue(rollout.getStatus()); item.getItemProperty(SPUILabelDefinitions.VAR_STATUS).setValue(rollout.getStatus());
@@ -159,7 +152,6 @@ public class RolloutListGrid extends AbstractGrid {
} }
item.getItemProperty(ROLLOUT_RENDERER_DATA) item.getItemProperty(ROLLOUT_RENDERER_DATA)
.setValue(new RolloutRendererData(rollout.getName(), rollout.getStatus().toString())); .setValue(new RolloutRendererData(rollout.getName(), rollout.getStatus().toString()));
} }
@Override @Override
@@ -198,9 +190,15 @@ public class RolloutListGrid extends AbstractGrid {
rolloutGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS, rolloutGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS,
TotalTargetCountStatus.class, null, false, false); TotalTargetCountStatus.class, null, false, false);
rolloutGridContainer.addContainerProperty(SPUILabelDefinitions.ACTION, String.class, rolloutGridContainer.addContainerProperty(RUN_OPTION, String.class, FontAwesome.PLAY.getHtml(), false, false);
FontAwesome.CIRCLE_O.getHtml(), false, false);
rolloutGridContainer.addContainerProperty(PAUSE_OPTION, String.class, FontAwesome.PAUSE.getHtml(), false,
false);
if (permissionChecker.hasRolloutUpdatePermission()) {
rolloutGridContainer.addContainerProperty(UPDATE_OPTION, String.class, FontAwesome.EDIT.getHtml(), false,
false);
}
} }
@Override @Override
@@ -221,8 +219,16 @@ public class RolloutListGrid extends AbstractGrid {
getColumn(SPUILabelDefinitions.VAR_NUMBER_OF_GROUPS).setMinimumWidth(40); getColumn(SPUILabelDefinitions.VAR_NUMBER_OF_GROUPS).setMinimumWidth(40);
getColumn(SPUILabelDefinitions.VAR_NUMBER_OF_GROUPS).setMaximumWidth(100); getColumn(SPUILabelDefinitions.VAR_NUMBER_OF_GROUPS).setMaximumWidth(100);
getColumn(SPUILabelDefinitions.ACTION).setMinimumWidth(75); getColumn(RUN_OPTION).setMinimumWidth(25);
getColumn(SPUILabelDefinitions.ACTION).setMaximumWidth(75); getColumn(RUN_OPTION).setMaximumWidth(25);
getColumn(PAUSE_OPTION).setMinimumWidth(25);
getColumn(PAUSE_OPTION).setMaximumWidth(25);
if (permissionChecker.hasRolloutUpdatePermission()) {
getColumn(UPDATE_OPTION).setMinimumWidth(25);
getColumn(UPDATE_OPTION).setMaximumWidth(25);
}
getColumn(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS).setMinimumWidth(280); getColumn(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS).setMinimumWidth(280);
@@ -232,9 +238,9 @@ public class RolloutListGrid extends AbstractGrid {
@Override @Override
protected void setColumnHeaderNames() { protected void setColumnHeaderNames() {
getColumn(ROLLOUT_RENDERER_DATA).setHeaderCaption(i18n.get("header.name")); getColumn(ROLLOUT_RENDERER_DATA).setHeaderCaption(i18n.get("header.name"));
getColumn(DS_TYPE).setHeaderCaption("Type"); getColumn(DS_TYPE).setHeaderCaption(i18n.get("header.type"));
getColumn(SW_MODULES).setHeaderCaption("swModules"); getColumn(SW_MODULES).setHeaderCaption(i18n.get("header.swmodules"));
getColumn(IS_REQUIRED_MIGRATION_STEP).setHeaderCaption("IsRequiredMigrationStep"); getColumn(IS_REQUIRED_MIGRATION_STEP).setHeaderCaption(i18n.get("header.migrations.step"));
getColumn(SPUILabelDefinitions.VAR_DIST_NAME_VERSION).setHeaderCaption(i18n.get("header.distributionset")); getColumn(SPUILabelDefinitions.VAR_DIST_NAME_VERSION).setHeaderCaption(i18n.get("header.distributionset"));
getColumn(SPUILabelDefinitions.VAR_NUMBER_OF_GROUPS).setHeaderCaption(i18n.get("header.numberofgroups")); getColumn(SPUILabelDefinitions.VAR_NUMBER_OF_GROUPS).setHeaderCaption(i18n.get("header.numberofgroups"));
getColumn(SPUILabelDefinitions.VAR_TOTAL_TARGETS).setHeaderCaption(i18n.get("header.total.targets")); getColumn(SPUILabelDefinitions.VAR_TOTAL_TARGETS).setHeaderCaption(i18n.get("header.total.targets"));
@@ -246,7 +252,16 @@ public class RolloutListGrid extends AbstractGrid {
getColumn(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS) getColumn(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS)
.setHeaderCaption(i18n.get("header.detail.status")); .setHeaderCaption(i18n.get("header.detail.status"));
getColumn(SPUILabelDefinitions.VAR_STATUS).setHeaderCaption(i18n.get("header.status")); getColumn(SPUILabelDefinitions.VAR_STATUS).setHeaderCaption(i18n.get("header.status"));
getColumn(SPUILabelDefinitions.ACTION).setHeaderCaption(i18n.get("upload.action"));
getColumn(RUN_OPTION).setHeaderCaption(i18n.get("header.action.run"));
getColumn(PAUSE_OPTION).setHeaderCaption(i18n.get("header.action.pause"));
if (permissionChecker.hasRolloutUpdatePermission()) {
getColumn(UPDATE_OPTION).setHeaderCaption(i18n.get("header.action.update"));
}
final HeaderCell join = getDefaultHeaderRow().join(RUN_OPTION, PAUSE_OPTION, UPDATE_OPTION);
join.setText(i18n.get("header.action"));
} }
@Override @Override
@@ -266,7 +281,13 @@ public class RolloutListGrid extends AbstractGrid {
columnList.add(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS); columnList.add(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS);
columnList.add(SPUILabelDefinitions.VAR_NUMBER_OF_GROUPS); columnList.add(SPUILabelDefinitions.VAR_NUMBER_OF_GROUPS);
columnList.add(SPUILabelDefinitions.VAR_TOTAL_TARGETS); columnList.add(SPUILabelDefinitions.VAR_TOTAL_TARGETS);
columnList.add(SPUILabelDefinitions.ACTION);
columnList.add(RUN_OPTION);
columnList.add(PAUSE_OPTION);
if (permissionChecker.hasRolloutUpdatePermission()) {
columnList.add(UPDATE_OPTION);
}
columnList.add(SPUILabelDefinitions.VAR_CREATED_DATE); columnList.add(SPUILabelDefinitions.VAR_CREATED_DATE);
columnList.add(SPUILabelDefinitions.VAR_CREATED_USER); columnList.add(SPUILabelDefinitions.VAR_CREATED_USER);
@@ -292,7 +313,6 @@ public class RolloutListGrid extends AbstractGrid {
for (final Object propertyId : columnsToBeHidden) { for (final Object propertyId : columnsToBeHidden) {
getColumn(propertyId).setHidden(true); getColumn(propertyId).setHidden(true);
} }
} }
@Override @Override
@@ -310,12 +330,21 @@ public class RolloutListGrid extends AbstractGrid {
createRolloutStatusToFontMap(); createRolloutStatusToFontMap();
getColumn(SPUILabelDefinitions.VAR_STATUS).setRenderer(new HtmlLabelRenderer(), new RolloutStatusConverter()); getColumn(SPUILabelDefinitions.VAR_STATUS).setRenderer(new HtmlLabelRenderer(), new RolloutStatusConverter());
getColumn(SPUILabelDefinitions.ACTION).setRenderer(new HtmlButtonRenderer(this::onClickOfActionBtn));
final RolloutRenderer customObjectRenderer = new RolloutRenderer(RolloutRendererData.class); final RolloutRenderer customObjectRenderer = new RolloutRenderer(RolloutRendererData.class);
customObjectRenderer.addClickListener(this::onClickOfRolloutName); customObjectRenderer.addClickListener(this::onClickOfRolloutName);
getColumn(ROLLOUT_RENDERER_DATA).setRenderer(customObjectRenderer); getColumn(ROLLOUT_RENDERER_DATA).setRenderer(customObjectRenderer);
getColumn(RUN_OPTION)
.setRenderer(new HtmlButtonRenderer(clickEvent -> startOrResumeRollout((Long) clickEvent.getItemId())));
getColumn(PAUSE_OPTION)
.setRenderer(new HtmlButtonRenderer(clickEvent -> pauseRollout((Long) clickEvent.getItemId())));
if (permissionChecker.hasRolloutUpdatePermission()) {
getColumn(UPDATE_OPTION)
.setRenderer(new HtmlButtonRenderer(clickEvent -> updateRollout((Long) clickEvent.getItemId())));
}
} }
private void createRolloutStatusToFontMap() { private void createRolloutStatusToFontMap() {
@@ -337,18 +366,7 @@ public class RolloutListGrid extends AbstractGrid {
} }
private void alignColumns() { private void alignColumns() {
setCellStyleGenerator(new CellStyleGenerator() { setCellStyleGenerator(new RollouStatusCellStyleGenerator(getContainerDataSource()));
private static final long serialVersionUID = 5573570647129792429L;
@Override
public String getStyle(final CellReference cellReference) {
final String[] coulmnNames = { SPUILabelDefinitions.VAR_STATUS, SPUILabelDefinitions.ACTION };
if (Arrays.asList(coulmnNames).contains(cellReference.getPropertyId())) {
return "centeralign";
}
return null;
}
});
} }
private void onClickOfRolloutName(final RendererClickEvent event) { private void onClickOfRolloutName(final RendererClickEvent event) {
@@ -362,83 +380,44 @@ public class RolloutListGrid extends AbstractGrid {
eventBus.publish(this, RolloutEvent.SHOW_ROLLOUT_GROUPS); eventBus.publish(this, RolloutEvent.SHOW_ROLLOUT_GROUPS);
} }
private void onClickOfActionBtn(final RendererClickEvent event) { private void pauseRollout(final Long rolloutId) {
final ContextMenu contextMenu = createContextMenu((Long) event.getItemId());
contextMenu.setAsContextMenuOf((AbstractClientConnector) event.getComponent());
contextMenu.open(event.getClientX(), event.getClientY());
}
private ContextMenu createContextMenu(final Long rolloutId) {
final ContextMenu context = new ContextMenu();
context.addItemClickListener(this::menuItemClicked);
final Item row = getContainerDataSource().getItem(rolloutId); final Item row = getContainerDataSource().getItem(rolloutId);
final RolloutStatus rolloutStatus = (RolloutStatus) row.getItemProperty(SPUILabelDefinitions.VAR_STATUS) final RolloutStatus rolloutStatus = (RolloutStatus) row.getItemProperty(SPUILabelDefinitions.VAR_STATUS)
.getValue(); .getValue();
switch (rolloutStatus) { if (!RolloutStatus.RUNNING.equals(rolloutStatus)) {
case READY:
final ContextMenuItem startItem = context.addItem(START_OPTION);
startItem.setData(new ContextMenuData(rolloutId, ACTION.START));
break;
case RUNNING:
final ContextMenuItem pauseItem = context.addItem(PAUSE_OPTION);
pauseItem.setData(new ContextMenuData(rolloutId, ACTION.PAUSE));
break;
case PAUSED:
final ContextMenuItem resumeItem = context.addItem(RESUME_OPTION);
resumeItem.setData(new ContextMenuData(rolloutId, ACTION.RESUME));
break;
case STARTING:
case CREATING:
case ERROR_CREATING:
case ERROR_STARTING:
// do not provide any action on these statuses
return context;
default:
break;
}
getUpdateMenuItem(context, rolloutId);
return context;
}
private void getUpdateMenuItem(final ContextMenu context, final Long rolloutId) {
// Add 'Update' option only if user has update permission
if (!permissionChecker.hasRolloutUpdatePermission()) {
return; return;
} }
final ContextMenuItem cancelItem = context.addItem(UPDATE_OPTION);
cancelItem.setData(new ContextMenuData(rolloutId, ACTION.UPDATE)); final String rolloutName = (String) row.getItemProperty(SPUILabelDefinitions.VAR_NAME).getValue();
rolloutManagement.pauseRollout(rolloutManagement.findRolloutById(rolloutId));
uiNotification.displaySuccess(i18n.get("message.rollout.paused", rolloutName));
} }
private void menuItemClicked(final ContextMenuItemClickEvent event) { private void startOrResumeRollout(final Long rolloutId) {
final ContextMenuItem item = (ContextMenuItem) event.getSource(); final Item row = getContainerDataSource().getItem(rolloutId);
final ContextMenuData contextMenuData = (ContextMenuData) item.getData();
final Item row = getContainerDataSource().getItem(contextMenuData.getRolloutId()); final RolloutStatus rolloutStatus = (RolloutStatus) row.getItemProperty(SPUILabelDefinitions.VAR_STATUS)
.getValue();
final String rolloutName = (String) row.getItemProperty(SPUILabelDefinitions.VAR_NAME).getValue(); final String rolloutName = (String) row.getItemProperty(SPUILabelDefinitions.VAR_NAME).getValue();
switch (contextMenuData.getAction()) {
case PAUSE: if (RolloutStatus.READY.equals(rolloutStatus)) {
rolloutManagement.pauseRollout(rolloutManagement.findRolloutById(contextMenuData.getRolloutId()));
uiNotification.displaySuccess(i18n.get("message.rollout.paused", rolloutName));
break;
case RESUME:
rolloutManagement.resumeRollout(rolloutManagement.findRolloutById(contextMenuData.getRolloutId()));
uiNotification.displaySuccess(i18n.get("message.rollout.resumed", rolloutName));
break;
case START:
rolloutManagement.startRolloutAsync(rolloutManagement.findRolloutByName(rolloutName)); rolloutManagement.startRolloutAsync(rolloutManagement.findRolloutByName(rolloutName));
uiNotification.displaySuccess(i18n.get("message.rollout.started", rolloutName)); uiNotification.displaySuccess(i18n.get("message.rollout.started", rolloutName));
break; return;
case UPDATE: }
onUpdate(contextMenuData);
break; if (RolloutStatus.PAUSED.equals(rolloutStatus)) {
default: rolloutManagement.resumeRollout(rolloutManagement.findRolloutById(rolloutId));
break; uiNotification.displaySuccess(i18n.get("message.rollout.resumed", rolloutName));
return;
} }
} }
private void onUpdate(final ContextMenuData contextMenuData) { private void updateRollout(final Long rolloutId) {
addUpdateRolloutWindow.populateData(contextMenuData.getRolloutId()); final CommonDialogWindow addTargetWindow = addUpdateRolloutWindow.getWindow(rolloutId);
final Window addTargetWindow = addUpdateRolloutWindow.getWindow();
addTargetWindow.setCaption(i18n.get("caption.update.rollout")); addTargetWindow.setCaption(i18n.get("caption.update.rollout"));
UI.getCurrent().addWindow(addTargetWindow); UI.getCurrent().addWindow(addTargetWindow);
addTargetWindow.setVisible(Boolean.TRUE); addTargetWindow.setVisible(Boolean.TRUE);
@@ -448,29 +427,6 @@ public class RolloutListGrid extends AbstractGrid {
((LazyQueryContainer) getContainerDataSource()).refresh(); ((LazyQueryContainer) getContainerDataSource()).refresh();
} }
/**
* Generator to generate fontIcon by String.
*/
public final class FontIconGenerator extends PropertyValueGenerator<String> {
private static final long serialVersionUID = 2544026030795375748L;
private final FontAwesome fontIcon;
public FontIconGenerator(final FontAwesome icon) {
this.fontIcon = icon;
}
@Override
public String getValue(final Item item, final Object itemId, final Object propertyId) {
return fontIcon.getHtml();
}
@Override
public Class<String> getType() {
return String.class;
}
}
private String getDescription(final CellReference cell) { private String getDescription(final CellReference cell) {
if (SPUILabelDefinitions.VAR_STATUS.equals(cell.getPropertyId())) { if (SPUILabelDefinitions.VAR_STATUS.equals(cell.getPropertyId())) {
return cell.getProperty().getValue().toString().toLowerCase(); return cell.getProperty().getValue().toString().toLowerCase();
@@ -524,61 +480,70 @@ public class RolloutListGrid extends AbstractGrid {
return stringBuilder.toString(); return stringBuilder.toString();
} }
enum ACTION { private static class RollouStatusCellStyleGenerator implements CellStyleGenerator {
PAUSE, RESUME, START, UPDATE
private static final long serialVersionUID = 1L;
/**
* Contains all expected rollout status per column to enable or disable
* the button.
*/
private static final Map<String, RolloutStatus> EXPECTED_ROLLOUT_STATUS_ENABLE_BUTTON = new HashMap<>();
private final Container.Indexed containerDataSource;
static {
EXPECTED_ROLLOUT_STATUS_ENABLE_BUTTON.put(RUN_OPTION, RolloutStatus.READY);
EXPECTED_ROLLOUT_STATUS_ENABLE_BUTTON.put(PAUSE_OPTION, RolloutStatus.RUNNING);
} }
/** /**
* Represents data of context menu item. * Constructor
* *
* @param containerDataSource
* the container
*/ */
public static class ContextMenuData { public RollouStatusCellStyleGenerator(final Container.Indexed containerDataSource) {
this.containerDataSource = containerDataSource;
private Long rolloutId;
private ACTION action;
/**
* Set rollout if and action.
*
* @param rolloutId
* id of rollout
* @param action
* user action {@link ACTION}
*/
public ContextMenuData(final Long rolloutId, final ACTION action) {
this.action = action;
this.rolloutId = rolloutId;
} }
/** @Override
* @return the rolloutId public String getStyle(final CellReference cellReference) {
*/ if (SPUILabelDefinitions.VAR_STATUS.equals(cellReference.getPropertyId())) {
public Long getRolloutId() { return "centeralign";
return rolloutId; }
return convertRolloutStatusToString(cellReference);
} }
/** private String convertRolloutStatusToString(final CellReference cellReference) {
* @param rolloutId final Object propertyId = cellReference.getPropertyId();
* the rolloutId to set final RolloutStatus expectedRolloutStatus = EXPECTED_ROLLOUT_STATUS_ENABLE_BUTTON.get(propertyId);
*/ if (expectedRolloutStatus == null) {
public void setRolloutId(final Long rolloutId) { return null;
this.rolloutId = rolloutId;
} }
/** if (RUN_OPTION.equals(cellReference.getPropertyId())) {
* @return the action return getStatus(cellReference, RolloutStatus.READY, RolloutStatus.PAUSED);
*/
public ACTION getAction() {
return action;
} }
/** if (PAUSE_OPTION.equals(cellReference.getPropertyId())) {
* @param action return getStatus(cellReference, RolloutStatus.RUNNING);
* the action to set }
*/
public void setAction(final ACTION action) { return null;
this.action = action; }
private String getStatus(final CellReference cellReference, final RolloutStatus... expectedRolloutStatus) {
final RolloutStatus currentRolloutStatus = getRolloutStatus(cellReference.getItemId());
if (Arrays.asList(expectedRolloutStatus).contains(currentRolloutStatus)) {
return null;
}
return org.eclipse.hawkbit.ui.customrenderers.client.renderers.HtmlButtonRenderer.DISABLE_VALUE;
}
private RolloutStatus getRolloutStatus(final Object itemId) {
final Item row = containerDataSource.getItem(itemId);
return (RolloutStatus) row.getItemProperty(SPUILabelDefinitions.VAR_STATUS).getValue();
} }
} }
@@ -684,7 +649,6 @@ public class RolloutListGrid extends AbstractGrid {
public Class<String> getPresentationType() { public Class<String> getPresentationType() {
return String.class; return String.class;
} }
} }
} }

View File

@@ -91,7 +91,6 @@ public class RolloutListHeader extends AbstractGridHeader {
@Override @Override
protected void addNewItem(final ClickEvent event) { protected void addNewItem(final ClickEvent event) {
addUpdateRolloutWindow.resetComponents();
final Window addTargetWindow = addUpdateRolloutWindow.getWindow(); final Window addTargetWindow = addUpdateRolloutWindow.getWindow();
UI.getCurrent().addWindow(addTargetWindow); UI.getCurrent().addWindow(addTargetWindow);
addTargetWindow.setVisible(Boolean.TRUE); addTargetWindow.setVisible(Boolean.TRUE);

View File

@@ -82,9 +82,9 @@ public final class HawkbitCommonUtil {
private static final String JS_DRAG_COUNT_REM_CHILD = " if(x) { document.head.removeChild(x); } "; private static final String JS_DRAG_COUNT_REM_CHILD = " if(x) { document.head.removeChild(x); } ";
private static final String DIV_DESCRIPTION = "<div id=\"desc-length\"><p id=\"desciption-p\">"; public static final String DIV_DESCRIPTION = "<div id=\"desc-length\"><p id=\"desciption-p\">";
private static final String DIV_CLOSE = "</p></div>"; public static final String DIV_CLOSE = "</p></div>";
private static final String DRAG_COUNT_ELEMENT = "var x = document.getElementById('sp-drag-count'); "; private static final String DRAG_COUNT_ELEMENT = "var x = document.getElementById('sp-drag-count'); ";
private static final String CLOSE_BRACE = "\"; }';"; private static final String CLOSE_BRACE = "\"; }';";

View File

@@ -176,6 +176,10 @@ public final class SPUIComponentIdProvider {
* ID - Dist jvm combo. * ID - Dist jvm combo.
*/ */
public static final String DIST_MODULE_COMBO = "dist.module.combo."; public static final String DIST_MODULE_COMBO = "dist.module.combo.";
/**
* ID for Distribution Tag ComboBox
*/
public static final String DIST_TAG_COMBO = "dist.tag.combo";
/** /**
* ID-Dist.PIN. * ID-Dist.PIN.
*/ */
@@ -242,6 +246,11 @@ public final class SPUIComponentIdProvider {
*/ */
public static final String DISCARD_SW_MODULE_TYPE = "save.actions.popup.discard.sw.module.type"; public static final String DISCARD_SW_MODULE_TYPE = "save.actions.popup.discard.sw.module.type";
/**
* Action history table cancel Id.
*/
public static final String ACTION_DETAILS_SOFT_ID = "action.details.soft.group";
/** /**
* ID - Label. * ID - Label.
*/ */
@@ -289,6 +298,21 @@ public final class SPUIComponentIdProvider {
*/ */
public static final String ACTION_HISTORY_TABLE_ID = "action.history.tableId"; public static final String ACTION_HISTORY_TABLE_ID = "action.history.tableId";
/**
* Action history table cancel Id.
*/
public static final String ACTION_HISTORY_TABLE_CANCEL_ID = "action.history.table.action.cancel";
/**
* Action history table force Id.
*/
public static final String ACTION_HISTORY_TABLE_FORCE_ID = "action.history.table.action.force";
/**
* Action history table force quit Id.
*/
public static final String ACTION_HISTORY_TABLE_FORCE_QUIT_ID = "action.history.table.action.force.quit";
/** /**
* Target filter wrapper id. * Target filter wrapper id.
*/ */
@@ -302,6 +326,22 @@ public final class SPUIComponentIdProvider {
* tag color preview button id. * tag color preview button id.
*/ */
public static final String TAG_COLOR_PREVIEW_ID = "tag.color.preview"; public static final String TAG_COLOR_PREVIEW_ID = "tag.color.preview";
/**
* Id for ColorPickerLayout
*/
public static final String COLOR_PICKER_LAYOUT = "color.picker.layout";
/**
* Id for ColorPickerLayout's red slider
*/
public static final String COLOR_PICKER_RED_SLIDER = "color.picker.red.slider";
/**
* Id for Color preview field with the color code
*/
public static final String COLOR_PREVIEW_FIELD = "color-preview-field";
/**
* Id for OptionGroup Create/Update tag
*/
public static final String OPTION_GROUP = "create.update.tag";
/** /**
* Confirmation dialogue OK button id. * Confirmation dialogue OK button id.
*/ */
@@ -817,19 +857,26 @@ public final class SPUIComponentIdProvider {
* Rollout target filter query combo id. * Rollout target filter query combo id.
*/ */
public static final String ROLLOUT_TARGET_FILTER_COMBO_ID = "rollout.target.filter.combo.id"; public static final String ROLLOUT_TARGET_FILTER_COMBO_ID = "rollout.target.filter.combo.id";
/** /**
* Rollout action button id. * Rollout action button id.
*/ */
public static final String ROLLOUT_ACTION_BUTTON_ID = "rollout.action.button.id"; public static final String ROLLOUT_ACTION_ID = "rollout.action.button.id";
/**
* Rollout start button id.
*/
public static final String ROLLOUT_RUN_BUTTON_ID = ROLLOUT_ACTION_ID + ".9";
/** /**
* Rollout pause button id. * Rollout pause button id.
*/ */
public static final String ROLLOUT_PAUSE_BUTTON_ID = "rollout.pause.button.id"; public static final String ROLLOUT_PAUSE_BUTTON_ID = ROLLOUT_ACTION_ID + ".10";
/** /**
* Rollout resume button id. * Rollout resume button id.
*/ */
public static final String ROLLOUT_RESUME_BUTTON_ID = "rollout.resume.button.id"; public static final String ROLLOUT_UPDATE_BUTTON_ID = ROLLOUT_ACTION_ID + ".11";
/** /**
* Rollout save or start option group id. * Rollout save or start option group id.
@@ -915,6 +962,75 @@ public final class SPUIComponentIdProvider {
*/ */
public static final String UPLOAD_STATUS_POPUP_ID = "artifact.upload.status.popup.id"; public static final String UPLOAD_STATUS_POPUP_ID = "artifact.upload.status.popup.id";
/**
* Software module table - Manage metadata id.
*/
public static final String SW_TABLE_MANAGE_METADATA_ID = "swtable.manage.metadata.id";
/**
* Metadata key id.
*/
public static final String METADATA_KEY_FIELD_ID = "metadata.key.id";
/**
* Metadata value id.
*/
public static final String METADATA_VALUE_ID = "metadata.value.id";
/**
* Metadata save id.
*/
public static final String METADTA_SAVE_ICON_ID = "metadata.save.icon.id";
/**
* Metadata discard id.
*/
public static final String METADTA_DISCARD_ICON_ID = "metadata.discard.icon.id";
/**
* Metadata add icon id.
*/
public static final String METADTA_ADD_ICON_ID = "metadata.add.icon.id";
/**
* Metadata table id.
*/
public static final String METDATA_TABLE_ID = "metadata.table.id";
/**
* Distribution set table - Manage metadata id.
*/
public static final String DS_TABLE_MANAGE_METADATA_ID = "dstable.manage.metadata.id";
/**
* DistributionSet - Metadata button id.
*/
public static final String DS_METADATA_DETAIL_LINK = "distributionset.metadata.detail.link";
/**
* Metadata popup id.
*/
public static final String METADATA_POPUP_ID = "metadata.popup.id";
/**
* DistributionSet table details tab id in Distributions .
*/
public static final String DISTRIBUTIONSET_DETAILS_TABSHEET_ID = "distributionset.details.tabsheet";
/**
* Software module table details tab id in Distributions .
*/
public static final String DIST_SW_MODULE_DETAILS_TABSHEET_ID = "dist.sw.module.details.tabsheet";
/**
* Software Module - Metadata button id.
*/
public static final String SW_METADATA_DETAIL_LINK = "softwaremodule.metadata.detail.link";
/**
* Table multiselect for selecting DistType
*/
public static final String SELECT_DIST_TYPE = "select-dist-type";
/** /**
* /* Private Constructor. * /* Private Constructor.
*/ */

View File

@@ -87,6 +87,11 @@ public final class SPUIDefinitions {
*/ */
public static final String ACTION_HIS_TBL_STATUS = "Status"; public static final String ACTION_HIS_TBL_STATUS = "Status";
/**
* Actions column.
*/
public static final String ACTIONS_COLUMN = "Actions";
/** /**
* Action history messages of particular action update. * Action history messages of particular action update.
*/ */
@@ -344,15 +349,6 @@ public final class SPUIDefinitions {
* New Target tag color lable id. * New Target tag color lable id.
*/ */
public static final String NEW_TARGET_TAG_COLOR = "target.tag.add.color"; public static final String NEW_TARGET_TAG_COLOR = "target.tag.add.color";
/**
* New Target tag save icon id.
*/
// public static final String NEW_TARGET_TAG_SAVE = "target.tag.add.save";
/**
* New Target tag discard icon id.
*/
// public static final String NEW_TARGET_TAG_DISRACD =
// "target.tag.add.discard";
/** /**
* New Target tag add icon id. * New Target tag add icon id.
*/ */
@@ -1017,6 +1013,21 @@ public final class SPUIDefinitions {
*/ */
public static final String ROLLOUT_ACTION = "rollout-action"; public static final String ROLLOUT_ACTION = "rollout-action";
/**
* DistributionSet Metadata tab Id
*/
public static final String DISTRIBUTIONSET_METADATA_TAB_ID = "distSet.metadata.tab.id";
/**
* SoftwareModule Metadata tab Id
*/
public static final String SOFTWAREMODULE_METADATA_TAB_ID = "swModule.metadata.tab.id";
/***
* Custom window for metadata.
*/
public static final String CUSTOM_METADATA_WINDOW = "custom.metadata.window";
/** /**
* /** Constructor. * /** Constructor.
*/ */

View File

@@ -561,6 +561,11 @@ public final class SPUILabelDefinitions {
*/ */
public static final String ROLLOUT_GROUP_INSTALLED_PERCENTAGE = "finishedPercentage"; public static final String ROLLOUT_GROUP_INSTALLED_PERCENTAGE = "finishedPercentage";
/**
* Add metadata icon.
*/
public static final String METADATA_ICON = "metadataDls";
/** /**
* Constructor. * Constructor.
*/ */

View File

@@ -137,6 +137,11 @@ public final class SPUIStyleDefinitions {
*/ */
public static final String ARTIFACT_DTLS_ICON = "swm-artifact-dtls-icon"; public static final String ARTIFACT_DTLS_ICON = "swm-artifact-dtls-icon";
/**
* Distribution metadata icon style.
*/
public static final String DS_METADATA_ICON = "ds-metadata-icon";
/** /**
* Target table style. * Target table style.
*/ */
@@ -293,6 +298,10 @@ public final class SPUIStyleDefinitions {
* Status pending icon. * Status pending icon.
*/ */
public static final String STATUS_ICON_PENDING = "statusIconPending"; public static final String STATUS_ICON_PENDING = "statusIconPending";
/**
* Grid style.
*/
public static final String METADATA_GRID = "metadata-grid";
/** /**
* Footer layout style. * Footer layout style.

View File

@@ -293,8 +293,4 @@
padding-bottom: 12px !important; padding-bottom: 12px !important;
} }
.v-button-default-color {
color: #551f62;
}
} }

View File

@@ -53,4 +53,12 @@
font-size: 16px; font-size: 16px;
} }
.marginTop {
margin-top: 20px !important;
}
.metadata-table-margin {
margin-top:3px;
}
} }

View File

@@ -164,5 +164,6 @@
.actionButtonsMargin { .actionButtonsMargin {
margin-top: 30px; margin-top: 30px;
margin-bottom: 10px;
} }
} }

View File

@@ -52,6 +52,10 @@
opacity: 0.5; opacity: 0.5;
} }
.action-type-padding{
padding: 0 0px !important;
}
.rollout-caption-links{ .rollout-caption-links{
font-weight: 400; font-weight: 400;
height: 25px ; height: 25px ;

Some files were not shown because too many files have changed in this diff Show More