最近因為某些原因有機會玩玩 gantt 圖的拖拉互動 web 介面,剛好又是基於 extjs 的套件,花了一點時間了解一下,在這與大家分享,若有需要使用此套件可以更加快速上手。
此套件的官網: Bryntum: HTML5 Gantt & Scheduling Charts,其相關套件如下圖:
算是完成度蠻高的套件,對於有需要甘特圖拖拉排定順序類是 ms project 的功能要做 web 版使用此套件算是剛剛好。
Bryntum gantt scheduleing
與 extjs 相同,Bryntum 也有其元件相關 API 文件,參考下面連結:
使用與查詢方式跟 extjs 官方一樣,若本來就熟悉 extjs 使用上沒有太大的問題。
Online Demo
若要把玩 bryntum 官方提供的 demo,可使用下列連結進行操作:
本機測試
知道大概的操作方法後,為了更加了解內部運作,把該範例的運行環境建置完成,透過最近接觸的 node.js + sails 建置,source code: extjs-bryntum-gantt-demo,相關執行步驟可參考 readme.md
Gnt model
了解一個系統的運作,需要先知道其資料結構,可以參考 bryntum gantt scheduleing API 中關於 Gnt.data.TaskStore 的介紹,連結中有大概的資料表,資料表中欄位的詳細說明可參考:
- Gnt.model.Task: 樹狀結構之 task
- Gnt.model.Dependency: 每個 task 間的連接線
其中 Gnt.data.TaskStore 從 bryntum gantt scheduleing API 中可以看到該類別是繼承於 Ext.data.TreeStore,所以 TreeStore 有的函式基本上都可在 TaskStore 呼叫,若只針對甘特圖的讀取跟儲存,我們來看下面程式碼:
github 連結: TaskStore.js
Ext.define("MyApp.store.TaskStore", {
extend : 'Gnt.data.TaskStore',
rootVisible : true,
proxy : 'memory',
constructor : function (config) {
config.calendar = new Gnt.data.calendar.BusinessTime({
calendarId : "Default",
name : "Default"
});
this.callParent(arguments);
},
//讀取資料來源
//this.url = data.js 參考 assets/data.js,在這可以替換為從後端 server 取得初始資料
loadDataSet : function () {
Ext.Ajax.request({
url : this.url,
method : 'GET',
success : this.populateDataStores,
callback : function () {
this.fireEvent('load');
},
scope : this
});
},
// 取得甘特圖操作後的資料並且將資料送交指定網址
saveDataSet : function () {
//getModifiedRecords() -> 屬於 Ext.data.TreeStore 的函式,新增或修改的資料可透過此函式取得
//getRemovedRecords() -> 屬於 Ext.data.AbstractStore 的函式,若要取得刪除的 dependencies 或 task 可用此函式
var resources = this.resourceStore.getModifiedRecords();
var assignments = this.assignmentStore.getModifiedRecords();
var dependencies = this.dependencyStore.getModifiedRecords();
var tasks = this.getModifiedRecords();
//將資料一一存為陣列
function extract(records) {
var result = [];
Ext.each(records, function(record) {
result.push(record.data);
});
return result;
}
var data = {
resources : extract(resources),
assignments : extract(assignments),
dependencies : extract(dependencies),
tasks : extract(tasks)
};
// 由後端進行資料儲存
Ext.Ajax.request({
url : "/gantt/save",
method : 'POST',
jsonData : data,
callback : function () {
this.fireEvent('save');
},
scope : this
})
},
//從後端取得資料後,一一將資料 load 到對應的 store
populateDataStores : function (response, options) {
var data = Ext.decode(response.responseText);
if (data.calendars && data.calendars["default"]) {
this.calendar.loadData(data.calendars["default"]);
}
if (data.dependencies) {
this.dependencyStore.loadData(data.dependencies);
}
if (data.assignments) {
this.assignmentStore.loadData(data.assignments);
}
if (data.resources) {
this.resourceStore.loadData(data.resources);
}
// Now all is in place, continue with tasks
this.setRootNode(data);
}
})
;
相關說明都在程式註解中,其中就如一開始有提到的 Gnt.data.TaskStore繼承於 Ext.data.TreeStore,所以我們可以透過下列函式來取得變更後的資料:
- Ext.data.AbstractStore-method-getModifiedRecords: 更新與新增(不包括刪除)
- Ext.data.TreeStore-method-getNewRecords: 只針對新增
- Ext.data.AbstractStore-method-getRemovedRecords: 刪除
屬於 bryntum gantt scheduling 範圍大概就到這,剩下的就是後端的資料處理與回存,希望可以幫到有需要的人囉!
沒有留言:
張貼留言