Friday, June 21, 2013

Creating datatable in an Alfresco activiti workflow task form using YUI and Web scripts

As mentioned in the title, in this article we will learn an advanced  Alfresco workflow feature: implementing datatables to display data in a workflow form.
This article assumes you have some knowledge of Alfresco and Activiti workflows. If this is not the case, you can refer to Alfresco docs. Good tutorials can be found here, especially the article concerning advanced workflows (PDF available here) .

1) Modeling the workflow

When developing workflows, first thing after reading and analyzing requirements is to model workflow. So if you already didn't you may install the Activiti BPMN 2.0 Designer plug-in for eclipse (install URL is here).
For the simplicity of this article, we will assume we have a simple workflow containing only one task that displays a datatable filled by dynamic data (remember, this is our main goal).
So here you can find the process definition:

    

    
 
       
    
 
      
        
          
            
    var jsonData ;
    var tableSize = 10;
    for(var i = 0; tableSize >i; i++){     
     if(i != 0){
      jsonData = jsonData+',{ "user": user"'+i+'","data1":data1_"'+i+'","data2":data2_"'+i+'","data3":data3_"'+i+'" }';
     }else{
      jsonData = '[{ "user": user"'+i+'","data1":data1_"'+i+'","data2":data2_"'+i+'","data3":data3_"'+i+'" }';
     }     
    }
    jsonData += ']';
    execution.setVariable('lrwf_userData',jsonData);                
   
          
                
      
    
 
 



 
The important part here is the activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener" element. It's in the create event that we prepare data to be displayed in the simpleTask form.
The data that will be sent to the client is in JSON format.
Another point to mention, is that we defined a custom formKey  for our task. The custom type lrwf:simpleTask will be defined in next step.
Now save the above code in "simple-process-datatable.bpmn" under "alfresco/module/custom/workflows/"

2) Workflow content model

Now that the workflow has been defined, next step is to integrate the process with the Alfresco UI by defining the content model and updating the client configuration (Alfresco Share). 
To do that, open the file: Repository/config/alfresco/application-context.xml (this is the starting point of the Spring configs of Alfresco). Then add the following line:
<import resource="classpath*:alfresco/module/custommodel/workflow-context.xml"/>
In workflow-context.xml we declare paths and names of our custom workflow model and process definitions:

 
  
   
    
     activiti
     alfresco/module/custom/workflows/simple-process-datatable.bpmn
     
     text/xml
     true
        
   
  
  
            
                alfresco/module/custom/model/workflowModel.xml
            
        
        
            
                alfresco.module.custom.messages.customWorkflow
            
        
 

In this config file, we define a)workflow definitions: engineId (in Alfresco 4 and above you can use both activiti and jBPM), path to process definition and otherproperties, b)workflow content model, i.e.: types of custom tasks, aspects etc... and c) path to message bundle. Next we define our content model, so in "workflowModel.xml":
 




 
 Custom Workflow Model
 Laâbidi RAISSI
 1.0

 
 
  
  
  
  
     
        
        
        
  
 

 
 
  
 
 
 
  
            bpm:activitiOutcomeTask
            
                
                    d:text
                    DefaultValue
                    
                        
                            
                                
                                    Reject
                                    DefaultValue
                                    Approve
                                
                            
                        
                    
                                
            
            
                
                    edit_package_item_actions
                
                
                    {http://www.telec.com/model/workflow/1.0}customOutcome
                
            
                         
             lrwf:withUserDataTable             
          
        
  
 
 
  
   Data that will be displayed in a datatable
   
    
     d:text
     false
     true
    
   
  
 


If you are using Eclipse than these files should go under Repository project. If not then, root directory is; TOMCAT_HOME/webapps/alfresco/WEB-INF/classes and there create the paths I already mentioned for every file.

3) Client configuration

Now we go to configure the client part (Share: share webapp under Tomcat). If you didn't already, go to "Slingshot project /config/alfresco/slingshot-application-context.xml" and declare path to Share Custom Config file to define forms contents:

classpath:alfresco/web-extension/share-config-custom.xml
jar:*!/META-INF/share-config-custom.xml
In file: "share-config-custom.xml" define forms config, in particular fields to display and their control templates:

 
      
         
You can see here, that we defined a config element, having "task-type" as evaluator and the name of our task as condition. In this element, we define properties that will be displayed to client. Also in the "appearance" sub-element, we attached to every field (property) its label, the "set" where it will be displayed and the "control" that will be responsible for its rendering. The control that matters for us is the control part (we declared one named "userDataTable.ftl" to render our datatable. This is a Freemarker template.
So in Slingshot project, under the defined path, create a file named "userDataTable.ftl":
<#assign controlId = fieldHtmlId + "-cntrl">



Here we just defined html elements that will contain the datatable, and we call a new Javascript function. We will use the YUI library (included by defualt in Alfresco and used to render almost everything in Share). So create a Javascript file "userDataTable.js" to handle data and build datatable. You can download the file from here.

Finally, in "Web Framework Commons/config/alfresco/site-webscripts/org/alfresco/components/form/form.get.head.ftl"
include "userDataTable.js" and eventually "userDataTable.css" if you don't like the default looking of YUI:
<@link rel="stylesheet" type="text/css" href="${page.url.context}/res/components/form/userDataTable.css" />
<@script type="text/javascript" src="${page.url.context}/res/components/form/userDataTable.js">
Et voilà!!! You have a pretty datatable to display info in your workflow tasks.

2 comments:

  1. Do you have any example for showing the custom simple dialog which accepts user data on clicking the workflow transition button (approve or reject) ?

    ReplyDelete