Thursday, November 15, 2018

Add Documents to Case SubFolder On Add Case Page Using An Entry Template - IBM Case Manager

Hi there guys , in a previous blog i provided a nice trick to add documents to a case sub folder directly after adding a new case ,check here :
 https://ecmmania.blogspot.com/2017/07/add-documents-to-case-subfolder-on-add.html

Today , i  would continue on this trick and add a new feature which is adding the documents to the case subfolder using an entry template

Thanks to the inspiration from this post :
 https://www.ibm.com/developerworks/community/blogs/e8206aad-10e2-4c49-b00c-fee572815374/entry/add_a_document_with_an_entry_template_using_icm_5_2?lang=en

i used the same idea he's using but simplified the code by using build-in functions instead of writing custom code myself

the only add-on to the previous code that i used is that iam now retrieving the entry template with the vs-Id and passing this entry template to the Add Content Item Dialog to open the dialog with the entry template 

 the trick here is that by default adding the document by an entry template it would add the doc to the predefined folder configured in the entry template or you would have to choose the folder manualy if configured like this from the entry template settings

so how to add the doc to the case subfolder  ? in the callback of the addContentItemDialog on pressing the add button we are filling the chosen doc to the subfolder , that's it

one limitation of this implementation is that always there will be a copy of the added doc in the folder specified in the entry template settings plus the one add in the case subfolder , i have to work on this one in the future :D 

so let's get to the code : 

on the add case page insert a new script adapter 

 :choose the wiring like this 

Case Toolbar (case created) ----> Script Adapter(Recieve eveny payload)


the code is as follows : 

make sure to change the vs-id to the one of your entry template and to change the path to the sub folder you want



require(["dojo/Deferred",
"dojo/dom",
"dojo/on",
"ecm/widget/dialog/AddContentItemDialog",
"dojo/domReady!"
], function(Deferred, dom, on, AddContentItemDialog) {
var getEntryTemplate = function(repository, entryTemplateId) {
var deferred = new Deferred();
repository.retrieveItem(null, function(item) {
//var entryTemplate = repository.getEntryTemplateById(item.id,item.name, item.objectStore);
var entryTemplateItem = {};
entryTemplateItem.entryTemplate = item;
entryTemplateItem.repository = repository;
deferred.resolve(entryTemplateItem);
},
"EntryTemplate",
"current",
entryTemplateId);
return deferred.promise;
};
var getCaseFolder = function(payload) {
var deferred = new Deferred();
var caseEditable = payload.caseEditable;
console.log("caseEditable");
console.log(caseEditable);
caseEditable.getCase().retrieveCaseFolder(function(parentCaseFolder) {
deferred.resolve(parentCaseFolder);
});
return deferred.promise;
};
var getSubFolder = function(parentCaseFolder, subFolderPath) {
var deferred = new Deferred();
console.log("parentCaseFolder");
console.log(parentCaseFolder);
var rootPath = parentCaseFolder.attributes.PathName;
var fullPath = rootPath + "/" + subFolderPath;
parentCaseFolder.repository.retrieveItem(fullPath, function(subfolder) {
console.log("Subfolder");
console.log(subfolder);
deferred.resolve(subfolder);
}, null, null, null, null, null);
return deferred;
};
var executeFn = function(payload) {
//vs-id of the entry template
var entryTemplateId = "{84F966D4-A6E5-C65A-8A97-67140EB00000}";
//the sub folder path like "Sub1/Sub2/Sub3"
var subFolderPath = "F1";
var getCaseFolderPromise = getCaseFolder(payload);
getCaseFolderPromise.then(function(parentCaseFolder) {
return getSubFolder(parentCaseFolder, subFolderPath);
}).then(function(subfolder) {
console.log("Promise Sub Folder");
console.log(subfolder);
console.log("Promise Repo ID");
console.log(subfolder.repository.repositoryId);
var repository = ecm.model.desktop.getRepository(subfolder.repository.repositoryId);
console.log("Promise repository");
console.log(repository);
var getEntryTemplatePromise = getEntryTemplate(repository, entryTemplateId);
getEntryTemplatePromise.then(function(entryTemplateItem) {
console.log("entryTemplateItem");
console.log(entryTemplateItem);
var entryTemplate = entryTemplateItem.entryTemplate;
var repository = entryTemplateItem.repository;
var addContentItemDialog = new AddContentItemDialog();
addContentItemDialog.showUsingTemplateItem(repository, subfolder, true, false, function(addedItem) {
console.log("addedItem");
console.log(addedItem);
subfolder.addToFolder(addedItem, function() {
console.log('Document added to sub folder ');
});
}, null, entryTemplate);
});
});
};
executeFn(payload);
});

Tuesday, February 6, 2018

Advanced Attachment validation based on which step response is selected - IBM Case Manager

Hi Guys , Iam back after a long stay away from the blog ,  here i will present an advanced scenario to validate that a certain attachment of a certain document class has an item content uploaded to it and that a certain number of versions are uploaded to this attachment.

The Biggest Main change from the previous post is the usage of deferred and promises , a big problem that some people has complained about the previous method that i wrote about validating the attachment is that sometimes it's working and sometimes it's not and that problem has been risen from the fact that a lot of the functions iam using to validate the attachments are asynchronous functions so sometimes the attachment check sequence is continued without the result of the asynchronous function call being provided 

so the usage of the promises and deferred will solve this problem , as i will use a deferred for each asynchronous function so that i will use it's promise to continue execution and checking , i mean i will use a chain of promises until i can get the final result of the check 

for example let's say i want to know a certain value of variable D and variable D can be only retrieved by a chain of asynchronous function calls as follows : 

Call Function1() then the callback  ---> retrieve variable A)
 Only if variable A is retrieved i can get Variable B
 Only if variable B is retrieved i can get Variable C
 Only if variable C is retrieved i can get Variable D

so the idea here is to use a chain of deferred and promises and after resolving each promise we continue execution

please check this tutorial for further info : further reading

in this example i provide a custom logic as follows :

i retrieve all the  attachment properties  i can get from the work item then validate each attachment to see which one represents the NOC attachment , then i retrieve all the content items attached to this NOC and check that the number of versions uploaded to the NOC is 2 or greater so it means that someone re uploaded a document to the attachment

 the additional validation  will be placed in a Script Adapter widget. 
  • Add a Script Adaptor widget to the hidden widgets area on a work details page
  • Wire an inbound event from the Page Container's Send Work Item to the Script Adaptor's Receive Event.
  • The additional data validation logic will be triggered when the appropriate response button is clicked

here is the code : 
           require(["icm/base/Constants", "icm/model/properties/controller/ControllerManager", "dojo/Deferred", "dojo/promise/all"],  
             function(Constants, ControllerManager, Deferred, all) {  
               var workItemEdt = payload.workItemEditable; // getting workitemEditable.  
               var coord = payload.coordination; // getting coordination.  
               _globalCaseEditable = workItemEdt; // assigning workitemEditable to _globalCaseEditable for global scope.  
               //validation for NOC Signing  
               coord.participate(Constants.CoordTopic.VALIDATE, function(context, complete, abort) {  
                 var collectionController = ControllerManager.bind(_globalCaseEditable);  
                 // Validate if response is Reject  
                 if (context[Constants.CoordContext.WKITEMRESPONSE] === "Submit") {  
                   //check that the document is signed  
                   var propertiesCollection = _globalCaseEditable.propertiesCollection;  
                   var isSigned = false;  
                   var checkIfSigned = function(propertiesCollection) {  
                     var deferred = new Deferred();  
                     var versionDeferred = new Deferred();  
                     var contentItemPromisArr = [];  
                     var versionsPromisArr = [];  
                     var isSignedFlag = false;  
                     if (propertiesCollection) {  
                       var k;  
                       for (k in propertiesCollection) {  
                         if (propertiesCollection.hasOwnProperty(k)) {  
                           var p = propertiesCollection[k];  
                           if (p.dataType == "xs:attachment") {  
                             console.log("Found Attachment Field-->" + k);  
                             p.retrieveAttachmentContents(function(items) {  
                               contentItemPromisArr.push(items[0]);  
                             });  
                           }  
                         }  
                       }  
                     }  
                     all(contentItemPromisArr).then(function(contentItems) {  
                       console.log("All Content Items");  
                       console.log(contentItems);  
                       for (var i = 0; i < contentItems.length; i++) {  
                         var item = contentItems[i];  
                         if (item.template == "WorkPermitNOC") {  
                           item.retrieveAllVersions(function(resultSet) {  
                             versionDeferred.resolve(resultSet);  
                           });  
                           versionDeferred.then(function(resultSet) {  
                             var versionsContentItem = resultSet.items;  
                             console.log("Versions");  
                             console.log(versionsContentItem);  
                             console.log("version length");  
                             console.log(versionsContentItem.length);  
                             if (versionsContentItem.length >= 2) {  
                               isSignedFlag = true;  
                               var lastElementIndex = versionsContentItem.length - 1;  
                               console.log("last version -- " + lastElementIndex);  
                               console.log(versionsContentItem[lastElementIndex].attributes.LastModifier);  
                               console.log("last version isSigned-- " + isSignedFlag);  
                             }  
                             deferred.resolve(isSignedFlag);  
                           });  
                         }  
                       }  
                     });  
                     return deferred;  
                   }  
                   checkIfSigned(propertiesCollection).then(function(isSigned) {  
                     if (isSigned) {  
                       console.log("Document is Signed with a working version");  
                       /*abort({  
                        "message": "<strong>Document is Signed MAN !!! :) :) </strong>"  
                       });*/  
                       complete();  
                     } else {  
                       console.log("Document is not working");  
                       abort({  
                         "message": "<strong>Please sign the NOC document before submitting the request.</strong>"  
                       });  
                     }  
                   });  
                 } else {  
                   complete();  
                 }  
                 ControllerManager.unbind(_globalCaseEditable);  
               });  
             });  

Sunday, August 6, 2017

Extending Datacap Add Document Dialog for entry templates

Hi there folks , iam back with a new blog entry for a new trick i have came across the past few days

as some of you do know that IBM provided a datacap navigator plugin that will install new custom actions that enable the user to add a new document using a scanner along with old the ways of adding a local document , an item or a document from an external url.

Once you choose to get a document from a scanner it will start the scanner module in the dialog and you can begin to scan document and edit them on the fly and append the document as a content item to the navigator object store.

this new dialog extends the original ecm/widget/dialog/AddContentItemDialog and adds the new capabilities mentioned above.


the problem we faced was with using this new custom dialog is that if you open the dialog and pass the entry template to it , the dialog opens without the option to add a document from a scanner as with the normal add document so i made a small trick that will do the needed and i thought a bout sharing it with you as a guideline for future customization

what i do is i made a new custom action for the entry templates so once you click on the entry template in the entry template feature i retrieve the content item of the entry template and then get the full entry template and pass it to the new addContentItemDialog of the datacap and here comes the interesting part:

i catch the widget of the content source type and prepare a new choice list for the widget then call the function of the widget to add the new choices and of course the widget will handle the change of the choicelist value

here is a code snippet :


lang.setObject("datacapCustomScanAction", function(repository, items, callback, teamspace, resultSet, parameterMap) {


this.repository = repository;
this.ETContentItem = items[0];
console.log("ETContentItem");
console.log(this.ETContentItem);
this.entryTemplate = repository.getEntryTemplateById(ETContentItem.id,ETContentItem.name,ETContentItem.objectStore);
console.log("this entryTemplate");
console.log(this.entryTemplate);
 
console.log("entry template NOTT retrieved!!");
//retrieve the setting for the entry templates then show the dialog
this.entryTemplate.retrieveEntryTemplate(dojo.hitch(this, function (retrievedEntryTemplate) {
      // Do something with retrievedEntryTemplate
console.log("retrievedEntryTemplate");
console.log(retrievedEntryTemplate);
console.log("This.Repository");
console.log(this.repository);
console.log("retrievedEntryTemplate.addClassName");
console.log(retrievedEntryTemplate.addClassName);
console.log("retrievedEntryTemplate.folder");
console.log(retrievedEntryTemplate.folder);
this.retrievedEntryTemplate = retrievedEntryTemplate;
if(this.addContentItemDialog){
this.addContentItemDialog.destroyRecursive();
}
this.addContentItemDialog = new AddContentItemDialog();
this.addContentItemDialog.setDefaultContentClass(retrievedEntryTemplate.addClassName);
this.addContentItemDialog.show (this.repository, null, true, false, null, null, true, retrievedEntryTemplate,false,null);
var choices = [];
if (this.addContentItemDialog._entryTemplate.allowSaveLocalDocument) {
choices.push("Document");
}
if (this.addContentItemDialog._entryTemplate.allowSavePropertiesOnly) {
choices.push("Item");
}
if (this.repository._isP8()) {
if (this.addContentItemDialog._entryTemplate.allowSaveExternalDocumentLink) {
choices.push("ExternalURL");
}
}
choices.push("Scanner");
this.addContentItemDialog.addContentItemGeneralPane.addContentSourceTypeChoices(choices);

 
   }), false, true);
 
 





});


Wednesday, July 12, 2017

Add Documents to Case SubFolder On Add Case Page - IBM Case Manager

Hi there guys , in a previous blog i provided a nice trick to add documents to a case directly after adding a new case ,check here : http://ecmmania.blogspot.ae/2017/06/add-documents-to-case-on-add-case-page.html

today i was playing a round and trying to understanding a bit further dojo deferred and promises and at last i found a trick to be able to add documents to a case subfolder directly after adding a new case,

the main problem in my old code is that you can only add docs to the root case folder not to a sub folder and by trying to use callbacks to retrieve the case sub folder then opening the dialog you can see that the chain is broken and the code won't execute and will break

this problem arises from the fact that you can make only one asynchronous call and then use the callback to retrieve the response and do something with it

 but using deferreds and promises i can do it now , the main ideas is to make like a chain of promises that depend on each other and once a promise is fulfilled the next promise will be triggered so i first make a deferred to get the case folder then another deferred to get the case sub folder and lastly i open a add content item dialog to add document to the case sub folder

i will leave you with the code , i wrapped it inside a function you can just call and pass the payload to it , you can also change the path of the subfolder that you want to store into or maybe create your custom add content item dialog and show it

addSubFolderDocs: function(payload) {
require(["dojo/Deferred", "dojo/dom", "dojo/on", "dojo/domReady!"],function(Deferred, dom, on){
 
var getCaseFolder = function(payload){

   var deferred = new Deferred();
var caseEditable = payload.caseEditable;
console.log("caseEditable");
console.log(caseEditable);
caseEditable.getCase().retrieveCaseFolder(function(parentCaseFolder){

deferred.resolve(parentCaseFolder);

});

return deferred.promise;

};

/*var showAddDocumentDialog = function(parentCaseFolder){

   var deferred = new Deferred();
var repositroy = parentCaseFolder.repository;
console.log("repositroy");
console.log(repositroy);
var addContentItemDialog = new ecm.widget.dialog.AddContentItemDialog();  
addContentItemDialog.show(repositroy, parentCaseFolder,true, false, function(addedItem){

addToSubFolder(addedItem);

}, null, false, null);


return deferred.promise;

};*/


var getSubFolder = function(parentCaseFolder){

   var deferred = new Deferred();
   console.log("parentCaseFolder");
   console.log(parentCaseFolder);
var rootPath = parentCaseFolder.attributes.PathName;
var fullPath = rootPath + "/" + "Leasing Documents";
parentCaseFolder.repository.retrieveItem(fullPath, function(subfolder){
   console.log("Subfolder");
   console.log(subfolder);
   deferred.resolve(subfolder);

}, null, null, null, null, null);

return deferred;
};


/*var folderRetrievedCB = function(subfolder,addedItem){
console.log("enter --> folderRetrievedCB <----this items to add");
console.log(addedItem);
console.log("enter --> folderRetrievedCB <----subfolder " + subfolder);
subFolder.moveToFolder(addedItem,addedItem.parent,function(response){
console.log("Response");
console.log("response");

});
subFolder.refresh(subFolder);
};*/



var executeFn = function(payload){

var getCaseFolderPromise = getCaseFolder(payload);
getCaseFolderPromise.then(function(parentCaseFolder){
     return getSubFolder(parentCaseFolder);
}).then(function(subfolder){

console.log("Promise Sub Folder");
console.log(subfolder);
console.log("Promise Repo ID");
console.log(subfolder.repository.repositoryId);
var repository = ecm.model.desktop.getRepository(subfolder.repository.repositoryId);
console.log("Promise repository");
console.log(repository);
var addContentItemDialog = new ecm.widget.dialog.AddContentItemDialog();  
addContentItemDialog.show(repository, subfolder,true, false, function(addedItem){

console.log("addedItem");
console.log(addedItem);

}, null, false, null);
});

};


executeFn(payload);


});



return payload;
}


Saturday, July 8, 2017

ICM 5.3.1 New Markup widget and Quick Tasks

in an update to the Awesome new IBM Case Manager Version 5.3.1 , Mr Dave Perman from IBM Team has shed light to 2 new features introduced in this version : The Markup Widget and the Quick Tasks

You Can check out the new Markup widget in this ECM Blog Entry
https://www.ibm.com/developerworks/community/blogs/e8206aad-10e2-4c49-b00c-fee572815374/entry/July_7_2017_at_8_43_23_PM?lang=en

and the New Quick Tasks in This blog entry
https://www.ibm.com/developerworks/community/blogs/e8206aad-10e2-4c49-b00c-fee572815374/entry/Announcing_the_Newest_Member_of_the_IBM_Case_Manager_Task_Family?lang=en

To be honest , i can't wait to get my hands on a virtual machine with the new version installed on it so i can start exploring it ☺😃😃

Wednesday, July 5, 2017

Build Your Own Customized ICN Eclipse Plug-in for IBM Content Navigator development

Hi there, a lot of times when you want to use the icn plugin jars to allow for icn plugin development Wizard appearing in eclipse New Project Wizard , you don't get the wizard working fine for each eclipse package as  the old jars ibm provided worked for certain eclipse packages only

IBM ICN Dev team has put a new project that you can use to get a customized jars for your own eclipse package then you can drop these new plugins in the dropins folder to get the icn plugin new project wizard when you create a new project

you can find the project and the details to how to customize it here in this ibm team repository along with instructions

https://github.com/ibm-ecm/ibm-content-navigator-samples/tree/master/eclipsePlugin

one small hint that could be useful:

during update bundle-version number for your Eclipse in MANIFEST.MF , you can't get the exact version by yourself so to get it automatically just press the old version written in the manifest file and press CTRL + SPACE that will get you the exact version for your eclipse

That's it

Enjoy :) 

Saturday, July 1, 2017

New IBM Case Manager v5.3.1 !

Announced just a few days ago

IBM Case Manager v5.3.1 Now Available!


 Thanks to Dave Perman from IBM team , he puplished 2 articles in the ECM Community Blog  where he provided a summary blog for the new features in this link

https://www.ibm.com/developerworks/community/blogs/e8206aad-10e2-4c49-b00c-fee572815374/entry/IBM_Case_Manager_v5_3_1_Now_Available?lang=en

and the great surprise is the new features they provided in the user interface found at this article

https://www.ibm.com/developerworks/community/blogs/e8206aad-10e2-4c49-b00c-fee572815374/entry/Styles_and_Layouts_in_IBM_Case_Manager_5_3_1?lang=en

A New Style , New widgets containers and markup widgets ^_^  and sure they provided a list of new exciting features still to be revealed !

still we need to see it in person to believe but it's a great step towards more friendly UI 

Way to Go IBM ! :) Keep it up