ガルーンポータル活用 Tips #3 「電光掲示板ポータル(kintone 連携編)」

目次

はじめに

中堅・大規模組織向けグループウェア「サイボウズ Garoon」のポータル活用企画の第三弾として、電光掲示板風のテロップが流れるポータルを作成していきます。

電光掲示板の文字は kintone のアプリから取得しており、kintone のプロセス管理機能を利用して「承認」ステータスの情報のみがテロップとして流れます。

こんなときに便利です

  • 重要な掲示を見逃す人がいて困ってませんか?
  • また、重要な掲示がたまりすぎて空気になっていませんか?
  • 上長が内容を確認してからでないと掲示できない運用で困ってませんか?

電光掲示板ならできるんです!ぜひお試しください。

完成図

画像だと少し見づらいため、一部動画にしてみました。(動画キャプチャだと暗めですが、実際はもう少し明るく映ります)

要件

この記事でできることは次のとおりです。

  • Garoon の HTML ポートレットに kintone のレコードから取得した情報を表示する。
  • 表示対象データ
    • 公開範囲(公開開始日、公開終了日)を設定して、現在日付がその範囲にあるもの
    • かつ、kintone のプロセス管理を設定したレコードで「承認」ステータスのもの
    • テロップの文字は、kintone アプリのレコードの「タイトル」と「内容」フィールドを連結したもの
    • 複数レコードが対象の場合、ランダムの順番ですべてを表示する。
  • テロップをクリックすると、kintone アプリの一覧画面へ遷移する(複数レコードの場合を考慮して一覧画面としています)
  • 対象データが存在しない場合は電光掲示板そのものを表示しない。

kintone アプリ(全社通達アプリ)の準備

Garoon のポータルからデータを参照させるための kintone アプリを作成していきます。

フォームの設定

フォームのフィールドは以下のように配置していきます。

フィールド名 フィールドコード フィールドタイプ 備考
通達番号 レコード番号 レコード番号 自動入力
公開開始日 公開開始日 日付
公開終了日 公開終了日 日付
作成者 作成者 作成者 自動入力
承認者 承認者 ユーザー選択
タイトル title 文字列(1行) テロップに掲載されます
内容 content 文字列(複数行) テロップに掲載されます
添付ファイル 添付ファイル 添付ファイル お好みで追加してください

プロセス管理の設定

また、「設定」タブから「プロセス管理」の設定画面に進み、以下の画面のように設定します。

一覧の設定

Garoon のテロップをクリックすると見られるリンク先の一覧を作成します。「設定」タブから「一覧」タブに進み、右端の「+」ボタンをクリック。

以下の条件に合致するレコードだけが表示される一覧を作ります。

  • 公開範囲(公開開始日、公開終了日)を設定して、現在日付がその範囲にあるもの
  • 「承認」ステータスのもの

以下の画面を参考に設定してください。

「保存」をクリックして一覧の設定を保存し、アプリの設定全体を「アプリを更新」ボタンを押して、設定変更完了です。
仕上げに、kintone アプリの URL 内に含まれるアプリ ID と一覧 ID を、今作った一覧を表示したときの URL で確認しておきます。
ブラウザーの URL バーで確認します。

たとえば、URL が https://sample.cybozu.com/k/<appid>/?view=<viewid> の場合、アプリ ID と一覧 ID は以下になります。

  • アプリ ID:<appid>
  • 一覧 ID:<viewid>

kintone アプリ側の設定ができました!次はプログラムです。

リソースの準備

これまでと同様に、静的ファイル置き場として Garoon の「ファイル管理」を使います。
今回使うライブラリファイル(jQuery.marquee.js、marquee.css)は以下です。

garoon-portal3.zip

展開されたファイルとその説明です。

# ファイル名 環境に合わせた修正 説明
1 jQuery.marquee.js 基本的には不要 マーキーの動作を実装するための JavaScriptファイル です。
速度変更などの動作設定を調整したい場合はこちらを編集します。
今回はオープンソースを利用しています。
2 marquee.css 基本的には不要 マーキーのデザインを実装するための CSS ファイルです。
見た目を調整したい場合はこちらを編集します。

Garoon の「ファイル管理」を使って次の手順でリソースの準備をしていきます。

  1. サンプルコード を参考に、「bulletinsignage.js」を作成します(文字コードは「UTF-8」で保存してください)
    このとき、13 行目の APPID と 17 行目の VIEWID を、kintone アプリの準備で確認した ID に書き換えます。

    ポイント

    • 35 行目からの関数 generateRandomx にて乱数を生成し、毎回ランダムに表示する順番をかえています。(前回の 「社員紹介ポータル」 の流用です)
    • 63 行目にて、css ファイル(marquee.css)で定義したクラスを指定するとデザインを切り替えることができます。
      クラス ledtext01 で動作しなかった場合は、 ledtext02(シンプルパターン)に書き換えてお試しください。
  2. Garoon の「ファイル管理」の「オプション」-「フォルダーを追加する」で今回のポートレット用にフォルダーを作成します。

  3. フォルダーを選択した状態で「ファイルを追加する」をクリックし、次の 3 つのファイルを追加します。

    • bulletinsignage.js(修正済み)
    • jQuery.marquee.js
    • marquee.css

  4. このとき、追加されたファイル名をクリックして確認できる URL に含まれる hid(フォルダー ID)、fid(ファイル ID)を確認しておきます。
    これは、後程ポートレット作成時に使いますのでメモをしておきましょう。

    たとえば、URL が https://sample.cybozu.com/g/cabinet/view.csp?hid=<hid>&fid=<fid> の場合、hid と fid は以下になります。

    • hid:<hid>
    • fid:<fid>

サンプルコード

  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
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
/*
 * Garoon Portal sample program
 * Copyright (c) 2016 Cybozu
 *
 * Licensed under the MIT License
 * https://opensource.org/license/mit/
 */

(function($) {
  'use strict';

  // 情報を取得するアプリを設定する
  const APPID = 1;
  const APPNAME = '全社通達';
  const TITLECODE = 'title';
  const CONTENTCODE = 'content';
  const VIEWID = 1;

  // API実行のため、XMLHttpRequestをセットする
  const XMLHTTP = function() {
    let xmlhttp = false;
    if (typeof ActiveXObject !== 'undefined') {
      try {
        xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');
      } catch (e) {
        xmlhttp = false;
      }
    }
    if (!xmlhttp && typeof XMLHttpRequest !== 'undefined') {
      xmlhttp = new XMLHttpRequest();
    }
    return xmlhttp;
  };
    // generate randum numbers
  function generateRandomx(count) {
    const generated = [];
    let generatedCount = generated.length;
    for (let i = 0; i < count; i++) {
      let candidate = Math.floor(Math.random() * count);
      for (let j = 0; j < generatedCount; j++) {
        if (candidate === generated[j]) {
          candidate = Math.floor(Math.random() * count);
          j = -1;
        }
      }
      generated[i] = candidate;
      generatedCount++;
    }
    return generated;
  }
  // HTML作成する
  function makeSignageHtml(records) {
    let text = '【' + APPNAME + '】';
    const randomAray = generateRandomx(records.length);
    if (records.length > 0) {
      for (let i = 0; i < records.length; i++) {
        text += records[randomAray[i]][TITLECODE].value + ' - ';
        text += records[randomAray[i]][CONTENTCODE].value;
        text += ' / ';
      }
    }
    const url = '/k/' + APPID + '/?view=' + VIEWID;
    const $myParts = $('<a href="' + url + '" target="_blank"><div class="marquee ledText01"><p>' +
        text + '</p></div></a>');
    return $myParts;
  }
  // HTML出力する
  function showSignage(records) {
    if (records.length > 0) {
      $('#signage').append(makeSignageHtml(records));
      $('.marquee p').marquee();
    }
  }

  // 対象のアプリから、対象のレコードを取得する
  const kintoneNewestRecord = function() {
    const xhr = XMLHTTP();
    let url = '/k/v1/records.json?app=' + APPID;
    const query = 'ステータス = "承認" and 公開開始日 <= TODAY() and 公開終了日 >= TODAY() order by 更新日時';
    url += ['&query=' + encodeURIComponent(query),
      '&fields[0]=' + encodeURIComponent('$id'),
      '&fields[1]=' + encodeURIComponent('title'),
      '&fields[2]=' + encodeURIComponent('content')
    ].join('');

    xhr.open('GET', url, true);
    xhr.onreadystatechange = function() {
      if (xhr.readyState === 4 && xhr.status === 200) {
        const respJson = JSON.parse(xhr.responseText);
        showSignage(respJson.records);
      }
    };
    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
    xhr.send(null);
  };

  // 関数を実行する
  kintoneNewestRecord();

})(jQuery.noConflict(true));

Garoon ポートレットの準備

今回使う HTML ポートレットを作成していきます。
11 行目、 12 行目、 15 行目の「jQuery.marquee.js」「bulletinsignage.js」「marquee.css」のダウンロードリンクをリソースの準備で生成したリンクにそれぞれ書き換えます。

 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
<!--
* Garoon Portal sample program
* Copyright (c) 2016 Cybozu
* 
* Licensed under the MIT License
* https://opensource.org/license/mit/
-->

<!-- ▼Javascript設定▼ -->
<script type="text/javascript" src="https://js.cybozu.com/jquery/3.4.1/jquery.min.js"></script>
<script type="text/javascript" src="/g/cabinet/download.csp/-/jquery.marquee.js?fid=XX&ticket=&hid=X&.js"></script>
<script src="/g/cabinet/download.csp/-/bulletinsignage.js?fid=XX&ticket=&hid=X&.js"></script>

<!-- ▼CSS設定▼ -->
<link rel="stylesheet" href="/g/cabinet/download.csp/-/marquee.css?fid=XX&ticket=&hid=X&.css" type="text/css" />
<style type="text/css">
<!--
/*↓設定変更可能↓*/
/*電光掲示板風*/
.ledText01 {
    margin: 0 auto 20px;  /*周りの余白を調整*/
    padding:5px 0;   /*文字周りの余白を調整*/
    color: #FFB400;   /*←フォントカラー設定*/
    /*color: #FF51A8;*/   /*フォントカラー例:ピンク*/
    /*color: #00FF00;*/   /*フォントカラー例:グリーン*/
    /*color: #00D9FF;*/   /*フォントカラー例:ブルー*/
    font-size: 40px;   /*←フォントサイズ設定*/
}

/*シンプルパターン*/
.ledText02 {
    margin: 0 auto 20px;  /*周りの余白を調整*/
    padding:5px 0;   /*文字周りの余白を調整*/
    font-size: 20px;   /*←フォントサイズ設定*/
}
-->
</style>

<div id="signage"></div>

ポートレットを作成したらポータルに配置しましょう。

動作確認

kintone にいくつかのレコードを登録します。次の条件を両方満たしていないとテロップに表示されないためご注意ください。

  • 公開開始日を過去、公開終了日は未来に設定します。
  • ステータスを「承認」に進めます。

Garoon を開いて設置したポータルを確認します。テロップは流れているでしょうか。

試しに、ブラウザーを何度かリロードしてみましょう。複数の対象レコードがある場合は、ランダムの順番で表示されます。

おまけ

「Garoon ポートレットの準備」で開いた HTML ポートレットの変更画面にて、「▼CSS 設定▼」の color を指定している箇所の任意の場所のコメントを外すと…
(デフォルトの ledtext01 クラスを使っている場合のみ)

グリーンになります。

おわりに

kintone のデータを利用して、今回もおもしろいポートレットができました。
パッと目を引くテロップには厳選された情報を載せたいため今回は「全社通達」にしましたが、社内メンテナンス情報や総務からのお知らせなど、いろいろなシーンでも使えそうです。
お好みでデザインや動作、データの表示のし方を変えてみたりして、いろいろ工夫してみてください。

ガルーンポータル活用 Tips

更新履歴

  • 2020/02/19
    jQuery の追加手順および jQuery.noConflict(true) を使うようにコードを修正