欲しいものリスト

phoenix-powerGitHubにあるような芝(カレンダー)をサイトに設置する方法。

cal-heatmapは、GitLabにも使われています。ここでは、GitLabユーザーのカレンダー情報をJSONで取得し、サイトに設定する方法を紹介します。

1
$ bower install cal-heatmap
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<script src="/bower_components/d3/d3.min.js" charset="utf-8"></script>
<script src="/bower_components/cal-heatmap/cal-heatmap.min.js"></script>
<link rel="stylesheet" href="/bower_components/cal-heatmap/cal-heatmap.css" />

<h3>GitLab Calendar Activities</h3>
<div id="cal-heatmap"></div>
<div id="example-heatmap"></div>
<script type="text/javascript">
var cal = new CalHeatMap();
cal.init({
  itemSelector: "#example-heatmap",
  domain: "month",
  data: "/json/datas.json",
  start: new Date(2016, 0),
  cellSize: 11,
  range: 9,
  previousSelector: "#example-b-PreviousDomain-selector",
  nextSelector: "#example-b-NextDomain-selector",

  legend: [1, 3, 5, 7],
  legendColors: {
      min: "#efefef",
      max: "steelblue",
      empty: "#efefef"
  },
  tooltip: true
});
</script>

ここで重要なのはitemSelector, dataです。

表示する場所はitemSelector:でHTML要素を指定します。dataではユーザーのカレンダー情報ですね。

sの他、例えば、legendで最小、最大のコミット数を指定します。次に、legendColorsはコミット数と関連したカラーの設定ですね。

GitLabのカレンダー情報をJSONで取得します。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ curl -sL gitlab.com/u/$USER/calendar

# jq
$ export x=`curl -sL gitlab.com/u/$USER/calendar|grep '{"'`
$ echo ${x%,}|jq .
$ echo ${x%,}|jq . >> json/datas.json

# example
$ curl -sLO http://cal-heatmap.com/datas-years.json
$ cat !$:t | jq .

# preview
$ jekyll server

例えば、これをjQuery, Ajaxで書いてみます。GitLabから情報を取るためにjquery.xdomainajax.jsを使います。

しかし、GitLabが提供する出力はHTMLですので、これを加工する必要があります。

必要なJSONは<script>内にあります。ここで、xdomainajax.js<script>が空にされるため、一部コードを書き換えて使います。

js/jquery.xdomainajax.js
1
2
3
# https://github.com/padolsey-archive/jquery.fn/blob/master/cross-domain-ajax/jquery.xdomainajax.js#L62
- .replace(/<script[^>]+?\/>|<script(.|\s)*?\/script>/gi, '')
+ //.replace(/<script[^>]+?\/>|<script(.|\s)*?\/script>/gi, '')

ちなみに、このjsファイルは手元において読み込んでください。http経由で読み込まないように。

t/foo.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="../static/js/jquery.xdomainajax.js"></script>
<script src="../static/bower_components/d3/d3.min.js" charset="utf-8"></script>
<script src="../static/bower_components/cal-heatmap/cal-heatmap.min.js"></script>
<link rel="stylesheet" href="../static/bower_components/cal-heatmap/cal-heatmap.css" />
<!--<script src="https://raw.githubusercontent.com/syui/jquery.fn/master/cross-domain-ajax/jquery.xdomainajax.js"></script>-->
<!--diff : https://github.com/padolsey-archive/jquery.fn/blob/master/cross-domain-ajax/jquery.xdomainajax.js#L62 -->
<h3>Calendar Activities</h3>
<div id="cal-heatmap"></div>
<div id="example-heatmap"></div>

<script>
jQuery(function ($) {
  var json;
      $.ajax({
        type: 'GET',
        url: 'https://gitlab.com/u/syui/calendar',
        dataType: 'html',
      async: false,
      cache: false,
      success: function(data) {
      var content = $(data.responseText).filter('script').html();
      var tmp = content.replace("<![CDATA[", "").replace("]]>", "");
      var s = tmp.indexOf( "{" );
      var e = tmp.indexOf( "}" );
      json = tmp.substring( s, e+1 );
      $('#gitlab-calendar-activities').text(json);
      }
  });
  setTimeout( $('#example-heatmap').each(function () {
  //setTimeout( function() {
      if( json != null ){
      var obj = $.parseJSON(json);
          var now = new Date();
          new CalHeatMap().init({
            data: obj,
            domain: 'month',
            domainLabelFormat: '%Y-%m',
            itemSelector: '#example-heatmap',
            legend: [1, 3, 5, 7],
            legendColors: {
              min: "#efefef",
              max: "steelblue",
              empty: "#efefef"
            },
            tooltip: true,
            start: new Date(now.getFullYear(), now.getMonth() - 9)
          });
      } else {
          setTimeout( arguments.callee, 100 );
      }
  }));
});
</script>

<div id="gitlab-calendar-activities" style="display:none;"></div>
t/foo.html
1
2
3
4
5
6
7
# 一応、Hugoのディレクトリ構造を想定
$ tree -L 2 -d .
  - t/foo.html
  - static/
      - bower_compotnent/{d3,cal-heatmap}
      - js/jquery.xdomainajax.js
$ open t/foo.html

これをブラウザで開き、Consoleからログを確認しながら修正していくとよいでしょう。console.log(json)

うまくいくと最終的に取れるJSONが#gitlab-calendar-activitiesに表示されるはずです。ただし、display:noneしているので、ソースを見てください。別にこれを使っても使わなくてもどっちでも良いです。使わない場合は当該箇所をコードから削除して問題ありません。ここではグローバル変数を使ってますのでカレンダーへの影響はないです。

JSONはこのような感じで取得し、カレンダーに表示してもよいですが、サイトのレスポンス(遅延)が気になります。

したがって、おすすめはdata: "/json/datas.json"として、1日1回サイト上においたファイルをサーバーやボットなどを使って自動更新することですかね。