Merge branch 'master' into feature_auto_assignment_squashed
This commit is contained in:
@@ -11,34 +11,31 @@
|
||||
-->
|
||||
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.5.1//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.5.1/distro-source/core/src/gwt-module.dtd">
|
||||
<module>
|
||||
<!-- This file is automatically updated based on new dependencies by the
|
||||
goal "vaadin:update-widgetset". -->
|
||||
<!-- This file is automatically updated based on new dependencies by the goal "vaadin:update-widgetset". -->
|
||||
|
||||
<!-- Inherit DefaultWidgetSet -->
|
||||
<inherits name="com.vaadin.DefaultWidgetSet" />
|
||||
<!-- Inherit DefaultWidgetSet -->
|
||||
<inherits name="com.vaadin.DefaultWidgetSet" />
|
||||
|
||||
<inherits
|
||||
name="org.vaadin.hene.flexibleoptiongroup.widgetset.FlexibleOptionGroupWidgetset" />
|
||||
<inherits name="org.vaadin.hene.flexibleoptiongroup.widgetset.FlexibleOptionGroupWidgetset" />
|
||||
|
||||
<inherits name="org.vaadin.tokenfield.TokenfieldWidgetset" />
|
||||
<inherits name="org.vaadin.tokenfield.TokenfieldWidgetset" />
|
||||
|
||||
|
||||
<inherits
|
||||
name="org.vaadin.alump.distributionbar.gwt.DistributionBarWidgetset" />
|
||||
<inherits name="org.vaadin.alump.distributionbar.gwt.DistributionBarWidgetset" />
|
||||
|
||||
|
||||
|
||||
<inherits name="org.vaadin.peter.contextmenu.ContextmenuWidgetset" />
|
||||
<inherits name="org.vaadin.peter.contextmenu.ContextmenuWidgetset" />
|
||||
|
||||
<inherits
|
||||
name="org.vaadin.hene.flexibleoptiongroup.widgetset.FlexibleOptionGroupWidgetset" />
|
||||
<inherits name="org.vaadin.hene.flexibleoptiongroup.widgetset.FlexibleOptionGroupWidgetset" />
|
||||
|
||||
<inherits
|
||||
name="org.vaadin.alump.distributionbar.gwt.DistributionBarWidgetset" />
|
||||
<inherits name="org.vaadin.alump.distributionbar.gwt.DistributionBarWidgetset" />
|
||||
|
||||
<inherits name="org.eclipse.hawkbit.ui.customrenderers.CustomRendererWidgetSet" />
|
||||
<inherits name="org.eclipse.hawkbit.ui.customrenderers.CustomRendererWidgetSet" />
|
||||
<inherits name="org.eclipse.hawkbit.ui.filtermanagement.TextFieldSuggestionBox" />
|
||||
|
||||
<inherits name="org.vaadin.hene.flexibleoptiongroup.widgetset.FlexibleOptionGroupWidgetset" />
|
||||
|
||||
<inherits name="org.vaadin.hene.flexibleoptiongroup.widgetset.FlexibleOptionGroupWidgetset" />
|
||||
|
||||
<inherits name="org.vaadin.alump.distributionbar.gwt.DistributionBarWidgetset" />
|
||||
<inherits name="org.vaadin.alump.distributionbar.gwt.DistributionBarWidgetset" />
|
||||
</module>
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
package org.eclipse.hawkbit.ui.artifacts.details;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -46,6 +46,7 @@ import org.vaadin.spring.events.EventScope;
|
||||
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.vaadin.data.Container;
|
||||
import com.vaadin.server.FontAwesome;
|
||||
import com.vaadin.shared.ui.label.ContentMode;
|
||||
@@ -207,8 +208,7 @@ public class ArtifactDetailsLayout extends VerticalLayout {
|
||||
}
|
||||
|
||||
private Container createArtifactLazyQueryContainer() {
|
||||
final Map<String, Object> queryConfiguration = new HashMap<>();
|
||||
return getArtifactLazyQueryContainer(queryConfiguration);
|
||||
return getArtifactLazyQueryContainer(Collections.emptyMap());
|
||||
}
|
||||
|
||||
private LazyQueryContainer getArtifactLazyQueryContainer(final Map<String, Object> queryConfig) {
|
||||
@@ -429,9 +429,12 @@ public class ArtifactDetailsLayout extends VerticalLayout {
|
||||
titleOfArtifactDetails.setContentMode(ContentMode.HTML);
|
||||
}
|
||||
}
|
||||
final Map<String, Object> queryConfiguration = new HashMap<>();
|
||||
final Map<String, Object> queryConfiguration;
|
||||
if (baseSwModuleId != null) {
|
||||
queryConfiguration = Maps.newHashMapWithExpectedSize(1);
|
||||
queryConfiguration.put(SPUIDefinitions.BY_BASE_SOFTWARE_MODULE, baseSwModuleId);
|
||||
} else {
|
||||
queryConfiguration = Collections.emptyMap();
|
||||
}
|
||||
final LazyQueryContainer artifactContainer = getArtifactLazyQueryContainer(queryConfiguration);
|
||||
artifactDetailsTable.setContainerDataSource(artifactContainer);
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
package org.eclipse.hawkbit.ui.artifacts.event;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.hawkbit.ui.common.AbstractAcceptCriteria;
|
||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.vaadin.spring.annotation.SpringComponent;
|
||||
import com.vaadin.spring.annotation.ViewScope;
|
||||
import com.vaadin.ui.Component;
|
||||
@@ -54,7 +54,7 @@ public class UploadViewAcceptCriteria extends AbstractAcceptCriteria {
|
||||
}
|
||||
|
||||
private static Map<String, List<String>> createDropConfigurations() {
|
||||
final Map<String, List<String>> config = new HashMap<>();
|
||||
final Map<String, List<String>> config = Maps.newHashMapWithExpectedSize(1);
|
||||
// Delete drop area droppable components
|
||||
config.put(UIComponentIdProvider.DELETE_BUTTON_WRAPPER_ID, Arrays.asList(
|
||||
UIComponentIdProvider.UPLOAD_SOFTWARE_MODULE_TABLE, UIComponentIdProvider.UPLOAD_TYPE_BUTTON_PREFIX));
|
||||
@@ -63,7 +63,7 @@ public class UploadViewAcceptCriteria extends AbstractAcceptCriteria {
|
||||
}
|
||||
|
||||
private static Map<String, Object> createDropHintConfigurations() {
|
||||
final Map<String, Object> config = new HashMap<>();
|
||||
final Map<String, Object> config = Maps.newHashMapWithExpectedSize(2);
|
||||
config.put(UIComponentIdProvider.UPLOAD_TYPE_BUTTON_PREFIX, UploadArtifactUIEvent.SOFTWARE_TYPE_DRAG_START);
|
||||
config.put(UIComponentIdProvider.UPLOAD_SOFTWARE_MODULE_TABLE, UploadArtifactUIEvent.SOFTWARE_DRAG_START);
|
||||
return config;
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
package org.eclipse.hawkbit.ui.artifacts.footer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -21,11 +20,12 @@ import org.eclipse.hawkbit.ui.artifacts.state.CustomFile;
|
||||
import org.eclipse.hawkbit.ui.common.confirmwindow.layout.AbstractConfirmationWindowLayout;
|
||||
import org.eclipse.hawkbit.ui.common.confirmwindow.layout.ConfirmationTab;
|
||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.vaadin.data.Container;
|
||||
import com.vaadin.data.Item;
|
||||
import com.vaadin.data.util.IndexedContainer;
|
||||
@@ -64,7 +64,7 @@ public class UploadViewConfirmationWindowLayout extends AbstractConfirmationWind
|
||||
|
||||
@Override
|
||||
protected Map<String, ConfirmationTab> getConfimrationTabs() {
|
||||
final Map<String, ConfirmationTab> tabs = new HashMap<>();
|
||||
final Map<String, ConfirmationTab> tabs = Maps.newHashMapWithExpectedSize(2);
|
||||
if (!artifactUploadState.getDeleteSofwareModules().isEmpty()) {
|
||||
tabs.put(i18n.get("caption.delete.swmodule.accordion.tab"), createSMDeleteConfirmationTab());
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.artifacts.smtable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -25,11 +24,11 @@ import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
||||
import org.eclipse.hawkbit.ui.distributions.smtable.SwMetadataPopupLayout;
|
||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.TableColumn;
|
||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory;
|
||||
import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer;
|
||||
@@ -37,6 +36,7 @@ import org.vaadin.addons.lazyquerycontainer.LazyQueryDefinition;
|
||||
import org.vaadin.spring.events.EventScope;
|
||||
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.vaadin.data.Container;
|
||||
import com.vaadin.data.Item;
|
||||
import com.vaadin.event.dd.DragAndDropEvent;
|
||||
@@ -97,7 +97,7 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable<SoftwareModul
|
||||
}
|
||||
|
||||
private Map<String, Object> prepareQueryConfigFilters() {
|
||||
final Map<String, Object> queryConfig = new HashMap<>();
|
||||
final Map<String, Object> queryConfig = Maps.newHashMapWithExpectedSize(2);
|
||||
artifactUploadState.getSoftwareModuleFilters().getSearchText()
|
||||
.ifPresent(value -> queryConfig.put(SPUIDefinitions.FILTER_BY_TEXT, value));
|
||||
|
||||
|
||||
@@ -32,11 +32,11 @@ import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleTiny;
|
||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.SpringContextHelper;
|
||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -572,6 +572,9 @@ public class UploadConfirmationWindow implements Button.ClickListener {
|
||||
|
||||
}
|
||||
|
||||
// Exception squid:S3655 - Optional access is checked in
|
||||
// checkIfArtifactDetailsDispalyed subroutine
|
||||
@SuppressWarnings("squid:S3655")
|
||||
private void processArtifactUpload() {
|
||||
final List<String> itemIds = (List<String>) uploadDetailsTable.getItemIds();
|
||||
if (preUploadValidation(itemIds)) {
|
||||
@@ -593,6 +596,7 @@ public class UploadConfirmationWindow implements Button.ClickListener {
|
||||
}
|
||||
refreshArtifactDetailsLayout = checkIfArtifactDetailsDispalyed(bSoftwareModule.getId());
|
||||
}
|
||||
|
||||
if (refreshArtifactDetailsLayout) {
|
||||
uploadLayout.refreshArtifactDetailsLayout(artifactUploadState.getSelectedBaseSoftwareModule().get());
|
||||
}
|
||||
|
||||
@@ -34,10 +34,10 @@ import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmall;
|
||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||
import org.eclipse.hawkbit.ui.utils.UINotification;
|
||||
import org.eclipse.hawkbit.util.SPInfo;
|
||||
import org.slf4j.Logger;
|
||||
@@ -254,6 +254,11 @@ public class UploadLayout extends VerticalLayout {
|
||||
final Html5File[] files = ((WrapperTransferable) event.getTransferable()).getFiles();
|
||||
// selected software module at the time of file drop is
|
||||
// considered for upload
|
||||
|
||||
if (!artifactUploadState.getSelectedBaseSoftwareModule().isPresent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final SoftwareModule selectedSw = artifactUploadState.getSelectedBaseSoftwareModule().get();
|
||||
// reset the flag
|
||||
hasDirectory = Boolean.FALSE;
|
||||
@@ -589,7 +594,9 @@ public class UploadLayout extends VerticalLayout {
|
||||
// delete file system zombies
|
||||
artifactUploadState.getFileSelected().forEach(customFile -> {
|
||||
final File file = new File(customFile.getFilePath());
|
||||
file.delete();
|
||||
if (!file.delete()) {
|
||||
LOG.warn("Failed to delete file {} in upload dialog", customFile.getFilePath());
|
||||
}
|
||||
});
|
||||
|
||||
artifactUploadState.getFileSelected().clear();
|
||||
|
||||
@@ -12,7 +12,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -28,11 +27,12 @@ import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleNoBorderWithIcon;
|
||||
import org.eclipse.hawkbit.ui.layouts.AbstractCreateUpdateTagLayout;
|
||||
import org.eclipse.hawkbit.ui.management.targettable.TargetAddUpdateWindowLayout;
|
||||
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||
import org.vaadin.hene.flexibleoptiongroup.FlexibleOptionGroupItemComponent;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.vaadin.data.Container.ItemSetChangeEvent;
|
||||
import com.vaadin.data.Container.ItemSetChangeListener;
|
||||
@@ -129,8 +129,8 @@ public class CommonDialogWindow extends Window {
|
||||
this.helpLink = helpLink;
|
||||
this.closeListener = closeListener;
|
||||
this.cancelButtonClickListener = cancelButtonClickListener;
|
||||
this.orginalValues = new HashMap<>();
|
||||
this.allComponents = getAllComponents(layout);
|
||||
this.orginalValues = Maps.newHashMapWithExpectedSize(allComponents.size());
|
||||
this.i18n = i18n;
|
||||
init();
|
||||
}
|
||||
|
||||
@@ -30,8 +30,8 @@ import org.eclipse.hawkbit.ui.utils.UINotification;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.vaadin.spring.events.EventBus;
|
||||
|
||||
import com.google.gwt.thirdparty.guava.common.collect.Iterables;
|
||||
import com.google.gwt.thirdparty.guava.common.collect.Sets;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.vaadin.data.Container;
|
||||
import com.vaadin.data.Item;
|
||||
import com.vaadin.event.Transferable;
|
||||
|
||||
@@ -96,7 +96,7 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet
|
||||
|
||||
private VerticalLayout tagsLayout;
|
||||
|
||||
private final Map<String, StringBuilder> assignedSWModule = new HashMap<>();
|
||||
private Map<String, StringBuilder> assignedSWModule;
|
||||
|
||||
/**
|
||||
* softwareLayout Initialize the component.
|
||||
@@ -153,6 +153,10 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet
|
||||
}
|
||||
|
||||
if (null != softwareModuleIdNameList) {
|
||||
if (assignedSWModule == null) {
|
||||
assignedSWModule = new HashMap<>();
|
||||
}
|
||||
|
||||
for (final SoftwareModuleIdName swIdName : softwareModuleIdNameList) {
|
||||
final SoftwareModule softwareModule = softwareManagement.findSoftwareModuleById(swIdName.getId());
|
||||
if (assignedSWModule.containsKey(softwareModule.getType().getName())) {
|
||||
@@ -178,9 +182,11 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet
|
||||
}
|
||||
|
||||
private Button assignSoftModuleButton(final String softwareModuleName) {
|
||||
if (getPermissionChecker().hasUpdateDistributionPermission() && distributionSetManagement
|
||||
.findDistributionSetById(manageDistUIState.getLastSelectedDistribution().get().getId())
|
||||
.getAssignedTargets().isEmpty()) {
|
||||
if (getPermissionChecker().hasUpdateDistributionPermission()
|
||||
&& manageDistUIState.getLastSelectedDistribution().isPresent()
|
||||
&& distributionSetManagement
|
||||
.findDistributionSetById(manageDistUIState.getLastSelectedDistribution().get().getId())
|
||||
.getAssignedTargets().isEmpty()) {
|
||||
final Button reassignSoftModule = SPUIComponentProvider.getButton(softwareModuleName, "", "", "", true,
|
||||
FontAwesome.TIMES, SPUIButtonStyleSmallNoBorder.class);
|
||||
reassignSoftModule.setEnabled(false);
|
||||
@@ -195,6 +201,9 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void updateSoftwareModule(final SoftwareModule module) {
|
||||
if (assignedSWModule == null) {
|
||||
assignedSWModule = new HashMap<>();
|
||||
}
|
||||
|
||||
softwareModuleTable.getContainerDataSource().getItemIds();
|
||||
if (assignedSWModule.containsKey(module.getType().getName())) {
|
||||
@@ -377,7 +386,9 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet
|
||||
if ((saveActionWindowEvent == SaveActionWindowEvent.SAVED_ASSIGNMENTS
|
||||
|| saveActionWindowEvent == SaveActionWindowEvent.DISCARD_ALL_ASSIGNMENTS)
|
||||
&& getSelectedBaseEntity() != null) {
|
||||
assignedSWModule.clear();
|
||||
if (assignedSWModule != null) {
|
||||
assignedSWModule.clear();
|
||||
}
|
||||
setSelectedBaseEntity(
|
||||
distributionSetManagement.findDistributionSetByIdWithDetails(getSelectedBaseEntityId()));
|
||||
UI.getCurrent().access(() -> populateModule());
|
||||
@@ -389,7 +400,9 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet
|
||||
if (saveActionWindowEvent == SaveActionWindowEvent.DISCARD_ASSIGNMENT
|
||||
|| saveActionWindowEvent == SaveActionWindowEvent.DISCARD_ALL_ASSIGNMENTS
|
||||
|| saveActionWindowEvent == SaveActionWindowEvent.DELETE_ALL_SOFWARE) {
|
||||
assignedSWModule.clear();
|
||||
if (assignedSWModule != null) {
|
||||
assignedSWModule.clear();
|
||||
}
|
||||
showUnsavedAssignment();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ import org.vaadin.addons.lazyquerycontainer.LazyQueryDefinition;
|
||||
import org.vaadin.spring.events.EventScope;
|
||||
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.vaadin.data.Container;
|
||||
import com.vaadin.data.Item;
|
||||
import com.vaadin.event.dd.DragAndDropEvent;
|
||||
@@ -167,7 +168,7 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
|
||||
}
|
||||
|
||||
private Map<String, Object> prepareQueryConfigFilters() {
|
||||
final Map<String, Object> queryConfig = new HashMap<>();
|
||||
final Map<String, Object> queryConfig = Maps.newHashMapWithExpectedSize(2);
|
||||
manageDistUIState.getManageDistFilters().getSearchText()
|
||||
.ifPresent(value -> queryConfig.put(SPUIDefinitions.FILTER_BY_TEXT, value));
|
||||
|
||||
@@ -530,7 +531,7 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
|
||||
return manageMetadataBtn;
|
||||
}
|
||||
|
||||
private void showMetadataDetails(final Long itemId) {
|
||||
private void showMetadataDetails(final Long itemId) {
|
||||
final DistributionSet ds = distributionSetManagement.findDistributionSetByIdWithDetails(itemId);
|
||||
UI.getCurrent().addWindow(dsMetadataPopupLayout.getWindow(ds, null));
|
||||
}
|
||||
|
||||
@@ -79,7 +79,6 @@ public class DsMetadataPopupLayout extends AbstractMetadataPopupLayout<Distribut
|
||||
|
||||
@Override
|
||||
protected void deleteMetadata(final DistributionSet entity, final String key, final String value) {
|
||||
final DistributionSetMetadata dsMetaData = entityFactory.generateDistributionSetMetadata(entity, key, value);
|
||||
distributionSetManagement.deleteDistributionSetMetadata(entity, key);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
package org.eclipse.hawkbit.ui.distributions.event;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -17,6 +16,7 @@ import org.eclipse.hawkbit.ui.common.AbstractAcceptCriteria;
|
||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.vaadin.spring.annotation.SpringComponent;
|
||||
import com.vaadin.spring.annotation.ViewScope;
|
||||
import com.vaadin.ui.Component;
|
||||
@@ -66,7 +66,7 @@ public class DistributionsViewAcceptCriteria extends AbstractAcceptCriteria {
|
||||
}
|
||||
|
||||
private static Map<String, List<String>> createDropConfigurations() {
|
||||
final Map<String, List<String>> config = new HashMap<>();
|
||||
final Map<String, List<String>> config = Maps.newHashMapWithExpectedSize(2);
|
||||
|
||||
// Delete drop area droppable components
|
||||
config.put(UIComponentIdProvider.DELETE_BUTTON_WRAPPER_ID,
|
||||
@@ -82,7 +82,7 @@ public class DistributionsViewAcceptCriteria extends AbstractAcceptCriteria {
|
||||
}
|
||||
|
||||
private static Map<String, Object> createDropHintConfigurations() {
|
||||
final Map<String, Object> config = new HashMap<>();
|
||||
final Map<String, Object> config = Maps.newHashMapWithExpectedSize(4);
|
||||
config.put(SPUIDefinitions.DISTRIBUTION_TYPE_ID_PREFIXS, DragEvent.DISTRIBUTION_TYPE_DRAG);
|
||||
config.put(UIComponentIdProvider.DIST_TABLE_ID, DragEvent.DISTRIBUTION_DRAG);
|
||||
config.put(UIComponentIdProvider.UPLOAD_SOFTWARE_MODULE_TABLE, DragEvent.SOFTWAREMODULE_DRAG);
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.distributions.footer;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -37,6 +36,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.vaadin.spring.events.EventScope;
|
||||
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.vaadin.data.Container;
|
||||
import com.vaadin.data.Item;
|
||||
import com.vaadin.data.util.IndexedContainer;
|
||||
@@ -90,7 +90,7 @@ public class DistributionsConfirmationWindowLayout extends AbstractConfirmationW
|
||||
|
||||
@Override
|
||||
protected Map<String, ConfirmationTab> getConfimrationTabs() {
|
||||
final Map<String, ConfirmationTab> tabs = new HashMap<>();
|
||||
final Map<String, ConfirmationTab> tabs = Maps.newHashMapWithExpectedSize(5);
|
||||
/* Create tab for SW Modules delete */
|
||||
if (!manageDistUIState.getDeleteSofwareModulesList().isEmpty()) {
|
||||
tabs.put(i18n.get("caption.delete.swmodule.accordion.tab"), createSMDeleteConfirmationTab());
|
||||
@@ -112,7 +112,6 @@ public class DistributionsConfirmationWindowLayout extends AbstractConfirmationW
|
||||
}
|
||||
|
||||
/* Create tab for Assign Software Module */
|
||||
|
||||
if (!manageDistUIState.getAssignedList().isEmpty()) {
|
||||
tabs.put(i18n.get("caption.assign.dist.accordion.tab"), createAssignSWModuleConfirmationTab());
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.distributions.smtable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -40,6 +39,7 @@ import org.vaadin.addons.lazyquerycontainer.LazyQueryDefinition;
|
||||
import org.vaadin.spring.events.EventScope;
|
||||
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.vaadin.data.Container;
|
||||
import com.vaadin.data.Item;
|
||||
import com.vaadin.event.dd.DragAndDropEvent;
|
||||
@@ -143,7 +143,7 @@ public class SwModuleTable extends AbstractNamedVersionTable<SoftwareModule, Lon
|
||||
}
|
||||
|
||||
private Map<String, Object> prepareQueryConfigFilters() {
|
||||
final Map<String, Object> queryConfig = new HashMap<>();
|
||||
final Map<String, Object> queryConfig = Maps.newHashMapWithExpectedSize(3);
|
||||
manageDistUIState.getSoftwareModuleFilters().getSearchText()
|
||||
.ifPresent(value -> queryConfig.put(SPUIDefinitions.FILTER_BY_TEXT, value));
|
||||
|
||||
|
||||
@@ -13,8 +13,7 @@ import static org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent.Sof
|
||||
import static org.eclipse.hawkbit.ui.utils.UIComponentIdProvider.SW_MODULE_TYPE_TABLE_ID;
|
||||
import static org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions.VAR_NAME;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent;
|
||||
import org.eclipse.hawkbit.ui.common.SoftwareModuleTypeBeanQuery;
|
||||
@@ -59,10 +58,9 @@ public class DistSMTypeFilterButtons extends AbstractFilterButtons {
|
||||
|
||||
@Override
|
||||
protected LazyQueryContainer createButtonsLazyQueryContainer() {
|
||||
final Map<String, Object> queryConfig = new HashMap<>();
|
||||
final BeanQueryFactory<SoftwareModuleTypeBeanQuery> typeQF = new BeanQueryFactory<>(
|
||||
SoftwareModuleTypeBeanQuery.class);
|
||||
typeQF.setQueryConfiguration(queryConfig);
|
||||
typeQF.setQueryConfiguration(Collections.emptyMap());
|
||||
return new LazyQueryContainer(new LazyQueryDefinition(true, 20, VAR_NAME), typeQF);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ public class ManageDistUIState implements ManagmentEntityState<DistributionSetId
|
||||
|
||||
private Set<Long> selectedSoftwareModules = emptySet();
|
||||
|
||||
private Set<String> selectedDeleteDistSetTypes = new HashSet<>();
|
||||
private final Set<String> selectedDeleteDistSetTypes = new HashSet<>();
|
||||
|
||||
private Set<String> selectedDeleteSWModuleTypes = new HashSet<>();
|
||||
|
||||
@@ -201,10 +201,6 @@ public class ManageDistUIState implements ManagmentEntityState<DistributionSetId
|
||||
return selectedDeleteDistSetTypes;
|
||||
}
|
||||
|
||||
public void setSelectedDeleteDistSetTypes(final Set<String> selectedDeleteDistSetTypes) {
|
||||
this.selectedDeleteDistSetTypes = selectedDeleteDistSetTypes;
|
||||
}
|
||||
|
||||
public Set<String> getSelectedDeleteSWModuleTypes() {
|
||||
return selectedDeleteSWModuleTypes;
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.filter;
|
||||
|
||||
/**
|
||||
* A filter expression interface definition to implement the UI filter
|
||||
* mechanism. The filter expression can evaluate if e.g. Targets should
|
||||
* currently be added to the target list or if the current enabled filtered will
|
||||
* filter the target and not show the newly created target.
|
||||
*
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface FilterExpression {
|
||||
|
||||
/**
|
||||
* @return {@code true} if the expression evaluate that it should be
|
||||
* filtered and not shown on the UI, otherwise {@code false}
|
||||
*/
|
||||
boolean doFilter();
|
||||
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.filter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* {@link Filters} which provides the functionality to combine
|
||||
* {@link FilterExpression}s.
|
||||
*
|
||||
*
|
||||
*
|
||||
* @see FilterExpression
|
||||
*
|
||||
*/
|
||||
public final class Filters {
|
||||
|
||||
/**
|
||||
* private.
|
||||
*/
|
||||
private Filters() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines the given filter to an or-expression and evaluate them.
|
||||
*
|
||||
* @param expressions
|
||||
* the expressions to combine with an or-filter
|
||||
* @return an or-combined filter expression
|
||||
*/
|
||||
public static FilterExpression or(final List<FilterExpression> expressions) {
|
||||
return or(expressions.toArray(new FilterExpression[expressions.size()]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines the given filter to an or-expression and evaluate them.
|
||||
*
|
||||
* @param expressions
|
||||
* the expressions to combine with an or-filter
|
||||
* @return an or-combined filter expression
|
||||
*/
|
||||
public static FilterExpression or(final FilterExpression... expressions) {
|
||||
return new OrFilterExpression(expressions);
|
||||
}
|
||||
|
||||
private static final class OrFilterExpression implements FilterExpression {
|
||||
|
||||
private final FilterExpression[] expresssions;
|
||||
|
||||
private OrFilterExpression(final FilterExpression[] expresssions) {
|
||||
this.expresssions = Arrays.copyOf(expresssions, expresssions.length);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.hawkbit.server.ui.filter.FilterExpression#evaluate()
|
||||
*/
|
||||
@Override
|
||||
public boolean doFilter() {
|
||||
for (final FilterExpression filterExpression : expresssions) {
|
||||
if (filterExpression.doFilter()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.filter.target;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
||||
import org.eclipse.hawkbit.ui.filter.FilterExpression;
|
||||
|
||||
/**
|
||||
* Checks if custom target filter is applied.
|
||||
*
|
||||
*/
|
||||
public class CustomTargetFilter implements FilterExpression {
|
||||
|
||||
private final Optional<TargetFilterQuery> targetFilterQuery;
|
||||
|
||||
/**
|
||||
* Initialize.
|
||||
*
|
||||
* @param targetFilterQuery
|
||||
* custom target filter applied
|
||||
*/
|
||||
public CustomTargetFilter(final Optional<TargetFilterQuery> targetFilterQuery) {
|
||||
this.targetFilterQuery = targetFilterQuery;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.hawkbit.ui.filter.FilterExpression#doFilter()
|
||||
*/
|
||||
@Override
|
||||
public boolean doFilter() {
|
||||
if (!targetFilterQuery.isPresent()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2011-2015 Bosch Software Innovations GmbH, Germany. All rights reserved.
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.filter.target;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.ui.filter.FilterExpression;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class TargetSearchTextFilter implements FilterExpression {
|
||||
|
||||
private final Target target;
|
||||
private final String searchTextUpper;
|
||||
|
||||
/**
|
||||
* @param target
|
||||
* the target to check against the search text
|
||||
* @param searchText
|
||||
* the search text check against the given target
|
||||
*/
|
||||
public TargetSearchTextFilter(final Target target, final String searchText) {
|
||||
this.target = target;
|
||||
this.searchTextUpper = searchText.toUpperCase();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.hawkbit.server.ui.filter.FilterExpression#evaluate()
|
||||
*/
|
||||
@Override
|
||||
public boolean doFilter() {
|
||||
return !(descriptionIgnoreCase() || nameIgnoreCase() || controllerIdIgnoreCase() || ipAddressIgnoreCase());
|
||||
}
|
||||
|
||||
private boolean descriptionIgnoreCase() {
|
||||
if (target.getDescription() == null) {
|
||||
return false;
|
||||
}
|
||||
return target.getDescription().toUpperCase().contains(searchTextUpper);
|
||||
}
|
||||
|
||||
private boolean nameIgnoreCase() {
|
||||
if (target.getName() == null) {
|
||||
return false;
|
||||
}
|
||||
return target.getName().toUpperCase().contains(searchTextUpper);
|
||||
}
|
||||
|
||||
private boolean controllerIdIgnoreCase() {
|
||||
return target.getControllerId().toUpperCase().contains(searchTextUpper);
|
||||
}
|
||||
|
||||
private boolean ipAddressIgnoreCase() {
|
||||
final URI targetAddress = target.getTargetInfo().getAddress();
|
||||
if (targetAddress == null || targetAddress.getHost() == null) {
|
||||
return false;
|
||||
}
|
||||
return targetAddress.getHost().toUpperCase().contains(searchTextUpper);
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2011-2015 Bosch Software Innovations GmbH, Germany. All rights reserved.
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.filter.target;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.ui.filter.FilterExpression;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class TargetStatusFilter implements FilterExpression {
|
||||
|
||||
private final List<TargetUpdateStatus> targetUpdateStatus;
|
||||
|
||||
/**
|
||||
* @param target
|
||||
* the target to check the update status against
|
||||
* @param updateStatus
|
||||
* the target update status to check against the given target
|
||||
*/
|
||||
public TargetStatusFilter(final List<TargetUpdateStatus> updateStatus) {
|
||||
this.targetUpdateStatus = updateStatus;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.hawkbit.server.ui.filter.FilterExpression#evaluate()
|
||||
*/
|
||||
@Override
|
||||
public boolean doFilter() {
|
||||
if (targetUpdateStatus.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2011-2015 Bosch Software Innovations GmbH, Germany. All rights reserved.
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.filter.target;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.ui.filter.FilterExpression;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class TargetTagFilter implements FilterExpression {
|
||||
|
||||
private final Target target;
|
||||
private final Collection<String> tags;
|
||||
private final boolean noTag;
|
||||
|
||||
/**
|
||||
* @param target
|
||||
* the target to check the filter against
|
||||
* @param tags
|
||||
* the tags to check the target against it
|
||||
* @param noTag
|
||||
* {@code true} indicates that targets which have no tags should
|
||||
* not be filtered, otherwise {@code false}
|
||||
*/
|
||||
public TargetTagFilter(final Target target, final Collection<String> tags, final boolean noTag) {
|
||||
this.target = target;
|
||||
this.tags = tags;
|
||||
this.noTag = noTag;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.hawkbit.server.ui.filter.FilterExpression#evaluate()
|
||||
*/
|
||||
@Override
|
||||
public boolean doFilter() {
|
||||
final List<String> targetTags = target.getTags().stream().map(targetTag -> targetTag.getName())
|
||||
.collect(Collectors.toList());
|
||||
if (targetTags.isEmpty() || (noTag && targetTags.isEmpty())) {
|
||||
return false;
|
||||
}
|
||||
return !CollectionUtils.containsAny(targetTags, tags);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.filtermanagement;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
import org.eclipse.hawkbit.repository.rsql.RsqlValidationOracle;
|
||||
import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder;
|
||||
import org.eclipse.hawkbit.ui.filtermanagement.event.CustomFilterUIEvent;
|
||||
import org.eclipse.hawkbit.ui.filtermanagement.state.FilterManagementUIState;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.vaadin.spring.events.EventBus;
|
||||
import org.vaadin.spring.events.EventScope;
|
||||
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
|
||||
|
||||
import com.vaadin.server.FontAwesome;
|
||||
import com.vaadin.shared.ui.label.ContentMode;
|
||||
import com.vaadin.spring.annotation.SpringComponent;
|
||||
import com.vaadin.spring.annotation.ViewScope;
|
||||
import com.vaadin.ui.AbstractTextField.TextChangeEventMode;
|
||||
import com.vaadin.ui.Alignment;
|
||||
import com.vaadin.ui.HorizontalLayout;
|
||||
import com.vaadin.ui.Label;
|
||||
import com.vaadin.ui.TextField;
|
||||
import com.vaadin.ui.UI;
|
||||
|
||||
/**
|
||||
* An textfield with the {@link TextFieldSuggestionBox} extension which shows
|
||||
* suggestions in a suggestion-pop-up window while typing.
|
||||
*/
|
||||
@SpringComponent
|
||||
@ViewScope
|
||||
public class AutoCompleteTextFieldComponent extends HorizontalLayout {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Autowired
|
||||
private FilterManagementUIState filterManagementUIState;
|
||||
|
||||
@Autowired
|
||||
private transient EventBus.SessionEventBus eventBus;
|
||||
|
||||
@Autowired
|
||||
private transient RsqlValidationOracle rsqlValidationOracle;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("uiExecutor")
|
||||
private transient Executor executor;
|
||||
|
||||
private transient List<FilterQueryChangeListener> listeners = new LinkedList<>();
|
||||
|
||||
private final Label validationIcon;
|
||||
private final TextField queryTextField;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public AutoCompleteTextFieldComponent() {
|
||||
|
||||
queryTextField = createSearchField();
|
||||
validationIcon = createStatusIcon();
|
||||
|
||||
setSizeUndefined();
|
||||
setSpacing(true);
|
||||
addStyleName("custom-search-layout");
|
||||
addComponents(validationIcon, queryTextField);
|
||||
setComponentAlignment(validationIcon, Alignment.TOP_CENTER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the spring-framework when this bean has be post-constructed.
|
||||
*/
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
eventBus.subscribe(this);
|
||||
new TextFieldSuggestionBox(rsqlValidationOracle, this).extend(queryTextField);
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
void destroy() {
|
||||
eventBus.unsubscribe(this);
|
||||
}
|
||||
|
||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||
void onEvent(final CustomFilterUIEvent custFUIEvent) {
|
||||
if (custFUIEvent == CustomFilterUIEvent.UPDATE_TARGET_FILTER_SEARCH_ICON) {
|
||||
validationIcon.setValue(FontAwesome.CHECK_CIRCLE.getHtml());
|
||||
if (!isValidationError()) {
|
||||
validationIcon.setStyleName(SPUIStyleDefinitions.SUCCESS_ICON);
|
||||
} else {
|
||||
validationIcon.setStyleName(SPUIStyleDefinitions.ERROR_ICON);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the textfield and resets the validation icon.
|
||||
*/
|
||||
public void clear() {
|
||||
queryTextField.clear();
|
||||
validationIcon.setValue(FontAwesome.CHECK_CIRCLE.getHtml());
|
||||
validationIcon.setStyleName("hide-status-label");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focus() {
|
||||
queryTextField.focus();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given listener
|
||||
*
|
||||
* @param textChangeListener
|
||||
* the listener to be called in case of text changed
|
||||
*/
|
||||
public void addTextChangeListener(final FilterQueryChangeListener textChangeListener) {
|
||||
listeners.add(textChangeListener);
|
||||
}
|
||||
|
||||
public void setValue(final String textValue) {
|
||||
queryTextField.setValue(textValue);
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return queryTextField.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the filter-query has been changed in the textfield, e.g. from
|
||||
* client-side.
|
||||
*
|
||||
* @param currentText
|
||||
* the current text of the textfield which has been changed
|
||||
* @param valid
|
||||
* {@code boolean} if the current text is RSQL syntax valid
|
||||
* otherwise {@code false}
|
||||
* @param validationMessage
|
||||
* a message shown in case of syntax errors as tooltip
|
||||
*/
|
||||
public void onQueryFilterChange(final String currentText, final boolean valid, final String validationMessage) {
|
||||
if (valid) {
|
||||
showValidationSuccesIcon(currentText);
|
||||
} else {
|
||||
showValidationFailureIcon(validationMessage);
|
||||
}
|
||||
listeners.forEach(listener -> listener.queryChanged(valid, currentText));
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the validation success icon in the textfield
|
||||
*
|
||||
* @param text
|
||||
* the text to store in the UI state object
|
||||
*/
|
||||
public void showValidationSuccesIcon(final String text) {
|
||||
validationIcon.setValue(FontAwesome.CHECK_CIRCLE.getHtml());
|
||||
validationIcon.setStyleName(SPUIStyleDefinitions.SUCCESS_ICON);
|
||||
filterManagementUIState.setFilterQueryValue(text);
|
||||
filterManagementUIState.setIsFilterByInvalidFilterQuery(Boolean.FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the validation error icon in the textfield
|
||||
*
|
||||
* @param validationMessage
|
||||
* the validation message which should be added to the error-icon
|
||||
* tooltip
|
||||
*/
|
||||
public void showValidationFailureIcon(final String validationMessage) {
|
||||
validationIcon.setValue(FontAwesome.TIMES_CIRCLE.getHtml());
|
||||
validationIcon.setStyleName(SPUIStyleDefinitions.ERROR_ICON);
|
||||
validationIcon.setDescription(validationMessage);
|
||||
filterManagementUIState.setFilterQueryValue(null);
|
||||
filterManagementUIState.setIsFilterByInvalidFilterQuery(Boolean.TRUE);
|
||||
}
|
||||
|
||||
public boolean isValidationError() {
|
||||
return validationIcon.getStyleName().equals(SPUIStyleDefinitions.ERROR_ICON);
|
||||
}
|
||||
|
||||
private TextField createSearchField() {
|
||||
final TextField textField = new TextFieldBuilder().immediate(true).id("custom.query.text.Id")
|
||||
.maxLengthAllowed(SPUILabelDefinitions.TARGET_FILTER_QUERY_TEXT_FIELD_LENGTH).buildTextComponent();
|
||||
textField.addStyleName("target-filter-textfield");
|
||||
textField.setWidth(900.0F, Unit.PIXELS);
|
||||
textField.setTextChangeEventMode(TextChangeEventMode.EAGER);
|
||||
textField.setImmediate(true);
|
||||
textField.setTextChangeTimeout(100);
|
||||
return textField;
|
||||
}
|
||||
|
||||
private static Label createStatusIcon() {
|
||||
final Label statusIcon = new Label();
|
||||
statusIcon.setImmediate(true);
|
||||
statusIcon.setContentMode(ContentMode.HTML);
|
||||
statusIcon.setSizeFull();
|
||||
setInitialStatusIconStyle(statusIcon);
|
||||
statusIcon.setId(UIComponentIdProvider.VALIDATION_STATUS_ICON_ID);
|
||||
return statusIcon;
|
||||
}
|
||||
|
||||
private static void setInitialStatusIconStyle(final Label statusIcon) {
|
||||
statusIcon.setValue(FontAwesome.CHECK_CIRCLE.getHtml());
|
||||
statusIcon.setStyleName("hide-status-label");
|
||||
}
|
||||
|
||||
class StatusCircledAsync implements Runnable {
|
||||
private final UI current;
|
||||
|
||||
public StatusCircledAsync(final UI current) {
|
||||
this.current = current;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
UI.setCurrent(current);
|
||||
eventBus.publish(this, CustomFilterUIEvent.FILTER_TARGET_BY_QUERY);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the spinner as progress indicator.
|
||||
*/
|
||||
public void showValidationInProgress() {
|
||||
validationIcon.setValue(null);
|
||||
validationIcon.addStyleName("show-status-label");
|
||||
validationIcon.setStyleName(SPUIStyleDefinitions.TARGET_FILTER_SEARCH_PROGRESS_INDICATOR_STYLE);
|
||||
}
|
||||
|
||||
public Executor getExecutor() {
|
||||
return executor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change listener on the textfield.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface FilterQueryChangeListener {
|
||||
/**
|
||||
* Called when the text has been changed and validated.
|
||||
*
|
||||
* @param valid
|
||||
* indicates if the entered query text is valid
|
||||
* @param query
|
||||
* the entered query text
|
||||
*/
|
||||
void queryChanged(final boolean valid, final String query);
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.filtermanagement;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
@@ -23,15 +23,15 @@ import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder;
|
||||
import org.eclipse.hawkbit.ui.components.SPUIButton;
|
||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
||||
import org.eclipse.hawkbit.ui.filtermanagement.AutoCompleteTextFieldComponent.FilterQueryChangeListener;
|
||||
import org.eclipse.hawkbit.ui.filtermanagement.event.CustomFilterUIEvent;
|
||||
import org.eclipse.hawkbit.ui.filtermanagement.state.FilterManagementUIState;
|
||||
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||
import org.eclipse.hawkbit.ui.utils.UINotification;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.vaadin.spring.events.EventBus;
|
||||
import org.vaadin.spring.events.EventScope;
|
||||
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
|
||||
@@ -40,16 +40,11 @@ import com.google.common.base.Strings;
|
||||
import com.vaadin.event.FieldEvents.BlurEvent;
|
||||
import com.vaadin.event.FieldEvents.BlurListener;
|
||||
import com.vaadin.event.FieldEvents.TextChangeEvent;
|
||||
import com.vaadin.event.FieldEvents.TextChangeListener;
|
||||
import com.vaadin.event.LayoutEvents.LayoutClickEvent;
|
||||
import com.vaadin.event.LayoutEvents.LayoutClickListener;
|
||||
import com.vaadin.event.ShortcutAction.KeyCode;
|
||||
import com.vaadin.server.FontAwesome;
|
||||
import com.vaadin.shared.ui.label.ContentMode;
|
||||
import com.vaadin.spring.annotation.SpringComponent;
|
||||
import com.vaadin.spring.annotation.ViewScope;
|
||||
import com.vaadin.ui.AbstractField;
|
||||
import com.vaadin.ui.AbstractTextField.TextChangeEventMode;
|
||||
import com.vaadin.ui.Alignment;
|
||||
import com.vaadin.ui.Button;
|
||||
import com.vaadin.ui.Button.ClickEvent;
|
||||
@@ -94,11 +89,10 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
private transient UiProperties uiProperties;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("uiExecutor")
|
||||
private transient Executor executor;
|
||||
private transient EntityFactory entityFactory;
|
||||
|
||||
@Autowired
|
||||
private transient EntityFactory entityFactory;
|
||||
private AutoCompleteTextFieldComponent queryTextField;
|
||||
|
||||
private HorizontalLayout breadcrumbLayout;
|
||||
|
||||
@@ -108,8 +102,6 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
|
||||
private Label headerCaption;
|
||||
|
||||
private TextField queryTextField;
|
||||
|
||||
private TextField nameTextField;
|
||||
|
||||
private Label nameLabel;
|
||||
@@ -120,9 +112,7 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
|
||||
private Link helpLink;
|
||||
|
||||
private Label validationIcon;
|
||||
|
||||
private HorizontalLayout searchLayout;
|
||||
private Button searchIcon;
|
||||
|
||||
private String oldFilterName;
|
||||
|
||||
@@ -136,8 +126,6 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
|
||||
private LayoutClickListener nameLayoutClickListner;
|
||||
|
||||
private boolean validationFailed = false;
|
||||
|
||||
/**
|
||||
* Initialize the Campaign Status History Header.
|
||||
*/
|
||||
@@ -170,8 +158,6 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
} else if (custFUIEvent == CustomFilterUIEvent.CREATE_NEW_FILTER_CLICK) {
|
||||
setUpCaptionLayout(true);
|
||||
resetComponents();
|
||||
} else if (custFUIEvent == CustomFilterUIEvent.UPDATE_TARGET_FILTER_SEARCH_ICON) {
|
||||
UI.getCurrent().access(() -> updateStatusIconAfterTablePopulated());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,38 +169,22 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
oldFilterQuery = filterManagementUIState.getTfQuery().get().getQuery();
|
||||
}
|
||||
breadcrumbName.setValue(nameLabel.getValue());
|
||||
showValidationSuccesIcon();
|
||||
queryTextField.showValidationSuccesIcon(filterManagementUIState.getFilterQueryValue());
|
||||
titleFilterIconsLayout.addStyleName(SPUIStyleDefinitions.TARGET_FILTER_CAPTION_LAYOUT);
|
||||
headerCaption.setVisible(false);
|
||||
setUpCaptionLayout(false);
|
||||
}
|
||||
|
||||
private void resetComponents() {
|
||||
queryTextField.clear();
|
||||
queryTextField.focus();
|
||||
headerCaption.setVisible(true);
|
||||
breadcrumbName.setValue(headerCaption.getValue());
|
||||
nameLabel.setValue("");
|
||||
queryTextField.setValue("");
|
||||
setInitialStatusIconStyle(validationIcon);
|
||||
validationFailed = false;
|
||||
saveButton.setEnabled(false);
|
||||
titleFilterIconsLayout.removeStyleName(SPUIStyleDefinitions.TARGET_FILTER_CAPTION_LAYOUT);
|
||||
}
|
||||
|
||||
private Label createStatusIcon() {
|
||||
final Label statusIcon = new Label();
|
||||
statusIcon.setImmediate(true);
|
||||
statusIcon.setContentMode(ContentMode.HTML);
|
||||
statusIcon.setSizeFull();
|
||||
setInitialStatusIconStyle(statusIcon);
|
||||
statusIcon.setId(UIComponentIdProvider.VALIDATION_STATUS_ICON_ID);
|
||||
return statusIcon;
|
||||
}
|
||||
|
||||
private void setInitialStatusIconStyle(final Label statusIcon) {
|
||||
statusIcon.setValue(FontAwesome.CHECK_CIRCLE.getHtml());
|
||||
statusIcon.setStyleName("hide-status-label");
|
||||
}
|
||||
|
||||
private void createComponents() {
|
||||
|
||||
breadcrumbButton = createBreadcrumbButton();
|
||||
@@ -227,11 +197,8 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
nameTextField = createNameTextField();
|
||||
nameTextField.setWidth(380, Unit.PIXELS);
|
||||
|
||||
queryTextField = createSearchField();
|
||||
addSearchLisenter();
|
||||
|
||||
validationIcon = createStatusIcon();
|
||||
saveButton = createSaveButton();
|
||||
searchIcon = createSearchIcon();
|
||||
|
||||
helpLink = SPUIComponentProvider.getHelpLink(uiProperties.getLinks().getDocumentation().getTargetfilterView());
|
||||
|
||||
@@ -282,6 +249,14 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
queryTextField.addTextChangeListener(new FilterQueryChangeListener() {
|
||||
@Override
|
||||
public void queryChanged(final boolean valid, final String query) {
|
||||
enableDisableSaveButton(!valid, query);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void onFilterNameChange(final TextChangeEvent event) {
|
||||
@@ -318,24 +293,15 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
titleFilterLayout.setComponentAlignment(titleFilterIconsLayout, Alignment.TOP_LEFT);
|
||||
titleFilterLayout.setComponentAlignment(closeIcon, Alignment.TOP_RIGHT);
|
||||
|
||||
validationIcon = createStatusIcon();
|
||||
|
||||
searchLayout = new HorizontalLayout();
|
||||
searchLayout.setSizeUndefined();
|
||||
searchLayout.setSpacing(false);
|
||||
searchLayout.addComponents(validationIcon, queryTextField);
|
||||
searchLayout.addStyleName("custom-search-layout");
|
||||
searchLayout.setComponentAlignment(validationIcon, Alignment.TOP_CENTER);
|
||||
|
||||
final HorizontalLayout iconLayout = new HorizontalLayout();
|
||||
iconLayout.setSizeUndefined();
|
||||
iconLayout.setSpacing(false);
|
||||
iconLayout.addComponents(helpLink, saveButton);
|
||||
iconLayout.addComponents(helpLink, searchIcon, saveButton);
|
||||
|
||||
final HorizontalLayout queryLayout = new HorizontalLayout();
|
||||
queryLayout.setSizeUndefined();
|
||||
queryLayout.setSpacing(true);
|
||||
queryLayout.addComponents(searchLayout, iconLayout);
|
||||
queryLayout.addComponents(queryTextField, iconLayout);
|
||||
|
||||
addComponent(breadcrumbLayout);
|
||||
addComponent(titleFilterLayout);
|
||||
@@ -358,66 +324,16 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
}
|
||||
}
|
||||
|
||||
private void addSearchLisenter() {
|
||||
queryTextField.addTextChangeListener(new TextChangeListener() {
|
||||
private static final long serialVersionUID = -6668604418942689391L;
|
||||
|
||||
@Override
|
||||
public void textChange(final TextChangeEvent event) {
|
||||
validationIcon.addStyleName("show-status-label");
|
||||
showValidationInProgress();
|
||||
onQueryChange(event.getText());
|
||||
executor.execute(new StatusCircledAsync(UI.getCurrent()));
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
class StatusCircledAsync implements Runnable {
|
||||
private final UI current;
|
||||
|
||||
public StatusCircledAsync(final UI current) {
|
||||
this.current = current;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
UI.setCurrent(current);
|
||||
eventBus.publish(this, CustomFilterUIEvent.FILTER_TARGET_BY_QUERY);
|
||||
}
|
||||
}
|
||||
|
||||
private void onQueryChange(final String input) {
|
||||
if (!Strings.isNullOrEmpty(input)) {
|
||||
final ValidationResult validationResult = FilterQueryValidation.getExpectedTokens(input);
|
||||
if (!validationResult.getIsValidationFailed()) {
|
||||
filterManagementUIState.setFilterQueryValue(input);
|
||||
filterManagementUIState.setIsFilterByInvalidFilterQuery(Boolean.FALSE);
|
||||
validationFailed = false;
|
||||
} else {
|
||||
validationFailed = true;
|
||||
filterManagementUIState.setFilterQueryValue(null);
|
||||
filterManagementUIState.setIsFilterByInvalidFilterQuery(Boolean.TRUE);
|
||||
validationIcon.setDescription(validationResult.getMessage());
|
||||
showValidationFailureIcon();
|
||||
}
|
||||
enableDisableSaveButton(validationFailed, input);
|
||||
} else {
|
||||
setInitialStatusIconStyle(validationIcon);
|
||||
filterManagementUIState.setFilterQueryValue(null);
|
||||
filterManagementUIState.setIsFilterByInvalidFilterQuery(Boolean.TRUE);
|
||||
}
|
||||
queryTextField.setValue(input);
|
||||
}
|
||||
|
||||
private void enableDisableSaveButton(final boolean validationFailed, final String query) {
|
||||
if (validationFailed || (isNameAndQueryEmpty(nameTextField.getValue(), query)
|
||||
|| (query.equals(oldFilterQuery) && nameTextField.getValue().equals(oldFilterName)))) {
|
||||
saveButton.setEnabled(false);
|
||||
searchIcon.setEnabled(false);
|
||||
} else {
|
||||
if (hasSavePermission()) {
|
||||
saveButton.setEnabled(true);
|
||||
}
|
||||
searchIcon.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -428,21 +344,6 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
return false;
|
||||
}
|
||||
|
||||
private void showValidationSuccesIcon() {
|
||||
validationIcon.setValue(FontAwesome.CHECK_CIRCLE.getHtml());
|
||||
validationIcon.setStyleName(SPUIStyleDefinitions.SUCCESS_ICON);
|
||||
}
|
||||
|
||||
private void showValidationFailureIcon() {
|
||||
validationIcon.setValue(FontAwesome.TIMES_CIRCLE.getHtml());
|
||||
validationIcon.setStyleName(SPUIStyleDefinitions.ERROR_ICON);
|
||||
}
|
||||
|
||||
private void showValidationInProgress() {
|
||||
validationIcon.setValue(null);
|
||||
validationIcon.setStyleName(SPUIStyleDefinitions.TARGET_FILTER_SEARCH_PROGRESS_INDICATOR_STYLE);
|
||||
}
|
||||
|
||||
private SPUIButton createSearchResetIcon() {
|
||||
final SPUIButton button = (SPUIButton) SPUIComponentProvider.getButton(
|
||||
UIComponentIdProvider.CUSTOM_FILTER_CLOSE, "", "", null, false, FontAwesome.TIMES,
|
||||
@@ -451,18 +352,6 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
return button;
|
||||
}
|
||||
|
||||
private static TextField createSearchField() {
|
||||
final TextField textField = new TextFieldBuilder().immediate(true).id("custom.query.text.Id")
|
||||
.maxLengthAllowed(SPUILabelDefinitions.TARGET_FILTER_QUERY_TEXT_FIELD_LENGTH).buildTextComponent();
|
||||
textField.addStyleName("target-filter-textfield");
|
||||
textField.setWidth(900.0F, Unit.PIXELS);
|
||||
textField.setTextChangeEventMode(TextChangeEventMode.LAZY);
|
||||
textField.setTextChangeTimeout(1000);
|
||||
|
||||
textField.addShortcutListener(new AbstractField.FocusShortcut(textField, KeyCode.ENTER));
|
||||
return textField;
|
||||
}
|
||||
|
||||
private void closeFilterLayout() {
|
||||
filterManagementUIState.setFilterQueryValue(null);
|
||||
filterManagementUIState.setCreateFilterBtnClicked(false);
|
||||
@@ -480,12 +369,26 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
return saveButton;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see com.vaadin.ui.Button.ClickListener#buttonClick(com.vaadin.ui.Button.
|
||||
* ClickEvent)
|
||||
*/
|
||||
private Button createSearchIcon() {
|
||||
searchIcon = SPUIComponentProvider.getButton(UIComponentIdProvider.FILTER_SEARCH_ICON_ID, "", "", null, false,
|
||||
FontAwesome.SEARCH, SPUIButtonStyleSmallNoBorder.class);
|
||||
searchIcon.addClickListener(event -> onSearchIconClick());
|
||||
searchIcon.setEnabled(false);
|
||||
searchIcon.setData(false);
|
||||
return searchIcon;
|
||||
}
|
||||
|
||||
private void onSearchIconClick() {
|
||||
|
||||
if (queryTextField.isValidationError()) {
|
||||
return;
|
||||
}
|
||||
|
||||
queryTextField.showValidationInProgress();
|
||||
queryTextField.getExecutor().execute(queryTextField.new StatusCircledAsync(UI.getCurrent()));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buttonClick(final ClickEvent event) {
|
||||
if (UIComponentIdProvider.CUSTOM_FILTER_SAVE_ICON.equals(event.getComponent().getId())
|
||||
@@ -509,7 +412,11 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
}
|
||||
|
||||
private void updateCustomFilter() {
|
||||
final TargetFilterQuery targetFilterQuery = filterManagementUIState.getTfQuery().get();
|
||||
final Optional<TargetFilterQuery> tfQuery = filterManagementUIState.getTfQuery();
|
||||
if (!tfQuery.isPresent()) {
|
||||
return;
|
||||
}
|
||||
final TargetFilterQuery targetFilterQuery = tfQuery.get();
|
||||
targetFilterQuery.setName(nameTextField.getValue());
|
||||
targetFilterQuery.setQuery(queryTextField.getValue());
|
||||
final TargetFilterQuery updatedTargetFilter = targetFilterQueryManagement
|
||||
@@ -546,13 +453,6 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updateStatusIconAfterTablePopulated() {
|
||||
queryTextField.focus();
|
||||
if (!validationFailed && !Strings.isNullOrEmpty(queryTextField.getValue())) {
|
||||
showValidationSuccesIcon();
|
||||
}
|
||||
}
|
||||
|
||||
private void showCustomFiltersView() {
|
||||
eventBus.publish(this, CustomFilterUIEvent.SHOW_FILTER_MANAGEMENT);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ package org.eclipse.hawkbit.ui.filtermanagement;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -37,6 +36,7 @@ import org.vaadin.spring.events.EventScope;
|
||||
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.vaadin.data.Item;
|
||||
import com.vaadin.server.FontAwesome;
|
||||
import com.vaadin.shared.ui.label.ContentMode;
|
||||
@@ -142,7 +142,7 @@ public class CreateOrUpdateFilterTable extends Table {
|
||||
}
|
||||
|
||||
private Map<String, Object> prepareQueryConfigFilters() {
|
||||
final Map<String, Object> queryConfig = new HashMap<>();
|
||||
final Map<String, Object> queryConfig = Maps.newHashMapWithExpectedSize(2);
|
||||
if (!Strings.isNullOrEmpty(filterManagementUIState.getFilterQueryValue())) {
|
||||
queryConfig.put(SPUIDefinitions.FILTER_BY_QUERY, filterManagementUIState.getFilterQueryValue());
|
||||
}
|
||||
|
||||
@@ -94,8 +94,7 @@ public class FilterManagementView extends VerticalLayout implements View {
|
||||
void onEvent(final CustomFilterUIEvent custFilterUIEvent) {
|
||||
if (custFilterUIEvent == CustomFilterUIEvent.TARGET_FILTER_DETAIL_VIEW) {
|
||||
viewTargetFilterDetailLayout();
|
||||
} else if (custFilterUIEvent == CustomFilterUIEvent.CREATE_NEW_FILTER_CLICK
|
||||
|| custFilterUIEvent == CustomFilterUIEvent.FILTER_TARGET_BY_QUERY) {
|
||||
} else if (custFilterUIEvent == CustomFilterUIEvent.CREATE_NEW_FILTER_CLICK) {
|
||||
this.getUI().access(() -> viewCreateTargetFilterLayout());
|
||||
} else if (custFilterUIEvent == CustomFilterUIEvent.EXIT_CREATE_OR_UPDATE_FILTRER_VIEW
|
||||
|| custFilterUIEvent == CustomFilterUIEvent.SHOW_FILTER_MANAGEMENT) {
|
||||
|
||||
@@ -1,182 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.filtermanagement;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.hawkbit.repository.TargetFields;
|
||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
||||
import org.eclipse.hawkbit.ui.utils.SpringContextHelper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
|
||||
import cz.jirutka.rsql.parser.ParseException;
|
||||
import cz.jirutka.rsql.parser.RSQLParserException;
|
||||
|
||||
/**
|
||||
*
|
||||
* Validates the target filter query.
|
||||
*
|
||||
*/
|
||||
public final class FilterQueryValidation {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(FilterQueryValidation.class);
|
||||
|
||||
private FilterQueryValidation() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* method for get ExpectedTokens.
|
||||
*
|
||||
* @param input
|
||||
* @param entityManager
|
||||
* @return
|
||||
*/
|
||||
public static ValidationResult getExpectedTokens(final String input) {
|
||||
|
||||
final TokenDescription tokenDesc = new TokenDescription();
|
||||
final ValidationResult result = new ValidationResult();
|
||||
final List<String> expectedTokens = new ArrayList<>();
|
||||
try {
|
||||
|
||||
final TargetManagement management = SpringContextHelper.getBean(TargetManagement.class);
|
||||
management.findTargetsAll(input, new PageRequest(0, 100));
|
||||
} catch (final RSQLParameterSyntaxException ex) {
|
||||
setExceptionDetails(new Exception(ex.getCause().getCause()), expectedTokens, result, tokenDesc);
|
||||
result.setMessage(getCustomMessage(ex.getCause().getMessage(), result.getExpectedTokens()));
|
||||
result.setIsValidationFailed(Boolean.TRUE);
|
||||
LOGGER.trace("Syntax exception on parsing :", ex);
|
||||
} catch (final RSQLParserException ex) {
|
||||
setExceptionDetails(ex, expectedTokens, result, tokenDesc);
|
||||
result.setMessage(getCustomMessage(ex.getMessage(), result.getExpectedTokens()));
|
||||
result.setIsValidationFailed(Boolean.TRUE);
|
||||
LOGGER.trace("Exception on parsing :", ex);
|
||||
} catch (final IllegalArgumentException ex) {
|
||||
result.setMessage(getCustomMessage(ex.getMessage(), null));
|
||||
result.setIsValidationFailed(Boolean.TRUE);
|
||||
LOGGER.trace("Illegal argument on parsing :", ex);
|
||||
} catch (final RSQLParameterUnsupportedFieldException ex) {
|
||||
result.setMessage(getCustomMessage(ex.getMessage(), null));
|
||||
result.setIsValidationFailed(Boolean.TRUE);
|
||||
LOGGER.trace("Unsupported field on parsing :", ex);
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
private static void setExceptionDetails(final Exception ex, final List<String> expectedTokens,
|
||||
final ValidationResult result, final TokenDescription tokenDesc) {
|
||||
for (final Integer node : getNextTokens(ex)) {
|
||||
if (node != 12) {
|
||||
expectedTokens.add(tokenDesc.getTokenImage()[node]);
|
||||
}
|
||||
}
|
||||
final List<String> customExpectTokenList = processExpectedTokens(getNextTokens(ex));
|
||||
if (!customExpectTokenList.isEmpty()) {
|
||||
result.setExpectedTokens(customExpectTokenList);
|
||||
} else {
|
||||
result.setExpectedTokens(expectedTokens);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* method for process ExpectedTokens.
|
||||
*
|
||||
* @param expectedTokens
|
||||
* @return
|
||||
*/
|
||||
// Exception squid:S2095 - see
|
||||
// https://jira.sonarsource.com/browse/SONARJAVA-1478
|
||||
@SuppressWarnings({ "squid:S2095" })
|
||||
public static List<String> processExpectedTokens(final List<Integer> expectedTokens) {
|
||||
final List<String> expectToken = new ArrayList<>();
|
||||
if (expectedTokens.size() == 2 && expectedTokens.contains(9) && expectedTokens.contains(4)) {
|
||||
final List<String> expectedFieldList = Arrays.stream(TargetFields.values()).map(v -> v.name().toLowerCase())
|
||||
.collect(Collectors.toList());
|
||||
expectToken.addAll(expectedFieldList);
|
||||
expectToken.add("assignedds.name");
|
||||
expectToken.add("assignedds.version");
|
||||
}
|
||||
return expectToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method To Get Next Token.
|
||||
*
|
||||
* @param e
|
||||
* .
|
||||
* @return list.
|
||||
*/
|
||||
public static List<Integer> getNextTokens(final Exception e) {
|
||||
Throwable parseException = e.getCause();
|
||||
final List<Integer> listTokens = new ArrayList<>();
|
||||
if (parseException != null) {
|
||||
do {
|
||||
if (parseException instanceof ParseException) {
|
||||
try {
|
||||
Field declaredField;
|
||||
declaredField = parseException.getClass().getDeclaredField("expectedTokenSequences");
|
||||
int[][] tokens;
|
||||
tokens = (int[][]) declaredField.get(parseException);
|
||||
for (final int[] is : tokens) {
|
||||
for (final int i : is) {
|
||||
listTokens.add(i);
|
||||
}
|
||||
}
|
||||
return listTokens;
|
||||
} catch (SecurityException | NoSuchFieldException | IllegalArgumentException
|
||||
| IllegalAccessException ex) {
|
||||
LOGGER.info("Exception on parsing :", ex);
|
||||
}
|
||||
|
||||
} else {
|
||||
return listTokens;
|
||||
}
|
||||
} while ((parseException = parseException.getCause()) != null);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* To Get Custom Message.
|
||||
*
|
||||
* @param message
|
||||
* @param expectedTokens
|
||||
* @return String.
|
||||
*/
|
||||
public static String getCustomMessage(final String message, final List<String> expectedTokens) {
|
||||
String builder = message;
|
||||
if (message.contains(":")) {
|
||||
builder = message.substring(message.indexOf(':') + 1, message.length());
|
||||
if (builder.indexOf("Was expecting") != -1) {
|
||||
builder = builder.substring(0, builder.lastIndexOf("Was expecting"));
|
||||
}
|
||||
if (null != expectedTokens && !expectedTokens.isEmpty()) {
|
||||
final StringBuilder tokens = new StringBuilder();
|
||||
expectedTokens.stream().forEach(value -> tokens.append(value + ","));
|
||||
builder = builder.concat("Was expecting :" + tokens.toString().substring(0, tokens.length() - 1));
|
||||
}
|
||||
builder = builder.replace('\r', ' ');
|
||||
builder = builder.replace('\n', ' ');
|
||||
builder = builder.replaceAll(">", " ");
|
||||
builder = builder.replaceAll("<", " ");
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -114,6 +114,7 @@ public class TargetFilterHeader extends VerticalLayout {
|
||||
}
|
||||
|
||||
private void addNewFilter() {
|
||||
filterManagementUIState.setTfQuery(null);
|
||||
filterManagementUIState.setFilterQueryValue(null);
|
||||
filterManagementUIState.setCreateFilterBtnClicked(true);
|
||||
eventBus.publish(this, CustomFilterUIEvent.CREATE_NEW_FILTER_CLICK);
|
||||
|
||||
@@ -44,6 +44,7 @@ import org.vaadin.spring.events.EventBus;
|
||||
import org.vaadin.spring.events.EventScope;
|
||||
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.vaadin.data.Container;
|
||||
import com.vaadin.data.Item;
|
||||
import com.vaadin.server.FontAwesome;
|
||||
@@ -136,7 +137,7 @@ public class TargetFilterTable extends Table {
|
||||
}
|
||||
|
||||
private Map<String, Object> prepareQueryConfigFilters() {
|
||||
final Map<String, Object> queryConfig = new HashMap<>();
|
||||
final Map<String, Object> queryConfig = Maps.newHashMapWithExpectedSize(1);
|
||||
filterManagementUIState.getCustomFilterSearchText()
|
||||
.ifPresent(value -> queryConfig.put(SPUIDefinitions.FILTER_BY_TEXT, value));
|
||||
return queryConfig;
|
||||
@@ -266,9 +267,8 @@ public class TargetFilterTable extends Table {
|
||||
final String targetFilterName = (String) ((Button) event.getComponent()).getData();
|
||||
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
|
||||
.findTargetFilterQueryByName(targetFilterName);
|
||||
filterManagementUIState.setTfQuery(targetFilterQuery);
|
||||
filterManagementUIState.setFilterQueryValue(targetFilterQuery.getQuery());
|
||||
|
||||
filterManagementUIState.setTfQuery(targetFilterQuery);
|
||||
filterManagementUIState.setEditViewDisplayed(true);
|
||||
eventBus.publish(this, CustomFilterUIEvent.TARGET_FILTER_DETAIL_VIEW);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
which accompanies this distribution, and is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
|
||||
-->
|
||||
<module>
|
||||
<inherits name="com.vaadin.DefaultWidgetSet" />
|
||||
|
||||
|
||||
<inherits name="org.eclipse.hawkbit.ui.AppWidgetSet" />
|
||||
|
||||
<inherits name="org.vaadin.peter.contextmenu.ContextmenuWidgetset" />
|
||||
|
||||
<inherits name="org.vaadin.tokenfield.TokenfieldWidgetset" />
|
||||
|
||||
<inherits name="org.eclipse.hawkbit.ui.customrenderers.CustomRendererWidgetSet" />
|
||||
|
||||
<inherits name="org.vaadin.hene.flexibleoptiongroup.widgetset.FlexibleOptionGroupWidgetset" />
|
||||
|
||||
<inherits name="org.vaadin.alump.distributionbar.gwt.DistributionBarWidgetset" />
|
||||
</module>
|
||||
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.filtermanagement;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.hawkbit.repository.rsql.RsqlValidationOracle;
|
||||
import org.eclipse.hawkbit.repository.rsql.SuggestionContext;
|
||||
import org.eclipse.hawkbit.repository.rsql.ValidationOracleContext;
|
||||
import org.eclipse.hawkbit.ui.filtermanagement.client.SuggestTokenDto;
|
||||
import org.eclipse.hawkbit.ui.filtermanagement.client.SuggestionContextDto;
|
||||
import org.eclipse.hawkbit.ui.filtermanagement.client.TextFieldSuggestionBoxClientRpc;
|
||||
import org.eclipse.hawkbit.ui.filtermanagement.client.TextFieldSuggestionBoxServerRpc;
|
||||
|
||||
import com.vaadin.server.AbstractExtension;
|
||||
import com.vaadin.ui.TextField;
|
||||
import com.vaadin.ui.UI;
|
||||
|
||||
/**
|
||||
* Extension for the AutoCompleteTexfield.
|
||||
*
|
||||
*/
|
||||
public class TextFieldSuggestionBox extends AbstractExtension implements TextFieldSuggestionBoxServerRpc {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final transient RsqlValidationOracle rsqlValidationOracle;
|
||||
private final AutoCompleteTextFieldComponent autoCompleteTextFieldComponent;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param autoCompleteTextFieldComponent
|
||||
* @param rsqlValidationOracle
|
||||
* the suggestion oracle where to retrieve the suggestions from
|
||||
*/
|
||||
public TextFieldSuggestionBox(final RsqlValidationOracle rsqlValidationOracle,
|
||||
final AutoCompleteTextFieldComponent autoCompleteTextFieldComponent) {
|
||||
this.rsqlValidationOracle = rsqlValidationOracle;
|
||||
this.autoCompleteTextFieldComponent = autoCompleteTextFieldComponent;
|
||||
|
||||
registerRpc(this, TextFieldSuggestionBoxServerRpc.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add this extension to the target connector. This method is protected to
|
||||
* allow subclasses to require a more specific type of target.
|
||||
*
|
||||
* @param target
|
||||
* the connector to attach this extension to
|
||||
*/
|
||||
public void extend(final TextField target) {
|
||||
super.extend(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void suggest(final String text, final int cursor) {
|
||||
final ValidationOracleContext suggest = rsqlValidationOracle.suggest(text, cursor);
|
||||
updateValidationIcon(suggest, text);
|
||||
getRpcProxy(TextFieldSuggestionBoxClientRpc.class).showSuggestions(mapToDto(suggest.getSuggestionContext()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeQuery(final String text, final int cursor) {
|
||||
if (!autoCompleteTextFieldComponent.isValidationError()) {
|
||||
autoCompleteTextFieldComponent.showValidationInProgress();
|
||||
autoCompleteTextFieldComponent.getExecutor()
|
||||
.execute(autoCompleteTextFieldComponent.new StatusCircledAsync(UI.getCurrent()));
|
||||
}
|
||||
}
|
||||
|
||||
private static SuggestionContextDto mapToDto(final SuggestionContext suggestionContext) {
|
||||
return new SuggestionContextDto(suggestionContext.getCursorPosition(),
|
||||
suggestionContext.getSuggestions().stream()
|
||||
.filter(suggestion -> suggestion.getTokenImageName() == null
|
||||
|| suggestion.getSuggestion().contains(suggestion.getTokenImageName()))
|
||||
.map(suggestion -> new SuggestTokenDto(suggestion.getStart(), suggestion.getEnd(),
|
||||
suggestion.getSuggestion()))
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
}
|
||||
|
||||
private void updateValidationIcon(final ValidationOracleContext suggest, final String text) {
|
||||
final String errorMessage = (suggest.getSyntaxErrorContext() != null)
|
||||
? suggest.getSyntaxErrorContext().getErrorMessage() : null;
|
||||
autoCompleteTextFieldComponent.onQueryFilterChange(text, !suggest.isSyntaxError(), errorMessage);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.filtermanagement;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
*
|
||||
* Available token details.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class TokenDescription {
|
||||
|
||||
/** Literal token values. */
|
||||
private static final String[] TOKEN_IMAGE = { "<EOF>", "\" \"", "\"\\t\"", "<ALPHA>", "<UNRESERVED_STR>",
|
||||
"<SINGLE_QUOTED_STR>", "<DOUBLE_QUOTED_STR>", "<AND>", "<OR>", "\"(\"", "\")\"", "<==>|<!=>", ">=|<=", };
|
||||
|
||||
public String[] getTokenImage() {
|
||||
return Arrays.copyOf(TOKEN_IMAGE, TOKEN_IMAGE.length);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.filtermanagement;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Query validation result with expected token on error.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ValidationResult {
|
||||
|
||||
private List<String> expectedTokens = new ArrayList<>();
|
||||
|
||||
private String message;
|
||||
|
||||
private Boolean isValidationFailed = Boolean.FALSE;
|
||||
|
||||
/**
|
||||
* @return the isValidationFailed
|
||||
*/
|
||||
public Boolean getIsValidationFailed() {
|
||||
return isValidationFailed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param isValidationFailed
|
||||
* the isValidationFailed to set
|
||||
*/
|
||||
public void setIsValidationFailed(final Boolean isValidationFailed) {
|
||||
this.isValidationFailed = isValidationFailed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the expectedTokens
|
||||
*/
|
||||
public List<String> getExpectedTokens() {
|
||||
return expectedTokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param expectedTokens
|
||||
* the expectedTokens to set
|
||||
*/
|
||||
public void setExpectedTokens(final List<String> expectedTokens) {
|
||||
this.expectedTokens = expectedTokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the message
|
||||
*/
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param message
|
||||
* the message to set
|
||||
*/
|
||||
public void setMessage(final String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.filtermanagement.client;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.ui.filtermanagement.TextFieldSuggestionBox;
|
||||
|
||||
import com.google.gwt.event.dom.client.KeyCodes;
|
||||
import com.google.gwt.event.dom.client.KeyUpEvent;
|
||||
import com.google.gwt.event.dom.client.KeyUpHandler;
|
||||
import com.google.gwt.user.client.ui.MenuItem;
|
||||
import com.vaadin.client.ComponentConnector;
|
||||
import com.vaadin.client.ServerConnector;
|
||||
import com.vaadin.client.extensions.AbstractExtensionConnector;
|
||||
import com.vaadin.client.ui.VOverlay;
|
||||
import com.vaadin.client.ui.VTextField;
|
||||
import com.vaadin.shared.ui.Connect;
|
||||
|
||||
/**
|
||||
* Connector for the AutoCompleteTextField which automatically listens to
|
||||
* key-events to show pop-up panel with entered suggestions based on the
|
||||
* {@link TextFieldSuggestionBoxServerRpc} call.
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings({ "deprecation", "squid:CallToDeprecatedMethod" })
|
||||
// need to use VOverlay because otherwise it's not in the correct theme
|
||||
// widget @see com.vaadin.client.ui.VOverlay.getOverlayContainer()
|
||||
@Connect(TextFieldSuggestionBox.class)
|
||||
public class AutoCompleteTextFieldConnector extends AbstractExtensionConnector {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final transient SuggestionsSelectList select = new SuggestionsSelectList();
|
||||
private transient VTextField textFieldWidget;
|
||||
|
||||
private final TextFieldSuggestionBoxServerRpc rpc = getRpcProxy(TextFieldSuggestionBoxServerRpc.class);
|
||||
|
||||
private final transient VOverlay panel = new VOverlay(true, false, true);
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
|
||||
registerRpc(TextFieldSuggestionBoxClientRpc.class, new TextFieldSuggestionBoxClientRpc() {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public void showSuggestions(final SuggestionContextDto suggestContext) {
|
||||
select.clearItems();
|
||||
if (suggestContext == null) {
|
||||
panel.hide();
|
||||
return;
|
||||
}
|
||||
final List<SuggestTokenDto> suggestions = suggestContext.getSuggestions();
|
||||
if (suggestions != null && !suggestions.isEmpty()) {
|
||||
select.addItems(suggestions, textFieldWidget, panel, rpc);
|
||||
panel.showRelativeTo(textFieldWidget);
|
||||
select.moveSelectionDown();
|
||||
return;
|
||||
}
|
||||
panel.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void extend(final ServerConnector target) {
|
||||
textFieldWidget = (VTextField) ((ComponentConnector) target).getWidget();
|
||||
textFieldWidget.setImmediate(true);
|
||||
textFieldWidget.textChangeEventMode = "EAGER";
|
||||
panel.setWidget(select);
|
||||
panel.setStyleName("suggestion-popup");
|
||||
panel.setOwner(textFieldWidget);
|
||||
|
||||
textFieldWidget.addKeyUpHandler(new KeyUpHandler() {
|
||||
@Override
|
||||
public void onKeyUp(final KeyUpEvent event) {
|
||||
if (panel.isAttached()) {
|
||||
handlePanelEventDelegation(event);
|
||||
} else if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
|
||||
rpc.executeQuery(textFieldWidget.getValue(), textFieldWidget.getCursorPos());
|
||||
} else {
|
||||
doAskForSuggestion();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void handlePanelEventDelegation(final KeyUpEvent event) {
|
||||
switch (event.getNativeKeyCode()) {
|
||||
case KeyCodes.KEY_DOWN:
|
||||
arrowKeyDown(event);
|
||||
break;
|
||||
case KeyCodes.KEY_UP:
|
||||
arrorKeyUp(event);
|
||||
break;
|
||||
case KeyCodes.KEY_ESCAPE:
|
||||
escapeKey();
|
||||
break;
|
||||
case KeyCodes.KEY_ENTER:
|
||||
enterKey();
|
||||
break;
|
||||
default:
|
||||
doAskForSuggestion();
|
||||
}
|
||||
}
|
||||
|
||||
private void escapeKey() {
|
||||
panel.hide();
|
||||
}
|
||||
|
||||
private void enterKey() {
|
||||
final MenuItem item = select.getSelectedItem();
|
||||
if (item != null) {
|
||||
item.getScheduledCommand().execute();
|
||||
}
|
||||
}
|
||||
|
||||
private void arrorKeyUp(final KeyUpEvent event) {
|
||||
select.moveSelectionUp();
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
private void arrowKeyDown(final KeyUpEvent event) {
|
||||
select.moveSelectionDown();
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
private void doAskForSuggestion() {
|
||||
rpc.suggest(textFieldWidget.getValue(), textFieldWidget.getCursorPos());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.filtermanagement.client;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* A suggestion which contains the start and the end character position of the
|
||||
* suggested token of the suggestion of the token and the actual suggestion.
|
||||
*/
|
||||
public class SuggestTokenDto implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private int start;
|
||||
private int end;
|
||||
private String suggestion;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public SuggestTokenDto() {
|
||||
// necessary for java serialization with GWT.
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param start
|
||||
* the character position of the start of the token
|
||||
* @param end
|
||||
* the character position of the end of the token
|
||||
* @param suggestion
|
||||
* the token suggestion
|
||||
*/
|
||||
public SuggestTokenDto(final int start, final int end, final String suggestion) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.suggestion = suggestion;
|
||||
}
|
||||
|
||||
public int getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public int getEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
public String getSuggestion() {
|
||||
return suggestion;
|
||||
}
|
||||
|
||||
public void setStart(final int start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
public void setEnd(final int end) {
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public void setSuggestion(final String suggestion) {
|
||||
this.suggestion = suggestion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SuggestTokenDto [start=" + start + ", end=" + end + ", suggestion=" + suggestion + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.filtermanagement.client;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
public class SuggestionContextDto implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private int cursorPosition;
|
||||
private List<SuggestTokenDto> suggestions;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public SuggestionContextDto() {
|
||||
// necessary for java serialization with GWT.
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param rsqlQuery
|
||||
* the original RSQL based query the suggestions based on
|
||||
* @param cursorPosition
|
||||
* the current cursor position
|
||||
* @param suggestions
|
||||
* the suggestions for the current cursor position
|
||||
*/
|
||||
public SuggestionContextDto(final int cursorPosition, final List<SuggestTokenDto> suggestions) {
|
||||
this.cursorPosition = cursorPosition;
|
||||
this.suggestions = suggestions;
|
||||
}
|
||||
|
||||
public List<SuggestTokenDto> getSuggestions() {
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
public int getCursorPosition() {
|
||||
return cursorPosition;
|
||||
}
|
||||
|
||||
public void setCursorPosition(final int cursorPosition) {
|
||||
this.cursorPosition = cursorPosition;
|
||||
}
|
||||
|
||||
public void setSuggestions(final List<SuggestTokenDto> suggestions) {
|
||||
this.suggestions = suggestions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SuggestionContextDto [cursorPosition=" + cursorPosition + ", suggestions=" + suggestions + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.filtermanagement.client;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.gwt.aria.client.Roles;
|
||||
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
|
||||
import com.google.gwt.user.client.ui.MenuBar;
|
||||
import com.google.gwt.user.client.ui.MenuItem;
|
||||
import com.google.gwt.user.client.ui.PopupPanel;
|
||||
import com.vaadin.client.WidgetUtil;
|
||||
import com.vaadin.client.ui.VTextField;
|
||||
|
||||
/**
|
||||
* The suggestion list within the suggestion pop-up panel.
|
||||
*/
|
||||
public class SuggestionsSelectList extends MenuBar {
|
||||
|
||||
public static final String CLASSNAME = "autocomplete";
|
||||
private final Map<String, TokenStartEnd> tokenMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public SuggestionsSelectList() {
|
||||
super(true);
|
||||
setFocusOnHoverEnabled(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds suggestions to the suggestion menu bar.
|
||||
*
|
||||
* @param suggestions
|
||||
* the suggestions to be added
|
||||
* @param textFieldWidget
|
||||
* the text field which the suggestion is attached to to bring
|
||||
* back the focus after selection
|
||||
* @param popupPanel
|
||||
* pop-up panel where the menu bar is shown to hide it after
|
||||
* selection
|
||||
* @param suggestionServerRpc
|
||||
* server RPC to ask for new suggestion after a selection
|
||||
*/
|
||||
public void addItems(final List<SuggestTokenDto> suggestions, final VTextField textFieldWidget,
|
||||
final PopupPanel popupPanel, final TextFieldSuggestionBoxServerRpc suggestionServerRpc) {
|
||||
for (int index = 0; index < suggestions.size(); index++) {
|
||||
final SuggestTokenDto suggestToken = suggestions.get(index);
|
||||
final MenuItem mi = new MenuItem(suggestToken.getSuggestion(), true, new ScheduledCommand() {
|
||||
@Override
|
||||
public void execute() {
|
||||
final String tmpSuggestion = suggestToken.getSuggestion();
|
||||
final TokenStartEnd tokenStartEnd = tokenMap.get(tmpSuggestion);
|
||||
final String text = textFieldWidget.getValue();
|
||||
final StringBuilder builder = new StringBuilder(text);
|
||||
builder.replace(tokenStartEnd.getStart(), tokenStartEnd.getEnd() + 1, tmpSuggestion);
|
||||
textFieldWidget.setValue(builder.toString(), true);
|
||||
popupPanel.hide();
|
||||
textFieldWidget.setFocus(true);
|
||||
suggestionServerRpc.suggest(builder.toString(), textFieldWidget.getCursorPos());
|
||||
}
|
||||
});
|
||||
tokenMap.put(suggestToken.getSuggestion(),
|
||||
new TokenStartEnd(suggestToken.getStart(), suggestToken.getEnd()));
|
||||
Roles.getListitemRole().set(mi.getElement());
|
||||
WidgetUtil.sinkOnloadForImages(mi.getElement());
|
||||
addItem(mi);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStyleName(final String style) {
|
||||
super.setStyleName(style + "-" + CLASSNAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MenuItem getSelectedItem() {
|
||||
return super.getSelectedItem();
|
||||
}
|
||||
|
||||
/**
|
||||
* Suggestion Token start and end index.
|
||||
*
|
||||
*/
|
||||
public static final class TokenStartEnd {
|
||||
final int start;
|
||||
final int end;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param start
|
||||
* @param end
|
||||
*/
|
||||
public TokenStartEnd(final int start, final int end) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public int getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public int getEnd() {
|
||||
return end;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.filtermanagement.client;
|
||||
|
||||
import com.vaadin.shared.communication.ClientRpc;
|
||||
|
||||
/**
|
||||
* Client RPC for the AutocompleteTextField. The Client RPC interface is used to
|
||||
* make server to client calls in Vaadin. Only void methods are allowed in
|
||||
* ClientRpc calls.
|
||||
*
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface TextFieldSuggestionBoxClientRpc extends ClientRpc {
|
||||
|
||||
/**
|
||||
* Notifies the client about showing the given suggestions in the suggestion
|
||||
* box.
|
||||
*
|
||||
* @param suggestionContext
|
||||
* the suggestion context which contains all informations about
|
||||
* showing suggestions
|
||||
*/
|
||||
void showSuggestions(final SuggestionContextDto suggestionContext);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.filtermanagement.client;
|
||||
|
||||
import com.vaadin.shared.communication.ServerRpc;
|
||||
|
||||
/**
|
||||
* Server RPC for the AutoCompleteTextField. The Server RPC interface is used to
|
||||
* make client to server calls in Vaadin. Only void methods are allowed in
|
||||
* ServerRpc calls.
|
||||
*/
|
||||
public interface TextFieldSuggestionBoxServerRpc extends ServerRpc {
|
||||
|
||||
/**
|
||||
* Parses the given RSQL based query and try finding suggestions at the
|
||||
* current given cursor position. When suggestions are possible the
|
||||
* {@link TextFieldSuggestionBoxClientRpc#showSuggestions(org.eclipse.hawkbit.rsql.SuggestionContext)}
|
||||
* is called as a callback mechanism back to the client.
|
||||
*
|
||||
* @param text
|
||||
* the current entered text e.g. in a text field to retrieve
|
||||
* suggestion for
|
||||
* @param cursor
|
||||
* the current cursor position
|
||||
*/
|
||||
void suggest(final String text, final int cursor);
|
||||
|
||||
/**
|
||||
* Executes the query text to get the filtered data.
|
||||
*
|
||||
* @param text
|
||||
* the current entered text e.g. in a text field to retrieve
|
||||
* suggestion for
|
||||
* @param cursor
|
||||
* the current cursor position
|
||||
*/
|
||||
void executeQuery(final String text, final int cursor);
|
||||
}
|
||||
@@ -8,9 +8,8 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.management.dstable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
@@ -178,10 +177,9 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent {
|
||||
* @return
|
||||
*/
|
||||
private LazyQueryContainer getDistSetTypeLazyQueryContainer() {
|
||||
final Map<String, Object> queryConfig = new HashMap<>();
|
||||
final BeanQueryFactory<DistributionSetTypeBeanQuery> dtQF = new BeanQueryFactory<>(
|
||||
DistributionSetTypeBeanQuery.class);
|
||||
dtQF.setQueryConfiguration(queryConfig);
|
||||
dtQF.setQueryConfiguration(Collections.emptyMap());
|
||||
|
||||
final LazyQueryContainer disttypeContainer = new LazyQueryContainer(
|
||||
new LazyQueryDefinition(true, SPUIDefinitions.DIST_TYPE_SIZE, SPUILabelDefinitions.VAR_NAME), dtQF);
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
package org.eclipse.hawkbit.ui.management.dstable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -43,11 +42,11 @@ import org.eclipse.hawkbit.ui.management.event.PinUnpinEvent;
|
||||
import org.eclipse.hawkbit.ui.management.event.SaveActionWindowEvent;
|
||||
import org.eclipse.hawkbit.ui.management.state.ManagementUIState;
|
||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.TableColumn;
|
||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||
import org.eclipse.hawkbit.ui.utils.UINotification;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory;
|
||||
@@ -56,6 +55,7 @@ import org.vaadin.addons.lazyquerycontainer.LazyQueryDefinition;
|
||||
import org.vaadin.spring.events.EventScope;
|
||||
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.vaadin.data.Container;
|
||||
import com.vaadin.data.Item;
|
||||
import com.vaadin.event.dd.DragAndDropEvent;
|
||||
@@ -240,7 +240,7 @@ public class DistributionTable extends AbstractNamedVersionTable<DistributionSet
|
||||
}
|
||||
|
||||
private Map<String, Object> prepareQueryConfigFilters() {
|
||||
final Map<String, Object> queryConfig = new HashMap<>();
|
||||
final Map<String, Object> queryConfig = Maps.newHashMapWithExpectedSize(4);
|
||||
managementUIState.getDistributionTableFilters().getSearchText()
|
||||
.ifPresent(value -> queryConfig.put(SPUIDefinitions.FILTER_BY_TEXT, value));
|
||||
managementUIState.getDistributionTableFilters().getPinnedTargetId()
|
||||
@@ -525,6 +525,10 @@ public class DistributionTable extends AbstractNamedVersionTable<DistributionSet
|
||||
}
|
||||
|
||||
private void styleDistributionTableOnPinning() {
|
||||
if (!managementUIState.getDistributionTableFilters().getPinnedTargetId().isPresent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Target targetObj = targetService.findTargetByControllerIDWithDetails(
|
||||
managementUIState.getDistributionTableFilters().getPinnedTargetId().get());
|
||||
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.management.dstag;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.eclipse.hawkbit.repository.EntityFactory;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetTagCreatedBulkEvent;
|
||||
@@ -101,9 +100,8 @@ public class DistributionTagButtons extends AbstractFilterButtons {
|
||||
|
||||
@Override
|
||||
protected LazyQueryContainer createButtonsLazyQueryContainer() {
|
||||
final Map<String, Object> queryConfig = new HashMap<>();
|
||||
final BeanQueryFactory<DistributionTagBeanQuery> tagQF = new BeanQueryFactory<>(DistributionTagBeanQuery.class);
|
||||
tagQF.setQueryConfiguration(queryConfig);
|
||||
tagQF.setQueryConfiguration(Collections.emptyMap());
|
||||
return HawkbitCommonUtil.createDSLazyQueryContainer(
|
||||
new BeanQueryFactory<DistributionTagBeanQuery>(DistributionTagBeanQuery.class));
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
package org.eclipse.hawkbit.ui.management.event;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -17,6 +16,7 @@ import org.eclipse.hawkbit.ui.common.AbstractAcceptCriteria;
|
||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.vaadin.spring.annotation.SpringComponent;
|
||||
import com.vaadin.spring.annotation.ViewScope;
|
||||
import com.vaadin.ui.Component;
|
||||
@@ -67,7 +67,7 @@ public class ManagementViewAcceptCriteria extends AbstractAcceptCriteria {
|
||||
}
|
||||
|
||||
private static Map<String, List<String>> createDropConfigurations() {
|
||||
final Map<String, List<String>> config = new HashMap<>();
|
||||
final Map<String, List<String>> config = Maps.newHashMapWithExpectedSize(6);
|
||||
|
||||
// Delete drop area acceptable components
|
||||
config.put(UIComponentIdProvider.DELETE_BUTTON_WRAPPER_ID,
|
||||
@@ -94,7 +94,7 @@ public class ManagementViewAcceptCriteria extends AbstractAcceptCriteria {
|
||||
}
|
||||
|
||||
private static Map<String, Object> createDropHintConfigurations() {
|
||||
final Map<String, Object> config = new HashMap<>();
|
||||
final Map<String, Object> config = Maps.newHashMapWithExpectedSize(4);
|
||||
config.put(SPUIDefinitions.TARGET_TAG_ID_PREFIXS, DragEvent.TARGET_TAG_DRAG);
|
||||
config.put(UIComponentIdProvider.TARGET_TABLE_ID, DragEvent.TARGET_DRAG);
|
||||
config.put(UIComponentIdProvider.DIST_TABLE_ID, DragEvent.DISTRIBUTION_DRAG);
|
||||
|
||||
@@ -10,7 +10,6 @@ package org.eclipse.hawkbit.ui.management.footer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -39,6 +38,7 @@ import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.vaadin.data.Item;
|
||||
import com.vaadin.data.util.IndexedContainer;
|
||||
import com.vaadin.server.FontAwesome;
|
||||
@@ -88,7 +88,7 @@ public class ManangementConfirmationWindowLayout extends AbstractConfirmationWin
|
||||
|
||||
@Override
|
||||
protected Map<String, ConfirmationTab> getConfimrationTabs() {
|
||||
final Map<String, ConfirmationTab> tabs = new HashMap<>();
|
||||
final Map<String, ConfirmationTab> tabs = Maps.newHashMapWithExpectedSize(3);
|
||||
if (!managementUIState.getDeletedDistributionList().isEmpty()) {
|
||||
tabs.put(i18n.get("caption.delete.dist.accordion.tab"), createDeletedDistributionTab());
|
||||
}
|
||||
@@ -150,7 +150,7 @@ public class ManangementConfirmationWindowLayout extends AbstractConfirmationWin
|
||||
? actionTypeOptionGroupLayout.getForcedTimeDateField().getValue().getTime()
|
||||
: RepositoryModelConstants.NO_FORCE_TIME;
|
||||
|
||||
final Map<Long, ArrayList<TargetIdName>> saveAssignedList = new HashMap<>();
|
||||
final Map<Long, ArrayList<TargetIdName>> saveAssignedList = Maps.newHashMapWithExpectedSize(itemIds.size());
|
||||
|
||||
int successAssignmentCount = 0;
|
||||
int duplicateAssignmentCount = 0;
|
||||
|
||||
@@ -87,10 +87,9 @@ public class ManagementUIState implements ManagmentEntityState<DistributionSetId
|
||||
private boolean customFilterSelected;
|
||||
|
||||
private boolean bulkUploadWindowMinimised;
|
||||
|
||||
|
||||
private DistributionSetIdName lastSelectedDistribution;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return the lastSelectedDistribution
|
||||
*/
|
||||
@@ -98,12 +97,10 @@ public class ManagementUIState implements ManagmentEntityState<DistributionSetId
|
||||
return Optional.ofNullable(lastSelectedDistribution);
|
||||
}
|
||||
|
||||
|
||||
public void setLastSelectedDistribution(final DistributionSetIdName value) {
|
||||
this.lastSelectedDistribution = value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the bulkUploadWindowMinimised
|
||||
*/
|
||||
|
||||
@@ -9,12 +9,9 @@
|
||||
package org.eclipse.hawkbit.ui.management.targettable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||
import org.eclipse.hawkbit.ui.UiProperties;
|
||||
@@ -40,6 +37,7 @@ import org.vaadin.addons.lazyquerycontainer.LazyQueryDefinition;
|
||||
import org.vaadin.spring.events.EventBus;
|
||||
import org.vaadin.tokenfield.TokenField;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.vaadin.data.Container;
|
||||
import com.vaadin.server.FontAwesome;
|
||||
import com.vaadin.shared.ui.combobox.FilteringMode;
|
||||
@@ -112,12 +110,6 @@ public class TargetBulkUpdateWindowLayout extends CustomComponent {
|
||||
buildLayout();
|
||||
setImmediate(true);
|
||||
setCompositionRoot(mainLayout);
|
||||
eventBus.subscribe(this);
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
void destroy() {
|
||||
eventBus.unsubscribe(this);
|
||||
}
|
||||
|
||||
protected void onStartOfUpload() {
|
||||
@@ -242,7 +234,7 @@ public class TargetBulkUpdateWindowLayout extends CustomComponent {
|
||||
*/
|
||||
private Container createContainer() {
|
||||
|
||||
final Map<String, Object> queryConfiguration = new HashMap<>();
|
||||
final Map<String, Object> queryConfiguration = Maps.newHashMapWithExpectedSize(2);
|
||||
|
||||
final List<String> list = new ArrayList<>();
|
||||
queryConfiguration.put(SPUIDefinitions.FILTER_BY_NO_TAG,
|
||||
|
||||
@@ -19,10 +19,10 @@ import static org.eclipse.hawkbit.ui.management.event.TargetFilterEvent.REMOVE_F
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -43,12 +43,6 @@ import org.eclipse.hawkbit.ui.common.ManagmentEntityState;
|
||||
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
|
||||
import org.eclipse.hawkbit.ui.common.table.AbstractTable;
|
||||
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
|
||||
import org.eclipse.hawkbit.ui.filter.FilterExpression;
|
||||
import org.eclipse.hawkbit.ui.filter.Filters;
|
||||
import org.eclipse.hawkbit.ui.filter.target.CustomTargetFilter;
|
||||
import org.eclipse.hawkbit.ui.filter.target.TargetSearchTextFilter;
|
||||
import org.eclipse.hawkbit.ui.filter.target.TargetStatusFilter;
|
||||
import org.eclipse.hawkbit.ui.filter.target.TargetTagFilter;
|
||||
import org.eclipse.hawkbit.ui.management.event.DragEvent;
|
||||
import org.eclipse.hawkbit.ui.management.event.ManagementUIEvent;
|
||||
import org.eclipse.hawkbit.ui.management.event.ManagementViewAcceptCriteria;
|
||||
@@ -78,6 +72,7 @@ import org.vaadin.spring.events.EventScope;
|
||||
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.vaadin.data.Container;
|
||||
import com.vaadin.data.Item;
|
||||
import com.vaadin.event.dd.DragAndDropEvent;
|
||||
@@ -140,11 +135,14 @@ public class TargetTable extends AbstractTable<Target, TargetIdName> {
|
||||
if (TargetCreatedEvent.class.isInstance(firstEvent)) {
|
||||
onTargetCreatedEvents();
|
||||
} else if (TargetInfoUpdateEvent.class.isInstance(firstEvent)) {
|
||||
onTargetInfoUpdateEvents((List<TargetInfoUpdateEvent>) events);
|
||||
onTargetUpdateEvents(((List<TargetInfoUpdateEvent>) events).stream()
|
||||
.map(targetInfoUpdateEvent -> targetInfoUpdateEvent.getEntity().getTarget())
|
||||
.collect(Collectors.toList()));
|
||||
} else if (TargetDeletedEvent.class.isInstance(firstEvent)) {
|
||||
onTargetDeletedEvent((List<TargetDeletedEvent>) events);
|
||||
} else if (TargetUpdatedEvent.class.isInstance(firstEvent)) {
|
||||
onTargetUpdateEvents((List<TargetUpdatedEvent>) events);
|
||||
onTargetUpdateEvents(((List<TargetUpdatedEvent>) events).stream()
|
||||
.map(targetInfoUpdateEvent -> targetInfoUpdateEvent.getEntity()).collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,7 +346,7 @@ public class TargetTable extends AbstractTable<Target, TargetIdName> {
|
||||
}
|
||||
|
||||
private Map<String, Object> prepareQueryConfigFilters() {
|
||||
final Map<String, Object> queryConfig = new HashMap<>();
|
||||
final Map<String, Object> queryConfig = Maps.newHashMapWithExpectedSize(7);
|
||||
managementUIState.getTargetTableFilters().getSearchText()
|
||||
.ifPresent(value -> queryConfig.put(SPUIDefinitions.FILTER_BY_TEXT, value));
|
||||
managementUIState.getTargetTableFilters().getDistributionSet()
|
||||
@@ -746,16 +744,17 @@ public class TargetTable extends AbstractTable<Target, TargetIdName> {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void updateVisibleItemOnEvent(final TargetInfo targetInfo, final Target target,
|
||||
final TargetIdName targetIdName) {
|
||||
private void updateVisibleItemOnEvent(final TargetInfo targetInfo) {
|
||||
final Target target = targetInfo.getTarget();
|
||||
final TargetIdName targetIdName = target.getTargetIdName();
|
||||
|
||||
final LazyQueryContainer targetContainer = (LazyQueryContainer) getContainerDataSource();
|
||||
final Item item = targetContainer.getItem(targetIdName);
|
||||
|
||||
item.getItemProperty(SPUILabelDefinitions.VAR_NAME).setValue(target.getName());
|
||||
if (targetInfo != null) {
|
||||
item.getItemProperty(SPUILabelDefinitions.VAR_POLL_STATUS_TOOL_TIP)
|
||||
.setValue(HawkbitCommonUtil.getPollStatusToolTip(targetInfo.getPollStatus(), i18n));
|
||||
item.getItemProperty(SPUILabelDefinitions.VAR_TARGET_STATUS).setValue(targetInfo.getUpdateStatus());
|
||||
}
|
||||
item.getItemProperty(SPUILabelDefinitions.VAR_POLL_STATUS_TOOL_TIP)
|
||||
.setValue(HawkbitCommonUtil.getPollStatusToolTip(targetInfo.getPollStatus(), i18n));
|
||||
item.getItemProperty(SPUILabelDefinitions.VAR_TARGET_STATUS).setValue(targetInfo.getUpdateStatus());
|
||||
}
|
||||
|
||||
private boolean isLastSelectedTarget(final TargetIdName targetIdName) {
|
||||
@@ -767,62 +766,30 @@ public class TargetTable extends AbstractTable<Target, TargetIdName> {
|
||||
* EventListener method which is called by the event bus to notify about a
|
||||
* list of {@link TargetInfoUpdateEvent}.
|
||||
*
|
||||
* @param targetInfoUpdateEvents
|
||||
* list of target info update event
|
||||
* @param updatedTargets
|
||||
* list of updated targets
|
||||
*/
|
||||
private void onTargetInfoUpdateEvents(final List<TargetInfoUpdateEvent> targetInfoUpdateEvents) {
|
||||
private void onTargetUpdateEvents(final List<Target> updatedTargets) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<Object> visibleItemIds = (List<Object>) getVisibleItemIds();
|
||||
boolean shoulTargetsUpdated = false;
|
||||
Target lastSelectedTarget = null;
|
||||
for (final TargetInfoUpdateEvent targetInfoUpdateEvent : targetInfoUpdateEvents) {
|
||||
final TargetInfo targetInfo = targetInfoUpdateEvent.getEntity();
|
||||
final Target target = targetInfo.getTarget();
|
||||
final TargetIdName targetIdName = target.getTargetIdName();
|
||||
if (Filters.or(getTargetTableFilters(target)).doFilter()) {
|
||||
shoulTargetsUpdated = true;
|
||||
} else {
|
||||
if (visibleItemIds.contains(targetIdName)) {
|
||||
updateVisibleItemOnEvent(targetInfo, target, targetIdName);
|
||||
}
|
||||
}
|
||||
// workaround until push is available for action history, re-select
|
||||
// the updated target so the action history gets refreshed.
|
||||
if (isLastSelectedTarget(targetIdName)) {
|
||||
lastSelectedTarget = target;
|
||||
}
|
||||
}
|
||||
if (shoulTargetsUpdated) {
|
||||
refreshTargets();
|
||||
}
|
||||
if (lastSelectedTarget != null) {
|
||||
eventBus.publish(this, new TargetTableEvent(BaseEntityEventType.SELECTED_ENTITY, lastSelectedTarget));
|
||||
}
|
||||
}
|
||||
|
||||
private void onTargetUpdateEvents(final List<TargetUpdatedEvent> events) {
|
||||
final List<Object> visibleItemIds = (List<Object>) getVisibleItemIds();
|
||||
boolean shoulTargetsUpdated = false;
|
||||
Target lastSelectedTarget = null;
|
||||
for (final TargetUpdatedEvent targetUpdatedEvent : events) {
|
||||
final Target target = targetUpdatedEvent.getEntity();
|
||||
final TargetIdName targetIdName = target.getTargetIdName();
|
||||
if (Filters.or(getTargetTableFilters(target)).doFilter()) {
|
||||
shoulTargetsUpdated = true;
|
||||
} else {
|
||||
if (visibleItemIds.contains(targetIdName)) {
|
||||
updateVisibleItemOnEvent(null, target, targetIdName);
|
||||
}
|
||||
}
|
||||
if (isLastSelectedTarget(targetIdName)) {
|
||||
lastSelectedTarget = target;
|
||||
}
|
||||
}
|
||||
if (shoulTargetsUpdated) {
|
||||
if (isFilterEnabled()) {
|
||||
LOG.debug("Filter enabled on UI {}. Refresh targets from database.", getUI().getUIId());
|
||||
refreshTargets();
|
||||
} else {
|
||||
updatedTargets.stream().filter(target -> visibleItemIds.contains(target.getTargetIdName()))
|
||||
.forEach(target -> updateVisibleItemOnEvent(target.getTargetInfo()));
|
||||
}
|
||||
if (lastSelectedTarget != null) {
|
||||
eventBus.publish(this, new TargetTableEvent(BaseEntityEventType.SELECTED_ENTITY, lastSelectedTarget));
|
||||
|
||||
// workaround until push is available for action
|
||||
// history, re-select
|
||||
// the updated target so the action history gets
|
||||
// refreshed.
|
||||
final Optional<Target> selected = updatedTargets.stream()
|
||||
.filter(target -> isLastSelectedTarget(target.getTargetIdName())).findAny();
|
||||
if (selected.isPresent()) {
|
||||
LOG.debug("Selected element has changed on UI {}. Reselect to update action history.", getUI().getUIId());
|
||||
eventBus.publish(this, new TargetTableEvent(BaseEntityEventType.SELECTED_ENTITY, selected.get()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -830,17 +797,11 @@ public class TargetTable extends AbstractTable<Target, TargetIdName> {
|
||||
refreshTargets();
|
||||
}
|
||||
|
||||
private List<FilterExpression> getTargetTableFilters(final Target target) {
|
||||
private boolean isFilterEnabled() {
|
||||
final TargetTableFilters targetTableFilters = managementUIState.getTargetTableFilters();
|
||||
final List<FilterExpression> filters = new ArrayList<>();
|
||||
if (targetTableFilters.getSearchText().isPresent()) {
|
||||
filters.add(new TargetSearchTextFilter(target, targetTableFilters.getSearchText().get()));
|
||||
}
|
||||
filters.add(new TargetStatusFilter(targetTableFilters.getClickedStatusTargetTags()));
|
||||
filters.add(new TargetTagFilter(target, targetTableFilters.getClickedTargetTags(),
|
||||
targetTableFilters.isNoTagSelected()));
|
||||
filters.add(new CustomTargetFilter(targetTableFilters.getTargetFilterQuery()));
|
||||
return filters;
|
||||
return targetTableFilters.getSearchText().isPresent() || !targetTableFilters.getClickedTargetTags().isEmpty()
|
||||
|| !targetTableFilters.getClickedStatusTargetTags().isEmpty()
|
||||
|| targetTableFilters.getTargetFilterQuery().isPresent();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,9 +9,8 @@
|
||||
package org.eclipse.hawkbit.ui.management.targettag;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
@@ -102,8 +101,7 @@ public class TargetFilterQueryButtons extends Table {
|
||||
protected LazyQueryContainer createButtonsLazyQueryContainer() {
|
||||
final BeanQueryFactory<TargetFilterBeanQuery> queryFactory = new BeanQueryFactory<>(
|
||||
TargetFilterBeanQuery.class);
|
||||
final Map<String, Object> queryConfig = new HashMap<>();
|
||||
queryFactory.setQueryConfiguration(queryConfig);
|
||||
queryFactory.setQueryConfiguration(Collections.emptyMap());
|
||||
return new LazyQueryContainer(new LazyQueryDefinition(true, 20, "id"), queryFactory);
|
||||
}
|
||||
|
||||
|
||||
@@ -296,7 +296,7 @@ public final class DashboardMenu extends CustomComponent {
|
||||
final Optional<DashboardMenuItem> findFirst = dashboardVaadinViews.stream()
|
||||
.filter(view -> view.getViewName().equals(viewName)).findFirst();
|
||||
|
||||
if (findFirst == null || !findFirst.isPresent()) {
|
||||
if (!findFirst.isPresent()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.push;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.BlockingDeque;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
@@ -20,6 +20,7 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.hawkbit.eventbus.event.EntityEvent;
|
||||
import org.eclipse.hawkbit.eventbus.event.Event;
|
||||
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
|
||||
import org.eclipse.hawkbit.ui.UIEventProvider;
|
||||
import org.slf4j.Logger;
|
||||
@@ -57,10 +58,11 @@ public class DelayedEventBusPushStrategy implements EventPushStrategy {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DelayedEventBusPushStrategy.class);
|
||||
|
||||
private static final int BLOCK_SIZE = 10_000;
|
||||
private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
|
||||
private final BlockingDeque<org.eclipse.hawkbit.eventbus.event.Event> queue = new LinkedBlockingDeque<>(BLOCK_SIZE);
|
||||
private final ScheduledExecutorService executorService;
|
||||
private final BlockingDeque<Event> queue = new LinkedBlockingDeque<>(BLOCK_SIZE);
|
||||
private final EventBus.SessionEventBus eventBus;
|
||||
private final com.google.common.eventbus.EventBus systemEventBus;
|
||||
private int uiid = -1;
|
||||
|
||||
private ScheduledFuture<?> jobHandle;
|
||||
|
||||
@@ -68,15 +70,20 @@ public class DelayedEventBusPushStrategy implements EventPushStrategy {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
*
|
||||
* @param executorService
|
||||
* for scheduled execution of event forwarding to the UI
|
||||
* @param eventBus
|
||||
* the session event bus to where the events should be dispatched
|
||||
* @param systemEventBus
|
||||
* the system event bus where to retrieve the events from the
|
||||
* back-end
|
||||
* @param eventProvider
|
||||
* for event delegation to UI
|
||||
*/
|
||||
public DelayedEventBusPushStrategy(final SessionEventBus eventBus,
|
||||
public DelayedEventBusPushStrategy(final ScheduledExecutorService executorService, final SessionEventBus eventBus,
|
||||
final com.google.common.eventbus.EventBus systemEventBus, final UIEventProvider eventProvider) {
|
||||
this.executorService = executorService;
|
||||
this.eventBus = eventBus;
|
||||
this.systemEventBus = systemEventBus;
|
||||
this.eventProvider = eventProvider;
|
||||
@@ -92,7 +99,7 @@ public class DelayedEventBusPushStrategy implements EventPushStrategy {
|
||||
*/
|
||||
@Subscribe
|
||||
@AllowConcurrentEvents
|
||||
public void dispatch(final org.eclipse.hawkbit.eventbus.event.Event event) {
|
||||
public void dispatch(final Event event) {
|
||||
// to dispatch too many events which are not interested on the UI
|
||||
if (!isEventProvided(event)) {
|
||||
LOG.trace("Event is not supported in the UI!!! Dropped event is {}", event);
|
||||
@@ -100,19 +107,24 @@ public class DelayedEventBusPushStrategy implements EventPushStrategy {
|
||||
}
|
||||
|
||||
if (!queue.offer(event)) {
|
||||
LOG.warn("Deque limit is reached, cannot add more events!!! Dropped event is {}", event);
|
||||
LOG.trace("Deque limit is reached, cannot add more events for UI {}! Dropped event is {}", uiid, event);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isEventProvided(final org.eclipse.hawkbit.eventbus.event.Event event) {
|
||||
private boolean isEventProvided(final Event event) {
|
||||
return eventProvider.getSingleEvents().contains(event.getClass())
|
||||
|| eventProvider.getBulkEvents().contains(event.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(final UI vaadinUI) {
|
||||
LOG.debug("Initialize delayed event push strategy");
|
||||
uiid = vaadinUI.getUIId();
|
||||
LOG.info("Initialize delayed event push strategy for UI {}", uiid);
|
||||
if (vaadinUI.getSession() == null) {
|
||||
LOG.error("Vaadin session of UI {} is null! Event push disabled!", uiid);
|
||||
}
|
||||
|
||||
jobHandle = executorService.scheduleWithFixedDelay(new DispatchRunnable(vaadinUI, vaadinUI.getSession()), 500,
|
||||
2000, TimeUnit.MILLISECONDS);
|
||||
systemEventBus.register(this);
|
||||
@@ -120,10 +132,9 @@ public class DelayedEventBusPushStrategy implements EventPushStrategy {
|
||||
|
||||
@Override
|
||||
public void clean() {
|
||||
LOG.debug("Cleanup resources");
|
||||
jobHandle.cancel(true);
|
||||
LOG.info("Cleanup delayed event push strategy for UI", uiid);
|
||||
systemEventBus.unregister(this);
|
||||
executorService.shutdownNow();
|
||||
jobHandle.cancel(true);
|
||||
queue.clear();
|
||||
}
|
||||
|
||||
@@ -138,8 +149,7 @@ public class DelayedEventBusPushStrategy implements EventPushStrategy {
|
||||
* @return {@code true} if the event can be dispatched to the UI otherwise
|
||||
* {@code false}
|
||||
*/
|
||||
protected boolean eventSecurityCheck(final SecurityContext userContext,
|
||||
final org.eclipse.hawkbit.eventbus.event.Event event) {
|
||||
protected static boolean eventSecurityCheck(final SecurityContext userContext, final Event event) {
|
||||
if (userContext == null || userContext.getAuthentication() == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -163,43 +173,39 @@ public class DelayedEventBusPushStrategy implements EventPushStrategy {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
LOG.debug("UI EventBus aggregator started");
|
||||
LOG.debug("UI EventBus aggregator started for UI {}", vaadinUI.getUIId());
|
||||
final long timestamp = System.currentTimeMillis();
|
||||
final List<org.eclipse.hawkbit.eventbus.event.Event> events = new LinkedList<>();
|
||||
for (int i = 0; i < BLOCK_SIZE; i++) {
|
||||
final org.eclipse.hawkbit.eventbus.event.Event pollEvent = queue.poll();
|
||||
if (pollEvent == null) {
|
||||
continue;
|
||||
}
|
||||
events.add(pollEvent);
|
||||
|
||||
final int size = queue.size();
|
||||
if (size <= 0) {
|
||||
LOG.debug("UI EventBus aggregator for UI {} has nothing to do.", vaadinUI.getUIId());
|
||||
return;
|
||||
}
|
||||
|
||||
final List<Event> events = new ArrayList<>(size);
|
||||
final int eventsSize = queue.drainTo(events);
|
||||
|
||||
if (events.isEmpty()) {
|
||||
LOG.debug("UI EventBus aggregator for UI {} has nothing to do.", vaadinUI.getUIId());
|
||||
return;
|
||||
}
|
||||
|
||||
if (vaadinSession == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG.debug("UI EventBus aggregator session: {}", vaadinSession);
|
||||
|
||||
final WrappedSession wrappedSession = vaadinSession.getSession();
|
||||
if (wrappedSession == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int eventsSize = events.size();
|
||||
LOG.debug("UI EventBus aggregator dispatches {} events for session {} for UI {}", eventsSize, vaadinSession,
|
||||
vaadinUI.getUIId());
|
||||
|
||||
doDispatch(events, wrappedSession);
|
||||
|
||||
LOG.debug("UI EventBus aggregator done with sending {} events in {} ms", eventsSize,
|
||||
System.currentTimeMillis() - timestamp);
|
||||
LOG.debug("UI EventBus aggregator done with sending {} events in {} ms for UI {}", eventsSize,
|
||||
System.currentTimeMillis() - timestamp, vaadinUI.getUIId());
|
||||
|
||||
}
|
||||
|
||||
private void doDispatch(final List<org.eclipse.hawkbit.eventbus.event.Event> events,
|
||||
final WrappedSession wrappedSession) {
|
||||
private void doDispatch(final List<Event> events, final WrappedSession wrappedSession) {
|
||||
final SecurityContext userContext = (SecurityContext) wrappedSession
|
||||
.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
|
||||
final SecurityContext oldContext = SecurityContextHolder.getContext();
|
||||
@@ -210,25 +216,24 @@ public class DelayedEventBusPushStrategy implements EventPushStrategy {
|
||||
if (vaadinSession.getState() != State.OPEN) {
|
||||
return;
|
||||
}
|
||||
LOG.debug("UI EventBus aggregator of UI {} got lock on session.", vaadinUI.getUIId());
|
||||
fowardSingleEvents(events, userContext);
|
||||
fowardBulkEvents(events, userContext);
|
||||
});
|
||||
LOG.debug("UI EventBus aggregator of UI {} left lock on session.", vaadinUI.getUIId());
|
||||
}).get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
LOG.error("Wait for Vaadin session for UI {} interrupted!", vaadinUI.getUIId(), e);
|
||||
} finally {
|
||||
SecurityContextHolder.setContext(oldContext);
|
||||
}
|
||||
}
|
||||
|
||||
private void fowardBulkEvents(final List<org.eclipse.hawkbit.eventbus.event.Event> events,
|
||||
final SecurityContext userContext) {
|
||||
private void fowardBulkEvents(final List<Event> events, final SecurityContext userContext) {
|
||||
final Set<Class<?>> filterBulkEvenTypes = eventProvider.getFilteredBulkEventsType(events);
|
||||
publishBulkEvent(events, userContext, filterBulkEvenTypes);
|
||||
}
|
||||
|
||||
private void publishBulkEvent(final List<org.eclipse.hawkbit.eventbus.event.Event> events,
|
||||
final SecurityContext userContext, final Set<Class<?>> filterBulkEvenTypes) {
|
||||
for (final Class<?> bulkType : filterBulkEvenTypes) {
|
||||
final List<org.eclipse.hawkbit.eventbus.event.Event> listBulkEvents = events.stream()
|
||||
.filter(event -> DelayedEventBusPushStrategy.this.eventSecurityCheck(userContext, event)
|
||||
final List<Event> listBulkEvents = events.stream()
|
||||
.filter(event -> DelayedEventBusPushStrategy.eventSecurityCheck(userContext, event)
|
||||
&& bulkType.isInstance(event))
|
||||
.collect(Collectors.toList());
|
||||
if (!listBulkEvents.isEmpty()) {
|
||||
@@ -237,10 +242,9 @@ public class DelayedEventBusPushStrategy implements EventPushStrategy {
|
||||
}
|
||||
}
|
||||
|
||||
private void fowardSingleEvents(final List<org.eclipse.hawkbit.eventbus.event.Event> events,
|
||||
final SecurityContext userContext) {
|
||||
private void fowardSingleEvents(final List<Event> events, final SecurityContext userContext) {
|
||||
events.stream()
|
||||
.filter(event -> DelayedEventBusPushStrategy.this.eventSecurityCheck(userContext, event)
|
||||
.filter(event -> DelayedEventBusPushStrategy.eventSecurityCheck(userContext, event)
|
||||
&& eventProvider.getSingleEvents().contains(event.getClass()))
|
||||
.forEach(event -> eventBus.publish(vaadinUI, event));
|
||||
}
|
||||
|
||||
@@ -43,10 +43,10 @@ import org.eclipse.hawkbit.ui.rollout.event.RolloutEvent;
|
||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
|
||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||
import org.eclipse.hawkbit.ui.utils.UINotification;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory;
|
||||
@@ -610,26 +610,15 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
|
||||
|
||||
@Override
|
||||
public void validate(final Object value) {
|
||||
try {
|
||||
if (isNoOfGroupsOrTargetFilterEmpty()) {
|
||||
uiNotification
|
||||
.displayValidationError(i18n.get("message.rollout.noofgroups.or.targetfilter.missing"));
|
||||
} else {
|
||||
if (value != null) {
|
||||
final int groupSize = getGroupSize();
|
||||
new IntegerRangeValidator(i18n.get(MESSAGE_ROLLOUT_FIELD_VALUE_RANGE, 0, groupSize), 0,
|
||||
groupSize).validate(Integer.valueOf(value.toString()));
|
||||
}
|
||||
if (isNoOfGroupsOrTargetFilterEmpty()) {
|
||||
uiNotification.displayValidationError(i18n.get("message.rollout.noofgroups.or.targetfilter.missing"));
|
||||
} else {
|
||||
if (value != null) {
|
||||
final int groupSize = getGroupSize();
|
||||
new IntegerRangeValidator(i18n.get(MESSAGE_ROLLOUT_FIELD_VALUE_RANGE, 0, groupSize), 0, groupSize)
|
||||
.validate(Integer.valueOf(value.toString()));
|
||||
}
|
||||
}
|
||||
// suppress the need of preserve original exception, will blow
|
||||
// up the
|
||||
// log and not necessary here
|
||||
catch (final InvalidValueException ex) {
|
||||
// we have to throw the exception here, otherwise the UI won't
|
||||
// show the vaadin validation error!
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isNoOfGroupsOrTargetFilterEmpty() {
|
||||
@@ -648,19 +637,9 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
|
||||
|
||||
@Override
|
||||
public void validate(final Object value) {
|
||||
try {
|
||||
if (value != null) {
|
||||
new IntegerRangeValidator(i18n.get(MESSAGE_ROLLOUT_FIELD_VALUE_RANGE, 0, 100), 0, 100)
|
||||
.validate(Integer.valueOf(value.toString()));
|
||||
}
|
||||
}
|
||||
// suppress the need of preserve original exception, will blow
|
||||
// up the
|
||||
// log and not necessary here
|
||||
catch (final InvalidValueException ex) {
|
||||
// we have to throw the exception here, otherwise the UI won't
|
||||
// show the vaadin validation error!
|
||||
throw ex;
|
||||
if (value != null) {
|
||||
new IntegerRangeValidator(i18n.get(MESSAGE_ROLLOUT_FIELD_VALUE_RANGE, 0, 100), 0, 100)
|
||||
.validate(Integer.valueOf(value.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -670,19 +649,9 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
|
||||
|
||||
@Override
|
||||
public void validate(final Object value) {
|
||||
try {
|
||||
if (value != null) {
|
||||
new IntegerRangeValidator(i18n.get(MESSAGE_ROLLOUT_FIELD_VALUE_RANGE, 0, 500), 0, 500)
|
||||
.validate(Integer.valueOf(value.toString()));
|
||||
}
|
||||
}
|
||||
// suppress the need of preserve original exception, will blow
|
||||
// up the
|
||||
// log and not necessary here
|
||||
catch (final InvalidValueException ex) {
|
||||
// we have to throw the exception here, otherwise the UI won't
|
||||
// show the vaadin validation error!
|
||||
throw ex;
|
||||
if (value != null) {
|
||||
new IntegerRangeValidator(i18n.get(MESSAGE_ROLLOUT_FIELD_VALUE_RANGE, 0, 500), 0, 500)
|
||||
.validate(Integer.valueOf(value.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import static org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions.VAR_TOTAL_TARGET
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
@@ -57,6 +56,7 @@ import org.vaadin.addons.lazyquerycontainer.LazyQueryDefinition;
|
||||
import org.vaadin.spring.events.EventScope;
|
||||
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.vaadin.data.Container;
|
||||
import com.vaadin.data.Item;
|
||||
import com.vaadin.data.util.converter.Converter;
|
||||
@@ -495,7 +495,8 @@ public class RolloutListGrid extends AbstractGrid {
|
||||
* Contains all expected rollout status per column to enable or disable
|
||||
* the button.
|
||||
*/
|
||||
private static final Map<String, RolloutStatus> EXPECTED_ROLLOUT_STATUS_ENABLE_BUTTON = new HashMap<>();
|
||||
private static final Map<String, RolloutStatus> EXPECTED_ROLLOUT_STATUS_ENABLE_BUTTON = Maps
|
||||
.newHashMapWithExpectedSize(2);
|
||||
private final Container.Indexed containerDataSource;
|
||||
|
||||
static {
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
package org.eclipse.hawkbit.ui.utils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
@@ -435,8 +435,7 @@ public final class HawkbitCommonUtil {
|
||||
*/
|
||||
public static LazyQueryContainer createLazyQueryContainer(
|
||||
final BeanQueryFactory<? extends AbstractBeanQuery<?>> queryFactory) {
|
||||
final Map<String, Object> queryConfig = new HashMap<>();
|
||||
queryFactory.setQueryConfiguration(queryConfig);
|
||||
queryFactory.setQueryConfiguration(Collections.emptyMap());
|
||||
return new LazyQueryContainer(new LazyQueryDefinition(true, 20, SPUILabelDefinitions.VAR_NAME), queryFactory);
|
||||
}
|
||||
|
||||
@@ -448,8 +447,7 @@ public final class HawkbitCommonUtil {
|
||||
*/
|
||||
public static LazyQueryContainer createDSLazyQueryContainer(
|
||||
final BeanQueryFactory<? extends AbstractBeanQuery<?>> queryFactory) {
|
||||
final Map<String, Object> queryConfig = new HashMap<>();
|
||||
queryFactory.setQueryConfiguration(queryConfig);
|
||||
queryFactory.setQueryConfiguration(Collections.emptyMap());
|
||||
return new LazyQueryContainer(new LazyQueryDefinition(true, 20, "tagIdName"), queryFactory);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ package org.eclipse.hawkbit.ui.utils;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
@@ -19,6 +18,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.time.DurationFormatUtils;
|
||||
import org.eclipse.hawkbit.repository.model.BaseEntity;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.vaadin.server.WebBrowser;
|
||||
|
||||
/**
|
||||
@@ -32,7 +32,7 @@ import com.vaadin.server.WebBrowser;
|
||||
public final class SPDateTimeUtil {
|
||||
|
||||
private static final String DURATION_FORMAT = "y','M','d','H','m','s";
|
||||
private static final Map<Integer, CalendarI18N> DURATION_I18N = new HashMap<>();
|
||||
private static final Map<Integer, CalendarI18N> DURATION_I18N = Maps.newHashMapWithExpectedSize(6);
|
||||
|
||||
static {
|
||||
DURATION_I18N.put(0, CalendarI18N.YEAR);
|
||||
|
||||
@@ -876,6 +876,10 @@ public final class UIComponentIdProvider {
|
||||
* ID for download anonymous checkbox
|
||||
*/
|
||||
public static final String DOWNLOAD_ANONYMOUS_CHECKBOX = "downloadanonymouscheckbox";
|
||||
/**
|
||||
* Id of custom filter query search Icon.
|
||||
*/
|
||||
public static final String FILTER_SEARCH_ICON_ID = "filter.search.icon";
|
||||
|
||||
/**
|
||||
* Distribution set select table id
|
||||
|
||||
@@ -8,6 +8,39 @@
|
||||
*/
|
||||
@mixin target-filter-query {
|
||||
|
||||
.gwt-MenuBar-autocomplete {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.gwt-MenuBar-autocomplete .gwt-MenuItem{
|
||||
border-radius: 3px !important;
|
||||
cursor: pointer !important;
|
||||
font-weight: 400 !important;
|
||||
line-height: 27px !important;
|
||||
padding: 0 20px 0 10px !important;
|
||||
position: relative !important;
|
||||
white-space: nowrap !important;
|
||||
}
|
||||
|
||||
.gwt-MenuBar-autocomplete .gwt-MenuItem-selected {
|
||||
background-color: $hawkbit-primary-color;
|
||||
background-image: linear-gradient(to bottom, #1b87e3 2%, #166ed5 98%) !important;
|
||||
color: #ecf2f8 !important;
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.05) !important;
|
||||
}
|
||||
.suggestion-popup{
|
||||
backface-visibility: hidden;
|
||||
background-color: white;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 4px 10px 0 rgba(0, 0, 0, 0.1), 0 3px 5px 0 rgba(0, 0, 0, 0.05), 0 0 0 1px rgba(0, 0, 0, 0.09);
|
||||
box-sizing: border-box;
|
||||
color: #474747;
|
||||
padding: 4px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
|
||||
.caption-header-layout{
|
||||
padding-left:10px;
|
||||
}
|
||||
@@ -23,15 +56,17 @@
|
||||
.target-filter-textfield, .target-filter-textfield:focus{
|
||||
border:none !important;
|
||||
box-shadow: none !important;
|
||||
height:26px !important;
|
||||
height: 26px !important;
|
||||
}
|
||||
|
||||
.error-icon{
|
||||
margin-left: 5px;
|
||||
color:$success-icon-color !important;
|
||||
padding-left:2px !important;
|
||||
}
|
||||
|
||||
.success-icon{
|
||||
margin-left: 5px;
|
||||
color:$error-icon-color !important;
|
||||
padding-left:2px !important;
|
||||
}
|
||||
@@ -42,10 +77,12 @@
|
||||
}
|
||||
|
||||
.target-filter-spinner{
|
||||
@include valo-spinner(
|
||||
$size: $v-font-size--small,
|
||||
$color: $bosch-color-light-blue
|
||||
);
|
||||
margin-top: 5px;
|
||||
margin-left: 5px;
|
||||
@include valo-spinner(
|
||||
$size:16px,
|
||||
$speed:500ms
|
||||
);
|
||||
}
|
||||
|
||||
.hide-status-label {
|
||||
|
||||
Reference in New Issue
Block a user