AEM 65 - Touch UI Sort tags alphabetically in Tags Console

Goal


Sort tags alphabetically in Tags Console - http://localhost:4502/aem/tags

For sorting tags in picker check this post

Demo | Package Install | Github


Product (No Alpha Sort)



Extension (Alpha Sorted)



Solution


1) Create a Sling Filter to intercept request URIs starting with /libs/cq/tagging/gui/content/tags* and /libs/cq/tagging/gui/content/tags/jcr:content/views/column*, use a sling servlet request wrapper TagSortSlingServletRequestWrapper to return a sorted datasource iterator

package apps.experienceaem.tags;

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.wrappers.SlingHttpServletRequestWrapper;
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.Comparator;
import java.util.Iterator;
import java.util.List;

@Component(
        service = Filter.class,
        immediate = true,
        name = "Tags Console Sort Filter",
        property = {
                Constants.SERVICE_RANKING + ":Integer=-99",
                "sling.filter.scope=REQUEST",
                "sling.filter.pattern=((/libs/cq/tagging/gui/content/tags*)|(/libs/cq/tagging/gui/content/tags/jcr:content/views/column*))"
        }
)
public class TagsConsoleSortFilter implements Filter {
    public static String DATA_SOURCE_NAME = DataSource.class.getName();

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        chain.doFilter(new TagSortSlingServletRequestWrapper((SlingHttpServletRequest)request), response);
    }

    @Override
    public void destroy() {
    }

    private class TagSortSlingServletRequestWrapper extends SlingHttpServletRequestWrapper {
        public TagSortSlingServletRequestWrapper(final SlingHttpServletRequest request) {
            super(request);
        }

        @Override
        public Object getAttribute(String attrName) {
            if(!TagsConsoleSortFilter.DATA_SOURCE_NAME.equals(attrName)){
                return super.getAttribute(attrName);
            }

            DataSource ds = (DataSource)super.getAttribute(attrName);

            if(ds == null){
                return ds;
            }

            final List<Resource> sortedList = new ArrayList<Resource>();
            Iterator<Resource> items = ds.iterator();

            while(items.hasNext()){
                sortedList.add(items.next());
            }

            sortedList.sort(Comparator.comparing(Resource::getValueMap, (v1, v2) -> {
                return v1.get("jcr:title", "").compareTo(v2.get("jcr:title", ""));
            }));

            ds = new AbstractDataSource() {
                public Iterator<Resource> iterator() {
                    return sortedList.iterator();
                }
            };

            return ds;
        }
    }
}


2) To increase the limit (number of tags loaded in column view) from default 40, user overlay and play with /apps/cq/tagging/gui/content/tags/jcr:content/views/column@limit, /libs/cq/tagging/gui/content/tags/jcr:content/views/column/datasource@limit






3 comments:

  1. Thank you for this post, saved me a day or two of work :)

    ReplyDelete
  2. does this extensoion work in aem as a cloud service? i am having trouble uploading the package, it fails with an error stating "package contains application content that isnt supported at runtime"

    ReplyDelete
  3. Is there any way to sort the tags for the particular namespace.

    ReplyDelete