Last week I received an e-mail from an Alfresco developer with a question about integrating dojox.gantt with Alfresco. The dojox.gantt widget is part of the popular Dojo Toolkit and provides an integrated widget for project and resource management.
I never used the Dojo Toolkit before, but I decided to give it a try and I must say that it is a poweful framework for web application development. In this tutorial I will show you how you can integrate dojox.gantt with Alfresco without much coding thanks to Alfresco’s Web Scripts and CMIS. In the end you will be able to load and save project data from Alfresco into the dojox.gantt widget. I used Alfresco Community 4.0b to test the integration, but it should also work with other versions.
Data Model
The dojox.gantt widget uses a simple JSON format to represent project management data. Here is an example:

The structure consists of one or more project items and each project has zero or more tasks. The first step is to upload a dojox.gantt project file into Alfresco. We will use this file as a source for the project data. The dojox.gantt widget requires at least one project item, otherwise you will not be able to open the context menu to add and update projects and tasks. Create a file called gantt_default.json in Alfresco in the Company Home space and add the following lines:
{"identifier":"id","items":[{"id":1,"name":"Development Project","startdate":"2012-2-11","tasks":[]}]}
Web Script
The next step is to create the Web Script. If you are not familiar with the concept of Web Scripts, I suggest that you read this first. On the file system go to the Alfresco Web Scripts folder to create a new Web Script. I used the following location:
tomcat/shared/classes/alfresco/extension/templates/webscripts
First create a file called dojox-gantt.get.desc.xml and add the following lines:
<webscript>
<shortname>dojox.gantt</shortname>
<description>dojox.gantt example</description>
<url>/samples/gantt</url>
<authentication>user</authentication>
</webscript>
This file declares the Web Script and the URL to access the service. Next create a file dojox-gantt.get.html.ftl and add the following lines:
<html>
<head>
<title>Dojo Gantt test</title>
<link type="text/css" rel="stylesheet" href="http://yandex.st/dojo/1.7.1/dijit/themes/claro/claro.css">
<link type="text/css" rel="stylesheet" href="http://yandex.st/dojo/1.7.1/dojox/gantt/resources/gantt.css">
<script src="http://yandex.st/dojo/1.7.1/dojo/dojo.js" type="text/javascript"></script>
<script type="text/javascript">
dojo.require("dojo.parser");
dojo.require("dojox.gantt.GanttChart");
dojo.addOnLoad(function(){
// put the save code here later
var ganttChart = new dojox.gantt.GanttChart({
readOnly: false,
dataFilePath: "${url.context}/s/cmis/p/gantt_default.json/content",
withResource: false
}, "gantt");
ganttChart.init();
ganttChart.loadJSONData();
});
</script>
</head>
<body class="claro">
<div class="ganttContent">
<div id="gantt">
</div>
</div>
</body>
</html>
This file is the view. It loads the required libraries, initializes the Gantt Chart and then loads the data from the server. This line of code is a CMIS get content request to load a file by providing the path:
${url.context}/s/cmis/p/gantt_default.json/content
Since the file is located in Company Home, Alfresco’s root space, providing the name of the file is enough. The /content part of the URL tells Alfresco to return the contents of the file in stead of the object metadata:
In order to test the Web Script first go to the Web Scripts Home page in Alfresco by visiting http://localhost:8080/alfresco/s/. Click the refresh button to add the new Web Script. When you now visit the page http://localhost:8080/alfresco/s/samples/gantt you should see a page similar to this:

When you move the mouse over the project name Requirements you will see a menu to add new tasks.
Saving Data
The dojox.gantt widget is now able to load data from Alfresco using the dataFilePath parameter, but not able to save it back into the system. To save data back into the system you can set a parameter called saveProgramPath in order to provide the server-side script that is able to persist the data. The widget will POST a request to the provided script.
In Alfresco you can create another Web Script to process the POST data, but this requires additional server-side coding. CMIS is able to directly write content back to the server using the same URL as used to read the content, but this requires a PUT method. The dojox.gantt widget by default uses the POST method. I will first show how to use the standard POST method and then we will extend dojox.gantt to use the PUT method.
Server-side Solution
First create another description document called gantt.post.desc.xml in the same directory as where you put the Web Script to read the Gantt chart and add the following lines:
<webscript>
<shortname>dojox.gantt</shortname>
<description>dojox.gantt save example</description>
<url>/samples/gantt/{filename}</url>
<authentication>user</authentication>
</webscript>
Next create a JavaScript controller that reads the data submitted by the dojox.gantt widget and saves it back to Alfresco. Create a file gantt.post.js with the following contents:
var filename = url.extension;
if (filename == undefined || filename.length == 0)
{
status.code = 400;
status.message = "Filename not provided.";
status.redirect = true;
}
else
{
var data = args["data"];
var document = companyhome.childByNamePath(filename);
if (document == null)
{
document = companyhome.createFile(filename) ;
}
document.content = data;
document.save();
model.content = data;
}
The last part of the Web Script is the view. This file simply returns the JSON data received from gthe dojox.gantt widget. Create a file gantt.post.json.ftl with the following line:
${content}
The final part is updating the gantt.get.html.ftl. Add the following parameter to the constructor of dojox.gantt.GanttChart just before the dataFilePath parameter:
saveProgramPath: "${url.context}/s/samples/gantt/gantt_default.json",
The result should look like this:
var ganttChart = new dojox.gantt.GanttChart({
readOnly: false,
saveProgramPath: "${url.context}/s/samples/gantt/gantt_default.json",
dataFilePath: "${url.context}/s/cmis/p/gantt_default.json/content",
withResource: false
}, "gantt");
Now refresh the Web Scripts and reload the page. Add some tasks to the Gantt chart and click save to save the contents back to Alfresco. You can now save project data back to Alfresco using the default dojox.gantt save method.
Client-side Solution
To avoid server-side coding we can rewrite the dojox.gantt save function to use a PUT in stead of a POST. I prefer this approach as it does not require any custom coding on the server. When using CMIS you can use the same URL as defined in the dataFilePath parameter to save data back to the server.
The Dojo Toolkit provides the ability to extend an object. To support the PUT method, we can rewrite the saveJSONData function in order to use PUT in stead of POST. Add the following lines of code to the body of the dojo.addOnLoad function in the file gantt.get.html.ftl:
dojo.extend(dojox.gantt.GanttChart, {
saveJSONData: function(fileName){
var _this = this;
_this.dataFilePath = (fileName && dojo.trim(fileName).length > 0) ? fileName : this.dataFilePath;
try {
var td = dojo.xhrPut({
url: _this.saveProgramPath,
putData: dojo.toJson(_this.getJSONData()),
handle: function(res, ioArgs) {
if ((dojo._isDocumentOk(ioArgs.xhr))||
(ioArgs.xhr.status == 405)){
alert("Successfully! Saved data to " + _this.dataFilePath);
}else{
alert("Failed! Saved error");
}
}
});
} catch (e){
alert("exception: " + e.message);
}
}
});
The function can be found in the file GanttChart.js in the Dojo Toolkit SVN that you can access on the Dojo Toolkit Download page. The only changes required are the replacement of xhrPost with xhrPut and the replacement of the content parameter with a parameter putData with the JSON data as value. The reference documentation for xhrPut is here.
In addition to this change the saveProgramPath needs to be added and since the value is the same as the value of the dataFilePath I added a separate variable saveAndLoadPath for the value:
var saveAndLoadPath = "${url.context}/s/cmis/p/gantt_default.json/content"
var ganttChart = new dojox.gantt.GanttChart({
readOnly: false,
saveProgramPath: saveAndLoadPath,
dataFilePath: saveAndLoadPath,
withResource: false
}, "gantt");
There is no need to refresh the Web Script as the only changes were made in the template. When you run this Web Script again you should be able to save any changes back to the system.

Conclusion
As you can see there is not that much work involved to load and save data from dojox.gantt to Alfresco. Thanks to CMIS a single call can both read and write data. The only challenge was to rewrite the save function to use PUT rather than POST. You can use dojox.gantt to create project plans using Alfresco, for example by creating a custom action or through a Share dashlet. The Alfresco developer who e-mailed me about the integration will use dojox.gantt to provide reports on top of Alfresco Share Data Lists. You can for example do this by creating a custom rendition that renders a Share Task List into the JSON structure that can be loaded into dojox.gantt.
Updates
February 19, 2012: added the server-side save method as an example.










