Implement target type CRUD UI operations (#1184)

* implement target type CRUD UI operations

Signed-off-by: Virginijus Kandrotas <Virginijus.Kandrotas@bosch.io>

* fix licenses

Signed-off-by: Virginijus Kandrotas <Virginijus.Kandrotas@bosch.io>

* code clean up

Signed-off-by: Virginijus Kandrotas <Virginijus.Kandrotas@bosch.io>

* code clean up

Signed-off-by: Virginijus Kandrotas <Virginijus.Kandrotas@bosch.io>

* refactor proxy target type

Signed-off-by: Virginijus Kandrotas <Virginijus.Kandrotas@bosch.io>

* refactor proxy target type

Signed-off-by: Virginijus Kandrotas <Virginijus.Kandrotas@bosch.io>

* fix review comments

Signed-off-by: Virginijus Kandrotas <Virginijus.Kandrotas@bosch.io>

* fix review comments

Signed-off-by: Virginijus Kandrotas <Virginijus.Kandrotas@bosch.io>

* fix review comments

Signed-off-by: Virginijus Kandrotas <Virginijus.Kandrotas@bosch.io>

* update class description

Signed-off-by: Virginijus Kandrotas <Virginijus.Kandrotas@bosch.io>

* fix review comments

Signed-off-by: Virginijus Kandrotas <Virginijus.Kandrotas@bosch.io>

* fix review comments

Signed-off-by: Virginijus Kandrotas <Virginijus.Kandrotas@bosch.io>

* fix review comments

Signed-off-by: Virginijus Kandrotas <Virginijus.Kandrotas@bosch.io>

* fix sonar issue

Signed-off-by: Virginijus Kandrotas <Virginijus.Kandrotas@bosch.io>

* fix sonar issue

Signed-off-by: Virginijus Kandrotas <Virginijus.Kandrotas@bosch.io>

* fix sonar issue

Signed-off-by: Virginijus Kandrotas <Virginijus.Kandrotas@bosch.io>

* fix showing assigned ds types

Signed-off-by: Virginijus Kandrotas <Virginijus.Kandrotas@bosch.io>

* remove unused import

Signed-off-by: Virginijus Kandrotas <Virginijus.Kandrotas@bosch.io>
This commit is contained in:
Virginijus Kandrotas
2021-10-21 15:18:39 +02:00
committed by GitHub
parent d5661d2fe2
commit d80d0d6349
35 changed files with 1410 additions and 62 deletions

View File

@@ -12,12 +12,10 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import javax.validation.ConstraintViolationException; import javax.validation.ConstraintViolationException;
import javax.validation.Valid; import javax.validation.Valid;
import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.builder.TargetCreate; import org.eclipse.hawkbit.repository.builder.TargetCreate;
import org.eclipse.hawkbit.repository.builder.TargetUpdate; import org.eclipse.hawkbit.repository.builder.TargetUpdate;

View File

@@ -10,12 +10,8 @@ package org.eclipse.hawkbit.repository.builder;
import java.net.URI; import java.net.URI;
import java.util.Optional; import java.util.Optional;
import org.eclipse.hawkbit.repository.TargetTypeManagement;
import org.eclipse.hawkbit.repository.ValidString; import org.eclipse.hawkbit.repository.ValidString;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.InvalidTargetAddressException; import org.eclipse.hawkbit.repository.exception.InvalidTargetAddressException;
import org.eclipse.hawkbit.repository.model.TargetType;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;

View File

@@ -18,7 +18,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.CriteriaQuery;
@@ -26,7 +25,6 @@ import javax.persistence.criteria.Expression;
import javax.persistence.criteria.MapJoin; import javax.persistence.criteria.MapJoin;
import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root; import javax.persistence.criteria.Root;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.FilterParams; import org.eclipse.hawkbit.repository.FilterParams;
import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.QuotaManagement;

View File

@@ -263,4 +263,5 @@ public class JpaTargetTypeManagement implements TargetTypeManagement {
private static Page<TargetType> convertPage(final Page<JpaTargetType> findAll, final Pageable pageable) { private static Page<TargetType> convertPage(final Page<JpaTargetType> findAll, final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements()); return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
} }
} }

View File

@@ -8,15 +8,14 @@
*/ */
package org.eclipse.hawkbit.rest.exception; package org.eclipse.hawkbit.rest.exception;
import com.google.common.collect.Iterables;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException; import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException; import javax.validation.ValidationException;
import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.commons.lang3.exception.ExceptionUtils;
import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.exception.SpServerError;
@@ -32,8 +31,6 @@ import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.multipart.MultipartException; import org.springframework.web.multipart.MultipartException;
import com.google.common.collect.Iterables;
/** /**
* General controller advice for exception handling. * General controller advice for exception handling.
*/ */

View File

@@ -0,0 +1,34 @@
/**
* Copyright (c) 2021 Bosch.IO 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.data.mappers;
import org.eclipse.hawkbit.repository.model.TargetType;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTargetType;
/**
* Maps {@link TargetType} entities, fetched from backend, to the {@link ProxyTargetType}
* entities.
*
* @param <T>
* Generic type of TargetType
*/
public class TargetTypeToProxyTargetTypeMapper<T extends TargetType> extends AbstractNamedEntityToProxyNamedEntityMapper<ProxyTargetType, T> {
@Override
public ProxyTargetType map(final T targetType) {
final ProxyTargetType proxyTargetType = new ProxyTargetType();
mapNamedEntityAttributes(targetType, proxyTargetType);
proxyTargetType.setColour(targetType.getColour());
return proxyTargetType;
}
}

View File

@@ -0,0 +1,100 @@
/**
* Copyright (c) 2021 Bosch.IO 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.data.proxies;
import com.google.common.base.MoreObjects;
import java.util.Set;
import org.eclipse.hawkbit.repository.model.TargetType;
import java.util.Objects;
/**
* Proxy for {@link TargetType}.
*/
public class ProxyTargetType extends ProxyFilterButton {
private static final long serialVersionUID = 1L;
private boolean isNoTargetType;
private Set<ProxyType> selectedDsTypes;
/**
* Constructor
*/
public ProxyTargetType() {
}
/**
* Constructor for ProxyTargetType
*
* @param id
* Type id
* @param name
* Type name
* @param colour
* Type colour
*/
public ProxyTargetType(final Long id, final String name, final String colour) {
setId(id);
setName(name);
setColour(colour);
}
public boolean isNoTargetType() {
return isNoTargetType;
}
public void setNoTargetType(boolean noTargetType) {
isNoTargetType = noTargetType;
}
/**
* Gets the selected distribution sets types
*
* @return selectedDsTypes
*/
public Set<ProxyType> getSelectedDsTypes() {
return selectedDsTypes;
}
/**
* Sets the selectedDsTypes
*
* @param selectedDsTypes
* Selected distribution sets types
*/
public void setSelectedDsTypes(final Set<ProxyType> selectedDsTypes) {
this.selectedDsTypes = selectedDsTypes;
}
@Override
public boolean equals(final Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final ProxyTargetType other = (ProxyTargetType) obj;
return Objects.equals(this.getId(), other.getId()) && Objects.equals(this.getName(), other.getName())
&& Objects.equals(this.getColour(), other.getColour());
}
@Override
public int hashCode() {
return Objects.hash(getId(), getName(), getColour());
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this).add("id", getId()).add("name", getName()).add("color", getColour())
.toString();
}
}

View File

@@ -12,5 +12,5 @@ package org.eclipse.hawkbit.ui.common.event;
* Enum constants for filter type * Enum constants for filter type
*/ */
public enum FilterType { public enum FilterType {
SEARCH, TYPE, TAG, NO_TAG, STATUS, OVERDUE, QUERY, DISTRIBUTION, MASTER; SEARCH, TYPE, TARGET_TYPE, TAG, NO_TAG, STATUS, OVERDUE, QUERY, DISTRIBUTION, MASTER;
} }

View File

@@ -12,5 +12,5 @@ package org.eclipse.hawkbit.ui.common.event;
* Enum constants for target filter tab change event * Enum constants for target filter tab change event
*/ */
public enum TargetFilterTabChangedEventPayload { public enum TargetFilterTabChangedEventPayload {
SIMPLE, CUSTOM; SIMPLE, CUSTOM, TARGET_TYPE;
} }

View File

@@ -8,11 +8,13 @@
*/ */
package org.eclipse.hawkbit.ui.common.filterlayout; package org.eclipse.hawkbit.ui.common.filterlayout;
import com.vaadin.ui.Button;
import com.vaadin.ui.UI;
import com.vaadin.ui.Window;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.eclipse.hawkbit.ui.common.CommonUiDependencies; import org.eclipse.hawkbit.ui.common.CommonUiDependencies;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyIdentifiableEntity; import org.eclipse.hawkbit.ui.common.data.proxies.ProxyIdentifiableEntity;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTag; import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTag;
@@ -32,10 +34,6 @@ import org.eclipse.hawkbit.ui.utils.UIMessageIdProvider;
import org.eclipse.hawkbit.ui.utils.UINotification; import org.eclipse.hawkbit.ui.utils.UINotification;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import com.vaadin.ui.Button;
import com.vaadin.ui.UI;
import com.vaadin.ui.Window;
/** /**
* Class for defining the tag filter buttons. * Class for defining the tag filter buttons.
*/ */

View File

@@ -0,0 +1,156 @@
/**
* Copyright (c) 2021 Bosch.IO 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.filterlayout;
import com.vaadin.ui.Button;
import java.util.Collection;
import java.util.Map;
import org.eclipse.hawkbit.ui.common.CommonUiDependencies;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyIdentifiableEntity;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTarget;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTargetType;
import org.eclipse.hawkbit.ui.common.event.EventTopics;
import org.eclipse.hawkbit.ui.common.event.EventView;
import org.eclipse.hawkbit.ui.common.event.FilterChangedEventPayload;
import org.eclipse.hawkbit.ui.common.event.FilterType;
import org.eclipse.hawkbit.ui.common.filterlayout.AbstractFilterButtonClickBehaviour.ClickBehaviourType;
import org.eclipse.hawkbit.ui.common.state.TagFilterLayoutUiState;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUITagButtonStyle;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.UIMessageIdProvider;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.springframework.util.CollectionUtils;
/**
* Class for defining the type filter buttons.
*/
public abstract class AbstractTargetTypeFilterButtons extends AbstractFilterButtons<ProxyTargetType, Void> {
private static final long serialVersionUID = 1L;
private final TagFilterLayoutUiState tagFilterLayoutUiState;
protected final UINotification uiNotification;
private final Button noTargetTypeButton;
private final TargetTypeFilterButtonClick targetTypeFilterButtonClick;
/**
* Constructor for AbstractTargetTypeFilterButtons
*
* @param uiDependencies
* {@link CommonUiDependencies}
* @param tagFilterLayoutUiState
* TagFilterLayoutUiState
*/
protected AbstractTargetTypeFilterButtons(final CommonUiDependencies uiDependencies,
final TagFilterLayoutUiState tagFilterLayoutUiState) {
super(uiDependencies.getEventBus(), uiDependencies.getI18n(), uiDependencies.getUiNotification(),
uiDependencies.getPermChecker());
this.uiNotification = uiDependencies.getUiNotification();
this.tagFilterLayoutUiState = tagFilterLayoutUiState;
this.noTargetTypeButton = buildNoTargetTypeButton();
this.targetTypeFilterButtonClick = new TargetTypeFilterButtonClick(this::onFilterChangedEvent);
}
private Button buildNoTargetTypeButton() {
final Button noTargetType = SPUIComponentProvider.getButton(
getFilterButtonIdPrefix() + "." + SPUIDefinitions.NO_TARGET_TYPE_BUTTON_ID,
i18n.getMessage(UIMessageIdProvider.LABEL_NO_TARGET_TYPE),
i18n.getMessage(UIMessageIdProvider.TOOLTIP_CLICK_TO_FILTER), "button-no-tag", false, null,
SPUITagButtonStyle.class);
final ProxyTargetType proxyTargetType = new ProxyTargetType();
proxyTargetType.setNoTargetType(true);
return noTargetType;
}
@Override
protected TargetTypeFilterButtonClick getFilterButtonClickBehaviour(){
return targetTypeFilterButtonClick;
}
private void onFilterChangedEvent(final ProxyTargetType targetType,
final ClickBehaviourType clickType) {
final Long targetTypeId = ClickBehaviourType.CLICKED == clickType ? targetType.getId()
: null;
publishFilterChangedEvent(targetTypeId);
}
private void publishFilterChangedEvent(final Long targetTypeId) {
eventBus.publish(EventTopics.FILTER_CHANGED, this, new FilterChangedEventPayload<>(ProxyTarget.class,
FilterType.TARGET_TYPE, targetTypeId, EventView.DEPLOYMENT));
}
/**
* Provides type of the master entity.
*
* @return type of the master entity
*/
protected abstract Class<? extends ProxyIdentifiableEntity> getFilterMasterEntityType();
/**
* Provides event view filter.
*
* @return event view filter.
*/
protected abstract EventView getView();
/**
* Target type deletion operation.
*
* @param targetTypeToDelete
* target type to delete
*
* @return true if target type is deleted, in error case false.
*/
protected abstract boolean deleteTargetType(final ProxyTargetType targetTypeToDelete);
/**
* @return Button component of no target type
*/
public Button getNoTargetTypeButton() {
return noTargetTypeButton;
}
@Override
public void restoreState() {
final Map<Long, String> targetTypesToRestore = tagFilterLayoutUiState.getClickedTagIdsWithName();
if (!CollectionUtils.isEmpty(targetTypesToRestore)) {
removeNonExistingTargetTypes(targetTypesToRestore);
}
if (tagFilterLayoutUiState.isNoTagClicked()) {
getNoTargetTypeButton().addStyleName(SPUIStyleDefinitions.SP_NO_TAG_BTN_CLICKED_STYLE);
}
}
private void removeNonExistingTargetTypes(final Map<Long, String> targetTypeIdsWithName) {
final Collection<Long> targetTypeIds = targetTypeIdsWithName.keySet();
final Collection<Long> existingTargetTypeIds = filterExistingTargetTypeIds(targetTypeIds);
if (targetTypeIds.size() != existingTargetTypeIds.size()) {
targetTypeIds.retainAll(existingTargetTypeIds);
}
}
/**
* Filters out non-existant target type by ids.
*
* @param targetTypeIds
* provided target type ids
* @return filtered list of existing target type ids
*/
protected abstract Collection<Long> filterExistingTargetTypeIds(final Collection<Long> targetTypeIds);
}

View File

@@ -0,0 +1,40 @@
/**
* Copyright (c) 2021 Bosch.IO 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.filterlayout;
import java.util.function.BiConsumer;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTargetType;
/**
* Button click behaviour of target type filter buttons layout.
*/
public class TargetTypeFilterButtonClick extends AbstractFilterSingleButtonClick<ProxyTargetType> {
private static final long serialVersionUID = 1L;
private final transient BiConsumer<ProxyTargetType, ClickBehaviourType> filterChangedCallback;
TargetTypeFilterButtonClick(final BiConsumer<ProxyTargetType, ClickBehaviourType> filterChangedCallback) {
this.filterChangedCallback = filterChangedCallback;
}
@Override
protected void filterUnClicked(ProxyTargetType clickedFilter) {
filterChangedCallback.accept(clickedFilter, ClickBehaviourType.UNCLICKED);
}
@Override
protected void filterClicked(ProxyTargetType clickedFilter) {
filterChangedCallback.accept(clickedFilter, ClickBehaviourType.CLICKED);
}
@Override
public boolean isFilterPreviouslyClicked(final ProxyTargetType clickedFilter) {
return false;
}
}

View File

@@ -0,0 +1,49 @@
/**
* Copyright (c) 2021 Bosch.IO 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.targettype;
import java.util.function.BooleanSupplier;
import org.eclipse.hawkbit.ui.common.EntityValidator;
import org.eclipse.hawkbit.ui.common.CommonUiDependencies;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTargetType;
import org.springframework.util.StringUtils;
/**
* Validator used in TargetType window controllers to validate {@link ProxyTargetType}.
*/
public class ProxyTargetTypeValidator extends EntityValidator {
/**
* Constructor
*
* @param uiDependencies
* {@link CommonUiDependencies}
*/
public ProxyTargetTypeValidator(final CommonUiDependencies uiDependencies) {
super(uiDependencies);
}
public boolean isEntityValid(final ProxyTargetType entity, final BooleanSupplier duplicateCheck) {
if (!StringUtils.hasText(entity.getName())) {
displayValidationError("message.error.missing.typename");
return false;
}
if (duplicateCheck.getAsBoolean()) {
final String trimmedName = StringUtils.trimWhitespace(entity.getName());
displayValidationError("message.type.duplicate.check", trimmedName);
return false;
}
return true;
}
}

View File

@@ -8,11 +8,17 @@
*/ */
package org.eclipse.hawkbit.ui.management; package org.eclipse.hawkbit.ui.management;
import com.vaadin.server.Page;
import com.vaadin.server.Page.BrowserWindowResizeEvent;
import com.vaadin.server.Page.BrowserWindowResizeListener;
import com.vaadin.spring.annotation.SpringView;
import com.vaadin.spring.annotation.UIScope;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Layout;
import java.util.Arrays; import java.util.Arrays;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.DeploymentManagement;
import org.eclipse.hawkbit.repository.DistributionSetInvalidationManagement; import org.eclipse.hawkbit.repository.DistributionSetInvalidationManagement;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement;
@@ -52,14 +58,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.vaadin.spring.events.EventBus.UIEventBus; import org.vaadin.spring.events.EventBus.UIEventBus;
import com.vaadin.server.Page;
import com.vaadin.server.Page.BrowserWindowResizeEvent;
import com.vaadin.server.Page.BrowserWindowResizeListener;
import com.vaadin.spring.annotation.SpringView;
import com.vaadin.spring.annotation.UIScope;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Layout;
/** /**
* Target status and deployment management view * Target status and deployment management view
*/ */
@@ -107,8 +105,8 @@ public class DeploymentView extends AbstractEventListenersAwareView implements B
if (permChecker.hasTargetReadPermission()) { if (permChecker.hasTargetReadPermission()) {
this.targetTagFilterLayout = new TargetTagFilterLayout(uiDependencies, managementUIState, this.targetTagFilterLayout = new TargetTagFilterLayout(uiDependencies, managementUIState,
targetFilterQueryManagement, targetTagManagement, targetManagement, targetFilterQueryManagement, targetTypeManagement, targetTagManagement, targetManagement,
managementUIState.getTargetTagFilterLayoutUiState()); managementUIState.getTargetTagFilterLayoutUiState(), distributionSetTypeManagement);
this.targetGridLayout = new TargetGridLayout(uiDependencies, targetManagement, targetTypeManagement, deploymentManagement, this.targetGridLayout = new TargetGridLayout(uiDependencies, targetManagement, targetTypeManagement, deploymentManagement,
uiProperties, targetTagManagement, distributionSetManagement, uiExecutor, configManagement, uiProperties, targetTagManagement, distributionSetManagement, uiExecutor, configManagement,

View File

@@ -46,13 +46,13 @@ public class TargetTagWindowBuilder extends AbstractEntityWindowBuilder<ProxyTag
@Override @Override
public Window getWindowForAdd() { public Window getWindowForAdd() {
return getWindowForNewEntity(new AddTargetTagWindowController(uiDependencies, targetTagManagement, return getWindowForNewEntity(new AddTargetTagWindowController(uiDependencies, targetTagManagement,
new TagWindowLayout<ProxyTag>(uiDependencies))); new TagWindowLayout<>(uiDependencies)));
} }
@Override @Override
public Window getWindowForUpdate(final ProxyTag proxyTag) { public Window getWindowForUpdate(final ProxyTag proxyTag) {
return getWindowForEntity(proxyTag, new UpdateTargetTagWindowController(uiDependencies, targetTagManagement, return getWindowForEntity(proxyTag, new UpdateTargetTagWindowController(uiDependencies, targetTagManagement,
new TagWindowLayout<ProxyTag>(uiDependencies))); new TagWindowLayout<>(uiDependencies)));
} }
} }

View File

@@ -8,16 +8,21 @@
*/ */
package org.eclipse.hawkbit.ui.management.targettag.filter; package org.eclipse.hawkbit.ui.management.targettag.filter;
import com.vaadin.ui.Accordion;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.ValoTheme;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.TargetTagManagement; import org.eclipse.hawkbit.repository.TargetTagManagement;
import org.eclipse.hawkbit.repository.TargetTypeManagement;
import org.eclipse.hawkbit.ui.common.CommonUiDependencies; import org.eclipse.hawkbit.ui.common.CommonUiDependencies;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTag; import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTag;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTarget; import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTarget;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTargetFilterQuery; import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTargetFilterQuery;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTargetType;
import org.eclipse.hawkbit.ui.common.event.EventLayout; import org.eclipse.hawkbit.ui.common.event.EventLayout;
import org.eclipse.hawkbit.ui.common.event.EventLayoutViewAware; import org.eclipse.hawkbit.ui.common.event.EventLayoutViewAware;
import org.eclipse.hawkbit.ui.common.event.EventTopics; import org.eclipse.hawkbit.ui.common.event.EventTopics;
@@ -29,16 +34,12 @@ import org.eclipse.hawkbit.ui.common.layout.listener.GridActionsVisibilityListen
import org.eclipse.hawkbit.ui.common.layout.listener.support.EntityModifiedGenericSupport; import org.eclipse.hawkbit.ui.common.layout.listener.support.EntityModifiedGenericSupport;
import org.eclipse.hawkbit.ui.common.layout.listener.support.EntityModifiedGridRefreshAwareSupport; import org.eclipse.hawkbit.ui.common.layout.listener.support.EntityModifiedGridRefreshAwareSupport;
import org.eclipse.hawkbit.ui.management.targettag.TargetTagWindowBuilder; import org.eclipse.hawkbit.ui.management.targettag.TargetTagWindowBuilder;
import org.eclipse.hawkbit.ui.management.targettag.targettype.TargetTypeWindowBuilder;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions; import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider; import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.vaadin.spring.events.EventBus.UIEventBus; import org.vaadin.spring.events.EventBus.UIEventBus;
import com.vaadin.ui.Accordion;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.ValoTheme;
/** /**
* Target filter tabsheet with 'simple' and 'complex' filter options. * Target filter tabsheet with 'simple' and 'complex' filter options.
*/ */
@@ -51,33 +52,41 @@ public class MultipleTargetFilter extends Accordion {
private final TargetTagFilterLayoutUiState targetTagFilterLayoutUiState; private final TargetTagFilterLayoutUiState targetTagFilterLayoutUiState;
private final VerticalLayout simpleFilterTab; private final VerticalLayout simpleFilterTab;
private final VerticalLayout targetTypeFilterTab;
private final TargetTagFilterButtons filterByButtons; private final TargetTagFilterButtons filterByButtons;
private final TargetTypeFilterButtons targetTypeFilterButtons;
private final FilterByStatusLayout filterByStatusFooter; private final FilterByStatusLayout filterByStatusFooter;
private final TargetFilterQueryButtons customFilterTab; private final TargetFilterQueryButtons customFilterTab;
private final transient GridActionsVisibilityListener gridActionsVisibilityListener; private final transient GridActionsVisibilityListener targetTagGridActionsVisibilityListener;
private final transient GridActionsVisibilityListener targetTypeGridActionsVisibilityListener;
private final transient EntityModifiedListener<ProxyTag> entityTagModifiedListener; private final transient EntityModifiedListener<ProxyTag> entityTagModifiedListener;
private final transient EntityModifiedListener<ProxyTargetFilterQuery> entityFilterQueryModifiedListener; private final transient EntityModifiedListener<ProxyTargetFilterQuery> entityFilterQueryModifiedListener;
private final transient EntityModifiedListener<ProxyTargetType> entityTargetTypeModifiedListener;
MultipleTargetFilter(final CommonUiDependencies uiDependencies, MultipleTargetFilter(final CommonUiDependencies uiDependencies,
final TargetFilterQueryManagement targetFilterQueryManagement, final TargetFilterQueryManagement targetFilterQueryManagement,
final TargetTagManagement targetTagManagement, final TargetManagement targetManagement, final TargetTagManagement targetTagManagement, final TargetManagement targetManagement,
final TargetTagFilterLayoutUiState targetTagFilterLayoutUiState, final TargetTagFilterLayoutUiState targetTagFilterLayoutUiState,
final TargetTagWindowBuilder targetTagWindowBuilder) { final TargetTagWindowBuilder targetTagWindowBuilder, final TargetTypeWindowBuilder targetTypeWindowBuilder, final TargetTypeManagement targetTypeManagement) {
this.i18n = uiDependencies.getI18n(); this.i18n = uiDependencies.getI18n();
this.eventBus = uiDependencies.getEventBus(); this.eventBus = uiDependencies.getEventBus();
this.targetTagFilterLayoutUiState = targetTagFilterLayoutUiState; this.targetTagFilterLayoutUiState = targetTagFilterLayoutUiState;
this.filterByButtons = new TargetTagFilterButtons(uiDependencies, targetTagManagement, targetManagement, this.filterByButtons = new TargetTagFilterButtons(uiDependencies, targetTagManagement, targetManagement,
targetTagFilterLayoutUiState, targetTagWindowBuilder); targetTagFilterLayoutUiState, targetTagWindowBuilder);
this.targetTypeFilterButtons = new TargetTypeFilterButtons(uiDependencies, targetTypeManagement, targetTagFilterLayoutUiState, targetTypeWindowBuilder);
this.filterByStatusFooter = new FilterByStatusLayout(i18n, eventBus, targetTagFilterLayoutUiState); this.filterByStatusFooter = new FilterByStatusLayout(i18n, eventBus, targetTagFilterLayoutUiState);
this.simpleFilterTab = buildSimpleFilterTab(); this.simpleFilterTab = buildSimpleFilterTab();
this.targetTypeFilterTab = buildTargetTypeFilterTab();
this.customFilterTab = new TargetFilterQueryButtons(i18n, eventBus, targetFilterQueryManagement, this.customFilterTab = new TargetFilterQueryButtons(i18n, eventBus, targetFilterQueryManagement,
targetTagFilterLayoutUiState); targetTagFilterLayoutUiState);
final EventLayoutViewAware layoutViewAware = new EventLayoutViewAware(EventLayout.TARGET_TAG_FILTER, final EventLayoutViewAware layoutViewAware = new EventLayoutViewAware(EventLayout.TARGET_TAG_FILTER,
EventView.DEPLOYMENT); EventView.DEPLOYMENT);
this.gridActionsVisibilityListener = new GridActionsVisibilityListener(eventBus, layoutViewAware, this.targetTagGridActionsVisibilityListener = new GridActionsVisibilityListener(eventBus, layoutViewAware,
filterByButtons::hideActionColumns, filterByButtons::showEditColumn, filterByButtons::showDeleteColumn); filterByButtons::hideActionColumns, filterByButtons::showEditColumn, filterByButtons::showDeleteColumn);
this.entityTagModifiedListener = new EntityModifiedListener.Builder<>(eventBus, ProxyTag.class) this.entityTagModifiedListener = new EntityModifiedListener.Builder<>(eventBus, ProxyTag.class)
.parentEntityType(ProxyTarget.class).viewAware(layoutViewAware) .parentEntityType(ProxyTarget.class).viewAware(layoutViewAware)
@@ -86,6 +95,12 @@ public class MultipleTargetFilter extends Accordion {
ProxyTargetFilterQuery.class).viewAware(layoutViewAware) ProxyTargetFilterQuery.class).viewAware(layoutViewAware)
.entityModifiedAwareSupports(getFilterQueryModifiedAwareSupports()).build(); .entityModifiedAwareSupports(getFilterQueryModifiedAwareSupports()).build();
this.targetTypeGridActionsVisibilityListener = new GridActionsVisibilityListener(eventBus, layoutViewAware,
targetTypeFilterButtons::hideActionColumns, targetTypeFilterButtons::showEditColumn, targetTypeFilterButtons::showDeleteColumn);
this.entityTargetTypeModifiedListener = new EntityModifiedListener.Builder<>(eventBus, ProxyTargetType.class)
.parentEntityType(ProxyTarget.class).viewAware(layoutViewAware)
.entityModifiedAwareSupports(getTargetTypeModifiedAwareSupports()).build();
init(); init();
addTabs(); addTabs();
addSelectedTabChangeListener(event -> selectedTabChanged()); addSelectedTabChangeListener(event -> selectedTabChanged());
@@ -119,11 +134,40 @@ public class MultipleTargetFilter extends Accordion {
return simpleTab; return simpleTab;
} }
private VerticalLayout buildTargetTypeFilterTab() {
final VerticalLayout targetTypeTab = new VerticalLayout();
targetTypeTab.setSpacing(false);
targetTypeTab.setMargin(false);
targetTypeTab.setSizeFull();
targetTypeTab.setCaption(i18n.getMessage("caption.filter.type"));
targetTypeTab.addStyleName(SPUIStyleDefinitions.TARGET_TYPE_FILTER_HEADER);
final VerticalLayout targetTypeGridLayout = new VerticalLayout();
targetTypeGridLayout.setSpacing(false);
targetTypeGridLayout.setMargin(false);
targetTypeGridLayout.setSizeFull();
targetTypeGridLayout.setId(UIComponentIdProvider.TARGET_TYPE_DROP_AREA_ID);
targetTypeGridLayout.addComponent(targetTypeFilterButtons.getNoTargetTypeButton());
targetTypeGridLayout.addComponent(targetTypeFilterButtons);
targetTypeGridLayout.setComponentAlignment(targetTypeFilterButtons, Alignment.MIDDLE_CENTER);
targetTypeGridLayout.setExpandRatio(targetTypeFilterButtons, 1.0F);
targetTypeTab.addComponent(targetTypeGridLayout);
targetTypeTab.setExpandRatio(targetTypeGridLayout, 1.0F);
return targetTypeTab;
}
private List<EntityModifiedAwareSupport> getTagModifiedAwareSupports() { private List<EntityModifiedAwareSupport> getTagModifiedAwareSupports() {
return Arrays.asList(EntityModifiedGridRefreshAwareSupport.of(filterByButtons::refreshAll), return Arrays.asList(EntityModifiedGridRefreshAwareSupport.of(filterByButtons::refreshAll),
EntityModifiedGenericSupport.of(null, null, filterByButtons::resetFilterOnTagsDeleted)); EntityModifiedGenericSupport.of(null, null, filterByButtons::resetFilterOnTagsDeleted));
} }
private List<EntityModifiedAwareSupport> getTargetTypeModifiedAwareSupports() {
return Arrays.asList(EntityModifiedGridRefreshAwareSupport.of(targetTypeFilterButtons::refreshAll),
EntityModifiedGenericSupport.of(null, null, null));
}
private List<EntityModifiedAwareSupport> getFilterQueryModifiedAwareSupports() { private List<EntityModifiedAwareSupport> getFilterQueryModifiedAwareSupports() {
return Arrays.asList(EntityModifiedGridRefreshAwareSupport.of(customFilterTab::refreshAll), return Arrays.asList(EntityModifiedGridRefreshAwareSupport.of(customFilterTab::refreshAll),
EntityModifiedGenericSupport.of(null, customFilterTab::reselectFilterOnTfqUpdated, EntityModifiedGenericSupport.of(null, customFilterTab::reselectFilterOnTfqUpdated,
@@ -138,6 +182,7 @@ public class MultipleTargetFilter extends Accordion {
private void addTabs() { private void addTabs() {
addTab(simpleFilterTab).setId(UIComponentIdProvider.SIMPLE_FILTER_ACCORDION_TAB); addTab(simpleFilterTab).setId(UIComponentIdProvider.SIMPLE_FILTER_ACCORDION_TAB);
addTab(customFilterTab).setId(UIComponentIdProvider.CUSTOM_FILTER_ACCORDION_TAB); addTab(customFilterTab).setId(UIComponentIdProvider.CUSTOM_FILTER_ACCORDION_TAB);
addTab(targetTypeFilterTab).setId(UIComponentIdProvider.TARGET_TYPE_FILTER_ACCORDION_TAB);
} }
/** /**
@@ -146,20 +191,30 @@ public class MultipleTargetFilter extends Accordion {
public void selectedTabChanged() { public void selectedTabChanged() {
final String selectedTabId = getTab(getSelectedTab()).getId(); final String selectedTabId = getTab(getSelectedTab()).getId();
if (UIComponentIdProvider.SIMPLE_FILTER_ACCORDION_TAB.equals(selectedTabId)) { if (UIComponentIdProvider.SIMPLE_FILTER_ACCORDION_TAB.equals(selectedTabId)) {
customFilterTab.clearAppliedTargetFilterQuery(); customFilterTab.clearAppliedTargetFilterQuery();
targetTagFilterLayoutUiState.setCustomFilterTabSelected(false); targetTagFilterLayoutUiState.setCustomFilterTabSelected(false);
targetTagFilterLayoutUiState.setTargetTypeFilterTabSelected(false);
eventBus.publish(EventTopics.TARGET_FILTER_TAB_CHANGED, this, TargetFilterTabChangedEventPayload.SIMPLE); eventBus.publish(EventTopics.TARGET_FILTER_TAB_CHANGED, this, TargetFilterTabChangedEventPayload.SIMPLE);
} else { }
if (UIComponentIdProvider.TARGET_TYPE_FILTER_ACCORDION_TAB.equals(selectedTabId)){
targetTagFilterLayoutUiState.setTargetTypeFilterTabSelected(true);
targetTagFilterLayoutUiState.setCustomFilterTabSelected(false);
eventBus.publish(EventTopics.TARGET_FILTER_TAB_CHANGED, this, TargetFilterTabChangedEventPayload.TARGET_TYPE);
}
if (UIComponentIdProvider.CUSTOM_FILTER_ACCORDION_TAB.equals(selectedTabId)){
filterByButtons.clearTargetTagFilters(); filterByButtons.clearTargetTagFilters();
filterByStatusFooter.clearStatusAndOverdueFilters(); filterByStatusFooter.clearStatusAndOverdueFilters();
targetTagFilterLayoutUiState.setCustomFilterTabSelected(true); targetTagFilterLayoutUiState.setCustomFilterTabSelected(true);
targetTagFilterLayoutUiState.setTargetTypeFilterTabSelected(false);
eventBus.publish(EventTopics.TARGET_FILTER_TAB_CHANGED, this, TargetFilterTabChangedEventPayload.CUSTOM); eventBus.publish(EventTopics.TARGET_FILTER_TAB_CHANGED, this, TargetFilterTabChangedEventPayload.CUSTOM);
} }
} }
/** /**
@@ -170,12 +225,19 @@ public class MultipleTargetFilter extends Accordion {
customFilterTab.restoreState(); customFilterTab.restoreState();
setSelectedTab(customFilterTab); setSelectedTab(customFilterTab);
} else { }
if (targetTagFilterLayoutUiState.isCustomFilterTabSelected()) {
filterByButtons.restoreState(); filterByButtons.restoreState();
filterByStatusFooter.restoreState(); filterByStatusFooter.restoreState();
setSelectedTab(simpleFilterTab); setSelectedTab(simpleFilterTab);
} }
if (targetTagFilterLayoutUiState.isTargetTypeFilterTabSelected()) {
filterByButtons.restoreState();
filterByStatusFooter.restoreState();
setSelectedTab(targetTypeFilterTab);
}
} }
/** /**
@@ -190,17 +252,21 @@ public class MultipleTargetFilter extends Accordion {
* Subscribe event listeners * Subscribe event listeners
*/ */
public void subscribeListeners() { public void subscribeListeners() {
gridActionsVisibilityListener.subscribe(); targetTagGridActionsVisibilityListener.subscribe();
entityTagModifiedListener.subscribe(); entityTagModifiedListener.subscribe();
entityFilterQueryModifiedListener.subscribe(); entityFilterQueryModifiedListener.subscribe();
targetTypeGridActionsVisibilityListener.subscribe();
entityTargetTypeModifiedListener.subscribe();
} }
/** /**
* Unsubscribe event listeners * Unsubscribe event listeners
*/ */
public void unsubscribeListeners() { public void unsubscribeListeners() {
gridActionsVisibilityListener.unsubscribe(); targetTagGridActionsVisibilityListener.unsubscribe();
entityTagModifiedListener.unsubscribe(); entityTagModifiedListener.unsubscribe();
entityFilterQueryModifiedListener.unsubscribe(); entityFilterQueryModifiedListener.unsubscribe();
targetTypeGridActionsVisibilityListener.unsubscribe();
entityTargetTypeModifiedListener.unsubscribe();
} }
} }

View File

@@ -13,6 +13,7 @@ import org.eclipse.hawkbit.ui.common.event.EventLayout;
import org.eclipse.hawkbit.ui.common.event.EventView; import org.eclipse.hawkbit.ui.common.event.EventView;
import org.eclipse.hawkbit.ui.common.grid.header.AbstractFilterHeader; import org.eclipse.hawkbit.ui.common.grid.header.AbstractFilterHeader;
import org.eclipse.hawkbit.ui.management.targettag.TargetTagWindowBuilder; import org.eclipse.hawkbit.ui.management.targettag.TargetTagWindowBuilder;
import org.eclipse.hawkbit.ui.management.targettag.targettype.TargetTypeWindowBuilder;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider; import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.UIMessageIdProvider; import org.eclipse.hawkbit.ui.utils.UIMessageIdProvider;
@@ -28,23 +29,26 @@ public class TargetTagFilterHeader extends AbstractFilterHeader {
private final transient TargetTagWindowBuilder targetTagWindowBuilder; private final transient TargetTagWindowBuilder targetTagWindowBuilder;
private final transient TargetTypeWindowBuilder targetTypeWindowBuilder;
/** /**
* Constructor for TargetTagFilterHeader * Constructor for TargetTagFilterHeader
*
* @param uiDependencies * @param uiDependencies
* {@link CommonUiDependencies} * {@link CommonUiDependencies}
* @param targetTagFilterLayoutUiState * @param targetTagFilterLayoutUiState
* TargetTagFilterLayoutUiState * TargetTagFilterLayoutUiState
* @param targetTagWindowBuilder * @param targetTagWindowBuilder
* TargetTagWindowBuilder * @param targetTypeWindowBuilder
*/ */
public TargetTagFilterHeader(final CommonUiDependencies uiDependencies, public TargetTagFilterHeader(final CommonUiDependencies uiDependencies,
final TargetTagFilterLayoutUiState targetTagFilterLayoutUiState, final TargetTagFilterLayoutUiState targetTagFilterLayoutUiState,
final TargetTagWindowBuilder targetTagWindowBuilder) { final TargetTagWindowBuilder targetTagWindowBuilder, TargetTypeWindowBuilder targetTypeWindowBuilder) {
super(uiDependencies.getI18n(), uiDependencies.getPermChecker(), uiDependencies.getEventBus()); super(uiDependencies.getI18n(), uiDependencies.getPermChecker(), uiDependencies.getEventBus());
this.targetTagFilterLayoutUiState = targetTagFilterLayoutUiState; this.targetTagFilterLayoutUiState = targetTagFilterLayoutUiState;
this.targetTagWindowBuilder = targetTagWindowBuilder; this.targetTagWindowBuilder = targetTagWindowBuilder;
this.targetTypeWindowBuilder = targetTypeWindowBuilder;
buildHeader(); buildHeader();
} }
@@ -70,11 +74,17 @@ public class TargetTagFilterHeader extends AbstractFilterHeader {
@Override @Override
protected Window getWindowForAdd() { protected Window getWindowForAdd() {
if (targetTagFilterLayoutUiState.isTargetTypeFilterTabSelected()) {
return targetTypeWindowBuilder.getWindowForAdd();
}
return targetTagWindowBuilder.getWindowForAdd(); return targetTagWindowBuilder.getWindowForAdd();
} }
@Override @Override
protected String getAddEntityWindowCaptionMsgKey() { protected String getAddEntityWindowCaptionMsgKey() {
if (targetTagFilterLayoutUiState.isTargetTypeFilterTabSelected()) {
return UIMessageIdProvider.CAPTION_TYPE;
}
return UIMessageIdProvider.CAPTION_TAG; return UIMessageIdProvider.CAPTION_TAG;
} }

View File

@@ -8,9 +8,11 @@
*/ */
package org.eclipse.hawkbit.ui.management.targettag.filter; package org.eclipse.hawkbit.ui.management.targettag.filter;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.TargetTagManagement; import org.eclipse.hawkbit.repository.TargetTagManagement;
import org.eclipse.hawkbit.repository.TargetTypeManagement;
import org.eclipse.hawkbit.ui.common.CommonUiDependencies; import org.eclipse.hawkbit.ui.common.CommonUiDependencies;
import org.eclipse.hawkbit.ui.common.event.EventTopics; import org.eclipse.hawkbit.ui.common.event.EventTopics;
import org.eclipse.hawkbit.ui.common.event.TargetFilterTabChangedEventPayload; import org.eclipse.hawkbit.ui.common.event.TargetFilterTabChangedEventPayload;
@@ -20,6 +22,7 @@ import org.eclipse.hawkbit.ui.management.ManagementUIState;
import org.eclipse.hawkbit.ui.management.targettag.TargetTagWindowBuilder; import org.eclipse.hawkbit.ui.management.targettag.TargetTagWindowBuilder;
import com.vaadin.ui.ComponentContainer; import com.vaadin.ui.ComponentContainer;
import org.eclipse.hawkbit.ui.management.targettag.targettype.TargetTypeWindowBuilder;
/** /**
* Target Tag filter layout. * Target Tag filter layout.
@@ -50,15 +53,19 @@ public class TargetTagFilterLayout extends AbstractFilterLayout {
*/ */
public TargetTagFilterLayout(final CommonUiDependencies uiDependencies, final ManagementUIState managementUIState, public TargetTagFilterLayout(final CommonUiDependencies uiDependencies, final ManagementUIState managementUIState,
final TargetFilterQueryManagement targetFilterQueryManagement, final TargetFilterQueryManagement targetFilterQueryManagement,
final TargetTypeManagement targetTypeManagement,
final TargetTagManagement targetTagManagement, final TargetManagement targetManagement, final TargetTagManagement targetTagManagement, final TargetManagement targetManagement,
final TargetTagFilterLayoutUiState targetTagFilterLayoutUiState) { final TargetTagFilterLayoutUiState targetTagFilterLayoutUiState, final DistributionSetTypeManagement distributionSetTypeManagement) {
final TargetTagWindowBuilder targetTagWindowBuilder = new TargetTagWindowBuilder(uiDependencies, final TargetTagWindowBuilder targetTagWindowBuilder = new TargetTagWindowBuilder(uiDependencies,
targetTagManagement); targetTagManagement);
final TargetTypeWindowBuilder targetTypeWindowBuilder = new TargetTypeWindowBuilder(uiDependencies,
targetTypeManagement, distributionSetTypeManagement);
this.targetTagFilterHeader = new TargetTagFilterHeader(uiDependencies, targetTagFilterLayoutUiState, this.targetTagFilterHeader = new TargetTagFilterHeader(uiDependencies, targetTagFilterLayoutUiState,
targetTagWindowBuilder); targetTagWindowBuilder, targetTypeWindowBuilder);
this.multipleTargetFilter = new MultipleTargetFilter(uiDependencies, targetFilterQueryManagement, this.multipleTargetFilter = new MultipleTargetFilter(uiDependencies, targetFilterQueryManagement,
targetTagManagement, targetManagement, targetTagFilterLayoutUiState, targetTagWindowBuilder); targetTagManagement, targetManagement, targetTagFilterLayoutUiState, targetTagWindowBuilder, targetTypeWindowBuilder, targetTypeManagement);
this.filterTabChangedListener = new GenericEventListener<>(uiDependencies.getEventBus(), this.filterTabChangedListener = new GenericEventListener<>(uiDependencies.getEventBus(),
EventTopics.TARGET_FILTER_TAB_CHANGED, this::onTargetFilterTabChanged); EventTopics.TARGET_FILTER_TAB_CHANGED, this::onTargetFilterTabChanged);

View File

@@ -24,6 +24,8 @@ public class TargetTagFilterLayoutUiState extends TagFilterLayoutUiState {
private final Collection<TargetUpdateStatus> clickedTargetUpdateStatusFilters = new ArrayList<>(); private final Collection<TargetUpdateStatus> clickedTargetUpdateStatusFilters = new ArrayList<>();
private boolean isOverdueFilterClicked; private boolean isOverdueFilterClicked;
private boolean isCustomFilterTabSelected; private boolean isCustomFilterTabSelected;
private boolean isTargetTypeFilterTabSelected;
/** /**
* @return Id of clicked target filter query * @return Id of clicked target filter query
@@ -94,4 +96,13 @@ public class TargetTagFilterLayoutUiState extends TagFilterLayoutUiState {
public void setCustomFilterTabSelected(final boolean isCustomFilterTabSelected) { public void setCustomFilterTabSelected(final boolean isCustomFilterTabSelected) {
this.isCustomFilterTabSelected = isCustomFilterTabSelected; this.isCustomFilterTabSelected = isCustomFilterTabSelected;
} }
public boolean isTargetTypeFilterTabSelected() {
return isTargetTypeFilterTabSelected;
}
public void setTargetTypeFilterTabSelected(boolean targetTypeFilterTabSelected) {
isTargetTypeFilterTabSelected = targetTypeFilterTabSelected;
}
} }

View File

@@ -0,0 +1,134 @@
/**
* Copyright (c) 2021 Bosch.IO 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.targettag.filter;
import com.vaadin.ui.UI;
import com.vaadin.ui.Window;
import java.util.Collection;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.repository.Identifiable;
import org.eclipse.hawkbit.repository.TargetTypeManagement;
import org.eclipse.hawkbit.repository.exception.TargetTypeInUseException;
import org.eclipse.hawkbit.ui.common.CommonUiDependencies;
import org.eclipse.hawkbit.ui.common.data.mappers.TargetTypeToProxyTargetTypeMapper;
import org.eclipse.hawkbit.ui.common.data.providers.TargetTypeDataProvider;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyIdentifiableEntity;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTarget;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTargetType;
import org.eclipse.hawkbit.ui.common.event.EntityModifiedEventPayload;
import org.eclipse.hawkbit.ui.common.event.EventTopics;
import org.eclipse.hawkbit.ui.common.event.EventView;
import org.eclipse.hawkbit.ui.common.filterlayout.AbstractTargetTypeFilterButtons;
import org.eclipse.hawkbit.ui.common.state.TagFilterLayoutUiState;
import org.eclipse.hawkbit.ui.management.targettag.targettype.TargetTypeWindowBuilder;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Target Type filter buttons table.
*/
@SuppressWarnings("squid:S2160")
public class TargetTypeFilterButtons extends AbstractTargetTypeFilterButtons {
private static final long serialVersionUID = 1L;
private final transient TargetTypeManagement targetTypeManagement;
private final transient TargetTypeWindowBuilder targetTypeWindowBuilder;
private static final Logger LOG = LoggerFactory.getLogger(TargetTypeFilterButtons.class);
TargetTypeFilterButtons(final CommonUiDependencies uiDependencies,
final TargetTypeManagement targetTypeManagement, final TagFilterLayoutUiState tagFilterLayoutUiState,
final TargetTypeWindowBuilder targetTypeWindowBuilder) {
super(uiDependencies, tagFilterLayoutUiState);
this.targetTypeManagement = targetTypeManagement;
this.targetTypeWindowBuilder = targetTypeWindowBuilder;
init();
setDataProvider(
new TargetTypeDataProvider<>(targetTypeManagement, new TargetTypeToProxyTargetTypeMapper<>()));
}
@Override
public String getGridId() {
return UIComponentIdProvider.TARGET_TYPE_TABLE_ID;
}
@Override
protected String getMessageKeyEntityTypeSing() {
return "caption.entity.target.type";
}
@Override
protected String getMessageKeyEntityTypePlur() {
return "caption.entity.target.types";
}
@Override
protected boolean deleteFilterButtons(Collection<ProxyTargetType> filterButtonsToDelete) {
final ProxyTargetType targetTypeToDelete = filterButtonsToDelete.iterator().next();
return deleteTargetType(targetTypeToDelete);
}
@Override
protected String getFilterButtonIdPrefix() {
return UIComponentIdProvider.TARGET_TYPE_ID_PREFIXS;
}
@Override
protected void editButtonClickListener(ProxyTargetType clickedFilter) {
final Window updateWindow = targetTypeWindowBuilder.getWindowForUpdate(clickedFilter);
updateWindow.setCaption(i18n.getMessage("caption.update", i18n.getMessage("caption.type")));
UI.getCurrent().addWindow(updateWindow);
updateWindow.setVisible(Boolean.TRUE);
}
@Override
protected Class<? extends ProxyIdentifiableEntity> getFilterMasterEntityType() {
return ProxyTarget.class;
}
@Override
protected EventView getView() {
return EventView.DEPLOYMENT;
}
@Override
protected boolean deleteTargetType(ProxyTargetType targetTypeToDelete) {
try{
targetTypeManagement.delete(targetTypeToDelete.getId());
eventBus.publish(EventTopics.ENTITY_MODIFIED, this,
new EntityModifiedEventPayload(EntityModifiedEventPayload.EntityModifiedEventType.ENTITY_REMOVED, getFilterMasterEntityType(),
ProxyTargetType.class, targetTypeToDelete.getId()));
return true;
} catch (TargetTypeInUseException exception){
LOG.trace("Target type already in use exception: {}", exception.getMessage());
uiNotification.displayValidationError(i18n.getMessage(exception.getMessage()));
}
return false;
}
@Override
protected Collection<Long> filterExistingTargetTypeIds(Collection<Long> targetTypeIds) {
return targetTypeManagement.get(targetTypeIds).stream().map(Identifiable::getId).collect(Collectors.toSet());
}
@Override
protected boolean isDeletionAllowed() {
return permissionChecker.hasDeleteTargetPermission();
}
@Override
protected boolean isEditAllowed() {
return permissionChecker.hasUpdateRepositoryPermission();
}
}

View File

@@ -0,0 +1,86 @@
/**
* Copyright (c) 2021 Bosch.IO 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.targettag.targettype;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.repository.TargetTypeManagement;
import org.eclipse.hawkbit.repository.model.TargetType;
import org.eclipse.hawkbit.ui.common.AbstractAddNamedEntityWindowController;
import org.eclipse.hawkbit.ui.common.CommonUiDependencies;
import org.eclipse.hawkbit.ui.common.EntityWindowLayout;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyIdentifiableEntity;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTarget;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTargetType;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyType;
import org.eclipse.hawkbit.ui.common.targettype.ProxyTargetTypeValidator;
import org.springframework.util.StringUtils;
/**
* Add target type window controller
*/
public class AddTargetTypeWindowController
extends AbstractAddNamedEntityWindowController<ProxyTargetType, ProxyTargetType, TargetType> {
private final TargetTypeWindowLayout layout;
private final ProxyTargetTypeValidator validator;
private final TargetTypeManagement targetTypeManagement;
/**
* Constructor for AddTargetTypeWindowController
*
* @param uiDependencies
* {@link CommonUiDependencies}
* @param targetTypeManagement
* targetTypeManagement
* @param layout
* TargetTypeWindowLayout
*/
public AddTargetTypeWindowController(final CommonUiDependencies uiDependencies,
final TargetTypeManagement targetTypeManagement, final TargetTypeWindowLayout layout) {
super(uiDependencies);
this.targetTypeManagement = targetTypeManagement;
this.layout = layout;
this.validator = new ProxyTargetTypeValidator(uiDependencies);
}
@Override
public EntityWindowLayout<ProxyTargetType> getLayout() {
return layout;
}
@Override
protected ProxyTargetType buildEntityFromProxy(final ProxyTargetType proxyEntity) {
return new ProxyTargetType();
}
@Override
protected TargetType persistEntityInRepository(final ProxyTargetType entity) {
return targetTypeManagement.create(getEntityFactory().targetType().create()
.name(entity.getName()).description(entity.getDescription()).colour(entity.getColour())
.compatible(entity.getSelectedDsTypes().stream().map(ProxyType::getId)
.collect(Collectors.toSet())));
}
@Override
protected Class<? extends ProxyIdentifiableEntity> getEntityClass() {
return ProxyTargetType.class;
}
@Override
protected Class<? extends ProxyIdentifiableEntity> getParentEntityClass() {
return ProxyTarget.class;
}
@Override
protected boolean isEntityValid(final ProxyTargetType entity) {
final String trimmedName = StringUtils.trimWhitespace(entity.getName());
return validator.isEntityValid(entity, () -> targetTypeManagement.getByName(trimmedName).isPresent());
}
}

View File

@@ -0,0 +1,63 @@
/**
* Copyright (c) 2021 Bosch.IO 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.targettag.targettype;
import com.vaadin.ui.Grid;
import com.vaadin.ui.themes.ValoTheme;
import org.eclipse.hawkbit.ui.common.builder.GridComponentBuilder;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyType;
import org.eclipse.hawkbit.ui.common.grid.AbstractGrid;
import org.eclipse.hawkbit.ui.common.grid.selection.RangeSelectionModel;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
/**
* Distribution Set Selected Type grid which is shown on the Target Type
* Create/Update popup layout.
*/
public class DsTypeSelectedGrid extends Grid<ProxyType> {
private static final long serialVersionUID = 1L;
private final VaadinMessageSource i18n;
/**
* Constructor for DsTypeSelectedGrid
*
* @param i18n
* VaadinMessageSource
*/
public DsTypeSelectedGrid(final VaadinMessageSource i18n) {
this.i18n = i18n;
init();
}
private void init() {
setSizeFull();
setHeightUndefined();
addStyleName(ValoTheme.TABLE_NO_HORIZONTAL_LINES);
addStyleName(ValoTheme.TABLE_NO_STRIPES);
addStyleName(ValoTheme.TABLE_NO_VERTICAL_LINES);
addStyleName(ValoTheme.TABLE_SMALL);
// used to deactivate cell text selection by user
addStyleName(AbstractGrid.MULTI_SELECT_STYLE);
setId(SPUIDefinitions.TWIN_TABLE_SELECTED_ID);
setSelectionModel(new RangeSelectionModel<>(i18n));
addColumns();
}
private void addColumns() {
GridComponentBuilder.addColumn(this, ProxyType::getName).setId(UIComponentIdProvider.DIST_TYPE_TABLE_SELECTED_ID)
.setCaption(i18n.getMessage("header.dt.twintable.selected"))
.setDescriptionGenerator(ProxyType::getDescription);
}
}

View File

@@ -0,0 +1,63 @@
/**
* Copyright (c) 2021 Bosch.IO 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.targettag.targettype;
import com.vaadin.ui.Grid;
import com.vaadin.ui.themes.ValoTheme;
import org.eclipse.hawkbit.ui.common.builder.GridComponentBuilder;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyType;
import org.eclipse.hawkbit.ui.common.grid.AbstractGrid;
import org.eclipse.hawkbit.ui.common.grid.selection.RangeSelectionModel;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
/**
* Distribution Set Source Type grid which is shown on the Target Type
* Create/Update popup layout.
*/
public class DsTypeSourceGrid extends Grid<ProxyType> {
private static final long serialVersionUID = 1L;
private final VaadinMessageSource i18n;
/**
* Constructor for DsTypeSourceGrid
*
* @param i18n
* VaadinMessageSource
*/
public DsTypeSourceGrid(final VaadinMessageSource i18n) {
this.i18n = i18n;
init();
}
private void init() {
setSizeFull();
setHeightUndefined();
addStyleName(ValoTheme.TABLE_NO_HORIZONTAL_LINES);
addStyleName(ValoTheme.TABLE_NO_STRIPES);
addStyleName(ValoTheme.TABLE_NO_VERTICAL_LINES);
addStyleName(ValoTheme.TABLE_SMALL);
// used to deactivate cell text selection by user
addStyleName(AbstractGrid.MULTI_SELECT_STYLE);
setId(SPUIDefinitions.TWIN_TABLE_SOURCE_ID);
setSelectionModel(new RangeSelectionModel<>(i18n));
addColumns();
}
private void addColumns() {
GridComponentBuilder.addColumn(this, ProxyType::getName).setId(UIComponentIdProvider.DIST_TYPE_TABLE_SOURCE_ID)
.setCaption(i18n.getMessage("header.dt.twintable.available"))
.setDescriptionGenerator(ProxyType::getDescription);
}
}

View File

@@ -0,0 +1,179 @@
/**
* Copyright (c) 2021 Bosch.IO 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.targettag.targettype;
import com.google.common.collect.Sets;
import com.vaadin.icons.VaadinIcons;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomField;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.VerticalLayout;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.ui.common.data.mappers.TypeToProxyTypeMapper;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyIdentifiableEntity;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyType;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleNoBorder;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.springframework.data.domain.PageRequest;
import org.springframework.util.CollectionUtils;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Layout for the distribution sets select grids for managing Target
* Types on the Distributions View.
*/
public class TargetTypeDsTypeSelectLayout extends CustomField<Set<ProxyType>> {
private static final long serialVersionUID = 1L;
private static final int MAX_DS_TYPE_QUERY = 500;
private final VaadinMessageSource i18n;
private final transient TypeToProxyTypeMapper<DistributionSetType> dsTypeToProxyTypeMapper;
private DsTypeSelectedGrid selectedGrid;
private DsTypeSourceGrid sourceGrid;
private final List<ProxyType> allDsTypes;
private Set<ProxyType> selectedDsTypes;
private final HorizontalLayout layout;
/**
* Constructor
*
* @param i18n
* VaadinMessageSource
* @param distributionSetTypeManagement
* distributionSetTypeManagement
*/
public TargetTypeDsTypeSelectLayout(final VaadinMessageSource i18n,
final DistributionSetTypeManagement distributionSetTypeManagement) {
this.i18n = i18n;
this.dsTypeToProxyTypeMapper = new TypeToProxyTypeMapper<>();
this.allDsTypes = distributionSetTypeManagement.findAll(PageRequest.of(0, MAX_DS_TYPE_QUERY))
.map(dsTypeToProxyTypeMapper::map).getContent();
this.selectedDsTypes = new HashSet<>();
this.layout = new HorizontalLayout();
this.layout.setSpacing(false);
this.layout.setMargin(false);
this.layout.setSizeFull();
this.layout.setWidth("400px");
buildLayout();
}
private void buildLayout() {
final VerticalLayout selectButtonLayout = new VerticalLayout();
selectButtonLayout.setSpacing(false);
selectButtonLayout.setMargin(false);
final Button selectButton = SPUIComponentProvider.getButton(UIComponentIdProvider.SELECT_DIST_TYPE, "", "",
"arrow-button", true, VaadinIcons.FORWARD, SPUIButtonStyleNoBorder.class);
selectButton.addClickListener(event -> addDsTypeToSelectedGrid());
final Button unSelectButton = SPUIComponentProvider.getButton(UIComponentIdProvider.UNSELECT_DIST_TYPE, "", "", "arrow-button",
true, VaadinIcons.BACKWARDS, SPUIButtonStyleNoBorder.class);
unSelectButton.addClickListener(event -> removeDsTypeFromSelectedGrid());
selectButtonLayout.addComponent(selectButton);
selectButtonLayout.addComponent(unSelectButton);
selectButtonLayout.setComponentAlignment(selectButton, Alignment.MIDDLE_CENTER);
selectButtonLayout.setComponentAlignment(unSelectButton, Alignment.MIDDLE_CENTER);
sourceGrid = buildSourceGrid();
selectedGrid = buildSelectedGrid();
layout.addComponent(sourceGrid);
layout.addComponent(selectButtonLayout);
layout.addComponent(selectedGrid);
layout.setComponentAlignment(sourceGrid, Alignment.MIDDLE_LEFT);
layout.setComponentAlignment(selectButtonLayout, Alignment.MIDDLE_CENTER);
layout.setComponentAlignment(selectedGrid, Alignment.MIDDLE_RIGHT);
layout.setExpandRatio(sourceGrid, 0.45F);
layout.setExpandRatio(selectButtonLayout, 0.07F);
layout.setExpandRatio(selectedGrid, 0.48F);
}
private void addDsTypeToSelectedGrid() {
final Set<ProxyType> selectedSourceDsTypes = sourceGrid.getSelectedItems();
if (CollectionUtils.isEmpty(selectedSourceDsTypes)) {
return;
}
setValue(Sets.union(selectedDsTypes, selectedSourceDsTypes).immutableCopy());
}
private void removeDsTypeFromSelectedGrid() {
final Set<ProxyType> selectedSelectedDsTypes = selectedGrid.getSelectedItems();
if (CollectionUtils.isEmpty(selectedSelectedDsTypes)) {
return;
}
setValue(Sets.difference(selectedDsTypes, selectedSelectedDsTypes).immutableCopy());
}
private DsTypeSourceGrid buildSourceGrid() {
final DsTypeSourceGrid grid = new DsTypeSourceGrid(i18n);
grid.setItems(allDsTypes);
if (!CollectionUtils.isEmpty(allDsTypes)) {
grid.select(allDsTypes.get(0));
}
return grid;
}
private DsTypeSelectedGrid buildSelectedGrid() {
final DsTypeSelectedGrid dsTypeSelectedGrid = new DsTypeSelectedGrid(i18n);
dsTypeSelectedGrid.setItems(selectedDsTypes);
return dsTypeSelectedGrid;
}
@Override
public Set<ProxyType> getValue() {
return selectedDsTypes;
}
@Override
protected Component initContent() {
return layout;
}
@Override
protected void doSetValue(final Set<ProxyType> value) {
if (value == null) {
return;
}
selectedDsTypes = value;
selectedGrid.setItems(selectedDsTypes);
sourceGrid.setItems(getSourceDsTypes());
}
private List<ProxyType> getSourceDsTypes() {
final Set<Long> selectedDsTypeIds = selectedDsTypes.stream().map(ProxyIdentifiableEntity::getId)
.collect(Collectors.toSet());
return allDsTypes.stream().filter(dsType -> !selectedDsTypeIds.contains(dsType.getId()))
.collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,66 @@
/**
* Copyright (c) 2021 Bosch.IO 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.targettag.targettype;
import com.vaadin.ui.Window;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.TargetTypeManagement;
import org.eclipse.hawkbit.ui.common.AbstractEntityWindowBuilder;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.common.CommonUiDependencies;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTargetType;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
/**
* Builder for target type window
*/
public class TargetTypeWindowBuilder extends AbstractEntityWindowBuilder<ProxyTargetType> {
private final TargetTypeManagement targetTypeManagement;
private final DistributionSetTypeManagement dsTypeManagement;
/**
* Constructor for TargetTypeWindowBuilder
*
* @param uiDependencies
* {@link CommonUiDependencies}
* @param dsTypeManagement
* DistributionSetTypeManagement
* @param targetTypeManagement
* TargetTypeManagement
*/
public TargetTypeWindowBuilder(final CommonUiDependencies uiDependencies, final TargetTypeManagement targetTypeManagement,
final DistributionSetTypeManagement dsTypeManagement) {
super(uiDependencies);
this.targetTypeManagement = targetTypeManagement;
this.dsTypeManagement = dsTypeManagement;
}
@Override
protected String getWindowId() {
return UIComponentIdProvider.TAG_POPUP_ID;
}
@Override
public Window getWindowForAdd() {
CommonDialogWindow window = getWindowForNewEntity(new AddTargetTypeWindowController(uiDependencies, targetTypeManagement,
new TargetTypeWindowLayout(uiDependencies, dsTypeManagement)));
window.hideMandatoryExplanation();
return window;
}
@Override
public Window getWindowForUpdate(final ProxyTargetType proxyType) {
CommonDialogWindow window = getWindowForEntity(proxyType, new UpdateTargetTypeWindowController(uiDependencies, targetTypeManagement,
new TargetTypeWindowLayout(uiDependencies, dsTypeManagement)));
window.hideMandatoryExplanation();
return window;
}
}

View File

@@ -0,0 +1,53 @@
/**
* Copyright (c) 2021 Bosch.IO 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.targettag.targettype;
import com.vaadin.ui.ComponentContainer;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.ui.common.CommonUiDependencies;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTargetType;
import org.eclipse.hawkbit.ui.management.tag.TagWindowLayout;
/**
* Target type window layout
*/
public class TargetTypeWindowLayout extends TagWindowLayout<ProxyTargetType> {
private final TargetTypeWindowLayoutComponentBuilder targetTypeWindowLayoutComponentBuilder;
private final TargetTypeDsTypeSelectLayout targetTypeDsTypeSelectLayout;
/**
* Constructor for TargetTypeWindowLayout
*
* @param uiDependencies
* {@link CommonUiDependencies}
* @param distributionSetTypeManagement
* DistributionSetTypeManagement
*/
public TargetTypeWindowLayout(final CommonUiDependencies uiDependencies,
final DistributionSetTypeManagement distributionSetTypeManagement) {
super(uiDependencies);
this.targetTypeWindowLayoutComponentBuilder = new TargetTypeWindowLayoutComponentBuilder(i18n, distributionSetTypeManagement);
this.targetTypeDsTypeSelectLayout = targetTypeWindowLayoutComponentBuilder.createTargetTypeDsSelectLayout(binder);
this.colorPickerComponent.getColorPickerBtn().setCaption(i18n.getMessage("label.choose.type.color"));
}
@Override
public ComponentContainer getRootComponent() {
final ComponentContainer rootLayout = super.getRootComponent();
rootLayout.addComponent(targetTypeDsTypeSelectLayout);
return rootLayout;
}
}

View File

@@ -0,0 +1,57 @@
/**
* Copyright (c) 2021 Bosch.IO 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.targettag.targettype;
import com.vaadin.data.Binder;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTargetType;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
/**
* Builder for target type window layout component
*/
public class TargetTypeWindowLayoutComponentBuilder {
private final VaadinMessageSource i18n;
private final DistributionSetTypeManagement distributionSetTypeManagement;
/**
* Constructor for TargetTypeWindowLayoutComponentBuilder
*
* @param i18n
* VaadinMessageSource
* @param distributionSetTypeManagement
* distributionSetTypeManagement
*/
public TargetTypeWindowLayoutComponentBuilder(final VaadinMessageSource i18n,
final DistributionSetTypeManagement distributionSetTypeManagement) {
this.i18n = i18n;
this.distributionSetTypeManagement = distributionSetTypeManagement;
}
/**
* Create target type layout
*
* @param binder
* Vaadin binder
*
* @return layout of target type distribution set selection
*/
public TargetTypeDsTypeSelectLayout createTargetTypeDsSelectLayout(final Binder<ProxyTargetType> binder) {
final TargetTypeDsTypeSelectLayout targetTypeDsTypeSelectLayout = new TargetTypeDsTypeSelectLayout(i18n, distributionSetTypeManagement);
targetTypeDsTypeSelectLayout.setRequiredIndicatorVisible(false);
binder.forField(targetTypeDsTypeSelectLayout)
.bind(ProxyTargetType::getSelectedDsTypes, ProxyTargetType::setSelectedDsTypes);
return targetTypeDsTypeSelectLayout;
}
}

View File

@@ -0,0 +1,131 @@
/**
* Copyright (c) 2021 Bosch.IO 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.targettag.targettype;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.repository.TargetTypeManagement;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.TargetType;
import org.eclipse.hawkbit.ui.common.AbstractEntityWindowLayout;
import org.eclipse.hawkbit.ui.common.AbstractUpdateNamedEntityWindowController;
import org.eclipse.hawkbit.ui.common.CommonUiDependencies;
import org.eclipse.hawkbit.ui.common.data.mappers.TypeToProxyTypeMapper;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyIdentifiableEntity;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTarget;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyTargetType;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyType;
import org.eclipse.hawkbit.ui.common.targettype.ProxyTargetTypeValidator;
import org.springframework.util.StringUtils;
/**
* Controller for update target type window
*/
public class UpdateTargetTypeWindowController
extends AbstractUpdateNamedEntityWindowController<ProxyTargetType, ProxyTargetType, TargetType> {
private final TargetTypeManagement targetTypeManagement;
private final TypeToProxyTypeMapper<DistributionSetType> dsTypeToProxyTypeMapper;
private final TargetTypeWindowLayout layout;
private final ProxyTargetTypeValidator validator;
private String nameBeforeEdit;
/**
* Constructor for UpdateTargetTypeWindowController
*
* @param uiDependencies
* {@link CommonUiDependencies}
* @param targetTypeManagement
* TargetTypeManagement
* @param layout
* TargetTypeWindowLayout
*/
public UpdateTargetTypeWindowController(final CommonUiDependencies uiDependencies,
final TargetTypeManagement targetTypeManagement,
final TargetTypeWindowLayout layout) {
super(uiDependencies);
this.targetTypeManagement = targetTypeManagement;
this.dsTypeToProxyTypeMapper = new TypeToProxyTypeMapper<>();
this.layout = layout;
this.validator = new ProxyTargetTypeValidator(uiDependencies);
}
@Override
public AbstractEntityWindowLayout<ProxyTargetType> getLayout() {
return layout;
}
@Override
protected ProxyTargetType buildEntityFromProxy(final ProxyTargetType proxyEntity) {
final ProxyTargetType dsType = new ProxyTargetType();
dsType.setId(proxyEntity.getId());
dsType.setName(proxyEntity.getName());
dsType.setDescription(proxyEntity.getDescription());
dsType.setColour(proxyEntity.getColour());
dsType.setSelectedDsTypes(getDsTypesByDsTypeId(proxyEntity.getId()));
nameBeforeEdit = proxyEntity.getName();
return dsType;
}
private Set<ProxyType> getDsTypesByDsTypeId(final Long id) {
Optional<TargetType> targetType = targetTypeManagement.get(id);
return targetType.map(type -> type.getCompatibleDistributionSetTypes().stream()
.map(dsTypeToProxyTypeMapper::map).collect(Collectors.toSet())).orElse(Collections.emptySet());
}
@Override
protected TargetType persistEntityInRepository(final ProxyTargetType entity) {
Set<Long> dsTypesIds = getDsTypesByDsTypeId(entity.getId()).stream().map(ProxyType::getId).collect(Collectors.toSet());
Set<Long> selectedDsIds = entity.getSelectedDsTypes().stream().map(ProxyType::getId).collect(Collectors.toSet());
Set<Long> dsTypesForRemoval = getDsTypesByDsTypeId(entity.getId()).stream().map(ProxyType::getId)
.filter(dsType -> !selectedDsIds.contains(dsType)).collect(Collectors.toSet());
Set<Long> dsTypesForAdd = selectedDsIds.stream()
.filter(dsType -> !dsTypesIds.contains(dsType)).collect(Collectors.toSet());
dsTypesForRemoval.forEach(dsType -> targetTypeManagement.unassignDistributionSetType(entity.getId(), dsType));
if (!dsTypesForAdd.isEmpty()) {
targetTypeManagement.assignCompatibleDistributionSetTypes(entity.getId(), dsTypesForAdd);
}
return targetTypeManagement.update(getEntityFactory().targetType().update(entity.getId())
.name(entity.getName()).description(entity.getDescription()).colour(entity.getColour()));
}
@Override
protected Class<? extends ProxyIdentifiableEntity> getEntityClass() {
return ProxyTargetType.class;
}
@Override
protected Class<? extends ProxyIdentifiableEntity> getParentEntityClass() {
return ProxyTarget.class;
}
@Override
protected boolean isEntityValid(final ProxyTargetType entity) {
final String trimmedName = StringUtils.trimWhitespace(entity.getName());
return validator.isEntityValid(entity,
() -> hasNamedChanged(trimmedName) && targetTypeManagement.getByName(trimmedName).isPresent());
}
private boolean hasNamedChanged(final String trimmedName) {
return !nameBeforeEdit.equals(trimmedName);
}
}

View File

@@ -262,6 +262,11 @@ public final class SPUIDefinitions {
*/ */
public static final String NO_TAG_BUTTON_ID = "no_tag_button"; public static final String NO_TAG_BUTTON_ID = "no_tag_button";
/**
* Id of "NO TARGET TYPE" button.
*/
public static final String NO_TARGET_TYPE_BUTTON_ID = "no_target_type_button";
/** /**
* DELETE column/button. * DELETE column/button.
*/ */

View File

@@ -116,6 +116,11 @@ public final class SPUIStyleDefinitions {
*/ */
public static final String SIMPLE_FILTER_HEADER = "simple-tag-filter-header"; public static final String SIMPLE_FILTER_HEADER = "simple-tag-filter-header";
/**
* Target type filter header layout.
*/
public static final String TARGET_TYPE_FILTER_HEADER = "target-type-filter-header";
/** /**
* Simple tag filter header layout. * Simple tag filter header layout.
*/ */

View File

@@ -580,6 +580,16 @@ public final class UIComponentIdProvider {
*/ */
public static final String TARGET_TAG_DROP_AREA_ID = "target.tag.drop.area"; public static final String TARGET_TAG_DROP_AREA_ID = "target.tag.drop.area";
/**
* ID-Target tag table.
*/
public static final String TARGET_TYPE_TABLE_ID = "target.type.tableId";
/**
* ID-Target type table drop area.
*/
public static final String TARGET_TYPE_DROP_AREA_ID = "target.type.drop.area";
/** /**
* ID-Distibution tag table. * ID-Distibution tag table.
*/ */
@@ -929,6 +939,11 @@ public final class UIComponentIdProvider {
*/ */
public static final String SIMPLE_FILTER_ACCORDION_TAB = "simple.filter.accordion.tab"; public static final String SIMPLE_FILTER_ACCORDION_TAB = "simple.filter.accordion.tab";
/**
* ID - target type filter- Accordion-Tab
*/
public static final String TARGET_TYPE_FILTER_ACCORDION_TAB = "target.type.filter.accordion.tab";
/** /**
* ID - custom filter- Accordion-Tab * ID - custom filter- Accordion-Tab
*/ */
@@ -1337,6 +1352,22 @@ public final class UIComponentIdProvider {
* Table multiselect for selecting DistType * Table multiselect for selecting DistType
*/ */
public static final String SELECT_DIST_TYPE = "select-dist-type"; public static final String SELECT_DIST_TYPE = "select-dist-type";
/**
* Table multiselect for unselecting DistType
*/
public static final String UNSELECT_DIST_TYPE = "unselect-dist-type";
/**
* ID for DistType source value table
*/
public static final String DIST_TYPE_TABLE_SOURCE_ID = "dsTypeSourceId";
/**
* ID for DistType selected value table
*/
public static final String DIST_TYPE_TABLE_SELECTED_ID = "dsTypeSelectedId";
/** /**
* ID for download anonymous checkbox * ID for download anonymous checkbox
*/ */
@@ -1528,6 +1559,10 @@ public final class UIComponentIdProvider {
* Target tag button id prefix. * Target tag button id prefix.
*/ */
public static final String TARGET_TAG_ID_PREFIXS = "target.tag"; public static final String TARGET_TAG_ID_PREFIXS = "target.tag";
/**
* Target type button id prefix.
*/
public static final String TARGET_TYPE_ID_PREFIXS = "target.type";
/** /**
* Distribution tag button id prefix. * Distribution tag button id prefix.
*/ */

View File

@@ -89,10 +89,14 @@ public final class UIMessageIdProvider {
public static final String CAPTION_TAG = "caption.tag"; public static final String CAPTION_TAG = "caption.tag";
public static final String CAPTION_TYPE = "caption.type";
public static final String LABEL_DROP_AREA_UPLOAD = "label.drop.area.upload"; public static final String LABEL_DROP_AREA_UPLOAD = "label.drop.area.upload";
public static final String LABEL_NO_TAG = "label.no.tag"; public static final String LABEL_NO_TAG = "label.no.tag";
public static final String LABEL_NO_TARGET_TYPE = "label.no.target.type";
public static final String LABEL_CREATE_FILTER = "label.create.filter"; public static final String LABEL_CREATE_FILTER = "label.create.filter";
public static final String LABEL_EDIT_FILTER = "label.edit.filter"; public static final String LABEL_EDIT_FILTER = "label.edit.filter";

View File

@@ -70,6 +70,8 @@ header.first.delete.swmodule.type.table = Software Module Type
header.second.delete.swmodule.type.table = Discard header.second.delete.swmodule.type.table = Discard
header.dist.twintable.selected=Selected header.dist.twintable.selected=Selected
header.dist.twintable.available=Available header.dist.twintable.available=Available
header.dt.twintable.available=Distribution set types
header.dt.twintable.selected=Compatible distribution set types
header.target.installed = Installed header.target.installed = Installed
header.target.assigned = Assigned header.target.assigned = Assigned
header.type=Type header.type=Type
@@ -112,6 +114,7 @@ caption.entity.missing.error = Entity is missing
caption.new.softwaremodule.application = Configure New Application caption.new.softwaremodule.application = Configure New Application
caption.new.softwaremodule.os = Configure New OS caption.new.softwaremodule.os = Configure New OS
caption.filter.simple = Simple Filter caption.filter.simple = Simple Filter
caption.filter.type = Type Filter
caption.filter.custom = Custom Filter caption.filter.custom = Custom Filter
caption.metadata = Metadata caption.metadata = Metadata
caption.rollout.name = Rollout name caption.rollout.name = Rollout name
@@ -177,6 +180,7 @@ label.menu = Menu
label.active = Active label.active = Active
label.action.id = Action Id label.action.id = Action Id
label.no.tag = NO TAG label.no.tag = NO TAG
label.no.target.type = NO TARGET TYPE
label.action.forced = Forced label.action.forced = Forced
label.action.type = Type label.action.type = Type
label.action.soft = Soft label.action.soft = Soft
@@ -408,6 +412,7 @@ message.cannot.delete = Cannot be deleted
message.check.softwaremodule = Please provide both name and version! message.check.softwaremodule = Please provide both name and version!
message.duplicate.softwaremodule = {0} : {1} already exists! message.duplicate.softwaremodule = {0} : {1} already exists!
message.tag.delete = Please deselect the tag {0} before deleting message.tag.delete = Please deselect the tag {0} before deleting
message.targettype.delete = Please deselect the target type {0} before deleting
message.dist.type.check.delete = Please deselect the distribution type {0} before deleting message.dist.type.check.delete = Please deselect the distribution type {0} before deleting
message.cannot.delete.default.dstype = Default distribution set type cannot be deleted message.cannot.delete.default.dstype = Default distribution set type cannot be deleted
message.swmodule.type.check.delete = Please deselect the Software Module type {0} before deleting message.swmodule.type.check.delete = Please deselect the Software Module type {0} before deleting
@@ -480,6 +485,7 @@ message.error.missing.filtername = Please select target filter name
message.error.missing.controllerId = Missing Controller Id message.error.missing.controllerId = Missing Controller Id
message.error.missing.nameorversion = Missing Name or Version message.error.missing.nameorversion = Missing Name or Version
message.error.missing.nameorversionortype = Missing Name or Version or Type message.error.missing.nameorversionortype = Missing Name or Version or Type
message.error.missing.typename = Please select target type name
message.error.distributionset.invalid = Action not allowed for invalid distribution set {0} message.error.distributionset.invalid = Action not allowed for invalid distribution set {0}
message.type.delete = Please unclick the type {0}, then try to delete message.type.delete = Please unclick the type {0}, then try to delete
message.error.dist.set.type.update= Distribution set type is already assigned to set(s) and cannot be changed message.error.dist.set.type.update= Distribution set type is already assigned to set(s) and cannot be changed
@@ -806,6 +812,8 @@ color.not.exists=There is no mapping for the provided colour {0}
caption.entity.target.tag = Target Tag caption.entity.target.tag = Target Tag
caption.entity.target.tags = Target Tags caption.entity.target.tags = Target Tags
caption.entity.target.type = Target Type
caption.entity.target.types = Target Types
caption.entity.distribution.tag = Distribution Tag caption.entity.distribution.tag = Distribution Tag
caption.entity.distribution.tags = Distribution Tags caption.entity.distribution.tags = Distribution Tags
caption.entity.distribution.type = Distribution set Type caption.entity.distribution.type = Distribution set Type