AEM Cloud Service SDK - InDesign Connector for converting HTML Bold in Content Fragment to InDesign Bold

Goal

Adobe Experience Manager 2024.7.17258.20240726T172406Z-240700

In AEM Cloud Services SDK Author add a custom InDesign Server Connector module for creating InDesign documents reading Html Rich Text from Content Fragments and converting to InDesign specific formatting using InDesign Server

Demo | Package Install | Github


Content Fragment with HTML Bold


Button in Action Bar


InDesign Doc Created


Doc in InDesign



Connector Configuration

http://localhost:4502/system/console/configMgr/apps.experienceaem.assets.core.services.impl.IDSServiceImpl


Solution 

1) Create a servlet apps.experienceaem.assets.core.servlets.IDSRequestServlet to handle CF processing requests. When POSTed with createInDesignDoc selector (eg. http://localhost:4502/content/dam/experience-aem/about-adobe.createInDesignDoc) logic reads content fragment, creates sling job item com/eaem/ids for InDesign Server communication. Requests are processed in order received, one at a time...

package apps.experienceaem.assets.core.servlets;

import com.adobe.cq.dam.cfm.ContentElement;
import com.adobe.cq.dam.cfm.ContentFragment;
import com.adobe.cq.dam.cfm.FragmentData;
import com.day.cq.commons.TidyJSONWriter;
import com.google.gson.JsonObject;
import org.apache.commons.lang.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.servlets.HttpConstants;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.apache.sling.event.jobs.Job;
import org.apache.sling.event.jobs.JobManager;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.Node;
import javax.jcr.Session;
import javax.servlet.Servlet;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

@Component(
immediate = true,
service = Servlet.class,
property = {
Constants.SERVICE_DESCRIPTION + "=Experience AEM InDesign Server Process Servlet",
"sling.servlet.methods=" + HttpConstants.METHOD_GET,
"sling.servlet.methods=" + HttpConstants.METHOD_POST,
"sling.servlet.resourceTypes=sling/servlet/default",
"sling.servlet.extensions=" + "createInDesignDoc"
}
)
public class IDSRequestServlet extends SlingAllMethodsServlet {
private final Logger logger = LoggerFactory.getLogger(getClass());

public static final String INDESIGN_SERVICE_USER = "eaem-ids-service";
public static final String JOB_PATH = "jobPath";
public static final String CONTENT_JSON = "contentJson";
public static final String INDESIGN_SERVER_TOPIC = "com/eaem/ids";
public static final String MASTER_VARIATION = "master";
public static final String P_TAG = "<p>";
public static final String P_END_TAG = "</p>";

public static final Map<String, Object> INDESIGN_AUTH_INFO = Collections.singletonMap("sling.service.subservice", INDESIGN_SERVICE_USER);

@Reference
private JobManager jobManager;

@Reference
private ResourceResolverFactory resolverFactory;

@Override
protected void doGet(final SlingHttpServletRequest req, final SlingHttpServletResponse resp) {
resp.setContentType("application/json");

final Resource resource = req.getResource();

try {
TidyJSONWriter writer = new TidyJSONWriter(resp.getWriter());
writer.object();

if (resource == null) {
writer.key("error").value("No resource found");
writer.endObject();
}

ResourceResolver resolver = resolverFactory.getServiceResourceResolver(INDESIGN_AUTH_INFO);
Session session = resolver.adaptTo(Session.class);

HashMap<String, Object> jobProps = new HashMap<String, Object>();
String cfPath = req.getRequestPathInfo().getResourcePath();
String valuesJSON = getValuesFromCFAsJSON(resolver, cfPath);

if(StringUtils.isEmpty(valuesJSON)){
writer.key("error").value("No content fragment - " + cfPath);
writer.endObject();
return;
}

jobProps.put(CONTENT_JSON, valuesJSON);

Job job = jobManager.addJob(INDESIGN_SERVER_TOPIC, jobProps);

session.save();

writer.key("success").value(job.getId());
writer.endObject();
} catch (Exception e) {
logger.error("Error scheduling indesign server job for asset : ", resource.getPath());
}
}

private String getValuesFromCFAsJSON(ResourceResolver resolver, String cfPath){
Resource cfResource = resolver.getResource(cfPath);

if(cfResource == null){
return "";
}

String value = null;
JsonObject contentMap = new JsonObject();
ContentFragment cf = cfResource.adaptTo(ContentFragment.class);

Iterator<ContentElement> cfElementsItr = cf.getElements();

while(cfElementsItr.hasNext()) {
ContentElement cfElement = cfElementsItr.next();

if (cfElement == null) {
continue;
}

FragmentData fragValue = getVariationValue(cfElement, MASTER_VARIATION);

if(fragValue == null){
continue;
}

value = String.valueOf(fragValue.getValue()).trim();

contentMap.addProperty(cfElement.getName(), removeUnnecessaryChars(value));
}

contentMap.addProperty("path", cfPath);

return contentMap.toString();
}

private FragmentData getVariationValue(ContentElement cfElement, String variation){
if(StringUtils.isEmpty(variation) || "master".equals(variation)){
return cfElement.getValue();
}

return cfElement.getVariation(variation).getValue();
}

private String removeUnnecessaryChars(String value){
if(StringUtils.isEmpty(value) || value.equals("null")){
return "";
}

if(value.startsWith(P_TAG)){
value = value.substring(P_TAG.length(), value.lastIndexOf(P_END_TAG));
}

return value;
}

@Override
protected void doPost(final SlingHttpServletRequest req, final SlingHttpServletResponse resp) {
doGet(req, resp);
}
}

2) Create a Sling Job Consumer apps.experienceaem.assets.core.listeners.IDSJobConsumer for assembling the necessary SOAP payload (InDesign doc creation scripts and content from content fragment) send a request to InDesign Server running on 8080 (> InDesignServer.com -port 8080)

package apps.experienceaem.assets.core.listeners;

import apps.experienceaem.assets.core.services.IDSService;
import apps.experienceaem.assets.core.servlets.IDSRequestServlet;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.event.jobs.Job;
import org.apache.sling.event.jobs.consumer.JobConsumer;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

@Component(
immediate = true,
service = JobConsumer.class,
property = {
"job.topics=" + IDSRequestServlet.INDESIGN_SERVER_TOPIC,
}
)
public class IDSJobConsumer implements JobConsumer {
protected final Logger logger = LoggerFactory.getLogger(IDSJobConsumer.class);

@Reference
private ResourceResolverFactory resolverFactory;

@Reference
private IDSService idsService;

public JobResult process(Job job) {
ResourceResolver resolver = null;

try {
resolver = resolverFactory.getServiceResourceResolver(IDSRequestServlet.INDESIGN_AUTH_INFO);

return executeCreateInDesignDoc(job, resolver);
} catch (Exception e) {
logger.error("Failed to process indesign server job", e);
return JobResult.FAILED;
} finally {
if(resolver != null){
resolver.close();
}
}
}

private JobResult executeCreateInDesignDoc(Job job, ResourceResolver resolver) throws Exception{
Map<String, String> scriptArs = new HashMap<String, String>();
scriptArs.put(IDSRequestServlet.CONTENT_JSON, (String)job.getProperty(IDSRequestServlet.CONTENT_JSON));

String payload = idsService.buildSOAPPayload(resolver, scriptArs, null);

JsonObject responseObj = idsService.executeInDesignServerRequest(resolver, payload);

JsonElement indesignSuccess = responseObj.get("success");

if(indesignSuccess == null){
JsonElement indesignError = responseObj.get("error");

if(indesignError != null){
logger.error("Indesign server job resulted in error {} ", indesignError.toString());
}

resolver.commit();

return JobResult.FAILED;
}

resolver.commit();

return JobResult.OK;
}
}

3) Create a OSGI service apps.experienceaem.assets.core.services.impl.IDSServiceImpl for configuration and helper methods to create request payload for InDesign Server...

package apps.experienceaem.assets.core.services.impl;

import apps.experienceaem.assets.core.listeners.IDSJobConsumer;
import apps.experienceaem.assets.core.services.IDSService;
import com.day.cq.dam.commons.xml.DocumentBuilderFactoryProvider;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.fluent.Request;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.osgi.services.HttpClientBuilderFactory;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.AttributeType;
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import javax.jcr.Node;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*;
import java.util.Arrays;
import java.util.Map;

@Component(service = IDSService.class)
@Designate(ocd = IDSServiceImpl.IDSConfiguration.class)
public class IDSServiceImpl implements IDSService{
private final Logger logger = LoggerFactory.getLogger(IDSServiceImpl.class);

private String[] idsScripts = new String[0];
private String inDesignServerUrl = "";
private String base64EncodedAEMCreds = "";
private String aemHost = "";

@Reference
private transient HttpClientBuilderFactory httpClientBuilderFactory;

private transient CloseableHttpClient httpClient;

@Override
public JsonObject executeInDesignServerRequest(ResourceResolver resolver, String payload) throws Exception{
String response = Request.Post(inDesignServerUrl)
.addHeader("HttpPost", "")
.bodyString(payload, ContentType.APPLICATION_XML)
.execute().returnContent().asString();

logger.debug("InDesign Server Response : " + response);

Document document = getResponseDocument(response);

String resultJSON = document.getElementsByTagName("data").item(0).getFirstChild().getNodeValue();

JsonObject resultObj = new JsonParser().parse(resultJSON).getAsJsonObject();

return resultObj;
}

private Document getResponseDocument(String responseStr) throws Exception{
DocumentBuilderFactoryProvider factoryprovider = new DocumentBuilderFactoryProvider();
DocumentBuilderFactory factory = factoryprovider.createSecureBuilderFactory(false, false);

DocumentBuilder builder = factory.newDocumentBuilder();
builder.setErrorHandler(new ErrorHandler() {
@Override
public void warning(SAXParseException exception) throws SAXException {
logger.debug("Error parsing SOAP response {}:", exception.getMessage());
}
@Override
public void error(SAXParseException exception) throws SAXException {
logger.debug("Error parsing SOAP response {}:", exception.getMessage());
}

@Override
public void fatalError(SAXParseException exception) throws SAXException {
logger.debug("Error parsing SOAP response {}:", exception.getMessage());
}
});

return builder.parse(new InputSource(new StringReader(responseStr)));
}

@Override
public String buildSOAPPayload(ResourceResolver resolver, Map<String, String> scriptArs, String[] customScripts){
StringBuilder payload = new StringBuilder();

payload.append(getSOAPHeader());

payload.append("<SOAP-ENV:Body><IDSP:RunScript><IDSP:runScriptParameters><IDSP:scriptText><![CDATA[");

payload.append(getGiantScript(resolver, customScripts));

payload.append("]]></IDSP:scriptText>");

payload.append(getScriptInputArgs(scriptArs));

payload.append("</IDSP:runScriptParameters></IDSP:RunScript></SOAP-ENV:Body>");

payload.append(getSOAPFooter());

return payload.toString();
}

private String getScriptInputArgs(Map<String, String> scriptArs){
scriptArs.put("aemHost", aemHost);
scriptArs.put("base64EncodedAEMCreds", base64EncodedAEMCreds);

StringBuilder args = new StringBuilder();
args.append("<IDSP:scriptLanguage>javascript</IDSP:scriptLanguage>");

scriptArs.entrySet().forEach(entry -> {
args.append("<IDSP:scriptArgs>");
args.append("<IDSP:name>").append(entry.getKey()).append("</IDSP:name>");
args.append("<IDSP:value><![CDATA[").append(entry.getValue()).append("]]></IDSP:value>");
args.append("</IDSP:scriptArgs>");
});

return args.toString();
}

private String getSOAPHeader(){
return "<?xml version='1.0' encoding='UTF-8'?>" +
"<SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' " +
"xmlns:xsd='http://www.w3.org/2001/XMLSchema' " +
"xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' " +
"xmlns:SOAP-ENC='http://schemas.xmlsoap.org/soap/encoding/' " +
"xmlns:IDSP='http://ns.adobe.com/InDesign/soap/'>";
}

private String getSOAPFooter(){
return "</SOAP-ENV:Envelope>";
}

private String getGiantScript(ResourceResolver resolver, String[] customScripts){
StringBuilder script = new StringBuilder();

if(ArrayUtils.isEmpty(customScripts)){
customScripts = idsScripts;
}

Arrays.stream(customScripts).forEach( scriptPath -> {
Resource resource = resolver.getResource(scriptPath);

if(resource == null){
throw new RuntimeException("Error finding script resource : " + scriptPath);
}

Node scriptNode = (Node)resource.adaptTo(Node.class);
try {
script.append(IOUtils.toString(scriptNode.getProperty("jcr:data").getBinary().getStream()));
} catch (Exception e) {
throw new RuntimeException("Error adding script resource : " + scriptPath);
}
});

return script.toString();
}

@Activate
@Modified
protected void activate(final IDSConfiguration config) {
idsScripts = config.inDesignServerScripts();

inDesignServerUrl = config.inDesignServerUrl();
aemHost = config.aemHost();
base64EncodedAEMCreds = config.base64EncodedAEMCreds();

final HttpClientBuilder builder = httpClientBuilderFactory.newBuilder();

final RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000)
.setSocketTimeout(30000).build();

builder.setDefaultRequestConfig(requestConfig);

httpClient = builder.build();
}

@ObjectClassDefinition(name = "Experience AEM InDesign Server Configuration")
public @interface IDSConfiguration {

@AttributeDefinition(
name = "InDesign Scripts in order",
description = "Add the InDesign Server Scripts in execution order",
type = AttributeType.STRING,
cardinality = 5
)
String[] inDesignServerScripts() default {
"/libs/settings/dam/indesign/scripts/json2.jsx/jcr:content",
"/libs/settings/dam/indesign/scripts/cq-lib.jsx/jcr:content",
"/apps/eaem-assets-cf-indesign/indesign/scripts/create-indesign-doc.jsx/jcr:content"
};

@AttributeDefinition(
name = "InDesign Server endpoint",
description = "Add the InDesign Server endpoint url eg. http://localhost:8080",
type = AttributeType.STRING
)
String inDesignServerUrl() default "http://localhost:8080";

@AttributeDefinition(
name = "AEM Server",
description = "The AEM Server, InDesign Server should connect to",
type = AttributeType.STRING
)
String aemHost() default "localhost:4502";

@AttributeDefinition(
name = "Base64 encoded AEM Creds",
description = "Base 64 encoded AEM Credentials Indesign server should use for download, eg. admin:admin is YWRtaW46YWRtaW4=",
type = AttributeType.STRING
)
String base64EncodedAEMCreds() default "YWRtaW46YWRtaW4=";
}
}

4) Add the script /ui.apps/src/main/content/jcr_root/apps/eaem-assets-cf-indesign/indesign/scripts/create-indesign-doc.jsx executed on InDesign Server to process the content payload received from AEM and create InDesign doc

(function () {
var returnObj = {}, aemHost, base64EncodedAEMCreds, cfPath, contentJson;

function createInDesignDoc() {
cfPath = contentJson.path;

var sourceFolder = getSourceFolder(),
fileName = cfPath.substring(cfPath.lastIndexOf ('/') + 1),
documentFile = new File(sourceFolder.fullName + "/" + fileName + '.indd'),
pdfOutputFile = new File(sourceFolder.fullName + "/" + fileName + '.pdf');

var document = app.documents.add();

app.findGrepPreferences = app.changeGrepPreferences = NothingEnum.nothing;
app.changeGrepPreferences.changeTo = "$3";

for(var eleName in contentJson){
if(eleName == "path"){
continue;
}

var spread = document.spreads.lastItem();
var textFrame = createTextFrame(spread);
textFrame.contents = contentJson[eleName];

var tfFont = "Calibri";
textFrame.parentStory.appliedFont = tfFont;

app.changeGrepPreferences.appliedCharacterStyle = getBoldStyle(document, tfFont);

app.findGrepPreferences.findWhat = "(<strong(\\s.*)?>)(.+?)(</strong(\\s.*)?>)";
textFrame.changeGrep();

app.findGrepPreferences.findWhat = "(<b(\\s.*)?>)(.+?)(</b(\\s.*)?>)";
textFrame.changeGrep();
}

app.findGrepPreferences = app.changeGrepPreferences = NothingEnum.nothing;

document.exportFile(ExportFormat.pdfType, pdfOutputFile);
document.save(documentFile);

var uploadPath = cfPath.substring(0, cfPath.lastIndexOf("/"));

app.consoleout('Uploading files - ' + pdfOutputFile + "," + documentFile);

uploadDAMFile(aemHost, base64EncodedAEMCreds, pdfOutputFile, pdfOutputFile.name, 'application/pdf', uploadPath);

app.consoleout('Upload Complete - ' + pdfOutputFile);

uploadDAMFile(aemHost, base64EncodedAEMCreds, documentFile, documentFile.name, 'application/indd', uploadPath);

app.consoleout('Upload Complete - ' + documentFile);

returnObj.success = "completed";
}

function getBoldStyle(document, font) {
var boldCharacterStyle = document.characterStyles.add();

boldCharacterStyle.appliedFont = font;
boldCharacterStyle.fontStyle = "Bold";
//boldCharacterStyle.pointSize = 28;

return boldCharacterStyle;
}

function createTextFrame(spread) {
var textFrame = spread.textFrames.add();

var y1 = 10; // upper left Y-Coordinate
var x1 = 10; // upper left X-Coordinate
var y2 = 50; // lower right Y-Coordinate
var x2 = 40; // lower right X-Coordinate

textFrame.geometricBounds = [y1, x1, y2, x2];

return textFrame;
}

function getSourceFolder(){
var today = new Date(),
folderName = today.getFullYear() + "-" + today.getMonth() + "-" + today.getDate() + "-" + today.getHours()
+ "-" + today.getMinutes() + "-" + today.getSeconds();

var sourceFolder = new Folder(folderName);
sourceFolder.create();

return sourceFolder;
}

function setParamsFromScriptArgs(){
if (app.scriptArgs.isDefined("base64EncodedAEMCreds")) {
base64EncodedAEMCreds = app.scriptArgs.getValue("base64EncodedAEMCreds");
} else {
throw "AEM host credentials argument is missing";
}

if (app.scriptArgs.isDefined("aemHost")) {
aemHost = app.scriptArgs.getValue("aemHost");
} else {
throw "aemHost argument is missing";
}

if (app.scriptArgs.isDefined("contentJson")) {
contentJson = JSON.parse(app.scriptArgs.getValue("contentJson"));
app.consoleout('contentJson: ' + app.scriptArgs.getValue("contentJson"));
} else {
throw "contentJson argument missing";
}

app.consoleout('base64EncodedAEMCreds --- ' + base64EncodedAEMCreds);
app.consoleout('aemHost --- ' + aemHost);
}

function uploadDAMFile(host, credentials, file, fileName, contentType, aemFolderPath) {
var transformedHost = transformHost(host);
host = transformedHost.host;
var contextPath = transformedHost.contextPath

var success = false;
var statusFromServer = 0;
var retries = 0;

while(!success && retries<5){
file.open ("r");
file.encoding = "BINARY";
var boundary = '----------V2ymHFg03ehbqgZCaKO6jy';
var connection = new Socket;
if (connection.open (host, "binary")) {
connection.write ("POST "+ encodeURI(contextPath + aemFolderPath + ".createasset.html") +" HTTP/1.0");
connection.write ("\n");
connection.write ("Authorization: Basic " + credentials);
connection.write ("\n");
connection.write ("User-Agent: Jakarta Commons-HttpClient/3.1");
connection.write ("\n");
connection.write ("Content-Type: multipart/form-data; boundary="+boundary);
connection.write ("\n");
var body = getMultiPartBodyDAMUpload(boundary, file, fileName, contentType);
connection.write ("Content-Length: "+body.length);
connection.write ("\r\n\r\n");
//END of header
connection.write (body);

statusFromServer = readResponse(connection);

if(statusFromServer>=400){
app.consoleout('Seen error response '+statusFromServer+' ['+retries+']');
} else if (statusFromServer>=300) {
app.consoleout('Redirects currently not supported');
} else if (statusFromServer>=200) {
success=true;
}

if(!success){
++retries;
}
} else {
app.consoleout('Connection to host ' + host + ' could not be opened');
}
file.close();
}
}

function getMultiPartBodyDAMUpload(boundary, file, fileName, contentType) {
var endBoundary = '\r\n--' + boundary + '--\r\n';
var body;

body = body + '--'+boundary+'\r\n';
body = body + 'content-disposition: form-data; name="_charset_"';
body = body + '\r\n\r\n';
body = body + 'utf-8';
body = body + '\r\n';

body = body + '--'+boundary+'\r\n';
body = body + 'content-disposition: form-data; name="fileName"';
body = body + '\r\n\r\n';
body = body + fileName;
body = body + '\r\n';

body = body + '--'+boundary+'\r\n';
body = body + 'content-disposition: form-data; name="file"; filename="'+Base64._utf8_encode(fileName)+'"\r\n';

if (contentType) {
body = body + 'Content-Type: '+contentType+'\r\n';
}
body = body + 'Content-Transfer-Encoding: binary\r\n';
body = body + '\r\n';

var content;
while ((content = file.read ()) != '') {
body = body + content;
}

file.close();

body = body + endBoundary;
return body;
}

function setTestParams(){
aemHost = "localhost:4502";
base64EncodedAEMCreds = "YWRtaW46YWRtaW4=";
contentJson = {"rteText":"This is <b>bold</b>","path":"/content/dam/experience-aem/bold"}
}

try{
setParamsFromScriptArgs();

//setTestParams();

createInDesignDoc();
}catch(err){
returnObj.error = err;
app.consoleout("Error processing content fragment : " + cfPath + ", error : " + err);
}finally{
}

return JSON.stringify(returnObj);
}());

5) Add /ui.config/src/main/content/jcr_root/apps/eaem-assets-cf-indesign/osgiconfig/config/org.apache.sling.event.jobs.QueueConfiguration-eaem-ids with following properties for ordering the com/eaem/ids sling job queue IDS requests...

<?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"
jcr:primaryType="sling:OsgiConfig"
queue.maxparallel="{Long}1"
queue.name="Experience AEM InDesign Server Processing Queue"
queue.priority="MIN"
queue.retries="{Long}0"
queue.retrydelay="{Long}60000"
queue.topics="com/eaem/ids"
queue.type="ORDERED"/>

6) Add repoinit script in /ui.config/src/main/content/jcr_root/apps/eaem-assets-cf-indesign/osgiconfig/config/org.apache.sling.jcr.repoinit.RepositoryInitializer-eaem-ids.config for  creating a service user eaem-ids-service and specifying ACLs 

{
"scripts": [
"create service user eaem-ids-service with path system/experience-aem",
"set ACL for eaem-ids-service \n allow jcr:read on /apps \n allow jcr:read on /conf \n allow jcr:read on /libs \n allow jcr:all on /content \n allow jcr:read on /var \n end"
]
}

8) Add core bundle to service user mapping in /ui.config/src/main/content/jcr_root/apps/eaem-assets-cf-indesign/osgiconfig/config/org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended-eaem-ids.cfg.json

{
"user.mapping": [
"eaem-assets-cf-indesign.core:eaem-ids-service=[eaem-ids-service]"
]
}

9) Add the UI button To InDesign in /apps/eaem-assets-cf-indesign/clientlibs/content

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:granite="http://www.adobe.com/jcr/granite/1.0"
xmlns:dam="http://www.day.com/dam/1.0" xmlns:cq="http://www.day.com/jcr/cq/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/coral/foundation/collection/action"
icon="link"
granite:rel="eaem-to-indesign-activator"
target=".cq-damadmin-admin-childpages"
text="To InDesign"
variant="actionBar"/>

10) Add the button action in /apps/eaem-assets-cf-indesign/clientlibs/id-clientlib/indesign-create-doc.js 

(function ($, $document) {
"use strict";

let ASSETS_PAGE = "/assets.html",
initialized = false,
BESIDE_ACTIVATOR = "button.cq-damadmin-admin-actions-downloadcf-activator",
INDESIGN_ACTIVATOR = "button.eaem-to-indesign-activator",
FOU_COL_ACT_HIDDEN = "foundation-collection-action-hidden",
ID_BUTTON_URL = "/apps/eaem-assets-cf-indesign/clientlibs/content/create-indesign-doc-but.html";

if (!isAssetsPage()) {
return;
}

$document.on("foundation-contentloaded", addActionBarButtons);

function addActionBarButtons(){
if (initialized) {
return;
}

initialized = true;

$.ajax(ID_BUTTON_URL).done(addToIndesignButton);
}

function addToIndesignButton(html) {
const $eActivator = $(BESIDE_ACTIVATOR);

if ($eActivator.length == 0) {
return;
}

html = '<coral-actionbar-item class="_coral-ActionBar-item" style="">' + html + '</coral-actionbar-item>';

let $inDesignBut = $(html).insertAfter($eActivator.closest("coral-actionbar-item"));

$inDesignBut.find("coral-button-label").css("padding-left", "7px");

$inDesignBut.click(() => {
const actionUrl = $(".foundation-selections-item").first().data("foundation-collection-item-id") + ".createInDesignDoc";

$.ajax(actionUrl).done(() => {
$(window).adaptTo("foundation-ui").alert("InDesign", "InDesign and PDF documents creation in progress...", "success");
});
});

$document.on("foundation-selections-change", function(){
let $inDesignBut = $(INDESIGN_ACTIVATOR),
$selections = $(".foundation-selections-item");

if($selections.length !== 1){
return;
}

$inDesignBut.removeClass(FOU_COL_ACT_HIDDEN);
});
}

function createIndesignDoc(){

}

function isAssetsPage() {
return (window.location.pathname.indexOf(ASSETS_PAGE) >= 0);
}
}(jQuery, jQuery(document)));

No comments:

Post a Comment