ガルーンポータル活用 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 テロップ部分のデザイン設定用ファイル 不要 JavaScript / CSS によるカスタマイズ
jQuery.marquee.js テロップ部分の動きの設定用ファイル 不要 JavaScript / CSS によるカスタマイズ

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

ポイント

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

サンプルコード

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

(($) => {
  '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;
  }

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


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

  function getNewestFollow() {
    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>';

    return fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'text/xml', // SOAP APIのためのContent-Type設定
      },
      body: followRequest // リクエストボディ
    })
      .then(response => {
        if (!response.ok) {
          throw new Error('Network response was not ok.');
        }
        return response.text(); // レスポンスをテキストとして返す
      })
      .then(str => (new window.DOMParser()).parseFromString(str, 'text/xml'))
      .then(data => data.getElementsByTagName('follow')[0])
      .catch(error => console.error('Fetch error:', error));
  }

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


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

  // ---- makeHtml ----//{{{
  function makeSignageHtml(newestFollow) {
    const text = escapeHtml(newestFollow.getAttribute('text'));
    const divElement = document.createElement('div');
    divElement.className = 'marquee ledText01';
    const pElement = document.createElement('p');
    pElement.textContent = text;
    divElement.appendChild(pElement);
    return divElement;
  }

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

  function showSignage(newestFollow) {
    const signageElement = makeSignageHtml(newestFollow);
    document.getElementById('signage').appendChild(signageElement);
    $('.marquee p').marquee(); // Assuming marquee() is a valid jQuery plugin/function
  }

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

  getNewestFollow()
    .then(showSignage)
    .catch(e => console.error(e));

})(jQuery.noConflict(true));

Garoon ポートレットの準備

今回使うポートレットを作成していきます。
新規に HTML ポートレットを作成し、「ポートレットの内容」に次の 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
<!--
* Garoon Portal sample program
* Copyright (c) 2016 Cybozu
*
* Licensed under the MIT License
* https://opensource.org/license/mit/
-->

<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>

JavaScript ファイルと CSS ファイルのアップロード

JavaScript / CSS によるカスタマイズから以下を追加します。

JavaScript カスタマイズ
  • https://js.cybozu.com/jquery/3.7.1/jquery.min.js
  • jQuery.marquee.js
  • bulletinsignage.js
CSS カスタマイズ
  • marquee.css

ポータルに配置

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

動作確認

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

おわりに

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

ガルーンポータル活用 Tips

更新履歴

  • 2020/02/19
    jQuery の追加手順および jQuery.noConflict(true) を使うようにコードを修正
  • 2024/04/02
    • JavaScript と CSS ファイルをファイル管理にアップロードする方法から、ポータルの「JavaScript / CSS によるカスタマイズ」を使用する方法に変更
    • jQuery から JavaScript へサンプルコードをリファクタリング
information

この Tips は、2024 年 4 月版 Garoon で動作を確認しています。