diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/ReviewImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/ReviewImpl.java index 71afa17ee8..de1ed17545 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/ReviewImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/ReviewImpl.java @@ -18,6 +18,7 @@ import java.util.Arrays; import java.util.Map; +import com.adobe.cq.forms.core.components.models.form.FieldType; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.Resource; import org.apache.sling.models.annotations.Exporter; @@ -43,31 +44,34 @@ public class ReviewImpl extends AbstractBaseImpl implements Review { private static final String LINKED_PANEL_PROPERTY = "fd:linkedPanels"; - private static final String EDIT_ACTION_PROPERTY = "fd:editAction"; + private static final String EDIT_ACTION_PROPERTY = "fd:editModeAction"; - @JsonIgnore - @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL, name = "linkedPanels") + @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL, name = "fd:linkedPanels") @Nullable private String[] linkedPanels; + @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL, name = "fd:editModeAction") + @Nullable + private String editModeAction; + public String[] getLinkedPanels() { return linkedPanels != null ? Arrays.copyOf(linkedPanels, linkedPanels.length) : new String[] {}; } - @JsonIgnore - @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL, name = "editAction") - @Nullable - private String editAction; + public String getEditModeAction() { + return editModeAction; + } - public String getEditAction() { - return editAction; + @Override + public String getFieldType() { + return super.getFieldType(FieldType.PLAIN_TEXT); } @Override public @NotNull Map getProperties() { Map customProperties = super.getProperties(); customProperties.put(LINKED_PANEL_PROPERTY, getLinkedPanels()); - customProperties.put(EDIT_ACTION_PROPERTY, getEditAction()); + customProperties.put(EDIT_ACTION_PROPERTY, getEditModeAction()); return customProperties; } } diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/servlets/ReviewDataSourceServlet.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/servlets/ReviewDataSourceServlet.java index 09d9468f20..75506c002d 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/servlets/ReviewDataSourceServlet.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/servlets/ReviewDataSourceServlet.java @@ -81,23 +81,25 @@ protected void doGet(@NotNull SlingHttpServletRequest request, @NotNull SlingHtt if (resourceResolver != null) { Resource componentInstance = resourceResolver.getResource(componentInstancePath); Resource formInstance = ComponentUtils.getFormContainer(componentInstance); - FormContainer formContainer = formInstance.adaptTo(FormContainer.class); - List panelList = (List) getPanels(formContainer); - List panels = panelList.stream().filter(x -> "panel".equals(x.getFieldType())).collect(Collectors.toList()); - for (Base panel : panels) { - String name = panel != null ? panel.getName() : ""; - String title = ""; - if (panel != null) { - Label label = panel.getLabel(); - if (label != null) { - String value = label.getValue(); - if (value != null) { - title = value; + if (formInstance != null) { + FormContainer formContainer = formInstance.adaptTo(FormContainer.class); + List panelList = (List) getMultipleChildPanels(formContainer); + List panels = panelList.stream().filter(x -> "panel".equals(x.getFieldType())).collect(Collectors.toList()); + for (Base panel : panels) { + String name = panel != null ? panel.getName() : ""; + String title = ""; + if (panel != null) { + Label label = panel.getLabel(); + if (label != null) { + String value = label.getValue(); + if (value != null) { + title = value; + } } } - } - if (name != null && title != null) { - resources.add(getResourceForDropdownDisplay(resourceResolver, title, name)); + if (name != null && title != null) { + resources.add(getResourceForDropdownDisplay(resourceResolver, title, name)); + } } } } @@ -105,7 +107,14 @@ protected void doGet(@NotNull SlingHttpServletRequest request, @NotNull SlingHtt request.setAttribute(DataSource.class.getName(), actionTypeDataSource); } - private List getPanels(FormComponent formContainer) { + /** + * Retrieves a list of child panels that have at least two siblings. + * If a panel has fewer than two siblings, it will not be included in the returned list. + * + * @param formContainer the top-level form container + * @return a list of panels with at least two siblings + */ + private List getMultipleChildPanels(FormComponent formContainer) { while (formContainer instanceof Container && ((Container) formContainer).getItems().size() == 1) { formContainer = (FormComponent) ((Container) formContainer).getItems().get(0); } diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Review.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Review.java index 8d05ec74b8..060c71d4ee 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Review.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Review.java @@ -1,5 +1,5 @@ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - ~ Copyright 2023 Adobe + ~ 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. @@ -16,15 +16,28 @@ package com.adobe.cq.forms.core.components.models.form; import org.osgi.annotation.versioning.ConsumerType; +import com.fasterxml.jackson.annotation.JsonIgnore; /** * Defines the {@code Review} Sling Model used for the {@code /apps/core/fd/components/form/review} component. * - * @since com.adobe.cq.forms.core.components.models 2.1.0 + * @since com.adobe.cq.forms.core.components.models 5.9.5 */ @ConsumerType public interface Review extends Base { + + /** + * @return an array of linked panels to be reviewed on the review page. Each linked panel is the name of a panel that is linked to the + * review page. + * @since com.adobe.cq.forms.core.components.models.form 5.9.5 + */ + @JsonIgnore String[] getLinkedPanels(); - String getEditAction(); + /** + * @return the edit mode action, which indicates whether edit button is visible on the review page at field, panel, both, or none + * @since com.adobe.cq.forms.core.components.models.form 5.9.5 + */ + @JsonIgnore + String getEditModeAction(); } \ No newline at end of file diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/package-info.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/package-info.java index 2bd01360b5..e143716fa4 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/package-info.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/package-info.java @@ -35,7 +35,7 @@ *

*/ -@Version("5.9.5") +@Version("5.9.6") package com.adobe.cq.forms.core.components.models.form; import org.osgi.annotation.versioning.Version; diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/ReviewImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/ReviewImplTest.java index c2e1b10830..dfefa5c66f 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/ReviewImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/ReviewImplTest.java @@ -47,14 +47,14 @@ void setUp() throws Exception { @Test void testGetEditAction() { Review review = Utils.getComponentUnderTest(PATH_REVIEW, ReviewImpl.class, context); - assertEquals("field", review.getEditAction()); + assertEquals("field", review.getEditModeAction()); } @Test public void testGetLinkedPanelsWithNonNullArray() throws IOException { Review review = Utils.getComponentUnderTest(PATH_REVIEW, ReviewImpl.class, context); String[] linkedPanels = review.getLinkedPanels(); - String[] expectedLinkedPanels = context.resourceResolver().getResource(PATH_REVIEW).getValueMap().get("linkedPanels", + String[] expectedLinkedPanels = context.resourceResolver().getResource(PATH_REVIEW).getValueMap().get("fd:linkedPanels", String[].class); assertNotNull(expectedLinkedPanels); assertArrayEquals(expectedLinkedPanels, linkedPanels); @@ -73,7 +73,7 @@ void testGetProperties() { Review review = Utils.getComponentUnderTest(PATH_REVIEW, ReviewImpl.class, context); Map properties = review.getProperties(); assertEquals("/apps/formcontainer/wizard/panel2/review", properties.get("fd:path")); - assertEquals("field", properties.get("editAction")); + assertEquals("field", properties.get("fd:editModeAction")); } diff --git a/bundles/af-core/src/test/resources/form/review/datasource/test-content.json b/bundles/af-core/src/test/resources/form/review/datasource/test-content.json index ae6c02d0bb..54c50522e2 100644 --- a/bundles/af-core/src/test/resources/form/review/datasource/test-content.json +++ b/bundles/af-core/src/test/resources/form/review/datasource/test-content.json @@ -41,7 +41,7 @@ "name": "item_2", "sling:resourceType": "core/fd/components/form/panelcontainer/v1/panelcontainer", "review": { - "editAction": "field", + "fd:editModeAction": "field", "fieldType": "plain-text", "hideTitle": "false", "jcr:primaryType": "nt:unstructured", @@ -69,7 +69,7 @@ "name": "item_2", "sling:resourceType": "core/fd/components/form/panelcontainer/v1/panelcontainer", "review": { - "editAction": "field", + "fd:editModeAction": "field", "fieldType": "plain-text", "hideTitle": "false", "jcr:primaryType": "nt:unstructured", diff --git a/bundles/af-core/src/test/resources/form/review/test-content.json b/bundles/af-core/src/test/resources/form/review/test-content.json index 09e8d01364..3dc1d85acb 100644 --- a/bundles/af-core/src/test/resources/form/review/test-content.json +++ b/bundles/af-core/src/test/resources/form/review/test-content.json @@ -55,12 +55,12 @@ "fd:linkedPanels": [ "item_1" ], - "fd:editAction": "field" + "fd:editModeAction": "field" }, - "linkedPanels": [ + "fd:linkedPanels": [ "item_1" ], - "editAction": "field" + "fd:editModeAction": "field" } } } diff --git a/examples/ui.apps/src/main/content/jcr_root/apps/forms-components-examples/components/form/review/_cq_template.xml b/examples/ui.apps/src/main/content/jcr_root/apps/forms-components-examples/components/form/review/_cq_template.xml index b947400529..1eed759959 100644 --- a/examples/ui.apps/src/main/content/jcr_root/apps/forms-components-examples/components/form/review/_cq_template.xml +++ b/examples/ui.apps/src/main/content/jcr_root/apps/forms-components-examples/components/form/review/_cq_template.xml @@ -1,7 +1,7 @@ diff --git a/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/review/basic/.content.xml b/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/review/basic/.content.xml index f034c7a685..529f03f020 100644 --- a/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/review/basic/.content.xml +++ b/it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/review/basic/.content.xml @@ -371,10 +371,10 @@ jcr:primaryType="nt:unstructured" jcr:title="review" sling:resourceType="forms-components-examples/components/form/review" - editAction="field" + fd:editModeAction="field" fieldType="plain-text" hideTitle="false" - linkedPanels="tab1_id" + fd:linkedPanels="tab1_id" name="review1724402878089"/> diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/review/v1/review/README.md b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/review/v1/review/README.md index a51b9da11e..2aa2ce380a 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/review/v1/review/README.md +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/review/v1/review/README.md @@ -31,8 +31,8 @@ The following properties are written to JCR for this Form Review component and a 1. `./jcr:title` - defines the label to use for this field 2. `./hideTitle` - if set to `true`, the label of this field will be hidden 3. `./name` - defines the name of the field, which will be submitted with the form data -3. `./linkedPanels` - defines linked panels for reviewing the panel. If no panel is linked, the component will review the entire form. -3. `./editAction` - defines the edit action for editing the fields, panels, field & panel, or none +3. `./fd:linkedPanels` - defines linked panels for reviewing the panel. If no panel is linked, the component will review the entire form. +3. `./fd:editModeAction` - defines the edit action for editing the fields, panels, field & panel, or none ## Client Libraries The component provides a `core.forms.components.review.v1.runtime` client library category that contains the Javascript runtime for the component. It should be added to a relevant site client library using the `embed` property. @@ -44,11 +44,16 @@ JavaScript handling for dialog interaction. It is already included by its edit d ``` BLOCK cmp-adaptiveform-review ELEMENT cmp-adaptiveform-review__container - ELEMENT cmp-adaptiveform-review__panel - MODIFIER cmp-adaptiveform-review__panel--repeatable - ELEMENT cmp-adaptiveform-review__label-containe - ELEMENT cmp-adaptiveform-review__field - ELEMENT cmp-adaptiveform-review__label - ELEMENT cmp-adaptiveform-review__value - ELEMENT cmp-adaptiveform-review__edit-button + ELEMENT cmp-adaptiveform-review__panel + MODIFIER cmp-adaptiveform-review__panel--repeatable + ELEMENT cmp-adaptiveform-review__label-containe + ELEMENT cmp-adaptiveform-review__label + ELEMENT cmp-adaptiveform-review__edit-button + ELEMENT cmp-adaptiveform-review__value + ELEMENT cmp-adaptiveform-review__field + ELEMENT cmp-adaptiveform-review__label + ELEMENT cmp-adaptiveform-review__value + ELEMENT cmp-adaptiveform-review__edit-button + ELEMENT cmp-adaptiveform-review__text + ELEMENT cmp-adaptiveform-review__label ``` \ No newline at end of file diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/review/v1/review/_cq_dialog/.content.xml b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/review/v1/review/_cq_dialog/.content.xml index ada868c76c..b2de838672 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/review/v1/review/_cq_dialog/.content.xml +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/review/v1/review/_cq_dialog/.content.xml @@ -69,13 +69,13 @@ text="Hide title" uncheckedValue="false" value="true" /> - - + + /> diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/review/v1/review/clientlibs/site/js/reviewview.js b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/review/v1/review/clientlibs/site/js/reviewview.js index 6eda5840b9..edc13d3b83 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/review/v1/review/clientlibs/site/js/reviewview.js +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/review/v1/review/clientlibs/site/js/reviewview.js @@ -30,6 +30,7 @@ static bemBlock = 'cmp-adaptiveform-review'; static templateAttribute = 'data-cmp-review'; static DATA_ATTRIBUTE_VISIBLE = 'data-cmp-visible'; + static hideFieldFromReview = ['button', 'plain-text', 'captcha', 'image']; static selectors = { self: "[data-" + this.NS + '-is="' + this.IS + '"]', container: `.${Review.bemBlock}__container`, @@ -90,7 +91,7 @@ } static addAccessibilityAttributes(element, item) { - const container = element.querySelector('[' + Review.templateAttribute + '-container]'); + const container = element.querySelector('div'); const label = element.querySelector('[' + Review.templateAttribute + '-label]'); const value = element.querySelector('[' + Review.templateAttribute + '-value]'); const editButton = element.querySelector('[' + Review.templateAttribute + '-editButton]'); @@ -217,7 +218,8 @@ const currentFragment = document.createDocumentFragment(); items.filter(item => item.visible !== false && item.fieldType && item[':type']).forEach(item => { if (Review.isRepeatable(item)) { - const repeatablePanel = this.#renderReviewFields(item.items); + const repeatableItems = this.getModel().form.getElement(item.id).getState(); + const repeatablePanel = this.#renderReviewFields(repeatableItems.items); if (Review.hasChild(repeatablePanel)) { currentFragment.appendChild(repeatablePanel); } @@ -241,7 +243,7 @@ } currentFragment.appendChild(cloneNode); } - } else if (item.fieldType !== 'button' && item.fieldType !== 'plain-text' && !item[':type'].endsWith('review')) { + } else if (!Review.hideFieldFromReview.includes(item.fieldType) && !item[':type'].endsWith('review')) { Review.renderValue(cloneNode, item); Review.addAccessibilityAttributes(cloneNode, item); currentFragment.appendChild(cloneNode); @@ -261,7 +263,7 @@ // return all top lavel panels if author has not linked any panel #getAllPanels() { - let state = this.formContainer._model.getState(); + let state = this.getModel().form.getState(); while (state?.items?.length === 1) { state = state.items[0]; } @@ -271,7 +273,7 @@ // return linked panels if author has linked any panel #getLinkedPanels(linkedPanels) { let queue = [], result = []; - let state = this.formContainer._model.getState(); + let state = this.getModel().form.getState(); queue.push(state); while (queue.length && linkedPanels.length) { const items = Array.isArray(queue[0]) ? queue[0] : [queue[0]]; @@ -303,10 +305,10 @@ } } #isVisibleEditButton(fieldType) { - let editAction = this._model?._jsonModel?.properties?.editAction; - if (editAction === 'both' || - (editAction === 'panel' && fieldType === 'panel') || - (editAction === 'field' && fieldType !== 'panel')) { + let editModeAction = this._model?._jsonModel?.properties?.['fd:editModeAction']; + if (editModeAction === 'both' || + (editModeAction === 'panel' && fieldType === 'panel') || + (editModeAction === 'field' && fieldType !== 'panel')) { return true; } return false; diff --git a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/review/v1/review/template/fieldTemplate.html b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/review/v1/review/template/fieldTemplate.html index a1b26994e8..35ce3308e2 100644 --- a/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/review/v1/review/template/fieldTemplate.html +++ b/ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/review/v1/review/template/fieldTemplate.html @@ -15,7 +15,7 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/-->