AEM 6510 - Assets Bulk Update Editor Remove Tags (or values added using Coral 3 Autocomplete)

Goal


Assets Bulk Update Editor provides Append option for adding Multi-valued data (like cq:tags)

This post extends the editor and provides an option to remove previously selected values

Demo | Package Install | Github


Product



Extension



Solution


1) Login to CRXDE Lite (http://localhost:4502/crx/de), create folder /apps/eaem-bulk-update-remove-tags

2) Create node /apps/eaem-bulk-update-remove-tags/clientlib of type cq:ClientLibraryFolder, add String property categories with value dam.gui.coral.metadataeditor, String[] property dependencies with value lodash

3) Create file (nt:file) /apps/eaem-bulk-update-remove-tags/clientlib/js.txt, add

                        bulk-update-remove-tags.js

4) Create file (nt:file) /apps/eaem-bulk-update-remove-tags/clientlib/bulk-update-remove-tags.js, add the following code for extending autocomplete in metadata editor and provide the Remove selected tags checkbox (when checked sends the parameter suffixed with eaem-remove e.g. cq:tags-eaem-remove read by the sling post processor in step 5)

(function($, $document) {
    var extended = false,
        FOUNDATION_SELECTIONS_CHANGE = "foundation-selections-change",
        FOUNDATION_CONTENT_LOADED = "foundation-contentloaded",
        DAM_ADMIN_CHILD_PAGES_SEL = ".cq-damadmin-admin-childpages",
        REMOVE_EAEM_CB_SUFFIX = "-eaem-remove";

    $document.on(FOUNDATION_CONTENT_LOADED, addRemoveTags);

    $document.on(FOUNDATION_SELECTIONS_CHANGE, DAM_ADMIN_CHILD_PAGES_SEL , showHideRemoveCheckbox);

    function showHideRemoveCheckbox(event){
        var $collection = $(event.target),
            selectApi = $collection.adaptTo("foundation-selections"),
            count = selectApi.count(),
            $acFields = $("foundation-autocomplete"), $removeCB, $acField;

        _.each($acFields, function(acField){
            $acField = $(acField);

            $removeCB = getRemoveCheckBox($acField);

            if(count === 1){
                $removeCB.attr("disabled", "disabled");
            }else{
                $removeCB.removeAttr("disabled").removeAttr("checked");
            }
        });
    }

    function addRemoveTags(){
        if(extended){
            return;
        }

        var $acFields = $("foundation-autocomplete"), $acField,
            $removeCB, cbName;

        if(_.isEmpty($acFields)){
            return;
        }

        _.each($acFields, function(acField){
            $acField = $(acField);

            cbName = $acField.attr("name") + REMOVE_EAEM_CB_SUFFIX;

            if(!_.isEmpty(getRemoveCheckBox($acField))){
                return;
            }

            $removeCB = $(getRemoveHtml(cbName)).insertBefore($acField);
        });
    }

    function getRemoveCheckBox($acField){
        var cbName = $acField.attr("name") + REMOVE_EAEM_CB_SUFFIX;

        return $acField.prev("[name='" + cbName + "']");
    }

    function getRemoveHtml(cbName){
        return '<coral-checkbox class="coral-Form-field" name="' + cbName + '" value="true">Remove selected tags</coral-checkbox>';
    }
})(jQuery, jQuery(document));


5) Add a Sling Post Processor apps.experienceaem.assets.EAEMBulkUpdateRemovePostProcessor for reading eaem-remove parameters and remove selected values

package apps.experienceaem.assets;

import org.apache.commons.lang.ArrayUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.request.RequestParameter;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.servlets.post.Modification;
import org.apache.sling.servlets.post.SlingPostProcessor;
import org.json.JSONObject;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;

import javax.jcr.*;
import java.util.*;

@Component(
        immediate = true,
        service = { SlingPostProcessor.class },
        property = {
                Constants.SERVICE_RANKING + ":Integer=-99"
        }
)
public class EAEMBulkUpdateRemovePostProcessor implements SlingPostProcessor {
    private static final String MODE = "mode";
    private static final String MODE_SOFT = "soft";
    private static final String BULK_UPDATE = "dam:bulkUpdate";
    private static final String EAEM_REMOVE_SUFFIX = "-eaem-remove";

    public void process(SlingHttpServletRequest request, List<Modification> modifications) throws Exception {
        ResourceResolver resolver = request.getResourceResolver();
        String reqType = request.getParameter(BULK_UPDATE);
        String reqMode = request.getParameter(MODE);

        if ((reqType == null) || (reqMode == null) || !reqMode.equals(MODE_SOFT)) {
            return;
        }

        Session session = resolver.adaptTo(Session.class);
        RequestParameter[] assets = request.getRequestParameters("asset");

        if ( (session == null) || (assets == null)) {
            return;
        }

        session.refresh(true);

        Map<String, String[]> removalMap = getValuesForRemoval(request);

        if(removalMap.isEmpty()){
            return;
        }

        for (RequestParameter asset : assets) {
            JSONObject assetJson = new JSONObject(asset.toString());

            processChanges(session, assetJson, removalMap);
        }

        session.save();
    }

    private Map<String, String[]> getValuesForRemoval(SlingHttpServletRequest request){
        Map<String, String[]> removalMap = new HashMap<String, String[]>();

        Map<String, String[]> params = request.getParameterMap();
        String removeKey = null;
        String[] removeValues = null;

        for(String param : params.keySet()){
            if(!param.endsWith(EAEM_REMOVE_SUFFIX)) {
                continue;
            }

            removeKey = param.substring(0, param.lastIndexOf(EAEM_REMOVE_SUFFIX));

            removeValues = params.get(removeKey);

            if(removeValues == null){
                continue;
            }

            removalMap.put(removeKey.substring(removeKey.lastIndexOf("/") + 1), removeValues);
        }

        return removalMap;
    }

    private void processChanges(Session session, JSONObject assetJson, Map<String, String[]> removalMap)
                        throws Exception{
        String assetPath = assetJson.getString("path");
        String metadataPath = assetPath + "/jcr:content/metadata";

        Node metadataNode = session.getNode(metadataPath);
        String removePropertyName;
        Property property;

        for(String removeKey : removalMap.keySet()){
            if(!metadataNode.hasProperty(removeKey)){
                continue;
            }

            property = metadataNode.getProperty(removeKey);

            if(!property.isMultiple()){
                continue;
            }

            Value values[] = getNewValues(property.getValues(), Arrays.asList(removalMap.get(removeKey)));

            if(ArrayUtils.isEmpty(values)){
                property.remove();
            }else{
                metadataNode.setProperty(removeKey, values);
            }

            removePropertyName = removeKey + EAEM_REMOVE_SUFFIX;

            if(metadataNode.hasProperty(removePropertyName)){
                metadataNode.getProperty(removePropertyName).remove();
            }
        }
    }

    private Value[] getNewValues(Value[] oldValues, List<String> removeValues) throws Exception{
        List<Value> newValues = new ArrayList<Value>();

        for(Value value : oldValues){
            if(removeValues.contains(value.getString())){
                continue;
            }

            newValues.add(value);
        }

        return newValues.toArray(new Value[newValues.size()]);
    }
}

No comments:

Post a Comment