This is an automated email from the ASF dual-hosted git repository.

mleila pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git


The following commit(s) were added to refs/heads/trunk by this push:
     new d462fc88b6 Improved: Automatic callback element propagation inside a 
modal tunnel process (OFBIZ-12664)
d462fc88b6 is described below

commit d462fc88b6088baa25d02b09829df85fe6a176ca
Author: MLeila <mle...@apache.org>
AuthorDate: Mon Oct 2 09:04:06 2023 +0200

    Improved: Automatic callback element propagation inside a modal tunnel
    process (OFBIZ-12664)
---
 framework/widget/dtd/widget-form.xsd               |  8 +++++
 .../java/org/apache/ofbiz/widget/WidgetWorker.java | 33 +++++++++++++------
 .../ofbiz/widget/model/CommonWidgetModels.java     | 37 ++++++++++++----------
 .../org/apache/ofbiz/widget/model/ModelForm.java   |  8 ++---
 .../apache/ofbiz/widget/model/ModelFormField.java  | 12 +++++++
 .../apache/ofbiz/widget/renderer/FormRenderer.java | 30 +++++++++++++++---
 .../widget/renderer/macro/MacroFormRenderer.java   |  8 +++--
 .../template/macro/HtmlFormMacroLibrary.ftl        | 13 ++++----
 .../webapp/common-theme/js/util/OfbizUtil.js       |  6 ++--
 9 files changed, 108 insertions(+), 47 deletions(-)

diff --git a/framework/widget/dtd/widget-form.xsd 
b/framework/widget/dtd/widget-form.xsd
index bb5c1d54c5..f7e3fa3997 100644
--- a/framework/widget/dtd/widget-form.xsd
+++ b/framework/widget/dtd/widget-form.xsd
@@ -1448,6 +1448,14 @@ under the License.
                     <xs:documentation>The message displayed in confirmation 
box</xs:documentation>
                 </xs:annotation>
             </xs:attribute>
+            <xs:attribute name="propagate-callback" type="xs:boolean" 
default="false">
+                <xs:annotation>
+                    <xs:documentation>If you are on an edition process with 
different steps and you want to wait the end of the complete action before 
using the callback,
+                        use propagate-callback="true". The submit will 
understand that you want to continue your process and will not close the modal 
to refresh the screen.
+                        The callback action will be kept within the different 
steps
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:attribute>
         </xs:complexType>
     </xs:element>
     <xs:element name="text" substitutionGroup="AllFields">
diff --git 
a/framework/widget/src/main/java/org/apache/ofbiz/widget/WidgetWorker.java 
b/framework/widget/src/main/java/org/apache/ofbiz/widget/WidgetWorker.java
index 71bd8278e5..d13529a272 100644
--- a/framework/widget/src/main/java/org/apache/ofbiz/widget/WidgetWorker.java
+++ b/framework/widget/src/main/java/org/apache/ofbiz/widget/WidgetWorker.java
@@ -35,6 +35,7 @@ import org.apache.ofbiz.service.LocalDispatcher;
 import org.apache.ofbiz.webapp.control.ConfigXMLReader;
 import org.apache.ofbiz.webapp.control.RequestHandler;
 import org.apache.ofbiz.webapp.taglib.ContentUrlTag;
+import org.apache.ofbiz.widget.model.CommonWidgetModels;
 import org.apache.ofbiz.widget.model.ModelForm;
 import org.apache.ofbiz.widget.model.ModelFormField;
 import org.apache.ofbiz.widget.renderer.ScreenRenderer;
@@ -100,17 +101,18 @@ public final class WidgetWorker {
             throw new RuntimeException(msg, e);
         }
 
-        final String tokenValue = CsrfUtil.generateTokenForNonAjax(request, 
target);
-        if (isNotEmpty(tokenValue)) {
-            additionalParameters.put(CsrfUtil.getTokenNameNonAjax(), 
tokenValue);
-        }
-
-        if (UtilValidate.isNotEmpty(parameterMap)) {
-            parameterMap.forEach(uriBuilder::addParameter);
-        }
+        if (!"plain".equals(targetType)) {
+            final String tokenValue = 
CsrfUtil.generateTokenForNonAjax(request, target);
+            if (isNotEmpty(tokenValue)) {
+                additionalParameters.put(CsrfUtil.getTokenNameNonAjax(), 
tokenValue);
+            }
 
-        additionalParameters.forEach(uriBuilder::addParameter);
+            if (UtilValidate.isNotEmpty(parameterMap)) {
+                parameterMap.forEach(uriBuilder::addParameter);
+            }
 
+            additionalParameters.forEach(uriBuilder::addParameter);
+        }
         try {
             return uriBuilder.build();
         } catch (URISyntaxException e) {
@@ -285,6 +287,19 @@ public final class WidgetWorker {
         return (ScreenRenderer.ScreenStack) context.get("screenStack");
     }
 
+    /**
+     * Returns the jwt callback id if present on the context.
+     * @param context
+     * @return
+     */
+    public static String getJwtCallback(Map<String, Object> context) {
+        String jwtCallback = (String) 
context.get(CommonWidgetModels.JWT_CALLBACK);
+        if (UtilValidate.isEmpty(jwtCallback) && 
context.containsKey("parameters")) {
+            jwtCallback = (String) ((Map) 
context.get("parameters")).get(CommonWidgetModels.JWT_CALLBACK);
+        }
+        return jwtCallback;
+    }
+
     public static int getPaginatorNumber(Map<String, Object> context) {
         int paginatorNumber = 0;
         if (context != null) {
diff --git 
a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/CommonWidgetModels.java
 
b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/CommonWidgetModels.java
index 9992ec14cb..83143ba170 100644
--- 
a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/CommonWidgetModels.java
+++ 
b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/CommonWidgetModels.java
@@ -48,6 +48,7 @@ import org.apache.ofbiz.service.GenericServiceException;
 import org.apache.ofbiz.service.LocalDispatcher;
 import org.apache.ofbiz.service.ModelParam;
 import org.apache.ofbiz.service.ModelService;
+import org.apache.ofbiz.widget.WidgetWorker;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 
@@ -574,26 +575,10 @@ public final class CommonWidgetModels {
             if (autoEntityParameters != null) {
                 
fullParameterMap.putAll(autoEntityParameters.getParametersMap(context, 
defaultEntityName));
             }
-            propagateCallbackInParameterMap(context, propagateMyCallback, 
fullParameterMap);
+            
fullParameterMap.putAll(UtilGenerics.cast(propagateCallbackInParameterMap(context,
 propagateMyCallback, getCallback())));
             return fullParameterMap;
         }
 
-        // If a call back is present on link or present on context, adding it 
to the parameters list
-        private void propagateCallbackInParameterMap(Map<String, Object> 
context, boolean propagateMyCallback, Map<String, String> fullParameterMap) {
-            if (getCallback() != null && propagateMyCallback) {
-                fullParameterMap.put(JWT_CALLBACK, 
getCallback().toJwtToken(context));
-            } else if (context.containsKey(JWT_CALLBACK)) {
-                fullParameterMap.put(JWT_CALLBACK, (String) 
context.get(JWT_CALLBACK));
-            } else {
-                if (context.containsKey("parameters")) {
-                    Map<String, Object> parameters = 
UtilGenerics.cast(context.get("parameters"));
-                    if (parameters.containsKey(JWT_CALLBACK)) {
-                        fullParameterMap.put(JWT_CALLBACK, (String) 
parameters.get(JWT_CALLBACK));
-                    }
-                }
-            }
-        }
-
         public Map<String, String> getParameterMap(Map<String, Object> 
context) {
             return getParameterMap(context, null, null, true);
         }
@@ -796,4 +781,22 @@ public final class CommonWidgetModels {
             }
         }
     }
+
+    // If a call back is present on link or present on context, adding it to 
the parameters list
+    public static Map<String, Object> 
propagateCallbackInParameterMap(Map<String, Object> context, boolean 
propagateMyCallback,
+            ModelForm.UpdateArea callBack) {
+        Map<String, Object> fullParameterMap = new HashMap<String, Object>();
+
+        // If the parameter contains the map, the call back will be 
automatically manage by the form
+        if (fullParameterMap.containsKey("_FORM_NAME_")) return 
fullParameterMap;
+
+        String currentJwtCallback = WidgetWorker.getJwtCallback(context);
+        if (callBack != null && propagateMyCallback) {
+            fullParameterMap.put(JWT_CALLBACK, callBack.toJwtToken(context));
+        } else if (UtilValidate.isNotEmpty(currentJwtCallback)) {
+            fullParameterMap.put(JWT_CALLBACK, currentJwtCallback);
+        }
+        return fullParameterMap;
+    }
+
 }
diff --git 
a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelForm.java 
b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelForm.java
index c214862cd7..37a9add126 100644
--- 
a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelForm.java
+++ 
b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelForm.java
@@ -2511,12 +2511,8 @@ public abstract class ModelForm extends ModelWidget {
         public static ModelForm.UpdateArea fromJwtToken(Map<String, Object> 
context) {
             Delegator delegator = (Delegator) context.get("delegator");
 
-            String jwtToken = (String) 
context.get(CommonWidgetModels.JWT_CALLBACK);
-            if (jwtToken == null && context.containsKey("parameters")) {
-                Map<String, Object> parameters = 
UtilGenerics.cast(context.get("parameters"));
-                jwtToken = (String) 
parameters.get(CommonWidgetModels.JWT_CALLBACK);
-            }
-            if (jwtToken == null) return null;
+            String jwtToken = WidgetWorker.getJwtCallback(context);
+            if (UtilValidate.isEmpty(jwtToken)) return null;
 
             Map<String, Object> claims = JWTManager.validateToken(jwtToken, 
JWTManager.getJWTKey(delegator));
             if (claims.containsKey(ModelService.ERROR_MESSAGE)) {
diff --git 
a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelFormField.java
 
b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelFormField.java
index 25c7901639..aef60ce782 100644
--- 
a/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelFormField.java
+++ 
b/framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelFormField.java
@@ -4913,6 +4913,7 @@ public final class ModelFormField {
     public static class SubmitField extends FieldInfo {
         private final FlexibleStringExpander backgroundSubmitRefreshTargetExdr;
         private final String buttonType;
+        private final boolean propagateCallback;
         private final FlexibleStringExpander confirmationMsgExdr;
         private final FlexibleStringExpander imageLocation;
         private final boolean requestConfirmation;
@@ -4925,6 +4926,7 @@ public final class ModelFormField {
             this.confirmationMsgExdr = 
FlexibleStringExpander.getInstance(element.getAttribute("confirmation-message"));
             this.imageLocation = 
FlexibleStringExpander.getInstance(element.getAttribute("image-location"));
             this.requestConfirmation = 
"true".equals(element.getAttribute("request-confirmation"));
+            this.propagateCallback = 
"true".equals(element.getAttribute("propagate-callback"));
         }
 
         public SubmitField(int fieldInfo, ModelFormField modelFormField) {
@@ -4934,6 +4936,7 @@ public final class ModelFormField {
             this.confirmationMsgExdr = FlexibleStringExpander.getInstance("");
             this.imageLocation = FlexibleStringExpander.getInstance("");
             this.requestConfirmation = false;
+            this.propagateCallback = false;
         }
 
         public SubmitField(ModelFormField modelFormField) {
@@ -4947,6 +4950,7 @@ public final class ModelFormField {
             this.backgroundSubmitRefreshTargetExdr = 
original.backgroundSubmitRefreshTargetExdr;
             this.requestConfirmation = original.requestConfirmation;
             this.confirmationMsgExdr = original.confirmationMsgExdr;
+            this.propagateCallback = original.propagateCallback;
         }
 
         @Override
@@ -5043,6 +5047,14 @@ public final class ModelFormField {
             return this.requestConfirmation;
         }
 
+        /**
+         * Gets keep callback.
+         * @return
+         */
+        public boolean getPropagateCallback() {
+            return this.propagateCallback;
+        }
+
         @Override
         public void renderFieldString(Appendable writer, Map<String, Object> 
context, FormStringRenderer formStringRenderer)
                 throws IOException {
diff --git 
a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/FormRenderer.java
 
b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/FormRenderer.java
index eef4a91a56..ba4391a0c1 100644
--- 
a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/FormRenderer.java
+++ 
b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/FormRenderer.java
@@ -18,6 +18,7 @@
  
*******************************************************************************/
 package org.apache.ofbiz.widget.renderer;
 
+import org.apache.ofbiz.widget.model.CommonWidgetModels;
 import static org.apache.ofbiz.widget.model.ModelFormField.usedFields;
 
 import java.io.IOException;
@@ -56,6 +57,7 @@ import org.apache.ofbiz.widget.model.ModelForm;
 import org.apache.ofbiz.widget.model.ModelForm.FieldGroup;
 import org.apache.ofbiz.widget.model.ModelForm.FieldGroupBase;
 import org.apache.ofbiz.widget.model.ModelFormField;
+import org.apache.ofbiz.widget.model.ModelFormFieldBuilder;
 import org.apache.ofbiz.widget.model.ModelGrid;
 import org.apache.ofbiz.widget.model.ModelWidget;
 import org.apache.ofbiz.widget.renderer.html.HtmlWidgetRenderer;
@@ -174,12 +176,30 @@ public class FormRenderer {
     }
 
     private static List<ModelFormField> getHiddenIgnoredFields(Map<String, 
Object> context, Set<String> alreadyRendered,
-            List<ModelFormField> fields, int position) {
-        return fields.stream()
+            List<ModelFormField> fields, ModelForm modelForm, int position) {
+        List<ModelFormField> hiddenIgnoredFields = fields.stream()
                 // with position == -1 then gets all the hidden fields
                 .filter(modelFormField -> position == -1 || 
modelFormField.getPosition() == position)
                 .filter(filteringIgnoredFields(context, alreadyRendered))
                 .collect(Collectors.toList());
+        ModelFormField jwtCallbackField = addJwtTokenHiddenField(context, 
modelForm);
+        if (jwtCallbackField != null) {
+            hiddenIgnoredFields.add(jwtCallbackField);
+        }
+        return hiddenIgnoredFields;
+    }
+
+    private static ModelFormField addJwtTokenHiddenField(Map<String, Object> 
context, ModelForm modelForm) {
+        if (UtilValidate.isNotEmpty(WidgetWorker.getJwtCallback(context))) {
+            ModelFormFieldBuilder builder = new ModelFormFieldBuilder();
+            builder.setModelForm(modelForm);
+            builder.setName(CommonWidgetModels.JWT_CALLBACK);
+            builder.setFieldName(CommonWidgetModels.JWT_CALLBACK);
+            ModelFormField.HiddenField hiddenField = new 
ModelFormField.HiddenField(FieldInfo.SOURCE_EXPLICIT, null);
+            builder.setFieldInfo(hiddenField);
+            return ModelFormField.from(builder);
+        }
+        return null;
     }
 
     private List<FieldGroupBase> getInbetweenList(FieldGroup startFieldGroup, 
FieldGroup endFieldGroup) {
@@ -869,8 +889,8 @@ public class FormRenderer {
                         innerDisplayHyperlinkFieldsEnd.add(modelFormField);
                         currentPosition = modelFormField.getPosition();
                     }
-                    List<ModelFormField> hiddenIgnoredFieldList = 
getHiddenIgnoredFields(localContext, null, tempFieldList,
-                            currentPosition);
+                    List<ModelFormField> hiddenIgnoredFieldList = 
getHiddenIgnoredFields(localContext, null,
+                            tempFieldList, modelForm, currentPosition);
 
                     // Rendering:
                     // the fields in the three lists created in the 
preprocessing phase
@@ -984,7 +1004,7 @@ public class FormRenderer {
         }
 
         // render all hidden & ignored fields
-        List<ModelFormField> hiddenIgnoredFieldList = 
getHiddenIgnoredFields(context, alreadyRendered, tempFieldList, -1);
+        List<ModelFormField> hiddenIgnoredFieldList = 
getHiddenIgnoredFields(context, alreadyRendered, tempFieldList, modelForm, -1);
         renderHiddenIgnoredFields(writer, context, formStringRenderer, 
hiddenIgnoredFieldList);
 
         // render formatting wrapper open
diff --git 
a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/MacroFormRenderer.java
 
b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/MacroFormRenderer.java
index 06042ad5e8..16fc404bf2 100644
--- 
a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/MacroFormRenderer.java
+++ 
b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/MacroFormRenderer.java
@@ -703,7 +703,9 @@ public final class MacroFormRenderer implements 
FormStringRenderer {
         boolean ajaxEnabled = UtilValidate.isNotEmpty(updateAreas) && 
this.javaScriptEnabled;
         String ajaxUrl = "";
         if (ajaxEnabled) {
-            ajaxUrl = 
MacroCommonRenderer.createAjaxParamsFromUpdateAreas(updateAreas, null, 
modelForm, "", context);
+            Map<String, Object> extraParams = 
CommonWidgetModels.propagateCallbackInParameterMap(context,
+                    submitField.getPropagateCallback(), jwtCallback);
+            ajaxUrl = 
MacroCommonRenderer.createAjaxParamsFromUpdateAreas(updateAreas, extraParams, 
modelForm, "", context);
         }
         String tabindex = modelFormField.getTabindex();
         boolean disabled = modelFormField.getDisabled(context);
@@ -747,7 +749,9 @@ public final class MacroFormRenderer implements 
FormStringRenderer {
         sr.append(tabindex);
         sr.append("\" disabled=");
         sr.append(Boolean.toString(disabled));
-        sr.append(" />");
+        sr.append(" closeOnSubmit=\"");
+        sr.append(String.valueOf(!submitField.getPropagateCallback()));
+        sr.append("\" />");
         executeMacro(writer, sr.toString());
         this.appendTooltip(writer, context, modelFormField);
     }
diff --git a/themes/common-theme/template/macro/HtmlFormMacroLibrary.ftl 
b/themes/common-theme/template/macro/HtmlFormMacroLibrary.ftl
index a0d4bde2c5..2d0fbe3547 100644
--- a/themes/common-theme/template/macro/HtmlFormMacroLibrary.ftl
+++ b/themes/common-theme/template/macro/HtmlFormMacroLibrary.ftl
@@ -228,7 +228,7 @@ under the License.
   </#list>
 </#macro>
 
-<#macro renderSubmitField buttonType className alert formName action imgSrc 
ajaxUrl id title="" name="" event="" confirmation="" containerId="" tabindex="" 
disabled=false>
+<#macro renderSubmitField buttonType className alert formName action imgSrc 
ajaxUrl id title="" name="" event="" confirmation="" containerId="" tabindex="" 
disabled=false closeOnSubmit="true">
   <#if buttonType=="text-link">
     <a <@renderClass className alert /> 
href="javascript:document.${formName}.submit()" <#if 
confirmation?has_content>onclick="return 
confirm('${confirmation?js_string}');"</#if>><#if 
title?has_content>${title}</#if> </a>
   <#elseif buttonType=="image">
@@ -253,14 +253,15 @@ under the License.
                 e.preventDefault();
                 e.stopPropagation();
                 if ($(this).valid()) {
-                    <#if confirmation?has_content>if 
(confirm('${confirmation?js_string}')) 
</#if>ajaxSubmitFormUpdateAreas('${formName}', '${ajaxUrl}');
+                    <#if confirmation?has_content>if 
(confirm('${confirmation?js_string}')) 
</#if>ajaxSubmitFormUpdateAreas('${formName}', '${ajaxUrl}', 
'${closeOnSubmit}');
                 }
             })
             .keypress(function(e) {
-              if (e.which === 13 && ! $(e.target).is('textarea')) {
-                e.preventDefault();
-                $("#${id!}").click();
-              }});
+                if (e.which === 13 && ! $(e.target).is('textarea')) {
+                    e.preventDefault();
+                    $("#${id!}").click();
+                }
+            });
         </script>
       </#if>
   </#if>
diff --git a/themes/common-theme/webapp/common-theme/js/util/OfbizUtil.js 
b/themes/common-theme/webapp/common-theme/js/util/OfbizUtil.js
index 031efd4bf0..a92848c967 100644
--- a/themes/common-theme/webapp/common-theme/js/util/OfbizUtil.js
+++ b/themes/common-theme/webapp/common-theme/js/util/OfbizUtil.js
@@ -834,7 +834,7 @@ function errorRetrievingResponseFromServer(xhr, status, 
exception) {
  * @param areaCsvString The area CSV string. The CSV string is a flat array in 
the
  * form of: areaId, target, target parameters [, areaId, target, target 
parameters...].
 */
-function ajaxSubmitFormUpdateAreas(formName, areaCsvString) {
+function ajaxSubmitFormUpdateAreas(formName, areaCsvString, close) {
    waitSpinnerShow();
 
    var $form = jQuery("form[name='" + formName + "']");
@@ -864,7 +864,9 @@ function ajaxSubmitFormUpdateAreas(formName, areaCsvString) 
{
                    areaCsvString += data[variableName] + 
endString.substring(endString.indexOf("_") + 1)
                }
                ajaxUpdateAreas(areaCsvString);
-               
$form.trigger("closeCurrentModalAfterAjaxSubmitFormUpdateAreasInSuccess");
+               if (close === undefined || close == 'true') {
+                    
$form.trigger('closeCurrentModalAfterAjaxSubmitFormUpdateAreasInSuccess');
+                }
            }
        }
    }

Reply via email to