Nullppo

メモ帳的なにか

Confluence Cloudのアクセス数を見える化した話

数か月前、
社内の情報共有ツールとして
Confluence Cloudを提案し導入しました。
登録数は250名ほど。

Cloud版のため色々制約はありますが、
0よりは1ということで便利になった気がします。

アクセス数を把握しよう

導入した側としては、
どれほどの閲覧数・書き込み数があるか気になるところ。

便利なのはいいけど利用者がいないと便利とは言えない。
また、PV数やセッション時間などを把握できないと、
利用を促すにも目標が立てづらい。

どうしようか悩んでAtlassian Marketplaceを見ていると、
一つのプラグインが目に留まった。

GoogleAnalytics for Confluence Cloud

Connect Confluence Cloud with Google Analytics: Gain in-depth understanding of your Confluence user and create greater content

とあるように、
GA連携を行ってアクセス分析を通して
より多くのコンテンツ作成を促せるというもの。

これだ!!
ということで、早速導入した。

設定はすごく簡単。

  1. GAのアカウント作成~Tracking IDの発行
  2. プラグインのインストール~Tracking IDを設定

たったこれだけで、様々なアクセス情報が
GAに流れてくる。

こうなってくると、
利用者にもアクセス状況を見てもらいたい

1つ考えたのが、GAの共有だ。
しかし、これには問題があると感じた。
見たい人は、GAにアクセスするというステップが必要だ。

面倒なので誰も見ないと思った。

どうにか、Confluence上で見せれないものか、、、

、、、

、、

、!!!


Confluence上でアクセス状況を見える化

Googleに便利なものがある!
Google Data Studioだ。

これを利用すれば、
利用者に見せたい情報だけを可視化できる。
しかも自由にグラフを作れたり、ラベルを貼れたりと
多機能!!


ってことで、早速DataStudioとGAを連携させ、
1枚のレポートを作った。

f:id:nullppo:20171013005907p:plain

そして、そのレポート自体を公開設定にする。
(このURLは埋め込みでは使用しない!!!)

f:id:nullppo:20171013010205p:plain

さらに、
ConfluenceのIframeマクロでTOPページに埋め込む。
(編集→レポートを埋め込む でURLを取得)

f:id:nullppo:20171013010407p:plain

f:id:nullppo:20171013011044p:plain


こうして、僕は見える化しました。
簡単でしょ?

是非参考に!以上。

Vueのmountedってどんな順で呼ばれるんだ?

子要素を含む要素をVueを使ってレンダリングしたときに、
mountedイベントはどんな順で発火するのか気になった。

ちょっと確認してみた。
(こんな適当なコードでよかったのかは、謎)

<div id="app"></div>
Vue.component('child1', {
  template: 
  '<p>child1</p>',
  mounted: function() {
    console.log('child1 - mounted!')
  }
});

Vue.component('child2', {
  template: 
  '<p>child2</p>',
  mounted: function() {
    console.log('child2 - mounted!')
  }
});

var app = new Vue({
  el: '#app',
  template: 
  '<div><child1 /><p>app</p><child2/></div>',
  mounted: function() {
    console.log('app - mounted!')
  }
});


結果↓

"child1 - mounted!"
"child2 - mounted!"
"app - mounted!"


子供⇒親かぁ。まぁそりゃそうか。
メモ記事です。

買っちゃった。

ついに。。。。
IntelliJ IDEAを買っちゃった。

まー。一旦は1ヶ月更新版で。


使い倒さねば。

Backboneでscrollイベントが動かねえぇえええ!!!

問題

今、僕はBackboneを使った画面の実装をしてました。
スクロールを使っている画面です。

いつものように

// ・・・・
el : '.sample',
events: {
    'click .button' : 'clickButton',
    'scroll .contents': 'scrollContents'
},
// ・・・・

と書きました。





f:id:nullppo:20170629132542p:plain
おい!動かないじゃねぇか!!!

なんで動かなかったのか

http://backbonejs.org/#View-events
Backbone.View.eventsに書いたイベントは、
jQueryのonを使用して関連付けられます。
rootとなるエレメントはthis.elです。
(英語が苦手だからそんなニュアンスだと思うという予測)

恐らく、上記のeventsはこうなるはず。

$('.sample').on('click', '.button', this.clickButton);
$('.sample').on('scroll', '.scroll', this.scrollContents);

なんか良さそうに見えますよね。
しかーし!!!

scrollイベントは、delegateできないみたいです。

やってみた

See the Pen Scroll Events by Daiki Nakamura (@DaikiNakamura) on CodePen.

はい。動きませんね。

僕は直でONしちゃいました。。。

この問題、renderが終わった後で、
子要素に直接バインドという手段で解決出来ます。(非推奨!

幸いなことにイベントを設定したかったViewは、
rerenderすることのないViewでした。(DOMの書き換えが発生しない)
なので、この手段が使えました。


はい。おわり。

Backbone.jsにおけるMediatorパターン

f:id:nullppo:20170529175721j:plain

業務でBackboneを使っていると、
「View通しの連携をどうしよう。」と悩んだことがありました。

そんな僕が着いた先は、Mediatorパターンによるイベントの連携でした。
調べたこと~サンプル実装までをまとめておこうと思います。

Mediator パターンとは

Mediator とは、英語で「仲裁人、調停者」を意味する単語です。
Mediator パターンとは、多数のオブジェクトの間の調整を行いながら処理をすすめる必要が ある場合に利用すると威力を発揮するパターンです。

ちゃんとしたMediatorパターンでもない気がするけど。。。ま、いっかw

まずは、実装のサンプルから

サンプルでやりたいことは、以下のとおりです。

  1. ViewAで作成したボタンオブジェクトをクリック
  2. ViewBがそれに反応して変わる

(HTMLは省略してます。)

// mediatorの作成
window.App = {};
App.mediator = _.extend({}, Backbone.Events);

// ViewAの定義
var ViewA = Backbone.View.extend({
  events: {
    'click #buttonA': 'clickA' // 1.クリックイベントを取得
  },
  render: function() {
    this.$el.append($('<button></button>', {
      text: 'click me!!',
      id: 'buttonA'
    }));
    return this;
  },
  clickA: function() {
    // 2.イベントが発生したことをmediatorに伝える
    App.mediator.trigger('clickA');
  }
});

// ViewBの定義
var ViewB = Backbone.View.extend({
  initialize: function() {
    // 3.mediatorを購読している、Viewのイベントが発火
    this.listenTo(App.mediator, 'clickA', this.clickA);
  },
  render: function() {
    this.$el.append($('<b></b>', {
      text: 'view B!!',
      id: 'target'
    }));
    return this;
  },
  // 4.実行される関数
  clickA: function(){
    this.$el.find('#target').text('clicked!!')
  }
});


// 描画
var viewA = new ViewA();
var viewB = new ViewB();
$('#MyApp').append(viewA.render().el);
$('#MyApp').append(viewB.render().el);

解説もどき

mediator自体はグローバルな領域に定義されているので、
どのViewからも参照できます。
viewB~FまでlistenToでclickAを購読しておけば、全て反応させる事もできました。
(どんな順番で実行されるかは未確認。)
実際に動きを見たい方は、こちら

また、triggerで引数を渡す場合は、

App.mediator.trigger('clickA', 'クリックされました');

のように、書けばOKです。


とりあえず、以上。
なんかイマイチな記事になった;

2016年度の日報返信名言集(笑)

私の勤めている会社では新人教育の一環として、日報という制度がある。
先輩に報告書を出し、それに対して先輩がコメントしていく簡単な作業です。

毎年、立候補してトレーナーをやっているのですが、
せっかくなので後輩にアドバイスしたことを今年の名言として
ココに晒しとくことにしよう。

来年もトレーナーをやる予定なので、振り返りネタにもなるし、
間違ってるよこれ!ってコメントが貰えるかもしれないしねw

ちょっと恥ずかしいけど、まー(なんやかんや)大丈夫でしょう。

ちなみに、トレーニーがダメだったとかそういうのではないです。
僕のトレーニーは心に突き刺さるエレベーターピッチを日報に書いたり、アドバイスに対して即効で修正してきたりと、素晴らしかったと思います!
ココに書くのを本人が嫌がったらソット削除します!

では早速。

1.目標の中に抽象的な言葉が含まれていたパターン

○○できるようになる。

系の目標ですね。

それに対する私の返信

これって、どうなったら出来た!って言えるんでしょう。
XXさんから「AA君の説明は素晴らしい!」と褒められたらですかね?
分析(←目標に対する分析のこと)のほうにも、「なんとかなった」としか記載がないので、
読み取れなかったです。抽象的な表現はせず、詳細がイメージできるような目標がいいですよ。
イメージしにくいと、目標への意欲も減ってしまう恐れがありますので。
(と、偉そうに言ってますが、僕自身も抽象的な目標を立ててしまう人ですorz)

2.↑に対して、どのように目標設定すればいいかアドバイスを求められたパターン

どうしても抽象的な目標になりがちです。アドバイスください。

系の質問ですね。

それに対する私の返信

お、聞き返してくれる!嬉しいです。
私なりの方法は、「目標を達成した自分がイメージできるか想像してみる」です。
>説明できるようにする。
この目標なんですが、達成した自分を想像してみてください。
その時、AAさんはどんな状態ですか?
その状態を書けば、きっと具体的な目標になっているはずです。
「XXさんに褒められた」でもいいですし、「説明に対する質問に全て回答できた」とか。
状態が思い浮かばないなら、その目標は重要ではないかもしれません。
なぜその目標なのかを自問自答して深堀りしてもいいですし、
目標チェンジしてもいいかもしれません。

ネットで探すと、方法はいくらでもあります。
自分なりの方法に出会えるといいですね。
後は「慣れ」もありますよ。
研修期間中、目標を立てることが多いとおもいます。いい機会ですので、慣れておきましょう!

3.目標がタスクパターン

タスクを終わらせる!

系の目標ですね。

それに対する私の返信

ちょっと内容に突っ込みますmm
スケジュール通りに作業を進められるようになりたい!ということですが、
タスクを終わらせるっていう目標は、上記の「思い」を解決できると思います?
AA君が思うのであれば問題ないのですよ!
僕的にはタスクを終わらせるために、「いつもと違う工夫」を目標に設定して欲しいな!って思いました。
でないと、またタスクが終わらないという問題が発生しそうで。。ループな気がw

4.数を意識しすぎる目標分析パターン

数値目標に対して数値がどうだった!

系の結果分析ですね。(数値に関する分析しかしていない

それに対する私の返信

3つの目標に対して振り返りをしてもらいましたが、
とっても重要なことが抜けているので、アドバイスしますね。
正直に言うと、「達成度合い」だとか「数」だとかは、僕にとって
どーーーでもいいです。。。(まぁ数を出せって言われるからやらなきゃいけないんだけど。

どっちかというと、目標に向かってアクションを起こした結果、
AA君の仕事内容とか夢とか人生、気持ちにどう影響を与えたかが興味あります。
プラスに働いたでしょうか?それとも変わらず?
分析内容ではそういった内容で書いて欲しかったです。
(今度からそんな感じで書いてくれると嬉しいな(*^^*)
数を達成していても、プラスに働いてなければもったいない!

取り組んでみてよかったことや悪かったことを脳内やメモ帳などに
たっくさんあげていきましょう。そして、1個か2個くらいをピックアップし、
もうちょっと深く考えてみましょう。コツは自分に問い掛けてみることです。
「なぜ?」「どうなった?」「どうなる?」みたいな感じで。
それを繰り返すことで、きっといい分析ができると思います。
最初は難しいと思いますが、頑張ってみてください。
実は僕も、つい最近までできませんでした。。。。今もかも。。。

5.目標が目先のことパターン

目先のタスクを片付ける

系の目標ですね。

それに対する私の返信

承知しm。。。。
って思ったけど、アドバイス1つ。
今回の目標は、とっても大切なことだとは思います。
でも、さらに良くする方法があります!
それは、、、目標設定をする際、
特に強い思い?がない限り「目先のタスクに焦点を当てない」ことです。
後、自分を分析してみるのも有効です。AA君の持っているスキルは何でしょう?
ゴール(全タスク完了)に対して、そのスキルをどう活かせばいいでしょう?
そのゴールに向かって行動することで、どう社会に貢献できるでしょう?
このような感じで自問自答を日々繰り返しながら、目標を考えてみましょう!
もっと成長を促せるような目標にたどり着けるはず!?

晒してみて

転記しながら振り返ると、
自分なりには間違ってないかなーって思います。

さて、、、公開しますよーw

Highchartsに好きなパラメータを渡す方法

何がしたいか

Highchartsのツールチップは、勝手にグラフの値を出してくれるので
非常に便利です。僕も愛用していますmm

しばらく使っているうちに、
ツールチップ「グラフの値以外も出したい!」といった欲が出てきました。
そんな時の解決方法を書きたいと思います。

解決方法

--解決前--

棒グラフを出力する際は、以下のようなコードを書くと思います。

<!--通常の棒グラフ-->
<div class="subTitle">
    <h2>通常の棒グラフ</h2>
</div>
<div class="chartArea" id="chart1"></div>

<!--サンプルスクリプト-->
<script type="text/javascript">
$(function () {
    $('#chart1').highcharts({
        chart: {
            type: 'column'
        },
        xAxis: {
            categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
        },
        plotOptions: {
            series: {
                allowPointSelect: true
            }
        },
        series: [{
            data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
        }]
    });
});
</script>

f:id:nullppo:20160614125524p:plain

--解決後--

まず、dataを指定する際に連想配列を使います。
そして、配列に独自のプロパティを定義して、そこにデータを突っ込めばDONE!!
後はツールチップのオプションで呼び出すだけです。(pointFormatの部分)

<!--複数パラメータを渡した棒グラフ-->
<div class="subTitle">
    <h2>複数パラメータを渡した棒グラフ</h2>
</div>
<div class="chartArea" id="chart2"></div>

<!--サンプルスクリプト-->
<script type="text/javascript">
    $(function () {
        $('#chart2').highcharts({
            chart: {
                type: 'column'
            },
            xAxis: {
                categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
            },
            plotOptions: {
                series: {
                    allowPointSelect: true
                }
            },
            tooltip: {
                pointFormat: '{series.name}: <b>{point.y}</b><br/><b>{point.exParam}</b><br/>',
                shared: true
            },
            series: [{
                data: [
                    {
                        y: 29.9,
                        exParam: 'sample1!'
                    }, {
                        y: 71.5,
                        exParam: 'sample2!'
                    }, {
                        y: 106.4,
                        exParam: 'sample3!'
                    }, {
                        y: 129.2,
                        exParam: 'sample4!'
                    }, {
                        y: 144.0,
                        exParam: 'sample5!'
                    }, {
                        y: 176.0,
                        exParam: 'sample6!'
                    }, {
                        y: 135.6,
                        exParam: 'sample7!'
                    }, {
                        y: 148.5,
                        exParam: 'sample8!'
                    }, {
                        y: 216.4,
                        exParam: 'sample9!'
                    }, {
                        y: 194.1,
                        exParam: 'sample10!'
                    }, {
                        y: 95.6,
                        exParam: 'sample11!'
                    }, {
                        y: 54.4,
                        exParam: 'sample12!'
                    }
                ]
            }]
        });
    });
</script>

f:id:nullppo:20160614125645p:plain

動きを見てみる

CodePenで動きを確認してみましょう
Extend parameter in Highcharts