Goal
Show simple Metadata Form in the Upload Dialog of Touch UI Assets Console; With this extension users can add metadata while uploading files
Demo | Package Install
Metadata Form in Upload Dialog
Metadata Validation
Metadata in CRX
Solution
1) Login to CRXDE Lite (http://localhost:4502/crx/de), create folder /apps/eaem-assets-file-upload-with-metadata
2) Metadata form shown in Upload Dialog is Authoring Dialog; Create the dialog /apps/eaem-assets-file-upload-with-metadata/dialog, add metadata form nodes
Dialog XML
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/container">
<layout
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns"
margin="{Boolean}false"/>
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/container">
<items jcr:primaryType="nt:unstructured">
<title
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/textfield"
fieldDescription="Enter Title"
fieldLabel="Title"
name="./eaemTitle"
required="{Boolean}true"/>
<useBy
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/datepicker"
class="field"
displayedFormat="YYYY-MM-DD HH:mm"
fieldLabel="Use By"
name="./eaemUseBy"
type="datetime"/>
<onlyForWeb
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/checkbox"
name="./eaemOnlyForWeb"
text="Only for web?"/>
<type
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/select"
fieldDescription="Select Size"
fieldLabel="Size"
name="./eaemSize">
<items jcr:primaryType="nt:unstructured">
<def
jcr:primaryType="nt:unstructured"
text="Select Size"
value=""/>
<small
jcr:primaryType="nt:unstructured"
text="Small"
value="small"/>
<medium
jcr:primaryType="nt:unstructured"
text="Medium"
value="medium"/>
<large
jcr:primaryType="nt:unstructured"
text="Large"
value="large"/>
</items>
</type>
<tags
jcr:primaryType="nt:unstructured"
sling:resourceType="cq/gui/components/common/tagspicker"
allowCreate="{Boolean}true"
fieldLabel="Tags"
name="./eaemTags"/>
</items>
</column>
</items>
</jcr:root>
3) Create node /apps/eaem-assets-file-upload-with-metadata/clientlib of type cq:ClientLibraryFolder, add String[] property categories with value dam.gui.coral.fileupload String[] property dependencies with value underscore
4) Create file (nt:file) /apps/eaem-assets-file-upload-with-metadata/clientlib/js.txt, add
fileupload-with-metadata.js
5) Create file (nt:file) /apps/eaem-assets-file-upload-with-metadata/clientlib/fileupload-with-metadata.js, add the following code
(function($, $document) {
var METADATA_DIALOG = "/apps/eaem-assets-file-upload-with-metadata/dialog.html",
METADATA_PREFIX = "eaem",
UPLOAD_LIST_DIALOG = "#uploadListDialog",
ACTION_CHECK_DATA_VALIDITY = "ACTION_CHECK_DATA_VALIDITY",
ACTION_POST_METADATA = "ACTION_POST_METADATA",
url = document.location.pathname;
if( url.indexOf("/assets.html") == 0 ){
handleAssetsConsole();
}else if(url.indexOf(METADATA_DIALOG) == 0){
handleMetadataDialog();
}
function handleAssetsConsole(){
$document.on("foundation-contentloaded", handleFileAdditions);
}
function handleMetadataDialog(){
$(function(){
_.defer(styleMetadataIframe);
});
}
function registerReceiveDataListener(handler) {
if (window.addEventListener) {
window.addEventListener("message", handler, false);
} else if (window.attachEvent) {
window.attachEvent("onmessage", handler);
}
}
function styleMetadataIframe(){
var $dialog = $("coral-dialog");
if(_.isEmpty($dialog)){
return;
}
$dialog.css("overflow", "hidden");
$dialog[0].open = true;
var $header = $dialog.css("background-color", "#fff").find(".coral-Dialog-header");
$header.find(".cq-dialog-actions").remove();
$dialog.find(".coral-Dialog-wrapper").css("margin","0").find(".coral-Dialog-content").css("padding","0");
registerReceiveDataListener(postMetadata);
function postMetadata(event){
var message = JSON.parse(event.data);
if( message.action !== ACTION_CHECK_DATA_VALIDITY ){
return;
}
var $dialog = $(".cq-dialog"),
$fields = $dialog.find("[name^='./']"),
data = {}, $field, $fValidation, name, value, values,
isDataInValid = false;
$fields.each(function(index, field){
$field = $(field);
name = $field.attr("name");
value = $field.val();
$fValidation = $field.adaptTo("foundation-validation");
if($fValidation && !$fValidation.checkValidity()){
isDataInValid = true;
}
$field.updateErrorUI();
if(_.isEmpty(value)){
return;
}
name = name.substr(2);
if(!name.indexOf(METADATA_PREFIX) === 0){
return
}
if(!_.isEmpty(data[name])){
if(_.isArray(data[name])){
data[name].push(value);
}else{
values = [];
values.push(data[name]);
values.push(value);
data[name] = values;
data[name + "@TypeHint"] = "String[]";
}
}else{
data[name] = value;
}
});
sendValidityMessage(isDataInValid, data);
}
function sendValidityMessage(isDataInValid, data){
var message = {
action: ACTION_CHECK_DATA_VALIDITY,
data: data,
isDataInValid: isDataInValid
};
parent.postMessage(JSON.stringify(message), "*");
}
}
function handleFileAdditions(){
var $fileUpload = $("coral-chunkfileupload"),
$metadataIFrame, $uploadButton, validateUploadButton,
metadata;
$fileUpload.on('coral-fileupload:fileadded', addMetadataDialog);
$fileUpload.on('coral-fileupload:loadend', postMetadata);
function sendDataMessage(message){
$metadataIFrame[0].contentWindow.postMessage(JSON.stringify(message), "*");
}
function addMetadataDialog(){
_.debounce(addDialog, 500)();
}
function addDialog(){
var $dialog = $(UPLOAD_LIST_DIALOG);
if(!_.isEmpty($dialog.find("iframe"))){
return;
}
var iFrame = '<iframe width="550px" height="450px" frameborder="0" src="' + METADATA_DIALOG + '"/>',
$dialogContent = $dialog.find("coral-dialog-content");
$metadataIFrame = $(iFrame).appendTo($dialogContent.css("max-height", "600px"));
$dialogContent.find("input").css("width", "30rem");
$dialogContent.closest(".coral-Dialog-wrapper").css("top", "30%").css("left", "50%");
addValidateUploadButton($dialog);
}
function addValidateUploadButton($dialog){
var $footer = $dialog.find("coral-dialog-footer");
$uploadButton = $footer.find("coral-button-label:contains('Upload')").closest("button");
validateUploadButton = new Coral.Button().set({
variant: 'primary'
});
validateUploadButton.label.textContent = Granite.I18n.get('Upload');
validateUploadButton.classList.add('dam-asset-upload-button');
$footer[0].appendChild(validateUploadButton);
$uploadButton.hide();
validateUploadButton.hide();
validateUploadButton.on('click', function() {
checkDataValidity();
});
$metadataIFrame.on('load', function(){
validateUploadButton.show();
});
registerReceiveDataListener(isMetadataValid);
}
function isMetadataValid(event){
var message = JSON.parse(event.data);
if( (message.action !== ACTION_CHECK_DATA_VALIDITY)){
return;
}
if(message.isDataInValid){
return;
}
metadata = message.data;
validateUploadButton.hide();
$uploadButton.click();
}
function checkDataValidity(){
var message = {
action: ACTION_CHECK_DATA_VALIDITY
};
sendDataMessage(message);
}
function postMetadata(event){
var detail = event.originalEvent.detail,
folderPath = detail.action.replace(".createasset.html", ""),
assetMetadataPath = folderPath + "/" + detail.item.name + "/jcr:content/metadata";
//jcr:content/metadata created by the DAM Update asset workflow may not be available when the below post
//call executes; ideally, post the parameters to aem, a scheduler runs and adds the metadata when metadata
//node becomes available
$.ajax({
type : 'POST',
url : assetMetadataPath,
data : metadata
})
}
}
})(jQuery, jQuery(document));
6) #212 is for demo purposes only; in real world implementations, the metadata node created by DAM Update Asset workflow may not yet exist yet, when the ajax post metadata call executes. Replace this direct call with a servlet temporarily storing the form metadata and update the metadata node (when it becomes available) in a scheduler or listener