The Create Correspondence user interface can be customized
for your project requirements. This user story describes how to
perform some of the common customizations.
Implementation overviewThe following examples provide detailed steps to make specific
changes to the Create Correspondence user interface. The Create
Correspondence user interface application uses the styles from the
following projects: [SDK]/riaservices/assetcomposer/10.0.0.0/flex/adobe-acm-ccr-styles.swc
[SDK]/riaservices/assetcomposer/10.0.0.0/flex/adobe-acm-authoring-styles.swc
[SDK]/riaservices/riacore/10.0.0.0/flex/adobe-lcc-styles.swc
These styles projects are applied as a theme in the Create Correspondence
application. The Create Correspondence Solution Template style is
defined in the CreateCorrespondence > src > CSS > ccr_styles.css file.
To apply a new style or change the existing styles, override these
styles in the Create Correspondence Solution Template application.
Customizing the application contextTo change the URL of Create Correspondence user interface,
perform the following tasks: Update the value of variable CM_APPLICATION_CONTEXT in
the following files: CorrespondenceManagementSolutionTemplate/CreateCorrespondence/src/com/adobe/solutions/cmg/ccr/presentation/CCRApplication.as
CorrespondenceManagementSolutionTemplate/ManageAssets/src/com/adobe/solutions/cmg/manage\presentation/AMApplication.as
Update the value of CORRESPONDENCE_MANAGEMENT_ROOT_FOLDER constant
in CorrespondenceManagementSolutionTemplate/Services/src/com/adobe/icc/bootstrap/AssetDefinitionsDeployer.java to
reflect the new application context.
Update the location of the solution supplied configuration
files of the Building Block. The location of the Building Block
config files is:
CorrespondenceManagementSolutionTemplate\package-resources\etc\aep\config\BuildingBlockName
Location
of the solution supplied config files is the location of the Building Block
config folder + application context of the solution ("/content"
is optional).
Specifically, you must change:
Rebuild and Redeploy. For information on rebuilding and redeploying,
see Building and deploying the Solution Template.
Customizing the date formatYou can change the default date format of the Correspondence
Management solution. Log in to CRXDE using the Administrator
account. The default user ID is admin and the default
password is admin.
Navigate to /content/cm folder on the left pane.
Open tbxeditor-config.xml file in a text
editor.
Locate <defaultDateFormat> tag in
the XML file and change the format.
Save the tbxeditor-config.xml file.
Rebuild and redploy the solution template for your changes
to take effect.
Removing indentation buttons in the Create Correspondence user interfaceYou can remove the capability to change indentation of
content in Create Correspondence user interface. You can customize
the toolbar skin file and hide the indentation buttons so that they
do not appear in the user interface. In Flash Builder,
open the CreateCorrespondence project in the Package Explorer view.
Navigate to CreateCorrespondence > src > com.adobe.solutions.cmg.ccr
> skins.
Create a skin file here say toolbarSkin.mxml as a copy of
the skin file com.adobe.solutions.acm.ccr.skins.ToolBarSkin.
Modify the new toolbarSkin.mxml file and set the "includeInLayout"
and "visible" property of the indentation buttons to "false" so
that the indentation buttons are not displayed. <s:HGroup gap="-1" >
<s:Button id="rightIndentBtn" styleName="increaseIndentButton" toolTip="{resourceManager.getString('Iccuser interfaceStrings','increaseIndentBtnToolTip')}" height="23" width="29" visible="false" includeInLayout="false"/>
<s:Button id="leftIndentBtn" styleName="decreaseIndentButton" toolTip="{resourceManager.getString('Iccuser interfaceStrings','decreaseIndentBtnToolTip')}" height="23" width="29" visible="false" includeInLayout="false"/>
</s:HGroup>
Create a Solution Template style sheet to use the customized
skin file at CreateCorrespondence > src > CSS, for example,
custom_styles.css. Add the following entry in the CreateCorrespondence > src > CSS > custom_styles.css so
the toolbar class uses the customized skin. @namespace ccrpresentation "com.adobe.solutions.acm.ccr.presentation.*";
ccrpresentation|toolbar
{
backgroundGradientStartColor : #656565;
backgroundGradientEndColor : #353535;
borderContainerBgColor : #525252;
borderColor : #222222;
skinClass: ClassReference("com.adobe.solutions.cmg.ccr.skins.toolbarSkin");
}
Add the new CSS file in CreateCorrespondence > src >
(default package) > index.mxml: <fx:Style source="/css/custom_styles.css"/>
Rebuild and Redeploy. For information on rebuilding and redeploying,
see Building and deploying the Solution Template.
The indentation buttons are removed from the toolbar.
Edit a Text Module based on user groupDepending on your requirements, you can restrict the ability
to edit a text module in Create Correspondence user interface based
on user group. To do so: Create a user group: see the
following documentation for creating a user group: http://dev.day.com/content/docs/en/crx/current/administering/user_group_ac_admin.html.
In Flash Builder, open the CreateCorrespondence project in
the Package Explorer view.
Navigate to CreateCorrespondence > src > com.adobe.solutions.cmg.ccr
> presentation.
Create an ActionScript class here say CustomModuleItemRenderer.as
which extends the com.adobe.solutions.acm.ccr.presentation.contentcapture.ModuleItemRenderer
class. Override the commitProperties function in it to disable the
edit button based on the user group. The source code shown below
assumes that there is a user group defined such as"EditText". Also,
the Edit button is enabled only for those users which are a part
of this group. package com.adobe.solutions.cmg.ccr.presentation
{
import com.adobe.icc.services.ServiceProvider;
import com.adobe.icc.services.user.ISSOManager;
import com.adobe.solutions.acm.ccr.presentation.contentcapture.ModuleItemRenderer;
import mx.collections.IList;
import spark.components.Button;
public class CustomModuleItemRenderer extends ModuleItemRenderer
{
public var userManager:ISSOManager = ServiceProvider.getUserService();
public function enableTextEditBtnBasedOnUserGroup():void
{
if(userManager && userManager.currentUser)
{
var listGroups:IList = userManager.currentUser.groups;
//If the EditText group is not assigned to the user disable the Edit button.
if(listGroups.getItemIndex("EditText") == -1)
textEditBtn.enabled = false;
}
}
override protected function commitProperties():void
{
super.commitProperties()
if(textEditBtn && textEditBtn.visible)
{
enableTextEditBtnBasedOnUserGroup();
}
invalidateDisplayList();
}
}
}
Navigate to CreateCorrespondence > src > com.adobe.solutions.cmg.ccr
> skins.Create skin file TargetAreaRendererSkin.mxml as a copy
of the skin file com.adobe.solutions.acm.ccr.skins.contentcapture.TargetAreaRendererSkin.mxml.
Modify the moduleViewList in the new TargetAreaRendererSkin.mxml
file to use the CustomModuleItemRenderer as follows: <s:List id="moduleViewList" contentBackgroundAlpha="1.0"
alternatingItemColors="[0xffffff, 0xf8f8f8]" contentBackgroundColor="0xf8f8f8"
itemRenderer="com.adobe.solutions.cmg.ccr.presentation.CustomModuleItemRenderer"
width="100%" minHeight="0" >
<s:layout >
<s:VerticalLayout horizontalAlign="contentJustify" variableRowHeight="true" gap="0" paddingTop="0" paddingBottom="0"/>
</s:layout>
</s:List>
Create a style sheet to use the customized files (such as
custom_styles.css). Add the following entries in the CreateCorrespondence
> src > CSS > custom_styles.css: /* CSS file */
@namespace s "library://ns.adobe.com/flex/spark";
@namespace mx "library://ns.adobe.com/flex/mx";
@namespace contentcapture "com.adobe.solutions.acm.ccr.presentation.contentcapture.*";
@namespace presentation "com.adobe.solutions.cmg.ccr.presentation.*";
contentcapture|TargetAreaRenderer
{
backgroundGradientStartColor : #656565;
backgroundGradientEndColor : #353535;
borderContainerBgColor : #454545;
borderColor : #222222;
skinClass: ClassReference("com.adobe.solutions.cmg.ccr.skins.TargetAreaRendererSkin");
}
presentation|CustomModuleItemRenderer
{
backgroundGradientStartColor : #656565;
backgroundGradientEndColor : #353535;
borderContainerBgColor : #454545;
borderColor : #222222;
skinClass: ClassReference("com.adobe.solutions.acm.ccr.skins.contentcapture.ModuleItemRendererSkin");
}
Update index.mxml file to include this custom CSS file, include
after including all other CSS files: <fx:Style source="/css/custom_styles.css"/>
Rebuild and Redeploy. For information on rebuilding and redeploying,
see Building and deploying the Solution Template.
The edit button is enabled if the user is a part of the "EditText"
group.
Filter the Target Areas for displayDepending on your requirements, you can filter the target
areas for display in the Create Correspondence user interface. For
example, you can hide target areas which are closed for any kind
of action by the agent. To do so: In Flash Builder, open
the CreateCorrespondence project in the Package Explorer view.
Navigate to CreateCorrespondence > src > com.adobe.solutions.cmg.ccr
> presentation and add a custom filter target area filter function
in the CCRApplication.as file: import com.adobe.icc.dc.domain.IModuleInstance;
import com.adobe.icc.dc.domain.TargetInstance;
import com.adobe.icc.dc.domain.VariableInstance;
import com.adobe.icc.dc.domain.TextModuleInstance;
/**
* Returns true if the target area needs to displayed,
* false if it is not to be displayed
*/
private function customTargetInstanceFilterFunction(item:Object):Boolean
{
if(! (item is TargetInstance))
return false;
var targetInstance:TargetInstance = item as TargetInstance;
//Show the target area if it allows free text
if(targetInstance.allowFreeText)
return true;
if(!targetInstance.contents || targetInstance.contents.length < 1)
return false;
//If the order is not fixed show the target area
if(!targetInstance.ordered)
return true;
//Check if there is any optional content in the target area
for(var i:int=0; i<targetInstance.contents.length; i++)
{
var moduleInst:IModuleInstance = targetInstance.contents[i] as IModuleInstance;
if(moduleInst.optional)
return true;
//If there is a TextModule which is editable show the target area
if(moduleInst is TextModuleInstance && moduleInst.editable)
return true;
}
//Check if there are any editable content variables in the target area
if(targetInstance.contentVariables && targetInstance.contentVariables.length > 0)
{
for(var i:int=0; i<targetInstance.contentVariables.length; i++)
{
var varInst:VariableInstance = targetInstance.contentVariables[i] as VariableInstance;
if(varInst.editable)
return true;
}
}
return false;
};
Modify partAdded function in the CCRApplication.as file and
set the custom target area filter function for the contentCapturePod. else if(instance == contentCapturePod)
{
//Set the custom filter function here
contentCapturePod.targetInstanceFilterFunction = customTargetInstanceFilterFunction;
BindingUtils.bindSetter(updateContentCaptureProvider, this, ["letterInstance", "targetInstances"]);
BindingUtils.bindSetter(updateContentCaptureVariableList, this, ["letterInstance", "variableInstances"]);
contentCapturePod.addEventListener("libraryInsertEvent", handleLibraryInsertEvent);
contentCapturePod.addEventListener("textEditEvent", handleTextEditEvent);
contentCapturePod.addEventListener("activeContentChange", contentCapturePod.handleActiveContentEvent);
addEventListener("ItemMoveUpClickEvent", handleItemMoveUpClick);
addEventListener("ItemMoveDownClickEvent", handleItemMoveDownClick);
addEventListener("ItemDeleteClickEvent", handleItemDeleteClick);
addEventListener("LeftIndentClickEvent", handleLeftIndentClick);
addEventListener("RightIndentClickEvent", handleRightIndentClick);
}
Rebuild and Redeploy. For information on rebuilding and redeploying,
see Building and deploying the Solution Template.
The target areas in the content view are displayed based on the
filter function defined.
Customize the Create Correspondence user interface view optionsBy default, if you open a letter instance in the Create
Correspondence user interface, you have the options to view the
letter in the Data view or the Content view. You can customize the
default view (data or content) for the letter instance. You can
also customize the view to display either the data or content view.
To customize the Create Correspondence view
Navigate to file [CorrespondenceManagementSolutionTemplate]\package-resources\content\cm\tbxeditor-config.xml and
open the file in any text editor.
Go to the following node:
CCRDefaultView
- AUTO
- Default. If the letter instance contains variables or fields,
by default, the instance is opened in the Data view. Choose Content
in the drop-down list to go to the Content view. If the letter instance
does not contain any variables or fields , the instance opens in
the Content view. However, you can still choose Data in the drop-down
list to go to the Data view.
- DATA
- The letter instance is opened in the Data view. Choose Content
in the drop-down list to go to the Content view.
- CONTENT
- The letter instance is opened in the Content view. Choose
Data in the drop-down list to go to the Data view.
- DATA_ONLY
- The letter instance is opened in the Data view. The drop-down list
only contains the Data option. Use this setting to ensure that a
user who opens a letter instance is not permitted to view the instance
in the Content view.
- CONTENT_ONLY
- The letter instance is opened in the Content view. The drop-down
list only contains the Content option. Use this setting to ensure
that a user who opens a letter instance is not permitted to view
the instance in the Data view.
Save the tbxeditor-config.xml file.
Rebuild and redploy the solution template for your changes
to take effect.
Create alternate Data CaptureDepending on your requirements, you can create an alternate
Data Capture user interface for the Create Correspondence application.
This interface can show the list of data elements from the letter
which the agent has to fill and then submit the letter. There is
no content view and no PDF display of the letter which would lead
to faster processing. To do so: In Flash Builder,
open the CreateCorrespondence project in the Package Explorer view.
Navigate to CreateCorrespondence > src > com.adobe.solutions.cmg.ccr > presentation.
Open the file CCRApplication.as and append the source
code below. import com.adobe.dct.event.DCTServiceEvent;
import com.adobe.dct.model.DataDictionaryInstanceModel;
import com.adobe.dct.service.DataDictionaryUtilService;
import com.adobe.dct.transfer.DataDictionaryElement;
import com.adobe.icc.services.render.ILetterRenderService;
import com.adobe.icc.util.Map;
import com.adobe.icc.vo.Field;
import com.adobe.icc.vo.Variable;
import flash.events.MouseEvent;
import mx.collections.ArrayCollection;
import mx.rpc.remoting.RemoteObject;
import mx.rpc.IResponder;
import spark.components.FormItem;
import spark.components.TextInput;
[SkinPart(required="false")]
/**
* The data capture form.
*/
public var dataCaptureForm:spark.components.Form;
[SkinPart(required="false")]
/**
* Submit button which the agent will press to submit the form.
*/
public var submitBtn:Button;
private var _dataDictionaryInstance:DataDictionaryInstanceModel = null;
private var fieldList:IList = null;
private var phList:IList = null;
private var ddeList:IList = null;
private var textInputFieldList:ArrayCollection = new ArrayCollection();
private var textInputDDEList:ArrayCollection = new ArrayCollection();
private var textInputVariableList:ArrayCollection = new ArrayCollection();
/**
* Wrapper function which invokes the getLetterDataElements of the LetterService
* running on the server
*/
public function letterServiceGetLetterDataElements(letterId:String):AsyncToken
{
var _service:RemoteObject;
_service = com.adobe.icc.services.ServiceLocator.getInstance().getRemoteObject("lc.icc.dbservices.letterService");
var operationToken:AsyncToken = _service.getLetterDataElements(letterId);
return operationToken;
}
protected function getLetterDataElements(invokeParams:InvokeParams):void
{
var operationToken:AsyncToken = letterServiceGetLetterDataElements(invokeParams.letterId);
var responder:IResponder = new Responder(
function(event:ResultEvent):void
{
Debug.info("getLetterDataElements success");
var dataElem:Map = Map.fromObject(event.result as Object);
if(dataElem.hasKey("Field"))
{
fieldList = dataElem.value("Field");
if(fieldList != null && fieldList.length > 0)
{
for(var i:int = 0; i<fieldList.length; i++)
{
var fd:Field = fieldList[i];
var dataCaptureFormItem:FormItem = new FormItem();
dataCaptureFormItem.label = fd.displayName + " Field " + fd.type;
var ti:TextInput = new TextInput();
textInputFieldList.addItemAt(ti, i);
dataCaptureFormItem.addElement(ti);
dataCaptureForm.addElementAt(dataCaptureFormItem, i);
}
}
}
if(dataElem.hasKey("DDE"))
{
ddeList = dataElem.value("DDE");
if(ddeList != null && ddeList.length > 0)
{
for(var j:int = 0; j<ddeList.length; j++)
{
var dde:DataDictionaryElement = ddeList[j];
var dataCaptureFormItem:FormItem = new FormItem();
dataCaptureFormItem.label = dde.displayName + " DDE " + dde.elementType;
var ti:TextInput = new TextInput();
textInputDDEList.addItemAt(ti, j);
dataCaptureFormItem.addElement(ti);
dataCaptureForm.addElementAt(dataCaptureFormItem, i+j);
}
}
}
if(dataElem.hasKey("PH"))
{
phList = dataElem.value("PH");
if(phList != null && phList.length > 0)
{
for(var k:int = 0; j<phList.length; k++)
{
var ph:Variable = phList[k];
var dataCaptureFormItem:FormItem = new FormItem();
dataCaptureFormItem.label = ph.name + " PH " + ph.dataType;
var ti:TextInput = new TextInput();
textInputVariableList.addItemAt(ti, k);
dataCaptureFormItem.addElement(ti);
dataCaptureForm.addElementAt(dataCaptureFormItem, i+j+k);
}
}
}
},
function(faultEvent:FaultEvent):void
{
Debug.error("Error in getLetterDataElements", faultEvent);
}
);
operationToken.addResponder(responder);
}
/**
* Wrapper function which invokes the serializeDataElementsToXML of the LetterRenderService
* running on the server
*/
public function letterRenderServiceSerializeDataElementsToXML(ddiDataAsXml:String, phValues:Object,fieldValues:Object):AsyncToken
{
var _service:RemoteObject;
_service = com.adobe.icc.services.ServiceLocator.getInstance().getRemoteObject("lc.icc.renderlib.letterRenderService");
var operationToken:AsyncToken = _service.serializeDataElementsToXML(ddiDataAsXml, phValues, fieldValues);
return operationToken;
}
private function serializeDataElementsToXML(ddi:String, mapVar:Map, mapField:Map)
{
var operationToken:AsyncToken = letterRenderServiceSerializeDataElementsToXML(ddi, mapVar.toObject(), mapField.toObject());
var responder:IResponder = new Responder(
function(event:ResultEvent):void
{
Debug.info("serializeDataElementsToXML success");
var serializedXML:String = event.result as String;
trace(serializedXML);
var letterRenderService:ILetterRenderService = ServiceProvider.getLetterRenderService();
letterRenderService.renderLetterToFile(invocationParams.letterId, true, serializedXML, false, false).addHandlers(
function(event:ResultEvent):void
{
Debug.info("renderLetter success");
},
function(faultEvent:FaultEvent):void
{
Debug.error("Error in renderLetter", faultEvent);
}
)
},
function(faultEvent:FaultEvent):void
{
Debug.error("Error in serializeDataElementsToXML", faultEvent);
}
);
operationToken.addResponder(responder);
}
private function onSubmitBtnClick(e:Event)
{
var mapField:Map = new Map();
var mapVar:Map = new Map();
for(var i:int=0;i<textInputFieldList.length; i++)
{
var textInput:TextInput = textInputFieldList.getItemAt(i) as TextInput;
if(textInput)
trace(textInput.text);
mapField.assign((fieldList[i] as Field).path, textInput.text);
}
for(var i:int=0;i<textInputVariableList.length; i++)
{
var textInput:TextInput = textInputVariableList.getItemAt(i) as TextInput;
if(textInput)
trace(textInput.text);
mapVar.assign((phList[i] as Variable).name, textInput.text);
}
for(var i:int=0;i<textInputDDEList.length; i++)
{
var textInput:TextInput = textInputDDEList.getItemAt(i) as TextInput;
if(textInput)
trace(textInput.text);
if(textInput.text && textInput.text != "")
_dataDictionaryInstance.setValue((ddeList[i] as DataDictionaryElement).referenceName, textInput.text);
}
var dDEUtilservice:DataDictionaryUtilService = DCTServiceProvider.getUtilService();
dDEUtilservice.serializeDDItoXML(_dataDictionaryInstance.vo,
function(event:DCTServiceEvent):void
{
Debug.info("serializeDDItoXML success");
trace(event.data as String)
serializeDataElementsToXML(event.data as String, mapVar, mapField);
},
function(faultEvent:FaultEvent):void
{
Debug.error("Error in serializeDDItoXML", faultEvent);
}
)
}
Modify the initLetterInstance function as
follows:
protected function initLetterInstance(invokeParams:InvokeParams):void
{
var letterInstanceBuilder:LetterInstanceBuilder = new LetterInstanceBuilder();
letterInstanceBuilder.setInitialXmlData(invokeParams.xmlData);
letterInstanceBuilder.setInitialXmlDataUrl(invokeParams.dataUrl);
letterInstanceBuilder.setLetterId(invokeParams.letterId);
letterInstanceBuilder.setLetterName(invokeParams.letterName);
letterInstanceBuilder.setLetterVersion(invokeParams.letterVersion);
letterInstanceBuilder.setUseTestData(invokeParams.useTestData);
letterInstanceBuilder.setUseLatest(invokeParams.useLatest);
letterInstanceBuilder.build().addHandlers(
function(event:ResultEvent):void
{
Debug.info("LetterInstanceBuilder success");
initialXmlData = event.result.initialXmlData;
letterInstance = event.result.letterInstance;
_dataDictionaryInstance = event.result.dataDictionaryInstance;
if(letterInstance)
{
getLetterDataElements(invokeParams);
}
},
function(faultEvent:FaultEvent):void
{
Debug.error("Error in letter Load", faultEvent);
if(faultEvent.fault && (faultEvent.fault.faultCode == "loadLetterFault" || faultEvent.fault.faultCode == "letterInstanceBuildFailure"))
{
ErrorManager.showMessage(resourceManager.getString('Messages', 'errorTitle'),resourceManager.getString('Iccuser interfaceStrings', 'errorLoadLetterTitle'),null,ErrorManager.Error_Icon,0xFFFF);
return;
}
ErrorManager.handleFault(faultEvent.fault, resourceManager.getString("Common","typeLetter"));
}
);
}
Add the click handler for the submit button in the partAdded
function as follows: else if(instance == submitBtn)
submitBtn.addEventListener(MouseEvent.CLICK, onSubmitBtnClick);
Navigate to CreateCorrespondence > src > com.adobe.solutions.cmg.Create Correspondence > skins.
Open the file CCRApplicationSkin.mxml. Replace the entire
content of this file with the source code below to create a form
with the data elements and a Submit button. Alternatively
you can create a skin file. Provide the reference of newly created
skin file in the CreateCorrespondence > src > CSS > CSS_styles.css. <?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="100%" height="100%" >
<fx:Metadata>
[HostComponent("com.adobe.solutions.cmg.ccr.presentation.CCRApplication")]
</fx:Metadata>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.core.user interfaceComponent;
]]>
</fx:Script>
<s:states>
<s:State name="initializing" />
<s:State name="normal" />
<s:State name="review" />
<s:State name="disabled"/>
</s:states>
<s:Rect left="0" right="0" top="0" bottom="0" >
<s:fill>
<s:SolidColor id="bgColor" color="0xeeeeee" alpha="1.0" />
</s:fill>
</s:Rect>
<s:Group width="100%" height="100%" >
<s:layout>
<s:VerticalLayout gap="0" />
</s:layout>
<s:Scroller width="100%" height="100%" >
<s:VGroup gap="0" width="100%" >
<s:Form id="dataCaptureForm" width="100%" height="100%" >
<!-- dataCaptureItems here dynamically -->
</s:Form>
</s:VGroup>
</s:Scroller>
<s:Button id="submitBtn" width="50" height="20" label="Submit"/>
</s:Group>
</s:SparkSkin>
Rebuild and Redeploy. For information on rebuilding and redeploying,
see Building and deploying the Solution Template.
Create Correspondence now creates forms with all the data elements.
Agent can fill in the values and hit the submit button at the bottom
to create the letter.
The steps describe this approach create the alternate data capture
functionality but there are a few limitations in the above implementation: It does not render the data capture form fields based on
the data type.
It does not display the default values of the data elements
retrieved, but presents a blank text field for all the data elements.
There are limitations with the _dataDictionaryInstance.setValue
function and it fails for collection type of DDEs.
Tools usedThis scenario uses Flash Builder to create the skin and
modify the solution template.
|
|
|