Expand my Community achievements bar.

Enhance your AEM Assets & Boost Your Development: [AEM Gems | June 19, 2024] Improving the Developer Experience with New APIs and Events
SOLVED

Folder change thumbnail customization

Avatar

Level 2

I have a requirement to select the thumbnail of folder from AEM /content/dam instead of local upload. I understand it currently is a file upload which stores the folder thumbnail in binary format under /folderThumbnail in the folder. I want to make the same functionality work by selecting the image from DAM and store the binary file inside the folder.

 

Screenshot 2024-05-23 at 5.39.36 PM.png

1 Accepted Solution

Avatar

Correct answer by
Level 9

Hi @aagarwal8192 ,

To customize the folder thumbnail functionality in Adobe Experience Manager (AEM) and allow users to select an image from the Digital Asset Management (DAM) instead of uploading a local image, you'll need to follow several steps. These include creating a custom component, modifying the folder thumbnail node structure, and implementing a servlet to handle the thumbnail selection and update process. Here’s a detailed guide on how to accomplish this:

Step 1: Create a Custom Component for Thumbnail Selection

  1. Overlay the Default Component:

    • First, overlay the default folder thumbnail component by copying it from /libs to /apps.
    • For example, if the original component is located at /libs/dam/gui/content/assets/folder, you can copy it to /apps/dam/gui/content/assets/folder.
  2. Modify the Overlayed Component:

    • In your new component, add a button or a field to trigger the DAM asset selection dialog.
    • Create a dialog with a pathfield to allow users to select an image from DAM

 

<!-- /apps/dam/gui/content/assets/folder/dialog/.content.xml -->
<jcr:root
    xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
    xmlns:cq="http://www.day.com/jcr/cq/1.0"
    jcr:primaryType="cq:Dialog"
    title="Folder Thumbnail"
    xtype="dialog">

    <items jcr:primaryType="cq:TabPanel">
        <items jcr:primaryType="cq:WidgetCollection">
            <imageTab
                jcr:primaryType="cq:Widget"
                xtype="panel"
                title="Thumbnail">
                <items jcr:primaryType="cq:WidgetCollection">
                    <thumbnailPath
                        jcr:primaryType="cq:Widget"
                        fieldLabel="Select Thumbnail"
                        name="./thumbnailPath"
                        xtype="pathfield"
                        rootPath="/content/dam"
                        allowUpload="false"
                        anchor="100%">
                    </thumbnailPath>
                </items>
            </imageTab>
        </items>
    </items>
</jcr:root>
​

 

Step 2: Create a Custom Servlet

  1. Create the Servlet:
    • Develop a Sling Servlet to handle the storage and update of the selected DAM asset as the folder thumbnail.

 

import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.apache.sling.api.servlets.SlingServletPaths;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ModifiableValueMap;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.propertytypes.ServiceDescription;

import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component(service = { Servlet.class })
@SlingServletPaths("/bin/updateFolderThumbnail")
@ServiceDescription("Servlet to update folder thumbnail from DAM asset")
public class FolderThumbnailServlet extends SlingAllMethodsServlet {

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String folderPath = request.getParameter("folderPath");
        String thumbnailPath = request.getParameter("thumbnailPath");

        ResourceResolver resourceResolver = request.getResourceResolver();
        Resource folderResource = resourceResolver.getResource(folderPath);

        if (folderResource != null) {
            ModifiableValueMap properties = folderResource.adaptTo(ModifiableValueMap.class);
            properties.put("thumbnailPath", thumbnailPath);
            resourceResolver.commit();
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Folder resource not found");
        }
    }
}
​



 

Step 3: Modify the Client-Side Code

  1. Override the Default Behavior:
    • Overlay the client-side JavaScript from /libs/dam/gui/content/assets/clientlibs/folder/js to /apps/dam/gui/content/assets/clientlibs/folder/js.
    • Modify the JavaScript to call the custom servlet and update the folder thumbnail.

 

(function(document, $) {
    $(document).on("click", ".cq-damadmin-admin-actions-change-thumbnail", function() {
        var folderPath = ...; // Get the folder path
        var dialog = new CQ.Dialog({
            title: "Select Thumbnail",
            items: [{
                xtype: "pathfield",
                fieldLabel: "Select Thumbnail",
                rootPath: "/content/dam",
                listeners: {
                    change: function(field, value) {
                        $.post("/bin/updateFolderThumbnail", {
                            folderPath: folderPath,
                            thumbnailPath: value
                        }).done(function() {
                            alert("Thumbnail updated successfully!");
                        }).fail(function() {
                            alert("Failed to update thumbnail.");
                        });
                    }
                }
            }]
        });
        dialog.show();
    });
})(document, Granite.$);
​

 

Summary

  1. Create a custom component with a pathfield for selecting the DAM asset.
  2. Develop a custom Sling Servlet to update the folder thumbnail property.
  3. Override and modify client-side JavaScript to handle the new functionality.

This process ensures the folder thumbnail can be updated using a DAM asset, providing a seamless experience within AEM. Adjust and refine the code snippets based on your specific AEM setup and requirements.



View solution in original post

6 Replies

Avatar

Level 9

Hi @aagarwal8192 ,

To customize the folder thumbnail functionality in AEM to select an image from DAM instead of a local upload, you can follow these general steps:

1. Create a custom component: Create a custom component that allows the user to select an image from DAM. You can use the Asset Finder component or create a custom component that uses the Asset Selector API to allow the user to select an image.

2. Store the binary file in the folder: Once the user selects an image, you can use the Sling POST Servlet to store the binary file in the folder. You can create a custom servlet that handles the POST request and saves the binary file to the /folderThumbnail node of the folder.

3. Update the folder thumbnail: After storing the binary file in the folder, you can update the folder thumbnail to use the new image. You can use the Asset Manager API to set the thumbnail property of the folder to the path of the new image.

Here's an example of how you can use the Sling POST Servlet to store the binary file in the folder:

```
@SlingServlet(
methods = { "POST" },
resourceTypes = { "sling/folder" },
selectors = { "thumbnail" },
extensions = { "jpg", "jpeg", "png", "gif" }
)
public class FolderThumbnailServlet extends SlingAllMethodsServlet {

@Override
protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
Resource folderResource = request.getResource();
Node folderNode = folderResource.adaptTo(Node.class);
Node thumbnailNode = JcrUtils.getNodeIfExists(folderNode, "folderThumbnail");

if (thumbnailNode == null) {
try {
thumbnailNode = folderNode.addNode("folderThumbnail", "nt:file");
Node contentNode = thumbnailNode.addNode("jcr:content", "nt:resource");
contentNode.setProperty("jcr:mimeType", "image/jpeg");
} catch (RepositoryException e) {
throw new ServletException("Failed to create folder thumbnail node", e);
}
}

InputStream inputStream = request.getInputStream();
Node contentNode = thumbnailNode.getNode("jcr:content");
Binary binary = contentNode.getSession().getValueFactory().createBinary(inputStream);
contentNode.setProperty("jcr:data", binary);
contentNode.setProperty("jcr:lastModified", Calendar.getInstance());
contentNode.getSession().save();

response.setStatus(HttpServletResponse.SC_OK);
}
}
```

In this example, we create a custom servlet that handles the POST request to store the binary file in the /folderThumbnail node of the folder. We check if the /folderThumbnail node exists, and if not, we create it. We then read the binary data from the request input stream and save it to the /folderThumbnail/jcr:content node as a binary property.

After storing the binary file in the folder, you can update the folder thumbnail to use the new image by setting the thumbnail property of the folder to the path of the new image. You can use the Asset Manager API to do this:

```
Resource folderResource = ...; // get the folder resource
String thumbnailPath = folderResource.getPath() + "/folderThumbnail/jcr:content";
AssetManager assetManager = folderResource.getResourceResolver().adaptTo(AssetManager.class);
assetManager.setThumbnail(folderResource.getPath(), thumbnailPath);
```

In this example, we get the folder resource and the path of the new thumbnail image. We then use the Asset Manager API to set the thumbnail property of the folder to the path of the new image.

Please note that this is just an example and may need to be customized to fit your specific requirements.

Avatar

Level 8

@aagarwal8192 

Can you share the use case you are trying to solve here?

This level of customization is not needed for a folder thumbnail which will not be utilized. 

Avatar

Level 2

@gkalyanI have a use case where the folders and thumbnails are already there and we need to migrate it to AEM. AEM OOTB gives a behavior of merging 3 assets and create one thumbnail. This need to be re written using the custom thumbnail which is already written and then using the the AEM pathfield feature to choose from AEM and then override the custom folderThumbnail.

Avatar

Level 2

@HrishikeshKa Do you have any pointers for custom component ? As I can see in the tree the change thumbnail is coming as part of node structure. I can overlay it in apps and then create another similar button or override the default behaviour of the current button in JS. But how do we show the pathfield dialog and call the servlet ?

Avatar

Correct answer by
Level 9

Hi @aagarwal8192 ,

To customize the folder thumbnail functionality in Adobe Experience Manager (AEM) and allow users to select an image from the Digital Asset Management (DAM) instead of uploading a local image, you'll need to follow several steps. These include creating a custom component, modifying the folder thumbnail node structure, and implementing a servlet to handle the thumbnail selection and update process. Here’s a detailed guide on how to accomplish this:

Step 1: Create a Custom Component for Thumbnail Selection

  1. Overlay the Default Component:

    • First, overlay the default folder thumbnail component by copying it from /libs to /apps.
    • For example, if the original component is located at /libs/dam/gui/content/assets/folder, you can copy it to /apps/dam/gui/content/assets/folder.
  2. Modify the Overlayed Component:

    • In your new component, add a button or a field to trigger the DAM asset selection dialog.
    • Create a dialog with a pathfield to allow users to select an image from DAM

 

<!-- /apps/dam/gui/content/assets/folder/dialog/.content.xml -->
<jcr:root
    xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
    xmlns:cq="http://www.day.com/jcr/cq/1.0"
    jcr:primaryType="cq:Dialog"
    title="Folder Thumbnail"
    xtype="dialog">

    <items jcr:primaryType="cq:TabPanel">
        <items jcr:primaryType="cq:WidgetCollection">
            <imageTab
                jcr:primaryType="cq:Widget"
                xtype="panel"
                title="Thumbnail">
                <items jcr:primaryType="cq:WidgetCollection">
                    <thumbnailPath
                        jcr:primaryType="cq:Widget"
                        fieldLabel="Select Thumbnail"
                        name="./thumbnailPath"
                        xtype="pathfield"
                        rootPath="/content/dam"
                        allowUpload="false"
                        anchor="100%">
                    </thumbnailPath>
                </items>
            </imageTab>
        </items>
    </items>
</jcr:root>
​

 

Step 2: Create a Custom Servlet

  1. Create the Servlet:
    • Develop a Sling Servlet to handle the storage and update of the selected DAM asset as the folder thumbnail.

 

import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.apache.sling.api.servlets.SlingServletPaths;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ModifiableValueMap;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.propertytypes.ServiceDescription;

import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component(service = { Servlet.class })
@SlingServletPaths("/bin/updateFolderThumbnail")
@ServiceDescription("Servlet to update folder thumbnail from DAM asset")
public class FolderThumbnailServlet extends SlingAllMethodsServlet {

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String folderPath = request.getParameter("folderPath");
        String thumbnailPath = request.getParameter("thumbnailPath");

        ResourceResolver resourceResolver = request.getResourceResolver();
        Resource folderResource = resourceResolver.getResource(folderPath);

        if (folderResource != null) {
            ModifiableValueMap properties = folderResource.adaptTo(ModifiableValueMap.class);
            properties.put("thumbnailPath", thumbnailPath);
            resourceResolver.commit();
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Folder resource not found");
        }
    }
}
​



 

Step 3: Modify the Client-Side Code

  1. Override the Default Behavior:
    • Overlay the client-side JavaScript from /libs/dam/gui/content/assets/clientlibs/folder/js to /apps/dam/gui/content/assets/clientlibs/folder/js.
    • Modify the JavaScript to call the custom servlet and update the folder thumbnail.

 

(function(document, $) {
    $(document).on("click", ".cq-damadmin-admin-actions-change-thumbnail", function() {
        var folderPath = ...; // Get the folder path
        var dialog = new CQ.Dialog({
            title: "Select Thumbnail",
            items: [{
                xtype: "pathfield",
                fieldLabel: "Select Thumbnail",
                rootPath: "/content/dam",
                listeners: {
                    change: function(field, value) {
                        $.post("/bin/updateFolderThumbnail", {
                            folderPath: folderPath,
                            thumbnailPath: value
                        }).done(function() {
                            alert("Thumbnail updated successfully!");
                        }).fail(function() {
                            alert("Failed to update thumbnail.");
                        });
                    }
                }
            }]
        });
        dialog.show();
    });
})(document, Granite.$);
​

 

Summary

  1. Create a custom component with a pathfield for selecting the DAM asset.
  2. Develop a custom Sling Servlet to update the folder thumbnail property.
  3. Override and modify client-side JavaScript to handle the new functionality.

This process ensures the folder thumbnail can be updated using a DAM asset, providing a seamless experience within AEM. Adjust and refine the code snippets based on your specific AEM setup and requirements.



Avatar

Level 2

@HrishikeshKa   Thanks for your entire solution. This clearly is the solution to my requirement. In the source code you mentioned its and EXTJS based dialog. Is it possible to achieve the same using Coral UI Pathfield ?