Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -377,11 +377,15 @@ public Map<String, String> getRules() {
*/
protected final Map<String, String> getRulesForResource(Resource resource) {
String[] VALID_RULES = new String[] { "description", "enabled", "enum", "enumNames",
"exclusiveMaximum", "exclusiveMinimum", "label", "maximum", "minimum",
"exclusiveMaximum", "exclusiveMinimum", "label", "maximum", "minimum", "properties",
"readOnly", "required", "value", "visible" };

Predicate<Map.Entry<String, Object>> isRuleNameValid = obj -> Arrays.stream(VALID_RULES).anyMatch(validKey -> validKey.equals(obj
.getKey()));
// A rule target may be one of the fixed editable properties (which includes the whole
// `properties` bag), or a granular custom-variable target keyed `properties.<path>` (e.g.
// properties.employer or properties.employer.category) that the runtime routes to the
// PropertiesManager per key. Preserve both the bag and the per-key targets.
Predicate<Map.Entry<String, Object>> isRuleNameValid = obj -> obj.getKey().startsWith("properties.")
|| Arrays.stream(VALID_RULES).anyMatch(validKey -> validKey.equals(obj.getKey()));

Predicate<Map.Entry<String, Object>> isRuleValid = isEntryNonEmpty.and(isRuleNameValid);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public class AbstractFormComponentImplTest {
private static final String PATH_COMPONENT_WITH_NO_VALIDATION_STATUS = CONTENT_ROOT + "/datepicker2";
private static final String PATH_COMPONENT_WITH_INVALID_VALIDATION_STATUS = CONTENT_ROOT + "/datepicker3";
private static final String PATH_COMPONENT_WITH_NO_RULE = CONTENT_ROOT + "/numberinput";
private static final String PATH_COMPONENT_WITH_PROPERTIES_RULE = CONTENT_ROOT + "/textinputWithPropertiesRule";
private static final String PATH_COMPONENT_WITH_DISABLED_XFA_SCRIPTS = CONTENT_ROOT + "/xfacomponent";
private static final String PATH_COMPONENT_WITH_INVALID_XFA_SCRIPTS = CONTENT_ROOT + "/xfacomponentinvalid";
private static final String PATH_COMPONENT_WITH_NO_XFA_SCRIPTS = CONTENT_ROOT + "/xfacomponentnone";
Expand Down Expand Up @@ -147,6 +148,39 @@ public void testRulesExcludedWhenPublishViewAttributeSetOnAuthor() {
"fd:rules should not appear when publish view attribute is set even in author WCMMode");
}

@Test
public void testGranularPropertiesRulesPreserved() {
// A rule keyed `properties.<path>` is a granular custom-variable target routed by the
// runtime to the PropertiesManager; the exporter must not drop flat or nested ones.
AbstractFormComponentImpl abstractFormComponentImpl = prepareTestClass(PATH_COMPONENT_WITH_PROPERTIES_RULE);
Map<String, String> rules = abstractFormComponentImpl.getRules();
assertEquals("some property expression", rules.get("properties.employer"),
"flat properties.<key> rule should be preserved");
assertEquals("some nested property expression", rules.get("properties.employer.category"),
"nested properties.<a.b> rule should be preserved");
}

@Test
public void testBarePropertiesAndWhitelistedRulesPreserved() {
// The whole `properties` bag is an editable property, and standard whitelisted targets
// (e.g. visible) must keep working alongside the granular properties.<path> targets.
AbstractFormComponentImpl abstractFormComponentImpl = prepareTestClass(PATH_COMPONENT_WITH_PROPERTIES_RULE);
Map<String, String> rules = abstractFormComponentImpl.getRules();
assertEquals("some expression", rules.get("visible"));
assertEquals("merge($field.properties, {a: 1})", rules.get("properties"),
"the whole properties bag rule should be preserved");
}

@Test
public void testUnknownRulesDropped() {
// Keys that are neither whitelisted nor a genuine properties.<path> target are filtered
// out, including a `properties`-prefixed key without the dot separator.
AbstractFormComponentImpl abstractFormComponentImpl = prepareTestClass(PATH_COMPONENT_WITH_PROPERTIES_RULE);
Map<String, String> rules = abstractFormComponentImpl.getRules();
assertNull(rules.get("notARule"), "non-whitelisted, non-properties rule keys should be dropped");
assertNull(rules.get("propertiesFoo"), "a properties-prefixed key without a dot is not a valid target");
}

@Test
public void testIsAuthorModeUtility() {
assertFalse(ComponentUtils.isAuthorMode(null), "null request should not be author mode");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,21 @@
"sling:resourceType": "forms-components-examples/components/form/numberinput",
"fieldType": "number-input"
},
"textinputWithPropertiesRule": {
"jcr:primaryType": "nt:unstructured",
"name": "name",
"sling:resourceType": "forms-components-examples/components/form/textinput",
"fieldType": "text-input",
"fd:rules": {
"jcr:primaryType": "nt:unstructured",
"visible": "some expression",
"properties": "merge($field.properties, {a: 1})",
"properties.employer": "some property expression",
"properties.employer.category": "some nested property expression",
"notARule": "should be dropped",
"propertiesFoo": "should be dropped"
}
},
"datepicker": {
"jcr:primaryType": "nt:unstructured",
"name": "datepicker1666939496905",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,6 @@
longTitle="Field"
propertySheet="/mnt/overlay/fd/af/components/stylePropertySheet/common">
<items jcr:primaryType="nt:unstructured">
<widgetAndText
jcr:primaryType="nt:unstructured"
jcr:title="Widget and Text"
id="af2_basewidgetandtext"
cssSelector=".cmp-adaptiveform-container input,select,textarea"
longTitle="Field Widget and Text"
propertySheet="/mnt/overlay/fd/af/components/stylePropertySheet/common">
<states jcr:primaryType="nt:unstructured">
<focus
jcr:primaryType="nt:unstructured"
jcr:title="Focus"
cssSelector=".cmp-adaptiveform-container input:focus,select:focus,textarea:focus"/>
<disabled
jcr:primaryType="nt:unstructured"
jcr:title="Disabled"
cssSelector=".cmp-adaptiveform-container input:disabled,select:disabled,textarea:disabled"/>
<hover
jcr:primaryType="nt:unstructured"
jcr:title="Hover"
cssSelector=".cmp-adaptiveform-container input:hover,select:hover,textarea:hover"/>
<mandatory
jcr:primaryType="nt:unstructured"
jcr:title="Mandatory"
cssSelector=".cmp-adaptiveform-container input:required,select:required,textarea:required"/>
</states>
</widgetAndText>
<fieldLabel
jcr:primaryType="nt:unstructured"
jcr:title="Label"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,26 @@ This approach is implemented to optimize performance by avoiding additional netw
## BEM Description
```
BLOCK cmp-adaptiveform-container
MODIFIER cmp-adaptiveform-container--loading
MODIFIER cmp-adaptiveform-container--submitting
ELEMENT cmp-adaptiveform-container__wrapper
ELEMENT cmp-adaptiveform-container__hamburger-menu
ELEMENT cmp-adaptiveform-container__hamburger-menu-top
ELEMENT cmp-adaptiveform-container__hamburger-menu-icon-container
ELEMENT cmp-adaptiveform-container__hamburger-menu-icon
ELEMENT cmp-adaptiveform-container__hamburger-menu-middle
ELEMENT cmp-adaptiveform-container__hamburger-menu-bottom
ELEMENT cmp-adaptiveform-container__hamburger-menu-active-item-title
MODIFIER cmp-adaptiveform-container__hamburger-menu-button--prev
MODIFIER cmp-adaptiveform-container__hamburger-menu-button--next
ELEMENT cmp-adaptiveform-container__hamburger-menu-top
ELEMENT cmp-adaptiveform-container__hamburger-menu-icon-container
ELEMENT cmp-adaptiveform-container__hamburger-menu-icon
ELEMENT cmp-adaptiveform-container__hamburger-menu-middle
ELEMENT cmp-adaptiveform-container__hamburger-menu-bottom
ELEMENT cmp-adaptiveform-container__hamburger-menu-active-item-title
ELEMENT cmp-adaptiveform-container__hamburger-menu-navigation
MODIFIER cmp-adaptiveform-container__hamburger-menu-button--prev
MODIFIER cmp-adaptiveform-container__hamburger-menu-button--next
MODIFIER cmp-adaptiveform-container__hamburger-menu-button--open
MODIFIER cmp-adaptiveform-container__hamburger-menu-button--close
ELEMENT cmp-adaptiveform-container__hamburger-menu-dropdown
ELEMENT cmp-adaptiveform-container__hamburger-menu-submenu
ELEMENT cmp-adaptiveform-container__hamburger-menu-link
MODIFIER cmp-adaptiveform-container__hamburger-menu-item--active
MODIFIER cmp-adaptiveform-container__hamburger-menu-item--activeparent
```

In edit mode, the BEM structure includes a modifier for the cmp-adaptiveform-container block,
Expand Down
Loading
Loading