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