【パブリッシャー】HTMLとJavaScriptでカスタムレポートを作成してみる


Sharperlightパブリッシャーで作成される公開クエリは、HTMLやJavaScriptを使用して作成するWEBインターフェースのコンテナとして使用することもできます。その簡単な例をここでは見ていきます。
Sharperlightには、jquery、KendoUI、yui、D3、Chart.JsなどのJavaScriptフレームワークが梱包されています。それらを利用してWebインターフェースを作成することができます。
今回は、Chart.Jsを利用して、折れ線グラフを表示してみます。元になるデータもパブリッシャーで公開クエリとして定義します。

データソースを準備する

パブリッシャーを起動して公開クエリを作成します。
グループ名とコードを入力したら、クエリの編集を開始します。

カスタム定義のデータセットを使用します。このようなデータセットを準備しましょう。

"日付::Date","金額::Number"
"2022-03-01",1000.00
"2022-03-02",1150.00
"2022-03-03",1050.00
"2022-03-04",1200.00
"2022-03-05",1259.00
"2022-03-06",1268.00
"2022-03-07",1300.00
"2022-03-08",1320.00
"2022-03-09",1340.00
"2022-03-10",1358.00
"2022-03-11",1390.00
"2022-03-12",1400.00
"2022-03-13",800.00
"2022-03-14",1410.00
"2022-03-15",1430.00
"2022-03-16",1459.00
"2022-03-17",1500.00
"2022-03-18",1523.00
"2022-03-19",1523.00
"2022-03-20",1558.00
"2022-03-21",1590.00
"2022-03-22",1600.00
"2022-03-23",1696.00
"2022-03-24",1750.00
"2022-03-25",1754.00
"2022-03-26",1759.00
"2022-03-27",1770.00
"2022-03-28",1800.00
"2022-03-29",1850.00
"2022-03-30",1900.00
"2022-03-31",2000.00

日付金額フィールドを出力に設定して[OK]ボタンを押し確定します。データセットの準備完了。

HTMLとJavaScriptのコードを準備する

このようなコードを準備します。

<!DOCTYPE html>
<!-- Ver 01 00 00 -->
<html>
<head>
	<meta charset="utf-8"/>
	<base href="{*Url.Root}">
	<link rel="shortcut icon" type="image/x-ico" href="favicon.ico" />
    <link rel="icon" type="image/x-ico" href="favicon.ico" />
	<title>ChartJS Sample</title>
	
	<link rel="stylesheet" type="text/css" href="{*Url.Root}Resources/Chart.js/Chart.min.css" />
    
	<script type="text/javascript" src="{*Url.Root}Resources/Chart.js/Chart.js"></script>
    <script type="text/javascript" src="{*Url.Root}Resources/Chart.js/Chart.min.js"></script>
    <script type="text/javascript" src="{*Url.Root}Resources/jquery/jquery.min.js"></script>
</head>
<body style="font-family: arial; font-size:13px">
    <div class="chart-container" style="position: relative; height:400px; width:750px">
        <canvas id="myLineChart"></canvas>
    </div>
	
    <script>
        var gDsSomething;       //Data Source
        var gURL_ReadSomething = "{*Row.URLCustomHTMLData.text}";
		
		$(document).ready(function(e) { ChartJS_Sample_Start(e) });
		
        function drawLineChart() {
            // Add a helper to format timestamp data
            Date.prototype.formatMMDDYYYY = function() {
                return (this.getMonth() + 1) +
                "/" +  this.getDate() +
                "/" +  this.getFullYear();
            }

            var jsonData = $.ajax({
                url: gURL_ReadSomething,
                dataType: 'json',
                }).done(
                    function (results) {
                        // Split timestamp and data into separate arrays
                        var labels = [], data=[];
                        results.forEach(function(packet) {
                            labels.push(new Date(packet.Date).toLocaleDateString());
                            data.push(parseFloat(packet.Amount));
                        });

                        // Create the chart.js data structure using 'labels' and 'data'
                        var tempData = {
                            labels : labels,
                            datasets : [
                                {
                                label                 : 'Dataset Sample',    
                                fillColor             : "rgba(151,187,205,0.2)",
                                strokeColor           : "rgba(151,187,205,1)",
                                pointColor            : "rgba(151,187,205,1)",
                                pointStrokeColor      : "#fff",
                                pointHighlightFill    : "#fff",
                                pointHighlightStroke  : "rgba(151,187,205,1)",
                                data                  : data
                                }
                            ]
                        };

                        // Get the context of the canvas element we want to select
                        var ctx = document.getElementById("myLineChart").getContext("2d");

                        // Instantiate a new chart
                        var myLineChart = new Chart(ctx, {
                                                        type: 'line',
                                                        data: tempData,
                                                        options: {
                                                            responsive: true,
                                                            maintainAspectRatio: false,
                                                            scales: {
                                                                xAxes: [{
                                                                    ticks: {
                                                                        autoSkip: false,
                                                                        maxRotation: 45,
                                                                        minRotation: 45
                                                                    }
                                                                }]
                                                            }
                                                        }
                                                    });
                    }
                );
        };

        function ChartJS_Sample_Start(e){
        try { 
            drawLineChart();
        }catch(err){
            alert("Error in ChartJS_Sample_Start(): " + err.message);
        }
        };
	</script>
</body>
</html>

ひとつずつみていきます。
headの部分です。
スタイツシートとJavaScriptフレームワークの参照構文があります。
その中の{*Url.Root}の部分は、実行時にSharperlightのRESTサービスのURLに置き換えられます。

<head>
	<meta charset="utf-8"/>
	<base href="{*Url.Root}">
	<link rel="shortcut icon" type="image/x-ico" href="favicon.ico" />
    <link rel="icon" type="image/x-ico" href="favicon.ico" />
	<title>ChartJS Sample</title>
	
	<link rel="stylesheet" type="text/css" href="{*Url.Root}Resources/Chart.js/Chart.min.css" />
    
	<script type="text/javascript" src="{*Url.Root}Resources/Chart.js/Chart.js"></script>
    <script type="text/javascript" src="{*Url.Root}Resources/Chart.js/Chart.min.js"></script>
    <script type="text/javascript" src="{*Url.Root}Resources/jquery/jquery.min.js"></script>
</head>

実行時はこんな感じです。

次に注目するべきところは、この部分。

    <script>
        var gDsSomething;       //Data Source
        var gURL_ReadSomething = "{*Row.URLCustomHTMLData.text}";
		
		$(document).ready(function(e) { ChartJS_Sample_Start(e) });
		
        function drawLineChart() {
            // Add a helper to format timestamp data
            Date.prototype.formatMMDDYYYY = function() {
                return (this.getMonth() + 1) +
                "/" +  this.getDate() +
                "/" +  this.getFullYear();
            }

            var jsonData = $.ajax({
                url: gURL_ReadSomething,
                dataType: 'json',
                }).done(
                    function (results) {
                        // Split timestamp and data into separate arrays
                        var labels = [], data=[];
                        results.forEach(function(packet) {
                            labels.push(new Date(packet.Date).toLocaleDateString());
                            data.push(parseFloat(packet.Amount));
                        });

先ずは、この部分var gURL_ReadSomething = "{*Row.URLCustomHTMLData.text}";
これは、このHTMLページで使用するデータを取得するためのURLを準備しています。どこから取得するかというと、この記事の上記で定義したデータソース用の公開クエリからです。

そして、この公開クエリをデータソース(JSONを返す)として呼び出すためのURLは、

http://{YourSeverName}/mdService1Rest/DataSource/?query=QiitaSample.CustomHTMLData&dfmt=jsonarray&dcat=UseNames

であり、本来はこのURLをコード内に直接記述してもいいのだけれど、ここではコントロールタグ{*Row.URLCustomHTMLData.text}を使用して、このソースコードのコンテナとなる公開クエリの内部に定義した拡張表現から取得するようにしています。これは後々URLに変更が発生した場合、コードの修正ではなく、公開クエリの内部に定義した拡張表現を変更するだけで変更に対応するためです。このような感じで。

そのURLはこのajaxコール部分で使用されています。

var jsonData = $.ajax({
                url: gURL_ReadSomething,
                dataType: 'json',

次に注目すべきところは、どのように取得したデータをChart.JSで使用できる形式に変換しているかという部分です。その箇所がここです。

// Split timestamp and data into separate arrays
       var labels = [], data=[];
       results.forEach(function(packet) {
           labels.push(new Date(packet.Date).toLocaleDateString());
           data.push(parseFloat(packet.Amount));
       });

ここでは、ラベルとデータの配列をそれぞれ取得したデータセットから作成しています。なぜそうするかはChart.JSの仕様を参照してください。
上記データセットを思い出してください。ここで言うラベルは日付、データは金額となります。
labels.pushのところで、packet.Dataを渡しています。そのDataの部分、これはデータソース用公開クエリの出力領域に設定した日付名前を指し示しています。data.pushのところも同じく、Amountの部分、これはデータソース用公開クエリの出力領域に設定した金額名前を指し示しています。

このようにして公開クエリで定義されたデータは、JavaScriptコード側で使用できます。
その他のコードは全て、Chart.JSで折れ線グラフを記述するための標準的なコードですので、Chart.JSの仕様を参照してください。

HTML+JavaScriptコードの公開クエリへの梱包

上記で記述したコードのコンテナとなる公開クエリをパブリッシャーで定義します。

コードとグループ

新規作成して、コードとグループ名を記入します。

クエリの編集

今回の場合、コンテナ用にクエリを定義する必要はないのですが、公開クエリにはクエリの定義が必須という条件があるので、なんでもいいですので簡単なクエリを定義します。しかし、上述したように今回はデータソース用の公開クエリの呼び出しURLを、このクエリ内に拡張表現として定義します。

拡張表現の名前 %URLCustomHTMLDataに注目、コード内のここで使われているよ。

これでコンテナ用のクエリの定義はおしまい。

コードの梱包と使用

[クエリの公開]ダイアログの[オプション]タブに移動します。そしてこの二つのプロパティを使用します。

コードの梱包には、リソースオプションを使用します。[リソース]オプションボタンをクリックすると、専用のダイアログが表示されます。1:[新規]ボタンでアイテムを追加し、2:ファイルオプションを選びます。あとは3:ファイル参照ボタンで記述したHTMLコードファイルを指定します。最後に、4:リソースコードをコピーし、[閉じる]ボタンで終了します。

次に[カスタムHTML]オプションの[編集]ボタンをクリックします。カスタムHTMLテキストエディタが表示されるので、クリップボードに保存してあるリソースコードを貼り付けます。

[OK]を押して完了です。公開クエリを保存して、さあ動作確認してみましょう。

動作確認

Sharperlightサービスを起動して、このURLをブラウザのアドレスバーに貼り付けるだけ。
http://{YourServerName}/mdService1Rest/Report/?query=QiitaSample.CustomHTML
このような折れ線グラフが表示されます。

Sharperlight