From 59381dc1a905b3417584a682903882dbf125b3df Mon Sep 17 00:00:00 2001 From: Shivam Agarwal Date: Tue, 17 Sep 2024 10:56:50 +0530 Subject: [PATCH] FORMS-16342 commenting test --- .../util/AbstractFormComponentImpl.java | 39 +++-- .../util/AbstractOptionsFieldImpl.java | 6 +- .../form/base/v1/base/_cq_editConfig.xml | 6 + .../form/button/v1/button/_cq_editConfig.xml | 6 + .../editorhook/js/qualifiedNameHook.js | 139 +++++++++++++++++- .../clientlibs/site/js/datepickerview.js | 4 + .../clientlibs/site/js/dropdownview.js | 2 + .../clientlibs/site/js/emailinputview.js | 2 + .../clientlibs/site/js/numberinputview.js | 2 + .../v1/panelcontainer/_cq_editConfig.xml | 6 + .../clientlibs/site/js/telephoneinputview.js | 2 + .../clientlibs/site/js/textinputview.js | 2 + .../page/v1/page/customfooterlibs.html | 1 + ui.frontend/src/handleXfa.js | 31 ++++ ui.frontend/src/utils.js | 19 ++- ui.frontend/src/view/FormCheckBox.js | 9 +- ui.frontend/src/view/FormField.js | 8 + 17 files changed, 268 insertions(+), 16 deletions(-) create mode 100644 ui.frontend/src/handleXfa.js diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractFormComponentImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractFormComponentImpl.java index 50f3a643d5..30b8790ac2 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractFormComponentImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractFormComponentImpl.java @@ -17,17 +17,7 @@ import java.io.IOException; import java.math.BigDecimal; -import java.util.AbstractMap; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; +import java.util.*; import java.util.function.Predicate; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -36,6 +26,9 @@ import javax.annotation.Nonnull; import javax.annotation.PostConstruct; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; import org.apache.commons.lang3.StringEscapeUtils; import org.apache.commons.lang3.StringUtils; import org.apache.sling.api.resource.Resource; @@ -289,6 +282,10 @@ protected boolean getEditMode() { if (rulesProperties.size() > 0) { properties.put(CUSTOM_RULE_PROPERTY_WRAPPER, rulesProperties); } + List disabledScripts = getDisabledXFAScripts(); + if (disabledScripts.size() > 0) { + properties.put("fd:disabledXfaScripts", disabledScripts); + } return properties; } @@ -541,4 +538,24 @@ public Map getDorProperties() { return customDorProperties; } + private List getDisabledXFAScripts() { + Set disabledScripts = new HashSet<>(); + String xfaScripts = resource.getValueMap().get("fd:xfaScripts", ""); + if (StringUtils.isNotEmpty(xfaScripts)) { + // read string xfaScripts to jsonNode + ObjectMapper mapper = new ObjectMapper(); + try { + ArrayNode node = (ArrayNode) mapper.readTree(xfaScripts); + // iterate through the array node and add the elements which have disabled property set to true + for (JsonNode jsonNode : node) { + if (jsonNode.has("disabled") && jsonNode.get("disabled").asBoolean()) { + disabledScripts.add(jsonNode.get("activity").asText()); + } + } + } catch (IOException e) { + logger.error("Error while parsing xfaScripts {} {}", e, resource.getPath()); + } + } + return new ArrayList<>(disabledScripts); + } } diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractOptionsFieldImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractOptionsFieldImpl.java index b43f30b643..1b7fb8537f 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractOptionsFieldImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractOptionsFieldImpl.java @@ -107,7 +107,11 @@ public String[] getEnumNames() { String[] enumName = map.values().toArray(new String[0]); return Arrays.stream(enumName) .map(p -> { - return this.translate(ReservedProperties.PN_ENUM_NAMES, p); + String value = this.translate(ReservedProperties.PN_ENUM_NAMES, p); + if (value == null) { + value = ""; + } + return value; }) .toArray(String[]::new); } diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/base/v1/base/_cq_editConfig.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/base/v1/base/_cq_editConfig.xml index fc6d62c32d..5a4a7100a8 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/base/v1/base/_cq_editConfig.xml +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/base/v1/base/_cq_editConfig.xml @@ -23,6 +23,12 @@ handler="CQ.FormsCoreComponents.editorhooks.viewQualifiedName" icon="viewSOMExpression" text="View Qualified Name"/> + + 0; + } catch(e) { + console.error('Error parsing xfaScripts', e, json['fd:xfaScripts']); + } + } + } + return false + } + + window.CQ.FormsCoreComponents.editorhooks.viewXfaScripts = function (editable) { + fetch(Granite.HTTP.externalize(editable.path + ".json")).then(async function (resp) { + const json = await resp.json(); + // Assuming `resp` contains the JSON string with `fd:xfaScripts` + var xfaScripts = JSON.parse(json['fd:xfaScripts']); + var dialogContent = document.createElement('div'); + + // Create a Coral Table + var table = document.createElement('coral-table'); + + // Create the header + var thead = document.createElement('coral-table-head'); + var headerRow = document.createElement('coral-table-row'); + + var eventNameHeader = document.createElement('coral-table-headercell'); + eventNameHeader.textContent = 'Event Name'; + var eventContentHeader = document.createElement('coral-table-headercell'); + eventContentHeader.textContent = 'Event Content'; + var disableHeader = document.createElement('coral-table-headercell'); + disableHeader.textContent = 'Disable'; + + headerRow.appendChild(eventNameHeader); + headerRow.appendChild(eventContentHeader); + headerRow.appendChild(disableHeader); + thead.appendChild(headerRow); + table.appendChild(thead); + + // Populate the table with data from xfaScripts + var tbody = document.createElement('coral-table-body'); + xfaScripts.forEach(function(script) { + var row = document.createElement('coral-table-row'); + + var nameCell = document.createElement('coral-table-cell'); + nameCell.textContent = script.runAt === "server" ? `${script.activity}(server)` : script.activity; + var contentCell = document.createElement('coral-table-cell'); + contentCell.innerHTML = script.value.replaceAll("\n", "
"); + + var checkboxCell = document.createElement('coral-table-cell'); + var checkbox = new Coral.Checkbox(); + checkbox.name = 'disableCheckbox'; + checkbox.on('change', function() { + script.disabled = this.checked; + }); + checkboxCell.appendChild(checkbox); + checkbox.checked = !!script.disabled; + if (script.runAt === "server") { + checkbox.disabled = true; + } + row.appendChild(nameCell); + row.appendChild(contentCell); + row.appendChild(checkboxCell); + + tbody.appendChild(row); + }); + table.appendChild(tbody); + + dialogContent.appendChild(table); + + // Create the dialog + var dialog = new Coral.Dialog().set({ + id: 'xfaScriptsDialog', + header: { + innerHTML: 'XFA Scripts' + }, + content: { + innerHTML: '' + }, + footer: {}, + closable: "on" + }); + + // Add the table to the dialog content + //dialog.content.appendChild(dialogContent); + + var okButton = new Coral.Button(); + okButton.label.textContent = 'OK'; + okButton.variant = Coral.Button.variant.PRIMARY; + okButton.addEventListener('click', function() { + // Prepare the modified xfaScripts for POST request + var modifiedXfaScripts = JSON.stringify({ 'fd:xfaScripts': JSON.stringify(xfaScripts) }); + $.ajax({ + url: editable.path, + type: 'POST', + data: { + "_charset_" : "UTF-8", + ':operation': 'import', + ':contentType': 'json', + ':content': modifiedXfaScripts, + ':replaceProperties': true + }, + success: function(response) { + console.log('Successfully posted the data'); + dialog.remove(); + }, + error: function(xhr, status, error) { + console.error('Error posting the data', error); + dialog.remove(); + } + }); + }); + dialog.footer.appendChild(okButton); + +// Append and show the dialog + document.body.appendChild(dialog); + + // add a listener on dialog show event + dialog.on('coral-overlay:open', function() { + dialog.content.appendChild(dialogContent); + }); + dialog.show(); + + }) + return true; + }; + +})(window, Granite.author, Coral); diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/datepicker/v1/datepicker/clientlibs/site/js/datepickerview.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/datepicker/v1/datepicker/clientlibs/site/js/datepickerview.js index 86f65a2ab5..c4df1c1302 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/datepicker/v1/datepicker/clientlibs/site/js/datepickerview.js +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/datepicker/v1/datepicker/clientlibs/site/js/datepickerview.js @@ -99,10 +99,12 @@ this.widgetObject.setDisplayValue(this._model.value); this.widgetObject.setCalendarWidgetValue(this._model.value); this.setInactive(); + this.triggerExit(); }, this.getWidget()); this.widgetObject.addEventListener('focus', (e) => { this.widgetObject.setValue(e.target.value); this.setActive(); + this.triggerEnter(); }, this.getWidget()); this.widgetObject.addEventListener('input', (e) => { if( e.target.value === '') { @@ -117,9 +119,11 @@ this.widget.addEventListener('blur', (e) => { this.setModelValue(e.target.value); this.setInactive(); + this.triggerExit(); }); this.widget.addEventListener('focus', (e) => { this.setActive(); + this.triggerEnter(); }); } } diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/dropdown/v1/dropdown/clientlibs/site/js/dropdownview.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/dropdown/v1/dropdown/clientlibs/site/js/dropdownview.js index 3deb8ba4a1..fc211ab282 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/dropdown/v1/dropdown/clientlibs/site/js/dropdownview.js +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/dropdown/v1/dropdown/clientlibs/site/js/dropdownview.js @@ -208,9 +208,11 @@ }); this.widget.addEventListener('focus', (e) => { this.setActive(); + this.triggerEnter(); }); this.widget.addEventListener('blur', (e) => { this.setInactive(); + this.triggerExit(); }); } diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/emailinput/v1/emailinput/clientlibs/site/js/emailinputview.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/emailinput/v1/emailinput/clientlibs/site/js/emailinputview.js index 41662f809c..b8974c5c7c 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/emailinput/v1/emailinput/clientlibs/site/js/emailinputview.js +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/emailinput/v1/emailinput/clientlibs/site/js/emailinputview.js @@ -74,10 +74,12 @@ this.setModelValue(e.target.value); this.setWidgetValueToDisplayValue(); this.setInactive(); + this.triggerExit(); }); this.widget.addEventListener('focus', (e) => { this.setActive(); this.setWidgetValueToModelValue(); + this.triggerEnter(); }); } } diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/numberinput/v1/numberinput/clientlibs/site/js/numberinputview.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/numberinput/v1/numberinput/clientlibs/site/js/numberinputview.js index 8d737e0a0c..a81994501f 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/numberinput/v1/numberinput/clientlibs/site/js/numberinputview.js +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/numberinput/v1/numberinput/clientlibs/site/js/numberinputview.js @@ -100,12 +100,14 @@ this.setModelValue(e.target.value); if(this.element) { this.setInactive(); + this.triggerExit(); } }); } this.getWidget().addEventListener('focus', (e) => { if (this.element) { this.setActive(); + this.triggerEnter(); } }); } diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/panelcontainer/v1/panelcontainer/_cq_editConfig.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/panelcontainer/v1/panelcontainer/_cq_editConfig.xml index b9cf9ad1bb..428607e492 100755 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/panelcontainer/v1/panelcontainer/_cq_editConfig.xml +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/panelcontainer/v1/panelcontainer/_cq_editConfig.xml @@ -25,5 +25,11 @@ handler="CQ.FormsCoreComponents.editorhooks.viewQualifiedName" icon="viewSOMExpression" text="View Qualified Name"/> + diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/telephoneinput/v1/telephoneinput/clientlibs/site/js/telephoneinputview.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/telephoneinput/v1/telephoneinput/clientlibs/site/js/telephoneinputview.js index 7fe8a2d048..ea43ca183f 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/telephoneinput/v1/telephoneinput/clientlibs/site/js/telephoneinputview.js +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/telephoneinput/v1/telephoneinput/clientlibs/site/js/telephoneinputview.js @@ -74,10 +74,12 @@ this.setModelValue(e.target.value); this.setWidgetValueToDisplayValue(); this.setInactive(); + this.triggerExit(); }); this.widget.addEventListener('focus', (e) => { this.setActive(); this.setWidgetValueToModelValue(); + this.triggerEnter(); }); } } diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/textinput/v1/textinput/clientlibs/site/js/textinputview.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/textinput/v1/textinput/clientlibs/site/js/textinputview.js index e2119a07df..2c075f12c1 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/textinput/v1/textinput/clientlibs/site/js/textinputview.js +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/textinput/v1/textinput/clientlibs/site/js/textinputview.js @@ -74,10 +74,12 @@ this.setModelValue(e.target.value); this.setWidgetValueToDisplayValue(); this.setInactive(); + this.triggerExit(); }); this.widget.addEventListener('focus', (e) => { this.setActive(); this.setWidgetValueToModelValue(); + this.triggerEnter(); }); } } diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/page/v1/page/customfooterlibs.html b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/page/v1/page/customfooterlibs.html index 268a57ac5c..c1152c89c8 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/page/v1/page/customfooterlibs.html +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/page/v1/page/customfooterlibs.html @@ -19,6 +19,7 @@ + diff --git a/ui.frontend/src/handleXfa.js b/ui.frontend/src/handleXfa.js new file mode 100644 index 0000000000..f1a6468b58 --- /dev/null +++ b/ui.frontend/src/handleXfa.js @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright 2024 Adobe + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************/ + +export function loadXfa(formdom, renderContext) { + if (window.xfalib) { + formBridge.registerConfig("disabledServerScripts", ["initialize", "$formready", "$layoutready"]) + const xfaJson = JSON.parse(JSON.parse(JSON.stringify(formdom))); + xfalib.runtime.renderContext = JSON.parse(JSON.parse(JSON.stringify(renderContext))); + xfalib.script.XfaModelRegistry.prototype.createModel(xfaJson); + //initialize Acrobat specific scripts + new xfalib.acrobat.Acrobat(); + return function (model) { + model._syncXfaProps(); + xfalib.runtime.xfa.form._initialize(true); + $(window).trigger("XfaInitialized"); + } + } +} diff --git a/ui.frontend/src/utils.js b/ui.frontend/src/utils.js index b201ae4eee..932f2d688e 100644 --- a/ui.frontend/src/utils.js +++ b/ui.frontend/src/utils.js @@ -17,7 +17,8 @@ import {Constants} from "./constants.js"; import HTTPAPILayer from "./HTTPAPILayer.js"; import {customFunctions} from "./customFunctions.js"; -import {FunctionRuntime} from '@aemforms/af-core' +import {FunctionRuntime} from '@aemforms/af-core'; +import {loadXfa} from "./handleXfa"; /** * @module FormView @@ -307,7 +308,18 @@ class Utils { if (_path == null) { console.error(`data-${Constants.NS}-${formContainerClass}-path attribute is not present in the HTML element. Form cannot be initialized` ) } else { - const _formJson = await HTTPAPILayer.getFormDefinition(_path, _pageLang); + const loader = elements[i].parentElement?.querySelector('[data-cmp-adaptiveform-container-loader]'); + let _formJson, callback; + if (loader) { + const id = loader.getAttribute('data-cmp-adaptiveform-container-loader'); + const response = await fetch(`/adobe/forms/af/${id}`) + _formJson = (await response.json()).afModelDefinition; + _formJson.id = id; + //window.formJson = _formJson + callback = loadXfa(_formJson.formdom, _formJson.xfaRenderContext); + } else { + _formJson = await HTTPAPILayer.getFormDefinition(_path, _pageLang); + } console.debug("fetched model json", _formJson); await this.registerCustomFunctions(_formJson.id); await this.registerCustomFunctionsByUrl(customFunctionUrl); @@ -325,6 +337,9 @@ class Utils { _path, _element: elements[i] }); + if (typeof callback === 'function') { + callback(formContainer.getModel()); + } Utils.initializeAllFields(formContainer); const event = new CustomEvent(Constants.FORM_CONTAINER_INITIALISED, { "detail": formContainer }); document.dispatchEvent(event); diff --git a/ui.frontend/src/view/FormCheckBox.js b/ui.frontend/src/view/FormCheckBox.js index acf5fc4075..7f0d5bc0a3 100644 --- a/ui.frontend/src/view/FormCheckBox.js +++ b/ui.frontend/src/view/FormCheckBox.js @@ -48,7 +48,14 @@ class FormCheckBox extends FormFieldBase { const value = this.widget.checked ? this._onValue : this._offValue; this._model.dispatch(new FormView.Actions.UIChange({'value': value})); }) - + this.widget.addEventListener('focus', (e) => { + this.setActive(); + this.triggerEnter(); + }); + this.widget.addEventListener('blur', (e) => { + this.setInactive(); + this.triggerExit(); + }); } } diff --git a/ui.frontend/src/view/FormField.js b/ui.frontend/src/view/FormField.js index 271d5451d9..b0a80abae9 100644 --- a/ui.frontend/src/view/FormField.js +++ b/ui.frontend/src/view/FormField.js @@ -101,6 +101,14 @@ class FormField { return this.element.getAttribute(Constants.DATA_ATTRIBUTE_ACTIVE) === 'true'; } + triggerExit() { + this._model.dispatch(new FormView.Actions.CustomEvent('xfaexit')); + } + + triggerEnter() { + this._model.dispatch(new FormView.Actions.CustomEvent('xfaenter')); + } + /** * Returns the form container path of the form field. * @returns {string} The form container path.