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'); + } } } }