jim yeh on 十月 2nd, 2012

今年初,同人打算在 PG 團隊建立任務看板。考量到實體看板可能不容易在團隊所處的環境中推行,同人求教喲哪桑學長,他建議我使用 Trello 來建立電子看板。接受他的建議,同人利用 Trello 運行 PG 團隊的任務看板,目前已經得到一些初步成效,而 PG 們也逐漸習慣用任務看板來管理工作過程。但對於不屬於 PG 團隊的 SA 和長官而言,PG 必須提供看板的資訊供他們參考,因為他們不能登入 PG 的任務看板檢視目前的工作狀態。然而,最近同人發現原來可以匯出 Trello 看板的任務與階段資料的 Trello Dump 已經不能用了,同人只好動手以 jQuery 寫程式用來讀取 Trello 任務看板資訊。程式完成後想到可以分享這支程式,除了為自己留下記錄外,也供有需要的人當做參考。

同人有用一些工具來讓 Trello 用起來更方便。例如 Trello 沒有提供整批建立任務卡的功能,每次都只能以一張卡建完再建立另一張卡的方式來建立 PG 的工作項目,相當不方便。我們的專案不小,PG 團隊和工作量都有相當的規模,常會需要建立大量的任務卡,如果每次只能建立一張卡片實在是非常費時費力。因此同人以 Trello: Add multiple cards bookklemart 來整批一次加入多張任務卡。此外,同人還安裝了 Chrome 的兩個擴充功能。一個是 Trello Scrum 可以在任務名稱加上故事點、另一個是 Kanban WIP for Trello 可以在任務階段名稱加入卡片限額,當卡片達到或超過限額,會以特殊的顏色標示該任務階段中的卡片。我的程式基於這兩個擴充功能,可以提供匯出任務的故事點和任務階段的卡片限額資料。

雖然 Trello 有提供 API 可以取得 Trello 看板資料,但呼叫 API 需要取得 token,處理會比較複雜。同人需要的是較為簡單的前端頁面,只要能夠讀取以 Trello 匯出的 JSON 看板資料檔案就夠用了,如下所示很簡單的前端頁面程式。

<html>
<script src="jquery-1.8.2.js"></script>

<script type="text/javascript">
var taskboardData = {};

function getListMap() {
     var listMap = {};
     $.each(taskboardData.lists,function(i,item){
          if (!item.closed) {
               var listInfo = {};
               listnameParts = /([^\[\]]*)(\[(\d+)\])?\s?$/.exec(item.name);
               listInfo.name = listnameParts[1];
               listInfo.cardLimit = listnameParts[3];
               for (i=0, n=0; i<taskboardData.cards.length; i++) {
                    if (taskboardData.cards[i].idList == item.id && !taskboardData.cards[i].closed) {
                         n++;
                    }
               }
               listInfo.cardCount = n;
               listMap[item.id]=listInfo;
          }
     });
     return listMap;
}

$(function(){
    $("#loaddata").click(function(){
        $.getJSON($("#fileinput").val(),function(data){
               taskboardData = data;
               $("#getcards").click();
        });
    });

     $("#getlists").click(function(){
          var lists = getListMap();
          var html = '';
          $.each(lists,function(i,item){
               html += '<tr><td>'+item.name+'</td>'+
                         '<td>'+(item.cardLimit!=null?item.cardLimit:'<p/>')+'</td>'+
                         '<td>'+item.cardCount+'</td>'+'</tr>';

          });
          $('#outputarea').html("<table id=\"infotable\" border=1 widtg=100%><tr><th width=50%>List</th><th width=5%>Card Limit</th><th width=5%>Card Count</th></tr>" + html + "</table>");
     });

     $("#getcards").click(function(){
          var cards = taskboardData.cards;
          /*
          var listNames = {};
          $.each(taskboardData.lists,function(i,item){
               listNames[item['id']]=item['name'];
          });
          */
          var lists = getListMap();
          var memberNames = {};
          $.each(taskboardData.members,function(i,item) {
               memberNames[item['id']]=item['initials'];
          });

          var html = '';
          $.each(cards,function(i,item){
               if (!item.closed) {
                    var members = '';
                    /*$.each(cards.idMembers,function(j,mbrId){
                         if (j > 0) {
                              members += ',';
                         }
                         members += memberNames[mbrId];
                    });*/
                    for (j=0; j<item.idMembers.length; j++) {
                         if (j > 0) {
                              members += ';';
                         }
                         members += memberNames[item.idMembers[j]];
                    }

                    var labels = '';
                    for (k=0; k<item.labels.length; k++) {
                         if (k > 0) {
                              labels += ';';
                         }
                         labels += item.labels[k].color + ':' + item.labels[k].name;
                    }
                    var cardParts = /(\((\d+\.?\d?)\))?(.*)$/.exec(item['name']);

                    var dueDate = '';
                    if (item.badges.due != null) {
                         var datetimeParts = /(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2})\.\d{3}Z/.exec(item.badges.due);
                         dueDate = datetimeParts[1];
                    }
                    html += '<tr><td>'+cardParts[3]+'</td>'+
                    '<td>'+(cardParts[2]!=null?cardParts[2]:'<p/>')+'</td>'+
                    '<td>'+lists[item['idList']].name+'</td>'+
                    '<td>'+(members.length!=0?members:'<p/>')+'</td>'+
                    '<td>'+(dueDate.length!=0?dueDate:'<p/>')+'</td>'+
                    '<td>'+(labels.length!=0?labels:'<p/>')+'</td></tr>';
               }
          });
          $('#outputarea').html("<table id=\"infotable\" border=1 widtg=100%><tr><th width=50%>Card</th><th width=5%>Point</th><th width=10%>List</th><th width=5%>Members</th><th width=10%>DueDate</th><th width=20%>Labels</th></tr>" + html + "</table>");
     });
  });
</script>
<input id="fileinput" type="text"/>
<input type="button" value="load" id="loaddata" />
<input type="button" value="getCards" id="getcards" />
<input type="button" value="getLists" id="getlists" />
<output id="list"></output>
<BODY>
  <div id="outputarea"></div>

</BODY>
</html>

這個前端頁面在 FireFox 測試可以正常運作,當完成輸入 Trello 匯出看板的檔案名稱後,使用者按下「load」按鈕讀取看板的資料內容,然後自動顯示看板的任務清單。當看到任務清單之後,使用者可以按下「getList」列出看板的任務階段清單;當看到看板的任務階段清單,使用者可以按下「getCards」按鈕列出看板的任務清單。

此頁面的程式會剖析看板每項任務卡片的名稱,以顯示任務名稱和故事點的數值,故事點數值允許小數點。此外顯示的任務項目內容還包括任務卡的任務階段、負責人員、DueDate、以及標籤的顏色及內容。其中負責人和標籤允許多筆,故當有多位負責人或標註多個標籤時,在資料欄位內容內會以分號隔開、而 DueDate 只會顯示日期而不顯示時間的資料細節。

至於看板的任務階段清單則是剖析每項任務階段的名稱,以顯示階段名稱和卡片最大數量,卡片數量沒有小數點。另外在每項看板的任務階段項目統計該階段的卡片總數。擷取任務階段的這些資訊,是用來發現工作過程的瓶頸,協助看板在 WIP 的管理。

然而,這個讀取 Trello 看板資訊的頁面不能直接在 Google Chrome 中執行,原因是 Chrome 的安全控管會禁止 JavaScript 讀本地檔案。解決之道是在執行 Chrome 的命令列加上"–allow-file-access-from-files"的參數。加上這個參數以後,在 Chrome 就可以使用這個頁面讀取本地端的 Trello 看板匯出的 JSON 檔案。

這個前端頁面可以很容易地讀出 Trello 任務看板的資訊,以表格的方式顯示資訊便於儲存成 Excel 的資料格式,可以便於統計及分析來提昇管理的效率。這讓 Trello 不會因為無法直接取得任務看板的資訊而增加管理的困難,對開發工作的精實和敏捷都有莫大的助益呀!



     

5 Responses to “讀取 Trello 任務看板的資訊”

  1. sam 說道:

    Thanks for sharing.

    "Trello: Add multiple cards bookklemart"的連結好像有問題。

  2. jim yeh 說道:

    Hi Sam,

    感謝告知,連結己修正,現在應該可以連結了,若再發現有問題請再賜告。謝謝。

  3. Umin 說道:

    感謝幫忙 ^^ 好用的工具。

  4. jim yeh 說道:

    Hi Umin,

    很高興我的分享對你有所助益。

  5. [...] PG 的 trello 看板中為某些任務卡片 List 設定可容納卡片數量上限,用來進行 WIP [...]

Leave a Reply

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="">