Goal
Just a simple component extending Asset Share Commons Date Filter - https://adobe-marketing-cloud.github.io/asset-share-commons/pages/search/date-range/
Provides a text box to enter query builder relativedaterange lowerBound - https://helpx.adobe.com/experience-manager/6-5/sites/developing/using/querybuilder-predicate-reference.html#relativedaterange
Demo | Package Install | Github
Configuration
Rendering
Solution
1) Create component dialog /apps/eaem-asset-share-date-filter/date-range/cq:dialog by extending the Asset Share Commons Date Filter dialog asset-share-commons/components/search/date-range and use render conditions granite:rendercondition to not display unnecessary tabs
<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:granite="http://www.adobe.com/jcr/granite/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" jcr:primaryType="nt:unstructured" jcr:title="Date Range Filter" sling:resourceType="cq/gui/components/authoring/dialog" extraClientlibs="[core.wcm.components.form.options.v1.editor,asset-share-commons.author.dialog]"> <content granite:class="cmp-options--editor-v1" jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/container"> <items jcr:primaryType="nt:unstructured"> <options jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns" margin="{Boolean}true"> <items jcr:primaryType="nt:unstructured"> <columns jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/container"> <items jcr:primaryType="nt:unstructured"> <dialog granite:class="foundation-layout-util-vmargin" jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/container"> <items jcr:primaryType="nt:unstructured"> <tabs jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/tabs" maxmized="{Boolean}true"> <items jcr:primaryType="nt:unstructured"> <tab1 jcr:primaryType="nt:unstructured" jcr:title="Filter" sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns" margin="{Boolean}true"> <items jcr:primaryType="nt:unstructured"> <column jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/container"> <items jcr:primaryType="nt:unstructured"> <title jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/textfield" fieldDescription="Legend to describe the role of the field." fieldLabel="Title" name="./jcr:title" required="{Boolean}true"/> <property jcr:primaryType="nt:unstructured" sling:orderBefore="name" sling:resourceType="granite/ui/components/coral/foundation/form/select" fieldDescription="The name of the field, which is submitted with the form data." fieldLabel="Date Property" metadataFieldTypes="[datetime]" name="./property" required="{Boolean}true"> <datasource jcr:primaryType="nt:unstructured" sling:resourceType="asset-share-commons/data-sources/filterable-properties"/> </property> <expanded jcr:primaryType="nt:unstructured" sling:orderBefore="name" sling:resourceType="granite/ui/components/coral/foundation/form/checkbox" fieldDescription="Select if the field set should start in an expanded state (not applicable for drop down)" name="./expanded" text="Start expanded" value="true"/> <date-types jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/hidden"/> </items> </column> </items> </tab1> <search-behavior-tab jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/hidden"> <granite:rendercondition jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/renderconditions/simple" expression="false"/> </search-behavior-tab> </items> </tabs> </items> </dialog> </items> </columns> </items> </options> </items> </content> </jcr:root>
2) Create a use api class apps.experienceaem.assets.EAEMDatePredicate for reading the dialog data in HTL file
package apps.experienceaem.assets; import com.adobe.aem.commons.assetshare.util.PredicateUtil; import com.adobe.cq.sightly.WCMUsePojo; import com.day.cq.search.eval.DateRangePredicateEvaluator; import org.apache.commons.lang3.StringUtils; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceUtil; import org.apache.sling.api.resource.ValueMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class EAEMDatePredicate extends WCMUsePojo { private static final Logger log = LoggerFactory.getLogger(EAEMDatePredicate.class); private static final String REQUEST_ATTR_FORM_ID_TRACKER = "asset-share-commons__form-id"; private static final String COMPONENT_NAME_IN_PAGE = "date_range"; private static final int INITIAL_GROUP_NUM = 99999; private ValueMap resourceProps; private String property; private int group; @Override public void activate() { Resource resource = getResource(); resourceProps = ResourceUtil.getValueMap(resource); property = resourceProps.get("property", ""); group = INITIAL_GROUP_NUM; String compName = COMPONENT_NAME_IN_PAGE + "_"; String resName = resource.getName(); if(resName.contains(compName)) { group = Integer.parseInt(resName.substring(resName.lastIndexOf("_") + 1)); } } public boolean isReady() { return StringUtils.isNotEmpty(property); } public String getTitle() { return resourceProps.get("jcr:title", ""); } public String getGroup() { return group + "_group"; } public String getName() { return "relativedaterange"; } public String getProperty() { return property; } public boolean isExpanded() { return Boolean.valueOf(resourceProps.get("expanded", "false")); } public String getFormId() { SlingHttpServletRequest request = getRequest(); if (request.getAttribute(REQUEST_ATTR_FORM_ID_TRACKER) == null) { request.setAttribute(REQUEST_ATTR_FORM_ID_TRACKER, 1); } return REQUEST_ATTR_FORM_ID_TRACKER + "__" + String.valueOf(request.getAttribute(REQUEST_ATTR_FORM_ID_TRACKER)); } public String getLowerBoundName() { return getName() + "." + DateRangePredicateEvaluator.LOWER_BOUND; } public String getInitialLowerBound() { return PredicateUtil.getParamFromQueryParams(getRequest(), getGroup() + "." + getLowerBoundName()); } public String getId() { SlingHttpServletRequest request = getRequest(); return "cmp-date-filter" + "_" + String.valueOf(request.getResource().getPath().hashCode()); } }
3) Create the component rendering HTL script /apps/eaem-asset-share-date-filter/date-range/date-range.html with the following code
<sly data-sly-use.predicate="apps.experienceaem.assets.EAEMDatePredicate" data-sly-use.placeholderTemplate="core/wcm/components/commons/v1/templates.html" data-sly-test.ready="${predicate.ready}"> <input type="hidden" form="${predicate.formId}" name="${predicate.group}.${predicate.name}.property" value="${predicate.property}" data-asset-share-predicate-id="${predicate.id}"/> <div class="ui form"> <div class="ui fluid styled accordion field"> <div class="${predicate.expanded ? 'active' : ''} title right"> <i class="dropdown icon"></i> ${predicate.title} </div> <div class="${predicate.expanded ? 'active' : ''} content field" data-asset-share-id="${predicate.id}__fields"> Units of time <span style="margin-left: 10px ;font-size: 12px"> e.g. <b>-2m</b> = past 2 minutes | <b>-3h</b> = past 3 hours | <b>-4d</b> = past 4 days | <b>-5M</b> = past 5 months | <b>-6y</b> = past 6 years </span> <div style="margin-top: 10px"> <input type="text" style="width: 60%" value="${predicate.initialLowerBound}" form="${predicate.formId}" maxlength="9" for="${predicate.id}" name="${predicate.group}.${predicate.name}.lowerBound"/> </div> </div> <div class="active content field"> </div> </div> </div> </sly> <sly data-sly-call="${placeholderTemplate.placeholder @ isEmpty=!ready}"></sly>
Relative Date Range Predicate Extension
The following predicate creates XPath expression for days in the past (assuming user enters only a number eg. 30 = -30d = 30 days in the past) 0 means today (logic calculates hours from 00:00)
package com.experienceaem.assets; import com.day.cq.search.Predicate; import com.day.cq.search.eval.EvaluationContext; import com.day.cq.search.eval.RelativeDateRangePredicateEvaluator; import org.apache.commons.lang3.StringUtils; import org.osgi.service.component.annotations.Component; import java.util.Calendar; @Component( factory = "com.day.cq.search.eval.PredicateEvaluator/eaemrelativedaterange" ) public class LowerBoundPredicateEvaluator extends RelativeDateRangePredicateEvaluator { public String getXPathExpression(Predicate predicate, EvaluationContext context) { String value = predicate.get("lowerBound"); if(StringUtils.isEmpty((value))){ return super.getXPathExpression(predicate, context); } value = value.trim(); if(value.equals("0")){//for today, get hours from midnight Calendar rightNow = Calendar.getInstance(); predicate.set("lowerBound", "-" + rightNow.get(Calendar.HOUR_OF_DAY) + "h"); }else{ predicate.set("lowerBound", "-" + value + "d"); } return super.getXPathExpression(predicate, context); } }
No comments:
Post a Comment