Adapt UI for target type compatibility check (#1189)
* Added compatibility calls needed for UI Signed-off-by: Robert Sing <robert.sing@bosch-si.com> * Adapted UI for target type compatibility checks Signed-off-by: Robert Sing <robert.sing@bosch-si.com> * improved exception handling for incompatibility check Signed-off-by: Robert Sing <robert.sing@bosch-si.com> * added & fixed unit tests Signed-off-by: Robert Sing <robert.sing@bosch-si.com> * fixed merged conflicts Signed-off-by: Robert Sing <robert.sing@bosch-si.com> * fixed target type incompatibly specification Signed-off-by: Robert Sing <robert.sing@bosch-si.com> * changed UI behaviour to close assignment popup in case of IncompatibleTargetTypeException Signed-off-by: Robert Sing <robert.sing@bosch-si.com> * added unit test to validate incompatibly specification fix Signed-off-by: Robert Sing <robert.sing@bosch-si.com> * fixed review findings Signed-off-by: Robert Sing <robert.sing@bosch-si.com> * fixed review findings Signed-off-by: Robert Sing <robert.sing@bosch-si.com> * fix potential null pointer Signed-off-by: Robert Sing <robert.sing@bosch-si.com> * Fixed rolloutcopy by adding dsTypeId to ProxyDistributionSetInfo Signed-off-by: Robert Sing <robert.sing@bosch-si.com> * suppressed warning Signed-off-by: Robert Sing <robert.sing@bosch-si.com>
This commit is contained in:
@@ -20,6 +20,7 @@ import org.eclipse.hawkbit.ui.common.data.suppliers.TargetManagementStateDataSup
|
||||
import org.eclipse.hawkbit.ui.error.HawkbitUIErrorHandler;
|
||||
import org.eclipse.hawkbit.ui.error.extractors.ConstraintViolationErrorExtractor;
|
||||
import org.eclipse.hawkbit.ui.error.extractors.EntityNotFoundErrorExtractor;
|
||||
import org.eclipse.hawkbit.ui.error.extractors.IncompatibleTargetTypeErrorExtractor;
|
||||
import org.eclipse.hawkbit.ui.error.extractors.InsufficientPermissionErrorExtractor;
|
||||
import org.eclipse.hawkbit.ui.error.extractors.InvalidDistributionSetErrorExtractor;
|
||||
import org.eclipse.hawkbit.ui.error.extractors.UiErrorDetailsExtractor;
|
||||
@@ -144,9 +145,21 @@ public class MgmtUiConfiguration {
|
||||
return new EntityNotFoundErrorExtractor(i18n);
|
||||
}
|
||||
|
||||
/**
|
||||
* UI incompatible Target Type error details extractor bean.
|
||||
*
|
||||
* @param i18n
|
||||
* VaadinMessageSource
|
||||
* @return UI IncompatibleTargetType Error details extractor
|
||||
*/
|
||||
@Bean
|
||||
UiErrorDetailsExtractor incompatibleTargetTypeErrorExtractor(final VaadinMessageSource i18n) {
|
||||
return new IncompatibleTargetTypeErrorExtractor(i18n);
|
||||
}
|
||||
|
||||
/**
|
||||
* UI Insufficient Permission Error details extractor bean.
|
||||
*
|
||||
*
|
||||
* @param i18n
|
||||
* VaadinMessageSource
|
||||
* @return UI InsufficientPermission Error details extractor
|
||||
|
||||
@@ -26,7 +26,8 @@ public class RolloutToProxyRolloutMapper extends AbstractNamedEntityToProxyNamed
|
||||
mapNamedEntityAttributes(rollout, proxyRollout);
|
||||
|
||||
final DistributionSet ds = rollout.getDistributionSet();
|
||||
proxyRollout.setDsInfo(new ProxyDistributionSetInfo(ds.getId(), ds.getName(), ds.getVersion(), ds.isValid()));
|
||||
proxyRollout.setDsInfo(new ProxyDistributionSetInfo(ds.getId(), ds.getName(), ds.getVersion(),
|
||||
ds.getType().getId(), ds.isValid()));
|
||||
proxyRollout
|
||||
.setNumberOfGroups(rollout.getRolloutGroupsCreated() > 0 ? rollout.getRolloutGroupsCreated() : null);
|
||||
proxyRollout.setForcedTime(rollout.getForcedTime() > 0 ? rollout.getForcedTime() : null);
|
||||
|
||||
@@ -38,7 +38,8 @@ public class TargetFilterQueryToProxyTargetFilterMapper
|
||||
if (distributionSet != null) {
|
||||
proxyTargetFilter.setAutoAssignmentEnabled(true);
|
||||
proxyTargetFilter.setDistributionSetInfo(new ProxyDistributionSetInfo(distributionSet.getId(),
|
||||
distributionSet.getName(), distributionSet.getVersion(), distributionSet.isValid()));
|
||||
distributionSet.getName(), distributionSet.getVersion(), distributionSet.getType().getId(),
|
||||
distributionSet.isValid()));
|
||||
proxyTargetFilter.setAutoAssignActionType(targetFilterQuery.getAutoAssignActionType());
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,6 @@ public class ProxyDistributionSet extends ProxyNamedEntity implements VersionAwa
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
* Flag that indicates if the distribution set is valid.
|
||||
*
|
||||
* @return <code>true</code> if the distribution set is valid, otherwise
|
||||
@@ -163,6 +162,7 @@ public class ProxyDistributionSet extends ProxyNamedEntity implements VersionAwa
|
||||
ds.setId(dsInfo.getId());
|
||||
ds.setName(dsInfo.getName());
|
||||
ds.setVersion(dsInfo.getVersion());
|
||||
ds.setTypeInfo(new ProxyTypeInfo(dsInfo.getDsTypeId(), null));
|
||||
ds.setNameVersion(dsInfo.getNameVersion());
|
||||
ds.setIsValid(dsInfo.isValid());
|
||||
|
||||
@@ -170,11 +170,12 @@ public class ProxyDistributionSet extends ProxyNamedEntity implements VersionAwa
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Id, Name and version of distribution set
|
||||
* Gets the Id, name, version, dsTypeId and invalidation state of distribution
|
||||
* set
|
||||
*
|
||||
* @return proxy of Id, Name and version
|
||||
* @return proxy of Id, name, version, dsTypeId and invalidation state
|
||||
*/
|
||||
public ProxyDistributionSetInfo getInfo() {
|
||||
return new ProxyDistributionSetInfo(getId(), getName(), getVersion(), getIsValid());
|
||||
return new ProxyDistributionSetInfo(getId(), getName(), getVersion(), getTypeInfo().getId(), getIsValid());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ public class ProxyDistributionSetInfo extends ProxyIdentifiableEntity {
|
||||
private String name;
|
||||
private String version;
|
||||
private String nameVersion;
|
||||
private Long dsTypeId;
|
||||
private boolean isValid;
|
||||
|
||||
/**
|
||||
@@ -39,12 +40,18 @@ public class ProxyDistributionSetInfo extends ProxyIdentifiableEntity {
|
||||
* distribution set name
|
||||
* @param version
|
||||
* distribution set version
|
||||
* @param dsTypeId
|
||||
* ID of the assigned dsType
|
||||
* @param isValid
|
||||
* invalidation state
|
||||
*/
|
||||
public ProxyDistributionSetInfo(final Long id, final String name, final String version, final boolean isValid) {
|
||||
public ProxyDistributionSetInfo(final Long id, final String name, final String version, final Long dsTypeId,
|
||||
final boolean isValid) {
|
||||
super(id);
|
||||
|
||||
this.name = name;
|
||||
this.version = version;
|
||||
this.dsTypeId = dsTypeId;
|
||||
this.isValid = isValid;
|
||||
this.nameVersion = HawkbitCommonUtil.getFormattedNameVersion(name, version);
|
||||
}
|
||||
@@ -81,13 +88,23 @@ public class ProxyDistributionSetInfo extends ProxyIdentifiableEntity {
|
||||
this.isValid = isValid;
|
||||
}
|
||||
|
||||
public Long getDsTypeId() {
|
||||
return dsTypeId;
|
||||
}
|
||||
|
||||
public void setDsTypeId(final Long dsTypeId) {
|
||||
this.dsTypeId = dsTypeId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// nameVersion is ignored because it is a composition of name and
|
||||
// version
|
||||
return Objects.hash(getId(), getName(), getVersion(), isValid());
|
||||
return Objects.hash(getId(), getName(), getVersion(), getDsTypeId(), isValid());
|
||||
}
|
||||
|
||||
// equals method requires all of the used conditions
|
||||
@SuppressWarnings("squid:S1067")
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (obj == null) {
|
||||
@@ -102,6 +119,7 @@ public class ProxyDistributionSetInfo extends ProxyIdentifiableEntity {
|
||||
// version
|
||||
return Objects.equals(this.getId(), other.getId()) && Objects.equals(this.getName(), other.getName())
|
||||
&& Objects.equals(this.getVersion(), other.getVersion())
|
||||
&& Objects.equals(this.getDsTypeId(), other.getDsTypeId())
|
||||
&& Objects.equals(this.isValid(), other.isValid());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 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.error.extractors;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.hawkbit.repository.exception.IncompatibleTargetTypeException;
|
||||
import org.eclipse.hawkbit.ui.error.UiErrorDetails;
|
||||
import org.eclipse.hawkbit.ui.utils.UIMessageIdProvider;
|
||||
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
||||
|
||||
/**
|
||||
* UI error details extractor for {@link IncompatibleTargetTypeException}.
|
||||
*/
|
||||
public class IncompatibleTargetTypeErrorExtractor extends AbstractSingleUiErrorDetailsExtractor {
|
||||
|
||||
private final VaadinMessageSource i18n;
|
||||
|
||||
/**
|
||||
* Constructor for IncompatibleTargetTypeErrorExtractor.
|
||||
*
|
||||
* @param i18n
|
||||
* Message source used for localization
|
||||
*/
|
||||
public IncompatibleTargetTypeErrorExtractor(final VaadinMessageSource i18n) {
|
||||
this.i18n = i18n;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<UiErrorDetails> findDetails(final Throwable error) {
|
||||
return findExceptionOf(error, IncompatibleTargetTypeException.class)
|
||||
.map(ex -> UiErrorDetails.create(i18n.getMessage("caption.error"),
|
||||
i18n.getMessage(UIMessageIdProvider.MESSAGE_ERROR_TARGET_TYPE_INCOMPATIBLE,
|
||||
ex.getTargetTypeNames(), ex.getDistributionSetTypeNames())));
|
||||
}
|
||||
}
|
||||
@@ -64,8 +64,8 @@ public class DeploymentAssignmentWindowController {
|
||||
* @param deploymentManagement
|
||||
* DeploymentManagement
|
||||
*/
|
||||
public DeploymentAssignmentWindowController(final CommonUiDependencies uiDependencies, final UiProperties uiProperties,
|
||||
final DeploymentManagement deploymentManagement) {
|
||||
public DeploymentAssignmentWindowController(final CommonUiDependencies uiDependencies,
|
||||
final UiProperties uiProperties, final DeploymentManagement deploymentManagement) {
|
||||
this.i18n = uiDependencies.getI18n();
|
||||
this.eventBus = uiDependencies.getEventBus();
|
||||
this.notification = uiDependencies.getUiNotification();
|
||||
|
||||
@@ -56,6 +56,7 @@ public class AdvancedGroupsLayout extends ValidatableLayout {
|
||||
private final GridLayout layout;
|
||||
|
||||
private String targetFilter;
|
||||
private Long dsTypeId;
|
||||
|
||||
private final List<AdvancedGroupRow> groupRows;
|
||||
private int lastGroupIndex;
|
||||
@@ -237,7 +238,7 @@ public class AdvancedGroupsLayout extends ValidatableLayout {
|
||||
private void validateTargetsPerGroup() {
|
||||
resetErrors();
|
||||
|
||||
if (StringUtils.isEmpty(targetFilter)) {
|
||||
if (StringUtils.isEmpty(targetFilter) || dsTypeId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -245,7 +246,7 @@ public class AdvancedGroupsLayout extends ValidatableLayout {
|
||||
final List<RolloutGroupCreate> groupsCreate = getRolloutGroupsCreateFromDefinitions(
|
||||
getAdvancedRolloutGroupDefinitions());
|
||||
final ListenableFuture<RolloutGroupsValidation> validateTargetsInGroups = rolloutManagement
|
||||
.validateTargetsInGroups(groupsCreate, targetFilter, System.currentTimeMillis());
|
||||
.validateTargetsInGroups(groupsCreate, targetFilter, System.currentTimeMillis(), dsTypeId);
|
||||
|
||||
final UI ui = UI.getCurrent();
|
||||
validateTargetsInGroups.addCallback(validation -> ui.access(() -> updateGroupsByValidation(validation)),
|
||||
@@ -273,10 +274,9 @@ public class AdvancedGroupsLayout extends ValidatableLayout {
|
||||
}
|
||||
|
||||
/**
|
||||
* YOU SHOULD NOT CALL THIS METHOD MANUALLY. It's only for the callback.
|
||||
* Only 1 runningValidation should be executed. If this runningValidation is
|
||||
* done, then this method is called. Maybe then a new runningValidation is
|
||||
* executed.
|
||||
* YOU SHOULD NOT CALL THIS METHOD MANUALLY. It's only for the callback. Only 1
|
||||
* runningValidation should be executed. If this runningValidation is done, then
|
||||
* this method is called. Maybe then a new runningValidation is executed.
|
||||
*
|
||||
*/
|
||||
private void updateGroupsByValidation(final RolloutGroupsValidation validation) {
|
||||
@@ -338,7 +338,30 @@ public class AdvancedGroupsLayout extends ValidatableLayout {
|
||||
*/
|
||||
public void setTargetFilter(final String targetFilter) {
|
||||
this.targetFilter = targetFilter;
|
||||
updateValidation();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param dsTypeId
|
||||
* ID of the Distribution set type which is required for the
|
||||
* compatibility check
|
||||
*/
|
||||
public void setDsTypeId(final Long dsTypeId) {
|
||||
this.dsTypeId = dsTypeId;
|
||||
updateValidation();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param targetFilter
|
||||
* the target filter which is required for verification
|
||||
* @param dsTypeId
|
||||
* ID of the Distribution set type which is required for the
|
||||
* compatibility check
|
||||
*/
|
||||
public void setTargetFilterAndDsType(final String targetFilter, final Long dsTypeId) {
|
||||
this.targetFilter = targetFilter;
|
||||
this.dsTypeId = dsTypeId;
|
||||
updateValidation();
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
||||
|
||||
import com.vaadin.data.Binder;
|
||||
import com.vaadin.data.Binder.Binding;
|
||||
import com.vaadin.data.HasValue;
|
||||
import com.vaadin.data.ValidationException;
|
||||
import com.vaadin.data.Validator;
|
||||
import com.vaadin.data.validator.LongRangeValidator;
|
||||
@@ -72,6 +73,7 @@ public class RolloutFormLayout extends ValidatableLayout {
|
||||
private Long totalTargets;
|
||||
|
||||
private Consumer<String> filterQueryChangedListener;
|
||||
private Consumer<Long> distSetChangedListener;
|
||||
|
||||
/**
|
||||
* Constructor for RolloutFormLayout
|
||||
@@ -190,11 +192,8 @@ public class RolloutFormLayout extends ValidatableLayout {
|
||||
}
|
||||
|
||||
private void addValueChangeListeners() {
|
||||
targetFilterQueryCombo.getComponent().addValueChangeListener(event -> {
|
||||
if (filterQueryChangedListener != null) {
|
||||
filterQueryChangedListener.accept(event.getValue() != null ? event.getValue().getQuery() : null);
|
||||
}
|
||||
});
|
||||
targetFilterQueryCombo.getComponent().addValueChangeListener(filterQueryChangedListener());
|
||||
dsCombo.addValueChangeListener(distSetChangedListener());
|
||||
|
||||
actionTypeLayout.getComponent().getActionTypeOptionGroup().addValueChangeListener(
|
||||
event -> actionTypeLayout.setRequired(event.getValue() == ActionType.TIMEFORCED));
|
||||
@@ -202,6 +201,26 @@ public class RolloutFormLayout extends ValidatableLayout {
|
||||
event -> autoStartOptionGroupLayout.setRequired(event.getValue() == AutoStartOption.SCHEDULED));
|
||||
}
|
||||
|
||||
private HasValue.ValueChangeListener<ProxyTargetFilterQuery> filterQueryChangedListener() {
|
||||
return event -> {
|
||||
if (filterQueryChangedListener != null) {
|
||||
filterQueryChangedListener.accept(event.getValue() != null ? event.getValue().getQuery() : null);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private HasValue.ValueChangeListener<ProxyDistributionSet> distSetChangedListener() {
|
||||
return event -> {
|
||||
if (distSetChangedListener != null) {
|
||||
if (event.getValue() != null && event.getValue().getTypeInfo() != null) {
|
||||
distSetChangedListener.accept(event.getValue().getTypeInfo().getId());
|
||||
} else {
|
||||
distSetChangedListener.accept(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Add rollout form to add layout
|
||||
*
|
||||
@@ -285,6 +304,16 @@ public class RolloutFormLayout extends ValidatableLayout {
|
||||
this.filterQueryChangedListener = filterQueryChangedListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the changed listener for distribution set
|
||||
*
|
||||
* @param distSetChangedListener
|
||||
* Changed listener
|
||||
*/
|
||||
public void setDistSetChangedListener(final Consumer<Long> distSetChangedListener) {
|
||||
this.distSetChangedListener = distSetChangedListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the count of total targets
|
||||
*
|
||||
|
||||
@@ -61,7 +61,7 @@ public class VisualGroupDefinitionLayout {
|
||||
|
||||
if (groupDefinitionMode == GroupDefinitionMode.SIMPLE) {
|
||||
updateBySimpleGroupsDefinition();
|
||||
} else {
|
||||
} else if (groupDefinitionMode == GroupDefinitionMode.ADVANCED) {
|
||||
updateByAdvancedGroupsDefinition();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ public class AddRolloutWindowLayout extends AbstractRolloutWindowLayout {
|
||||
private final VisualGroupDefinitionLayout visualGroupDefinitionLayout;
|
||||
|
||||
private String filterQuery;
|
||||
private Long dsTypeId;
|
||||
private Long totalTargets;
|
||||
private int noOfGroups;
|
||||
private List<ProxyAdvancedRolloutGroup> advancedRolloutGroupDefinitions;
|
||||
@@ -82,24 +83,33 @@ public class AddRolloutWindowLayout extends AbstractRolloutWindowLayout {
|
||||
}
|
||||
|
||||
private void addValueChangeListeners() {
|
||||
rolloutFormLayout.setFilterQueryChangedListener(this::onTargetFilterQueryChange);
|
||||
rolloutFormLayout.setFilterQueryChangedListener(this::onFilterQueryChange);
|
||||
rolloutFormLayout.setDistSetChangedListener(this::onDistSetTypeChange);
|
||||
groupsDefinitionTabs.addSelectedTabChangeListener(event -> onGroupDefinitionTabChanged());
|
||||
simpleGroupsLayout.setNoOfGroupsChangedListener(this::onNoOfSimpleGroupsChanged);
|
||||
advancedGroupsLayout.setAdvancedGroupDefinitionsChangedListener(this::onAdvancedGroupsChanged);
|
||||
}
|
||||
|
||||
private void onTargetFilterQueryChange(final String filterQuery) {
|
||||
private void onFilterQueryChange(final String filterQuery) {
|
||||
this.filterQuery = filterQuery;
|
||||
|
||||
totalTargets = !StringUtils.isEmpty(filterQuery) ? targetManagement.countByRsql(filterQuery) : null;
|
||||
updateTotalTargetsAwareComponents();
|
||||
updateTotalTargets();
|
||||
|
||||
if (isAdvancedGroupsTabSelected()) {
|
||||
advancedGroupsLayout.setTargetFilter(filterQuery);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTotalTargetsAwareComponents() {
|
||||
private void onDistSetTypeChange(final Long dsTypeId) {
|
||||
this.dsTypeId = dsTypeId;
|
||||
updateTotalTargets();
|
||||
|
||||
if (isAdvancedGroupsTabSelected()) {
|
||||
advancedGroupsLayout.setDsTypeId(dsTypeId);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTotalTargets() {
|
||||
this.totalTargets = getTotalTargets(filterQuery, dsTypeId);
|
||||
rolloutFormLayout.setTotalTargets(totalTargets);
|
||||
visualGroupDefinitionLayout.setTotalTargets(totalTargets);
|
||||
if (isSimpleGroupsTabSelected()) {
|
||||
@@ -107,6 +117,16 @@ public class AddRolloutWindowLayout extends AbstractRolloutWindowLayout {
|
||||
}
|
||||
}
|
||||
|
||||
private Long getTotalTargets(final String filterQuery, final Long distSetTypeId) {
|
||||
if (StringUtils.isEmpty(filterQuery)) {
|
||||
return null;
|
||||
}
|
||||
if (distSetTypeId == null) {
|
||||
return targetManagement.countByRsql(filterQuery);
|
||||
}
|
||||
return targetManagement.countByRsqlAndCompatible(filterQuery, distSetTypeId);
|
||||
}
|
||||
|
||||
private boolean isSimpleGroupsTabSelected() {
|
||||
return groupsDefinitionTabs.getSelectedTab().equals(simpleGroupsLayout.getLayout());
|
||||
}
|
||||
@@ -128,7 +148,7 @@ public class AddRolloutWindowLayout extends AbstractRolloutWindowLayout {
|
||||
if (isAdvancedGroupsTabSelected()) {
|
||||
adaptAdvancedGroupsValidation();
|
||||
|
||||
advancedGroupsLayout.setTargetFilter(filterQuery);
|
||||
advancedGroupsLayout.setTargetFilterAndDsType(filterQuery, dsTypeId);
|
||||
|
||||
visualGroupDefinitionLayout.setGroupDefinitionMode(GroupDefinitionMode.ADVANCED);
|
||||
visualGroupDefinitionLayout.setAdvancedRolloutGroupDefinitions(advancedRolloutGroupDefinitions);
|
||||
@@ -209,7 +229,6 @@ public class AddRolloutWindowLayout extends AbstractRolloutWindowLayout {
|
||||
proxyEntity.setAdvancedRolloutGroupDefinitions(advancedGroupsLayout.getAdvancedRolloutGroupDefinitions());
|
||||
proxyEntity.setGroupDefinitionMode(GroupDefinitionMode.ADVANCED);
|
||||
}
|
||||
|
||||
return proxyEntity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,6 +163,8 @@ public final class UIMessageIdProvider {
|
||||
|
||||
public static final String MESSAGE_ERROR_PERMISSION_INSUFFICIENT = "message.permission.insufficient";
|
||||
|
||||
public static final String MESSAGE_ERROR_TARGET_TYPE_INCOMPATIBLE = "message.target.type.incompatible";
|
||||
|
||||
public static final String CRON_VALIDATION_ERROR = "message.maintenancewindow.schedule.validation.error";
|
||||
|
||||
public static final String TOOLTIP_OVERDUE = "tooltip.overdue";
|
||||
|
||||
@@ -538,6 +538,7 @@ message.invalidate.distributionset.affected.entities.intro.plural = When you con
|
||||
message.invalidate.distributionset.affected.entities.actions = {0} action(s) will be canceled
|
||||
message.invalidate.distributionset.affected.entities.rollouts = {0} rollout(s) will be stopped
|
||||
message.invalidate.distributionset.affected.entities.autoassignments = {0} auto assignment(s) will be stopped
|
||||
message.target.type.incompatible = Target(s) of type(s) {0} not compatible with distribution set type(s) {1}
|
||||
|
||||
# action info
|
||||
action.target.table.selectall = Select all (Ctrl+A)
|
||||
|
||||
Reference in New Issue
Block a user