Added subview for polling configuration in system configuration window

* updated architectural concept os subview
** added base class BaseConfigurationView
** updated interface ConfigurationGroup
* updated message strings for new pollign configurations
* implemented new vaadin compontent DurationField (extends DateTimeField)

TODO:
* update positioning of DurationFields
* update validation of user input, espacilly against min and max value

Signed-off-by: Nonnenmacher Fabian <fabian.nonnenmacher@bosch-si.com>
This commit is contained in:
Fabian Nonnenmacher
2015-12-22 16:30:00 +01:00
committed by Nonnenmacher Fabian
parent 7e2ad9fc4a
commit ee1aabc93f
9 changed files with 371 additions and 78 deletions

View File

@@ -8,9 +8,6 @@
*/
package org.eclipse.hawkbit.ui.tenantconfiguration;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
@@ -26,7 +23,6 @@ import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.CheckBox;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Panel;
@@ -40,8 +36,8 @@ import com.vaadin.ui.VerticalLayout;
*/
@SpringComponent
@ViewScope
public class AuthenticationConfigurationView extends CustomComponent
implements ConfigurationGroup, TenantConfigurationItem.TenantConfigurationChangeListener {
public class AuthenticationConfigurationView extends BaseConfigurationView
implements ConfigurationGroup, TenantConfigurationItem.TenantConfigurationChangeListener, ValueChangeListener {
/**
*
@@ -65,8 +61,6 @@ public class AuthenticationConfigurationView extends CustomComponent
@Autowired
private GatewaySecurityTokenAuthenticationConfigurationItem gatewaySecurityTokenAuthenticationConfigurationItem;
private final List<ConfigurationGroupChangeListener> configurationChangeListeners = new ArrayList<>();
private CheckBox gatewaySecTokenCheckBox;
private CheckBox targetSecTokenCheckBox;
@@ -100,16 +94,14 @@ public class AuthenticationConfigurationView extends CustomComponent
certificateAuthCheckbox = SPUIComponentProvider.getCheckBox("", DIST_CHECKBOX_STYLE, null, false, "");
certificateAuthCheckbox.setValue(certificateAuthenticationConfigurationItem.isConfigEnabled());
certificateAuthCheckbox.addValueChangeListener(new AuthenticationTenantConfigurationItemChangeListener(
certificateAuthCheckbox, certificateAuthenticationConfigurationItem));
certificateAuthCheckbox.addValueChangeListener(this);
certificateAuthenticationConfigurationItem.addConfigurationChangeListener(this);
gridLayout.addComponent(certificateAuthCheckbox, 0, 0);
gridLayout.addComponent(certificateAuthenticationConfigurationItem, 1, 0);
targetSecTokenCheckBox = SPUIComponentProvider.getCheckBox("", DIST_CHECKBOX_STYLE, null, false, "");
targetSecTokenCheckBox.setValue(targetSecurityTokenAuthenticationConfigurationItem.isConfigEnabled());
targetSecTokenCheckBox.addValueChangeListener(new AuthenticationTenantConfigurationItemChangeListener(
targetSecTokenCheckBox, targetSecurityTokenAuthenticationConfigurationItem));
targetSecTokenCheckBox.addValueChangeListener(this);
targetSecurityTokenAuthenticationConfigurationItem.addConfigurationChangeListener(this);
gridLayout.addComponent(targetSecTokenCheckBox, 0, 1);
gridLayout.addComponent(targetSecurityTokenAuthenticationConfigurationItem, 1, 1);
@@ -117,8 +109,7 @@ public class AuthenticationConfigurationView extends CustomComponent
gatewaySecTokenCheckBox = SPUIComponentProvider.getCheckBox("", DIST_CHECKBOX_STYLE, null, false, "");
gatewaySecTokenCheckBox.setId("gatewaysecuritycheckbox");
gatewaySecTokenCheckBox.setValue(gatewaySecurityTokenAuthenticationConfigurationItem.isConfigEnabled());
gatewaySecTokenCheckBox.addValueChangeListener(new AuthenticationTenantConfigurationItemChangeListener(
gatewaySecTokenCheckBox, gatewaySecurityTokenAuthenticationConfigurationItem));
gatewaySecTokenCheckBox.addValueChangeListener(this);
gatewaySecurityTokenAuthenticationConfigurationItem.addConfigurationChangeListener(this);
gridLayout.addComponent(gatewaySecTokenCheckBox, 0, 2);
gridLayout.addComponent(gatewaySecurityTokenAuthenticationConfigurationItem, 1, 2);
@@ -126,7 +117,6 @@ public class AuthenticationConfigurationView extends CustomComponent
vLayout.addComponent(gridLayout);
rootPanel.setContent(vLayout);
setCompositionRoot(rootPanel);
}
/*
@@ -160,47 +150,42 @@ public class AuthenticationConfigurationView extends CustomComponent
gatewaySecTokenCheckBox.setValue(gatewaySecurityTokenAuthenticationConfigurationItem.isConfigEnabled());
}
private void notifyConfigurationChanged() {
configurationChangeListeners.forEach(listener -> listener.configurationChanged());
}
@Override
public void addChangeListener(final ConfigurationGroupChangeListener listener) {
configurationChangeListeners.add(listener);
}
@Override
public void configurationHasChanged() {
notifyConfigurationChanged();
}
private final class AuthenticationTenantConfigurationItemChangeListener implements ValueChangeListener {
/*
* (non-Javadoc)
*
* @see com.vaadin.data.Property.ValueChangeListener#valueChange(com.vaadin.
* data.Property. ValueChangeEvent)
*/
@Override
public void valueChange(final ValueChangeEvent event) {
private static final long serialVersionUID = 1L;
private final CheckBox checkBox;
private final TenantConfigurationItem configurationItem;
private AuthenticationTenantConfigurationItemChangeListener(final CheckBox checkBox,
final TenantConfigurationItem configurationItem) {
this.checkBox = checkBox;
this.configurationItem = configurationItem;
}
/*
* (non-Javadoc)
*
* @see
* com.vaadin.data.Property.ValueChangeListener#valueChange(com.vaadin.
* data.Property. ValueChangeEvent)
*/
@Override
public void valueChange(final ValueChangeEvent event) {
if (event.getProperty() instanceof CheckBox) {
notifyConfigurationChanged();
CheckBox checkBox = (CheckBox) event.getProperty();
TenantConfigurationItem configurationItem = null;
if (checkBox == gatewaySecTokenCheckBox) {
configurationItem = gatewaySecurityTokenAuthenticationConfigurationItem;
} else if (checkBox == targetSecTokenCheckBox) {
configurationItem = targetSecurityTokenAuthenticationConfigurationItem;
} else if (checkBox == certificateAuthCheckbox) {
configurationItem = certificateAuthenticationConfigurationItem;
} else {
return;
}
if (checkBox.getValue()) {
configurationItem.configEnable();
} else {
configurationItem.configDisable();
}
}
}
}

View File

@@ -0,0 +1,35 @@
package org.eclipse.hawkbit.ui.tenantconfiguration;
import java.util.ArrayList;
import java.util.List;
import com.vaadin.ui.CustomComponent;
/**
* base class for all configuration views. This class implements the logic for
* the handling of the
*
* @author Fabian Nonnenmacher
*/
public abstract class BaseConfigurationView extends CustomComponent implements ConfigurationGroup {
private static final long serialVersionUID = 1L;
private final List<ConfigurationGroupChangeListener> configurationChangeListeners = new ArrayList<>();
protected void notifyConfigurationChanged() {
configurationChangeListeners.forEach(listener -> listener.configurationChanged());
}
@Override
public void addChangeListener(final ConfigurationGroupChangeListener listener) {
configurationChangeListeners.add(listener);
}
@Override
public boolean isUserInputValid() {
// default return value is true, because often user can only choose from
// different valid options.
return true;
}
}

View File

@@ -10,12 +10,14 @@ package org.eclipse.hawkbit.ui.tenantconfiguration;
import java.io.Serializable;
import com.vaadin.ui.Component;
/**
*
*
*
*/
public interface ConfigurationGroup {
public interface ConfigurationGroup extends Component {
/**
* called to store any configuration changes.
@@ -27,6 +29,13 @@ public interface ConfigurationGroup {
*/
void undo();
/**
* called to verify that the Input done by the user is valid
*
* @return true when the data is valid, false otherwise
*/
boolean isUserInputValid();
/**
* Adds a configuration change listener to notify about configuration
* changes.
@@ -40,8 +49,6 @@ public interface ConfigurationGroup {
/**
* Configuration Change Listener to be notified about configuration changes
* in configuration group.
*
*
*
*/
interface ConfigurationGroupChangeListener extends Serializable {

View File

@@ -8,9 +8,6 @@
*/
package org.eclipse.hawkbit.ui.tenantconfiguration;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
@@ -29,7 +26,6 @@ import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Panel;
@@ -43,7 +39,7 @@ import com.vaadin.ui.VerticalLayout;
*/
@SpringComponent
@ViewScope
public class DefaultDistributionSetTypeLayout extends CustomComponent implements ConfigurationGroup {
public class DefaultDistributionSetTypeLayout extends BaseConfigurationView implements ConfigurationGroup {
private static final long serialVersionUID = 17896542758L;
@@ -66,8 +62,6 @@ public class DefaultDistributionSetTypeLayout extends CustomComponent implements
private Label changeIcon;
private final List<ConfigurationGroupChangeListener> configurationChangeListeners = new ArrayList<>();
/**
* Initialize Default Distribution Set layout.
*/
@@ -163,13 +157,4 @@ public class DefaultDistributionSetTypeLayout extends CustomComponent implements
changeIcon.setVisible(false);
}
}
private void notifyConfigurationChanged() {
configurationChangeListeners.forEach(listener -> listener.configurationChanged());
}
@Override
public void addChangeListener(final ConfigurationGroupChangeListener listener) {
configurationChangeListeners.add(listener);
}
}

View File

@@ -0,0 +1,144 @@
package org.eclipse.hawkbit.ui.tenantconfiguration;
import static org.eclipse.hawkbit.repository.model.helper.PollConfigurationHelper.EXPECTED_POLLING_TIME_FORMAT;
import javax.annotation.PostConstruct;
import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.model.helper.PollConfigurationHelper;
import org.eclipse.hawkbit.ui.tenantconfiguration.polling.DurationField;
import org.eclipse.hawkbit.ui.utils.I18N;
import org.springframework.beans.factory.annotation.Autowired;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Validator;
import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.ViewScope;
import com.vaadin.ui.Field;
import com.vaadin.ui.Label;
import com.vaadin.ui.Panel;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
/**
* View to configure the polling interval and the overdue time.
*
* @author Fabian Nonnenmacher
*
*/
@SpringComponent
@ViewScope
public class PollingConfigurationView extends BaseConfigurationView
implements ConfigurationGroup, Field.ValueChangeListener {
private static final long serialVersionUID = 1L;
@Autowired
private transient SystemManagement systemManagement;
@Autowired
private I18N i18n;
@Autowired
PollConfigurationHelper pollConfigurationHelper;
final private DurationField fieldPollingTime = new DurationField();
final private DurationField fieldPollingOverdueTime = new DurationField();
/**
* Initialize Authentication Configuration layout.
*/
@PostConstruct
public void init() {
Validator correctFormatValidator = new Validator() {
private static final long serialVersionUID = 1L;
@Override
public void validate(Object value) throws InvalidValueException {
if (!(value instanceof String) || !((String) value).matches(EXPECTED_POLLING_TIME_FORMAT)) {
throw new InvalidValueException("Not in HH:MM:SS Format.");
}
}
};
final Panel rootPanel = new Panel();
rootPanel.setSizeFull();
rootPanel.addStyleName("config-panel");
// TODO Better Layout than Vertical Layout - maybe a table layout?
final VerticalLayout vLayout = new VerticalLayout();
vLayout.setMargin(true);
vLayout.setSizeFull();
final Label headerDisSetType = new Label(i18n.get("configuration.polling.title"));
headerDisSetType.addStyleName("config-panel-header");
vLayout.addComponent(headerDisSetType);
final Label labelPollingTime = new Label(i18n.get("configuration.polling.time"));
vLayout.addComponent(labelPollingTime);
vLayout.addComponent(fieldPollingTime);
final Label labelPollingOverdueTime = new Label(i18n.get("configuration.polling.overduetime"));
vLayout.addComponent(labelPollingOverdueTime);
vLayout.addComponent(fieldPollingOverdueTime);
rootPanel.setContent(vLayout);
setCompositionRoot(rootPanel);
}
/*
* (non-Javadoc)
*
* @see
* com.vaadin.data.Property.ValueChangeListener#valueChange(com.vaadin.data.
* Property.ValueChangeEvent)
*
* This method is called when a value of a textField changes. When the value
* is not in the correct format, but has valid data, this method will change
* the value to the correct format
*/
@Override
public void valueChange(ValueChangeEvent event) {
notifyConfigurationChanged();
if (event.getProperty() instanceof TextField) {
TextField textfield = (TextField) event.getProperty();
String value = textfield.getValue();
if (value.matches("[0-9]{1,6}")) {
value = "000000".substring(value.length()) + value;
value = value.substring(0, 2) + ":" + value.substring(2, 4) + ":" + value.substring(4, 6);
}
if (value.matches("([0-5]?[0-9]?(:[0-5][0-9]){1,2})")) {
value = "00:00:00".substring(0, 8 - value.length()) + value;
}
if (value.matches(EXPECTED_POLLING_TIME_FORMAT)) {
textfield.setValue(value);
}
}
}
@Override
public void save() {
// TODO Auto-generated method stub
}
@Override
public void undo() {
}
@Override
public boolean isUserInputValid() {
return fieldPollingTime.isValid() && fieldPollingOverdueTime.isValid();
}
}

View File

@@ -8,6 +8,11 @@
*/
package org.eclipse.hawkbit.ui.tenantconfiguration;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import org.eclipse.hawkbit.ui.HawkbitUI;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
@@ -51,6 +56,9 @@ public class TenantConfigurationDashboardView extends CustomComponent
@Autowired
private AuthenticationConfigurationView authenticationConfigurationView;
@Autowired
private PollingConfigurationView pollingConfigurationView;
@Autowired
private I18N i18n;
@@ -60,6 +68,18 @@ public class TenantConfigurationDashboardView extends CustomComponent
private Button saveConfigurationBtn;
private Button undoConfigurationBtn;
private List<ConfigurationGroup> configurationViews = new ArrayList<ConfigurationGroup>();
/**
* init method adds all Configuration Views to the list of Views.
*/
@PostConstruct
public void init() {
configurationViews.add(defaultDistributionSetTypeLayout);
configurationViews.add(authenticationConfigurationView);
configurationViews.add(pollingConfigurationView);
}
@Override
public void enter(final ViewChangeEvent event) {
@@ -70,17 +90,20 @@ public class TenantConfigurationDashboardView extends CustomComponent
rootLayout.setSizeFull();
rootLayout.setMargin(true);
rootLayout.setSpacing(true);
rootLayout.addComponent(defaultDistributionSetTypeLayout);
rootLayout.addComponent(authenticationConfigurationView);
configurationViews.forEach(view -> {
rootLayout.addComponent(view);
});
final HorizontalLayout buttonContent = saveConfigurationButtonsLayout();
rootLayout.addComponent(buttonContent);
rootLayout.setComponentAlignment(buttonContent, Alignment.BOTTOM_LEFT);
rootPanel.setContent(rootLayout);
setCompositionRoot(rootPanel);
authenticationConfigurationView.addChangeListener(this);
defaultDistributionSetTypeLayout.addChangeListener(this);
configurationViews.forEach(view -> {
view.addChangeListener(this);
});
}
private HorizontalLayout saveConfigurationButtonsLayout() {
@@ -108,19 +131,30 @@ public class TenantConfigurationDashboardView extends CustomComponent
}
private void saveConfiguration() {
defaultDistributionSetTypeLayout.save();
authenticationConfigurationView.save();
// More methods
saveConfigurationBtn.setEnabled(false);
undoConfigurationBtn.setEnabled(false);
uINotification.displaySuccess(i18n.get("notification.configuration.save"));
boolean isUserInputValid = configurationViews.stream().allMatch(confView -> {
return confView.isUserInputValid();
});
if (isUserInputValid) {
configurationViews.forEach(confView -> {
confView.save();
});
// More methods
saveConfigurationBtn.setEnabled(false);
undoConfigurationBtn.setEnabled(false);
uINotification.displaySuccess(i18n.get("notification.configuration.save.successful"));
} else {
uINotification.displayValidationError(i18n.get("notification.configuration.save.notpossible"));
}
}
private void undoConfiguration() {
defaultDistributionSetTypeLayout.undo();
authenticationConfigurationView.undo();
configurationViews.forEach(confView -> {
confView.undo();
});
// More methods
saveConfigurationBtn.setEnabled(false);
undoConfigurationBtn.setEnabled(false);

View File

@@ -0,0 +1,96 @@
package org.eclipse.hawkbit.ui.tenantconfiguration.polling;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import com.vaadin.data.Property;
import com.vaadin.data.util.converter.Converter.ConversionException;
import com.vaadin.shared.ui.datefield.Resolution;
import com.vaadin.ui.DateField;
/**
* This class represents a Field which is optimized to enter a time duration in
* form HH:mm:ss (see {@link #DEFAULT_DURATION_FORMAT}). It uses the vaadin
* DateField as a basic element, but the format is optimized for the duration
* input. For a correct view of the popup it is recommended not to display the
* css-class "v-datefield-calendarpanel-header" and
* "v-datefield-calendarpanel-body" (see systemconfig.scss}
*/
public class DurationField extends DateField {
private static final long serialVersionUID = 1L;
private static String CSS_STYLE_NAME = "durationfield";
private static String DEFAULT_DURATION_FORMAT = "HH:mm:ss";
private static String ADDITIONAL_DURATION_FORMAT = "HHmmss";
private SimpleDateFormat default_format = new SimpleDateFormat(DEFAULT_DURATION_FORMAT);
private SimpleDateFormat additional_format = new SimpleDateFormat(ADDITIONAL_DURATION_FORMAT);
/**
* Creates a DurationField
*/
public DurationField() {
default_format.setLenient(false);
additional_format.setLenient(false);
this.setResolution(Resolution.SECOND);
this.setDateFormat(DEFAULT_DURATION_FORMAT);
this.addStyleName(CSS_STYLE_NAME);
// needed that popup shows a 24h clock
this.setLocale(Locale.GERMANY);
// adds empty change Listener, but is needed that field reacts on
// pressed enter
this.addValueChangeListener(this);
}
@Override
protected Date handleUnparsableDateString(String value) throws ConversionException {
try {
return default_format.parse(value);
} catch (ParseException e1) {
try {
return additional_format.parse(value);
} catch (ParseException e2) {
// if Parsing is not possible ConversionException is thrown
}
}
throw new ConversionException("input is not in HH:MM:SS format.");
}
/**
* Sets the duration value as a String
*
* @param duration
* duration as String in format HH:mm:ss, only values <= 23:59:59
* are excepted
* @throws ParseException
* Exception is thrown, when String parameter is in wrong
* format.
*/
public void setValueAsString(String duration) throws ParseException {
super.setValue(default_format.parse(duration));
}
/**
* Gets the duration value as a formated String
*
* @return duration as String in format HH:mm:ss
*/
public String getValueAsString() {
return default_format.format(super.getValue());
}
@Override
public void valueChange(Property.ValueChangeEvent event) {
// does nothing, but method overrides super methods and is needed that
// parsing works correctly on pressed enter key
}
}

View File

@@ -390,12 +390,16 @@ link.support.name=Support
link.usermanagement.name=User Management
# System Configuration View
notification.configuration.save=Saved changes
notification.configuration.save.successful=Saved changes
notification.configuration.save.notpossible = Saving was not possible, because of invalid user input.
configuration.defaultdistributionset.title=Distribution Set Type
configuration.defaultdistributionset.select.label=Select the default Distribution Set type:
configuration.savebutton.tooltip=Save Configurations
configuration.cancellbutton.tooltip=Cancel Configurations
configuration.authentication.title=Authentication Configuration
configuration.polling.title=Polling Configuration
configuration.polling.time=Polling Time
configuration.polling.overduetime=Polling Overdue Time
#Calendar
calendar.year=year

View File

@@ -380,6 +380,9 @@ configuration.defaultdistributionset.select.label=Select the default Distributio
configuration.savebutton.tooltip=Save Configurations
configuration.cancellbutton.tooltip=Cancel Configurations
configuration.authentication.title=Authentication Configuration
controller.polling.title=Polling Configuration
controller.polling.time=Polling Time
controller.polling.overduetime=Polling Overdue Time
#Calendar
calendar.year=year