You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by nm...@apache.org on 2021/05/21 16:00:15 UTC

[ofbiz-framework] branch trunk updated: Implemented: on-event-update-area on form inherit information from parent form (OFBIZ-11811) (OFBIZ-11808)

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

nmalin 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 b663660  Implemented: on-event-update-area on form inherit information from parent form (OFBIZ-11811) (OFBIZ-11808)
b663660 is described below

commit b663660486074196385bdf08034547839dc1e11c
Author: Nicolas Malin <ni...@nereide.fr>
AuthorDate: Fri May 21 17:40:46 2021 +0200

    Implemented: on-event-update-area on form inherit information from parent form
    (OFBIZ-11811) (OFBIZ-11808)
    
    When you write a form, if you want the dynamic interaction and style, you need to implement everything on the form.
    The developer must know the style used, different area and rules support by the technology besides the really information/action that the form will do.
    
       <form name="ListFacility" type="list" list-name="listIt" paginate-target="FindFacility"
             odd-row-style="alternate-row" header-row-style="header-row-2" default-table-style="basic-table hover-bar">
           <actions>...
           <field name="facilityId">....
           <on-event-update-area event-type="sort-column" area-id="search-results" area-target="FacilitySearchResults"/>
           <on-event-update-area event-type="paginate" area-id="search-results" area-target="FacilitySearchResults"/>
       </form>
    
    We can put all information on the theme and all dynamic refresh (for area) are related to the parent form and parent screen. Finally we will obtain :
    
        <form name="ListFacility" extends="CommonDynamicList" extends-resource="component://common/widget/CommonForms.xml"
              paginate-target="FindFacility">
            <actions>...
            <field name="facilityId">....
        </form>
    
        <form name="CommonDynamicList" type="list"
             odd-row-style="alternate-row" header-row-style="header-row-2" default-table-style="basic-table hover-bar">
           <on-event-update-area event-type="sort-column"/>
           <on-event-update-area event-type="paginate"/>
       </form>
    
    The target and area to update has been automatically resolved from the parent form and screen.
    
    This commit improve the modelForm and the widget-form.xsd to do that.
    
    Thanks to Gil Portenseigne his help
---
 .../ofbiz/webapp/control/RequestHandler.java       |  4 +-
 framework/widget/dtd/widget-form.xsd               | 20 ++++-
 .../org/apache/ofbiz/widget/model/ModelForm.java   |  2 +
 .../widget/renderer/macro/MacroCommonRenderer.java | 90 +++++++++++-----------
 .../widget/renderer/macro/MacroFormRenderer.java   | 23 +++---
 5 files changed, 81 insertions(+), 58 deletions(-)

diff --git a/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/RequestHandler.java b/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/RequestHandler.java
index 46ed743..9ebd1e4 100644
--- a/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/RequestHandler.java
+++ b/framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/RequestHandler.java
@@ -1388,10 +1388,10 @@ public final class RequestHandler {
         }
 
         // now add the actual passed url, but if it doesn't start with a / add one first
-        if (!url.startsWith("/")) {
+        if (url != null && !url.startsWith("/")) {
             newURL.append("/");
         }
-        newURL.append(url);
+        newURL.append(url == null ? "": url);
 
         String encodedUrl;
         if (encode) {
diff --git a/framework/widget/dtd/widget-form.xsd b/framework/widget/dtd/widget-form.xsd
index c989030..93e5d56 100644
--- a/framework/widget/dtd/widget-form.xsd
+++ b/framework/widget/dtd/widget-form.xsd
@@ -597,8 +597,24 @@ under the License.
                     </xs:restriction>
                 </xs:simpleType>
             </xs:attribute>
-            <xs:attribute name="area-id" type="xs:string" use="required" />
-            <xs:attribute name="area-target" type="xs:string" use="required" />
+            <xs:attribute name="area-id" type="xs:string">
+                <xs:annotation>
+                    <xs:documentation>
+                        Mandatory in classic usage.
+                        This has been made optional for template needs (common-theme) and automatic area-id
+                        definition, based on calling widget.
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:attribute>
+            <xs:attribute name="area-target" type="xs:string">
+                <xs:annotation>
+                    <xs:documentation>
+                        Mandatory in classic usage.
+                        This has been made optional for template needs (common-theme) and automatic area-id
+                        definition, based on calling widget.
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:attribute>
         </xs:complexType>
     </xs:element>
 
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 62d9d91..1869d2b 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
@@ -36,6 +36,7 @@ import org.apache.ofbiz.base.util.GroovyUtil;
 import org.apache.ofbiz.base.util.StringUtil;
 import org.apache.ofbiz.base.util.UtilCodec;
 import org.apache.ofbiz.base.util.UtilGenerics;
+import org.apache.ofbiz.base.util.UtilMisc;
 import org.apache.ofbiz.base.util.UtilProperties;
 import org.apache.ofbiz.base.util.UtilValidate;
 import org.apache.ofbiz.base.util.UtilXml;
@@ -2278,6 +2279,7 @@ public abstract class ModelForm extends ModelWidget {
      * elements used in form widgets.
      */
     public static class UpdateArea {
+        public static final List<String> EVENT_TYPES_FOR_LIST_REFRESH = UtilMisc.toList("paginate", "sort-column");
         private final String eventType;
         private final String areaId;
         private final String areaTarget;
diff --git a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/MacroCommonRenderer.java b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/MacroCommonRenderer.java
index 8fb85f5..997317f 100644
--- a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/MacroCommonRenderer.java
+++ b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/MacroCommonRenderer.java
@@ -23,21 +23,19 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.stream.Collectors;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import org.apache.ofbiz.base.util.StringUtil;
 import org.apache.ofbiz.base.util.UtilGenerics;
 import org.apache.ofbiz.base.util.UtilHttp;
 import org.apache.ofbiz.base.util.UtilMisc;
+import org.apache.ofbiz.base.util.UtilValidate;
 import org.apache.ofbiz.base.util.string.FlexibleStringExpander;
 import org.apache.ofbiz.webapp.control.RequestHandler;
 import org.apache.ofbiz.widget.WidgetWorker;
 import org.apache.ofbiz.widget.model.CommonWidgetModels;
 import org.apache.ofbiz.widget.model.ModelForm;
 
-/**
- * TODO : Migrate to {@link org.apache.ofbiz.widget.renderer.macro.renderable.RenderableFtl}
- */
 public class MacroCommonRenderer {
 
     /**
@@ -50,38 +48,56 @@ public class MacroCommonRenderer {
      * @return Parameter string or empty string if no UpdateArea objects were found
      */
     public static String createAjaxParamsFromUpdateAreas(List<ModelForm.UpdateArea> updateAreas, Map<String, Object> extraParams,
-                                                   String anchor, Map<String, ? extends Object> context) {
+                                                         ModelForm parentModelForm, String anchor, Map<String, ? extends Object> context) {
 
         HttpServletRequest request = (HttpServletRequest) context.get("request");
         HttpServletResponse response = (HttpServletResponse) context.get("response");
+        Map<String, Object> ctx = UtilGenerics.cast(context);
         RequestHandler rh = RequestHandler.from(request);
 
         StringBuilder sb = new StringBuilder();
         Iterator<ModelForm.UpdateArea> updateAreaIter = updateAreas.iterator();
         while (updateAreaIter.hasNext()) {
             ModelForm.UpdateArea updateArea = updateAreaIter.next();
-            sb.append(updateArea.getAreaId()).append(",");
+
+            //For each update area we need to resolve three information below
+            String areaIdToUpdate;
+            String targetToCall;
+            String parametersToForward;
+
+            // 1. areaId to update, use the screen stack with the potential area given by the update area element
+            areaIdToUpdate = WidgetWorker.getScreenStack(ctx).resolveScreenAreaId(updateArea.getAreaId());
+
+            // 2. the target, if the updateArea haven't the information and we are on event link to the pagination,
+            //     will ask to the parent model the pagination target
             String ajaxTarget = updateArea.getAreaTarget(context);
-            String urlPath = UtilHttp.removeQueryStringFromTarget(ajaxTarget);
-            sb.append(rh.makeLink(request, response, urlPath)).append(",");
+            if (UtilValidate.isEmpty(ajaxTarget)
+                    && parentModelForm != null) {
+                if (ModelForm.UpdateArea.EVENT_TYPES_FOR_LIST_REFRESH.contains(updateArea.getEventType())) {
+                    ajaxTarget = parentModelForm.getPaginateTarget(ctx);
+                } else {
+                    ajaxTarget = parentModelForm.getTarget(ctx, parentModelForm.getTargetType());
+                }
+            }
+            targetToCall = rh.makeLink(request, response, UtilHttp.removeQueryStringFromTarget(ajaxTarget));
+
+            // 3. Build parameters to forward
             String queryString = UtilHttp.getQueryStringFromTarget(ajaxTarget).replace("?", "");
             Map<String, Object> parameters = UtilHttp.getQueryStringOnlyParameterMap(queryString);
-            Map<String, Object> ctx = UtilGenerics.cast(context);
-            Map<String, Object> updateParams = UtilGenerics.cast(updateArea.getParameterMap(ctx));
-            parameters.putAll(updateParams);
+            parameters.putAll(UtilGenerics.cast(updateArea.getParameterMap(ctx)));
             UtilHttp.canonicalizeParameterMap(parameters);
-            if (extraParams != null) {
-                parameters.putAll(extraParams);
-            }
-            Iterator<Map.Entry<String, Object>> paramIter = parameters.entrySet().iterator();
-            while (paramIter.hasNext()) {
-                Map.Entry<String, Object> entry = paramIter.next();
-                sb.append(entry.getKey()).append("=").append(entry.getValue());
-                if (paramIter.hasNext()) {
-                    sb.append("&");
-                }
+            parametersToForward = UtilHttp.urlEncodeArgs(parameters, false);
+            if (UtilValidate.isNotEmpty(parametersToForward)
+                    && UtilValidate.isNotEmpty(extraParams)) {
+                parametersToForward += "&";
             }
-            if (anchor != null) {
+            parametersToForward += buildParamStringFromMap(extraParams);
+
+            // 4. build the final string
+            sb.append(areaIdToUpdate).append(",")
+                    .append(targetToCall).append(",")
+                    .append(parametersToForward);
+            if (UtilValidate.isNotEmpty(anchor)) {
                 sb.append("#").append(anchor);
             }
             if (updateAreaIter.hasNext()) {
@@ -92,28 +108,12 @@ public class MacroCommonRenderer {
         return FlexibleStringExpander.expandString(sb.toString(), context, locale);
     }
 
-    /** Create an ajaxXxxx JavaScript CSV string from a list of UpdateArea objects. See
-     * <code>OfbizUtil.js</code>.
-     * @param updateAreas
-     * @param extraParams Renderer-supplied additional target parameters String
-     * @param context
-     * @return Parameter string or empty string if no UpdateArea objects were found
-     */
-    public static String createAjaxParamsFromUpdateAreas(List<ModelForm.UpdateArea> updateAreas, String extraParams,
-                                                         Map<String, ? extends Object> context) {
-        Map<String, Object> extraParamsAsMap = buildParamMapFromString(extraParams);
-        return createAjaxParamsFromUpdateAreas(updateAreas, extraParamsAsMap, null, context);
-    }
-
-    private static Map<String, Object> buildParamMapFromString(String extraParams) {
-        Map<String, Object> extraParamsAsMap = null;
-        if (extraParams != null) {
-            while (extraParams.startsWith("&")) {
-                extraParams = extraParams.replaceFirst("&", "");
-            }
-            extraParamsAsMap = UtilGenerics.cast(StringUtil.strToMap(extraParams, "&", false));
-        }
-        return extraParamsAsMap;
+    private static String buildParamStringFromMap(Map<String, Object> extraParamsAsMap) {
+        if (extraParamsAsMap == null) return "";
+        final Map<String, Object> extraParamsAsMapConverted = extraParamsAsMap;
+        return extraParamsAsMap.keySet().stream()
+                .map(key -> key + "=" + extraParamsAsMapConverted.get(key))
+                .collect(Collectors.joining("&"));
     }
 
     /**
@@ -132,7 +132,7 @@ public class MacroCommonRenderer {
                     WidgetWorker.getScreenStack(context).resolveScreenAreaId(link.getTargetWindow(context)),
                     link.getTarget(context));
             linkUrl = createAjaxParamsFromUpdateAreas(UtilMisc.toList(resolveUpdateArea),
-                    UtilHttp.urlEncodeArgs(link.getParameterMap(context)), context);
+                    UtilGenerics.cast(link.getParameterMap(context)), null, null, context);
             break;
         default:
             final URI linkUri = WidgetWorker.buildHyperlinkUri(link.getTarget(context), link.getUrlMode(),
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 2e0e5af..d093526 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
@@ -1022,7 +1022,7 @@ public final class MacroFormRenderer implements FormStringRenderer {
                 && this.javaScriptEnabled;
         String ajaxUrl = "";
         if (ajaxEnabled) {
-            ajaxUrl = MacroCommonRenderer.createAjaxParamsFromUpdateAreas(updateAreas, "", context);
+            ajaxUrl = MacroCommonRenderer.createAjaxParamsFromUpdateAreas(updateAreas, null, modelForm, "", context);
         }
         String tabindex = modelFormField.getTabindex();
         StringWriter sr = new StringWriter();
@@ -2117,7 +2117,7 @@ public final class MacroFormRenderer implements FormStringRenderer {
         this.appendContentUrl(imgSrc, "/images/fieldlookup.gif");
         String ajaxUrl = "";
         if (ajaxEnabled) {
-            ajaxUrl = MacroCommonRenderer.createAjaxParamsFromUpdateAreas(updateAreas, "", context);
+            ajaxUrl = MacroCommonRenderer.createAjaxParamsFromUpdateAreas(updateAreas, null, modelForm, "", context);
         }
         String lookupPresentation = lookupField.getLookupPresentation();
         if (UtilValidate.isEmpty(lookupPresentation)) {
@@ -2341,7 +2341,7 @@ public final class MacroFormRenderer implements FormStringRenderer {
         String ajaxLastUrl = "";
         if (viewIndex > 0) {
             if (ajaxEnabled) {
-                ajaxFirstUrl = MacroCommonRenderer.createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + 0 + anchor, context);
+                ajaxFirstUrl = MacroCommonRenderer.createAjaxParamsFromUpdateAreas(updateAreas, null, modelForm, prepLinkText + 0 + anchor, context);
             } else {
                 linkText = prepLinkText + 0 + anchor;
                 firstUrl = rh.makeLink(this.request, this.response, urlPath + linkText);
@@ -2349,7 +2349,8 @@ public final class MacroFormRenderer implements FormStringRenderer {
         }
         if (viewIndex > 0) {
             if (ajaxEnabled) {
-                ajaxPreviousUrl = MacroCommonRenderer.createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + (viewIndex - 1) + anchor, context);
+                ajaxPreviousUrl = MacroCommonRenderer.createAjaxParamsFromUpdateAreas(updateAreas, null, modelForm,
+                        prepLinkText + (viewIndex - 1) + anchor, context);
             } else {
                 linkText = prepLinkText + (viewIndex - 1) + anchor;
                 previousUrl = rh.makeLink(this.request, this.response, urlPath + linkText);
@@ -2358,7 +2359,8 @@ public final class MacroFormRenderer implements FormStringRenderer {
         // Page select dropdown
         if (listSize > 0 && this.javaScriptEnabled) {
             if (ajaxEnabled) {
-                ajaxSelectUrl = MacroCommonRenderer.createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + "' + this.value + '", context);
+                ajaxSelectUrl = MacroCommonRenderer.createAjaxParamsFromUpdateAreas(updateAreas, null, modelForm,
+                        prepLinkText + "' + this.value + '", context);
             } else {
                 linkText = prepLinkText;
                 if (linkText.startsWith("/")) {
@@ -2370,7 +2372,8 @@ public final class MacroFormRenderer implements FormStringRenderer {
         // Next button
         if (highIndex < listSize) {
             if (ajaxEnabled) {
-                ajaxNextUrl = MacroCommonRenderer.createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + (viewIndex + 1) + anchor, context);
+                ajaxNextUrl = MacroCommonRenderer.createAjaxParamsFromUpdateAreas(updateAreas, null,
+                        modelForm, prepLinkText + (viewIndex + 1) + anchor, context);
             } else {
                 linkText = prepLinkText + (viewIndex + 1) + anchor;
                 nextUrl = rh.makeLink(this.request, this.response, urlPath + linkText);
@@ -2380,7 +2383,8 @@ public final class MacroFormRenderer implements FormStringRenderer {
         if (highIndex < listSize) {
             int lastIndex = UtilMisc.getViewLastIndex(listSize, viewSize);
             if (ajaxEnabled) {
-                ajaxLastUrl = MacroCommonRenderer.createAjaxParamsFromUpdateAreas(updateAreas, prepLinkText + lastIndex + anchor, context);
+                ajaxLastUrl = MacroCommonRenderer.createAjaxParamsFromUpdateAreas(updateAreas, null,
+                        modelForm, prepLinkText + lastIndex + anchor, context);
             } else {
                 linkText = prepLinkText + lastIndex + anchor;
                 lastUrl = rh.makeLink(this.request, this.response, urlPath + linkText);
@@ -2389,7 +2393,8 @@ public final class MacroFormRenderer implements FormStringRenderer {
         // Page size select dropdown
         if (listSize > 0 && this.javaScriptEnabled) {
             if (ajaxEnabled) {
-                ajaxSelectSizeUrl = MacroCommonRenderer.createAjaxParamsFromUpdateAreas(updateAreas, prepLinkSizeText + anchor, context);
+                ajaxSelectSizeUrl = MacroCommonRenderer.createAjaxParamsFromUpdateAreas(updateAreas, null,
+                        modelForm, prepLinkSizeText + anchor, context);
             } else {
                 linkText = prepLinkSizeText;
                 if (linkText.startsWith("/")) {
@@ -2833,7 +2838,7 @@ public final class MacroFormRenderer implements FormStringRenderer {
         UtilHttp.canonicalizeParameterMap(paramMap);
         String linkUrl = null;
         if (ajaxEnabled) {
-            linkUrl = MacroCommonRenderer.createAjaxParamsFromUpdateAreas(updateAreas, paramMap, null, context);
+            linkUrl = MacroCommonRenderer.createAjaxParamsFromUpdateAreas(updateAreas, paramMap, modelForm, null, context);
         } else {
             StringBuilder sb = new StringBuilder("?");
             Iterator<Map.Entry<String, Object>> iter = paramMap.entrySet().iterator();