ガルーンで予定のリマインダーをブラウザのみで実施する

Cybozuのガルーンは、PCのCybozu Desktop2やスマホのKUNAIアプリに予定の通知機能はあるものの、 ブラウザでのNotification APIを使った通知機能は実装されていない(2023-01-24時点)。

そこで、JavaScript / CSSによるカスタマイズ機能を使って予定の時刻に迫った時に通知を表示させてみた(管理者向け)。

実装

使うJavaScriptファイルは以下の内容の1ファイル。適当に拡張子.jsをつけて保存する。

(async function(){
	const TIME_FETCH_INTERVAL = 5 * 60 * 1000; // 予定の再取得をする間隔 [ms]
	const TIME_NOTIFY_BEFORE = 3 * 60 * 1000; // 予定の何ミリ秒前に通知するか
	const TIME_NOTIFY_CLOSE = 30 * 1000; // 予定の通知を何ミリ秒後に閉じるか
	const icon_url = getComputedStyle(document.querySelector(".icon-appMenu-schedule")).backgroundImage.replace(/^.*"(.*)".*$/, "$1");
	const timers = [];
	
	if(Notification.permission === "default"){
		Notification.requestPermission();
	}
	
	const notifyGaroonEvent = function(){
		const now = Date.now();
		const date_start = (new Date(now)).toISOString();
		const date_end =  (new Date(now + 86400000)).toISOString();
		
		garoon.api(`/api/v1/schedule/events?rangeStart=${date_start}&rangeEnd=${date_end}&showPrivate=true`, "GET", {}, (resp) => {
			// 予定取得成功
			
			// 既存のタイマをクリア
			timers.map(e => clearTimeout(e));
			timers.length = 0;
			
			// タイマをセット
			for(const evt of resp.data.events.filter(e => e.isAllDay === false)){
				console.log(evt);
				const starttime = Date.parse(evt.start.dateTime);
				const timediff = starttime - now;
				
				// TIME_NOTIFY_BEFORE以降に予定があれば、通知するようにsetTimeout
				if(TIME_NOTIFY_BEFORE < timediff){
					timers.push(setTimeout(function(){
						console.log("Notification: " + evt.subject);
						const n = new Notification((evt.eventMenu ? (evt.eventMenu + ": ") : "") + evt.subject, {
							body: evt.notes,
							icon: icon_url,
							tag: evt.id
						});
						n.onclick = function(e){
							e.preventDefault();
							window.open("https://" + location.host + "/g/schedule/view.csp?event=" + evt.id, "_blank");
						};
						setTimeout(n.close.bind(n), TIME_NOTIFY_CLOSE); // 通知を自動消去
					}, timediff - TIME_NOTIFY_BEFORE));
					
					console.log("Set timer: " + (timediff - TIME_NOTIFY_BEFORE));
				}
			}
		}, (error) => {
			// エラー
			console.log(error);
		});
		
		// TIME_FETCH_INTERVAL後に再度予定を取得
		setTimeout(notifyGaroonEvent, TIME_FETCH_INTERVAL);
	};
	
	notifyGaroonEvent();
})();

上記のコードはクラウド版を前提にしているので、オンプレミス環境の場合はURLを適宜変更する。

あとはスケジュールのカスタマイズ | クラウド版 Garoon ヘルプに従って作業する。

途中で保存したJavaScriptファイルをアップロードすればOK。CSSは不要。

動作

カスタマイズ反映後の最初のアクセス時は、ブラウザが通知を許可するかどうかを訪ねてくるので「許可」する。

あとは適当に予定を作成すると、その開始時刻の3分前に以下のような通知が出てくるようになる(ChromeとEdgeでは動作を確認したが、Firefoxも動作するはず)。

ただし、ブラウザでガルーンのタブを開きっぱなしにしていないと通知は出ない点は注意。

また、SetTimeoutは正確に指定時刻後に実行されることを保証するわけではないが、だいたいうまく動作している。