Goal
Give AEM admin the flexibility to add additional columns in Assets Omni Search List View - http://localhost:4502/assets.html
Thank you ACS Commons for the Generic Lists
For adding custom columns to Assets List View check this post
For adding custom columns to Reports Console check this post
For AEM 65 check this post
Demo | Package Install | Source Code | GitHub
Configure Columns
http://localhost:4502/etc/experience-aem/omni-search-columns.html
Custom Omni Search Columns
Solution
1) Create the extension nt:folder /apps/eaem-omni-search-dynamic-columns
2) Add the ACS Commons Generic List in nt:folder /apps/eaem-omni-search-dynamic-columns/components, /apps/eaem-omni-search-dynamic-columns/templates (available in Package Install if installing the extension)
3) Create OSGI servlet apps.experienceaem.omnisearch.MetadataResultsServlet with the following code, to get the custom column values; eg. http://localhost:4502/bin/eaem/metadataResults.json?paths=/content/dam/geometrixx/shapes/cir_circle.png,/content/dam/geometrixx/shapes/sq_cube.png
package apps.experienceaem.omnisearch; import org.apache.commons.lang3.StringUtils; import org.apache.felix.scr.annotations.sling.SlingServlet; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.SlingHttpServletResponse; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.api.resource.ValueMap; import org.apache.sling.api.servlets.SlingAllMethodsServlet; import org.apache.sling.commons.json.JSONArray; import org.apache.sling.commons.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.jcr.Node; import javax.jcr.RepositoryException; import javax.servlet.ServletException; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @SlingServlet(paths = "/bin/eaem/metadataResults", methods = "GET", metatype = true, label = "Experience AEM Metadata Results Servlet", extensions = "json") public class MetadataResultsServlet extends SlingAllMethodsServlet{ private static final Logger log = LoggerFactory.getLogger(MetadataResultsServlet.class); private static String OMNI_SEARCH_COL_CONFIG = "/etc/experience-aem/omni-search-columns/jcr:content/list"; @Override protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException { doPost(request, response); } @Override protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException { ResourceResolver resourceResolver = request.getResourceResolver(); try{ JSONObject jsonResponse = new JSONObject(); String paths = request.getParameter("paths"); if(StringUtils.isEmpty(paths)){ return; }else{ List<String> configList = getOmniSearchConfigValues(resourceResolver.getResource(OMNI_SEARCH_COL_CONFIG)); Resource resource, propResource; String parentPath, propName, propValue; JSONObject valueObj; for(String path : paths.split(",")){ resource = resourceResolver.getResource(path); if(resource == null){ continue; } valueObj = new JSONObject(); for(String relPath : configList){ parentPath = relPath.substring(0, relPath.lastIndexOf("/")); propName = relPath.substring(relPath.lastIndexOf("/") + 1); propResource = resource.getChild(parentPath); if(propResource == null){ continue; } propValue = propResource.adaptTo(ValueMap.class).get(propName, ""); valueObj.put(relPath, propValue); } jsonResponse.put(path, valueObj); } } jsonResponse.write(response.getWriter()); }catch(Exception e){ log.error("Error reading collections", e); } } public List<String> getOmniSearchConfigValues(Resource managedListResource) { List<String> configList = new ArrayList<String>(); try { Iterator<Resource> managedList = managedListResource.listChildren(); while (managedList.hasNext()) { Resource r = managedList.next(); Node resNode = r.adaptTo(Node.class); if (!resNode.hasProperty("value")) { continue; } configList.add(resNode.getProperty("value").getString()); } } catch (RepositoryException re) { log.error("Error getting list values", re); } return configList; } }
3) Create cq:ClientLibraryFolder /apps/eaem-omni-search-dynamic-columns/clientlib with categories dam.gui.admin.util and dependencies underscore
4) Create nt:file /apps/eaem-omni-search-dynamic-columns/clientlib/js.txt with the following content
dynamic-columns.js
5) Create nt:file /apps/eaem-omni-search-dynamic-columnss/clientlib/dynamic-columns.js with the following code
(function ($, $document) { var FOUNDATION_CONTENT_LOADED = "foundation-contentloaded", ROW_SELECTOR = "tr.foundation-collection-item", GRANITE_OMNI_SEARCH_RESULT = "#granite-omnisearch-result", COLUMN_LIST = "/etc/experience-aem/omni-search-columns/_jcr_content.list.json", COLUMN_CONFIG = {}, METADATA_MAPPING = "data-metadata-mapping", RESULTS_URL = "/bin/eaem/metadataResults.json", GRANITE_OMNI_SEARCH_CONTENT = ".granite-omnisearch-content"; loadColumnsConfiguration(); $document.on(FOUNDATION_CONTENT_LOADED, GRANITE_OMNI_SEARCH_CONTENT, function(event){ _.defer(function(){ handleContentLoad(event); }); }); function handleContentLoad(event){ var layout = $(GRANITE_OMNI_SEARCH_RESULT).data("foundationLayout"); if(!layout || (layout.layoutId !== "list")){ return; } addColumnHeaders(); fillColumnData(); } function fillColumnData(){ var $fui = $(window).adaptTo("foundation-ui"); $fui.wait(); $.ajax({ type: "POST", dataType: "json", url: RESULTS_URL, data: { paths: getPaths().join(",") } }).done(collectionIterate); function collectionIterate(data){ $(ROW_SELECTOR).each(function(index, item){ itemHandler(data, $(item) ); }); $fui.clearWait(); } function itemHandler(data, $row){ if(!_.isEmpty($row.find("[" + METADATA_MAPPING + "]"))){ return; } var itemPath = $row.data("foundation-collection-item-id"), metaValue; _.each(COLUMN_CONFIG, function(colName, colMetaPath){ metaValue = data[itemPath][colMetaPath] || ""; $row.append(getListCellHtml(colMetaPath, metaValue)); }); } } function getPaths(){ var paths = [], $item; $(ROW_SELECTOR).each(function(index, item){ $item = $(item); if(!_.isEmpty($item.find("td[" + METADATA_MAPPING + "]"))){ return; } paths.push($item.data("foundation-collection-item-id")); }); return paths; } function addColumnHeaders(){ if(checkIFHeadersAdded()){ return; } var headerHtml, $container = $(GRANITE_OMNI_SEARCH_CONTENT), $headRow = $container.find("thead > tr"); _.each(COLUMN_CONFIG, function(headerText, metaRelPath){ headerHtml = getTableHeader(metaRelPath, headerText); $headRow.append(headerHtml); }); } function checkIFHeadersAdded(){ return !_.isEmpty($(GRANITE_OMNI_SEARCH_CONTENT).find("tr").find("[" + METADATA_MAPPING + "]")); } function getListCellHtml(colMapping, colValue){ return '<td is="coral-td" class="coral-Table-cell coral-Table-cell--left" alignment="column" ' + METADATA_MAPPING + '="' + colMapping + '">' + '<coral-td-label class="coral-Table-cellLabel">' + colValue + '</coral-td-label>' + '</td>'; } function getTableHeader(colMapping, colText) { return '<th is="coral-th" ' + METADATA_MAPPING + '="' + colMapping + '">' + colText + '</th>'; } function loadColumnsConfiguration(){ $.ajax({ url: COLUMN_LIST }).done(function(data){ _.each(data, function(item){ COLUMN_CONFIG[item.value] = item.text; }) }); } })(jQuery, jQuery(document));
This comment has been removed by a blog administrator.
ReplyDeleteHi Could you please help me on how to customize the omnisearch based on the some custom properties.
ReplyDelete