Merge branch 'master' into feature_rollouts_credentials

Conflicts:
	hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadStatusObject.java


Signed-off-by: SirWayne <dennis.melzer@bosch-si.com>
This commit is contained in:
SirWayne
2016-06-15 09:53:06 +02:00
125 changed files with 3091 additions and 3106 deletions

View File

@@ -8,6 +8,7 @@
*/
package org.eclipse.hawkbit.simulator.amqp;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
@@ -15,6 +16,7 @@ import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.QueueBuilder;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
@@ -65,9 +67,12 @@ public class AmqpConfiguration {
* @return the queue
*/
@Bean
public Queue receiverConnectorQueueFromSp() {
return new Queue(amqpProperties.getReceiverConnectorQueueFromSp(), true, false, false,
getDeadLetterExchangeArgs());
public Queue receiverConnectorQueueFromHawkBit() {
final Map<String, Object> arguments = getDeadLetterExchangeArgs();
arguments.putAll(getTTLMaxArgs());
return QueueBuilder.nonDurable(amqpProperties.getReceiverConnectorQueueFromSp()).withArguments(arguments)
.build();
}
/**
@@ -89,7 +94,7 @@ public class AmqpConfiguration {
*/
@Bean
public Binding bindReceiverQueueToSpExchange() {
return BindingBuilder.bind(receiverConnectorQueueFromSp()).to(exchangeQueueToConnector());
return BindingBuilder.bind(receiverConnectorQueueFromHawkBit()).to(exchangeQueueToConnector());
}
/**
@@ -99,7 +104,7 @@ public class AmqpConfiguration {
*/
@Bean
public Queue deadLetterQueue() {
return new Queue(amqpProperties.getDeadLetterQueue(), true, false, true);
return QueueBuilder.nonDurable(amqpProperties.getDeadLetterQueue()).withArguments(getTTLMaxArgs()).build();
}
/**
@@ -145,4 +150,11 @@ public class AmqpConfiguration {
return args;
}
private static Map<String, Object> getTTLMaxArgs() {
final Map<String, Object> args = new HashMap<>();
args.put("x-message-ttl", Duration.ofDays(1).toMillis());
args.put("x-max-length", 100_000);
return args;
}
}

View File

@@ -82,21 +82,4 @@ public class MessageService {
clazz.getTypeName());
return (T) rabbitTemplate.getMessageConverter().fromMessage(message);
}
/**
* Method to verify if lwm2m header is set.
*
* @param message
* the message with the header
* @param header
* the header to verify
*/
public void checkIfLwm2mHeaderEmpty(final Message message, final String header) {
final Object headerObject = message.getMessageProperties().getHeaders().get(header);
if (null == headerObject) {
logAndThrowMessageError(message, "Header of " + header + "empty.");
}
}
}

View File

@@ -19,7 +19,6 @@
<Logger name="org.apache.coyote.http11.Http11NioProtocol" level="WARN" />
<Logger name="org.apache.tomcat.util.net.NioSelectorPool" level="WARN" />
<Logger name="org.apache.tomcat.jdbc.pool.ConnectionPool" level="DEBUG" />
<Logger name="org.apache.catalina.startup.DigesterFactory" level="ERROR" />
<!-- Security Log with hints on potential attacks -->

View File

@@ -23,7 +23,6 @@ import org.springframework.scheduling.annotation.EnableAsync;
*
*
*/
@Configuration
@EnableAsync
@ConditionalOnMissingBean(AsyncConfigurer.class)

View File

@@ -20,7 +20,7 @@ public class AsyncConfigurerThreadpoolProperties {
/**
* Max queue size for central event executor.
*/
private Integer queuesize = 250;
private Integer queuesize = 5_000;
/**
* Core processing threads for central event executor.
@@ -30,7 +30,7 @@ public class AsyncConfigurerThreadpoolProperties {
/**
* Maximum thread pool size for central event executor.
*/
private Integer maxthreads = 50;
private Integer maxthreads = 20;
/**
* When the number of threads is greater than the core, this is the maximum

View File

@@ -11,6 +11,7 @@ package org.eclipse.hawkbit.autoconfigure.scheduling;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@@ -21,6 +22,9 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.security.concurrent.DelegatingSecurityContextExecutor;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
@@ -39,11 +43,21 @@ public class ExecutorAutoConfiguration {
private AsyncConfigurerThreadpoolProperties asyncConfigurerProperties;
/**
* @return ExecutorService for general purpose multi threaded operations
* @return ExecutorService with security context availability in thread
* execution..
*/
@Bean
@ConditionalOnMissingBean
public Executor asyncExecutor() {
return new DelegatingSecurityContextExecutor(threadPoolExecutor());
}
/**
* @return central ThreadPoolExecutor for general purpose multi threaded
* operations. Tries an orderly shutdown when destroyed.
*/
@Bean(destroyMethod = "shutdown")
public ThreadPoolExecutor threadPoolExecutor() {
final BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<>(
asyncConfigurerProperties.getQueuesize());
final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(asyncConfigurerProperties.getCorethreads(),
@@ -53,7 +67,8 @@ public class ExecutorAutoConfiguration {
threadPoolExecutor.setRejectedExecutionHandler((r, executor) -> LOGGER.warn(
"Reject runnable for centralExecutorService, reached limit of queue size {}",
executor.getQueue().size()));
return new DelegatingSecurityContextExecutor(threadPoolExecutor);
return threadPoolExecutor;
}
/**
@@ -69,4 +84,32 @@ public class ExecutorAutoConfiguration {
return new DelegatingSecurityContextExecutor(threadPoolExecutor);
}
/**
* @return {@link TaskExecutor} for task execution
*/
@Bean
@ConditionalOnMissingBean
public TaskExecutor taskExecutor() {
return new ConcurrentTaskExecutor(asyncExecutor());
}
/**
* @return {@link ScheduledExecutorService} based on
* {@link #threadPoolTaskScheduler()}.
*/
@Bean
@ConditionalOnMissingBean
public ScheduledExecutorService scheduledExecutorService() {
return threadPoolTaskScheduler().getScheduledExecutor();
}
/**
* @return {@link ThreadPoolTaskScheduler} for scheduled operations.
*/
@Bean
@ConditionalOnMissingBean
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
return new ThreadPoolTaskScheduler();
}
}

View File

@@ -30,12 +30,6 @@ vaadin.servlet.urlMapping=/UI/*
vaadin.servlet.heartbeatInterval=60
vaadin.servlet.closeIdleSessions=false
# Defines the thread pool executor
hawkbit.threadpool.corethreads=5
hawkbit.threadpool.maxthreads=20
hawkbit.threadpool.idletimeout=10000
hawkbit.threadpool.queuesize=20000
# Defines the polling time for the controllers in HH:MM:SS notation
hawkbit.controller.pollingTime=00:05:00
hawkbit.controller.pollingOverdueTime=00:05:00

View File

@@ -134,7 +134,7 @@ public class DdiArtifactStoreController implements DdiDlArtifactStoreControllerR
private Action checkAndReportDownloadByTarget(final HttpServletRequest request, final String targetid,
final LocalArtifact artifact) {
final Target target = controllerManagement.updateLastTargetQuery(targetid,
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
IpUtil.getClientIpFromRequest(request, securityProperties));
final Action action = controllerManagement
.getActionForDownloadByTargetAndSoftwareModule(target.getControllerId(), artifact.getSoftwareModule());

View File

@@ -119,16 +119,14 @@ public class DdiRootController implements DdiRootControllerRestApi {
public ResponseEntity<DdiControllerBase> getControllerBase(@PathVariable("targetid") final String targetid) {
LOG.debug("getControllerBase({})", targetid);
final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotexist(targetid,
IpUtil.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(),
securityProperties.getClients().getRemoteIpHeader()));
final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotexist(targetid, IpUtil
.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(), securityProperties));
if (target.getTargetInfo().getUpdateStatus() == TargetUpdateStatus.UNKNOWN) {
LOG.debug("target with {} extsisted but was in status UNKNOWN -> REGISTERED)", targetid);
controllerManagement.updateTargetStatus(target.getTargetInfo(), TargetUpdateStatus.REGISTERED,
System.currentTimeMillis(),
IpUtil.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(),
securityProperties.getClients().getRemoteIpHeader()));
System.currentTimeMillis(), IpUtil.getClientIpFromRequest(
requestResponseContextHolder.getHttpServletRequest(), securityProperties));
}
return new ResponseEntity<>(
@@ -143,9 +141,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
@PathVariable("fileName") final String fileName) {
ResponseEntity<InputStream> result;
final Target target = controllerManagement.updateLastTargetQuery(targetid,
IpUtil.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(),
securityProperties.getClients().getRemoteIpHeader()));
final Target target = controllerManagement.updateLastTargetQuery(targetid, IpUtil
.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(), securityProperties));
final SoftwareModule module = softwareManagement.findSoftwareModuleById(softwareModuleId);
if (checkModule(fileName, module)) {
@@ -200,9 +197,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
public ResponseEntity<Void> downloadArtifactMd5(@PathVariable("targetid") final String targetid,
@PathVariable("softwareModuleId") final Long softwareModuleId,
@PathVariable("fileName") final String fileName) {
controllerManagement.updateLastTargetQuery(targetid,
IpUtil.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(),
securityProperties.getClients().getRemoteIpHeader()));
controllerManagement.updateLastTargetQuery(targetid, IpUtil
.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(), securityProperties));
final SoftwareModule module = softwareManagement.findSoftwareModuleById(softwareModuleId);
@@ -228,9 +224,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
@RequestParam(value = "c", required = false, defaultValue = "-1") final int resource) {
LOG.debug("getControllerBasedeploymentAction({},{})", targetid, resource);
final Target target = controllerManagement.updateLastTargetQuery(targetid,
IpUtil.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(),
securityProperties.getClients().getRemoteIpHeader()));
final Target target = controllerManagement.updateLastTargetQuery(targetid, IpUtil
.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(), securityProperties));
final Action action = findActionWithExceptionIfNotFound(actionId);
if (!action.getTarget().getId().equals(target.getId())) {
@@ -263,9 +258,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
@PathVariable("targetid") final String targetid, @PathVariable("actionId") @NotEmpty final Long actionId) {
LOG.debug("provideBasedeploymentActionFeedback for target [{},{}]: {}", targetid, actionId, feedback);
final Target target = controllerManagement.updateLastTargetQuery(targetid,
IpUtil.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(),
securityProperties.getClients().getRemoteIpHeader()));
final Target target = controllerManagement.updateLastTargetQuery(targetid, IpUtil
.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(), securityProperties));
if (!actionId.equals(feedback.getId())) {
LOG.warn(
@@ -357,9 +351,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
@Override
public ResponseEntity<Void> putConfigData(@Valid @RequestBody final DdiConfigData configData,
@PathVariable("targetid") final String targetid) {
controllerManagement.updateLastTargetQuery(targetid,
IpUtil.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(),
securityProperties.getClients().getRemoteIpHeader()));
controllerManagement.updateLastTargetQuery(targetid, IpUtil
.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(), securityProperties));
controllerManagement.updateControllerAttributes(targetid, configData.getData());
@@ -372,9 +365,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
@PathVariable("actionId") @NotEmpty final Long actionId) {
LOG.debug("getControllerCancelAction({})", targetid);
final Target target = controllerManagement.updateLastTargetQuery(targetid,
IpUtil.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(),
securityProperties.getClients().getRemoteIpHeader()));
final Target target = controllerManagement.updateLastTargetQuery(targetid, IpUtil
.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(), securityProperties));
final Action action = findActionWithExceptionIfNotFound(actionId);
if (!action.getTarget().getId().equals(target.getId())) {
@@ -403,9 +395,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
@PathVariable("actionId") @NotEmpty final Long actionId) {
LOG.debug("provideCancelActionFeedback for target [{}]: {}", targetid, feedback);
final Target target = controllerManagement.updateLastTargetQuery(targetid,
IpUtil.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(),
securityProperties.getClients().getRemoteIpHeader()));
final Target target = controllerManagement.updateLastTargetQuery(targetid, IpUtil
.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(), securityProperties));
if (!actionId.equals(feedback.getId())) {
LOG.warn(

View File

@@ -29,11 +29,11 @@ import org.apache.commons.lang3.RandomUtils;
import org.eclipse.hawkbit.eventbus.event.DownloadProgressEvent;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.util.WithUser;
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTestWithMongoDB;
import org.junit.Test;
import org.slf4j.LoggerFactory;

View File

@@ -28,14 +28,16 @@ import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.repository.util.WithSpringAuthorityRule;
import org.eclipse.hawkbit.repository.util.WithUser;
import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule;
import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTestWithMongoDB;
import org.eclipse.hawkbit.rest.util.JsonBuilder;
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
import org.eclipse.hawkbit.util.IpUtil;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.MediaTypes;
import org.springframework.http.MediaType;
@@ -50,6 +52,9 @@ import ru.yandex.qatools.allure.annotations.Stories;
@Stories("Root Poll Resource")
public class DdiRootControllerTest extends AbstractRestIntegrationTestWithMongoDB {
@Autowired
private HawkbitSecurityProperties securityProperties;
@Test
@Description("Ensures that targets cannot be created e.g. in plug'n play scenarios when tenant does not exists but can be created if the tenant exists.")
@WithUser(tenantId = "tenantDoesNotExists", allSpPermissions = true, authorities = "ROLE_CONTROLLER", autoCreateTenant = false)
@@ -257,6 +262,23 @@ public class DdiRootControllerTest extends AbstractRestIntegrationTestWithMongoD
}
@Test
@Description("Ensures that the source IP address of the polling target is not stored in repository if disabled")
public void rootRsIpAddressNotStoredIfDisabled() throws Exception {
securityProperties.getClients().setTrackRemoteIp(false);
// test
final String knownControllerId1 = "0815";
mvc.perform(get("/{tenant}/controller/v1/{controllerId}", tenantAware.getCurrentTenant(), knownControllerId1))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
// verify
final Target target = targetManagement.findTargetByControllerID(knownControllerId1);
assertThat(target.getTargetInfo().getAddress()).isEqualTo(IpUtil.createHttpUri("***"));
securityProperties.getClients().setTrackRemoteIp(true);
}
@Test
@Description("Controller trys to finish an update process after it has been finished by an error action status.")
public void tryToFinishAnUpdateProcessAfterItHasBeenFinished() throws Exception {

View File

@@ -8,21 +8,32 @@
*/
package org.eclipse.hawkbit.amqp;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import org.eclipse.hawkbit.dmf.amqp.api.AmqpSettings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.amqp.RabbitProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.retry.backoff.ExponentialBackOffPolicy;
import org.springframework.retry.support.RetryTemplate;;
/**
* The spring AMQP configuration which is enabled by using the profile
@@ -32,14 +43,69 @@ import org.springframework.context.annotation.Bean;
@EnableConfigurationProperties({ AmqpProperties.class, AmqpDeadletterProperties.class })
public class AmqpConfiguration {
@Autowired
protected AmqpProperties amqpProperties;
private static final Logger LOGGER = LoggerFactory.getLogger(AmqpConfiguration.class);
@Autowired
protected AmqpDeadletterProperties amqpDeadletterProperties;
private AmqpProperties amqpProperties;
@Autowired
private ConnectionFactory connectionFactory;
private AmqpDeadletterProperties amqpDeadletterProperties;
@Autowired
@Qualifier("threadPoolExecutor")
private ThreadPoolExecutor threadPoolExecutor;
@Autowired
private ConnectionFactory rabbitConnectionFactory;
@Configuration
@ConditionalOnMissingBean(ConnectionFactory.class)
protected static class RabbitConnectionFactoryCreator {
@Autowired
private AmqpProperties amqpProperties;
@Autowired
@Qualifier("threadPoolExecutor")
private ThreadPoolExecutor threadPoolExecutor;
@Autowired
private ScheduledExecutorService scheduledExecutorService;
/**
* {@link ConnectionFactory} with enabled publisher confirms and
* heartbeat.
*
* @param config
* with standard {@link RabbitProperties}
* @return {@link ConnectionFactory}
*/
@Bean
public ConnectionFactory rabbitConnectionFactory(final RabbitProperties config) {
final CachingConnectionFactory factory = new CachingConnectionFactory();
factory.setRequestedHeartBeat(amqpProperties.getRequestedHeartBeat());
factory.setExecutor(threadPoolExecutor);
factory.getRabbitConnectionFactory().setHeartbeatExecutor(scheduledExecutorService);
factory.setPublisherConfirms(true);
final String addresses = config.getAddresses();
factory.setAddresses(addresses);
if (config.getHost() != null) {
factory.setHost(config.getHost());
factory.setPort(config.getPort());
}
if (config.getUsername() != null) {
factory.setUsername(config.getUsername());
}
if (config.getPassword() != null) {
factory.setPassword(config.getPassword());
}
if (config.getVirtualHost() != null) {
factory.setVirtualHost(config.getVirtualHost());
}
return factory;
}
}
/**
* Create a {@link RabbitAdmin} and ignore declaration exceptions.
@@ -49,20 +115,34 @@ public class AmqpConfiguration {
*/
@Bean
public RabbitAdmin rabbitAdmin() {
final RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
final RabbitAdmin rabbitAdmin = new RabbitAdmin(rabbitConnectionFactory);
rabbitAdmin.setIgnoreDeclarationExceptions(true);
return rabbitAdmin;
}
/**
* Method to set the Jackson2JsonMessageConverter.
*
* @return the Jackson2JsonMessageConverter
* @return {@link RabbitTemplate} with automatic retry, published confirms
* and {@link Jackson2JsonMessageConverter}.
*/
@Bean
public RabbitTemplate rabbitTemplate() {
final RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
final RabbitTemplate rabbitTemplate = new RabbitTemplate(rabbitConnectionFactory);
rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
final RetryTemplate retryTemplate = new RetryTemplate();
retryTemplate.setBackOffPolicy(new ExponentialBackOffPolicy());
rabbitTemplate.setRetryTemplate(retryTemplate);
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
if (ack) {
LOGGER.debug("Message with correlation ID {} confirmed by broker.", correlationData.getId());
} else {
LOGGER.error("Broker is unable to handle message with correlation ID {} : {}", correlationData.getId(),
cause);
}
});
return rabbitTemplate;
}
@@ -159,7 +239,7 @@ public class AmqpConfiguration {
public SimpleRabbitListenerContainerFactory listenerContainerFactory() {
final SimpleRabbitListenerContainerFactory containerFactory = new SimpleRabbitListenerContainerFactory();
containerFactory.setDefaultRequeueRejected(false);
containerFactory.setConnectionFactory(connectionFactory);
containerFactory.setConnectionFactory(rabbitConnectionFactory);
containerFactory.setMissingQueuesFatal(amqpProperties.isMissingQueuesFatal());
return containerFactory;
}

View File

@@ -8,6 +8,8 @@
*/
package org.eclipse.hawkbit.amqp;
import java.util.concurrent.TimeUnit;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -38,6 +40,11 @@ public class AmqpProperties {
*/
private boolean missingQueuesFatal = false;
/**
* Requested heartbeat interval from broker in {@link TimeUnit#SECONDS}.
*/
private int requestedHeartBeat = (int) TimeUnit.SECONDS.toSeconds(60);
/**
* Is missingQueuesFatal enabled
*
@@ -102,4 +109,13 @@ public class AmqpProperties {
public void setReceiverQueue(final String receiverQueue) {
this.receiverQueue = receiverQueue;
}
public int getRequestedHeartBeat() {
return requestedHeartBeat;
}
public void setRequestedHeartBeat(final int requestedHeartBeat) {
this.requestedHeartBeat = requestedHeartBeat;
}
}

View File

@@ -109,7 +109,7 @@ public class BaseAmqpService {
}
protected final void logAndThrowMessageError(final Message message, final String error) {
LOGGER.warn("Error \"{}\" reported by message: {}", error, message);
LOGGER.warn("Warning! \"{}\" reported by message: {}", error, message);
throw new IllegalArgumentException(error);
}

View File

@@ -9,10 +9,14 @@
package org.eclipse.hawkbit.amqp;
import java.net.URI;
import java.util.UUID;
import org.eclipse.hawkbit.util.IpUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
/**
* A default implementation for the sender service. The service sends all amqp
@@ -20,6 +24,7 @@ import org.springframework.amqp.rabbit.core.RabbitTemplate;
* extracted from the uri.
*/
public class DefaultAmqpSenderService implements AmqpSenderService {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultAmqpSenderService.class);
private final RabbitTemplate internalAmqpTemplate;
@@ -39,7 +44,16 @@ public class DefaultAmqpSenderService implements AmqpSenderService {
return;
}
internalAmqpTemplate.send(extractExchange(replyTo), null, message);
final String correlationId = UUID.randomUUID().toString();
final String exchange = extractExchange(replyTo);
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Sending message {} to exchange {} with correlationId {}", message, exchange, correlationId);
} else {
LOGGER.debug("Sending message to exchange {} with correlationId {}", exchange, correlationId);
}
internalAmqpTemplate.send(exchange, null, message, new CorrelationData(correlationId));
}
}

View File

@@ -8,6 +8,14 @@
*/
package org.eclipse.hawkbit;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.eclipse.hawkbit.amqp.AmqpProperties;
import org.eclipse.hawkbit.amqp.AmqpSenderService;
import org.eclipse.hawkbit.amqp.DefaultAmqpSenderService;
import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder;
@@ -16,13 +24,22 @@ import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.security.concurrent.DelegatingSecurityContextExecutor;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
/**
*
*/
@Configuration
@EnableConfigurationProperties({ AmqpProperties.class })
public class AmqpTestConfiguration {
/**
* @return the {@link SystemSecurityContext} singleton bean which make it
@@ -56,4 +73,55 @@ public class AmqpTestConfiguration {
public AmqpSenderService amqpSenderServiceBean(final RabbitTemplate rabbitTemplate) {
return new DefaultAmqpSenderService(rabbitTemplate);
}
/**
* @return ExecutorService with security context availability in thread
* execution..
*/
@Bean
@ConditionalOnMissingBean
public Executor asyncExecutor() {
return new DelegatingSecurityContextExecutor(threadPoolExecutor());
}
/**
* @return central ThreadPoolExecutor for general purpose multi threaded
* operations. Tries an orderly shutdown when destroyed.
*/
@Bean(destroyMethod = "shutdown")
public ThreadPoolExecutor threadPoolExecutor() {
final BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<>(10);
final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 10, 1000, TimeUnit.MILLISECONDS,
blockingQueue, new ThreadFactoryBuilder().setNameFormat("central-executor-pool-%d").build());
return threadPoolExecutor;
}
/**
* @return {@link TaskExecutor} for task execution
*/
@Bean
@ConditionalOnMissingBean
public TaskExecutor taskExecutor() {
return new ConcurrentTaskExecutor(asyncExecutor());
}
/**
* @return {@link ScheduledExecutorService} based on
* {@link #threadPoolTaskScheduler()}.
*/
@Bean
@ConditionalOnMissingBean
public ScheduledExecutorService scheduledExecutorService() {
return threadPoolTaskScheduler().getScheduledExecutor();
}
/**
* @return {@link ThreadPoolTaskScheduler} for scheduled operations.
*/
@Bean
@ConditionalOnMissingBean
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
return new ThreadPoolTaskScheduler();
}
}

View File

@@ -37,7 +37,7 @@ import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.util.AbstractIntegrationTestWithMongoDB;
import org.eclipse.hawkbit.repository.test.util.AbstractIntegrationTestWithMongoDB;
import org.eclipse.hawkbit.util.IpUtil;
import org.junit.Test;
import org.mockito.ArgumentCaptor;

View File

@@ -16,7 +16,7 @@ import org.eclipse.hawkbit.api.UrlProtocol;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.util.AbstractIntegrationTestWithMongoDB;
import org.eclipse.hawkbit.repository.test.util.AbstractIntegrationTestWithMongoDB;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
@@ -33,6 +33,7 @@ import ru.yandex.qatools.allure.annotations.Stories;
@Stories("Test to generate the artifact download URL")
@SpringApplicationConfiguration(classes = { AmqpTestConfiguration.class,
org.eclipse.hawkbit.RepositoryApplicationConfiguration.class })
public class PropertyBasedArtifactUrlHandlerTest extends AbstractIntegrationTestWithMongoDB {
private static final String HTTPS_LOCALHOST = "https://localhost:8080/";

View File

@@ -29,12 +29,12 @@ import java.util.Set;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
import org.eclipse.hawkbit.repository.test.util.WithUser;
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.Target;
import org.eclipse.hawkbit.repository.util.TestdataFactory;
import org.eclipse.hawkbit.repository.util.WithUser;
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTest;
import org.eclipse.hawkbit.rest.util.JsonBuilder;
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;

View File

@@ -27,7 +27,7 @@ import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.util.WithUser;
import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTest;
import org.eclipse.hawkbit.rest.util.JsonBuilder;
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;

View File

@@ -29,7 +29,7 @@ import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus;
import org.eclipse.hawkbit.repository.model.RolloutGroup;
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessCondition;
import org.eclipse.hawkbit.repository.util.WithUser;
import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTest;

View File

@@ -41,8 +41,8 @@ import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
import org.eclipse.hawkbit.repository.util.HashGeneratorUtils;
import org.eclipse.hawkbit.repository.util.WithUser;
import org.eclipse.hawkbit.repository.test.util.HashGeneratorUtils;
import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTestWithMongoDB;
import org.eclipse.hawkbit.rest.json.model.ExceptionInfo;
import org.eclipse.hawkbit.rest.util.JsonBuilder;

View File

@@ -26,7 +26,7 @@ import java.util.List;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.util.WithUser;
import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTest;
import org.eclipse.hawkbit.rest.util.JsonBuilder;
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;

View File

@@ -40,7 +40,7 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.util.WithUser;
import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.eclipse.hawkbit.repository.model.ActionStatus;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.SoftwareModule;

View File

@@ -0,0 +1,47 @@
# hawkBit metadata repository
The repository is in charge for managing the meta data of the update server, e.g. provisioning targets, distribution sets, software modules etc.
# Build
[indent=0]
----
$ mvn clean install
----
Note, in order to build correctly in your IDE, you have to add ./target/generated-sources/apt to your build path.
#Concepts
## Rollout
A rollout consists of the distribution set and a target-query-filter which defines the targets to be updated in this rollout. The targets within this filter are split up in configured amount of _Deployment Groups_ at creation time.
When starting a rollout, for all targets within this rollout deployment actions will be created. The deployment actions of the first group will be started immediately all other deployment actions will be scheduled.
> Due rollouts might include a large number of targets and deployment group, creation as well as starting a rollout might take some time and therefore the creation and starting of an rollout is executed asynchronously. The creation and starting progress is reflected by the rollout's status attribute
### Rollout Creation
The targets reflected by the target-query-filter is interpreted at creation time. Only targets which have been created at that time are included in the rollout. Targets which are created after the rollout creation will not be included. At rollout creation time all necessary deployment groups containing the targets will be created. Dynamically adding targets to a created or running rollout is currently not supported.
### Rollout Starting
The rollout is using the same concept based on _deployment acionts_ per target. All necessary _deployment acionts_ will be created at starting point but not all _deployment acionts_ will be set to running. Only the _deployment acionts_ of the first _deployment group_ is set to running, all other actions are created in _scheduled_ state.
If targets having not finished _deployment actions_ at rollout starting time, these action are tried to cancel (state: canceling). Scheduled actions from another rollout are canceled directly on server side because they were never running before and can be safely canceled.
>Multiple rollouts can be running at the same time, but if the rollouts effect the same targets they will interfer the targets _deployment actions_ e.g. canceling/cancel already running/scheduled _deployment actions_.
### Deployment Group Condition/Action
#### Success Condition/Action
A _success condition_ defines when a deployment group is interpreted as success and triggers the _success action_. E.g. a threshold of successfully updated targets within the group.
The _success action_ is executed if the _success_condition_ is fullfilled. Currently only the _success action_ starting the next following deployment group is available.
#### Error Condition/Action
A _error condition_ defines when a deployment group is interpreted as failure and triggers the _error action_. E.g. a threshold of update failures of targets within the group.
The _error action_ is executed if the _error condition_ is fullfilled. Currently only the _error action_ pausing the whole rollout is available, a paused rollout can be resumed by a user.
### Rollout Scheduler
The rollout is managed by a scheduler task which is checking for rollouts in _running_ state. This is done atomic by updating the row in the database, so only the rollouts are checked and processed for the current instance to avoid that multiple instances are processing a rollout.
>Due the scheduler, it might take some time until a rollouts is processed and switching is state or starting the next deployment group.

View File

@@ -0,0 +1,6 @@
# hawkBit repository API
API for repository access. Contains:
- Entity Model
- Management service API

View File

@@ -33,7 +33,7 @@ public final class Constants {
* generated by repository for every new account for "Firmware/Operating
* System" .
*/
public static final String SMT_DEFAULT_OS_NAME = "Firmware";
public static final String SMT_DEFAULT_OS_NAME = "OS";
/**
* {@link SoftwareModuleType#getName()} of a {@link SoftwareModuleType}
* generated by repository for every new account for "applications/apps".

View File

@@ -0,0 +1,3 @@
# hawkBit common implementation
Core elements that can be used by implementations.

View File

@@ -1,47 +1,3 @@
# hawkBit metadata repository
The repository is in charge for managing the meta data of the update server, e.g. provisioning targets, distribution sets, software modules etc.
# Build
[indent=0]
----
$ mvn clean install
----
Note, in order to build correctly in your IDE, you have to add ./target/generated-sources/apt to your build path.
#Concepts
## Rollout
A rollout consists of the distribution set and a target-query-filter which defines the targets to be updated in this rollout. The targets within this filter are split up in configured amount of _Deployment Groups_ at creation time.
When starting a rollout, for all targets within this rollout deployment actions will be created. The deployment actions of the first group will be started immediately all other deployment actions will be scheduled.
> Due rollouts might include a large number of targets and deployment group, creation as well as starting a rollout might take some time and therefore the creation and starting of an rollout is executed asynchronously. The creation and starting progress is reflected by the rollout's status attribute
### Rollout Creation
The targets reflected by the target-query-filter is interpreted at creation time. Only targets which have been created at that time are included in the rollout. Targets which are created after the rollout creation will not be included. At rollout creation time all necessary deployment groups containing the targets will be created. Dynamically adding targets to a created or running rollout is currently not supported.
### Rollout Starting
The rollout is using the same concept based on _deployment acionts_ per target. All necessary _deployment acionts_ will be created at starting point but not all _deployment acionts_ will be set to running. Only the _deployment acionts_ of the first _deployment group_ is set to running, all other actions are created in _scheduled_ state.
If targets having not finished _deployment actions_ at rollout starting time, these action are tried to cancel (state: canceling). Scheduled actions from another rollout are canceled directly on server side because they were never running before and can be safely canceled.
>Multiple rollouts can be running at the same time, but if the rollouts effect the same targets they will interfer the targets _deployment actions_ e.g. canceling/cancel already running/scheduled _deployment actions_.
### Deployment Group Condition/Action
#### Success Condition/Action
A _success condition_ defines when a deployment group is interpreted as success and triggers the _success action_. E.g. a threshold of successfully updated targets within the group.
The _success action_ is executed if the _success_condition_ is fullfilled. Currently only the _success action_ starting the next following deployment group is available.
#### Error Condition/Action
A _error condition_ defines when a deployment group is interpreted as failure and triggers the _error action_. E.g. a threshold of update failures of targets within the group.
The _error action_ is executed if the _error condition_ is fullfilled. Currently only the _error action_ pausing the whole rollout is available, a paused rollout can be resumed by a user.
### Rollout Scheduler
The rollout is managed by a scheduler task which is checking for rollouts in _running_ state. This is done atomic by updating the row in the database, so only the rollouts are checked and processed for the current instance to avoid that multiple instances are processing a rollout.
>Due the scheduler, it might take some time until a rollouts is processed and switching is state or starting the next deployment group.
# hawkBit JPA implementation
JPA implementation of the repository. Based on [EclipseLink](http://www.eclipse.org/eclipselink/) and [Spring Data Jpa](http://projects.spring.io/spring-data-jpa/).

View File

@@ -16,7 +16,9 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Tag;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
@@ -82,15 +84,26 @@ public interface DistributionSetRepository
List<DistributionSet> findByModules(JpaSoftwareModule module);
/**
* Finds {@link DistributionSet}s based on given ID if they are not assigned
* yet to an {@link UpdateAction}, i.e. unused.
* Finds {@link DistributionSet}s based on given ID that are assigned yet to
* an {@link Action}, i.e. in use.
*
* @param ids
* to search for
* @return
* @return list of {@link DistributionSet#getId()}
*/
@Query("select ac.distributionSet.id from JpaAction ac where ac.distributionSet.id in :ids")
List<Long> findAssignedDistributionSetsById(@Param("ids") Long... ids);
List<Long> findAssignedToTargetDistributionSetsById(@Param("ids") Long... ids);
/**
* Finds {@link DistributionSet}s based on given ID that are assigned yet to
* an {@link Rollout}, i.e. in use.
*
* @param ids
* to search for
* @return list of {@link DistributionSet#getId()}
*/
@Query("select ra.distributionSet.id from JpaRollout ra where ra.distributionSet.id in :ids")
List<Long> findAssignedToRolloutDistributionSetsById(@Param("ids") Long... ids);
/**
* Saves all given {@link DistributionSet}s.

View File

@@ -171,7 +171,9 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
public void deleteDistributionSet(final Long... distributionSetIDs) {
final List<Long> toHardDelete = new ArrayList<>();
final List<Long> assigned = distributionSetRepository.findAssignedDistributionSetsById(distributionSetIDs);
final List<Long> assigned = distributionSetRepository
.findAssignedToTargetDistributionSetsById(distributionSetIDs);
assigned.addAll(distributionSetRepository.findAssignedToRolloutDistributionSetsById(distributionSetIDs));
// soft delete assigned
if (!assigned.isEmpty()) {

View File

@@ -12,7 +12,7 @@ import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.eclipse.hawkbit.cache.TenantAwareCacheManager;
import org.eclipse.hawkbit.repository.util.AbstractIntegrationTest;
import org.eclipse.hawkbit.repository.test.util.AbstractIntegrationTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.data.mongodb.gridfs.GridFsOperations;

View File

@@ -12,7 +12,7 @@ import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.eclipse.hawkbit.cache.TenantAwareCacheManager;
import org.eclipse.hawkbit.repository.util.AbstractIntegrationTestWithMongoDB;
import org.eclipse.hawkbit.repository.test.util.AbstractIntegrationTestWithMongoDB;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;

View File

@@ -32,8 +32,8 @@ import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.ExternalArtifactProvider;
import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.util.HashGeneratorUtils;
import org.eclipse.hawkbit.repository.util.WithUser;
import org.eclipse.hawkbit.repository.test.util.HashGeneratorUtils;
import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.junit.Test;
import org.slf4j.LoggerFactory;
import org.springframework.data.mongodb.core.query.Criteria;

View File

@@ -27,6 +27,7 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType;
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.model.Action;
@@ -37,9 +38,15 @@ import org.eclipse.hawkbit.repository.model.DistributionSetFilter.DistributionSe
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupErrorAction;
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupErrorCondition;
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessCondition;
import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder;
import org.eclipse.hawkbit.repository.model.RolloutGroupConditions;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.util.WithUser;
import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.fest.assertions.core.Condition;
import org.junit.Test;
import org.springframework.data.domain.Page;
@@ -777,36 +784,55 @@ public class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
}
@Test
@Description("Deltes a DS that is no in use. Expected behaviour is a soft delete on the database, i.e. only marked as "
+ "deleted, kept eas refernce and unavailable for future use..")
@Description("Deletes a DS that is in use by either target assignment or rollout. Expected behaviour is a soft delete on the database, i.e. only marked as "
+ "deleted, kept as reference but unavailable for future use..")
public void deleteAssignedDistributionSet() {
DistributionSet ds1 = testdataFactory.createDistributionSet("ds-1");
DistributionSet ds2 = testdataFactory.createDistributionSet("ds-2");
DistributionSet dsAssigned = testdataFactory.createDistributionSet("ds-3");
DistributionSet dsToTargetAssigned = testdataFactory.createDistributionSet("ds-3");
final DistributionSet dsToRolloutAssigned = testdataFactory.createDistributionSet("ds-4");
ds1 = distributionSetManagement.findDistributionSetByNameAndVersion(ds1.getName(), ds1.getVersion());
ds2 = distributionSetManagement.findDistributionSetByNameAndVersion(ds2.getName(), ds2.getVersion());
// create assigned DS
dsAssigned = distributionSetManagement.findDistributionSetByNameAndVersion(dsAssigned.getName(),
dsAssigned.getVersion());
dsToTargetAssigned = distributionSetManagement.findDistributionSetByNameAndVersion(dsToTargetAssigned.getName(),
dsToTargetAssigned.getVersion());
final Target target = new JpaTarget("4712");
final Target savedTarget = targetManagement.createTarget(target);
final List<Target> toAssign = new ArrayList<>();
toAssign.add(savedTarget);
deploymentManagement.assignDistributionSet(dsAssigned, toAssign);
deploymentManagement.assignDistributionSet(dsToTargetAssigned, toAssign);
// delete a ds
assertThat(distributionSetRepository.findAll()).hasSize(3);
distributionSetManagement.deleteDistributionSet(dsAssigned.getId());
// create assigned rollout
createRolloutByVariables("test", "test", 5, "name==*", dsToRolloutAssigned, "50", "5");
// delete assigned ds
assertThat(distributionSetRepository.findAll()).hasSize(4);
distributionSetManagement.deleteDistributionSet(dsToTargetAssigned.getId(), dsToRolloutAssigned.getId());
// not assigned so not marked as deleted
assertThat(distributionSetRepository.findAll()).hasSize(3);
assertThat(distributionSetRepository.findAll()).hasSize(4);
assertThat(distributionSetManagement
.findDistributionSetsByDeletedAndOrCompleted(pageReq, Boolean.FALSE, Boolean.TRUE).getTotalElements())
.isEqualTo(2);
}
private Rollout createRolloutByVariables(final String rolloutName, final String rolloutDescription,
final int groupSize, final String filterQuery, final DistributionSet distributionSet,
final String successCondition, final String errorCondition) {
final RolloutGroupConditions conditions = new RolloutGroupConditionBuilder()
.successCondition(RolloutGroupSuccessCondition.THRESHOLD, successCondition)
.errorCondition(RolloutGroupErrorCondition.THRESHOLD, errorCondition)
.errorAction(RolloutGroupErrorAction.PAUSE, null).build();
final Rollout rolloutToCreate = new JpaRollout();
rolloutToCreate.setName(rolloutName);
rolloutToCreate.setDescription(rolloutDescription);
rolloutToCreate.setTargetFilterQuery(filterQuery);
rolloutToCreate.setDistributionSet(distributionSet);
return rolloutManagement.createRollout(rolloutToCreate, groupSize, conditions);
}
private Target sendUpdateActionStatusToTarget(final Status status, final Action updActA, final Target t,
final String... msgs) {
updActA.setStatus(status);

View File

@@ -37,9 +37,9 @@ import org.eclipse.hawkbit.repository.report.model.DataReportSeries;
import org.eclipse.hawkbit.repository.report.model.DataReportSeriesItem;
import org.eclipse.hawkbit.repository.report.model.InnerOuterDataReportSeries;
import org.eclipse.hawkbit.repository.report.model.SeriesTime;
import org.eclipse.hawkbit.repository.util.TestdataFactory;
import org.eclipse.hawkbit.repository.util.WithSpringAuthorityRule;
import org.eclipse.hawkbit.repository.util.WithUser;
import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule;
import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.junit.After;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

View File

@@ -34,13 +34,13 @@ import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupErrorAction
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupErrorCondition;
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupStatus;
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessCondition;
import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder;
import org.eclipse.hawkbit.repository.model.RolloutGroupConditions;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
import org.eclipse.hawkbit.repository.util.TestdataFactory;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Description;

View File

@@ -39,7 +39,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.repository.util.WithUser;
import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.junit.Test;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;

View File

@@ -18,7 +18,7 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.report.model.TenantUsage;
import org.eclipse.hawkbit.repository.util.WithSpringAuthorityRule;
import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule;
import org.junit.Test;
import ru.yandex.qatools.allure.annotations.Description;

View File

@@ -38,13 +38,13 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule;
import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Tag;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetIdName;
import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.util.WithSpringAuthorityRule;
import org.eclipse.hawkbit.repository.util.WithUser;
import org.junit.Test;
import org.springframework.data.domain.PageRequest;

View File

@@ -20,7 +20,7 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.util.TestdataFactory;
import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
import org.junit.Before;
import org.junit.Test;
import org.springframework.data.domain.Page;

View File

@@ -16,7 +16,7 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleMetadata;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
import org.eclipse.hawkbit.repository.util.TestdataFactory;
import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
import org.junit.Before;
import org.junit.Test;
import org.springframework.data.domain.Page;

View File

@@ -18,7 +18,7 @@ import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleMetadata;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
import org.eclipse.hawkbit.repository.util.TestdataFactory;
import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
import org.junit.Before;
import org.junit.Test;
import org.springframework.data.domain.Page;

View File

@@ -10,6 +10,7 @@ package org.eclipse.hawkbit.repository.jpa.rsql;
import static org.fest.assertions.api.Assertions.assertThat;
import org.eclipse.hawkbit.repository.Constants;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeFields;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
@@ -34,7 +35,7 @@ public class RSQLSoftwareModuleTypeFieldsTest extends AbstractJpaIntegrationTest
@Test
@Description("Test filter software module test type by name")
public void testFilterByParameterName() {
assertRSQLQuery(SoftwareModuleTypeFields.NAME.name() + "==Firmware", 1);
assertRSQLQuery(SoftwareModuleTypeFields.NAME.name() + "==" + Constants.SMT_DEFAULT_OS_NAME, 1);
}
@Test

View File

@@ -24,7 +24,7 @@ import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetInfo;
import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.repository.util.TestdataFactory;
import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
import org.junit.Before;
import org.junit.Test;
import org.springframework.data.domain.Page;

View File

@@ -16,8 +16,8 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.util.WithSpringAuthorityRule;
import org.eclipse.hawkbit.repository.util.WithUser;
import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule;
import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.junit.Test;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Slice;

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.util;
package org.eclipse.hawkbit.repository.test.util;
import org.eclipse.hawkbit.ExcludePathAwareShallowETagFilter;
import org.eclipse.hawkbit.repository.ArtifactManagement;

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.util;
package org.eclipse.hawkbit.repository.test.util;
import java.io.IOException;
import java.net.UnknownHostException;

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.util;
package org.eclipse.hawkbit.repository.test.util;
import java.sql.Connection;
import java.sql.DriverManager;

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.util;
package org.eclipse.hawkbit.repository.test.util;
import java.io.File;
import java.net.InetSocketAddress;

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.util;
package org.eclipse.hawkbit.repository.test.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.util;
package org.eclipse.hawkbit.repository.test.util;
import java.util.List;

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.util;
package org.eclipse.hawkbit.repository.test.util;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.util;
package org.eclipse.hawkbit.repository.test.util;
/**
* Repository support for tests.

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.util;
package org.eclipse.hawkbit.repository.test.util;
import java.io.InputStream;
import java.nio.charset.Charset;

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.util;
package org.eclipse.hawkbit.repository.test.util;
/**
*

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.util;
package org.eclipse.hawkbit.repository.test.util;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.util;
package org.eclipse.hawkbit.repository.test.util;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;

View File

@@ -8,7 +8,7 @@
*/
package org.eclipse.hawkbit.rest;
import org.eclipse.hawkbit.repository.util.AbstractIntegrationTest;
import org.eclipse.hawkbit.repository.test.util.AbstractIntegrationTest;
import org.eclipse.hawkbit.rest.configuration.RestConfiguration;
import org.eclipse.hawkbit.rest.util.FilterHttpResponse;
import org.springframework.beans.factory.annotation.Autowired;

View File

@@ -8,7 +8,7 @@
*/
package org.eclipse.hawkbit.rest;
import org.eclipse.hawkbit.repository.util.AbstractIntegrationTestWithMongoDB;
import org.eclipse.hawkbit.repository.test.util.AbstractIntegrationTestWithMongoDB;
import org.eclipse.hawkbit.rest.configuration.RestConfiguration;
import org.eclipse.hawkbit.rest.util.FilterHttpResponse;
import org.springframework.beans.factory.annotation.Autowired;

View File

@@ -100,7 +100,7 @@ public class DosFilter extends OncePerRequestFilter {
boolean processChain;
final String ip = IpUtil.getClientIpFromRequest(request, forwardHeader).getHost();
final String ip = IpUtil.getClientIpFromRequest(request, forwardHeader, true).getHost();
if (checkIpFails(ip)) {
processChain = handleMissingIpAddress(response);
} else {

View File

@@ -82,10 +82,16 @@ public class HawkbitSecurityProperties {
private String blacklist = "";
/**
* Name of the http header from which the remote ip is extracted.
* Name of the http header from which the remote ip is extracted for DDI
* connected clients.
*/
private String remoteIpHeader = "X-Forwarded-For";
/**
* Set to <code>true</code> if DDI clients remote IP should be stored.
*/
private boolean trackRemoteIp = true;
public String getBlacklist() {
return blacklist;
}
@@ -101,6 +107,14 @@ public class HawkbitSecurityProperties {
public void setRemoteIpHeader(final String remoteIpHeader) {
this.remoteIpHeader = remoteIpHeader;
}
public boolean isTrackRemoteIp() {
return trackRemoteIp;
}
public void setTrackRemoteIp(final boolean trackRemoteIp) {
this.trackRemoteIp = trackRemoteIp;
}
}
/**

View File

@@ -15,6 +15,8 @@ import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
import com.google.common.net.HttpHeaders;
/**
@@ -45,17 +47,49 @@ public final class IpUtil {
* @param request
* the {@link HttpServletRequest} to determine the IP address
* where this request has been sent from
* @param forwardHeader
* the header name containing the IP address e.g. forwarded by a
* proxy {@code x-forwarded-for}
* @param securityProperties
* hawkBit security properties.
* @return the {@link URI} based IP address from the client which sent the
* request
*/
public static URI getClientIpFromRequest(final HttpServletRequest request, final String forwardHeader) {
String ip = request.getHeader(forwardHeader);
if (ip == null || (ip = findClientIpAddress(ip)) == null) {
ip = request.getRemoteAddr();
public static URI getClientIpFromRequest(final HttpServletRequest request,
final HawkbitSecurityProperties securityProperties) {
return getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader(),
securityProperties.getClients().isTrackRemoteIp());
}
/**
* Retrieves the string based IP address from a given
* {@link HttpServletRequest} by either the
* {@link HttpHeaders#X_FORWARDED_FOR} or by the
* {@link HttpServletRequest#getRemoteAddr()} methods.
*
* @param request
* the {@link HttpServletRequest} to determine the IP address
* where this request has been sent from
* @param forwardHeader
* the header name containing the IP address e.g. forwarded by a
* proxy {@code x-forwarded-for}
*
* @param trackRemoteIp
* to <code>true</code> if remote IP should be tracked.
* @return the {@link URI} based IP address from the client which sent the
* request
*/
public static URI getClientIpFromRequest(final HttpServletRequest request, final String forwardHeader,
final boolean trackRemoteIp) {
String ip;
if (trackRemoteIp) {
ip = request.getHeader(forwardHeader);
if (ip == null || (ip = findClientIpAddress(ip)) == null) {
ip = request.getRemoteAddr();
}
} else {
ip = "***";
}
return createHttpUri(ip);
}

View File

@@ -50,7 +50,7 @@ public class IpUtilTest {
when(requestMock.getRemoteAddr()).thenReturn(knownRemoteClientIP.getHost());
// test
final URI remoteAddr = IpUtil.getClientIpFromRequest(requestMock, "bumlux");
final URI remoteAddr = IpUtil.getClientIpFromRequest(requestMock, "bumlux", true);
// verify
assertThat(remoteAddr).as("The remote address should be as the known client IP address")
@@ -59,6 +59,25 @@ public class IpUtilTest {
verify(requestMock, times(1)).getRemoteAddr();
}
@Test
@Description("Tests create uri from request with masked IP when IP tracking is disabled")
public void maskRemoteAddrIfDisabled() {
// known values
final URI knownRemoteClientIP = IpUtil.createHttpUri("***");
// mock
when(requestMock.getHeader(HttpHeaders.X_FORWARDED_FOR)).thenReturn(null);
when(requestMock.getRemoteAddr()).thenReturn(knownRemoteClientIP.getHost());
// test
final URI remoteAddr = IpUtil.getClientIpFromRequest(requestMock, "bumlux", false);
// verify
assertThat(remoteAddr).as("The remote address should be as the known client IP address")
.isEqualTo(knownRemoteClientIP);
verify(requestMock, times(0)).getHeader("bumlux");
verify(requestMock, times(0)).getRemoteAddr();
}
@Test
@Description("Tests create uri from x forward header")
public void getRemoteAddrFromXForwardedForHeader() {
@@ -69,7 +88,7 @@ public class IpUtilTest {
when(requestMock.getRemoteAddr()).thenReturn(null);
// test
final URI remoteAddr = IpUtil.getClientIpFromRequest(requestMock, "X-Forwarded-For");
final URI remoteAddr = IpUtil.getClientIpFromRequest(requestMock, "X-Forwarded-For", true);
// verify
assertThat(remoteAddr).as("The remote address should be as the known client IP address")

View File

@@ -14,10 +14,10 @@ import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareManagement;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.common.SoftwareModuleTypeBeanQuery;
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.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.I18N;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
@@ -29,29 +29,25 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory;
import org.vaadin.spring.events.EventBus;
import com.vaadin.server.FontAwesome;
import com.vaadin.event.FieldEvents.TextChangeEvent;
import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.FormLayout;
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.Window;
import com.vaadin.ui.themes.ValoTheme;
/**
* Generates window for Software module add or update.
*
*
*/
@SpringComponent
@ViewScope
public class SoftwareModuleAddUpdateWindow implements Serializable {
public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Serializable {
private static final long serialVersionUID = -5217675246477211483L;
@@ -70,7 +66,7 @@ public class SoftwareModuleAddUpdateWindow implements Serializable {
@Autowired
private transient EntityFactory entityFactory;
private Label madatoryLabel;
private Label mandatoryLabel;
private TextField nameTextField;
@@ -78,15 +74,11 @@ public class SoftwareModuleAddUpdateWindow implements Serializable {
private TextField vendorTextField;
private Button saveSoftware;
private Button closeWindow;
private ComboBox typeComboBox;
private TextArea descTextArea;
private Window window;
private CommonDialogWindow window;
private String oldDescriptionValue;
@@ -102,7 +94,8 @@ public class SoftwareModuleAddUpdateWindow implements Serializable {
* @return reference of {@link com.vaadin.ui.Window} to add new software
* module.
*/
public Window createAddSoftwareModuleWindow() {
public CommonDialogWindow createAddSoftwareModuleWindow() {
editSwModule = Boolean.FALSE;
createRequiredComponents();
createWindow();
@@ -118,6 +111,7 @@ public class SoftwareModuleAddUpdateWindow implements Serializable {
* module.
*/
public Window createUpdateSoftwareModuleWindow(final Long baseSwModuleId) {
editSwModule = Boolean.TRUE;
this.baseSwModuleId = baseSwModuleId;
createRequiredComponents();
@@ -132,33 +126,35 @@ public class SoftwareModuleAddUpdateWindow implements Serializable {
private void createRequiredComponents() {
/* name textfield */
nameTextField = SPUIComponentProvider.getTextField("", ValoTheme.TEXTFIELD_TINY, true, null,
i18n.get("textfield.name"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
nameTextField = SPUIComponentProvider.getTextField(i18n.get("textfield.name"), "", ValoTheme.TEXTFIELD_TINY,
true, null, i18n.get("textfield.name"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
nameTextField.setId(SPUIComponentIdProvider.SOFT_MODULE_NAME);
/* version text field */
versionTextField = SPUIComponentProvider.getTextField("", ValoTheme.TEXTFIELD_TINY, true, null,
i18n.get("textfield.version"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
versionTextField = SPUIComponentProvider.getTextField(i18n.get("textfield.version"), "",
ValoTheme.TEXTFIELD_TINY, true, null, i18n.get("textfield.version"), true,
SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
versionTextField.setId(SPUIComponentIdProvider.SOFT_MODULE_VERSION);
/* Vendor text field */
vendorTextField = SPUIComponentProvider.getTextField("", ValoTheme.TEXTFIELD_TINY, false, null,
i18n.get("textfield.vendor"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
vendorTextField = SPUIComponentProvider.getTextField(i18n.get("textfield.vendor"), "", ValoTheme.TEXTFIELD_TINY,
false, null, i18n.get("textfield.vendor"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
vendorTextField.setId(SPUIComponentIdProvider.SOFT_MODULE_VENDOR);
descTextArea = SPUIComponentProvider.getTextArea("text-area-style", ValoTheme.TEXTAREA_TINY, false, null,
i18n.get("textfield.description"), SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
descTextArea = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "text-area-style",
ValoTheme.TEXTAREA_TINY, false, null, i18n.get("textfield.description"),
SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
descTextArea.setId(SPUIComponentIdProvider.ADD_SW_MODULE_DESCRIPTION);
addDescriptionTextChangeListener();
addVendorTextChangeListener();
/* Label for mandatory symbol */
madatoryLabel = new Label(i18n.get("label.mandatory.field"));
madatoryLabel.setStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR);
madatoryLabel.addStyleName(ValoTheme.LABEL_SMALL);
mandatoryLabel = new Label(i18n.get("label.mandatory.field"));
mandatoryLabel.setStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR);
mandatoryLabel.addStyleName(ValoTheme.LABEL_SMALL);
typeComboBox = SPUIComponentProvider.getComboBox("", "", null, null, false, null,
i18n.get("upload.swmodule.type"));
typeComboBox = SPUIComponentProvider.getComboBox(i18n.get("upload.swmodule.type"), "", "", null, null, true,
null, i18n.get("upload.swmodule.type"));
typeComboBox.setId(SPUIComponentIdProvider.SW_MODULE_TYPE);
typeComboBox.setStyleName(SPUIDefinitions.COMBO_BOX_SPECIFIC_STYLE + " " + ValoTheme.COMBOBOX_TINY);
typeComboBox.setNewItemsAllowed(Boolean.FALSE);
@@ -166,24 +162,6 @@ public class SoftwareModuleAddUpdateWindow implements Serializable {
populateTypeNameCombo();
/* save or update button */
saveSoftware = SPUIComponentProvider.getButton(SPUIComponentIdProvider.SOFT_MODULE_SAVE, "", "", "", true,
FontAwesome.SAVE, SPUIButtonStyleSmallNoBorder.class);
saveSoftware.addClickListener(event -> {
if (editSwModule) {
updateSwModule();
} else {
/* add new or update software module */
addNewBaseSoftware();
}
});
/* close button */
closeWindow = SPUIComponentProvider.getButton(SPUIComponentIdProvider.SOFT_MODULE_DISCARD, "", "", "", true,
FontAwesome.TIMES, SPUIButtonStyleSmallNoBorder.class);
/* Just close this window when this button is clicked */
closeWindow.addClickListener(event -> closeThisWindow());
resetOldValues();
}
@@ -203,68 +181,44 @@ public class SoftwareModuleAddUpdateWindow implements Serializable {
}
/**
* Keep UI components on Layout.
* Build the window content and get an instance of customDialogWindow
*
* @return
*/
private void createWindow() {
/* action button layout (save & dicard) */
final HorizontalLayout buttonsLayout = new HorizontalLayout();
buttonsLayout.setSizeFull();
buttonsLayout.addComponents(saveSoftware, closeWindow);
buttonsLayout.setComponentAlignment(saveSoftware, Alignment.BOTTOM_LEFT);
buttonsLayout.setComponentAlignment(closeWindow, Alignment.BOTTOM_RIGHT);
buttonsLayout.addStyleName("window-style");
final Label madatoryStarLabel = new Label("*");
madatoryStarLabel.setStyleName("v-caption v-required-field-indicator");
madatoryStarLabel.setWidth(null);
final HorizontalLayout hLayout = new HorizontalLayout();
hLayout.setSizeFull();
hLayout.addComponents(typeComboBox, madatoryStarLabel);
hLayout.setComponentAlignment(typeComboBox, Alignment.TOP_LEFT);
hLayout.setComponentAlignment(madatoryStarLabel, Alignment.TOP_RIGHT);
hLayout.setExpandRatio(typeComboBox, 0.8f);
/*
* The main layout of the window contains mandatory info, textboxes
* (controller Id, name & description) and action buttons layout
*/
final VerticalLayout mainLayout = new VerticalLayout();
mainLayout.setSpacing(Boolean.TRUE);
mainLayout.addStyleName("lay-color");
mainLayout.addComponent(madatoryLabel);
mainLayout.setComponentAlignment(madatoryLabel, Alignment.MIDDLE_LEFT);
mainLayout.addComponent(hLayout);
mainLayout.setComponentAlignment(hLayout, Alignment.MIDDLE_LEFT);
mainLayout.addComponents(nameTextField, versionTextField, vendorTextField, descTextArea, buttonsLayout);
addStyleName("lay-color");
final FormLayout formLayout = new FormLayout();
formLayout.addComponent(mandatoryLabel);
formLayout.addComponent(typeComboBox);
formLayout.addComponent(nameTextField);
formLayout.addComponent(versionTextField);
formLayout.addComponent(vendorTextField);
formLayout.addComponent(descTextArea);
setCompositionRoot(formLayout);
/* add main layout to the window */
window = SPUIComponentProvider.getWindow(i18n.get("upload.caption.add.new.swmodule"), null,
SPUIDefinitions.CREATE_UPDATE_WINDOW);
window.setContent(mainLayout);
window.setModal(true);
SPUIDefinitions.CREATE_UPDATE_WINDOW, this, event -> saveOrUpdate(), event -> closeThisWindow(), null);
window.getButtonsLayout().removeStyleName("actionButtonsMargin");
nameTextField.focus();
}
private void addDescriptionTextChangeListener() {
descTextArea.addTextChangeListener(event -> {
if (event.getText().equals(oldDescriptionValue) && vendorTextField.getValue().equals(oldVendorValue)) {
saveSoftware.setEnabled(false);
} else {
saveSoftware.setEnabled(true);
}
});
descTextArea.addTextChangeListener(event -> window.setSaveButtonEnabled(hasDescriptionChanged(event)));
}
private void addVendorTextChangeListener() {
vendorTextField.addTextChangeListener(event -> {
if (event.getText().equals(oldVendorValue) && descTextArea.getValue().equals(oldDescriptionValue)) {
saveSoftware.setEnabled(false);
} else {
saveSoftware.setEnabled(true);
}
});
vendorTextField.addTextChangeListener(event -> window.setSaveButtonEnabled(hasVendorChanged(event)));
}
/**
@@ -276,26 +230,31 @@ public class SoftwareModuleAddUpdateWindow implements Serializable {
final String vendor = HawkbitCommonUtil.trimAndNullIfEmpty(vendorTextField.getValue());
final String description = HawkbitCommonUtil.trimAndNullIfEmpty(descTextArea.getValue());
final String type = typeComboBox.getValue() != null ? typeComboBox.getValue().toString() : null;
if (mandatoryCheck(name, version, type)) {
if (HawkbitCommonUtil.isDuplicate(name, version, type)) {
uiNotifcation.displayValidationError(
i18n.get("message.duplicate.softwaremodule", new Object[] { name, version }));
} else {
final SoftwareModule newBaseSoftwareModule = HawkbitCommonUtil.addNewBaseSoftware(entityFactory, name,
version, vendor, softwareManagement.findSoftwareModuleTypeByName(type), description);
if (newBaseSoftwareModule != null) {
/* display success message */
uiNotifcation.displaySuccess(i18n.get("message.save.success", new Object[] {
newBaseSoftwareModule.getName() + ":" + newBaseSoftwareModule.getVersion() }));
eventBus.publish(this,
new SoftwareModuleEvent(BaseEntityEventType.NEW_ENTITY, newBaseSoftwareModule));
}
// close the window
closeThisWindow();
if (!mandatoryCheck(name, version, type)) {
return;
}
if (HawkbitCommonUtil.isDuplicate(name, version, type)) {
uiNotifcation.displayValidationError(
i18n.get("message.duplicate.softwaremodule", new Object[] { name, version }));
} else {
final SoftwareModule newBaseSoftwareModule = HawkbitCommonUtil.addNewBaseSoftware(entityFactory, name,
version, vendor, softwareManagement.findSoftwareModuleTypeByName(type), description);
if (newBaseSoftwareModule != null) {
/* display success message */
uiNotifcation.displaySuccess(i18n.get("message.save.success",
new Object[] { newBaseSoftwareModule.getName() + ":" + newBaseSoftwareModule.getVersion() }));
eventBus.publish(this, new SoftwareModuleEvent(BaseEntityEventType.NEW_ENTITY, newBaseSoftwareModule));
}
// close the window
closeThisWindow();
}
}
/**
* updates a softwareModule
*/
private void updateSwModule() {
final String newDesc = HawkbitCommonUtil.trimAndNullIfEmpty(descTextArea.getValue());
final String newVendor = HawkbitCommonUtil.trimAndNullIfEmpty(vendorTextField.getValue());
@@ -312,6 +271,9 @@ public class SoftwareModuleAddUpdateWindow implements Serializable {
closeThisWindow();
}
/**
* fill the data of a softwareModule in the content of the window
*/
private void populateValuesOfSwModule() {
final SoftwareModule swModle = softwareManagement.findSoftwareModuleById(baseSwModuleId);
nameTextField.setValue(swModle.getName());
@@ -326,7 +288,7 @@ public class SoftwareModuleAddUpdateWindow implements Serializable {
typeComboBox.addItem(swModle.getType().getName());
}
typeComboBox.setValue(swModle.getType().getName());
saveSoftware.setEnabled(Boolean.FALSE);
window.setSaveButtonEnabled(Boolean.FALSE);
}
/**
@@ -364,4 +326,21 @@ public class SoftwareModuleAddUpdateWindow implements Serializable {
}
return isValid;
}
private void saveOrUpdate() {
if (editSwModule) {
updateSwModule();
} else {
addNewBaseSoftware();
}
}
private boolean hasDescriptionChanged(final TextChangeEvent event) {
return !(event.getText().equals(oldDescriptionValue) && vendorTextField.getValue().equals(oldVendorValue));
}
private boolean hasVendorChanged(final TextChangeEvent event) {
return !(event.getText().equals(oldVendorValue) && descTextArea.getValue().equals(oldDescriptionValue));
}
}

View File

@@ -9,279 +9,114 @@
package org.eclipse.hawkbit.ui.artifacts.smtype;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareManagement;
import org.eclipse.hawkbit.repository.SpPermissionChecker;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent.SoftwareModuleTypeEnum;
import org.eclipse.hawkbit.ui.common.CoordinatesToColor;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerConstants;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper;
import org.eclipse.hawkbit.ui.common.SoftwareModuleTypeBeanQuery;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.management.tag.SpColorPickerPreview;
import org.eclipse.hawkbit.ui.layouts.CreateUpdateTypeLayout;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory;
import org.vaadin.spring.events.EventBus;
import com.google.common.base.Strings;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.server.FontAwesome;
import com.vaadin.server.Page;
import com.vaadin.shared.ui.colorpicker.Color;
import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.AbstractColorPicker.Coordinates2Color;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Label;
import com.vaadin.ui.OptionGroup;
import com.vaadin.ui.Slider;
import com.vaadin.ui.Slider.ValueOutOfBoundsException;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
import com.vaadin.ui.components.colorpicker.ColorChangeEvent;
import com.vaadin.ui.components.colorpicker.ColorChangeListener;
import com.vaadin.ui.components.colorpicker.ColorPickerGradient;
import com.vaadin.ui.components.colorpicker.ColorSelector;
import com.vaadin.ui.themes.ValoTheme;
/**
*
* Layout for the create or update software module type.
*
*/
@SpringComponent
@ViewScope
public class CreateUpdateSoftwareTypeLayout extends CustomComponent implements ColorChangeListener, ColorSelector {
public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout
implements ColorChangeListener, ColorSelector {
private static final long serialVersionUID = -5169398523815919367L;
private static final Logger LOG = LoggerFactory.getLogger(CreateUpdateSoftwareTypeLayout.class);
@Autowired
private SpPermissionChecker permChecker;
@Autowired
private I18N i18n;
/**
* Instance of ColorPickerPreview.
*/
private SpColorPickerPreview selPreview;
@Autowired
private transient UINotification uiNotification;
@Autowired
private transient SoftwareManagement swTypeManagementService;
@Autowired
private transient EntityFactory entityFactory;
@Autowired
private transient EventBus.SessionEventBus eventBus;
private String createTypeStr;
private String updateTypeStr;
private String singleAssignStr;
private String multiAssignStr;
private Label createType;
private Label updateType;
private Label singleAssign;
private Label multiAssign;
private Label comboLabel;
private Label colorLabel;
private Label madatoryLabel;
private TextField typeName;
private TextField typeKey;
private TextArea typeDesc;
private Button saveTag;
private Button discardTag;
private Button tagColorPreviewBtn;
private OptionGroup createOptiongroup;
private OptionGroup assignOptiongroup;
private ComboBox typeNameComboBox;
protected static final String DEFAULT_COLOR = "rgb(44,151,32)";
private static final String TYPE_NAME_DYNAMIC_STYLE = "new-tag-name";
private static final String TYPE_DESC_DYNAMIC_STYLE = "new-tag-desc";
private static final String TAG_DYNAMIC_STYLE = "tag-color-preview";
private Set<ColorSelector> selectors;
private Color selectedColor;
private ColorPickerGradient colorSelect;
private Slider redSlider;
private Slider greenSlider;
private Slider blueSlider;
private Window swTypeWindow;
protected boolean tagPreviewBtnClicked = false;
private VerticalLayout comboLayout;
private VerticalLayout sliders;
private VerticalLayout colorPickerLayout;
private HorizontalLayout mainLayout;
private VerticalLayout fieldLayout;
/** RGB color converter. */
private final Coordinates2Color rgbConverter = new CoordinatesToColor();
/**
* Initialize the artifact details layout.
*/
public void init() {
createComponents();
buildLayout();
addListeners();
@Override
protected void addListeners() {
super.addListeners();
optiongroup.addValueChangeListener(this::createOptionValueChanged);
}
private void createComponents() {
createTypeStr = i18n.get("label.create.type");
updateTypeStr = i18n.get("label.update.type");
@Override
protected void createRequiredComponents() {
super.createRequiredComponents();
singleAssignStr = i18n.get("label.singleAssign.type");
multiAssignStr = i18n.get("label.multiAssign.type");
createType = SPUIComponentProvider.getLabel(createTypeStr, null);
updateType = SPUIComponentProvider.getLabel(updateTypeStr, null);
singleAssign = SPUIComponentProvider.getLabel(singleAssignStr, null);
multiAssign = SPUIComponentProvider.getLabel(multiAssignStr, null);
comboLabel = SPUIComponentProvider.getLabel(i18n.get("label.choose.type"), null);
madatoryLabel = getMandatoryLabel();
colorLabel = SPUIComponentProvider.getLabel(i18n.get("label.choose.type.color"), null);
colorLabel.addStyleName(SPUIDefinitions.COLOR_LABEL_STYLE);
typeName = SPUIComponentProvider.getTextField("", ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TYPE_NAME,
true, "", i18n.get("textfield.name"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
typeName.setId(SPUIDefinitions.NEW_SOFTWARE_TYPE_NAME);
tagName = SPUIComponentProvider.getTextField(i18n.get("textfield.name"), "",
ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TYPE_NAME, true, "", i18n.get("textfield.name"), true,
SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
tagName.setId(SPUIDefinitions.NEW_SOFTWARE_TYPE_NAME);
typeKey = SPUIComponentProvider.getTextField("", ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TYPE_KEY,
true, "", i18n.get("textfield.key"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
typeKey = SPUIComponentProvider.getTextField(i18n.get("textfield.key"), "",
ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TYPE_KEY, true, "", i18n.get("textfield.key"), true,
SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
typeKey.setId(SPUIDefinitions.NEW_SOFTWARE_TYPE_KEY);
typeDesc = SPUIComponentProvider.getTextArea("", ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TYPE_DESC,
false, "", i18n.get("textfield.description"), SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
tagDesc = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "",
ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TYPE_DESC, false, "",
i18n.get("textfield.description"), SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
typeDesc.setId(SPUIDefinitions.NEW_SOFTWARE_TYPE_DESC);
typeDesc.setImmediate(true);
typeDesc.setNullRepresentation("");
typeNameComboBox = SPUIComponentProvider.getComboBox("", "", null, null, false, "",
i18n.get("label.combobox.type"));
typeNameComboBox.addStyleName(SPUIDefinitions.FILTER_TYPE_COMBO_STYLE);
typeNameComboBox.setImmediate(true);
saveTag = SPUIComponentProvider.getButton(SPUIDefinitions.NEW_SW_TYPE_SAVE, "", "", "", true, FontAwesome.SAVE,
SPUIButtonStyleSmallNoBorder.class);
saveTag.addStyleName(ValoTheme.BUTTON_BORDERLESS);
discardTag = SPUIComponentProvider.getButton(SPUIDefinitions.NEW_TARGET_TAG_DISRACD, "", "",
"discard-button-style", true, FontAwesome.TIMES, SPUIButtonStyleSmallNoBorder.class);
discardTag.addStyleName(ValoTheme.BUTTON_BORDERLESS);
tagColorPreviewBtn = new Button();
tagColorPreviewBtn.setId(SPUIComponentIdProvider.TAG_COLOR_PREVIEW_ID);
getPreviewButtonColor(DEFAULT_COLOR);
tagColorPreviewBtn.setStyleName(TAG_DYNAMIC_STYLE);
selectors = new HashSet<>();
selectedColor = new Color(44, 151, 32);
selPreview = new SpColorPickerPreview(selectedColor);
colorSelect = new ColorPickerGradient("rgb-gradient", rgbConverter);
colorSelect.setColor(selectedColor);
colorSelect.setWidth("220px");
redSlider = createRGBSlider("", "red");
greenSlider = createRGBSlider("", "green");
blueSlider = createRGBSlider("", "blue");
setRgbSliderValues(selectedColor);
createUpdateOptionGroup();
tagDesc.setId(SPUIDefinitions.NEW_SOFTWARE_TYPE_DESC);
tagDesc.setImmediate(true);
tagDesc.setNullRepresentation("");
singleMultiOptionGroup();
}
private void buildLayout() {
comboLayout = new VerticalLayout();
@Override
protected void buildLayout() {
sliders = new VerticalLayout();
sliders.addComponents(redSlider, greenSlider, blueSlider);
selectors.add(colorSelect);
colorPickerLayout = new VerticalLayout();
colorPickerLayout.setStyleName("rgb-vertical-layout");
colorPickerLayout.addComponent(selPreview);
colorPickerLayout.addComponent(colorSelect);
fieldLayout = new VerticalLayout();
fieldLayout.setSpacing(true);
fieldLayout.setMargin(false);
fieldLayout.setWidth("100%");
fieldLayout.setHeight(null);
fieldLayout.addComponent(createOptiongroup);
fieldLayout.addComponent(comboLayout);
fieldLayout.addComponent(madatoryLabel);
fieldLayout.addComponent(typeName);
fieldLayout.addComponent(typeKey);
fieldLayout.addComponent(typeDesc);
fieldLayout.addComponent(assignOptiongroup);
final HorizontalLayout colorLabelLayout = new HorizontalLayout();
colorLabelLayout.addComponents(colorLabel, tagColorPreviewBtn);
fieldLayout.addComponent(colorLabelLayout);
final HorizontalLayout buttonLayout = new HorizontalLayout();
buttonLayout.addComponent(saveTag);
buttonLayout.addComponent(discardTag);
buttonLayout.setComponentAlignment(discardTag, Alignment.BOTTOM_RIGHT);
buttonLayout.setComponentAlignment(saveTag, Alignment.BOTTOM_LEFT);
buttonLayout.addStyleName("window-style");
buttonLayout.setWidth("152px");
final VerticalLayout fieldButtonLayout = new VerticalLayout();
fieldButtonLayout.addComponent(fieldLayout);
fieldButtonLayout.addComponent(buttonLayout);
mainLayout = new HorizontalLayout();
mainLayout.addComponent(fieldButtonLayout);
setCompositionRoot(mainLayout);
typeName.focus();
super.buildLayout();
ColorPickerHelper.setRgbSliderValues(colorPickerLayout);
getFormLayout().addComponent(typeKey, 4);
getFormLayout().addComponent(assignOptiongroup);
}
private void addListeners() {
saveTag.addClickListener(event -> save());
discardTag.addClickListener(event -> discard());
colorSelect.addColorChangeListener(this);
selPreview.addColorChangeListener(this);
tagColorPreviewBtn.addClickListener(event -> previewButtonClicked());
createOptiongroup.addValueChangeListener(event -> createOptionValueChanged(event));
typeNameComboBox.addValueChangeListener(event -> typeNameChosen(event));
slidersValueChangeListeners();
}
public Window getWindow() {
@Override
public void createWindow() {
reset();
swTypeWindow = SPUIComponentProvider.getWindow(i18n.get("caption.add.type"), null,
SPUIDefinitions.CREATE_UPDATE_WINDOW);
swTypeWindow.setContent(this);
return swTypeWindow;
window = SPUIComponentProvider.getWindow(i18n.get("caption.add.type"), null,
SPUIDefinitions.CREATE_UPDATE_WINDOW, this, this::save, this::discard, null);
}
/**
@@ -290,100 +125,35 @@ public class CreateUpdateSoftwareTypeLayout extends CustomComponent implements C
* @param event
* ValueChangeEvent
*/
private void createOptionValueChanged(final ValueChangeEvent event) {
if ("Update Type".equals(event.getProperty().getValue())) {
typeName.clear();
typeDesc.clear();
typeKey.clear();
typeKey.setEnabled(false);
typeName.setEnabled(false);
@Override
protected void createOptionValueChanged(final ValueChangeEvent event) {
super.createOptionValueChanged(event);
if (updateTypeStr.equals(event.getProperty().getValue())) {
assignOptiongroup.setEnabled(false);
populateTypeNameCombo();
// show target name combo
comboLayout.addComponent(comboLabel);
comboLayout.addComponent(typeNameComboBox);
} else {
typeKey.setEnabled(true);
typeName.setEnabled(true);
typeName.clear();
typeDesc.clear();
typeKey.clear();
assignOptiongroup.setEnabled(true);
// hide target name combo
comboLayout.removeComponent(comboLabel);
comboLayout.removeComponent(typeNameComboBox);
}
// close the color picker layout
tagPreviewBtnClicked = false;
// reset the selected color - Set defualt color
restoreComponentStyles();
getPreviewButtonColor(DEFAULT_COLOR);
selPreview.setColor(rgbToColorConverter(DEFAULT_COLOR));
// remove the sliders and color picker layout
fieldLayout.removeComponent(sliders);
mainLayout.removeComponent(colorPickerLayout);
}
/**
* Populate Software Module Type name combo.
*/
public void populateTypeNameCombo() {
typeNameComboBox.setContainerDataSource(HawkbitCommonUtil.createLazyQueryContainer(
new BeanQueryFactory<SoftwareModuleTypeBeanQuery>(SoftwareModuleTypeBeanQuery.class)));
typeNameComboBox.setItemCaptionPropertyId(SPUILabelDefinitions.VAR_NAME);
}
/**
* reset the components.
*/
private void reset() {
typeName.setEnabled(true);
typeName.clear();
typeKey.clear();
typeDesc.clear();
restoreComponentStyles();
@Override
protected void reset() {
// hide target name combo
comboLayout.removeComponent(comboLabel);
comboLayout.removeComponent(typeNameComboBox);
fieldLayout.removeComponent(sliders);
mainLayout.removeComponent(colorPickerLayout);
createOptiongroup.select(createTypeStr);
super.reset();
assignOptiongroup.select(singleAssignStr);
// Default green color
selectedColor = new Color(44, 151, 32);
selPreview.setColor(selectedColor);
tagPreviewBtnClicked = false;
}
private void typeNameChosen(final ValueChangeEvent event) {
final String tagSelected = (String) event.getProperty().getValue();
if (null != tagSelected) {
setTypeTagCombo(tagSelected);
} else {
resetTagNameField();
}
}
private void resetTagNameField() {
typeName.setEnabled(false);
typeName.clear();
@Override
protected void resetTagNameField() {
super.resetTagNameField();
typeKey.clear();
typeDesc.clear();
restoreComponentStyles();
fieldLayout.removeComponent(sliders);
mainLayout.removeComponent(colorPickerLayout);
tagDesc.clear();
assignOptiongroup.select(singleAssignStr);
// Default green color
selectedColor = new Color(44, 151, 32);
selPreview.setColor(selectedColor);
tagPreviewBtnClicked = false;
}
/**
@@ -393,12 +163,13 @@ public class CreateUpdateSoftwareTypeLayout extends CustomComponent implements C
* @param targetTagSelected
* as the selected tag from combo
*/
private void setTypeTagCombo(final String targetTagSelected) {
typeName.setValue(targetTagSelected);
@Override
protected void setTagDetails(final String targetTagSelected) {
tagName.setValue(targetTagSelected);
final SoftwareModuleType selectedTypeTag = swTypeManagementService
.findSoftwareModuleTypeByName(targetTagSelected);
if (null != selectedTypeTag) {
typeDesc.setValue(selectedTypeTag.getDescription());
tagDesc.setValue(selectedTypeTag.getDescription());
typeKey.setValue(selectedTypeTag.getKey());
if (selectedTypeTag.getMaxAssignments() == Integer.MAX_VALUE) {
assignOptiongroup.setValue(multiAssignStr);
@@ -406,46 +177,10 @@ public class CreateUpdateSoftwareTypeLayout extends CustomComponent implements C
assignOptiongroup.setValue(singleAssignStr);
}
if (null == selectedTypeTag.getColour()) {
selectedColor = new Color(44, 151, 32);
selPreview.setColor(selectedColor);
colorSelect.setColor(selectedColor);
createDynamicStyleForComponents(typeName, typeKey, typeDesc, DEFAULT_COLOR);
getPreviewButtonColor(DEFAULT_COLOR);
} else {
selectedColor = rgbToColorConverter(selectedTypeTag.getColour());
selPreview.setColor(selectedColor);
colorSelect.setColor(selectedColor);
createDynamicStyleForComponents(typeName, typeKey, typeDesc, selectedTypeTag.getColour());
getPreviewButtonColor(selectedTypeTag.getColour());
}
setColorPickerComponentsColor(selectedTypeTag.getColour());
}
}
/**
* Dynamic styles for window.
*
* @param top
* int value
* @param marginLeft
* int value
*/
private void getPreviewButtonColor(final String color) {
Page.getCurrent().getJavaScript().execute(HawkbitCommonUtil.getPreviewButtonColorScript(color));
}
private void createUpdateOptionGroup() {
final List<String> optionValues = new ArrayList<>();
if (permChecker.hasCreateDistributionPermission()) {
optionValues.add(createType.getValue());
}
if (permChecker.hasUpdateDistributionPermission()) {
optionValues.add(updateType.getValue());
}
createOptionGroupByValues(optionValues);
}
private void singleMultiOptionGroup() {
final List<String> optionValues = new ArrayList<>();
optionValues.add(singleAssign.getValue());
@@ -453,16 +188,6 @@ public class CreateUpdateSoftwareTypeLayout extends CustomComponent implements C
assignOptionGroupByValues(optionValues);
}
private void createOptionGroupByValues(final List<String> tagOptions) {
createOptiongroup = new OptionGroup("", tagOptions);
createOptiongroup.setStyleName(ValoTheme.OPTIONGROUP_SMALL);
createOptiongroup.addStyleName("custom-option-group");
createOptiongroup.setNullSelectionAllowed(false);
if (!tagOptions.isEmpty()) {
createOptiongroup.select(tagOptions.get(0));
}
}
private void assignOptionGroupByValues(final List<String> tagOptions) {
assignOptiongroup = new OptionGroup("", tagOptions);
assignOptiongroup.setStyleName(ValoTheme.OPTIONGROUP_SMALL);
@@ -471,156 +196,32 @@ public class CreateUpdateSoftwareTypeLayout extends CustomComponent implements C
assignOptiongroup.select(tagOptions.get(0));
}
private Label getMandatoryLabel() {
final Label label = new Label(i18n.get("label.mandatory.field"));
label.setStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR + " " + ValoTheme.LABEL_SMALL);
return label;
}
@Override
protected void save(final ClickEvent event) {
if (!mandatoryValuesPresent()) {
return;
}
private Slider createRGBSlider(final String caption, final String styleName) {
final Slider slider = new Slider(caption, 0, 255);
slider.setImmediate(true);
slider.setWidth("150px");
slider.addStyleName(styleName);
return slider;
}
final SoftwareModuleType existingSMTypeByKey = swTypeManagementService
.findSoftwareModuleTypeByKey(typeKey.getValue());
final SoftwareModuleType existingSMTypeByName = swTypeManagementService
.findSoftwareModuleTypeByName(tagName.getValue());
if (optiongroup.getValue().equals(createTypeStr)) {
if (!checkIsDuplicateByKey(existingSMTypeByKey) && !checkIsDuplicate(existingSMTypeByName)) {
createNewSWModuleType();
}
} else {
private void setRgbSliderValues(final Color color) {
try {
final double redColorValue = color.getRed();
redSlider.setValue(new Double(redColorValue));
final double blueColorValue = color.getBlue();
blueSlider.setValue(new Double(blueColorValue));
final double greenColorValue = color.getGreen();
greenSlider.setValue(new Double(greenColorValue));
} catch (final ValueOutOfBoundsException e) {
LOG.error("Unable to set RGB color value to " + color.getRed() + "," + color.getGreen() + ","
+ color.getBlue(), e);
updateSWModuleType(existingSMTypeByName);
}
}
/**
* Value change listeners implementations of sliders.
*/
private void slidersValueChangeListeners() {
redSlider.addValueChangeListener(new ValueChangeListener() {
private static final long serialVersionUID = -8336732888800920839L;
@Override
public void valueChange(final ValueChangeEvent event) {
final double red = (Double) event.getProperty().getValue();
final Color newColor = new Color((int) red, selectedColor.getGreen(), selectedColor.getBlue());
setColorToComponents(newColor);
}
});
greenSlider.addValueChangeListener(new ValueChangeListener() {
private static final long serialVersionUID = 1236358037766775663L;
@Override
public void valueChange(final ValueChangeEvent event) {
final double green = (Double) event.getProperty().getValue();
final Color newColor = new Color(selectedColor.getRed(), (int) green, selectedColor.getBlue());
setColorToComponents(newColor);
}
});
blueSlider.addValueChangeListener(new ValueChangeListener() {
private static final long serialVersionUID = 8466370763686043947L;
@Override
public void valueChange(final ValueChangeEvent event) {
final double blue = (Double) event.getProperty().getValue();
final Color newColor = new Color(selectedColor.getRed(), selectedColor.getGreen(), (int) blue);
setColorToComponents(newColor);
}
});
}
private void setColorToComponents(final Color newColor) {
setColor(newColor);
colorSelect.setColor(newColor);
getPreviewButtonColor(newColor.getCSS());
createDynamicStyleForComponents(typeName, typeKey, typeDesc, newColor.getCSS());
}
/**
* reset the tag name and tag description component border color.
*/
private void restoreComponentStyles() {
typeName.removeStyleName(TYPE_NAME_DYNAMIC_STYLE);
typeDesc.removeStyleName(TYPE_DESC_DYNAMIC_STYLE);
typeKey.removeStyleName(TYPE_NAME_DYNAMIC_STYLE);
getPreviewButtonColor(DEFAULT_COLOR);
}
private void save() {
if (mandatoryValuesPresent()) {
final SoftwareModuleType existingType = swTypeManagementService
.findSoftwareModuleTypeByName(typeName.getValue());
if (createOptiongroup.getValue().equals(createTypeStr)) {
if (!checkIsKeyDuplicate(typeKey.getValue()) && !checkIsDuplicate(existingType)) {
createNewSWModuleType();
}
} else {
updateSWModuleType(existingType);
}
}
}
private boolean checkIsKeyDuplicate(final String key) {
final SoftwareModuleType existingKeyType = swTypeManagementService.findSoftwareModuleTypeByKey(key);
if (existingKeyType != null) {
uiNotification.displayValidationError(
i18n.get("message.type.key.swmodule.duplicate.check", new Object[] { existingKeyType.getKey() }));
return Boolean.TRUE;
}
return Boolean.FALSE;
}
private Boolean mandatoryValuesPresent() {
if (Strings.isNullOrEmpty(typeName.getValue()) && Strings.isNullOrEmpty(typeKey.getValue())) {
if (createOptiongroup.getValue().equals(createTypeStr)) {
uiNotification.displayValidationError(SPUILabelDefinitions.MISSING_TYPE_NAME_KEY);
}
if (createOptiongroup.getValue().equals(updateTypeStr)) {
if (null == typeNameComboBox.getValue()) {
uiNotification.displayValidationError(i18n.get("message.error.missing.typename"));
} else {
uiNotification.displayValidationError(SPUILabelDefinitions.MISSING_TAG_NAME);
}
}
return Boolean.FALSE;
}
return Boolean.TRUE;
}
private Boolean checkIsDuplicate(final SoftwareModuleType existingType) {
if (existingType != null) {
uiNotification.displayValidationError(
i18n.get("message.tag.duplicate.check", new Object[] { existingType.getName() }));
return Boolean.TRUE;
}
return Boolean.FALSE;
}
private void closeWindow() {
swTypeWindow.close();
UI.getCurrent().removeWindow(swTypeWindow);
}
private void discard() {
UI.getCurrent().removeWindow(swTypeWindow);
}
/**
* Create new tag.
*/
private void createNewSWModuleType() {
int assignNumber = 0;
final String colorPicked = getColorPickedString();
final String typeNameValue = HawkbitCommonUtil.trimAndNullIfEmpty(typeName.getValue());
final String colorPicked = ColorPickerHelper.getColorPickedString(getColorPickerLayout().getSelPreview());
final String typeNameValue = HawkbitCommonUtil.trimAndNullIfEmpty(tagName.getValue());
final String typeKeyValue = HawkbitCommonUtil.trimAndNullIfEmpty(typeKey.getValue());
final String typeDescValue = HawkbitCommonUtil.trimAndNullIfEmpty(typeDesc.getValue());
final String typeDescValue = HawkbitCommonUtil.trimAndNullIfEmpty(tagDesc.getValue());
final String assignValue = (String) assignOptiongroup.getValue();
if (null != assignValue && assignValue.equalsIgnoreCase(singleAssignStr)) {
assignNumber = 1;
@@ -651,38 +252,16 @@ public class CreateUpdateSoftwareTypeLayout extends CustomComponent implements C
}
}
/**
* Get color picked value in string.
*
* @return String of color picked value.
*/
private String getColorPickedString() {
return "rgb(" + getSelPreview().getColor().getRed() + "," + getSelPreview().getColor().getGreen() + ","
+ getSelPreview().getColor().getBlue() + ")";
}
/**
* Color view.
*
* @return ColorPickerPreview as UI
*/
public SpColorPickerPreview getSelPreview() {
return selPreview;
}
/**
* update tag.
*/
private void updateSWModuleType(final SoftwareModuleType existingType) {
final String typeNameValue = HawkbitCommonUtil.trimAndNullIfEmpty(typeName.getValue());
final String typeDescValue = HawkbitCommonUtil.trimAndNullIfEmpty(typeDesc.getValue());
final String typeNameValue = HawkbitCommonUtil.trimAndNullIfEmpty(tagName.getValue());
final String typeDescValue = HawkbitCommonUtil.trimAndNullIfEmpty(tagDesc.getValue());
if (null != typeNameValue) {
existingType.setName(typeNameValue);
existingType.setDescription(null != typeDescValue ? typeDescValue : null);
existingType.setColour(getColorPickedString());
existingType.setColour(ColorPickerHelper.getColorPickedString(getColorPickerLayout().getSelPreview()));
swTypeManagementService.updateSoftwareModuleType(existingType);
uiNotification.displaySuccess(i18n.get("message.update.success", new Object[] { existingType.getName() }));
closeWindow();
@@ -699,55 +278,33 @@ public class CreateUpdateSoftwareTypeLayout extends CustomComponent implements C
* Open color picker on click of preview button. Auto select the color based
* on target tag if already selected.
*/
private void previewButtonClicked() {
@Override
protected void previewButtonClicked() {
if (!tagPreviewBtnClicked) {
final String selectedOption = (String) createOptiongroup.getValue();
if (null != selectedOption && selectedOption.equalsIgnoreCase(updateTypeStr)) {
if (null != typeNameComboBox.getValue()) {
final String selectedOption = (String) optiongroup.getValue();
if (StringUtils.isNotEmpty(selectedOption) && selectedOption.equalsIgnoreCase(updateTypeStr)) {
if (null != tagNameComboBox.getValue()) {
final SoftwareModuleType typeSelected = swTypeManagementService
.findSoftwareModuleTypeByName(typeNameComboBox.getValue().toString());
.findSoftwareModuleTypeByName(tagNameComboBox.getValue().toString());
if (null != typeSelected) {
selectedColor = typeSelected.getColour() != null ? rgbToColorConverter(typeSelected.getColour())
: rgbToColorConverter(DEFAULT_COLOR);
getColorPickerLayout().setSelectedColor(typeSelected.getColour() != null
? ColorPickerHelper.rgbToColorConverter(typeSelected.getColour())
: ColorPickerHelper.rgbToColorConverter(ColorPickerConstants.DEFAULT_COLOR));
}
} else {
selectedColor = rgbToColorConverter(DEFAULT_COLOR);
getColorPickerLayout().setSelectedColor(
ColorPickerHelper.rgbToColorConverter(ColorPickerConstants.DEFAULT_COLOR));
}
}
selPreview.setColor(selectedColor);
fieldLayout.addComponent(sliders);
mainLayout.addComponent(colorPickerLayout);
mainLayout.setComponentAlignment(colorPickerLayout, Alignment.BOTTOM_CENTER);
getColorPickerLayout().getSelPreview().setColor(getColorPickerLayout().getSelectedColor());
mainLayout.addComponent(colorPickerLayout, 1, 0);
mainLayout.setComponentAlignment(colorPickerLayout, Alignment.MIDDLE_CENTER);
} else {
mainLayout.removeComponent(colorPickerLayout);
}
tagPreviewBtnClicked = !tagPreviewBtnClicked;
}
/**
* Covert RGB code to {@Color}.
*
* @param value
* RGB vale
* @return Color
*/
protected Color rgbToColorConverter(final String value) {
if (value.startsWith("rgb")) {
final String[] colors = value.substring(value.indexOf('(') + 1, value.length() - 1).split(",");
final int red = Integer.parseInt(colors[0]);
final int green = Integer.parseInt(colors[1]);
final int blue = Integer.parseInt(colors[2]);
if (colors.length > 3) {
final int alpha = (int) (Double.parseDouble(colors[3]) * 255d);
return new Color(red, green, blue, alpha);
} else {
return new Color(red, green, blue);
}
}
return null;
}
@Override
public void addColorChangeListener(final ColorChangeListener listener) {
LOG.debug("inside addColorChangeListener");
@@ -759,63 +316,16 @@ public class CreateUpdateSoftwareTypeLayout extends CustomComponent implements C
}
@Override
public void setColor(final Color color) {
if (color == null) {
return;
}
selectedColor = color;
selPreview.setColor(selectedColor);
final String colorPickedPreview = selPreview.getColor().getCSS();
if (typeName.isEnabled() && null != colorSelect) {
createDynamicStyleForComponents(typeName, typeKey, typeDesc, colorPickedPreview);
colorSelect.setColor(selPreview.getColor());
}
}
@Override
public Color getColor() {
return null;
}
@Override
public void colorChanged(final ColorChangeEvent event) {
setColor(event.getColor());
for (final ColorSelector select : selectors) {
if (!event.getSource().equals(select) && select.equals(this) && !select.getColor().equals(selectedColor)) {
select.setColor(selectedColor);
}
}
setRgbSliderValues(selectedColor);
getPreviewButtonColor(event.getColor().getCSS());
createDynamicStyleForComponents(typeName, typeKey, typeDesc, event.getColor().getCSS());
}
/**
* Set tag name and desc field border color based on chosen color.
*
* @param tagName
* @param tagDesc
* @param taregtTagColor
*/
private void createDynamicStyleForComponents(final TextField typeName, final TextField typeKey,
final TextArea typeDesc, final String typeTagColor) {
getTargetDynamicStyles(typeTagColor);
typeName.addStyleName(TYPE_NAME_DYNAMIC_STYLE);
typeKey.addStyleName(TYPE_NAME_DYNAMIC_STYLE);
typeDesc.addStyleName(TYPE_DESC_DYNAMIC_STYLE);
}
/**
* Get target style - Dynamically as per the color picked, cannot be done
* from the static css.
*
* @param colorPickedPreview
*/
private void getTargetDynamicStyles(final String colorPickedPreview) {
Page.getCurrent().getJavaScript()
.execute(HawkbitCommonUtil.changeToNewSelectedPreviewColor(colorPickedPreview));
protected void populateTagNameCombo() {
tagNameComboBox.setContainerDataSource(HawkbitCommonUtil.createLazyQueryContainer(
new BeanQueryFactory<SoftwareModuleTypeBeanQuery>(SoftwareModuleTypeBeanQuery.class)));
tagNameComboBox.setItemCaptionPropertyId(SPUILabelDefinitions.VAR_NAME);
}
}

View File

@@ -53,70 +53,65 @@ public class ArtifactUploadState implements ManagmentEntityState<Long>, Serializ
private Set<Long> selectedSoftwareModules = Collections.emptySet();
private boolean swTypeFilterClosed = Boolean.FALSE;
private boolean swTypeFilterClosed;
private boolean swModuleTableMaximized = Boolean.FALSE;
private boolean swModuleTableMaximized;
private boolean artifactDetailsMaximized = Boolean.FALSE;
private boolean artifactDetailsMaximized;
private final Set<String> selectedDeleteSWModuleTypes = new HashSet<>();
private boolean noDataAvilableSoftwareModule = Boolean.FALSE;
private boolean isStatusPopupMinimized = Boolean.FALSE;
private boolean isUploadCompleted = Boolean.FALSE;
private boolean noDataAvilableSoftwareModule;
private boolean statusPopupMinimized;
private boolean uploadCompleted;
private List<UploadStatusObject> uploadedFileStatusList = new ArrayList<>();
private final AtomicInteger numberOfFileUploadsExpected = new AtomicInteger();
private final AtomicInteger numberOfFilesActuallyUpload = new AtomicInteger();
private final AtomicInteger numberOfFileUploadsFailed = new AtomicInteger();
public AtomicInteger getNumberOfFileUploadsFailed() {
return numberOfFileUploadsFailed;
}
public AtomicInteger getNumberOfFilesActuallyUpload() {
return numberOfFilesActuallyUpload;
}
public AtomicInteger getNumberOfFileUploadsExpected() {
return numberOfFileUploadsExpected;
}
public List<UploadStatusObject> getUploadedFileStatusList() {
return uploadedFileStatusList;
}
public void setUploadedFileStatusList(List<UploadStatusObject> uploadedFileStatusList) {
public void setUploadedFileStatusList(final List<UploadStatusObject> uploadedFileStatusList) {
this.uploadedFileStatusList = uploadedFileStatusList;
}
public boolean isUploadCompleted() {
return isUploadCompleted;
}
public void setUploadCompleted(boolean isUploadCompleted) {
this.isUploadCompleted = isUploadCompleted;
return uploadCompleted;
}
public void setUploadCompleted(final boolean uploadCompleted) {
this.uploadCompleted = uploadCompleted;
}
public void setStatusPopupMinimized(final boolean statusPopupMinimized) {
this.statusPopupMinimized = statusPopupMinimized;
}
public void setStatusPopupMinimized(boolean isStatusPopupMinimized) {
this.isStatusPopupMinimized = isStatusPopupMinimized;
}
public boolean isStatusPopupMinimized() {
return isStatusPopupMinimized;
}
return statusPopupMinimized;
}
/**
/**
* Set software.
*
* @return

View File

@@ -245,16 +245,16 @@ public class UploadConfirmationwindow implements Button.ClickListener {
deleteIcon.setData(itemId);
newItem.getItemProperty(ACTION).setValue(deleteIcon);
final TextField sha1 = SPUIComponentProvider.getTextField("", ValoTheme.TEXTFIELD_TINY, false, null, null,
true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
final TextField sha1 = SPUIComponentProvider.getTextField(null, "", ValoTheme.TEXTFIELD_TINY, false, null,
null, true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
sha1.setId(swNameVersion + "/" + customFile.getFileName() + "/sha1");
final TextField md5 = SPUIComponentProvider.getTextField("", ValoTheme.TEXTFIELD_TINY, false, null, null,
true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
final TextField md5 = SPUIComponentProvider.getTextField(null, "", ValoTheme.TEXTFIELD_TINY, false, null,
null, true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
md5.setId(swNameVersion + "/" + customFile.getFileName() + "/md5");
final TextField customFileName = SPUIComponentProvider.getTextField("", ValoTheme.TEXTFIELD_TINY, false,
null, null, true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
final TextField customFileName = SPUIComponentProvider.getTextField(null, "", ValoTheme.TEXTFIELD_TINY,
false, null, null, true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
customFileName.setId(swNameVersion + "/" + customFile.getFileName() + "/customFileName");
newItem.getItemProperty(SHA1_CHECKSUM).setValue(sha1);
newItem.getItemProperty(MD5_CHECKSUM).setValue(md5);
@@ -265,8 +265,8 @@ public class UploadConfirmationwindow implements Button.ClickListener {
private void addFileNameLayout(final Item newItem, final String baseSoftwareModuleNameVersion,
final String customFileName, final String itemId) {
final HorizontalLayout horizontalLayout = new HorizontalLayout();
final TextField fileNameTextField = SPUIComponentProvider.getTextField("", ValoTheme.TEXTFIELD_TINY, false,
null, null, true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
final TextField fileNameTextField = SPUIComponentProvider.getTextField(null, "", ValoTheme.TEXTFIELD_TINY,
false, null, null, true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
fileNameTextField.setId(baseSoftwareModuleNameVersion + "/" + customFileName + "/customFileName");
fileNameTextField.setData(baseSoftwareModuleNameVersion + "/" + customFileName);
fileNameTextField.setValue(customFileName);

View File

@@ -328,7 +328,7 @@ public class UploadLayout extends VerticalLayout {
SPUIButtonStyleSmall.class);
processBtn.setIcon(FontAwesome.BELL);
processBtn.addStyleName(SPUIStyleDefinitions.ACTION_BUTTON);
processBtn.addClickListener(event -> displayConfirmWindow(event));
processBtn.addClickListener(this::displayConfirmWindow);
processBtn.setHtmlContentAllowed(true);
processBtn.setEnabled(false);
}
@@ -339,7 +339,7 @@ public class UploadLayout extends VerticalLayout {
SPUIButtonStyleSmall.class);
discardBtn.setIcon(FontAwesome.TRASH_O);
discardBtn.addStyleName(SPUIStyleDefinitions.ACTION_BUTTON);
discardBtn.addClickListener(event -> discardUploadData(event));
discardBtn.addClickListener(this::discardUploadData);
}
boolean checkForDuplicate(final String filename, final SoftwareModule selectedSw) {

View File

@@ -8,6 +8,8 @@
*/
package org.eclipse.hawkbit.ui.artifacts.upload;
import java.io.Serializable;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
/**
@@ -16,22 +18,24 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
* popup.
*
*/
public class UploadStatusObject {
public class UploadStatusObject implements Serializable {
private static final long serialVersionUID = 1L;
private String status;
private Double progress;
private String filename;
private String reason;
private SoftwareModule selectedSoftwareModule;
private final SoftwareModule selectedSoftwareModule;
public UploadStatusObject(final String status, final Double progress, final String fileName, final String reason,
final SoftwareModule selectedSoftwareModule) {
this(fileName,selectedSoftwareModule);
this(fileName, selectedSoftwareModule);
this.status = status;
this.progress = progress;
this.reason = reason;
}
public UploadStatusObject(String fileName, SoftwareModule selectedSoftwareModule) {
public UploadStatusObject(final String fileName, final SoftwareModule selectedSoftwareModule) {
this.filename = fileName;
this.selectedSoftwareModule = selectedSoftwareModule;
}
@@ -44,7 +48,7 @@ public class UploadStatusObject {
return status;
}
public void setStatus(String status) {
public void setStatus(final String status) {
this.status = status;
}
@@ -52,7 +56,7 @@ public class UploadStatusObject {
return progress;
}
public void setProgress(Double progress) {
public void setProgress(final Double progress) {
this.progress = progress;
}
@@ -60,7 +64,7 @@ public class UploadStatusObject {
return filename;
}
public void setFilename(String filename) {
public void setFilename(final String filename) {
this.filename = filename;
}
@@ -68,19 +72,38 @@ public class UploadStatusObject {
return reason;
}
public void setReason(String reason) {
public void setReason(final String reason) {
this.reason = reason;
}
@Override
public boolean equals(Object obj) {
if (this == null || obj == null) {
return false;
}
if (obj instanceof UploadStatusObject && this.getFilename() == ((UploadStatusObject) obj).getFilename()) {
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((filename == null) ? 0 : filename.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
return false;
if (obj == null) {
return false;
}
if (!(obj instanceof UploadStatusObject)) {
return false;
}
final UploadStatusObject other = (UploadStatusObject) obj;
if (filename == null) {
if (other.filename != null) {
return false;
}
} else if (!filename.equals(other.filename)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,25 @@
/**
* 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.colorpicker;
import com.vaadin.shared.ui.colorpicker.Color;
/**
* Provides color constants for the ColorPickerLayout
*
*/
public class ColorPickerConstants {
public static final String DEFAULT_COLOR = "rgb(44,151,32)";
public static final Color START_COLOR = new Color(0, 146, 58);
private ColorPickerConstants() {
}
}

View File

@@ -0,0 +1,92 @@
/**
* 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.colorpicker;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.hawkbit.ui.management.tag.SpColorPickerPreview;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.vaadin.shared.ui.colorpicker.Color;
import com.vaadin.ui.Slider.ValueOutOfBoundsException;
/**
* Contains helper methods for the ColorPickerLayout to handle the ColorPicker
*
*/
public class ColorPickerHelper {
private static final Logger LOG = LoggerFactory.getLogger(ColorPickerHelper.class);
private ColorPickerHelper() {
}
/**
* Get color picked value as string.
*
* @return String of color picked value.
*/
public static String getColorPickedString(final SpColorPickerPreview preview) {
final Color color = preview.getColor();
return "rgb(" + color.getRed() + "," + color.getGreen() + "," + color.getBlue() + ")";
}
/**
* Covert RGB code to {@Color}.
*
* @param value
* RGB vale
* @return Color
*/
public static Color rgbToColorConverter(final String value) {
if (StringUtils.isEmpty(value) || (StringUtils.isNotEmpty(value) && !value.startsWith("rgb"))) {
throw new IllegalArgumentException(
"String to convert is empty or of invalid format - value: '" + value + "'");
}
// RGB color format rgb/rgba(255,255,255,0.1)
final String[] colors = value.substring(value.indexOf('(') + 1, value.length() - 1).split(",");
final int red = Integer.parseInt(colors[0]);
final int green = Integer.parseInt(colors[1]);
final int blue = Integer.parseInt(colors[2]);
if (colors.length > 3) {
final int alpha = (int) (Double.parseDouble(colors[3]) * 255d);
return new Color(red, green, blue, alpha);
}
return new Color(red, green, blue);
}
/**
*
* Gets the selectedColor in the ColorPickerLayout and sets the slider
* values
*
* @param colorPickerLayout
* colorPickerLayout
*/
public static void setRgbSliderValues(final ColorPickerLayout colorPickerLayout) {
try {
final double redColorValue = colorPickerLayout.getSelectedColor().getRed();
colorPickerLayout.getRedSlider().setValue(Double.valueOf(redColorValue));
final double blueColorValue = colorPickerLayout.getSelectedColor().getBlue();
colorPickerLayout.getBlueSlider().setValue(Double.valueOf(blueColorValue));
final double greenColorValue = colorPickerLayout.getSelectedColor().getGreen();
colorPickerLayout.getGreenSlider().setValue(Double.valueOf(greenColorValue));
} catch (final ValueOutOfBoundsException e) {
LOG.error("Unable to set RGB color value to " + colorPickerLayout.getSelectedColor().getRed() + ","
+ colorPickerLayout.getSelectedColor().getGreen() + ","
+ colorPickerLayout.getSelectedColor().getBlue(), e);
}
}
}

View File

@@ -0,0 +1,148 @@
/**
* 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.colorpicker;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.hawkbit.ui.common.CoordinatesToColor;
import org.eclipse.hawkbit.ui.management.tag.SpColorPickerPreview;
import com.vaadin.shared.ui.colorpicker.Color;
import com.vaadin.ui.AbstractColorPicker.Coordinates2Color;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.Slider;
import com.vaadin.ui.components.colorpicker.ColorPickerGradient;
import com.vaadin.ui.components.colorpicker.ColorSelector;
/**
*
* Defines the Layout for the ColorPicker
*
*/
public class ColorPickerLayout extends GridLayout {
private static final long serialVersionUID = -7025970080613796692L;
private SpColorPickerPreview selPreview;
private ColorPickerGradient colorSelect;
private Set<ColorSelector> selectors;
private Color selectedColor;
/** RGB color converter. */
private final Coordinates2Color rgbConverter = new CoordinatesToColor();
private Slider redSlider;
private Slider greenSlider;
private Slider blueSlider;
public ColorPickerLayout() {
setColumns(2);
setRows(4);
init();
setStyleName("rgb-vertical-layout");
addComponent(redSlider, 0, 1);
addComponent(greenSlider, 0, 2);
addComponent(blueSlider, 0, 3);
addComponent(selPreview, 1, 0);
addComponent(colorSelect, 1, 1, 1, 3);
}
public void init() {
selectors = new HashSet<>();
selectedColor = getDefaultColor();
selPreview = new SpColorPickerPreview(selectedColor);
colorSelect = new ColorPickerGradient("rgb-gradient", rgbConverter);
colorSelect.setColor(selectedColor);
colorSelect.setWidth("220px");
redSlider = createRGBSlider("", "red");
greenSlider = createRGBSlider("", "green");
blueSlider = createRGBSlider("", "blue");
selectors.add(colorSelect);
}
public Slider createRGBSlider(final String caption, final String styleName) {
final Slider slider = new Slider(caption, 0, 255);
slider.setImmediate(true);
slider.setWidth("150px");
slider.addStyleName(styleName);
return slider;
}
public SpColorPickerPreview getSelPreview() {
return selPreview;
}
public void setSelPreview(final SpColorPickerPreview selPreview) {
this.selPreview = selPreview;
}
public ColorPickerGradient getColorSelect() {
return colorSelect;
}
public void setColorSelect(final ColorPickerGradient colorSelect) {
this.colorSelect = colorSelect;
}
public Set<ColorSelector> getSelectors() {
return selectors;
}
public Color getSelectedColor() {
return selectedColor;
}
public void setSelectedColor(final Color selectedColor) {
this.selectedColor = selectedColor;
}
public Coordinates2Color getRgbConverter() {
return rgbConverter;
}
public Color getDefaultColor() {
return new Color(44, 151, 32);
}
public Slider getRedSlider() {
return redSlider;
}
public void setRedSlider(final Slider redSlider) {
this.redSlider = redSlider;
}
public Slider getGreenSlider() {
return greenSlider;
}
public void setGreenSlider(final Slider greenSlider) {
this.greenSlider = greenSlider;
}
public Slider getBlueSlider() {
return blueSlider;
}
public void setBlueSlider(final Slider blueSlider) {
this.blueSlider = blueSlider;
}
}

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;
import static com.google.common.base.Preconditions.checkNotNull;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleBorderWithIcon;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.server.FontAwesome;
import com.vaadin.ui.AbstractOrderedLayout;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Link;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
/**
*
* Superclass for pop-up-windows including a minimize and close icon in the
* upper right corner and a save and cancel button at the bottom.
*
*/
public class CommonDialogWindow extends Window {
private static final long serialVersionUID = -1321949234316858703L;
private final VerticalLayout mainLayout = new VerticalLayout();
private final String caption;
private final Component content;
private final String helpLink;
private Button saveButton;
private Button cancelButton;
private HorizontalLayout buttonsLayout;
protected ValueChangeListener buttonEnableListener;
private final ClickListener saveButtonClickListener;
private final ClickListener cancelButtonClickListener;
/**
* Constructor.
*
* @param caption
* the caption
* @param content
* the content
* @param helpLink
* the helpLinks
* @param saveButtonClickListener
* the saveButtonClickListener
* @param cancelButtonClickListener
* the cancelButtonClickListener
*/
public CommonDialogWindow(final String caption, final Component content, final String helpLink,
final ClickListener saveButtonClickListener, final ClickListener cancelButtonClickListener) {
checkNotNull(saveButtonClickListener);
checkNotNull(cancelButtonClickListener);
this.caption = caption;
this.content = content;
this.helpLink = helpLink;
this.saveButtonClickListener = saveButtonClickListener;
this.cancelButtonClickListener = cancelButtonClickListener;
init();
}
private final void init() {
if (content instanceof AbstractOrderedLayout) {
((AbstractOrderedLayout) content).setSpacing(true);
((AbstractOrderedLayout) content).setMargin(true);
}
if (null != content) {
mainLayout.addComponent(content);
}
final HorizontalLayout buttonLayout = createActionButtonsLayout();
mainLayout.addComponent(buttonLayout);
mainLayout.setComponentAlignment(buttonLayout, Alignment.TOP_CENTER);
setCaption(caption);
setContent(mainLayout);
setResizable(false);
center();
setModal(true);
addStyleName("fontsize");
}
private HorizontalLayout createActionButtonsLayout() {
buttonsLayout = new HorizontalLayout();
buttonsLayout.setSizeFull();
buttonsLayout.setSpacing(true);
createSaveButton();
createCancelButton();
buttonsLayout.addStyleName("actionButtonsMargin");
addHelpLink();
return buttonsLayout;
}
private void createCancelButton() {
cancelButton = SPUIComponentProvider.getButton(SPUIComponentIdProvider.CANCEL_BUTTON, "Cancel", "", "", true,
FontAwesome.TIMES, SPUIButtonStyleBorderWithIcon.class);
cancelButton.setSizeUndefined();
cancelButton.addStyleName("default-color");
cancelButton.addClickListener(cancelButtonClickListener);
buttonsLayout.addComponent(cancelButton);
buttonsLayout.setComponentAlignment(cancelButton, Alignment.MIDDLE_LEFT);
buttonsLayout.setExpandRatio(cancelButton, 1.0F);
}
private void createSaveButton() {
saveButton = SPUIComponentProvider.getButton(SPUIComponentIdProvider.SAVE_BUTTON, "Save", "", "", true,
FontAwesome.SAVE, SPUIButtonStyleBorderWithIcon.class);
saveButton.setSizeUndefined();
saveButton.addStyleName("default-color");
saveButton.addClickListener(saveButtonClickListener);
buttonsLayout.addComponent(saveButton);
buttonsLayout.setComponentAlignment(saveButton, Alignment.MIDDLE_RIGHT);
buttonsLayout.setExpandRatio(saveButton, 1.0F);
}
private void addHelpLink() {
if (StringUtils.isEmpty(helpLink)) {
return;
}
final Link helpLinkComponent = SPUIComponentProvider.getHelpLink(helpLink);
buttonsLayout.addComponent(helpLinkComponent);
buttonsLayout.setComponentAlignment(helpLinkComponent, Alignment.MIDDLE_RIGHT);
}
public void setSaveButtonEnabled(final boolean enabled) {
saveButton.setEnabled(enabled);
}
public void setCancelButtonEnabled(final boolean enabled) {
cancelButton.setEnabled(enabled);
}
public HorizontalLayout getButtonsLayout() {
return buttonsLayout;
}
}

View File

@@ -42,11 +42,11 @@ import com.vaadin.ui.themes.ValoTheme;
public abstract class AbstractFilterButtons extends Table {
private static final long serialVersionUID = 7783305719009746375L;
private static final String DEFAULT_GREEN = "rgb(44,151,32)";
protected static final String FILTER_BUTTON_COLUMN = "filterButton";
@Autowired
protected transient EventBus.SessionEventBus eventBus;
@@ -63,7 +63,7 @@ public abstract class AbstractFilterButtons extends Table {
createTable();
eventBus.subscribe(this);
}
@PreDestroy
void destroy() {
eventBus.unsubscribe(this);
@@ -125,8 +125,7 @@ public abstract class AbstractFilterButtons extends Table {
} else if (id != null && isClickedByDefault(name)) {
filterButtonClickBehaviour.setDefaultClickedButton(typeButton);
}
final DragAndDropWrapper wrapper = createDragAndDropWrapper(typeButton, name, id);
return wrapper;
return createDragAndDropWrapper(typeButton, name, id);
}
protected boolean isNoTagSateSelected() {
@@ -156,6 +155,7 @@ public abstract class AbstractFilterButtons extends Table {
columnIds.add(FILTER_BUTTON_COLUMN);
setVisibleColumns(columnIds.toArray());
setColumnHeaderMode(ColumnHeaderMode.HIDDEN);
setColumnWidth(FILTER_BUTTON_COLUMN, 137);
}
private Button createFilterButton(final Long id, final String name, final String description, final String color,
@@ -180,6 +180,7 @@ public abstract class AbstractFilterButtons extends Table {
button.setDescription(name);
}
button.setData(id == null ? SPUIDefinitions.NO_TAG_BUTTON_ID : itemId);
return button;
}

View File

@@ -34,7 +34,6 @@ public abstract class AbstractFilterHeader extends VerticalLayout {
private static final long serialVersionUID = -1388340600522323332L;
@Autowired
protected SpPermissionChecker permChecker;
@@ -64,7 +63,7 @@ public abstract class AbstractFilterHeader extends VerticalLayout {
if (hasCreateUpdatePermission() && isAddTagRequired()) {
config = SPUIComponentProvider.getButton(getConfigureFilterButtonId(), "", "", "", true, FontAwesome.COG,
SPUIButtonStyleSmallNoBorder.class);
config.addClickListener(event -> settingsIconClicked(event));
config.addClickListener(this::settingsIconClicked);
}
hideIcon = SPUIComponentProvider.getButton(getHideButtonId(), "", "", "", true, FontAwesome.TIMES,
SPUIButtonStyleSmallNoBorder.class);
@@ -92,8 +91,7 @@ public abstract class AbstractFilterHeader extends VerticalLayout {
}
private Label createHeaderCaption() {
final Label captionLabel = SPUIComponentProvider.getLabel(getTitle(), SPUILabelDefinitions.SP_WIDGET_CAPTION);
return captionLabel;
return SPUIComponentProvider.getLabel(getTitle(), SPUILabelDefinitions.SP_WIDGET_CAPTION);
}
/**

View File

@@ -102,7 +102,7 @@ public abstract class AbstractGridHeader extends VerticalLayout {
}
private TextField createSearchField() {
final TextField textField = SPUIComponentProvider.getTextField("filter-box", "text-style filter-box-hide",
final TextField textField = SPUIComponentProvider.getTextField("", "filter-box", "text-style filter-box-hide",
false, "", "", false, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
textField.setId(getSearchBoxId());
textField.setWidth(100.0f, Unit.PERCENTAGE);
@@ -123,14 +123,14 @@ public abstract class AbstractGridHeader extends VerticalLayout {
private Button createAddButton() {
final Button button = SPUIComponentProvider.getButton(getAddIconId(), "", "", null, false, FontAwesome.PLUS,
SPUIButtonStyleSmallNoBorder.class);
button.addClickListener(event -> addNewItem(event));
button.addClickListener(this::addNewItem);
return button;
}
private Button createCloseButton() {
final Button button = SPUIComponentProvider.getButton(getCloseButtonId(), "", "", null, false,
FontAwesome.TIMES, SPUIButtonStyleSmallNoBorder.class);
button.addClickListener(event -> onClose(event));
button.addClickListener(this::onClose);
return button;
}

View File

@@ -213,7 +213,7 @@ public abstract class AbstractTableHeader extends VerticalLayout {
}
private TextField createSearchField() {
final TextField textField = SPUIComponentProvider.getTextField("filter-box", "text-style filter-box-hide",
final TextField textField = SPUIComponentProvider.getTextField("", "filter-box", "text-style filter-box-hide",
false, "", "", false, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
textField.setId(getSearchBoxId());
textField.setWidth(100.0f, Unit.PERCENTAGE);
@@ -235,14 +235,14 @@ public abstract class AbstractTableHeader extends VerticalLayout {
private Button createAddIcon() {
final Button button = SPUIComponentProvider.getButton(getAddIconId(), "", "", null, false, FontAwesome.PLUS,
SPUIButtonStyleSmallNoBorder.class);
button.addClickListener(event -> addNewItem(event));
button.addClickListener(this::addNewItem);
return button;
}
private Button createBulkUploadIcon() {
final Button button = SPUIComponentProvider.getButton(getBulkUploadIconId(), "", "", null, false,
FontAwesome.UPLOAD, SPUIButtonStyleSmallNoBorder.class);
button.addClickListener(event -> bulkUpload(event));
button.addClickListener(this::bulkUpload);
return button;
}

View File

@@ -14,6 +14,7 @@ import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.hawkbit.repository.model.BaseEntity;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonDecorator;
import org.eclipse.hawkbit.ui.decorators.SPUIComboBoxDecorator;
@@ -32,8 +33,10 @@ import com.vaadin.server.FontAwesome;
import com.vaadin.server.Resource;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Link;
@@ -137,6 +140,24 @@ public final class SPUIComponentProvider {
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.
*
@@ -155,6 +176,8 @@ public final class SPUIComponentProvider {
/**
* Get Label UI component.
*
* @param caption
* set the caption of the textfield
* @param style
* set style
* @param styleName
@@ -163,7 +186,7 @@ public final class SPUIComponentProvider {
* to set field as mandatory
* @param data
* component data
* @param promt
* @param prompt
* prompt user for input
* @param immediate
* set component's immediate mode specified mode
@@ -171,9 +194,11 @@ public final class SPUIComponentProvider {
* maximum characters allowed
* @return TextField text field
*/
public static TextField getTextField(final String style, final String styleName, final boolean required,
final String data, final String promt, final boolean immediate, final int maxLengthAllowed) {
return SPUITextFieldDecorator.decorate(style, styleName, required, data, promt, immediate, maxLengthAllowed);
public static TextField getTextField(final String caption, final String style, final String styleName,
final boolean required, final String data, final String prompt, final boolean immediate,
final int maxLengthAllowed) {
return SPUITextFieldDecorator.decorate(caption, style, styleName, required, data, prompt, immediate,
maxLengthAllowed);
}
/**
@@ -193,14 +218,16 @@ public final class SPUIComponentProvider {
* maximum characters allowed
* @return TextArea text area
*/
public static TextArea getTextArea(final String style, final String styleName, final boolean required,
final String data, final String promt, final int maxLength) {
return SPUITextAreaDecorator.decorate(style, styleName, required, data, promt, maxLength);
public static TextArea getTextArea(final String caption, final String style, final String styleName,
final boolean required, final String data, final String promt, final int maxLength) {
return SPUITextAreaDecorator.decorate(caption, style, styleName, required, data, promt, maxLength);
}
/**
* Get Label UI component.
*
* @param caption
* caption of the combo box
* @param height
* combo box height
* @param width
@@ -217,9 +244,9 @@ public final class SPUIComponentProvider {
* input prompt
* @return ComboBox
*/
public static ComboBox getComboBox(final String height, final String width, final String style,
final String styleName, final boolean required, final String data, final String promt) {
return SPUIComboBoxDecorator.decorate(height, width, style, styleName, required, data, promt);
public static ComboBox getComboBox(final String caption, final String height, final String width,
final String style, final String styleName, final boolean required, final String data, final String promt) {
return SPUIComboBoxDecorator.decorate(caption, height, width, style, styleName, required, data, promt);
}
/**

View File

@@ -0,0 +1,57 @@
/**
* 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.decorators;
import com.vaadin.server.Resource;
import com.vaadin.ui.Button;
import com.vaadin.ui.themes.ValoTheme;
/**
* Button with icon decorator.
*
*/
public class SPUIButtonStyleBorderWithIcon implements SPUIButtonDecorator {
private Button button;
@Override
public Button decorate(final Button button, final String style, final boolean setStyle, final Resource icon) {
this.button = button;
setButtonStyle(style, setStyle);
setButtonIcon(icon);
button.addStyleName(ValoTheme.LABEL_SMALL);
button.setSizeFull();
return button;
}
private void setButtonStyle(final String style, final boolean setStyle) {
if (style == null) {
return;
}
if (setStyle) {
button.setStyleName(style);
} else {
button.addStyleName(style);
}
}
private void setButtonIcon(final Resource icon) {
if (icon == null) {
return;
}
button.setIcon(icon);
}
}

View File

@@ -8,6 +8,8 @@
*/
package org.eclipse.hawkbit.ui.decorators;
import org.apache.commons.lang3.StringUtils;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.themes.ValoTheme;
@@ -29,6 +31,8 @@ public final class SPUIComboBoxDecorator {
/**
* Decorate.
*
* @param caption
* caption of the combobox
* @param height
* as H
* @param width
@@ -41,39 +45,42 @@ public final class SPUIComboBoxDecorator {
* as T|F
* @param data
* as data
* @param promt
* @param prompt
* as promt
* @return ComboBox as comp
*/
public static ComboBox decorate(final String height, final String width, final String style, final String styleName,
final boolean required, final String data, final String promt) {
public static ComboBox decorate(final String caption, final String height, final String width, final String style,
final String styleName, final boolean required, final String data, final String prompt) {
final ComboBox spUICombo = new ComboBox();
// Default settings
spUICombo.setRequired(required);
spUICombo.addStyleName(ValoTheme.COMBOBOX_TINY);
if (StringUtils.isNotEmpty(caption)) {
spUICombo.setCaption(caption);
}
// Add style
if (null != style) {
if (StringUtils.isNotEmpty(style)) {
spUICombo.setStyleName(style);
}
// Add style Name
if (null != styleName) {
if (StringUtils.isNotEmpty(styleName)) {
spUICombo.addStyleName(styleName);
}
// Add height
if (null != height) {
if (StringUtils.isNotEmpty(height)) {
spUICombo.setHeight(height);
}
// AddWidth
if (null != width) {
if (StringUtils.isNotEmpty(width)) {
spUICombo.setWidth(width);
}
// Set promt
if (null != promt) {
spUICombo.setInputPrompt(promt);
// Set prompt
if (StringUtils.isNotEmpty(prompt)) {
spUICombo.setInputPrompt(prompt);
}
// Set Data
if (null != data) {
if (StringUtils.isNotEmpty(data)) {
spUICombo.setData(data);
}

View File

@@ -8,8 +8,6 @@
*/
package org.eclipse.hawkbit.ui.decorators;
import org.eclipse.hawkbit.ui.utils.SPUIButtonDefinitions;
import com.vaadin.server.Resource;
import com.vaadin.ui.Button;
import com.vaadin.ui.themes.ValoTheme;
@@ -22,16 +20,10 @@ public class SPUITagButtonStyle implements SPUIButtonDecorator {
@Override
public Button decorate(final Button button, final String style, final boolean setStyle, final Resource icon) {
/**
* Add ... for long name
*/
final String buttonCaption = button.getCaption();
if (buttonCaption != null && buttonCaption.length() > SPUIButtonDefinitions.BUTTON_CAPTION_LENGTH) {
button.setCaption(buttonCaption.substring(0, SPUIButtonDefinitions.BUTTON_CAPTION_LENGTH) + "...");
}
button.setImmediate(true);
button.addStyleName("button-no-border" + " " + ValoTheme.BUTTON_BORDERLESS + " " + ValoTheme.BUTTON_TINY + " "
button.addStyleName("generatedColumnPadding button-no-border" + " " + ValoTheme.BUTTON_BORDERLESS + " "
+ "button-tag-no-border");
// Set Style
if (null != style) {
if (setStyle) {

View File

@@ -8,6 +8,8 @@
*/
package org.eclipse.hawkbit.ui.decorators;
import org.apache.commons.lang3.StringUtils;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.themes.ValoTheme;
@@ -37,33 +39,36 @@ public final class SPUITextAreaDecorator {
* to set field as mandatory
* @param data
* component data
* @param promt
* @param prompt
* as user for input
* @param maxLength
* maximum characters allowed
* @return TextArea as comp
*/
public static TextArea decorate(String style, String styleName, boolean required, String data, String promt,
int maxLength) {
public static TextArea decorate(final String caption, final String style, final String styleName,
final boolean required, final String data, final String prompt, final int maxLength) {
final TextArea spUITxtArea = new TextArea();
// Default settings
spUITxtArea.setRequired(false);
spUITxtArea.addStyleName(ValoTheme.COMBOBOX_SMALL);
spUITxtArea.addStyleName(ValoTheme.TEXTAREA_SMALL);
if (StringUtils.isNotEmpty(caption)) {
spUITxtArea.setCaption(caption);
}
if (required) {
spUITxtArea.setRequired(true);
}
// Add style
if (null != style) {
if (StringUtils.isNotEmpty(style)) {
spUITxtArea.setStyleName(style);
}
// Add style Name
if (null != styleName) {
if (StringUtils.isNotEmpty(styleName)) {
spUITxtArea.addStyleName(styleName);
}
if (null != promt) {
spUITxtArea.setInputPrompt(promt);
if (StringUtils.isNotEmpty(prompt)) {
spUITxtArea.setInputPrompt(prompt);
}
if (null != data) {
if (StringUtils.isNotEmpty(data)) {
spUITxtArea.setData(data);
}

View File

@@ -8,6 +8,8 @@
*/
package org.eclipse.hawkbit.ui.decorators;
import org.apache.commons.lang3.StringUtils;
import com.vaadin.ui.TextField;
import com.vaadin.ui.themes.ValoTheme;
@@ -27,8 +29,9 @@ public final class SPUITextFieldDecorator {
}
/**
* Decorate.
*
* @param caption
* set the caption of the textfield
* @param style
* set style
* @param styleName
@@ -37,7 +40,7 @@ public final class SPUITextFieldDecorator {
* to set field as mandatory
* @param data
* component data
* @param promt
* @param prompt
* prompt user for input
* @param immediate
* as for display
@@ -45,9 +48,13 @@ public final class SPUITextFieldDecorator {
* maximum characters allowed
* @return Text field as decorated
*/
public static TextField decorate(String style, String styleName, boolean required, String data, String promt,
boolean immediate, int maxLengthAllowed) {
public static TextField decorate(final String caption, final String style, final String styleName,
final boolean required, final String data, final String prompt, final boolean immediate,
final int maxLengthAllowed) {
final TextField spUITxtFld = new TextField();
if (StringUtils.isNotEmpty(caption)) {
spUITxtFld.setCaption(caption);
}
// Default settings
spUITxtFld.setRequired(false);
spUITxtFld.addStyleName(ValoTheme.TEXTFIELD_SMALL);
@@ -58,17 +65,17 @@ public final class SPUITextFieldDecorator {
spUITxtFld.setImmediate(true);
}
// Add style
if (null != style) {
if (StringUtils.isNotEmpty(style)) {
spUITxtFld.setStyleName(style);
}
// Add style Name
if (null != styleName) {
if (StringUtils.isNotEmpty(styleName)) {
spUITxtFld.addStyleName(styleName);
}
if (null != promt) {
spUITxtFld.setInputPrompt(promt);
if (StringUtils.isNotEmpty(prompt)) {
spUITxtFld.setInputPrompt(prompt);
}
if (null != data) {
if (StringUtils.isNotEmpty(data)) {
spUITxtFld.setData(data);
}
if (maxLengthAllowed > 0) {

View File

@@ -8,9 +8,12 @@
*/
package org.eclipse.hawkbit.ui.decorators;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Component;
import com.vaadin.ui.Window;
/**
@@ -28,6 +31,38 @@ public final class SPUIWindowDecorator {
}
/**
* Decorates window based on type.
*
* @param caption
* window caption
* @param id
* window id
* @param type
* window type
* @return Window
*/
public static CommonDialogWindow getDeocratedWindow(final String caption, final String id, final String type,
final Component content, final ClickListener saveButtonClickListener,
final ClickListener cancelButtonClickListener, final String helpLink) {
final CommonDialogWindow window = new CommonDialogWindow(caption, content, helpLink, saveButtonClickListener,
cancelButtonClickListener);
if (null != id) {
window.setId(id);
}
if (SPUIDefinitions.CONFIRMATION_WINDOW.equals(type)) {
window.setDraggable(false);
window.setClosable(true);
window.addStyleName(SPUIStyleDefinitions.CONFIRMATION_WINDOW_CAPTION);
} else if (SPUIDefinitions.CREATE_UPDATE_WINDOW.equals(type)) {
window.setDraggable(true);
window.setClosable(true);
}
return window;
}
/**
* Decorates window based on type.
*

View File

@@ -10,6 +10,7 @@ package org.eclipse.hawkbit.ui.distributions.disttype;
import javax.annotation.PostConstruct;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.common.filterlayout.AbstractFilterHeader;
import org.eclipse.hawkbit.ui.distributions.event.DistributionsUIEvent;
import org.eclipse.hawkbit.ui.distributions.state.ManageDistUIState;
@@ -21,7 +22,6 @@ import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.UI;
import com.vaadin.ui.Window;
/**
* Distribution Set Type filter buttons header.
@@ -38,6 +38,8 @@ public class DSTypeFilterHeader extends AbstractFilterHeader {
@Autowired
private CreateUpdateDistSetTypeLayout createUpdateDistSetTypeLayout;
private CommonDialogWindow addUpdateWindow;
@Override
@PostConstruct
public void init() {
@@ -59,10 +61,8 @@ public class DSTypeFilterHeader extends AbstractFilterHeader {
@Override
protected void settingsIconClicked(final ClickEvent event) {
final Window addUpdateWindow = createUpdateDistSetTypeLayout.getWindow();
addUpdateWindow = createUpdateDistSetTypeLayout.getWindow();
UI.getCurrent().addWindow(addUpdateWindow);
addUpdateWindow.setVisible(Boolean.TRUE);
}
@Override

View File

@@ -66,10 +66,9 @@ public class DistSMTypeFilterHeader extends AbstractFilterHeader {
@Override
protected void settingsIconClicked(final ClickEvent event) {
final Window addUpdateWindow = createUpdateSWTypeLayout.getWindow();
UI.getCurrent().addWindow(addUpdateWindow);
addUpdateWindow.setVisible(Boolean.TRUE);
final Window window = createUpdateSWTypeLayout.getWindow();
UI.getCurrent().addWindow(window);
window.setVisible(Boolean.TRUE);
}
@Override

View File

@@ -69,7 +69,7 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
private static final long serialVersionUID = 7474232427119031474L;
private static final String breadcrumbCustomFilters = "breadcrumb.target.filter.custom.filters";
private static final String BREADCRUMB_CUSTOM_FILTERS = "breadcrumb.target.filter.custom.filters";
@Autowired
private I18N i18n;
@@ -242,19 +242,20 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
final Button createFilterViewLink = SPUIComponentProvider.getButton(null, "", "", null, false, null,
SPUIButtonStyleSmallNoBorder.class);
createFilterViewLink.setStyleName(ValoTheme.LINK_SMALL + " " + "on-focus-no-border link rollout-caption-links");
createFilterViewLink.setDescription(i18n.get(breadcrumbCustomFilters));
createFilterViewLink.setCaption(i18n.get(breadcrumbCustomFilters));
createFilterViewLink.setDescription(i18n.get(BREADCRUMB_CUSTOM_FILTERS));
createFilterViewLink.setCaption(i18n.get(BREADCRUMB_CUSTOM_FILTERS));
createFilterViewLink.addClickListener(value -> showCustomFiltersView());
return createFilterViewLink;
}
private TextField createNameTextField() {
final TextField nameField = SPUIComponentProvider.getTextField("", ValoTheme.TEXTFIELD_TINY, false, null,
i18n.get("textfield.customfiltername"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
final TextField nameField = SPUIComponentProvider.getTextField(i18n.get("textfield.customfiltername"), "",
ValoTheme.TEXTFIELD_TINY, false, null, i18n.get("textfield.customfiltername"), true,
SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
nameField.setId(SPUIComponentIdProvider.CUSTOM_FILTER_ADD_NAME);
nameField.setPropertyDataSource(nameLabel);
nameField.addTextChangeListener(event -> onFilterNameChange(event));
nameField.addTextChangeListener(this::onFilterNameChange);
return nameField;
}
@@ -451,8 +452,8 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
}
private TextField createSearchField() {
final TextField textField = SPUIComponentProvider.getTextField("", ValoTheme.TEXTFIELD_TINY, false, "", "",
true, SPUILabelDefinitions.TARGET_FILTER_QUERY_TEXT_FIELD_LENGTH);
final TextField textField = SPUIComponentProvider.getTextField(null, "", ValoTheme.TEXTFIELD_TINY, false, "",
"", true, SPUILabelDefinitions.TARGET_FILTER_QUERY_TEXT_FIELD_LENGTH);
textField.setId("custom.query.text.Id");
textField.addStyleName("target-filter-textfield");
textField.setWidth(900.0F, Unit.PIXELS);
@@ -490,15 +491,11 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
public void buttonClick(final ClickEvent event) {
if (SPUIComponentIdProvider.CUSTOM_FILTER_SAVE_ICON.equals(event.getComponent().getId())
&& manadatoryFieldsPresent()) {
if (filterManagementUIState.isCreateFilterViewDisplayed()) {
if (!doesAlreadyExists()) {
createTargetFilterQuery();
}
if (filterManagementUIState.isCreateFilterViewDisplayed() && !doesAlreadyExists()) {
createTargetFilterQuery();
} else {
if (!nameTextField.getValue().equals(oldFilterName)) {
if (!doesAlreadyExists()) {
updateCustomFilter();
}
if (!nameTextField.getValue().equals(oldFilterName) && !doesAlreadyExists()) {
updateCustomFilter();
} else {
updateCustomFilter();
}

View File

@@ -121,7 +121,7 @@ public class TargetFilterHeader extends VerticalLayout {
}
private TextField createSearchField() {
final TextField campSearchTextField = SPUIComponentProvider.getTextField("filter-box",
final TextField campSearchTextField = SPUIComponentProvider.getTextField(null, "filter-box",
"text-style filter-box-hide", false, "", "", false, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
campSearchTextField.setId("target.filter.search.text.Id");
campSearchTextField.setWidth(500.0f, Unit.PIXELS);

View File

@@ -167,7 +167,7 @@ public class TargetFilterTable extends Table {
SPUILabelDefinitions.DELETE_CUSTOM_FILTER, ValoTheme.BUTTON_TINY + " " + "redicon", true,
FontAwesome.TRASH_O, SPUIButtonStyleSmallNoBorder.class);
deleteIcon.setData(itemId);
deleteIcon.addClickListener(event -> onDelete(event));
deleteIcon.addClickListener(this::onDelete);
return deleteIcon;
}
@@ -217,7 +217,7 @@ public class TargetFilterTable extends Table {
SPUILabelDefinitions.UPDATE_CUSTOM_FILTER, null, false, null, SPUIButtonStyleSmallNoBorder.class);
updateIcon.setData(tfName);
updateIcon.addStyleName(ValoTheme.LINK_SMALL + " " + "on-focus-no-border link");
updateIcon.addClickListener(event -> onClickOfDetailButton(event));
updateIcon.addClickListener(this::onClickOfDetailButton);
return updateIcon;
}

View File

@@ -0,0 +1,647 @@
/**
* 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.layouts;
import javax.annotation.PreDestroy;
import org.eclipse.hawkbit.repository.SpPermissionChecker;
import org.eclipse.hawkbit.repository.TagManagement;
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.Tag;
import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerConstants;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerLayout;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
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.google.common.base.Strings;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.server.Page;
import com.vaadin.shared.ui.colorpicker.Color;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.OptionGroup;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.components.colorpicker.ColorChangeEvent;
import com.vaadin.ui.components.colorpicker.ColorChangeListener;
import com.vaadin.ui.components.colorpicker.ColorSelector;
import com.vaadin.ui.themes.ValoTheme;
/**
* Abstract class for create/update target tag layout.
*/
public abstract class AbstractCreateUpdateTagLayout extends CustomComponent
implements ColorChangeListener, ColorSelector {
private static final long serialVersionUID = 4229177824620576456L;
private static final String TAG_NAME_DYNAMIC_STYLE = "new-tag-name";
private static final String TAG_DESC_DYNAMIC_STYLE = "new-tag-desc";
protected static final String TAG_DYNAMIC_STYLE = "tag-color-preview";
protected static final String MESSAGE_ERROR_MISSING_TAGNAME = "message.error.missing.tagname";
@Autowired
protected I18N i18n;
@Autowired
protected transient TagManagement tagManagement;
@Autowired
protected transient EventBus.SessionEventBus eventBus;
@Autowired
protected SpPermissionChecker permChecker;
@Autowired
protected transient UINotification uiNotification;
private final FormLayout formLayout = new FormLayout();
protected String createTagStr;
protected String updateTagStr;
protected Label comboLabel;
protected CommonDialogWindow window;
protected Label colorLabel;
protected Label madatoryLabel;
protected TextField tagName;
protected TextArea tagDesc;
protected Button tagColorPreviewBtn;
protected OptionGroup optiongroup;
protected ComboBox tagNameComboBox;
protected VerticalLayout comboLayout;
protected ColorPickerLayout colorPickerLayout;
protected GridLayout mainLayout;
protected VerticalLayout contentLayout;
protected boolean tagPreviewBtnClicked = false;
private String colorPicked;
protected String tagNameValue;
protected String tagDescValue;
protected void createWindow() {
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.
*
* @param event
*/
protected abstract void save(final Button.ClickEvent event);
/**
* Discard the changes and close the popup.
*
* @param event
*/
protected void discard(final Button.ClickEvent event) {
UI.getCurrent().removeWindow(window);
}
/**
* Populate target name combo.
*/
protected abstract void populateTagNameCombo();
protected abstract void setTagDetails(final String tagSelected);
/**
* Init the layout.
*/
public void init() {
setSizeUndefined();
createRequiredComponents();
buildLayout();
createWindow();
addListeners();
eventBus.subscribe(this);
}
@PreDestroy
void destroy() {
eventBus.unsubscribe(this);
}
protected void createRequiredComponents() {
createTagStr = i18n.get("label.create.tag");
updateTagStr = i18n.get("label.update.tag");
comboLabel = SPUIComponentProvider.getLabel(i18n.get("label.choose.tag"), null);
madatoryLabel = getMandatoryLabel();
colorLabel = SPUIComponentProvider.getLabel(i18n.get("label.choose.tag.color"), null);
colorLabel.addStyleName(SPUIDefinitions.COLOR_LABEL_STYLE);
tagName = SPUIComponentProvider.getTextField(i18n.get("textfield.name"), "",
ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TAG_NAME, true, "", i18n.get("textfield.name"), true,
SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
tagName.setId(SPUIDefinitions.NEW_TARGET_TAG_NAME);
tagDesc = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "",
ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TAG_DESC, false, "", i18n.get("textfield.description"),
SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
tagDesc.setId(SPUIDefinitions.NEW_TARGET_TAG_DESC);
tagDesc.setImmediate(true);
tagDesc.setNullRepresentation("");
tagNameComboBox = SPUIComponentProvider.getComboBox(null, "", "", null, null, false, "",
i18n.get("label.combobox.tag"));
tagNameComboBox.addStyleName(SPUIDefinitions.FILTER_TYPE_COMBO_STYLE);
tagNameComboBox.setImmediate(true);
tagColorPreviewBtn = new Button();
tagColorPreviewBtn.setId(SPUIComponentIdProvider.TAG_COLOR_PREVIEW_ID);
getPreviewButtonColor(ColorPickerConstants.DEFAULT_COLOR);
tagColorPreviewBtn.setStyleName(TAG_DYNAMIC_STYLE);
}
protected void buildLayout() {
mainLayout = new GridLayout(3, 2);
mainLayout.setSpacing(true);
comboLayout = new VerticalLayout();
colorPickerLayout = new ColorPickerLayout();
ColorPickerHelper.setRgbSliderValues(colorPickerLayout);
contentLayout = new VerticalLayout();
final HorizontalLayout colorLabelLayout = new HorizontalLayout();
colorLabelLayout.setMargin(false);
colorLabelLayout.addComponents(colorLabel, tagColorPreviewBtn);
formLayout.addComponent(optiongroup);
formLayout.addComponent(comboLayout);
formLayout.addComponent(madatoryLabel);
formLayout.addComponent(tagName);
formLayout.addComponent(tagDesc);
formLayout.addStyleName("form-lastrow");
formLayout.setSizeFull();
contentLayout.addComponent(formLayout);
contentLayout.addComponent(colorLabelLayout);
contentLayout.setComponentAlignment(formLayout, Alignment.MIDDLE_CENTER);
contentLayout.setComponentAlignment(colorLabelLayout, Alignment.MIDDLE_LEFT);
contentLayout.setSizeUndefined();
mainLayout.setSizeFull();
mainLayout.addComponent(contentLayout, 0, 0);
setCompositionRoot(mainLayout);
tagName.focus();
}
protected void addListeners() {
colorPickerLayout.getColorSelect().addColorChangeListener(this);
colorPickerLayout.getSelPreview().addColorChangeListener(this);
tagColorPreviewBtn.addClickListener(event -> previewButtonClicked());
tagNameComboBox.addValueChangeListener(this::tagNameChosen);
slidersValueChangeListeners();
}
/**
* Open color picker on click of preview button. Auto select the color based
* on target tag if already selected.
*/
protected void previewButtonClicked() {
if (!tagPreviewBtnClicked) {
setColor();
mainLayout.getComponent(1, 0);
mainLayout.addComponent(colorPickerLayout, 1, 0);
mainLayout.setComponentAlignment(colorPickerLayout, Alignment.MIDDLE_CENTER);
} else {
mainLayout.removeComponent(colorPickerLayout);
}
tagPreviewBtnClicked = !tagPreviewBtnClicked;
}
private void setColor() {
final String selectedOption = (String) optiongroup.getValue();
if (selectedOption == null || !selectedOption.equalsIgnoreCase(updateTagStr)) {
return;
}
if (tagNameComboBox.getValue() == null) {
colorPickerLayout
.setSelectedColor(ColorPickerHelper.rgbToColorConverter(ColorPickerConstants.DEFAULT_COLOR));
return;
}
final TargetTag targetTagSelected = tagManagement.findTargetTag(tagNameComboBox.getValue().toString());
if (targetTagSelected == null) {
final DistributionSetTag distTag = tagManagement
.findDistributionSetTag(tagNameComboBox.getValue().toString());
colorPickerLayout.setSelectedColor(
distTag.getColour() != null ? ColorPickerHelper.rgbToColorConverter(distTag.getColour())
: ColorPickerHelper.rgbToColorConverter(ColorPickerConstants.DEFAULT_COLOR));
} else {
colorPickerLayout.setSelectedColor(targetTagSelected.getColour() != null
? ColorPickerHelper.rgbToColorConverter(targetTagSelected.getColour())
: ColorPickerHelper.rgbToColorConverter(ColorPickerConstants.DEFAULT_COLOR));
}
}
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) {
final String tagSelected = (String) event.getProperty().getValue();
if (null != tagSelected) {
setTagDetails(tagSelected);
} else {
resetTagNameField();
}
}
protected void resetTagNameField() {
tagName.setEnabled(false);
tagName.clear();
tagDesc.clear();
restoreComponentStyles();
mainLayout.removeComponent(colorPickerLayout);
colorPickerLayout.setSelectedColor(colorPickerLayout.getDefaultColor());
colorPickerLayout.getSelPreview().setColor(colorPickerLayout.getSelectedColor());
tagPreviewBtnClicked = false;
}
/**
* Listener for option group - Create tag/Update.
*
* @param event
* ValueChangeEvent
*/
protected void optionValueChanged(final ValueChangeEvent event) {
if (updateTagStr.equals(event.getProperty().getValue())) {
tagName.clear();
tagDesc.clear();
tagName.setEnabled(false);
populateTagNameCombo();
// show target name combo
comboLayout.addComponent(comboLabel);
comboLayout.addComponent(tagNameComboBox);
} else {
tagName.setEnabled(true);
tagName.clear();
tagDesc.clear();
// hide target name combo
comboLayout.removeComponent(comboLabel);
comboLayout.removeComponent(tagNameComboBox);
}
// close the color picker layout
tagPreviewBtnClicked = false;
// reset the selected color - Set default color
restoreComponentStyles();
getPreviewButtonColor(ColorPickerConstants.DEFAULT_COLOR);
colorPickerLayout.getSelPreview()
.setColor(ColorPickerHelper.rgbToColorConverter(ColorPickerConstants.DEFAULT_COLOR));
mainLayout.removeComponent(colorPickerLayout);
}
/**
* reset the components.
*/
protected void reset() {
tagName.setEnabled(true);
tagName.clear();
tagDesc.clear();
restoreComponentStyles();
// hide target name combo
comboLayout.removeComponent(comboLabel);
comboLayout.removeComponent(tagNameComboBox);
mainLayout.removeComponent(colorPickerLayout);
// Default green color
colorPickerLayout.setSelectedColor(colorPickerLayout.getDefaultColor());
colorPickerLayout.getSelPreview().setColor(colorPickerLayout.getSelectedColor());
tagPreviewBtnClicked = false;
}
/**
* On change of color in color picker ,change RGB sliders, components border
* color and color of preview button.
*/
@Override
public void colorChanged(final ColorChangeEvent event) {
setColor(event.getColor());
for (final ColorSelector select : colorPickerLayout.getSelectors()) {
if (!event.getSource().equals(select) && select.equals(this)
&& !select.getColor().equals(colorPickerLayout.getSelectedColor())) {
select.setColor(colorPickerLayout.getSelectedColor());
}
}
ColorPickerHelper.setRgbSliderValues(colorPickerLayout);
getPreviewButtonColor(event.getColor().getCSS());
createDynamicStyleForComponents(tagName, tagDesc, event.getColor().getCSS());
}
/**
* Dynamic styles for window.
*
* @param top
* int value
* @param marginLeft
* int value
*/
protected void getPreviewButtonColor(final String color) {
Page.getCurrent().getJavaScript().execute(HawkbitCommonUtil.getPreviewButtonColorScript(color));
}
/**
* Set tag name and desc field border color based on chosen color.
*
* @param tagName
* @param tagDesc
* @param taregtTagColor
*/
protected void createDynamicStyleForComponents(final TextField tagName, final TextArea tagDesc,
final String taregtTagColor) {
tagName.removeStyleName(SPUIDefinitions.TAG_NAME);
tagDesc.removeStyleName(SPUIDefinitions.TAG_DESC);
getTargetDynamicStyles(taregtTagColor);
tagName.addStyleName(TAG_NAME_DYNAMIC_STYLE);
tagDesc.addStyleName(TAG_DESC_DYNAMIC_STYLE);
}
/**
* reset the tag name and tag description component border color.
*/
protected void restoreComponentStyles() {
tagName.removeStyleName(TAG_NAME_DYNAMIC_STYLE);
tagDesc.removeStyleName(TAG_DESC_DYNAMIC_STYLE);
tagName.addStyleName(SPUIDefinitions.TAG_NAME);
tagDesc.addStyleName(SPUIDefinitions.TAG_DESC);
getPreviewButtonColor(ColorPickerConstants.DEFAULT_COLOR);
}
/**
* Get target style - Dynamically as per the color picked, cannot be done
* from the static css.
*
* @param colorPickedPreview
*/
private void getTargetDynamicStyles(final String colorPickedPreview) {
Page.getCurrent().getJavaScript()
.execute(HawkbitCommonUtil.changeToNewSelectedPreviewColor(colorPickedPreview));
}
@Override
public Color getColor() {
return null;
}
@Override
public void setColor(final Color color) {
if (color == null) {
return;
}
colorPickerLayout.setSelectedColor(color);
colorPickerLayout.getSelPreview().setColor(colorPickerLayout.getSelectedColor());
final String colorPickedPreview = colorPickerLayout.getSelPreview().getColor().getCSS();
if (tagName.isEnabled() && null != colorPickerLayout.getColorSelect()) {
createDynamicStyleForComponents(tagName, tagDesc, colorPickedPreview);
colorPickerLayout.getColorSelect().setColor(colorPickerLayout.getSelPreview().getColor());
}
}
protected void closeWindow() {
window.close();
UI.getCurrent().removeWindow(window);
}
/**
* create option group with Create tag/Update tag based on permissions.
*/
protected void createOptionGroup(final boolean hasCreatePermission, final boolean hasUpdatePermission) {
optiongroup = new OptionGroup("Select Action");
optiongroup.addStyleName(ValoTheme.OPTIONGROUP_SMALL);
optiongroup.addStyleName("custom-option-group");
optiongroup.setNullSelectionAllowed(false);
if (hasCreatePermission) {
optiongroup.addItem(createTagStr);
}
if (hasUpdatePermission) {
optiongroup.addItem(updateTagStr);
}
setOptionGroupDefaultValue(hasCreatePermission, hasUpdatePermission);
}
protected void setOptionGroupDefaultValue(final boolean hasCreatePermission, final boolean hasUpdatePermission) {
if (hasCreatePermission) {
optiongroup.select(createTagStr);
}
if (hasUpdatePermission && !hasCreatePermission) {
optiongroup.select(updateTagStr);
}
}
@Override
public void addColorChangeListener(final ColorChangeListener listener) {
}
@Override
public void removeColorChangeListener(final ColorChangeListener listener) {
}
public ColorPickerLayout getColorPickerLayout() {
return colorPickerLayout;
}
public CommonDialogWindow getWindow() {
reset();
return window;
}
public void setWindow(final CommonDialogWindow window) {
this.window = window;
}
/**
* Value change listeners implementations of sliders.
*/
private void slidersValueChangeListeners() {
colorPickerLayout.getRedSlider().addValueChangeListener(new ValueChangeListener() {
private static final long serialVersionUID = -8336732888800920839L;
@Override
public void valueChange(final ValueChangeEvent event) {
final double red = (Double) event.getProperty().getValue();
final Color newColor = new Color((int) red, colorPickerLayout.getSelectedColor().getGreen(),
colorPickerLayout.getSelectedColor().getBlue());
setColorToComponents(newColor);
}
});
colorPickerLayout.getGreenSlider().addValueChangeListener(new ValueChangeListener() {
private static final long serialVersionUID = 1236358037766775663L;
@Override
public void valueChange(final ValueChangeEvent event) {
final double green = (Double) event.getProperty().getValue();
final Color newColor = new Color(colorPickerLayout.getSelectedColor().getRed(), (int) green,
colorPickerLayout.getSelectedColor().getBlue());
setColorToComponents(newColor);
}
});
colorPickerLayout.getBlueSlider().addValueChangeListener(new ValueChangeListener() {
private static final long serialVersionUID = 8466370763686043947L;
@Override
public void valueChange(final ValueChangeEvent event) {
final double blue = (Double) event.getProperty().getValue();
final Color newColor = new Color(colorPickerLayout.getSelectedColor().getRed(),
colorPickerLayout.getSelectedColor().getGreen(), (int) blue);
setColorToComponents(newColor);
}
});
}
protected void setColorToComponents(final Color newColor) {
setColor(newColor);
colorPickerLayout.getColorSelect().setColor(newColor);
getPreviewButtonColor(newColor.getCSS());
createDynamicStyleForComponents(tagName, tagDesc, newColor.getCSS());
}
/**
* Create new tag.
*/
protected void createNewTag() {
colorPicked = ColorPickerHelper.getColorPickedString(colorPickerLayout.getSelPreview());
tagNameValue = HawkbitCommonUtil.trimAndNullIfEmpty(tagName.getValue());
tagDescValue = HawkbitCommonUtil.trimAndNullIfEmpty(tagDesc.getValue());
}
/**
* update tag.
*/
protected void updateExistingTag(final Tag targetObj) {
final String nameUpdateValue = HawkbitCommonUtil.trimAndNullIfEmpty(tagName.getValue());
final String descUpdateValue = HawkbitCommonUtil.trimAndNullIfEmpty(tagDesc.getValue());
if (null != nameUpdateValue) {
targetObj.setName(nameUpdateValue);
targetObj.setDescription(null != descUpdateValue ? descUpdateValue : null);
targetObj.setColour(ColorPickerHelper.getColorPickedString(colorPickerLayout.getSelPreview()));
if (targetObj instanceof TargetTag) {
tagManagement.updateTargetTag((TargetTag) targetObj);
} else if (targetObj instanceof DistributionSetTag) {
tagManagement.updateDistributionSetTag((DistributionSetTag) targetObj);
}
uiNotification.displaySuccess(i18n.get("message.update.success", new Object[] { targetObj.getName() }));
closeWindow();
} else {
uiNotification.displayValidationError(i18n.get("message.tag.update.mandatory"));
}
}
protected void displaySuccess(final String tagName) {
uiNotification.displaySuccess(i18n.get("message.save.success", new Object[] { tagName }));
}
protected void displayValidationError(final String errorMessage) {
uiNotification.displayValidationError(errorMessage);
}
protected void setTagColor(final Color selectedColor, final String previewColor) {
getColorPickerLayout().setSelectedColor(selectedColor);
getColorPickerLayout().getSelPreview().setColor(getColorPickerLayout().getSelectedColor());
getColorPickerLayout().getColorSelect().setColor(getColorPickerLayout().getSelectedColor());
createDynamicStyleForComponents(tagName, tagDesc, 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) {
if (existingTag != null) {
displayValidationError(i18n.get("message.tag.duplicate.check", new Object[] { existingTag.getName() }));
return Boolean.TRUE;
}
return Boolean.FALSE;
}
public String getColorPicked() {
return colorPicked;
}
public void setColorPicked(final String colorPicked) {
this.colorPicked = colorPicked;
}
public String getTagNameValue() {
return tagNameValue;
}
public void setTagNameValue(final String tagNameValue) {
this.tagNameValue = tagNameValue;
}
public String getTagDescValue() {
return tagDescValue;
}
public void setTagDescValue(final String tagDescValue) {
this.tagDescValue = tagDescValue;
}
public FormLayout getFormLayout() {
return formLayout;
}
}

View File

@@ -0,0 +1,321 @@
/**
* 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.layouts;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.NamedEntity;
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.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
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.server.Page;
import com.vaadin.shared.ui.colorpicker.Color;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.OptionGroup;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField;
import com.vaadin.ui.components.colorpicker.ColorChangeEvent;
import com.vaadin.ui.components.colorpicker.ColorSelector;
import com.vaadin.ui.themes.ValoTheme;
/**
*
* Superclass defining common properties and methods for creating/updating
* types.
*
*/
public class CreateUpdateTypeLayout extends AbstractCreateUpdateTagLayout {
private static final long serialVersionUID = 5732904956185988397L;
protected String createTypeStr;
protected String updateTypeStr;
protected TextField typeKey;
public static final String TYPE_NAME_DYNAMIC_STYLE = "new-tag-name";
private static final String TYPE_DESC_DYNAMIC_STYLE = "new-tag-desc";
@Override
protected void addListeners() {
super.addListeners();
optiongroup.addValueChangeListener(this::createOptionValueChanged);
}
@Override
protected void createRequiredComponents() {
createTypeStr = i18n.get("label.create.type");
updateTypeStr = i18n.get("label.update.type");
comboLabel = SPUIComponentProvider.getLabel(i18n.get("label.choose.type"), null);
madatoryLabel = getMandatoryLabel();
colorLabel = SPUIComponentProvider.getLabel(i18n.get("label.choose.type.color"), null);
colorLabel.addStyleName(SPUIDefinitions.COLOR_LABEL_STYLE);
tagNameComboBox = SPUIComponentProvider.getComboBox(i18n.get("label.combobox.type"), "", "", null, null, false,
"", i18n.get("label.combobox.type"));
tagNameComboBox.setId(SPUIDefinitions.NEW_DISTRIBUTION_SET_TYPE_NAME_COMBO);
tagNameComboBox.addStyleName(SPUIDefinitions.FILTER_TYPE_COMBO_STYLE);
tagNameComboBox.setImmediate(true);
tagNameComboBox.setPageLength(SPUIDefinitions.DIST_TYPE_SIZE);
tagColorPreviewBtn = new Button();
tagColorPreviewBtn.setId(SPUIComponentIdProvider.TAG_COLOR_PREVIEW_ID);
getPreviewButtonColor(ColorPickerConstants.DEFAULT_COLOR);
tagColorPreviewBtn.setStyleName(TAG_DYNAMIC_STYLE);
createOptionGroup(permChecker.hasCreateDistributionPermission(), permChecker.hasUpdateDistributionPermission());
}
@Override
protected void setColorToComponents(final Color newColor) {
super.setColorToComponents(newColor);
createDynamicStyleForComponents(tagName, typeKey, tagDesc, newColor.getCSS());
}
/**
* Set tag name and desc field border color based on chosen color.
*
* @param tagName
* @param tagDesc
* @param taregtTagColor
*/
protected void createDynamicStyleForComponents(final TextField tagName, final TextField typeKey,
final TextArea typeDesc, final String typeTagColor) {
tagName.removeStyleName(SPUIDefinitions.TYPE_NAME);
typeKey.removeStyleName(SPUIDefinitions.TYPE_KEY);
typeDesc.removeStyleName(SPUIDefinitions.TYPE_DESC);
getDynamicStyles(typeTagColor);
tagName.addStyleName(TYPE_NAME_DYNAMIC_STYLE);
typeKey.addStyleName(TYPE_NAME_DYNAMIC_STYLE);
typeDesc.addStyleName(TYPE_DESC_DYNAMIC_STYLE);
}
/**
* Get target style - Dynamically as per the color picked, cannot be done
* from the static css.
*
* @param colorPickedPreview
*/
private void getDynamicStyles(final String colorPickedPreview) {
Page.getCurrent().getJavaScript()
.execute(HawkbitCommonUtil.changeToNewSelectedPreviewColor(colorPickedPreview));
}
/**
* reset the components.
*/
@Override
protected void reset() {
super.reset();
typeKey.clear();
restoreComponentStyles();
setOptionGroupDefaultValue(permChecker.hasCreateDistributionPermission(),
permChecker.hasUpdateDistributionPermission());
}
/**
* Listener for option group - Create tag/Update.
*
* @param event
* ValueChangeEvent
*/
protected void createOptionValueChanged(final ValueChangeEvent event) {
if (updateTypeStr.equals(event.getProperty().getValue())) {
tagName.clear();
tagDesc.clear();
typeKey.clear();
typeKey.setEnabled(false);
tagName.setEnabled(false);
populateTagNameCombo();
comboLayout.addComponent(comboLabel);
comboLayout.addComponent(tagNameComboBox);
} else {
typeKey.setEnabled(true);
tagName.setEnabled(true);
window.setSaveButtonEnabled(true);
tagName.clear();
tagDesc.clear();
typeKey.clear();
comboLayout.removeComponent(comboLabel);
comboLayout.removeComponent(tagNameComboBox);
}
restoreComponentStyles();
getPreviewButtonColor(ColorPickerConstants.DEFAULT_COLOR);
getColorPickerLayout().getSelPreview()
.setColor(ColorPickerHelper.rgbToColorConverter(ColorPickerConstants.DEFAULT_COLOR));
}
/*
* (non-Javadoc)
*
* @see
* com.vaadin.ui.components.colorpicker.ColorSelector#setColor(com.vaadin.
* shared.ui.colorpicker .Color)
*/
@Override
public void setColor(final Color color) {
if (color == null) {
return;
}
getColorPickerLayout().setSelectedColor(color);
getColorPickerLayout().getSelPreview().setColor(getColorPickerLayout().getSelectedColor());
final String colorPickedPreview = getColorPickerLayout().getSelPreview().getColor().getCSS();
if (tagName.isEnabled() && null != getColorPickerLayout().getColorSelect()) {
createDynamicStyleForComponents(tagName, typeKey, tagDesc, colorPickedPreview);
getColorPickerLayout().getColorSelect().setColor(getColorPickerLayout().getSelPreview().getColor());
}
}
/**
* reset the tag name and tag description component border color.
*/
@Override
protected void restoreComponentStyles() {
super.restoreComponentStyles();
typeKey.removeStyleName(TYPE_NAME_DYNAMIC_STYLE);
typeKey.addStyleName(SPUIDefinitions.TYPE_KEY);
}
/**
* create option group with Create tag/Update tag based on permissions.
*/
@Override
protected void createOptionGroup(final boolean hasCreatePermission, final boolean hasUpdatePermission) {
optiongroup = new OptionGroup("Select Action");
optiongroup.addStyleName(ValoTheme.OPTIONGROUP_SMALL);
optiongroup.addStyleName("custom-option-group");
optiongroup.setNullSelectionAllowed(false);
if (hasCreatePermission) {
optiongroup.addItem(createTypeStr);
}
if (hasUpdatePermission) {
optiongroup.addItem(updateTypeStr);
}
setOptionGroupDefaultValue(hasCreatePermission, hasUpdatePermission);
}
@Override
protected void setOptionGroupDefaultValue(final boolean hasCreatePermission, final boolean hasUpdatePermission) {
if (hasCreatePermission) {
optiongroup.select(createTypeStr);
}
if (hasUpdatePermission && !hasCreatePermission) {
optiongroup.select(updateTypeStr);
}
}
protected void setColorPickerComponentsColor(final String color) {
if (null == color) {
getColorPickerLayout()
.setSelectedColor(ColorPickerHelper.rgbToColorConverter(ColorPickerConstants.DEFAULT_COLOR));
getColorPickerLayout().getSelPreview().setColor(getColorPickerLayout().getSelectedColor());
getColorPickerLayout().getColorSelect().setColor(getColorPickerLayout().getSelectedColor());
createDynamicStyleForComponents(tagName, typeKey, tagDesc, ColorPickerConstants.DEFAULT_COLOR);
getPreviewButtonColor(ColorPickerConstants.DEFAULT_COLOR);
} else {
getColorPickerLayout().setSelectedColor(ColorPickerHelper.rgbToColorConverter(color));
getColorPickerLayout().getSelPreview().setColor(getColorPickerLayout().getSelectedColor());
getColorPickerLayout().getColorSelect().setColor(getColorPickerLayout().getSelectedColor());
createDynamicStyleForComponents(tagName, typeKey, tagDesc, color);
getPreviewButtonColor(color);
}
}
@Override
public void colorChanged(final ColorChangeEvent event) {
setColor(event.getColor());
for (final ColorSelector select : getColorPickerLayout().getSelectors()) {
if (!event.getSource().equals(select) && select.equals(this)
&& !select.getColor().equals(getColorPickerLayout().getSelectedColor())) {
select.setColor(getColorPickerLayout().getSelectedColor());
}
}
ColorPickerHelper.setRgbSliderValues(getColorPickerLayout());
getPreviewButtonColor(event.getColor().getCSS());
createDynamicStyleForComponents(tagName, typeKey, tagDesc, event.getColor().getCSS());
}
protected Boolean checkIsDuplicate(final NamedEntity existingType) {
if (existingType != null) {
uiNotification.displayValidationError(
i18n.get("message.tag.duplicate.check", new Object[] { existingType.getName() }));
return Boolean.TRUE;
}
return Boolean.FALSE;
}
protected Boolean checkIsDuplicateByKey(final NamedEntity existingType) {
if (existingType != null) {
if (existingType instanceof DistributionSetType) {
uiNotification.displayValidationError(i18n.get("message.type.key.duplicate.check",
new Object[] { ((DistributionSetType) existingType).getKey() }));
return Boolean.TRUE;
} else if (existingType instanceof SoftwareModuleType) {
uiNotification.displayValidationError(i18n.get("message.type.key.swmodule.duplicate.check",
new Object[] { ((SoftwareModuleType) existingType).getKey() }));
return Boolean.TRUE;
}
}
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
protected void save(final ClickEvent event) {
// is implemented in the inherited class
}
@Override
protected void populateTagNameCombo() {
// is implemented in the inherited class
}
@Override
protected void setTagDetails(final String tagSelected) {
// is implemented in the inherited class
}
}

View File

@@ -22,10 +22,10 @@ import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.TenantMetaData;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.common.DistributionSetTypeBeanQuery;
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.management.event.DistributionTableEvent;
import org.eclipse.hawkbit.ui.management.event.DragEvent;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
@@ -47,21 +47,17 @@ 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.server.FontAwesome;
import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.FormLayout;
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.Window;
import com.vaadin.ui.themes.ValoTheme;
/**
@@ -70,7 +66,7 @@ import com.vaadin.ui.themes.ValoTheme;
*/
@SpringComponent
@ViewScope
public class DistributionAddUpdateWindowLayout extends VerticalLayout {
public class DistributionAddUpdateWindowLayout extends CustomComponent {
private static final long serialVersionUID = -5602182034230568435L;
@@ -94,8 +90,6 @@ public class DistributionAddUpdateWindowLayout extends VerticalLayout {
@Autowired
private transient EntityFactory entityFactory;
private Button saveDistributionBtn;
private Button discardDistributionBtn;
private TextField distNameTextField;
private TextField distVersionTextField;
private Label madatoryLabel;
@@ -104,7 +98,7 @@ public class DistributionAddUpdateWindowLayout extends VerticalLayout {
private ComboBox distsetTypeNameComboBox;
private boolean editDistribution = Boolean.FALSE;
private Long editDistId;
private Window addDistributionWindow;
private CommonDialogWindow addDistributionWindow;
private String originalDistName;
private String originalDistVersion;
private String originalDistDescription;
@@ -117,6 +111,8 @@ public class DistributionAddUpdateWindowLayout extends VerticalLayout {
private TextChangeListener distVersionTextFieldListener;
private ValueChangeListener distsetTypeNameComboBoxListener;
private FormLayout formLayout;
/**
* Initialize Distribution Add and Edit Window.
*/
@@ -127,53 +123,51 @@ public class DistributionAddUpdateWindowLayout extends VerticalLayout {
}
private void buildLayout() {
/* action button layout ( save & discard ) */
final HorizontalLayout buttonsLayout = new HorizontalLayout();
buttonsLayout.setSizeFull();
buttonsLayout.setStyleName("dist-buttons-horz-layout");
buttonsLayout.addComponents(saveDistributionBtn, discardDistributionBtn);
buttonsLayout.setComponentAlignment(saveDistributionBtn, Alignment.BOTTOM_LEFT);
buttonsLayout.setComponentAlignment(discardDistributionBtn, Alignment.BOTTOM_RIGHT);
buttonsLayout.addStyleName("window-style");
/*
* The main layout of the window contains mandatory info, textboxes
* (controller Id, name & description) and action buttons layout
*/
setSpacing(Boolean.TRUE);
addStyleName("lay-color");
setSizeUndefined();
addComponents(madatoryLabel, distsetTypeNameComboBox, distNameTextField, distVersionTextField, descTextArea,
reqMigStepCheckbox);
addComponent(buttonsLayout);
setComponentAlignment(madatoryLabel, Alignment.MIDDLE_LEFT);
formLayout = new FormLayout();
formLayout.addComponent(madatoryLabel);
formLayout.addComponent(distsetTypeNameComboBox);
formLayout.addComponent(distNameTextField);
formLayout.addComponent(distVersionTextField);
formLayout.addComponent(descTextArea);
formLayout.addComponent(reqMigStepCheckbox);
setCompositionRoot(formLayout);
distNameTextField.focus();
}
/**
* Create required UI components.
*/
private void createRequiredComponents() {
distNameTextField = SPUIComponentProvider.getTextField("", ValoTheme.TEXTFIELD_TINY, true, null,
i18n.get("textfield.name"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
distNameTextField = SPUIComponentProvider.getTextField(i18n.get("textfield.name"), "", ValoTheme.TEXTFIELD_TINY,
true, null, i18n.get("textfield.name"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
distNameTextField.setId(SPUIComponentIdProvider.DIST_ADD_NAME);
distNameTextField.setNullRepresentation("");
distVersionTextField = SPUIComponentProvider.getTextField("", ValoTheme.TEXTFIELD_TINY, true, null,
i18n.get("textfield.version"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
distVersionTextField = SPUIComponentProvider.getTextField(i18n.get("textfield.version"), "",
ValoTheme.TEXTFIELD_TINY, true, null, i18n.get("textfield.version"), true,
SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
distVersionTextField.setId(SPUIComponentIdProvider.DIST_ADD_VERSION);
distVersionTextField.setNullRepresentation("");
distsetTypeNameComboBox = SPUIComponentProvider.getComboBox("", "", null, "", false, "",
i18n.get("label.combobox.type"));
distsetTypeNameComboBox = SPUIComponentProvider.getComboBox(i18n.get("label.combobox.type"), "", "", null, "",
false, "", i18n.get("label.combobox.type"));
distsetTypeNameComboBox.setImmediate(true);
distsetTypeNameComboBox.setNullSelectionAllowed(false);
distsetTypeNameComboBox.setId(SPUIComponentIdProvider.DIST_ADD_DISTSETTYPE);
descTextArea = SPUIComponentProvider.getTextArea("text-area-style", ValoTheme.TEXTAREA_TINY, false, null,
i18n.get("textfield.description"), SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
descTextArea = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "text-area-style",
ValoTheme.TEXTAREA_TINY, false, null, i18n.get("textfield.description"),
SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
descTextArea.setId(SPUIComponentIdProvider.DIST_ADD_DESC);
descTextArea.setNullRepresentation("");
@@ -185,16 +179,6 @@ public class DistributionAddUpdateWindowLayout extends VerticalLayout {
"dist-checkbox-style", null, false, "");
reqMigStepCheckbox.addStyleName(ValoTheme.CHECKBOX_SMALL);
reqMigStepCheckbox.setId(SPUIComponentIdProvider.DIST_ADD_MIGRATION_CHECK);
/* save or update button */
saveDistributionBtn = SPUIComponentProvider.getButton(SPUIComponentIdProvider.DIST_ADD_SAVE, "", "", "", true,
FontAwesome.SAVE, SPUIButtonStyleSmallNoBorder.class);
saveDistributionBtn.addClickListener(event -> saveDistribution());
/* close button */
discardDistributionBtn = SPUIComponentProvider.getButton(SPUIComponentIdProvider.DIST_ADD_DISCARD, "", "", "",
true, FontAwesome.TIMES, SPUIButtonStyleSmallNoBorder.class);
discardDistributionBtn.addClickListener(event -> discardDistribution());
}
/**
@@ -217,7 +201,7 @@ public class DistributionAddUpdateWindowLayout extends VerticalLayout {
}
private void enableSaveButton() {
saveDistributionBtn.setEnabled(true);
addDistributionWindow.setSaveButtonEnabled(true);
}
private DistributionSetType getDefaultDistributionSetType() {
@@ -226,7 +210,7 @@ public class DistributionAddUpdateWindowLayout extends VerticalLayout {
}
private void disableSaveButton() {
saveDistributionBtn.setEnabled(false);
addDistributionWindow.setSaveButtonEnabled(false);
}
private void saveDistribution() {
@@ -414,7 +398,9 @@ public class DistributionAddUpdateWindowLayout extends VerticalLayout {
distsetTypeNameComboBox.removeStyleName(SPUIStyleDefinitions.SP_COMBOFIELD_ERROR);
descTextArea.clear();
reqMigStepCheckbox.clear();
saveDistributionBtn.setEnabled(true);
if (addDistributionWindow != null) {
addDistributionWindow.setSaveButtonEnabled(true);
}
removeListeners();
changedComponents.clear();
}
@@ -496,7 +482,7 @@ public class DistributionAddUpdateWindowLayout extends VerticalLayout {
public void populateValuesOfDistribution(final Long editDistId) {
this.editDistId = editDistId;
editDistribution = Boolean.TRUE;
saveDistributionBtn.setEnabled(false);
addDistributionWindow.setSaveButtonEnabled(false);
final DistributionSet distSet = distributionSetManagement.findDistributionSetByIdWithDetails(editDistId);
if (distSet != null) {
distNameTextField.setValue(distSet.getName());
@@ -518,13 +504,15 @@ public class DistributionAddUpdateWindowLayout extends VerticalLayout {
}
}
public Window getWindow() {
public CommonDialogWindow getWindow() {
eventBus.publish(this, DragEvent.HIDE_DROP_HINT);
populateRequiredComponents();
resetComponents();
addDistributionWindow = SPUIComponentProvider.getWindow(i18n.get("caption.add.new.dist"), null,
SPUIDefinitions.CREATE_UPDATE_WINDOW);
addDistributionWindow.setContent(this);
SPUIDefinitions.CREATE_UPDATE_WINDOW, this, event -> saveDistribution(), event -> discardDistribution(),
null);
addDistributionWindow.getButtonsLayout().removeStyleName("actionButtonsMargin");
return addDistributionWindow;
}
@@ -544,4 +532,5 @@ public class DistributionAddUpdateWindowLayout extends VerticalLayout {
public void setOriginalDistSetTYpe(final String originalDistSetType) {
this.originalDistSetType = originalDistSetType;
}
}

View File

@@ -8,7 +8,8 @@
*/
package org.eclipse.hawkbit.ui.management.dstag;
import java.util.ArrayList;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
import java.util.List;
import org.eclipse.hawkbit.repository.EntityFactory;
@@ -16,276 +17,37 @@ import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetTagCreatedBu
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetTagDeletedEvent;
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetTagUpdateEvent;
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.management.tag.CreateUpdateTagLayout;
import org.eclipse.hawkbit.ui.management.tag.SpColorPickerPreview;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerConstants;
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper;
import org.eclipse.hawkbit.ui.layouts.AbstractCreateUpdateTagLayout;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.spring.events.EventScope;
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
import com.google.common.base.Strings;
import com.vaadin.shared.ui.colorpicker.Color;
import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.VaadinSessionScope;
import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.OptionGroup;
import com.vaadin.ui.UI;
import com.vaadin.ui.Window;
import com.vaadin.ui.themes.ValoTheme;
/**
*
*
* Class for Create/Update Tag Layout of distribution set
*
*/
@SpringComponent
@VaadinSessionScope
public class CreateUpdateDistributionTagLayoutWindow extends CreateUpdateTagLayout {
private static final long serialVersionUID = 444276149954167545L;
@ViewScope
public class CreateUpdateDistributionTagLayoutWindow extends AbstractCreateUpdateTagLayout {
@Autowired
private transient UINotification uiNotification;
private static final long serialVersionUID = 444276149954167545L;
@Autowired
private transient EntityFactory entityFactory;
private static final String MISSING_TAG_NAME = "message.error.missing.tagname";
private static final String TARGET_TAG_NAME_DYNAMIC_STYLE = "new-target-tag-name";
private static final String MSG_TEXTFIELD_NAME = "textfield.name";
private Window distTagWindow;
public Window getWindow() {
reset();
distTagWindow = SPUIComponentProvider.getWindow(i18n.get("caption.add.tag"), null,
SPUIDefinitions.CREATE_UPDATE_WINDOW);
distTagWindow.setContent(this);
return distTagWindow;
}
@Override
protected void populateTagNameCombo() {
tagNameComboBox.removeAllItems();
final List<DistributionSetTag> distTagNameList = tagManagement.findAllDistributionSetTags();
distTagNameList.forEach(value -> tagNameComboBox.addItem(value.getName()));
}
/**
* Update DistributionTag.
*/
@Override
public void save(final ClickEvent event) {
if (mandatoryValuesPresent()) {
final DistributionSetTag existingDistTag = tagManagement.findDistributionSetTag(tagName.getValue());
if (optiongroup.getValue().equals(createTagNw)) {
if (!checkIsDuplicate(existingDistTag)) {
crateNewTag();
}
} else {
updateTag(existingDistTag);
}
}
}
/**
* Create new tag.
*/
private void crateNewTag() {
final String colorPicked = getColorPickedSting();
final String tagNameValue = HawkbitCommonUtil.trimAndNullIfEmpty(tagName.getValue());
final String tagDescValue = HawkbitCommonUtil.trimAndNullIfEmpty(tagDesc.getValue());
if (null != tagNameValue) {
DistributionSetTag newDistTag = entityFactory.generateDistributionSetTag(tagNameValue, tagDescValue,
new Color(0, 146, 58).getCSS());
if (colorPicked != null) {
newDistTag.setColour(colorPicked);
}
newDistTag = tagManagement.createDistributionSetTag(newDistTag);
uiNotification.displaySuccess(i18n.get("message.save.success", new Object[] { newDistTag.getName() }));
resetDistTagValues();
} else {
uiNotification.displayValidationError(i18n.get(MISSING_TAG_NAME));
}
}
/**
* update tag.
*/
private void updateTag(final DistributionSetTag distObj) {
final String nameUpdateValue = HawkbitCommonUtil.trimAndNullIfEmpty(tagName.getValue());
final String descUpdateValue = HawkbitCommonUtil.trimAndNullIfEmpty(tagDesc.getValue());
if (null != nameUpdateValue) {
distObj.setName(nameUpdateValue);
distObj.setDescription(null != descUpdateValue ? descUpdateValue : null);
// update target tag with color selected
distObj.setColour(getColorPickedSting());
tagManagement.updateDistributionSetTag(distObj);
uiNotification.displaySuccess(i18n.get("message.update.success", new Object[] { distObj.getName() }));
closeWindow();
} else {
uiNotification.displayValidationError(i18n.get("message.tag.update.mandatory"));
}
}
private void closeWindow() {
distTagWindow.close();
UI.getCurrent().removeWindow(distTagWindow);
}
/**
* RESET.
*
* @param event
*/
@Override
public void discard(final ClickEvent event) {
distTagWindow.setVisible(false);
UI.getCurrent().removeWindow(distTagWindow);
resetDistTagValues();
}
/**
* Get color picked value in string.
*
* @return String of color picked value.
*/
private String getColorPickedSting() {
return "rgb(" + getSelPreview().getColor().getRed() + "," + getSelPreview().getColor().getGreen() + ","
+ getSelPreview().getColor().getBlue() + ")";
}
/**
* Color view.
*
* @return ColorPickerPreview as UI
*/
public SpColorPickerPreview getSelPreview() {
return selPreview;
}
/**
* RESET.
*/
private void resetDistTagValues() {
tagName.removeStyleName(TARGET_TAG_NAME_DYNAMIC_STYLE);
tagName.addStyleName(SPUIDefinitions.NEW_TARGET_TAG_NAME);
tagName.setValue("");
tagName.setInputPrompt(i18n.get(MSG_TEXTFIELD_NAME));
setColor(new Color(0, 146, 58));
distTagWindow.setVisible(false);
tagPreviewBtnClicked = false;
UI.getCurrent().removeWindow(distTagWindow);
}
/*
* (non-Javadoc)
*
* @see hawkbit.server.ui.management.CreateUpdateTagLayout#createOptionGroup
* ()
*/
@Override
protected void createOptionGroup() {
final List<String> optionValues = new ArrayList<>();
if (permChecker.hasCreateDistributionPermission()) {
optionValues.add(createTag.getValue());
}
if (permChecker.hasUpdateDistributionPermission()) {
optionValues.add(updateTag.getValue());
}
createOptionGroup(optionValues);
}
private void createOptionGroup(final List<String> tagOptions) {
optiongroup = new OptionGroup("", tagOptions);
optiongroup.addStyleName(ValoTheme.OPTIONGROUP_SMALL);
optiongroup.addStyleName("custom-option-group");
optiongroup.setNullSelectionAllowed(false);
if (!tagOptions.isEmpty()) {
optiongroup.select(tagOptions.get(0));
}
}
/**
*
* @return
*/
private Boolean mandatoryValuesPresent() {
if (Strings.isNullOrEmpty(tagName.getValue())) {
if (optiongroup.getValue().equals(createTagNw)) {
uiNotification.displayValidationError(SPUILabelDefinitions.MISSING_TAG_NAME);
}
if (optiongroup.getValue().equals(updateTagNw)) {
if (null == tagNameComboBox.getValue()) {
uiNotification.displayValidationError(i18n.get("message.error.missing.tagname"));
} else {
uiNotification.displayValidationError(SPUILabelDefinitions.MISSING_TAG_NAME);
}
}
return Boolean.FALSE;
}
return Boolean.TRUE;
}
/**
* Select tag & set tag name & tag desc values corresponding to selected
* tag.
*
* @param targetTagSelected
* as the selected tag from combo
*/
@Override
public void setTagDetails(final String distTagSelected) {
tagName.setValue(distTagSelected);
final DistributionSetTag selectedDistTag = tagManagement.findDistributionSetTag(distTagSelected);
if (null != selectedDistTag) {
tagDesc.setValue(selectedDistTag.getDescription());
if (null == selectedDistTag.getColour()) {
selectedColor = new Color(44, 151, 32);
selPreview.setColor(selectedColor);
colorSelect.setColor(selectedColor);
createDynamicStyleForComponents(tagName, tagDesc, DEFAULT_COLOR);
getPreviewButtonColor(DEFAULT_COLOR);
} else {
selectedColor = rgbToColorConverter(selectedDistTag.getColour());
selPreview.setColor(selectedColor);
colorSelect.setColor(selectedColor);
createDynamicStyleForComponents(tagName, tagDesc, selectedDistTag.getColour());
getPreviewButtonColor(selectedDistTag.getColour());
}
}
}
/**
* Checking Tag already existed or not.
*
* @param existingDistTag
* @return
*/
private Boolean checkIsDuplicate(final DistributionSetTag existingDistTag) {
if (existingDistTag != null) {
uiNotification.displayValidationError(
i18n.get("message.tag.duplicate.check", new Object[] { existingDistTag.getName() }));
return Boolean.TRUE;
}
return Boolean.FALSE;
}
@EventBusListenerMethod(scope = EventScope.SESSION)
// Exception squid:S1172 - event not needed
@SuppressWarnings({ "squid:S1172" })
@@ -307,4 +69,116 @@ public class CreateUpdateDistributionTagLayoutWindow extends CreateUpdateTagLayo
populateTagNameCombo();
}
@Override
protected void populateTagNameCombo() {
tagNameComboBox.removeAllItems();
final List<DistributionSetTag> distTagNameList = tagManagement.findAllDistributionSetTags();
distTagNameList.forEach(value -> tagNameComboBox.addItem(value.getName()));
}
@Override
protected void addListeners() {
super.addListeners();
optiongroup.addValueChangeListener(this::optionValueChanged);
}
/**
* Update DistributionTag.
*/
@Override
public void save(final ClickEvent event) {
if (mandatoryValuesPresent()) {
final DistributionSetTag existingDistTag = tagManagement.findDistributionSetTag(tagName.getValue());
if (optiongroup.getValue().equals(createTagStr)) {
if (!checkIsDuplicate(existingDistTag)) {
createNewTag();
}
} else {
updateExistingTag(existingDistTag);
}
}
}
/**
* Create new tag.
*/
@Override
protected void createNewTag() {
super.createNewTag();
if (isNotEmpty(getTagNameValue())) {
DistributionSetTag newDistTag = entityFactory.generateDistributionSetTag(tagNameValue, tagDescValue,
ColorPickerConstants.START_COLOR.getCSS());
if (isNotEmpty(getColorPicked())) {
newDistTag.setColour(getColorPicked());
}
newDistTag = tagManagement.createDistributionSetTag(newDistTag);
displaySuccess(newDistTag.getName());
resetDistTagValues();
} else {
displayValidationError(i18n.get(SPUILabelDefinitions.MISSING_TAG_NAME));
}
}
/**
* RESET.
*
* @param event
*/
@Override
public void discard(final ClickEvent event) {
super.discard(event);
resetDistTagValues();
}
/**
* RESET.
*/
private void resetDistTagValues() {
tagName.removeStyleName(TARGET_TAG_NAME_DYNAMIC_STYLE);
tagName.addStyleName(SPUIDefinitions.NEW_TARGET_TAG_NAME);
tagName.setValue("");
tagName.setInputPrompt(i18n.get(MSG_TEXTFIELD_NAME));
setColor(ColorPickerConstants.START_COLOR);
getWindow().setVisible(false);
tagPreviewBtnClicked = false;
UI.getCurrent().removeWindow(getWindow());
}
/**
* Select tag & set tag name & tag desc values corresponding to selected
* tag.
*
* @param distTagSelected
* as the selected tag from combo
*/
@Override
public void setTagDetails(final String distTagSelected) {
tagName.setValue(distTagSelected);
final DistributionSetTag selectedDistTag = tagManagement.findDistributionSetTag(distTagSelected);
if (null != selectedDistTag) {
tagDesc.setValue(selectedDistTag.getDescription());
if (null == selectedDistTag.getColour()) {
setTagColor(getColorPickerLayout().getDefaultColor(), ColorPickerConstants.DEFAULT_COLOR);
} else {
setTagColor(ColorPickerHelper.rgbToColorConverter(selectedDistTag.getColour()),
selectedDistTag.getColour());
}
}
}
@Override
protected void createRequiredComponents() {
super.createRequiredComponents();
createOptionGroup(permChecker.hasCreateDistributionPermission(), permChecker.hasUpdateDistributionPermission());
}
@Override
protected void reset() {
super.reset();
setOptionGroupDefaultValue(permChecker.hasCreateDistributionPermission(),
permChecker.hasUpdateDistributionPermission());
}
}

View File

@@ -56,6 +56,7 @@ public class ActionTypeOptionGroupLayout extends HorizontalLayout {
createOptionGroup();
addValueChangeListener();
setStyleName("dist-window-actiontype-horz-layout");
setSizeUndefined();
}
private void addValueChangeListener() {
@@ -127,8 +128,8 @@ public class ActionTypeOptionGroupLayout extends HorizontalLayout {
forcedTimeDateField.setStyleName("dist-window-forcedtime");
final TimeZone tz = SPDateTimeUtil.getBrowserTimeZone();
forcedTimeDateField.setValue(Date.from(LocalDateTime.now().plusWeeks(2)
.atZone(SPDateTimeUtil.getTimeZoneId(tz)).toInstant()));
forcedTimeDateField.setValue(
Date.from(LocalDateTime.now().plusWeeks(2).atZone(SPDateTimeUtil.getTimeZoneId(tz)).toInstant()));
forcedTimeDateField.setImmediate(true);
forcedTimeDateField.setTimeZone(tz);
forcedTimeDateField.setLocale(i18n.getLocale());

View File

@@ -481,8 +481,7 @@ public class ManangementConfirmationWindowLayout extends AbstractConfirmationWin
/*
* On delete of pinned target ,unpin refresh both target table and DS
*/
managementUIState.getDistributionTableFilters().getPinnedTargetId()
.ifPresent(targetId -> unPinDeletedTarget(targetId));
managementUIState.getDistributionTableFilters().getPinnedTargetId().ifPresent(this::unPinDeletedTarget);
eventBus.publish(this, SaveActionWindowEvent.DELETED_TARGETS);
managementUIState.getDeletedTargetList().clear();

View File

@@ -1,587 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.ui.management.tag;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.PreDestroy;
import org.eclipse.hawkbit.repository.SpPermissionChecker;
import org.eclipse.hawkbit.repository.TagManagement;
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.ui.common.CoordinatesToColor;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.spring.events.EventBus;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.server.FontAwesome;
import com.vaadin.server.Page;
import com.vaadin.shared.ui.colorpicker.Color;
import com.vaadin.ui.AbstractColorPicker.Coordinates2Color;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.OptionGroup;
import com.vaadin.ui.Slider;
import com.vaadin.ui.Slider.ValueOutOfBoundsException;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.components.colorpicker.ColorChangeEvent;
import com.vaadin.ui.components.colorpicker.ColorChangeListener;
import com.vaadin.ui.components.colorpicker.ColorPickerGradient;
import com.vaadin.ui.components.colorpicker.ColorSelector;
import com.vaadin.ui.themes.ValoTheme;
/**
* Abstract class for create/update target tag layout.
*/
public abstract class CreateUpdateTagLayout extends CustomComponent implements ColorChangeListener, ColorSelector {
private static final long serialVersionUID = 4229177824620576456L;
private static final Logger LOG = LoggerFactory.getLogger(CreateUpdateTagLayout.class);
protected static final String DEFAULT_COLOR = "rgb(44,151,32)";
private static final String TAG_NAME_DYNAMIC_STYLE = "new-tag-name";
private static final String TAG_DESC_DYNAMIC_STYLE = "new-tag-desc";
private static final String TAG_DYNAMIC_STYLE = "tag-color-preview";
protected String createTagNw;
protected String updateTagNw;
@Autowired
protected I18N i18n;
@Autowired
protected transient TagManagement tagManagement;
@Autowired
protected transient EventBus.SessionEventBus eventBus;
@Autowired
protected SpPermissionChecker permChecker;
/**
* Local Instance of ColorPickerPreview.
*/
protected SpColorPickerPreview selPreview;
protected Label createTag;
protected Label updateTag;
private Label comboLabel;
private Label colorLabel;
private Label madatoryLabel;
protected TextField tagName;
protected TextArea tagDesc;
private Button saveTag;
private Button discardTag;
private Button tagColorPreviewBtn;
protected OptionGroup optiongroup;
protected ComboBox tagNameComboBox;
protected ColorPickerGradient colorSelect;
private Set<ColorSelector> selectors;
protected Color selectedColor;
private Slider redSlider;
private Slider greenSlider;
private Slider blueSlider;
private VerticalLayout comboLayout;
private VerticalLayout sliders;
private VerticalLayout colorPickerLayout;
private HorizontalLayout mainLayout;
private VerticalLayout fieldLayout;
/** RGB color converter. */
private final Coordinates2Color rgbConverter = new CoordinatesToColor();
protected boolean tagPreviewBtnClicked = false;
/**
* Save new tag / update new tag.
*
* @param event
*/
protected abstract void save(final Button.ClickEvent event);
/**
* Discard the changes and close the popup.
*
* @param event
*/
protected abstract void discard(final Button.ClickEvent event);
/**
* create option group with Create tag/Update tag based on permissions.
*/
protected abstract void createOptionGroup();
/**
* Populate target name combo.
*/
protected abstract void populateTagNameCombo();
protected abstract void setTagDetails(final String tagSelected);
/**
* Init the layout.
*/
public void init() {
createRequiredComponents();
addListeners();
buildLayout();
eventBus.subscribe(this);
}
@PreDestroy
void destroy() {
eventBus.unsubscribe(this);
}
private void createRequiredComponents() {
createTagNw = i18n.get("label.create.tag");
updateTagNw = i18n.get("label.update.tag");
createTag = SPUIComponentProvider.getLabel(createTagNw, null);
updateTag = SPUIComponentProvider.getLabel(i18n.get("label.update.tag"), null);
comboLabel = SPUIComponentProvider.getLabel(i18n.get("label.choose.tag"), null);
madatoryLabel = getMandatoryLabel();
colorLabel = SPUIComponentProvider.getLabel(i18n.get("label.choose.tag.color"), null);
colorLabel.addStyleName(SPUIDefinitions.COLOR_LABEL_STYLE);
tagName = SPUIComponentProvider.getTextField("", ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TAG_NAME,
true, "", i18n.get("textfield.name"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
tagName.setId(SPUIDefinitions.NEW_TARGET_TAG_NAME);
tagDesc = SPUIComponentProvider.getTextArea("", ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TAG_DESC,
false, "", i18n.get("textfield.description"), SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
tagDesc.setId(SPUIDefinitions.NEW_TARGET_TAG_DESC);
tagDesc.setImmediate(true);
tagDesc.setNullRepresentation("");
tagNameComboBox = SPUIComponentProvider.getComboBox("", "", null, null, false, "",
i18n.get("label.combobox.tag"));
tagNameComboBox.addStyleName(SPUIDefinitions.FILTER_TYPE_COMBO_STYLE);
tagNameComboBox.setImmediate(true);
saveTag = SPUIComponentProvider.getButton(SPUIDefinitions.NEW_TARGET_TAG_SAVE, "", "", "", true,
FontAwesome.SAVE, SPUIButtonStyleSmallNoBorder.class);
saveTag.addStyleName(ValoTheme.BUTTON_BORDERLESS);
discardTag = SPUIComponentProvider.getButton(SPUIDefinitions.NEW_TARGET_TAG_DISRACD, "", "",
"discard-button-style", true, FontAwesome.TIMES, SPUIButtonStyleSmallNoBorder.class);
discardTag.addStyleName(ValoTheme.BUTTON_BORDERLESS);
tagColorPreviewBtn = new Button();
tagColorPreviewBtn.setId(SPUIComponentIdProvider.TAG_COLOR_PREVIEW_ID);
getPreviewButtonColor(DEFAULT_COLOR);
tagColorPreviewBtn.setStyleName(TAG_DYNAMIC_STYLE);
selectors = new HashSet<>();
selectedColor = new Color(44, 151, 32);
selPreview = new SpColorPickerPreview(selectedColor);
colorSelect = new ColorPickerGradient("rgb-gradient", rgbConverter);
colorSelect.setColor(selectedColor);
colorSelect.setWidth("220px");
redSlider = createRGBSlider("", "red");
greenSlider = createRGBSlider("", "green");
blueSlider = createRGBSlider("", "blue");
setRgbSliderValues(selectedColor);
createOptionGroup();
}
private void buildLayout() {
comboLayout = new VerticalLayout();
sliders = new VerticalLayout();
sliders.addComponents(redSlider, greenSlider, blueSlider);
selectors.add(colorSelect);
colorPickerLayout = new VerticalLayout();
colorPickerLayout.setStyleName("rgb-vertical-layout");
colorPickerLayout.addComponent(selPreview);
colorPickerLayout.addComponent(colorSelect);
fieldLayout = new VerticalLayout();
fieldLayout.setSpacing(false);
fieldLayout.setMargin(false);
fieldLayout.setWidth("100%");
fieldLayout.setHeight(null);
fieldLayout.addComponent(optiongroup);
fieldLayout.addComponent(comboLayout);
fieldLayout.addComponent(madatoryLabel);
fieldLayout.addComponent(tagName);
fieldLayout.addComponent(tagDesc);
final HorizontalLayout colorLabelLayout = new HorizontalLayout();
colorLabelLayout.addComponents(colorLabel, tagColorPreviewBtn);
fieldLayout.addComponent(colorLabelLayout);
final HorizontalLayout buttonLayout = new HorizontalLayout();
buttonLayout.addComponent(saveTag);
buttonLayout.addComponent(discardTag);
buttonLayout.setComponentAlignment(discardTag, Alignment.BOTTOM_RIGHT);
buttonLayout.setComponentAlignment(saveTag, Alignment.BOTTOM_LEFT);
buttonLayout.addStyleName("window-style");
buttonLayout.setWidth("152px");
final VerticalLayout fieldButtonLayout = new VerticalLayout();
fieldButtonLayout.addComponent(fieldLayout);
fieldButtonLayout.addComponent(buttonLayout);
fieldButtonLayout.setComponentAlignment(buttonLayout, Alignment.BOTTOM_CENTER);
mainLayout = new HorizontalLayout();
mainLayout.addComponent(fieldButtonLayout);
setCompositionRoot(mainLayout);
tagName.focus();
}
private void addListeners() {
saveTag.addClickListener(event -> save(event));
discardTag.addClickListener(event -> discard(event));
colorSelect.addColorChangeListener(this);
selPreview.addColorChangeListener(this);
tagColorPreviewBtn.addClickListener(event -> previewButtonClicked());
optiongroup.addValueChangeListener(event -> optionValueChanged(event));
tagNameComboBox.addValueChangeListener(event -> tagNameChosen(event));
slidersValueChangeListeners();
}
/**
* Open color picker on click of preview button. Auto select the color based
* on target tag if already selected.
*/
private void previewButtonClicked() {
if (!tagPreviewBtnClicked) {
setColor();
selPreview.setColor(selectedColor);
fieldLayout.addComponent(sliders);
mainLayout.addComponent(colorPickerLayout);
mainLayout.setComponentAlignment(colorPickerLayout, Alignment.BOTTOM_CENTER);
}
tagPreviewBtnClicked = !tagPreviewBtnClicked;
}
private void setColor() {
final String selectedOption = (String) optiongroup.getValue();
if (selectedOption == null || !selectedOption.equalsIgnoreCase(updateTagNw)) {
return;
}
if (tagNameComboBox.getValue() == null) {
selectedColor = rgbToColorConverter(DEFAULT_COLOR);
return;
}
final TargetTag targetTagSelected = tagManagement.findTargetTag(tagNameComboBox.getValue().toString());
if (targetTagSelected == null) {
final DistributionSetTag distTag = tagManagement
.findDistributionSetTag(tagNameComboBox.getValue().toString());
selectedColor = distTag.getColour() != null ? rgbToColorConverter(distTag.getColour())
: rgbToColorConverter(DEFAULT_COLOR);
} else {
selectedColor = targetTagSelected.getColour() != null ? rgbToColorConverter(targetTagSelected.getColour())
: rgbToColorConverter(DEFAULT_COLOR);
}
}
/**
* Covert RGB code to {@Color}.
*
* @param value
* RGB vale
* @return Color
*/
protected Color rgbToColorConverter(final String value) {
if (!value.startsWith("rgb")) {
return null;
}
// RGB color format rgb/rgba(255,255,255,0.1)
final String[] colors = value.substring(value.indexOf('(') + 1, value.length() - 1).split(",");
final int red = Integer.parseInt(colors[0]);
final int green = Integer.parseInt(colors[1]);
final int blue = Integer.parseInt(colors[2]);
if (colors.length > 3) {
final int alpha = (int) (Double.parseDouble(colors[3]) * 255d);
return new Color(red, green, blue, alpha);
} else {
return new Color(red, green, blue);
}
}
private 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) {
final String tagSelected = (String) event.getProperty().getValue();
if (null != tagSelected) {
setTagDetails(tagSelected);
} else {
resetTagNameField();
}
}
private void resetTagNameField() {
tagName.setEnabled(false);
tagName.clear();
tagDesc.clear();
restoreComponentStyles();
fieldLayout.removeComponent(sliders);
mainLayout.removeComponent(colorPickerLayout);
selectedColor = new Color(44, 151, 32);
selPreview.setColor(selectedColor);
tagPreviewBtnClicked = false;
}
/**
* Listener for option group - Create tag/Update.
*
* @param event
* ValueChangeEvent
*/
private void optionValueChanged(final ValueChangeEvent event) {
if ("Update Tag".equals(event.getProperty().getValue())) {
tagName.clear();
tagDesc.clear();
tagName.setEnabled(false);
populateTagNameCombo();
// show target name combo
comboLayout.addComponent(comboLabel);
comboLayout.addComponent(tagNameComboBox);
} else {
tagName.setEnabled(true);
tagName.clear();
tagDesc.clear();
// hide target name combo
comboLayout.removeComponent(comboLabel);
comboLayout.removeComponent(tagNameComboBox);
}
// close the color picker layout
tagPreviewBtnClicked = false;
// reset the selected color - Set defualt color
restoreComponentStyles();
getPreviewButtonColor(DEFAULT_COLOR);
selPreview.setColor(rgbToColorConverter(DEFAULT_COLOR));
// remove the sliders and color picker layout
fieldLayout.removeComponent(sliders);
mainLayout.removeComponent(colorPickerLayout);
}
/**
* reset the components.
*/
protected void reset() {
tagName.setEnabled(true);
tagName.clear();
tagDesc.clear();
restoreComponentStyles();
// hide target name combo
comboLayout.removeComponent(comboLabel);
comboLayout.removeComponent(tagNameComboBox);
fieldLayout.removeComponent(sliders);
mainLayout.removeComponent(colorPickerLayout);
optiongroup.select(createTagNw);
// Default green color
selectedColor = new Color(44, 151, 32);
selPreview.setColor(selectedColor);
tagPreviewBtnClicked = false;
}
/**
* On change of color in color picker ,change RGB sliders, components border
* color and color of preview button.
*/
@Override
public void colorChanged(final ColorChangeEvent event) {
setColor(event.getColor());
for (final ColorSelector select : selectors) {
if (!event.getSource().equals(select) && select.equals(this) && !select.getColor().equals(selectedColor)) {
select.setColor(selectedColor);
}
}
setRgbSliderValues(selectedColor);
getPreviewButtonColor(event.getColor().getCSS());
createDynamicStyleForComponents(tagName, tagDesc, event.getColor().getCSS());
}
/**
* Dynamic styles for window.
*
* @param top
* int value
* @param marginLeft
* int value
*/
protected void getPreviewButtonColor(final String color) {
Page.getCurrent().getJavaScript().execute(HawkbitCommonUtil.getPreviewButtonColorScript(color));
}
private Slider createRGBSlider(final String caption, final String styleName) {
final Slider slider = new Slider(caption, 0, 255);
slider.setImmediate(true);
slider.setWidth("150px");
slider.addStyleName(styleName);
return slider;
}
private void setRgbSliderValues(final Color color) {
try {
final double redColorValue = color.getRed();
redSlider.setValue(new Double(redColorValue));
final double blueColorValue = color.getBlue();
blueSlider.setValue(new Double(blueColorValue));
final double greenColorValue = color.getGreen();
greenSlider.setValue(new Double(greenColorValue));
} catch (final ValueOutOfBoundsException e) {
LOG.error("Unable to set RGB color value to " + color.getRed() + "," + color.getGreen() + ","
+ color.getBlue(), e);
}
}
/**
* Set tag name and desc field border color based on chosen color.
*
* @param tagName
* @param tagDesc
* @param taregtTagColor
*/
protected void createDynamicStyleForComponents(final TextField tagName, final TextArea tagDesc,
final String taregtTagColor) {
tagName.removeStyleName(SPUIDefinitions.TAG_NAME);
tagDesc.removeStyleName(SPUIDefinitions.TAG_DESC);
getTargetDynamicStyles(taregtTagColor);
tagName.addStyleName(TAG_NAME_DYNAMIC_STYLE);
tagDesc.addStyleName(TAG_DESC_DYNAMIC_STYLE);
}
/**
* reset the tag name and tag description component border color.
*/
private void restoreComponentStyles() {
tagName.removeStyleName(TAG_NAME_DYNAMIC_STYLE);
tagDesc.removeStyleName(TAG_DESC_DYNAMIC_STYLE);
tagName.addStyleName(SPUIDefinitions.TAG_NAME);
tagDesc.addStyleName(SPUIDefinitions.TAG_DESC);
getPreviewButtonColor(DEFAULT_COLOR);
}
/**
* Get target style - Dynamically as per the color picked, cannot be done
* from the static css.
*
* @param colorPickedPreview
*/
private void getTargetDynamicStyles(final String colorPickedPreview) {
Page.getCurrent().getJavaScript()
.execute(HawkbitCommonUtil.changeToNewSelectedPreviewColor(colorPickedPreview));
}
@Override
public Color getColor() {
return null;
}
@Override
public void setColor(final Color color) {
if (color == null) {
return;
}
selectedColor = color;
selPreview.setColor(selectedColor);
final String colorPickedPreview = selPreview.getColor().getCSS();
if (tagName.isEnabled() && null != colorSelect) {
createDynamicStyleForComponents(tagName, tagDesc, colorPickedPreview);
colorSelect.setColor(selPreview.getColor());
}
}
/**
* Value change listeners implementations of sliders.
*/
private void slidersValueChangeListeners() {
redSlider.addValueChangeListener(new ValueChangeListener() {
private static final long serialVersionUID = -8336732888800920839L;
@Override
public void valueChange(final ValueChangeEvent event) {
final double red = (Double) event.getProperty().getValue();
final Color newColor = new Color((int) red, selectedColor.getGreen(), selectedColor.getBlue());
setColorToComponents(newColor);
}
});
greenSlider.addValueChangeListener(new ValueChangeListener() {
private static final long serialVersionUID = 1236358037766775663L;
@Override
public void valueChange(final ValueChangeEvent event) {
final double green = (Double) event.getProperty().getValue();
final Color newColor = new Color(selectedColor.getRed(), (int) green, selectedColor.getBlue());
setColorToComponents(newColor);
}
});
blueSlider.addValueChangeListener(new ValueChangeListener() {
private static final long serialVersionUID = 8466370763686043947L;
@Override
public void valueChange(final ValueChangeEvent event) {
final double blue = (Double) event.getProperty().getValue();
final Color newColor = new Color(selectedColor.getRed(), selectedColor.getGreen(), (int) blue);
setColorToComponents(newColor);
}
});
}
private void setColorToComponents(final Color newColor) {
setColor(newColor);
colorSelect.setColor(newColor);
getPreviewButtonColor(newColor.getCSS());
createDynamicStyleForComponents(tagName, tagDesc, newColor.getCSS());
}
@Override
public void addColorChangeListener(final ColorChangeListener listener) {
}
@Override
public void removeColorChangeListener(final ColorChangeListener listener) {
}
}

View File

@@ -98,7 +98,7 @@ public class BulkUploadHandler extends CustomComponent
final TargetBulkUpdateWindowLayout targetBulkUpdateWindowLayout;
private final EntityFactory entityFactory;
private transient EntityFactory entityFactory;
/**
*

View File

@@ -15,9 +15,9 @@ import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetIdName;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
import org.eclipse.hawkbit.ui.management.event.DragEvent;
import org.eclipse.hawkbit.ui.management.event.TargetTableEvent;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
@@ -33,18 +33,14 @@ import org.vaadin.spring.events.EventBus;
import com.vaadin.event.FieldEvents.TextChangeEvent;
import com.vaadin.event.FieldEvents.TextChangeListener;
import com.vaadin.server.FontAwesome;
import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.VaadinSessionScope;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.FormLayout;
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.Window;
import com.vaadin.ui.themes.ValoTheme;
@@ -73,21 +69,19 @@ public class TargetAddUpdateWindowLayout extends CustomComponent {
@Autowired
private transient EntityFactory entityFactory;
private TextField controllerIDTextField;
private TextField nameTextField;
private TextArea descTextArea;
private Label madatoryLabel;
private Button saveTarget;
private Button discardTarget;
private boolean editTarget = Boolean.FALSE;
private String controllerId;
private VerticalLayout mainLayout;
private Window addTargetWindow;
private FormLayout formLayout;
private CommonDialogWindow window;
private String oldTargetName;
private String oldTargetDesc;
/**
* Initialize the Add Update Window Component for Target.
*/
@@ -98,23 +92,22 @@ public class TargetAddUpdateWindowLayout extends CustomComponent {
buildLayout();
/* register all listeners related to the Window */
addListeners();
setCompositionRoot(mainLayout);
setCompositionRoot(formLayout);
}
private void createRequiredComponents() {
/* Textfield for controller Id */
controllerIDTextField = SPUIComponentProvider.getTextField("", ValoTheme.TEXTFIELD_TINY, true, null,
controllerIDTextField = SPUIComponentProvider.getTextField( i18n.get("prompt.target.id"), "", ValoTheme.TEXTFIELD_TINY, true, null,
i18n.get("prompt.target.id"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
controllerIDTextField.setId(SPUIComponentIdProvider.TARGET_ADD_CONTROLLER_ID);
/* Textfield for target name */
nameTextField = SPUIComponentProvider.getTextField("", ValoTheme.TEXTFIELD_TINY, false, null,
nameTextField = SPUIComponentProvider.getTextField( i18n.get("textfield.name"), "", ValoTheme.TEXTFIELD_TINY, false, null,
i18n.get("textfield.name"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
nameTextField.setId(SPUIComponentIdProvider.TARGET_ADD_NAME);
/* Textarea for target description */
descTextArea = SPUIComponentProvider.getTextArea("text-area-style", ValoTheme.TEXTFIELD_TINY, false, null,
descTextArea = SPUIComponentProvider.getTextArea( i18n.get("textfield.description"), "text-area-style", ValoTheme.TEXTFIELD_TINY, false, null,
i18n.get("textfield.description"), SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
descTextArea.setId(SPUIComponentIdProvider.TARGET_ADD_DESC);
descTextArea.setNullRepresentation(HawkbitCommonUtil.SP_STRING_EMPTY);
@@ -122,48 +115,31 @@ public class TargetAddUpdateWindowLayout extends CustomComponent {
/* Label for mandatory symbol */
madatoryLabel = new Label(i18n.get("label.mandatory.field"));
madatoryLabel.setStyleName(SPUIStyleDefinitions.SP_TEXTFIELD_ERROR + " " + ValoTheme.LABEL_SMALL);
/* save or update button */
saveTarget = SPUIComponentProvider.getButton(SPUIDefinitions.NEW_TARGET_SAVE, "", "", "", true,
FontAwesome.SAVE, SPUIButtonStyleSmallNoBorder.class);
saveTarget.addClickListener(event -> saveTargetListner());
/* close button */
discardTarget = SPUIComponentProvider.getButton(SPUIDefinitions.NEW_TARGET_DISCARD, "", "", "", true,
FontAwesome.TIMES, SPUIButtonStyleSmallNoBorder.class);
discardTarget.addClickListener(event -> discardTargetListner());
}
private void buildLayout() {
/* action button layout (save & dicard) */
final HorizontalLayout buttonsLayout = new HorizontalLayout();
buttonsLayout.setSizeFull();
buttonsLayout.addComponents(saveTarget, discardTarget);
buttonsLayout.setComponentAlignment(saveTarget, Alignment.BOTTOM_LEFT);
buttonsLayout.setComponentAlignment(discardTarget, Alignment.BOTTOM_RIGHT);
buttonsLayout.addStyleName("window-style");
/*
* The main layout of the window contains mandatory info, textboxes
* (controller Id, name & description) and action buttons layout
*/
mainLayout = new VerticalLayout();
mainLayout.setSpacing(Boolean.TRUE);
mainLayout.addStyleName("lay-color");
mainLayout.setSizeUndefined();
mainLayout.addComponent(madatoryLabel);
mainLayout.setComponentAlignment(madatoryLabel, Alignment.MIDDLE_LEFT);
formLayout = new FormLayout();
formLayout.addComponent(madatoryLabel);
formLayout.addComponent(controllerIDTextField);
formLayout.addComponent(nameTextField);
formLayout.addComponent(descTextArea);
if (Boolean.TRUE.equals(editTarget)) {
madatoryLabel.setVisible(Boolean.FALSE);
}
mainLayout.addComponents(madatoryLabel, controllerIDTextField, nameTextField, descTextArea, buttonsLayout);
nameTextField.focus();
controllerIDTextField.focus();
}
private void addListeners() {
addTargetNameChangeListner();
addTargetDescChangeListner();
}
private void addTargetNameChangeListner() {
@@ -177,14 +153,13 @@ public class TargetAddUpdateWindowLayout extends CustomComponent {
@Override
public void textChange(final TextChangeEvent event) {
if (event.getText().equals(oldTargetName) && descTextArea.getValue().equals(oldTargetDesc)) {
saveTarget.setEnabled(false);
window.setSaveButtonEnabled(false);
} else {
saveTarget.setEnabled(true);
window.setSaveButtonEnabled(true);
}
}
});
}
private void addTargetDescChangeListner() {
@@ -198,14 +173,14 @@ public class TargetAddUpdateWindowLayout extends CustomComponent {
@Override
public void textChange(final TextChangeEvent event) {
if (event.getText().equals(oldTargetDesc) && nameTextField.getValue().equals(oldTargetName)) {
saveTarget.setEnabled(false);
window.setSaveButtonEnabled(false);
} else {
saveTarget.setEnabled(true);
window.setSaveButtonEnabled(true);
}
}
});
}
}
/**
* Update the Target if modified.
@@ -268,10 +243,9 @@ public class TargetAddUpdateWindowLayout extends CustomComponent {
public Window getWindow() {
eventBus.publish(this, DragEvent.HIDE_DROP_HINT);
addTargetWindow = SPUIComponentProvider.getWindow(i18n.get("caption.add.new.target"), null,
SPUIDefinitions.CREATE_UPDATE_WINDOW);
addTargetWindow.setContent(this);
return addTargetWindow;
window = SPUIComponentProvider.getWindow(i18n.get("caption.add.new.target"), null,
SPUIDefinitions.CREATE_UPDATE_WINDOW, this, event -> saveTargetListner(), event -> discardTargetListner(), null);
return window;
}
/**
@@ -290,8 +264,8 @@ public class TargetAddUpdateWindowLayout extends CustomComponent {
private void closeThisWindow() {
editTarget = Boolean.FALSE;
addTargetWindow.close();
UI.getCurrent().removeWindow(addTargetWindow);
window.close();
UI.getCurrent().removeWindow(window);
}
private void setTargetValues(final Target target, final String name, final String description) {
@@ -333,19 +307,11 @@ public class TargetAddUpdateWindowLayout extends CustomComponent {
if (target.getDescription() != null) {
descTextArea.setValue(target.getDescription());
}
saveTarget.setEnabled(Boolean.FALSE);
window.setSaveButtonEnabled(Boolean.FALSE);
oldTargetDesc = descTextArea.getValue();
oldTargetName = nameTextField.getValue();
addTargetWindow.addStyleName("target-update-window");
}
public VerticalLayout getMainLayout() {
return mainLayout;
}
public void setMainLayout(final VerticalLayout mainLayout) {
this.mainLayout = mainLayout;
window.addStyleName("target-update-window");
}
}

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