Presentation Title

Download Report

Transcript Presentation Title

Workflow Dashboard Custom Dashlet
(Replacement for My Tasks)
14 November 2013
Bill Young, Flatirons Solutions
#SummitNow
Overview
Justification
Problem Analysis
Solution
#SummitNow
#SummitNow
Justification
Overview of All Active Workflows
More Workflow Detail
Single Point of Control
Tabular Representation
Column Ordering
Column Filtering
#SummitNow
#SummitNow
Workflow Details
Workflow Type
Task Status
Task Owner
Task Start Date/Time
Workflow Diagram
#SummitNow
#SummitNow
Problem Analysis
OOTB Features on Different Screens
Some Features Not Available
Custom Dashlet to Unify Needs
Modify My Tasks - Insufficient
#SummitNow
#SummitNow
Solution
Dashlet Screenshot
Dashlet Template
Java Webscript
Dashlet JavaScript
#SummitNow
#SummitNow
Dashlet Screenshot
#SummitNow
#SummitNow
Dashlet Template
#SummitNow
#SummitNow
Dashlet Template
workflowstatus.get.desc.xml
<webscript>
<shortname>Workflow Status</shortname>
<description>Display status of running workflows</description>
<family>user-dashlet</family>
<url>/components/dashlets/workflowstatus</url>
</webscript>
#SummitNow
#SummitNow
Dashlet Template
workflowstatus.get.head.ftl
<#include "/org/alfresco/components/component.head.inc">
<!-- Workflow Actions -->
<@script ... src="${page.url.context}/res/components/workflow/workflow-actions.js" />
<!– jQuery -->
<@link ... href="${page.url.context}/res/scripts/css/jquery-ui-1.8.16.css" ... />
<@link ... href="${page.url.context}/res/scripts/css/datatable_jui.css" ... />
<@script ... src="${page.url.context}/res/scripts/js/jquery-1.6.4.min.js" />
<@script ... src="${page.url.context}/res/scripts/js/jquery-ui-1.8.16.custom.min.js" />
<@script ... src="${page.url.context}/res/scripts/js/jquery.dataTables.min.js" />
<@script ... src="${page.url.context}/res/scripts/js/jquery.dataTables.columnFilter.js" />
<!-- Custom -->
<@link ... href="${...}/res/scripts/components/flatirons/dashlets/workflowstatus.css" />
<script ... src="${...}/res/scripts/components/flatirons/dashlets/workflowstatus.js" />
#SummitNow
#SummitNow
Dashlet Template
workflowstatus.get.html.ftl
<#assign id = args.htmlid>
<#assign jsid = args.htmlid?js_string>
<script type="text/javascript">//<![CDATA[
(function(){
new Flatirons.dashlet.WorkflowStatus("${jsid}").setOptions( {
maxItems: ${maxItems!"50"},
}).setMessages(${messages});
new Alfresco.widget.DashletResizer("${id}", "${instance.object.id}");
})();
//]]></script>
<div class="dashlet workflowstatus">
<div class="title">${msg("dashlet.title")}</div>
<div class="toolbar flat-button"><-- button row --></div>
<div class="body scrollableList" <#if args.height??>style="height: ${args.height}px;"</#if>>
<div id="loading"><span><img src="${url.context}/res/scripts/img/load.gif" /> Loading...</span></div>
<div id="wfstatus-tasks"></div>
</div>
</div>
#SummitNow
#SummitNow
Webscript
UML and Java code
#SummitNow
#SummitNow
UML
#SummitNow
#SummitNow
Java Code
public abstract class AbstractWorkflowWebscript extends AbstractWebScript {
/** Service Registry */
private ServiceRegistry serviceRegistry;
/** Cache manager */
private CacheManager cacheManager;
. . . Getters/Setters . . .
#SummitNow
#SummitNow
Java Code
public void execute(final WebScriptRequest req, final WebScriptResponse res)
throws IOException {
IWorkflowWebscriptModelBuilder modelBuilder =
new WorkflowStatusModelBuilder(getServiceRegistry(),
getCacheManager(), schedulersMap, solrURL,
req.getParameter("username"));
res.getWriter().write(modelBuilder.getJSONResponse());
}
#SummitNow
#SummitNow
UML
#SummitNow
#SummitNow
Java Code
public interface IWorkflowWebscriptModelBuilder {
/**
* Get the collection of workflow information.
*
* @return JSON representation for workflow information
*/
String getJSONResponse();
}
#SummitNow
#SummitNow
Java Code
public String getJSONResponse() {
JSONObject jsonObj = new JSONObject();
jsonObj.put("data", makeDataArray());
return jsonObj.toString();
}
#SummitNow
#SummitNow
Java Code
protected JSONArray makeDataArray() {
JSONArray jsonArray = new JSONArray();
// get workflow and task information
Map<String, Map<String, List<JSONObject>>> workflowsMap =
getWorkflowsMap(workflowService.getActiveWorkflows());
for (String workflowName : workflowsMap.keySet());) { // Iterate the workflows
Map<String, List<JSONObject>> tasksMap = workflowsMap.get(workflowName);
for (String taskName : tasksMap.keySet()) {// Iterate Tasks/Paths
// Process the list of JSON Objects representing the workflow instances
for (JSONObject dataObject : tasksMap.get(taskName)) {
if (dataObject != null) {
jsonArray.add(dataObject);
}
}
}
}
return jsonArray;
}
#SummitNow
#SummitNow
JSON Response
"workflowData": [
{
"workflowName": "activiti$FlatironsCustomEdit",
"taskName": "adwf$directorProcessSelectionEditTask", "lastCompletedTask": "",
"taskId": "activiti$17844", "taskTitle": "Director Choice",
"owneruserName": "byoung", "ownerfirstName": "Bill", "ownerlastName": "Young",
"isPooled": true, "isEditable": true, "isSystemTask": false,
"isExecutingTask": false, "isQueuedTask": false, "isFailedTask": false,
"initiatoruserName": "byoung",
"initiatorfirstName": "Bill", "initiatorlastName": "Young",
"workPackageName": "Summit C", "count": "46", "startDate": 1382814274000,
. . .
},
. . .
]
#SummitNow
#SummitNow
JSON Response
"prefs": {
"numItemsDisplayed": "-1",
"filterValues": [
"", "", "Actions",
"Bill%20Young%20%28byoung%29",
"Work Package", "Count", "", "Last Activity"
],
"sortValues": [
"sorting", "sorting", "sorting_disabled", "sorting",
"sorting", "sorting_disabled", "sorting",
"sorting_desc"
]
}
#SummitNow
#SummitNow
Dashlet JavaScript
YUI plus jQuery Data Tables
if ((typeof Flatirons == "undefined") || !Flatirons) {
var Flatirons = {};
}
/**
* Flatirons top-level dashlet namespace.
*
* @namespace Flatirons
* @class Flatirons.dashlet
*/
Flatirons.dashlet = Flatirons.dashlet || {};
#SummitNow
#SummitNow
Dashlet JavaScript
/**
* Dashboard WorkflowStatus component.
*
* @namespace Flatirons.dashlet
* @class Flatirons.dashlet.WorkflowStatus
*/
(function() {
/**
* YUI Library aliases
*/
var Dom = YAHOO.util.Dom, Event = YAHOO.util.Event, Selector = YAHOO.util.Selector;
/**
* Alfresco Slingshot aliases
*/
var $html = Alfresco.util.encodeHTML, $siteURL = Alfresco.util.siteURL;
#SummitNow
#SummitNow
Dashlet JavaScript
/**
* Dashboard WorkflowStatus constructor.
*
* @param {String} htmlId The HTML id of the parent element
* @return {Flatirons.dashlet.WorkflowStatus} The new component instance
* @constructor
*/
Flatirons.dashlet.WorkflowStatus = function WorkflowStatus_constructor(htmlId) {
Flatirons.dashlet.WorkflowStatus.superclass.constructor.call(this,
"Flatirons.dashlet.WorkflowStatus", htmlId,
[ "button", "container", "datasource", "datatable", "paginator", "history",
"animation" ]);
return this;
};
#SummitNow
#SummitNow
Dashlet JavaScript
/**
* Extend from Alfresco.component.Base
*/
YAHOO.extend(Flatirons.dashlet.WorkflowStatus, Alfresco.component.Base);
/**
* Augment prototype with Common Workflow actions to reuse createFilterURLParameters
*/
YAHOO.lang.augmentProto(Flatirons.dashlet.WorkflowStatus,
Alfresco.action.WorkflowActions);
#SummitNow
#SummitNow
Dashlet JavaScript
/** Augment prototype with main class implementation, ensuring overwrite is enabled */
YAHOO.lang.augmentObject(Flatirons.dashlet.WorkflowStatus.prototype, {
/**
* Object container for initialization options
* @property options
* @type object
*/
options : {
/**
* Maximum number of tasks to display in the dashlet.
* @property maxItems
* @type int
* @default 50
*/
maxItems : 50,
},
#SummitNow
#SummitNow
Dashlet JavaScript
/** Fired by YUI when parent element is available for scripting */
onReady : function WorkflowStatus_onReady() {
// Set event listeners to notice when anything is
// changed so that change can be saved to prefs.
$('#wfstatus-tasks-table_length').live('change', function(event) {
WorkflowStatus_updatePrefs();
});
$('#wfstatus-tasks-table thead tr th').live('click', function(event) {
WorkflowStatus_updatePrefs();
});
$('#wfstatus-tasks-table thead tr th span input').live(
'propertychange keyup input paste', function(event) {
WorkflowStatus_updatePrefs();
});
#SummitNow
#SummitNow
Dashlet JavaScript
$("#wfstatus-loading").show();
var msgRef = this;
var cur_call = $.ajax({
dataType : 'json',
url : Alfresco.constants.PROXY_URI
+ 'flatirons/workflowstatus?username=‘
+ Alfresco.constants.USERNAME,
method : 'get',
cache : false,
success : function(data) { /* build table */ },
error : function(xhr, ajaxOptions, error) { /* show error */ }
});
}
#SummitNow
#SummitNow
Dashlet JavaScript
var prefsItem = data.data[0].prefs;
var workflowDataItem = data.data[0].workflowData;
for (var itemIndex in workflowDataItem) {
var item = workflowDataItem[itemIndex];
// build cells from workflow item
row = '<tr>' + workflowType + task + actions + initiator + workPackage
+ countInfo + claimant + lastActivityTime + '</tr>';
// put row in table
}
// attach data table behavior
var resTable = $('#wfstatus-tasks-table').dataTable({
. . .
});
#SummitNow
#SummitNow
Dashlet JavaScript
/**
* Post the JSON map of user preferences to the Alfresco user preferences webscript
*
* @method: WorkflowStatus_updatePrefs
*/
function WorkflowStatus_updatePrefs() {
var prefs = {};
prefs.numItemsDisplayed = $('#wfstatus-tasks-table_length').find(":selected").val();
. . .
this.preferencesService = new Alfresco.service.Preferences();
var config = {
failureCallback : { . . . },
successCallback : { . . . }
};
this.preferencesService.set("com.flatirons.workflow.status.preferences", prefs, config);
};
#SummitNow
#SummitNow
Demo
#SummitNow
#SummitNow
Other Considerations
Table Load Time
User Preferences
Column Width Adjustments
#SummitNow
#SummitNow
Contributors
Sri Patil, Senior Developer, Flatirons
April Eggers, Developer, Flatirons
#SummitNow
#SummitNow
Questions
#SummitNow
#SummitNow
#SummitNow