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

@@ -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

@@ -22,7 +22,7 @@ import org.springframework.util.StringUtils;
* Data provider for {@link TargetTypeManagement}, which dynamically loads a
* batch of {@link TargetType} entities from backend and maps them to
* corresponding output type.
*
*
* @param <T>
* output type
*/

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
*/
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
*/
public enum TargetFilterTabChangedEventPayload {
SIMPLE, CUSTOM;
SIMPLE, CUSTOM, TARGET_TYPE;
}

View File

@@ -8,11 +8,13 @@
*/
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.Collections;
import java.util.Map;
import java.util.Set;
import org.eclipse.hawkbit.ui.common.CommonUiDependencies;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyIdentifiableEntity;
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.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.
*/

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;
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.EnumMap;
import java.util.Map;
import java.util.concurrent.Executor;
import org.eclipse.hawkbit.repository.DeploymentManagement;
import org.eclipse.hawkbit.repository.DistributionSetInvalidationManagement;
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.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
*/
@@ -107,8 +105,8 @@ public class DeploymentView extends AbstractEventListenersAwareView implements B
if (permChecker.hasTargetReadPermission()) {
this.targetTagFilterLayout = new TargetTagFilterLayout(uiDependencies, managementUIState,
targetFilterQueryManagement, targetTagManagement, targetManagement,
managementUIState.getTargetTagFilterLayoutUiState());
targetFilterQueryManagement, targetTypeManagement, targetTagManagement, targetManagement,
managementUIState.getTargetTagFilterLayoutUiState(), distributionSetTypeManagement);
this.targetGridLayout = new TargetGridLayout(uiDependencies, targetManagement, targetTypeManagement, deploymentManagement,
uiProperties, targetTagManagement, distributionSetManagement, uiExecutor, configManagement,

View File

@@ -46,13 +46,13 @@ public class TargetTagWindowBuilder extends AbstractEntityWindowBuilder<ProxyTag
@Override
public Window getWindowForAdd() {
return getWindowForNewEntity(new AddTargetTagWindowController(uiDependencies, targetTagManagement,
new TagWindowLayout<ProxyTag>(uiDependencies)));
new TagWindowLayout<>(uiDependencies)));
}
@Override
public Window getWindowForUpdate(final ProxyTag proxyTag) {
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;
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.List;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.TargetManagement;
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.data.proxies.ProxyTag;
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.ProxyTargetType;
import org.eclipse.hawkbit.ui.common.event.EventLayout;
import org.eclipse.hawkbit.ui.common.event.EventLayoutViewAware;
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.EntityModifiedGridRefreshAwareSupport;
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.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
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.
*/
@@ -51,33 +52,41 @@ public class MultipleTargetFilter extends Accordion {
private final TargetTagFilterLayoutUiState targetTagFilterLayoutUiState;
private final VerticalLayout simpleFilterTab;
private final VerticalLayout targetTypeFilterTab;
private final TargetTagFilterButtons filterByButtons;
private final TargetTypeFilterButtons targetTypeFilterButtons;
private final FilterByStatusLayout filterByStatusFooter;
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<ProxyTargetFilterQuery> entityFilterQueryModifiedListener;
private final transient EntityModifiedListener<ProxyTargetType> entityTargetTypeModifiedListener;
MultipleTargetFilter(final CommonUiDependencies uiDependencies,
final TargetFilterQueryManagement targetFilterQueryManagement,
final TargetTagManagement targetTagManagement, final TargetManagement targetManagement,
final TargetTagFilterLayoutUiState targetTagFilterLayoutUiState,
final TargetTagWindowBuilder targetTagWindowBuilder) {
final TargetFilterQueryManagement targetFilterQueryManagement,
final TargetTagManagement targetTagManagement, final TargetManagement targetManagement,
final TargetTagFilterLayoutUiState targetTagFilterLayoutUiState,
final TargetTagWindowBuilder targetTagWindowBuilder, final TargetTypeWindowBuilder targetTypeWindowBuilder, final TargetTypeManagement targetTypeManagement) {
this.i18n = uiDependencies.getI18n();
this.eventBus = uiDependencies.getEventBus();
this.targetTagFilterLayoutUiState = targetTagFilterLayoutUiState;
this.filterByButtons = new TargetTagFilterButtons(uiDependencies, targetTagManagement, targetManagement,
targetTagFilterLayoutUiState, targetTagWindowBuilder);
this.targetTypeFilterButtons = new TargetTypeFilterButtons(uiDependencies, targetTypeManagement, targetTagFilterLayoutUiState, targetTypeWindowBuilder);
this.filterByStatusFooter = new FilterByStatusLayout(i18n, eventBus, targetTagFilterLayoutUiState);
this.simpleFilterTab = buildSimpleFilterTab();
this.targetTypeFilterTab = buildTargetTypeFilterTab();
this.customFilterTab = new TargetFilterQueryButtons(i18n, eventBus, targetFilterQueryManagement,
targetTagFilterLayoutUiState);
final EventLayoutViewAware layoutViewAware = new EventLayoutViewAware(EventLayout.TARGET_TAG_FILTER,
EventView.DEPLOYMENT);
this.gridActionsVisibilityListener = new GridActionsVisibilityListener(eventBus, layoutViewAware,
this.targetTagGridActionsVisibilityListener = new GridActionsVisibilityListener(eventBus, layoutViewAware,
filterByButtons::hideActionColumns, filterByButtons::showEditColumn, filterByButtons::showDeleteColumn);
this.entityTagModifiedListener = new EntityModifiedListener.Builder<>(eventBus, ProxyTag.class)
.parentEntityType(ProxyTarget.class).viewAware(layoutViewAware)
@@ -86,6 +95,12 @@ public class MultipleTargetFilter extends Accordion {
ProxyTargetFilterQuery.class).viewAware(layoutViewAware)
.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();
addTabs();
addSelectedTabChangeListener(event -> selectedTabChanged());
@@ -119,11 +134,40 @@ public class MultipleTargetFilter extends Accordion {
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() {
return Arrays.asList(EntityModifiedGridRefreshAwareSupport.of(filterByButtons::refreshAll),
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() {
return Arrays.asList(EntityModifiedGridRefreshAwareSupport.of(customFilterTab::refreshAll),
EntityModifiedGenericSupport.of(null, customFilterTab::reselectFilterOnTfqUpdated,
@@ -138,6 +182,7 @@ public class MultipleTargetFilter extends Accordion {
private void addTabs() {
addTab(simpleFilterTab).setId(UIComponentIdProvider.SIMPLE_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() {
final String selectedTabId = getTab(getSelectedTab()).getId();
if (UIComponentIdProvider.SIMPLE_FILTER_ACCORDION_TAB.equals(selectedTabId)) {
customFilterTab.clearAppliedTargetFilterQuery();
targetTagFilterLayoutUiState.setCustomFilterTabSelected(false);
targetTagFilterLayoutUiState.setTargetTypeFilterTabSelected(false);
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();
filterByStatusFooter.clearStatusAndOverdueFilters();
targetTagFilterLayoutUiState.setCustomFilterTabSelected(true);
targetTagFilterLayoutUiState.setTargetTypeFilterTabSelected(false);
eventBus.publish(EventTopics.TARGET_FILTER_TAB_CHANGED, this, TargetFilterTabChangedEventPayload.CUSTOM);
}
}
/**
@@ -170,12 +225,19 @@ public class MultipleTargetFilter extends Accordion {
customFilterTab.restoreState();
setSelectedTab(customFilterTab);
} else {
}
if (targetTagFilterLayoutUiState.isCustomFilterTabSelected()) {
filterByButtons.restoreState();
filterByStatusFooter.restoreState();
setSelectedTab(simpleFilterTab);
}
if (targetTagFilterLayoutUiState.isTargetTypeFilterTabSelected()) {
filterByButtons.restoreState();
filterByStatusFooter.restoreState();
setSelectedTab(targetTypeFilterTab);
}
}
/**
@@ -190,17 +252,21 @@ public class MultipleTargetFilter extends Accordion {
* Subscribe event listeners
*/
public void subscribeListeners() {
gridActionsVisibilityListener.subscribe();
targetTagGridActionsVisibilityListener.subscribe();
entityTagModifiedListener.subscribe();
entityFilterQueryModifiedListener.subscribe();
targetTypeGridActionsVisibilityListener.subscribe();
entityTargetTypeModifiedListener.subscribe();
}
/**
* Unsubscribe event listeners
*/
public void unsubscribeListeners() {
gridActionsVisibilityListener.unsubscribe();
targetTagGridActionsVisibilityListener.unsubscribe();
entityTagModifiedListener.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.grid.header.AbstractFilterHeader;
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.UIMessageIdProvider;
@@ -28,23 +29,26 @@ public class TargetTagFilterHeader extends AbstractFilterHeader {
private final transient TargetTagWindowBuilder targetTagWindowBuilder;
private final transient TargetTypeWindowBuilder targetTypeWindowBuilder;
/**
* Constructor for TargetTagFilterHeader
*
* @param uiDependencies
* @param uiDependencies
* {@link CommonUiDependencies}
* @param targetTagFilterLayoutUiState
* TargetTagFilterLayoutUiState
* @param targetTagWindowBuilder
* TargetTagWindowBuilder
* @param targetTypeWindowBuilder
*/
public TargetTagFilterHeader(final CommonUiDependencies uiDependencies,
final TargetTagFilterLayoutUiState targetTagFilterLayoutUiState,
final TargetTagWindowBuilder targetTagWindowBuilder) {
final TargetTagFilterLayoutUiState targetTagFilterLayoutUiState,
final TargetTagWindowBuilder targetTagWindowBuilder, TargetTypeWindowBuilder targetTypeWindowBuilder) {
super(uiDependencies.getI18n(), uiDependencies.getPermChecker(), uiDependencies.getEventBus());
this.targetTagFilterLayoutUiState = targetTagFilterLayoutUiState;
this.targetTagWindowBuilder = targetTagWindowBuilder;
this.targetTypeWindowBuilder = targetTypeWindowBuilder;
buildHeader();
}
@@ -70,11 +74,17 @@ public class TargetTagFilterHeader extends AbstractFilterHeader {
@Override
protected Window getWindowForAdd() {
if (targetTagFilterLayoutUiState.isTargetTypeFilterTabSelected()) {
return targetTypeWindowBuilder.getWindowForAdd();
}
return targetTagWindowBuilder.getWindowForAdd();
}
@Override
protected String getAddEntityWindowCaptionMsgKey() {
if (targetTagFilterLayoutUiState.isTargetTypeFilterTabSelected()) {
return UIMessageIdProvider.CAPTION_TYPE;
}
return UIMessageIdProvider.CAPTION_TAG;
}

View File

@@ -8,9 +8,11 @@
*/
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.TargetManagement;
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.event.EventTopics;
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 com.vaadin.ui.ComponentContainer;
import org.eclipse.hawkbit.ui.management.targettag.targettype.TargetTypeWindowBuilder;
/**
* Target Tag filter layout.
@@ -49,16 +52,20 @@ public class TargetTagFilterLayout extends AbstractFilterLayout {
* TargetTagFilterLayoutUiState
*/
public TargetTagFilterLayout(final CommonUiDependencies uiDependencies, final ManagementUIState managementUIState,
final TargetFilterQueryManagement targetFilterQueryManagement,
final TargetTagManagement targetTagManagement, final TargetManagement targetManagement,
final TargetTagFilterLayoutUiState targetTagFilterLayoutUiState) {
final TargetFilterQueryManagement targetFilterQueryManagement,
final TargetTypeManagement targetTypeManagement,
final TargetTagManagement targetTagManagement, final TargetManagement targetManagement,
final TargetTagFilterLayoutUiState targetTagFilterLayoutUiState, final DistributionSetTypeManagement distributionSetTypeManagement) {
final TargetTagWindowBuilder targetTagWindowBuilder = new TargetTagWindowBuilder(uiDependencies,
targetTagManagement);
final TargetTypeWindowBuilder targetTypeWindowBuilder = new TargetTypeWindowBuilder(uiDependencies,
targetTypeManagement, distributionSetTypeManagement);
this.targetTagFilterHeader = new TargetTagFilterHeader(uiDependencies, targetTagFilterLayoutUiState,
targetTagWindowBuilder);
targetTagWindowBuilder, targetTypeWindowBuilder);
this.multipleTargetFilter = new MultipleTargetFilter(uiDependencies, targetFilterQueryManagement,
targetTagManagement, targetManagement, targetTagFilterLayoutUiState, targetTagWindowBuilder);
targetTagManagement, targetManagement, targetTagFilterLayoutUiState, targetTagWindowBuilder, targetTypeWindowBuilder, targetTypeManagement);
this.filterTabChangedListener = new GenericEventListener<>(uiDependencies.getEventBus(),
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 boolean isOverdueFilterClicked;
private boolean isCustomFilterTabSelected;
private boolean isTargetTypeFilterTabSelected;
/**
* @return Id of clicked target filter query
@@ -94,4 +96,13 @@ public class TargetTagFilterLayoutUiState extends TagFilterLayoutUiState {
public void setCustomFilterTabSelected(final boolean 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";
/**
* Id of "NO TARGET TYPE" button.
*/
public static final String NO_TARGET_TYPE_BUTTON_ID = "no_target_type_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";
/**
* Target type filter header layout.
*/
public static final String TARGET_TYPE_FILTER_HEADER = "target-type-filter-header";
/**
* 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";
/**
* 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.
*/
@@ -929,6 +939,11 @@ public final class UIComponentIdProvider {
*/
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
*/
@@ -1337,6 +1352,22 @@ public final class UIComponentIdProvider {
* Table multiselect for selecting DistType
*/
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
*/
@@ -1528,6 +1559,10 @@ public final class UIComponentIdProvider {
* Target tag button id prefix.
*/
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.
*/

View File

@@ -89,10 +89,14 @@ public final class UIMessageIdProvider {
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_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_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.dist.twintable.selected=Selected
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.assigned = Assigned
header.type=Type
@@ -112,6 +114,7 @@ caption.entity.missing.error = Entity is missing
caption.new.softwaremodule.application = Configure New Application
caption.new.softwaremodule.os = Configure New OS
caption.filter.simple = Simple Filter
caption.filter.type = Type Filter
caption.filter.custom = Custom Filter
caption.metadata = Metadata
caption.rollout.name = Rollout name
@@ -177,6 +180,7 @@ label.menu = Menu
label.active = Active
label.action.id = Action Id
label.no.tag = NO TAG
label.no.target.type = NO TARGET TYPE
label.action.forced = Forced
label.action.type = Type
label.action.soft = Soft
@@ -408,6 +412,7 @@ message.cannot.delete = Cannot be deleted
message.check.softwaremodule = Please provide both name and version!
message.duplicate.softwaremodule = {0} : {1} already exists!
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.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
@@ -480,6 +485,7 @@ message.error.missing.filtername = Please select target filter name
message.error.missing.controllerId = Missing Controller Id
message.error.missing.nameorversion = Missing Name or Version
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.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
@@ -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.tags = Target Tags
caption.entity.target.type = Target Type
caption.entity.target.types = Target Types
caption.entity.distribution.tag = Distribution Tag
caption.entity.distribution.tags = Distribution Tags
caption.entity.distribution.type = Distribution set Type