Conneのダッシュボードをkintoneで作った話

入社3年目、Webエンジニアの今村です。
主な仕事内容としては、弊社が販売しているサービス「現場クラウドConne」の開発を行っております。

今回は、私が入社2年目の夏に行っていた「ダッシュボードアプリ開発」で悪戦苦闘した話をご紹介します。

 

やりたかったこと

  • 社内のカスタマーサクセスチームがConneの利用状況を把握するためのダッシュボード作成。
    ※Conne→建設業に関わる方向けのコミュニケーションツール
    https://conne.genbasupport.com
  • kintoneで作成したダッシュボードアプリ上に、Conneが持つ各種指標を日、週、月単位で登録。
    ※kintone→https://kintone.cybozu.co.jp/
  • ダッシュボードアプリとその他の連携させたいアプリからレコードを取得し、グラフで表示。
  • 組織や日付を切り替えたら、その条件で各グラフを再描画

 

先に完成した画面を載せておきます。
※情報を伏せる為、一部ぼかしてあります。

アプリの構成


構成は以上のようになっていて、
今回私が行ったのは、ダッシュボードアプリ内の連携とグラフ描画の部分になります。

主に以下の処理をJavaScriptで実装しました。

  • kintone APIでレコード情報を取得
  • 取得した情報を表示したいグラフに合わせて整形
  • chart.jsでグラフを描画

 

chart.jsについて

https://www.chartjs.org/

使用したJavaScriptライブラリ「chart.js」の使い方について、解説していきます。
下に、今回作成したグラフの中から一部抜粋したコードを掲載します。

//データの準備
function createTotalUsersCount(fromDate, toDate, offset) { 
    var data = { 
        dates: [], 
        userCounts: [], 
        guestCounts: [] 
    } 
     
    requestBody = { 
        "app": DB_APP_ID, 
        "totalCount": true, 
        "fields": ["日付", "組織ユーザー総数", "ゲスト総数"], 
        'query': 'レコードタイプ in ("日次") and 日付 >= "' + fromDate + '" and 日付 <= "' + toDate + '" order by 日付 asc offset ' + offset 
    }; 

    kintone.api(kintone.api.url('/k/v1/records', true), 'GET', requestBody, function(resp) { 
        resp.records.forEach(function(record, i){ 
            data.dates.push(record["日付"].value); 
            data.userCounts.push(record["組織ユーザー総数"].value); 
            data.guestCounts.push(record["ゲスト総数"].value); 
        }); 
        
        // GET数制限対応
        if(resp.records.length == 100){ 
            offset += 100; 
            createTotalUsersCount(fromDate, toDate, offset); 
        }else{ 
            drawTotalUsersCount(data); 
        } 
    }, function(error) { 
        // 失敗したときの処理 
        console.log(error); 
    }); 
}

// グラフ描画
function drawTotalUsersCount(data){ 
         
    var ctx = document.getElementById("total-users-canvas").getContext("2d"); 
     
    // 再表示する際、グラフのインスタンスを破棄する 
    if(totalUsersCountGraph){ 
        totalUsersCountGraph.destroy(); 
     } 
     
    // 設定 
    var config = { 
        type: "line", 
        data: { 
            labels: data.dates, 
            datasets: [ 
                { 
                    label: "組織ユーザー", 
                    data: data.userCounts, 
                    borderColor: "rgba(254,97,132,0.5)", 
                    backgroundColor: "rgba(0,0,0,0)" 
                },{ 
                    label: "ゲストユーザー", 
                    data: data.guestCounts, 
                    borderColor: "rgba(54,164,235,0.5)", 
                    backgroundColor: "rgba(0,0,0,0)" 
                } 
            ] 
        }, 
        options: { 
            responsive: true, 
            title: { 
                display: true, 
                fontSize: 18, 
                text: '総ユーザー数' 
            }, 
            tooltips: { 
                mode: 'x-axis', 
                position: 'average', 
                bodyFontSize: 14, 
            }, 
            scales: { 
              yAxes: [{ 
                ticks: { 
                  beginAtZero: true, 
                  min: 0 
                } 
              }] 
            } 
        } 
    }; 
     
    window.totalUsersCountGraph = new Chart(ctx, config); 
}

前半の関数でdataを用意し、それを引数に渡して描画関数を実行します。
描画関数の最終行で new Chart() に、「どこに描画するか、どんなグラフにするか」
という情報を与えて描画処理を行っています。
肝となる「どんなグラフにするか」の部分は config という変数名で渡しているので、その中身を見ていきます。

config では 以下3つの設定を行います。

  • type (グラフの形式)
  • data (縦軸、横軸の値)
  • options (各種設定)

今回は type は折れ線グラフなので “line”
data.labels は横軸なので日付
data.datasets は配列になっていて、集計結果を複数表示させることもできます。
data.datasets[i].data に、整形したデータを入れています。
それに応じて縦軸の数字は自動で入ってくれますが、 options.scales でさらにその辺の細かい設定ができます。
options では他にも、タイトルのフォントや位置、ツールチップに関する設定など行うことができます。

他にも色々設定できるようですので、詳細は公式ドキュメントをご覧ください。
日本語版もあるようです。
https://misc.0o0o.org/chartjs-doc-ja/

 

大変だったこと

設計面

依頼者との認識合わせが思っていたより大変で、しかしとても大切だと感じました。
アプリ開発前後でそれぞれ以下の認識を合わせていました。

開発前…要望をみて疑問点を質問し、解消しながら設計に落としていく
開発後…使用したデータの説明や計算式をまとめて共有

特に、開発後に行った計算式等の共有は、

  • 要望通りのデータが集計できているのかどうかわからない
  • 今の仕様を確認できない

といった状況を防ぐために行いました。
しかし、本来であれば、設計に落とした段階で共有しておくべだったと反省しています。

今回は社内からの依頼でしたが、今後同じような機会があった際には、社内でも社外でも活かしていきたいと思います。

技術面

今回は特に難しい技術を使っているわけでは無かったので、時間はかかりましたが、調べながら自力で8割方進められました。
その中で躓いたのは以下の点でした。

  •  jQuery
    $ is not defined
    $(…).datepicker is not a function
    といったエラーに何度も会いました
    読み込む順番や書き方がおかしくないか、複数回読み込んでいないか、等
    一つ一つおかしいところを探して修正を行っていましたが、ここには結構時間を使ってしまいました。
  • kintone API
    1度に取得できるレコード数が100件までという制限があったので、それ以上取得したい場合は、再帰的に「次の100件を取得する」処理を書かなければなりません。
    上に載せたコードの「// GET数制限対応」で書いていますが、初めはここの書き方が慣れなかったです。

 

開発を終えて

今回kintoneで開発するに至った経緯として、

  • 社内の皆がkintoneを使い慣れていて、誰でも閲覧できること
  • kintoneのグラフ機能を活用すれば、低い開発コストで実現できそうだったこと

があります。

しかし、kintoneのグラフ機能では、今回の要望を全て満たすことが難しく、
今回紹介したような、Chart.jsを使って実装する作りになりました。
その結果として、今回開発した部分においてkintoneの機能を全く使わない作りになってしまいました。

さらに、kintoneを使うことで以下のような課題もあるため、kintoneを使わない新たな構成を検討したいと思っています。

  • 同じプログラムを使いまわしづらい
  • 開発、保守にkintoneの知識が必要となり、属人化につながる
  • 今後レコードが膨大になったとき、パフォーマンス低下の可能性がある
  • kintoneAPIの制限に引っかかる可能性がある。

今後、このダッシュボードアプリを他の自社サービスにも展開していけるよう、汎用性、保守性を高め、より使いやすいものにしていきたいと思います。