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

目次

はじめに

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

あれ?電光掲示板はこの前もやったんじゃない?と思われるかもしれません。

…違うんです! 「電光掲示板ポータル(kintone 連携編)」 は電光掲示板の文字を kintone のアプリから取得しましたが、今回はシンプル版!
Garoon 掲示板の最新フォローから取得してみます。複雑なロジックも少なく、よりスモールスタートしやすい版ともいえます。

こんなときに便利です

  • 重要な掲示を見逃す人がいて困ってませんか?
  • また、重要な掲示がたまりすぎて空気になっていませんか?

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

完成イメージ

テロップだけ動画にしてみました。

このポータルは電光掲示板風ポートレットの活用例としての、各部からのお知らせを表示するポータルです。
今回作る部分は、トップの「全社通知ポートレット」のみです。掲示板のフォローからデータを抽出します。

なお、電光掲示板の部分以外は、標準ポートレットの「掲示板」の本文を利用しています。
本文からデータを取得するパターンはまた別の Tips で紹介します!

データ取得元の準備

使いたい掲示板のタイトルをクリックした際、URL 内に含まれる aid(掲示 ID)を確認しておきます。
これは、掲示板情報の取得プログラムの修正時に使います。

たとえば URL が https://sample.cybozu.com/g/bulletin/view.csp?cid=<cid>&aid=<aid> の場合、aid は <aid> の部分です。

今回はこのような掲示板です。最新のフォローのみ取得します。

リソースの準備

今回使うライブラリファイル(marquee.css、jQuery.marquee.js)は以下からダウンロードできます。

garoon-portal4.zip

ファイルの説明

ファイル名 説明 修正が必要か 配置先
marquee.css テロップ部分のデザイン設定用ファイル 不要 ファイル管理
jQuery.marquee.js テロップ部分の動きの設定用ファイル 不要 ファイル管理

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

  1. カスタマイズファイルとして、 サンプルコード を参考に「bulletinsignage.js」を作成します(文字コードは「UTF-8」で保存してください)
    このとき、14 行目の TOPIC_ID を、 データ取得元の準備 で確認した aid に書き換えます。

    ポイント

    132 行目で、css ファイル(marquee.css)にて定義したクラスを指定することでデザインを切り替えることができます。
    クラス ledtext01 で動作しなかった場合は、ledtext02(シンプルパターン)に書き換えてお試しください。

  2. Garoon の「ファイル管理」で今回のポートレット用にフォルダーを作成します。

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

    • marquee.css
    • jQuery.marquee.js
    • bulletinsignage.js(修正済み)
  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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
 * Garoon Portal sample program
 * Copyright (c) 2016 Cybozu
 *
 * Licensed under the MIT License
 * https://opensource.org/license/mit/
 */

(function($) {
  'use strict';

  // ---- settings ----//{{{

  const TOPIC_ID = 1;

  // function to escape html
  function escapeHtml(str) {
    if (!str) {
      return '';
    }
    return str
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;')
      .replace(/'/g, '&#39;');
  }

  // ---- settings ----//}}}


  // ---- xml settings ----//{{{

  // function to make XML Header for Garoon API
  // arg1:services:service type (base,schedule)
  // arg2:action:name of API
  // return:XML header string
  function makeXMLHeader(services, action) {
    let xmlns;
    switch (services) {
      case 'base':
        xmlns = 'base_services="http://wsdl.cybozu.co.jp/base/2008"';
        break;
      case 'bulletin':
        xmlns = 'workflow_services="http://wsdl.cybozu.co.jp/bulletin/2008"';
        break;
      default:
        alert('Can not select services');
        return;
    }

    const xmlHeader =
      '<?xml version="1.0" encoding="UTF-8"?>' +
      '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:' + xmlns + '>' +
      '<SOAP-ENV:Header>' +
        '<Action SOAP-ENV:mustUnderstand="1" xmlns="http://schemas.xmlsoap.org/ws/2003/03/addressing">' + escapeHtml(action) + '</Action>' +
        '<Timestamp SOAP-ENV:mustUnderstand="1" Id="id" xmlns="http://schemas.xmlsoap.org/ws/2002/07/utility">' +
            '<Created>2037-08-12T14:45:00Z</Created>' +
            '<Expires>2037-08-12T14:45:00Z</Expires>' +
        '</Timestamp>' +
        '<Locale>jp</Locale>' +
      '</SOAP-ENV:Header>';
    return xmlHeader;
  }


  // function to set XMLHTTP
  // return xmlhttp object
  function setXMLHTTP() {
    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;
  }

  // ---- xml settings end ----//}}}


  // ---- getGrnData ----//{{{

  function getNewestFollow() {
    return new Promise((resolve, reject) => {
      const xhrForFollow = setXMLHTTP();
      const url = '/g/cbpapi/bulletin/api.csp';
      const apiName = 'BulletinGetFollows';

      const followRequest =
        makeXMLHeader('bulletin', apiName) +
        '<SOAP-ENV:Body>' +
            '<' + apiName + '>' +
                '<parameters topic_id="' + TOPIC_ID + '" offset="0" limit="1"></parameters>' +
            '</' + apiName + '>' +
        '</SOAP-ENV:Body>' +
        '</SOAP-ENV:Envelope>';
      console.log(followRequest);

      xhrForFollow.open('POST', url, true);
      xhrForFollow.onload = function() {
        if (xhrForFollow.readyState === 4 && xhrForFollow.status === 200) {
          resolve(xhrForFollow.responseXML.getElementsByTagName('follow')[0]);
        }
      };
      xhrForFollow.send(followRequest);
    });
  }

  // ---- getGrnData finish ----//}}}


  // ---- showPortlet ----//{{{

  // ---- makeHtml ----//{{{
  function makeSignageHtml(newestFollow) {
    const text = newestFollow.getAttribute('text');
    return '<div class="marquee ledText01"><p>' + text + '</p></div>';
    // "/g/bulletin/view.csp?cid=1&aid=14&follow_id_autolink=3#follow"
  }

  // ---- makeHtml end ----//}}}

  function showSignage(newestFollow) {
    console.log(newestFollow);
    const signageHtml = makeSignageHtml(newestFollow);
    $('#signage').append(signageHtml);
    $('.marquee p').marquee();
  }

  // ----showPortlet finish----//}}}


  getNewestFollow()
    .then(showSignage, (e) => {
      console.log(e);
    });


})(jQuery.noConflict(true));

Garoon ポートレットの準備

今回使うポートレットを作成していきます。
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
40
41
42
43
44
45
<!--
* 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 type="text/javascript" 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;   /*←フォントサイズ設定*/
}
/*オリジナルの配色設定*/
.ledText02.marqueeColorScheme {
    color: #fff;   /*←フォントカラー設定*/
    background: #333;   /*←背景色設定*/
}
-->
</style>

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

新規に HTML ポートレットを作成し、「ポートレットの内容」に記述します。

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

動作確認

掲示板の最新のフォローと、電光掲示板の内容が一致しているか確認します。

おわりに

シンプルに実装できる電光掲示板風ポートレットを紹介しました。
冒頭の完成イメージのように各部の掲示板とセットで配置すると、全社の重要な情報&各部からのリアルタイム発信をまとめて把握できる、実用的なポータルになりますね。
今後も簡単に作れる凝ったポートレットをどんどん紹介していきますので、お楽しみに~。

ガルーンポータル活用 Tips

更新履歴

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