Goal
Add a new predicate to Assets Admin Search rail to filter assets based on the existence of metadata
Requirement could be to find all assets with specific metadata missing. Here a filter (predicate) is added to filter assets containing / not containing metadata property (configurable) jcr:content/metadata/dc:title
For 6430 add the workaround discussed at the end of this article...
To check for missing renditions or nodes check this post
Demo | Package Install | Github
Search Filter
Search form Configuration
Solution
1) Login to CRXDe Lite and create the metadata exists predicate configuration metadataexists in /apps/settings/dam/search/facets/formbuilderconfig/predicatetypes/items
<?xml version="1.0" encoding="UTF-8"?> <jcr:root 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="cq:Page"> <adminui/> <search jcr:primaryType="nt:unstructured"> <facets jcr:primaryType="nt:unstructured"> <formbuilderconfig jcr:primaryType="nt:unstructured"> <predicatetypes jcr:primaryType="nt:unstructured"> <items jcr:primaryType="nt:unstructured"> <metadataexists jcr:primaryType="nt:unstructured" fieldLabel="Metadata Property" fieldPropResourceType="/apps/eaem-search-form-metadata-exists-predicate/metadata-exists-field" fieldResourceType="/apps/eaem-search-form-metadata-exists-predicate/metadata-exists-predicate" fieldTitle="Experience AEM Metadata Exists Predicate" fieldViewResourceType="granite/ui/components/foundation/form/formbuilder/checkbox" renderType="checkbox"/> </items> </predicatetypes> </formbuilderconfig> </facets> </search> </jcr:root>
2) Create the configuration page for predicate (fieldPropResourceType in step 1) /apps/eaem-search-form-metadata-exists-predicate/metadata-exists-field/metadata-exists-field.jsp with the following code (metadataexists is for identifying the config page to render under /mnt/overlay/settings/dam/search/facets/formbuilderconfig/predicatetypes/items )
<%@include file="/libs/granite/ui/global.jsp" %> <%@ page session="false" contentType="text/html" pageEncoding="utf-8" import="com.adobe.granite.ui.components.Config" %> <% String key = resource.getName(); Config cfg = new Config(resource); String metaType = "metadataexists"; String listOrder = cfg.get("listOrder", String.class); listOrder = (listOrder == null) ? "" : listOrder; String fieldLabel = i18n.get("Metadata Exists Predicate"); %> <input type="hidden" name="<%= xssAPI.encodeForHTMLAttr("./items/" + key) %>"> <input type="hidden" name="<%= xssAPI.encodeForHTMLAttr("./items/" + key + "/jcr:primaryType") %>" value="nt:unstructured"> <input type="hidden" name="<%= xssAPI.encodeForHTMLAttr("./items/" + key + "/sling:resourceType") %>" value="/apps/eaem-search-form-metadata-exists-predicate/metadata-exists-predicate"> <input type="hidden" name="<%= xssAPI.encodeForHTMLAttr("./items/" + key + "/fieldLabel") %>" value="<%= fieldLabel %>"> <input type="hidden" name="<%= xssAPI.encodeForHTMLAttr("./items/" + key + "/metaType") %>" value="<%= metaType %>"> <input type="hidden" name="<%= xssAPI.encodeForHTMLAttr("./items/" + key + "/listOrder@Delete") %>"> <input type="hidden" name="<%= xssAPI.encodeForHTMLAttr("./items/" + key + "/listOrder@TypeHint") %>" value="String"> <input type="hidden" class="listOrder" name="<%= xssAPI.encodeForHTMLAttr("./items/" + key + "/listOrder") %>" value="<%= xssAPI.encodeForHTMLAttr(listOrder) %>"> <div><h3><%= i18n.get("Metadata Exists Predicate")%></h3></div> <% request.setAttribute ("com.adobe.cq.datasource.fieldtextplaceholder", i18n.get("Metadata Property"));%> <sling:include resource="<%= resource %>" resourceType="dam/gui/coral/components/admin/customsearch/formbuilder/predicatefieldproperties/fieldlabelpropertyfield"/> <sling:include resource="<%= resource %>" resourceType="dam/gui/coral/components/admin/customsearch/formbuilder/predicatefieldproperties/maptopropertyfield"/> <sling:include resource="<%= resource %>" resourceType="granite/ui/components/foundation/form/formbuilder/formfieldproperties/titlefields"/> <sling:include resource="<%= resource %>" resourceType="granite/ui/components/foundation/form/formbuilder/formfieldproperties/deletefields"/>
3) Create the predicate widget render html (fieldResourceType in step 1) /apps/eaem-search-form-metadata-exists-predicate/metadata-exists-predicate/metadata-exists-predicate.jsp with following code (it includes clientlib eaem.dam.admin.metadataexists)
<%@include file="/libs/granite/ui/global.jsp" %> <%@ page session="false" contentType="text/html" pageEncoding="utf-8" import="com.adobe.granite.ui.components.Config"%> <% Config cfg = new Config(resource); String metaPropName = cfg.get("name", ""); long predicateIndex = cfg.get("listOrder", 5000L); String indexGroup = predicateIndex + "_group"; String predicateName = indexGroup + ".property"; String propertyOperation = predicateName + ".operation"; boolean foldableOpen = cfg.get("open", true); String selected = foldableOpen ? "selected":""; %> <ui:includeClientLib categories="eaem.dam.admin.metadataexists" /> <coral-accordion variant="large"> <coral-accordion-item "<%=selected%>" data-metaType="checkboxgroup" data-type="metadataexists"> <coral-accordion-item-label><%= xssAPI.encodeForHTML(cfg.get("text", i18n.get("Property"))) %></coral-accordion-item-label> <coral-accordion-item-content class="coral-Form coral-Form--vertical" id="<%= xssAPI.encodeForHTMLAttr(resource.getPath()) %>"> <input type="hidden" name="<%=predicateName%>" value="<%= xssAPI.encodeForHTMLAttr(metaPropName) %>"> <coral-checkbox class="coral-Form-field eaem-metadata-exists-predicate" name="<%=propertyOperation%>" value="not"> Not Exists </coral-checkbox> <coral-checkbox class="coral-Form-field eaem-metadata-exists-predicate" name="<%=propertyOperation%>" value="exists"> Exists </coral-checkbox> </coral-accordion-item-content> </coral-accordion-item> </coral-accordion>
4) Create node /apps/eaem-search-form-metadata-exists-predicate/metadata-exists-predicate/clientlib of type cq:ClientLibraryFolder, add String property categories with value eaem.dam.admin.metadataexists, String[] property dependencies with value lodash
6) Create file (nt:file) /apps/eaem-search-form-metadata-exists-predicate/metadata-exists-predicate/clientlib/js.txt, add
metadata-exists.js
7) Create file (nt:file) /apps/eaem-search-form-metadata-exists-predicate/metadata-exists-predicate/clientlib/metadata-exists.js, add the following code
(function($, $document) { var EAEM_METADATA_EXISTS_PREDICATE = ".eaem-metadata-exists-predicate"; $document.on("change", EAEM_METADATA_EXISTS_PREDICATE, function(event) { $(EAEM_METADATA_EXISTS_PREDICATE).removeAttr("checked"); event.currentTarget.checked = true; var $form = $(this).closest(".granite-omnisearch-form"); $form.submit(); }) })(jQuery, jQuery(document));
6430 Solution
1) In addition to the above package install, add the following filter
package com.experienceaem.assets; import com.adobe.granite.ui.components.ds.AbstractDataSource; import com.adobe.granite.ui.components.ds.DataSource; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.api.resource.ResourceWrapper; import org.osgi.framework.Constants; import org.osgi.service.component.annotations.Component; import javax.servlet.*; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @Component( service = Filter.class, immediate = true, name = "Experience AEM Assets Search Facets Filter", property = { Constants.SERVICE_RANKING + ":Integer=-99", "sling.filter.scope=COMPONENT", "sling.filter.resourceTypes=cq/gui/components/common/admin/customsearch/facetconfiguration/facetconfigdatasource" } ) public class SearchFacetsFilter implements Filter { public static String DATA_SOURCE_NAME = DataSource.class.getName(); public static String ASSETS_SEARCH_FACETS_PATH = "/settings/dam/search/facets/assets"; public static String LIBS_ASSETS_SEARCH_FACETS_RT = "/libs/cq/gui/components/common/admin/customsearch/facetconfiguration/childfacetconfig"; @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { SlingHttpServletRequest sfrWrapper = (SlingHttpServletRequest)request; chain.doFilter(sfrWrapper, response); ResourceResolver resolver = sfrWrapper.getResourceResolver(); Resource assetsFacetsResource = resolver.getResource("/libs" + ASSETS_SEARCH_FACETS_PATH); if(assetsFacetsResource == null){ return; } DataSource ds = (DataSource)sfrWrapper.getAttribute(DATA_SOURCE_NAME); if(ds == null){ return; } final List<Resource> resultList = new ArrayList<Resource>(); Iterator<Resource> items = ds.iterator(); ResourceWrapper assetsFacetsResourceWrapper = new ResourceWrapper(assetsFacetsResource) { public String getResourceType() { return LIBS_ASSETS_SEARCH_FACETS_RT; } }; Resource resource = null; boolean exists = false; while(items.hasNext()){ resource = items.next(); if(resource.getPath().endsWith(ASSETS_SEARCH_FACETS_PATH)){ exists = true; } resultList.add(resource); } if(!exists && !resultList.isEmpty()){ resultList.add(assetsFacetsResourceWrapper); } ds = new AbstractDataSource() { public Iterator<Resource> iterator() { return resultList.iterator(); } }; sfrWrapper.setAttribute(DATA_SOURCE_NAME, ds); } @Override public void destroy() { } }
No comments:
Post a Comment