From f88e50f8fe9759944d17fbb8d95da1327459576c Mon Sep 17 00:00:00 2001 From: Ilya Obshadko Date: Sat, 16 Apr 2016 09:59:23 +0300 Subject: [PATCH] Prevent modal dismiss in case of form submission errors --- pom.xml | 2 +- .../xtensions/components/ModalDialog.java | 42 +++++++++---------- .../xtensions/mixins/ModalIntegration.java | 17 ++++++++ .../services/ModalIntegrationWorker.java | 18 ++++++++ .../xtensions/services/XtensionsModule.java | 10 ++++- .../modules/t5xtensions/modaldialog.js | 34 ++++++--------- .../xtensions/components/ModalDialog.tml | 4 +- 7 files changed, 81 insertions(+), 46 deletions(-) create mode 100644 src/main/java/com/xfyre/tapestry5/xtensions/mixins/ModalIntegration.java create mode 100644 src/main/java/com/xfyre/tapestry5/xtensions/services/ModalIntegrationWorker.java diff --git a/pom.xml b/pom.xml index ba30730..63eb4c5 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.xfyre tapestry5-xtensions - 0.9-SNAPSHOT + 0.91-SNAPSHOT org.apache.tapestry diff --git a/src/main/java/com/xfyre/tapestry5/xtensions/components/ModalDialog.java b/src/main/java/com/xfyre/tapestry5/xtensions/components/ModalDialog.java index 63c2abd..3247fc9 100644 --- a/src/main/java/com/xfyre/tapestry5/xtensions/components/ModalDialog.java +++ b/src/main/java/com/xfyre/tapestry5/xtensions/components/ModalDialog.java @@ -1,11 +1,11 @@ package com.xfyre.tapestry5.xtensions.components; -import org.apache.commons.lang3.StringUtils; import org.apache.tapestry5.*; import org.apache.tapestry5.annotations.AfterRender; import org.apache.tapestry5.annotations.Events; import org.apache.tapestry5.annotations.Parameter; import org.apache.tapestry5.annotations.Property; +import org.apache.tapestry5.internal.util.Holder; import org.apache.tapestry5.ioc.annotations.Inject; import org.apache.tapestry5.json.JSONObject; import org.apache.tapestry5.services.Request; @@ -35,15 +35,15 @@ public class ModalDialog implements ClientElement { @Property @Parameter(required=false,defaultPrefix=BindingConstants.LITERAL) private String title; - @Property @Parameter(required=false,defaultPrefix=BindingConstants.LITERAL) - private String width; - - @Property @Parameter(required=false,defaultPrefix=BindingConstants.LITERAL) - private String height; - @Property @Parameter(required=false,defaultPrefix=BindingConstants.LITERAL,value="false") private Boolean enableFooter; + /** + * Zone to monitor for updates + */ + @Parameter(required=false,defaultPrefix=BindingConstants.PROP) + private String monitorZone; + /** * Zone to update when user dismisses modal */ @@ -78,30 +78,30 @@ public String getClientId () { @AfterRender private void afterRender () { - JSONObject params = new JSONObject ( + final JSONObject params = new JSONObject ( "id", getClientId (), "hide", hideAfterZoneUpdate ); if ( updateZone != null ) { - Link link = updateContext == null ? - resources.createEventLink ( "modalHidden" ) : - resources.createEventLink ( "modalHidden", updateContext ); - params.put ( "zoneId", updateZone ); + final Link link = updateContext == null ? + resources.createEventLink ( "modalHiddenInternal" ) : + resources.createEventLink ( "modalHiddenInternal", updateContext ); + params.put ( "updateZone", updateZone ); + params.put ( "monitorZone", monitorZone ); params.put ( "updateZoneLink", link.toAbsoluteURI () ); } - if ( StringUtils.isNotBlank ( width ) ) - params.put ( "width", width ); - - if ( StringUtils.isNotBlank ( height ) ) - params.put ( "height", height ); - javaScriptSupport.require ( "t5xtensions/modaldialog" ).with ( params ); } -// public Integer getLeftMargin () { -// return - ( width / 2 ); -// } + Object onModalHiddenInternal ( EventContext ctx ) { + final Holder holder = new Holder<> (); + final boolean eventResult = resources.triggerContextEvent ( EVENT_MODAL_HIDDEN, ctx, result -> { + holder.put ( result ); + return true; + } ); + return eventResult ? holder.get () : null; + } } diff --git a/src/main/java/com/xfyre/tapestry5/xtensions/mixins/ModalIntegration.java b/src/main/java/com/xfyre/tapestry5/xtensions/mixins/ModalIntegration.java new file mode 100644 index 0000000..23a03b3 --- /dev/null +++ b/src/main/java/com/xfyre/tapestry5/xtensions/mixins/ModalIntegration.java @@ -0,0 +1,17 @@ +package com.xfyre.tapestry5.xtensions.mixins; + +import org.apache.tapestry5.MarkupWriter; +import org.apache.tapestry5.annotations.InjectContainer; +import org.apache.tapestry5.annotations.MixinAfter; +import org.apache.tapestry5.corelib.components.Form; + +@MixinAfter +public class ModalIntegration { + @InjectContainer + private Form form; + + void afterRender ( MarkupWriter markupWriter ) { + if ( form.getHasErrors () ) + markupWriter.attributeNS ( null, "data-submission-failed", "true" ); + } +} diff --git a/src/main/java/com/xfyre/tapestry5/xtensions/services/ModalIntegrationWorker.java b/src/main/java/com/xfyre/tapestry5/xtensions/services/ModalIntegrationWorker.java new file mode 100644 index 0000000..1cbd657 --- /dev/null +++ b/src/main/java/com/xfyre/tapestry5/xtensions/services/ModalIntegrationWorker.java @@ -0,0 +1,18 @@ +package com.xfyre.tapestry5.xtensions.services; + +import org.apache.tapestry5.corelib.components.Form; +import org.apache.tapestry5.model.MutableComponentModel; +import org.apache.tapestry5.plastic.PlasticClass; +import org.apache.tapestry5.services.transform.ComponentClassTransformWorker2; +import org.apache.tapestry5.services.transform.TransformationSupport; + +import com.xfyre.tapestry5.xtensions.mixins.ModalIntegration; + +public class ModalIntegrationWorker implements ComponentClassTransformWorker2 { + @Override + public void transform ( PlasticClass plasticClass, TransformationSupport support, MutableComponentModel model ) { + if ( Form.class.getName ().equals ( plasticClass.getClassName () ) ) + model.addMixinClassName ( ModalIntegration.class.getName () ); + } + +} diff --git a/src/main/java/com/xfyre/tapestry5/xtensions/services/XtensionsModule.java b/src/main/java/com/xfyre/tapestry5/xtensions/services/XtensionsModule.java index 411fd78..20bc634 100644 --- a/src/main/java/com/xfyre/tapestry5/xtensions/services/XtensionsModule.java +++ b/src/main/java/com/xfyre/tapestry5/xtensions/services/XtensionsModule.java @@ -4,11 +4,13 @@ import org.apache.tapestry5.ioc.Configuration; import org.apache.tapestry5.ioc.MappedConfiguration; +import org.apache.tapestry5.ioc.OrderedConfiguration; import org.apache.tapestry5.ioc.ScopeConstants; import org.apache.tapestry5.ioc.annotations.*; import org.apache.tapestry5.ioc.services.RegistryShutdownHub; import org.apache.tapestry5.services.ComponentClassResolver; import org.apache.tapestry5.services.LibraryMapping; +import org.apache.tapestry5.services.transform.ComponentClassTransformWorker2; import org.apache.tapestry5.upload.internal.services.MultipartDecoderImpl; import org.apache.tapestry5.upload.services.MultipartDecoder; import org.slf4j.Logger; @@ -18,7 +20,7 @@ public class XtensionsModule { public static void initT5XtensionsModule ( Logger logger ) { logger.info ( "Initializing t5xtensions" ); } - + @Contribute(ComponentClassResolver.class) public static void contributeComponentClassResolver ( Configuration configuration ) { configuration.add ( new LibraryMapping ( "t5xtensions", "com.xfyre.tapestry5.xtensions" ) ); @@ -32,6 +34,7 @@ public static MultipartDecoder buildMultipartDecoder2 ( RegistryShutdownHub shut if ( needToAddShutdownListener.getAndSet ( false ) ) { shutdownHub.addRegistryShutdownListener ( new Runnable () { + @Override @SuppressWarnings("deprecation") public void run () { org.apache.commons.io.FileCleaner.exitWhenFinished (); @@ -49,4 +52,9 @@ public static void contributeServiceOverride ( overrides.add ( MultipartDecoder.class, multipartDecoder ); } + @Contribute(ComponentClassTransformWorker2.class) + public static void provideWorkers ( OrderedConfiguration workers ) { + workers.addInstance ( "ModalIntegrationWorker", ModalIntegrationWorker.class ); + } + } diff --git a/src/main/resources/META-INF/modules/t5xtensions/modaldialog.js b/src/main/resources/META-INF/modules/t5xtensions/modaldialog.js index 6818ce2..0aca2e4 100644 --- a/src/main/resources/META-INF/modules/t5xtensions/modaldialog.js +++ b/src/main/resources/META-INF/modules/t5xtensions/modaldialog.js @@ -1,28 +1,20 @@ define(["jquery","t5/core/events", "t5/core/zone", "bootstrap/modal"], function($, events, zone) { return function(spec) { - var $modal = $('#' + spec.id); - - /* - if (spec.width) { - var realWidth = spec.width > $(window).width() ? $(window).width() : spec.width; - $('#' + spec.id + ' > .modal-dialog').width(realWidth); - } - */ - + var $modal = $('#' + spec.id) + $modal.on('hidden.bs.modal', function(event) { - $modal.remove(); - + $modal.remove() if (spec.updateZoneLink) { - var $zone = $('#' + spec.zoneId); - $zone.trigger(events.zone.refresh, {url: spec.updateZoneLink}); + $('#' + spec.updateZone).trigger(events.zone.refresh, {url: spec.updateZoneLink}) } - }); + }) + + if (spec.monitorZone) + $('#' + spec.monitorZone).on(events.zone.didUpdate, function(event){ + if (spec.hide && !$modal.find('form[data-submission-failed="true"]').length) $modal.modal('hide') + }) - if (spec.hide && spec.zoneId) { - var $zone = $('#' + spec.zoneId); - $zone.on(events.zone.update, function(){ $modal.modal('hide'); }) - } + $modal.modal() + } +}); - $modal.modal(); - }; -}); \ No newline at end of file diff --git a/src/main/resources/com/xfyre/tapestry5/xtensions/components/ModalDialog.tml b/src/main/resources/com/xfyre/tapestry5/xtensions/components/ModalDialog.tml index bd0dc6c..d61c62e 100644 --- a/src/main/resources/com/xfyre/tapestry5/xtensions/components/ModalDialog.tml +++ b/src/main/resources/com/xfyre/tapestry5/xtensions/components/ModalDialog.tml @@ -12,9 +12,9 @@ -