How to add tagging capability during Drag and Drop How to add tagging capability during drag'n'drop

Here's a question that comes back often, asked by bruce: How to add tag capability during drag'n'drop?. Since Thierry added HTML5 drag'n'drop to the Nuxeo Platform, it's possible to fill in metadata right after the import, and apply them to all the imported documents. But I understand it can be frustrating not being able to add tags. And fortunately the drag'n'drop service for content capture is extensible. The full code sample is available on GitHub.

So here's how it works. When dragging files in a content view for at least 2 seconds, you'll be prompted with a Select import operation choice. Those select operations are actually actions. It means you can add as any as you want through the action extension point. These actions have a specific behavior.

The ID of the action must, for instance, be the ID of the operation or the operation chain that will be executed when dropping the files. The link will display an iFrame itself displaying the layout passed as query parameter (layout=dndTagsEdit). The schema query parameter (schema=dc) is used to specify which schema you need to update with the chosen layout. Take a look at the documentation for the other specificities of those actions.

<?xml version="1.0"?>
<component name="org.nuxeo.sample.dnd.actions.contrib">

<require>org.nuxeo.ecm.platform.actions</require>

<extension target="org.nuxeo.ecm.platform.actions.ActionService"
point="actions">

<action id="Chain.FileManager.ImportWithMetaDataAndTagsInSeam"
link="${org.nuxeo.ecm.contextPath}/dndFormCollector.faces?schema=dc&#038;layout=dndTagsEdit"
order="30" label="label.smart.import.with.mdTags"
help="desc.smart.import.with.md.mdTags">
<category>ContentView</category>
<filter-id>create</filter-id>
</action>

</extension>

</component>


There are two things different from the classic import with metadata: the layout and the operation chain. The operation chain as an intermediate operation called Document.TagDocument. It's responsible for the actual tagging of every document.

/*

  • (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and contributors.
    *
  • All rights reserved. This program and the accompanying materials
  • are made available under the terms of the GNU Lesser General Public License
  • (LGPL) version 2.1 which accompanies this distribution, and is available at
  • http://www.gnu.org/licenses/lgpl.html
    *
  • This library is distributed in the hope that it will be useful,
  • but WITHOUT ANY WARRANTY; without even the implied warranty of
  • MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  • Lesser General Public License for more details.
    *
  • Contributors:
  • ldoguin
    */

package org.nuxeo.sample.dnd;

import java.io.Serializable;
import java.util.List;

import org.jboss.seam.contexts.Contexts;
import org.nuxeo.ecm.automation.OperationContext;
import org.nuxeo.ecm.automation.core.Constants;
import org.nuxeo.ecm.automation.core.annotations.Context;
import org.nuxeo.ecm.automation.core.annotations.Operation;
import org.nuxeo.ecm.automation.core.annotations.OperationMethod;
import org.nuxeo.ecm.automation.core.collectors.DocumentModelCollector;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.platform.tag.TagService;

/**

  • @author ldoguin
    */
    @Operation(id = TagDocument.ID, category = Constants.CAT_DOCUMENT, requires = Constants.SEAM_CONTEXT, label = "TagDocument", description = "")
    public class TagDocument {

public static final String ID = "Document.TagDocument";

@Context
protected CoreSession session;

@Context
protected OperationContext ctx;

@Context
TagService tagService;

@OperationMethod(collector = DocumentModelCollector.class)
public DocumentModel run(DocumentModel doc) throws Exception {
if (!isSeamContextAvailable()) {
return doc;
}
List tags = getDndTagsFormAction().getDndTags();
for (Serializable tag : tags) {
tagService.tag(session, doc.getId(), (String) tag,
ctx.getPrincipal().getName());
}
return doc;
}

public static boolean isSeamContextAvailable() {
return Contexts.isSessionContextActive();
}

public static DndTagsFormActionBean getDndTagsFormAction() {
return (DndTagsFormActionBean) Contexts.getConversationContext().get(
"dndTagsFormActions");
}

}


As you can see, it retrieves the list of tags from a SEAM bean. It's the backing bean of a new widget I have defined in my custom layout dndTagsEdit. This layout is almost the same as the original one, except it displays the tag widget. Take a look at the code and the documentation - it's pretty easy to understand.