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