Goal
Add Asset Count, Size column to List view and Card view to show the count of assets and total size of a folder
Tested with AEM 63
For adding columns to Search Results check this post
For adding custom columns to Reports Console check this post
Demo | Package Install | Source Code | GitHub
Configuration & Column Visibility
List View
Card View
Solution
1) Create a servlet apps.experienceaem.assets.GetFolderSizeServlet for getting the assets count and size in folder with following code; sample call - http://localhost:4502/content/dam/experience-aem.size.json
package apps.experienceaem.assets; import com.day.cq.dam.api.Asset; 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.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.jcr.Node; import javax.jcr.NodeIterator; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.query.Query; import javax.jcr.query.QueryManager; import javax.servlet.ServletException; import java.util.Iterator; import java.util.Map; @SlingServlet( label = "Experience AEM - Folder Size Servlet", description = "Experience AEM - Servlet to return folder size", resourceTypes = { "sling:OrderedFolder", "sling:Folder" }, selectors = { GetFolderSizeServlet.SEL_FOLDER_SIZE }, methods = "GET") public class GetFolderSizeServlet extends SlingAllMethodsServlet { private static final Logger log = LoggerFactory.getLogger(GetFolderSizeServlet.class); public static final String SEL_FOLDER_SIZE = "size"; @Override protected void doGet(final SlingHttpServletRequest request, final SlingHttpServletResponse response) throws ServletException { response.setContentType("application/json"); response.setCharacterEncoding("utf-8"); String folderPath = request.getRequestPathInfo().getResourcePath(); try{ String stmt = "SELECT * FROM [dam:Asset] WHERE ISDESCENDANTNODE('" + folderPath + "')"; ResourceResolver resolver = request.getResourceResolver(); QueryManager qm = getQueryManager(request); JSONObject folderJSON = getFolderMapJSON(resolver.getResource(folderPath)); JSONObject sizeObj = null; Query query = qm.createQuery(stmt, Query.JCR_SQL2); NodeIterator results = query.execute().getNodes(); Node node = null; Asset asset = null; Long totalSize = 0L, size; Integer totalAssets = 0, countedAssets = 0; String superParentPath; while (results.hasNext()) { node = results.nextNode(); superParentPath = getSuperParentPath(folderPath, node); if(!folderJSON.has(superParentPath)){ continue; } sizeObj = (JSONObject) folderJSON.get(superParentPath); totalSize = (Long)sizeObj.get("size"); totalAssets = (Integer)sizeObj.get("totalAssets"); countedAssets = (Integer)sizeObj.get("countedAssets"); asset = resolver.getResource(node.getPath()).adaptTo(Asset.class); if(asset.getMetadata("dam:size") instanceof Long){ size = (Long)asset.getMetadata("dam:size"); countedAssets++; totalSize = totalSize + size; } totalAssets++; sizeObj.put("size", totalSize); sizeObj.put("totalAssets", totalAssets); sizeObj.put("countedAssets", countedAssets); } response.getWriter().print(folderJSON); }catch(Exception e){ log.error("Error getting size for - " + folderPath, e); } } private String getSuperParentPath(String folderPath, Node node) throws Exception{ String assetPath = node.getPath(); if(node.getParent().getPath().equals(folderPath)){ return folderPath; } return folderPath + "/" + assetPath.substring(folderPath.length() + 1, assetPath.indexOf("/", folderPath.length() + 1)); } private JSONObject getFolderMapJSON(Resource folderResource) throws Exception{ Iterator<Resource> childrenItr = folderResource.listChildren(); Resource child = null; JSONObject folderJSON = new JSONObject(); while(childrenItr.hasNext()){ child = childrenItr.next(); if(child.isResourceType("sling:OrderedFolder") || child.isResourceType("sling:Folder")){ folderJSON.put(child.getPath(), getSizeObj()); } } return folderJSON; } private JSONObject getSizeObj() throws Exception{ JSONObject sizeObj = new JSONObject(); Long totalSize = 0L, size; Integer totalAssets = 0, countedAssets = 0; sizeObj.put("totalAssets", totalAssets); sizeObj.put("countedAssets", countedAssets); sizeObj.put("size", totalSize); return sizeObj; } private QueryManager getQueryManager(SlingHttpServletRequest request)throws Exception { ResourceResolver resolver = request.getResourceResolver(); Session session = resolver.adaptTo(Session.class); return session.getWorkspace().getQueryManager(); } }
2) To add the necessary columns (here eaemAssetsCount) overlay /libs/dam/gui/content/commons/availablecolumns and create /apps/dam/gui/content/commons/availablecolumns
3) Create nt:unstructured node /apps/dam/gui/content/commons/availablecolumns/eaemAssetsCount with the following properties
<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" jcr:primaryType="nt:unstructured"> <eaemAssetsCount jcr:primaryType="nt:unstructured" jcr:title="Assets Count, Size" columnGroup="Experience AEM" default="{Boolean}false" sortable="{Boolean}true" sortType="number"/> </jcr:root>
4) To add dynamic content (Asset count, size) to the column, create clientlib /apps/eaem-touchui-assets-folder-size/clientlib with JS logic and categories - dam.gui.admin.util, dependencies - underscore executed on view load
5) Create nt:file /apps/eaem-touchui-assets-folder-size/clientlib/js.txt with the following content
asset-count.js
6) Create nt:file /apps/eaem-touchui-assets-folder-size/clientlib/asset-count.js, add the following code
(function ($, $document) { "use strict"; var firstLoad = true, COOKIE_AEM_ASSETS_LIST_VIEW_COLUMNS = "aem.assets.listview.columns", EAEM_ASSETS_COUNT = "eaemAssetsCount", LAYOUT_COL_VIEW = "column", LAYOUT_LIST_VIEW = "list", LAYOUT_CARD_VIEW = "card", DIRECTORY = "directory", FOUNDATION_CONTENT_LOADED = "foundation-contentloaded", SEL_DAM_ADMIN_CHILD_PAGES = ".cq-damadmin-admin-childpages", DIR_CELL_HTML = '<td is="coral-td" class="coral-Table-cell coral-Table-cell--left" alignment="column">' + '<coral-td-label class="coral-Table-cellLabel">Total Count: ASSET_COUNT, Size: ASSETS_SIZE</coral-td-label>' + '</td>', LIST_CELL_HTML = '<td is="coral-td" class="coral-Table-cell coral-Table-cell--left" alignment="column">' + '<coral-td-label class="coral-Table-cellLabel"></coral-td-label>' + '</td>'; $document.on(FOUNDATION_CONTENT_LOADED, SEL_DAM_ADMIN_CHILD_PAGES, addAssetCount); $document.on("cui-contentloaded", function (e) { if(!firstLoad){ return; } var $childPages = $(e.currentTarget).find(SEL_DAM_ADMIN_CHILD_PAGES); if(_.isEmpty($childPages)){ return; } firstLoad = false; $childPages.trigger(FOUNDATION_CONTENT_LOADED); }); function isFolderCountEnabled(){ var cookies = document.cookie.split(";"), tokens, isEnabled = false; _.each(cookies, function(cookie){ tokens = cookie.split("="); if(tokens[0].trim() !== COOKIE_AEM_ASSETS_LIST_VIEW_COLUMNS){ return; } isEnabled = tokens[1].trim().indexOf(EAEM_ASSETS_COUNT) > 0; }); return isEnabled; } function addAssetCount(e) { if(!e.currentTarget || !isFolderCountEnabled()){ return; } var $currentTarget = $(e.currentTarget), foundationLayout = $currentTarget.data("foundation-layout"); if(_.isEmpty(foundationLayout)){ return; } var layoutId = foundationLayout.layoutId; if(layoutId == LAYOUT_COL_VIEW){ return; } var path = $currentTarget.data("foundation-collection-id"); $.ajax(path + ".size.json").done(function(data){ var $dragHandles = $(".cq-damadmin-admin-childpages .coral-Icon--dragHandle"); if(_.isEmpty($dragHandles) || ($dragHandles.closest("td").css("display") == "none")){ //adjust UI removing drag handle column header $(".cq-damadmin-admin-childpages thead th:last").prev().remove(); } $(".foundation-collection-item").each(function(index, item){ itemHandler(data, layoutId, $(item) ); }); }); function itemHandler(data, layoutId, $item){ var itemPath = $item.data("foundation-collection-item-id"), isFolder; var sizeObj = data[itemPath], size = "0 MB", notExact, totalAssets, html; if(!_.isEmpty(sizeObj)){ notExact = (sizeObj["totalAssets"] !== sizeObj["countedAssets"]); if(sizeObj["size"] !== "0"){ size = (notExact ? "~" : "") + ((parseFloat(sizeObj["size"]) / (1024 * 1024))).toFixed(2) + " MB"; } } if(layoutId == LAYOUT_LIST_VIEW){ isFolder = $item.data("item-type") == DIRECTORY; if(!isFolder){ html = LIST_CELL_HTML; }else{ html = DIR_CELL_HTML.replace("ASSET_COUNT", sizeObj["totalAssets"]).replace("ASSETS_SIZE", size); } $item.append(html); }else if(layoutId == LAYOUT_CARD_VIEW){ var $itemMeta = $item.find(".foundation-collection-assets-meta"), $cardTitle; isFolder = $itemMeta.data("foundation-collection-meta-type") == DIRECTORY; if(!isFolder){ return; } $cardTitle =$item.find("coral-card-content > coral-card-title"); $cardTitle.html($cardTitle.html() + " - Assets: " + sizeObj["totalAssets"] + ", " + size); } } function getStringAfterLastSlash(str){ if(!str || (str.indexOf("/") == -1)){ return ""; } return str.substr(str.lastIndexOf("/") + 1); } } })(jQuery, jQuery(document));
No comments:
Post a Comment