anmolbabu has uploaded a new change for review. Change subject: webadmin : Handle snapshot create multi-tab validation error ......................................................................
webadmin : Handle snapshot create multi-tab validation error Snapshot create popup has 2 tabs : 1. General 2. Schedule Some Editors in both tabs have validations for each input elements in the tabs.However, although the validations validate as expected, the problem was as under: When user in some tab and a validation fails in an input element of the other tab, although tab complained of error, it used to go unnoticed as the tab reporting the error is not the one that is active. This patch, activates the tab that has the errors in the following order: 1. If the general tab has any validation failures, it opens up the general tab. 2. If the schedule tab has any failures, it opens up the schedule tab. In accordance with above 2 steps, if both the tabs have validation failures, immaterial of the number of failures in each tab or any other criteria, general tab opens up(Does nothing if its already open). Along with the above this patch also does the following: 1. Refactored EntityModelDateTimeBox and GwtDateTimeBox in accordance with most other widgets. 2. Corrected implementations of handling widget inValidity states. Change-Id: I88c05aa369758ce174b0dc85f83a253e608d6c0e Bug-Url: https://bugzilla.redhat.com/show_bug.cgi?id=1215887 Bug-Url: https://bugzilla.redhat.com/show_bug.cgi?id=1218606 Signed-off-by: Anmol Babu <[email protected]> --- M frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/editor/ListModelCheckBoxGroupEditor.java M frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/editor/ListModelDaysOfMonthSelectorEditor.java M frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/gluster/GlusterVolumeSnapshotListModel.java M frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/gluster/GlusterVolumeSnapshotModel.java M frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/popup/gluster/GlusterVolumeSnapshotCreatePopupPresenterWidget.java M frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/gluster/GlusterVolumeSnapshotCreatePopupView.java M frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/gluster/GlusterVolumeSnapshotCreatePopupView.ui.xml 7 files changed, 183 insertions(+), 34 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/55/40955/1 diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/editor/ListModelCheckBoxGroupEditor.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/editor/ListModelCheckBoxGroupEditor.java index d40db73..7ddb8b9 100644 --- a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/editor/ListModelCheckBoxGroupEditor.java +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/editor/ListModelCheckBoxGroupEditor.java @@ -7,6 +7,7 @@ import org.ovirt.engine.ui.common.widget.renderer.StringRenderer; import com.google.gwt.dom.client.Style.BorderStyle; +import com.google.gwt.dom.client.Style.Display; import com.google.gwt.editor.client.IsEditor; import com.google.gwt.text.shared.Renderer; @@ -45,6 +46,7 @@ @Override public void markAsInvalid(List<String> validationHints) { super.markAsInvalid(validationHints); + getValidatedWidgetStyle().setDisplay(Display.INLINE_BLOCK); } @Override diff --git a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/editor/ListModelDaysOfMonthSelectorEditor.java b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/editor/ListModelDaysOfMonthSelectorEditor.java index 2a42c42..7469a32 100644 --- a/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/editor/ListModelDaysOfMonthSelectorEditor.java +++ b/frontend/webadmin/modules/gwt-common/src/main/java/org/ovirt/engine/ui/common/widget/editor/ListModelDaysOfMonthSelectorEditor.java @@ -6,6 +6,7 @@ import org.ovirt.engine.ui.common.widget.VisibilityRenderer; import com.google.gwt.dom.client.Style.BorderStyle; +import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.editor.client.IsEditor; /** @@ -46,6 +47,7 @@ @Override public void markAsInvalid(List<String> validationHints) { super.markAsInvalid(validationHints); + getValidatedWidgetStyle().setWidth(75, Unit.PCT); } } diff --git a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/gluster/GlusterVolumeSnapshotListModel.java b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/gluster/GlusterVolumeSnapshotListModel.java index 89eee2a..7c2a24c 100644 --- a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/gluster/GlusterVolumeSnapshotListModel.java +++ b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/gluster/GlusterVolumeSnapshotListModel.java @@ -465,7 +465,7 @@ private void onCreateSnapshot() { final GlusterVolumeSnapshotModel snapshotModel = (GlusterVolumeSnapshotModel) getWindow(); - if (!snapshotModel.validate()) { + if (!snapshotModel.validate(false)) { return; } @@ -699,7 +699,7 @@ public void onEditSnapshotSchedule() { final GlusterVolumeSnapshotModel snapshotModel = (GlusterVolumeSnapshotModel) getWindow(); - if (!snapshotModel.validate()) { + if (!snapshotModel.validate(false)) { return; } diff --git a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/gluster/GlusterVolumeSnapshotModel.java b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/gluster/GlusterVolumeSnapshotModel.java index 367d567..c25d7be 100644 --- a/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/gluster/GlusterVolumeSnapshotModel.java +++ b/frontend/webadmin/modules/uicommonweb/src/main/java/org/ovirt/engine/ui/uicommonweb/models/gluster/GlusterVolumeSnapshotModel.java @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Set; @@ -17,6 +18,10 @@ import org.ovirt.engine.ui.uicommonweb.validation.LengthValidation; import org.ovirt.engine.ui.uicommonweb.validation.NotEmptyValidation; import org.ovirt.engine.ui.uicompat.ConstantsManager; +import org.ovirt.engine.ui.uicompat.Event; +import org.ovirt.engine.ui.uicompat.EventArgs; +import org.ovirt.engine.ui.uicompat.IEventListener; +import org.ovirt.engine.ui.uicompat.PropertyChangedEventArgs; public class GlusterVolumeSnapshotModel extends Model { private EntityModel<String> dataCenter; @@ -35,6 +40,8 @@ private EntityModel<Date> executionTime; private ListModel<List<DayOfWeek>> daysOfWeek; private ListModel<String> daysOfMonth; + //Listeners should be registered only once and not initially itself but only after a first validation occurs after user clicks on ok. + private boolean listenersRegistered = false; public GlusterVolumeSnapshotModel(boolean generalTabVisible, boolean scheduleTabVisible) { init(); @@ -72,6 +79,70 @@ List<List<DayOfWeek>> list = new ArrayList<List<DayOfWeek>>(); list.add(daysList); daysOfWeek.setItems(list, new ArrayList<DayOfWeek>()); + } + + private void initValueChangeListeners() { + IEventListener<EventArgs> onPropertyChangeValidate = new IEventListener<EventArgs>() { + @Override + public void eventRaised(Event<? extends EventArgs> ev, Object sender, EventArgs args) { + validate(true); + } + }; + getSnapshotName().getEntityChangedEvent().addListener(onPropertyChangeValidate); + + getDaysOfTheWeek().getSelectedItemChangedEvent().addListener(onPropertyChangeValidate); + + getDaysOfMonth().getSelectedItemChangedEvent().addListener(onPropertyChangeValidate); + + getEndDate().getEntityChangedEvent().addListener(onPropertyChangeValidate); + } + + private void validateSnapshotName() { + getSnapshotName().validateEntity(new IValidation[] { new NotEmptyValidation(), new LengthValidation(128), + new AsciiNameValidation() }); + } + + private void validateEndDate() { + if (getRecurrence().getSelectedItem() != GlusterVolumeSnapshotScheduleRecurrence.UNKNOWN + && getEndByOptions().getSelectedItem() == EndDateOptions.HasEndDate + && getEndDate().getEntity().compareTo(getStartAt().getEntity()) <= 0) { + String message = ConstantsManager.getInstance().getConstants().endDateBeforeStartDate(); + getEndDate().setInvalidityReasons(Collections.singletonList(message)); + getEndDate().setIsValid(false); + } else { + getEndDate().setInvalidityReasons(new ArrayList<String>()); + getEndDate().setIsValid(true); + } + } + + private void validateDaysOfMonth() { + if (getRecurrence().getSelectedItem() == GlusterVolumeSnapshotScheduleRecurrence.MONTHLY) { + if (getDaysOfMonth().getSelectedItem() == null || getDaysOfMonth().getSelectedItem().equals("")) {//$NON-NLS-1$ + String message = ConstantsManager.getInstance().getConstants().noMonthDaysSelectedMessage(); + getDaysOfMonth().setInvalidityReasons(Collections.singletonList(message)); + getDaysOfMonth().setIsValid(false); + } else if (getDaysOfMonth().getSelectedItem().contains(",L") || getDaysOfMonth().getSelectedItem().contains("L,")) {//$NON-NLS-1$//$NON-NLS-2$ + String message = ConstantsManager.getInstance().getConstants().lastDayMonthCanBeSelectedAlone(); + getDaysOfMonth().setInvalidityReasons(Collections.singletonList(message)); + getDaysOfMonth().setIsValid(false); + } else { + getDaysOfMonth().setInvalidityReasons(new ArrayList<String>()); + getDaysOfMonth().setIsValid(true); + } + } + } + + private void validateDaysOfWeek() { + if (getRecurrence().getSelectedItem() == GlusterVolumeSnapshotScheduleRecurrence.WEEKLY) { + if (getDaysOfTheWeek().getSelectedItem() == null || getDaysOfTheWeek().getSelectedItem().isEmpty()) { + String message = ConstantsManager.getInstance().getConstants().noWeekDaysSelectedMessage(); + getDaysOfTheWeek().setInvalidityReasons(Collections.singletonList(message)); + getDaysOfTheWeek().setIsValid(false); + } else { + getDaysOfTheWeek().setInvalidityReasons(new ArrayList<String>()); + getDaysOfTheWeek().setIsValid(true); + } + } } private void initIntervals() { @@ -217,38 +288,31 @@ this.daysOfMonth = daysOfMonth; } - public boolean validate() { - boolean validWeekDays = true; - boolean validMonthDays = true; - boolean validEndDate = true; - getSnapshotName().validateEntity(new IValidation[] { new NotEmptyValidation(), new LengthValidation(128), - new AsciiNameValidation() }); + public boolean validate(boolean inplaceValidate) { + String propName; - if (getRecurrence().getSelectedItem() == GlusterVolumeSnapshotScheduleRecurrence.WEEKLY - && (getDaysOfTheWeek().getSelectedItem() == null || getDaysOfTheWeek().getSelectedItem().isEmpty())) { - setMessage(ConstantsManager.getInstance().getConstants().noWeekDaysSelectedMessage()); - validWeekDays = false; + validateSnapshotName(); + + validateDaysOfWeek(); + + validateDaysOfMonth(); + + validateEndDate(); + + if (!listenersRegistered) { + initValueChangeListeners(); + listenersRegistered = true; } - if (getRecurrence().getSelectedItem() == GlusterVolumeSnapshotScheduleRecurrence.MONTHLY) { - if (getDaysOfMonth().getSelectedItem() == null || getDaysOfMonth().getSelectedItem().equals("")) {//$NON-NLS-1$ - setMessage(ConstantsManager.getInstance().getConstants().noMonthDaysSelectedMessage()); - validMonthDays = false; - } else if (getDaysOfMonth().getSelectedItem().contains(",L") || getDaysOfMonth().getSelectedItem().contains("L,")) {//$NON-NLS-1$//$NON-NLS-2$ - setMessage(ConstantsManager.getInstance().getConstants().lastDayMonthCanBeSelectedAlone()); - validMonthDays = false; - } + if(inplaceValidate) { + propName = "modelPropertiesChanged";//$NON-NLS-1$ + } else { + propName = "validateAndSwitchAppropriateTab";//$NON-NLS-1$ } - - if (getRecurrence().getSelectedItem() != GlusterVolumeSnapshotScheduleRecurrence.UNKNOWN - && getEndByOptions().getSelectedItem() == EndDateOptions.HasEndDate - && getEndDate().getEntity().compareTo(getStartAt().getEntity()) <= 0) { - setMessage(ConstantsManager.getInstance().getConstants().endDateBeforeStartDate()); - validEndDate = false; - } + onPropertyChanged(new PropertyChangedEventArgs(propName)); return getSnapshotName().getIsValid() && getDaysOfTheWeek().getIsValid() && getDaysOfMonth().getIsValid() - && validWeekDays && validMonthDays && validEndDate; + && getDaysOfTheWeek().getIsValid() && getDaysOfMonth().getIsValid() && getEndDate().getIsValid(); } public enum EndDateOptions { diff --git a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/popup/gluster/GlusterVolumeSnapshotCreatePopupPresenterWidget.java b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/popup/gluster/GlusterVolumeSnapshotCreatePopupPresenterWidget.java index 5385e55..9ee099a 100644 --- a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/popup/gluster/GlusterVolumeSnapshotCreatePopupPresenterWidget.java +++ b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/presenter/popup/gluster/GlusterVolumeSnapshotCreatePopupPresenterWidget.java @@ -7,6 +7,7 @@ import org.ovirt.engine.ui.uicompat.Event; import org.ovirt.engine.ui.uicompat.EventArgs; import org.ovirt.engine.ui.uicompat.IEventListener; +import org.ovirt.engine.ui.uicompat.PropertyChangedEventArgs; import com.google.gwt.event.shared.EventBus; import com.google.inject.Inject; @@ -49,6 +50,18 @@ getView().setEndDateVisibility(model); } }); + + model.getPropertyChangedEvent().addListener(new IEventListener<PropertyChangedEventArgs>() { + @Override + public void eventRaised(Event<? extends PropertyChangedEventArgs> ev, Object sender, PropertyChangedEventArgs args) { + if(args.propertyName.equalsIgnoreCase("validateAndSwitchAppropriateTab")) {//$NON-NLS-1$ + getView().handleValidationErrors(model); + getView().switchTabBasedOnEditorInvalidity(); + } else if(args.propertyName.equalsIgnoreCase("modelPropertiesChanged")) {//$NON-NLS-1$ + getView().handleValidationErrors(model); + } + } + }); } public interface ViewDef extends AbstractModelBoundPopupPresenterWidget.ViewDef<GlusterVolumeSnapshotModel> { @@ -57,5 +70,9 @@ public void setEndDateVisibility(GlusterVolumeSnapshotModel object); public void setCriticalIntervalLabelVisibility(GlusterVolumeSnapshotModel object, int value); + + public void handleValidationErrors(GlusterVolumeSnapshotModel object); + + public void switchTabBasedOnEditorInvalidity(); } } diff --git a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/gluster/GlusterVolumeSnapshotCreatePopupView.java b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/gluster/GlusterVolumeSnapshotCreatePopupView.java index 8d3febb..d45b0c6 100644 --- a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/gluster/GlusterVolumeSnapshotCreatePopupView.java +++ b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/gluster/GlusterVolumeSnapshotCreatePopupView.java @@ -1,5 +1,8 @@ package org.ovirt.engine.ui.webadmin.section.main.view.popup.gluster; +import java.util.Collections; +import java.util.List; + import org.ovirt.engine.core.common.businessentities.gluster.GlusterVolumeSnapshotScheduleRecurrence; import org.ovirt.engine.core.compat.DayOfWeek; import org.ovirt.engine.ui.common.idhandler.ElementIdHandler; @@ -8,6 +11,7 @@ import org.ovirt.engine.ui.common.widget.dialog.InfoIcon; import org.ovirt.engine.ui.common.widget.dialog.SimpleDialogPanel; import org.ovirt.engine.ui.common.widget.dialog.tab.DialogTab; +import org.ovirt.engine.ui.common.widget.dialog.tab.DialogTabPanel; import org.ovirt.engine.ui.common.widget.editor.EntityModelDateTimeBoxEditor; import org.ovirt.engine.ui.common.widget.editor.ListModelCheckBoxGroupEditor; import org.ovirt.engine.ui.common.widget.editor.ListModelDaysOfMonthSelectorEditor; @@ -52,6 +56,9 @@ } @UiField + DialogTabPanel tabContainer; + + @UiField WidgetStyle style; @UiField @@ -79,6 +86,11 @@ @Path(value = "description.entity") @WithElementId StringEntityModelTextBoxEditor snapshotDescriptionEditor; + + @UiField + @Ignore + @WithElementId + Label generalTabErrorMsgLabel; @UiField DialogTab scheduleTab; @@ -136,7 +148,7 @@ @UiField @Ignore @WithElementId - Label errorMsgLabel; + Label scheduleTabErrorMessageLabel; private final ApplicationConstants constants; @@ -247,10 +259,60 @@ } } + public void setMessage(String msg, Label errorLabel) { + errorLabel.setText(msg); + errorLabel.setVisible(!msg.isEmpty()); + } + @Override - public void setMessage(String msg) { - super.setMessage(msg); - errorMsgLabel.setText(msg); + public void handleValidationErrors(GlusterVolumeSnapshotModel object) { + String generalTabErrors = collectGeneralTabErrors(object); + setMessage(generalTabErrors, generalTabErrorMsgLabel); + + String scheduleTabErrors = collectScheduleTabErrors(object); + setMessage(scheduleTabErrors, scheduleTabErrorMessageLabel); + } + + private String collectScheduleTabErrors(GlusterVolumeSnapshotModel object) { + StringBuilder scheduleTabErrors = new StringBuilder(); + if (!daysOfWeekEditor.isValid()) { + appendErrors(object.getDaysOfTheWeek().getInvalidityReasons(), scheduleTabErrors); + } + if (!daysOfMonthEditor.isValid()) { + appendErrors(object.getDaysOfMonth().getInvalidityReasons(), scheduleTabErrors); + } + if (!endDate.isValid()) { + appendErrors(object.getEndDate().getInvalidityReasons(), scheduleTabErrors); + } + return scheduleTabErrors.toString(); + } + + private String collectGeneralTabErrors(GlusterVolumeSnapshotModel object) { + StringBuilder generalTabErrorBuilder = new StringBuilder(); + if (!snapshotNameEditor.isValid()){ + appendErrors(Collections.singletonList(constants.volumeSnapshotNamePrefixLabel()), generalTabErrorBuilder); + appendErrors(object.getSnapshotName().getInvalidityReasons(), generalTabErrorBuilder); + } + return generalTabErrorBuilder.toString(); + } + + @Override + public void switchTabBasedOnEditorInvalidity() { + if (!clusterNameEditor.isValid() || !volumeNameEditor.isValid() || !snapshotNameEditor.isValid() + || !snapshotDescriptionEditor.isValid()) { + tabContainer.switchTab(generalTab); + } else if (!recurrenceEditor.isValid() || !intervalEditor.isValid() || !timeZoneEditor.isValid() + || !startAtEditor.isValid() || !executionTimeEditor.isValid() || !daysOfWeekEditor.isValid() + || !daysOfMonthEditor.isValid() || !endByOptionsEditor.isValid() || !endDate.isValid()) { + tabContainer.switchTab(scheduleTab); + } + } + + private void appendErrors(List<String> errors, StringBuilder sBuilder) { + for(String currentError : errors) { + sBuilder.append(currentError); + sBuilder.append("\n");//$NON-NLS-1$ + } } private void updateTabVisibilities(GlusterVolumeSnapshotModel object) { diff --git a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/gluster/GlusterVolumeSnapshotCreatePopupView.ui.xml b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/gluster/GlusterVolumeSnapshotCreatePopupView.ui.xml index bd18806..a7fbda8 100644 --- a/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/gluster/GlusterVolumeSnapshotCreatePopupView.ui.xml +++ b/frontend/webadmin/modules/webadmin/src/main/java/org/ovirt/engine/ui/webadmin/section/main/view/popup/gluster/GlusterVolumeSnapshotCreatePopupView.ui.xml @@ -57,7 +57,7 @@ <d:SimpleDialogPanel width="700px" height="500px"> <d:content> - <t:DialogTabPanel height="100%" width="100%"> + <t:DialogTabPanel ui:field="tabContainer" height="100%" width="100%"> <t:tab> <t:DialogTab ui:field="generalTab"> <t:content> @@ -74,6 +74,8 @@ </g:HorizontalPanel> <ge:StringEntityModelTextBoxEditor ui:field="snapshotDescriptionEditor" /> + <g:Label ui:field="generalTabErrorMsgLabel" + addStyleNames="{style.errMsgLabel}" /> </g:FlowPanel> </t:content> </t:DialogTab> @@ -99,7 +101,7 @@ ui:field="endDate" addStyleNames="{style.endDate}"/> <g:Label ui:field="criticalIntervalLabel" addStyleNames="{style.criticalIntervalLabel}" /> - <g:Label ui:field="errorMsgLabel" + <g:Label ui:field="scheduleTabErrorMessageLabel" addStyleNames="{style.errMsgLabel}" /> </g:FlowPanel> </t:content> -- To view, visit https://gerrit.ovirt.org/40955 To unsubscribe, visit https://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I88c05aa369758ce174b0dc85f83a253e608d6c0e Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: ovirt-engine-3.5-gluster Gerrit-Owner: anmolbabu <[email protected]> _______________________________________________ Engine-patches mailing list [email protected] http://lists.ovirt.org/mailman/listinfo/engine-patches
