Ext Gantt 3 を始めよう

Ext.Gantt のドキュメント http://www.bryntum.com/docs/scheduling/3.x/?#!/guide/gantt_getting_started を翻訳してみました。中に {@hoge } というような記述がありますが、これは JSDuck でドキュメントを作るためのものです。ここではそのままにしています。

Ext Gantt 3 を始めよう

概要

HTML file:

<!DOCTYPE html>
<html>
    <head>
        <link href="http://cdn.sencha.com/ext/gpl/4.2.0/resources/css/ext-all.css" rel="stylesheet" type="text/css" />
        <link href="http://bryntum.com/examples/gantt-latest/resources/css/sch-gantt-all.css" rel="stylesheet" type="text/css" />

        <script src="https://cdn.sencha.com/ext/gpl/4.2.0/ext-all-debug.js" type="text/javascript"></script>
        <script src="https://bryntum.com/examples/gantt-latest/gnt-all-debug.js" type="text/javascript"></script>

        <script src="synopsys.js" type="text/javascript"></script>
    </head>

    <body>
    </body>
</html>    

synopsys.js:

Ext.onReady(function(){

    var taskStore = Ext.create('Gnt.data.TaskStore', {
        autoLoad    : true,
        proxy       : {
            type    : 'memory',
            reader  : {
                type: 'json'
            },

            data: [ 
                { 
                    "StartDate" : "2010-01-18",
                    "EndDate" : "2010-02-02",
                    "Id" : 1,
                    "Name" : "Planning",
                    "expanded" : true,
                    "children" : [
                        { 
                            "StartDate" : "2010-01-18",
                            "EndDate" : "2010-01-26",
                            "Id" : 2,
                            "leaf" : true,
                            "Name" : "Investigate",
                            "parentId" : 1
                        },
                        { 
                            "StartDate" : "2010-01-22",
                            "EndDate" : "2010-01-25",
                            "Id" : 3,
                            "leaf" : true,
                            "Name" : "Investigate2",
                            "parentId" : 1
                        },
                        { 
                            "StartDate" : "2010-01-28",
                            "EndDate" : "2010-01-28",
                            "Id" : 4,
                            "leaf" : true,
                            "Name" : "Investigate3",
                            "parentId" : 1
                        }
                    ]
                }
            ]
            // eof data
        }
        // eof proxy
    });

    var ganttPanel = Ext.create('Gnt.panel.Gantt', {
        height      : 400,
        width       : 1000,

        viewPreset      : 'weekAndDayLetter',

        startDate       : new Date(2010, 0, 15),
        endDate         : Sch.util.Date.add(new Date(2010, 0, 15), Sch.util.Date.WEEK, 3),

        columns         : [
            {
                xtype       : 'treecolumn',
                header      : 'Tasks',
                sortable    : false,
                dataIndex   : 'Name',
                width       : 200
            }
        ],

        taskStore       : taskStore
    });

    ganttPanel.render(Ext.getBody());
});

はじめに

Ext Gantt は、互いに依存し合うタスクを表示することができる、 Ext JS のカスタムコンポーネントです。

このコンポーネントを使うには、まず Ext JS フレームワークのライセンスを所持する必要があります。 次の URL から、購入または試用のための評価版をダウンロードできます。 – http://www.sencha.com/products/extjs

{@img gantt-panel.png}

データ

Gannt チャートは、いくつかのデータセットを受け取り更新します。 それらのデータセットは必須のものとオプションのものがあります。 すべてのデータセットは {@link Ext.data.Store} の特別なサブクラスのインスタンスであり、 {@link Ext.data.Model models} のインスタンスのコレクションを内包します。

次のガイドを参照して、Ext JS データパッケージの基本的な情報を確認して下さい。 http://docs.sencha.com/ext-js/4-0/#/guide/data

すべてのデータセットは、このクラスのコンフィグオプションそして指定できます。

  • {@link Gnt.panel.Gantt#taskStore taskStore} – 「メイン」のデータセット(必須) – {@link Gnt.data.TaskStore} のインスタンス。表示するタスクのツリーを保持します。 各タスクは {@link Gnt.model.Task} のインスタンスとして表現されます。 タスクは子タスクを持つことができ、その場合には「親」タスクとなり、その開始日、終了日は子タスクによって決定されます。
  • {@link Gnt.panel.Gantt#dependencyStore dependencyStore} (オプション). {@link Gnt.data.DependencyStore store} タスク間の依存関係に関する情報を保持します。 それぞれの依存関係は {@link Gnt.model.Dependency} のインスタンスとして表現されます。
  • {@link Gnt.panel.Gantt#resourceStore resourceStore} (オプション). {@link Gnt.data.ResourceStore store} タスクに割り当てることができるリソースに関する情報を保持します。 各リソースは、 {@link Gnt.model.Resource} のインスタンスとして表現されます。
  • {@link Gnt.panel.Gantt#assignmentStore assignmentStore} (オプション). {@link Gnt.data.AssignmentStore store} タスクに割り当てられるリソースに関する情報を保持します。 それぞれの割り当ては {@link Gnt.model.Assignment} のインスタンスとして表現されます。

オプションのデータストアを指定しない場合は、空のものが生成されます。

これらのデータストアは、ガントチャートの「モデル」となります。 すべての UI コンポーネント (このクラスのような) は、これらのデータストアとバインドされます。データを操作すると、画面表示が自動的に更新されます。

カレンダー. 有効な時間

{@img calendar.png}

カレンダーは、 {@link Gnt.data.Calendar} と {@link Gnt.data.calendar.BusinessTime} で表現されます。

カレンダーは基本的には {@link Gnt.model.CalendarDay days} のコレクションです。 それぞれの日付は、平日/休日 {@link Gnt.model.CalendarDay#isWorkingDayField flag} のフラグや、いくつかの「有効な間隔」があります。

有効な間隔では、タスクが実行できるとか、あるリソースが有効である時間を定義します。 間隔は、分単位で指定でき、一日に複数の間隔を指定できます。 カレンダーはまた、平日のデフォルトの有効間隔を保持します。

例えば、デフォルトの仕事時間を、月曜日から金曜日は、08:00から12:00 と 13:00から17:00 とし、8/19 だけは、09:00 から 16:00 という指定ができます。

また、プロジェクト全体に渡る「メイン」カレンダーがあります。 また、全てのタスクやリソースは自身のカレンダーを持てます

タスクの期間を計算したりタスクを動かすとき、 仕事時間ではない時間はスキップされ、 適切なパラメーター (期間/開始日) は調整されます。 これはデフォルトの動作で、違うレベルで無効にすることもできます。

{@link Gnt.panel.Gantt#skipWeekendsDuringDragDrop skipWeekendsDuringDragDrop} オプションを使うと、タスクを自由に移動/リサイズさせたり、 期間を計算する際に、仕事以外の時間を含むようにできます。

{@link Gnt.panel.Gantt#weekendsAreWorkdays weekendsAreWorkdays} オプションを使うと、この機能を完全に無効にでき、一日中仕事時間とみなします。

最後に、SchedulingMode フィールド {@link Gnt.model.Task} をご覧ください。 これを “Manual” にすると、タスクを自由に移動することができるようになります。

カレンダー利用法ガイド もご覧ください。

タイムラインヘッダー

タイムラインのヘッダーの見た目は {@link gnt.panel.gantt#viewpreset viewpreset} コンフィグオプションを使ってカスタマイズできます。

事前に定義したプリセットのリストから選んだり、独自のものも簡単に登録できます。 {@link Sch.preset.Manager} のドキュメンテーションで使い方を参照して下さい。

Gantt コンポーネントは、3レベル以上のヘッダーをサポートし、それぞれに独自のオプションセットがあります。 すべてをミリ秒から年までで表示でき、あらゆる日付のフォーマットやテキストを出力できます。

イベントの監視

Gantt チャートのほとんどのコンポーネント (Gantt コンポーネント自身、そのデータストアや個々のデータエントリ) は Observable パターンを実装しています。 Ext JS フレームワークでは、このパターンは {@link Ext.util.Observable} ミックスインが担います。

Gantt チャートで起こる沢山のイベントについての通知をリッスンし、カスタムのハンドラー (リスナー) を定義できます。 例えば、

ganttPanel.on('taskclick', function (ganttPanel, task) {
    alert("You've clicked on the task named " + task.getName());
}); 

on 呼び出しの 2つめの引数として渡される関数は、「リスナー関数」で、Gantt スケジュールのタスクをクリックしたさいに呼び出されます。 リスナーの動作をカスタマイズする方法について詳しくは {@link Ext.util.Observable} ドキュメントを参照して下さい。 また、このドキュメントにリストされているイベントをご覧ください。

レンダリングのカスタマイズ

タスクの表示をカスタマイズするいくつかの方法があります。 このセクションではそれを簡単にまとめてみます。 それぞれのオプションのドキュメントを参照して下さい。

  • {@link Gnt.model.Task#clsField} を使って簡単にタスクのスタイルを設定できます。 データセットのフィールドにこのプロパティを設定すると、ガントビューはタスクエレメントにこの値を CSS として設定します。 詳しくは、advanced gantt サンプルのソースコードをご覧ください。

    Ext.define('MyTaskModel', {
        extend : 'Gnt.model.Task',
    
        // A field in the dataset that will be added as a CSS class to each rendered task element
        clsField : 'TaskType',
        fields : [
            { name : 'TaskType', type : 'string' }
        ]
    });
    

次のデータをセットします

[{ 
    "EndDate" : "2010-02-02",
    "BaselineEndDate" : "2010-02-01",
    "Id" : 1,
    "Name" : "Planning",
    "PercentDone" : 40,
    "StartDate" : "2010-01-18",
    "BaselineStartDate" : "2010-01-13",
    "TaskType" : "Important",
    ...
}]

こうすると “Important” CSS クラスをこのタスクエレメントにセットします。

  • {@link Gnt.model.Dependency#clsField} を使うだけで、簡単に依存関係のスタイを設定できます。

  • {@link Gnt.panel.Gantt#eventRenderer eventRenderer} この関数をコンフィグオプションとして指定すると、各タスクの描画時に呼び出されます。この関数では、描画時に使われる特別なプロパティのプレースホルダ値を含むオブジェクトを返す必要があります。利用可能なプレースホルダは次の通りです。

    • cls – タスクバーエレメントに追加される CSS クラス
    • ctcls – タスクバーやラベルを保持する ‘root’ エレメントに追加される CSS クラス
    • style – タスクバーエレメントに適用されるインラインスタイル定義
    • progressBarStyle – このタスクのプログレスバーに適用されるインライン CSS スタイル
    • leftLabel – 左側のラベルの内容 (通常はタスクから{@link Gnt.panel.Gantt#leftLabelField leftLabelField} オプションを使って抽出されます)。 ラベル描画を有効にするには leftlabelfield に何らかの値を設定する必要もあります。
    • rightLabel – 右側のラベルの内容 (通常はタスクから{@link Gnt.panel.Gantt#rightLabelField rightLabelField} オプションを使って抽出されます)。 ラベル描画を有効にするには rightlabelfield に何らかの値を設定する必要もあります。
    • basecls – ベースライン DOMエレメントに追加する CSS クラス、 {@link Gnt.panel.Gantt#showBaseline showBaseline} オプションが true で、タスクにベースライン情報がある場合だけ有効になります。

サンプル:

eventRenderer: function (taskRecord) {
    var cls = taskRecord.get('PercentDone') > 80 ? 'almostDone' : '';
    return {
        cls : almostDone
    };
}

.almostDone {
    background:green;
    border: lime;
}

プラグインと追加機能

それ自身では、Gantt パネルはデータを描画するだけです。 インタラクトする機能を追加するためには、多くの機能やプラグインを有効にしたり追加したりします。 最も簡単な例では、タスクのドラッグ&ドロップ機能は、{@link Gnt.panel.Gantt#enableTaskDragDrop enableTaskDragDrop} コンフィグオプションで有効にします。 そうすると内部では、ドラッグ&ドロッププラグインを追加します。

プラグインを手動で追加するには、plugins コンフィグにプラグインのインスタンスを渡す必要があります。 例えば、印刷サポートを追加するには、{@link Gnt.plugin.Printable print plugin} を有効にします。

    var ganttPanel = Ext.create('Gnt.panel.Gantt', {
        ...
        taskStore       : taskStore,

        plugins         : [
            Ext.create('Gnt.plugin.Printable')
        ]
    });

プラグインには、独自のコンフィグオプションがあります。 ‘plugins’ 配列には複数のプラグインを指定できます。 利用できるプラグインのリストは、Gnt.plugn ネームスペースのクラスを調べて下さい。 Sch.plugin ネームスペースのプラグインの一部も使うことができます。