今回は
通知を登録する
APIを用いて、kintoneレコードが新規登録された際、Garoonにレコード内容を通知するカスタマイズを紹介します。
いままで、Garoonとkintoneを両方使用していたユーザーの方は、双方通知を確認する必要がありましたが、今回のカスタマイズで通知をGaroonに一元管理できます。
- この機能は、以下の環境で動作します。
- クラウド版Garoon
- パッケージ版Garoon(ver 5.0.0以降)
- 製品のアップデートにより、通知アイコンを正常に表示できなくなる場合があります。
kintoneアプリ
固定リンクがコピーされました
Garoonシステム管理設定
固定リンクがコピーされました
システム管理(各アプリケーション)> 通知一覧 > 外部通知の設定 > 外部通知の追加から外部通知を設定する必要があります。
Garoonヘルプ - APIの外部通知の設定
クラウド版
・
パッケージ版
を参照してください。
下図を参考に外部通知を追加してください。
- ステータスは「有効」を選択します。
- 許可する外部通知は「API」にチェックしてください。
- 外部通知コードは「kintonedailyreport」に設定します。
- 許可するURLは下記2つを設定します
sample
の部分はご自身の環境に合わせて設定してください。
https://sample.cybozu.com/*
kintone(sample.cybozu.com/k...)からGaroon REST APIを実行するために設定します。
https://static.cybozu.com/*
今回は通知アイコンに製品内の画像を使用しているので上記URLを含める必要があります。
kintoneアプリ作成
固定リンクがコピーされました
下表を参考に4つのフィールドをアプリに設定し、簡単な日報アプリを作成します。
フィールドタイプ |
フィールドコード |
備考 |
文字列 (1行) |
title |
必須項目にする |
文字列 (複数行) |
body |
必須項目にする |
日付 |
date |
レコード登録時の日付を初期値にする |
作成者 |
作成者 |
|
JavaScript / CSSカスタマイズ設定
固定リンクがコピーされました
サンプルコード
次のサンプルコードを「dailyReport.js」という名前で保存します。文字コードは「UTF-8」を使用してください。
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
|
/*
* Notify Garoon Sample Program
* Copyright (c) 2018 Cybozu
*
* Licensed under the MIT License
* https://opensource.org/license/mit/
*/
(function($) {
'use strict';
// Garoonで設定した外部通知コード
const grnNoticeCode = 'kintonedailyreport';
// 通知を送信するユーザーのログイン名
const grnNoticeUser = ['{Target User Login Name}'];
// kintoneのアプリのURL
const kntAppURL = 'https://sample.cybozu.com/k/xx/';
// SOAPのXMLのヘッダー部分を作成する
const makeXMLHeader = function(service, action) {
let xmlns;
if (service === 'schedule') {
xmlns = 'schedule_services="http://wsdl.cybozu.co.jp/schedule/2008"';
} else {
return null;
}
return '<?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">' + 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>';
};
// ajaxを実行する
const runajax = function(url, method, dtype, sendobj, callback) {
const objajax = {type: method, url: url};
const headers = {'X-Requested-With': 'XMLHttpRequest'};
// データをxml形式で送信する場合
if (dtype === 'xml') {
headers['Content-Type'] = 'text/xml; charset=UTF-8';
objajax.data = sendobj;
// データをjson形式で送信する場合
} else if (dtype === 'json') {
headers['Content-Type'] = 'application/json';
objajax.contentType = 'application/json';
objajax.data = JSON.stringify(sendobj);
objajax.dataType = 'json';
}
objajax.headers = headers;
// ajaxを実行
return $.ajax(
objajax
);
};
// Garoonに通知を送信
const sendNotice = function(rec, token) {
const arydest = [];
// 通知の送信先を配列にまとめる
for (let i = 0; i < grnNoticeUser.length; i += 1) {
arydest.push({type: 'USER', code: grnNoticeUser[i]});
}
// 送信する通知の情報
const sendobj = {
// リクエストトークン
__REQUEST_TOKEN__: token,
// Garoonで設定した外部通知コード
app: grnNoticeCode,
// 通知のキー(他のレコードと重複しないこと)
notificationKey: kntAppURL + rec.$id.value,
// kintoneのレコードのURL
url: kntAppURL + 'show#record=' + rec.$id.value,
// 通知のモード 「add: 追加, modify: 変更, remove: 削除」
operation: 'add',
// 通知のタイトル ※レコードのタイトルを出力
title: rec.title.value,
// 通知の本文 ※レコードの本文を出力
body: rec.body.value,
// 通知のアイコン
icon: 'https://static.cybozu.com/g/F19.11_379/grn/image/cybozu/image-common/kintone.svg',
// 通知の送信先
destinations: arydest
};
// 通知を送信
return runajax('/g/api/v1/notification/items', 'POST', 'json', sendobj).then((resp) => {
return resp;
}).catch((err) => {
return err;
});
};
// Garoonのリクエストトークンを取得する
const getRequestToken = function() {
const xml = makeXMLHeader('schedule', 'UtilGetRequestToken') +
'<SOAP-ENV:Body>' +
'<UtilGetRequestToken></UtilGetRequestToken>' +
'</SOAP-ENV:Body>' +
'</SOAP-ENV:Envelope>';
// Garoonのリクエストトークンを取得
return runajax('/g/util_api/util/api.csp', 'POST', 'xml', xml).then((resp) => {
const $resp = $(resp);
// リクエストトークンの文字列部分を抽出して返す
const token = $resp.find('request_token').text();
return token;
}).catch((err) => {
return err;
});
};
// レコードの保存に成功したとき
kintone.events.on(['app.record.create.submit.success'], (ev) => {
const rec = ev.record;
// Garoonのリクエストトークンを取得する
return getRequestToken().then((token) => {
// 通知を送信する
return sendNotice(rec, token);
// 成功時
}).then((resp) => {
return ev;
// 失敗時
}).catch((err) => {
alert(err.responseText);
return ev;
});
});
// イベント:新規画面を開いたとき
kintone.events.on(['app.record.create.show'], (ev) => {
const rec = ev.record;
// 「タイトル」フィールドにユーザー名と日付を表示する
rec.title.value = '日報: ' + kintone.getLoginUser().name + ' (' + rec.date.value + ')';
// 「本文」フィールドに日報の初期フォーマットを表示する
rec.body.value = '■本日の業務\n\n\n■本日の学び・感想\n\n\n■相談・連絡';
return ev;
});
})(jQuery.noConflict(true));
|
14・16行目をご自身の環境に合わせて編集してください。
13
14
15
16
|
// 通知を送信するユーザーのログイン名
const grnNoticeUser = ['{Target User Login Name}'];
// kintoneのアプリのURL
const kntAppURL = 'https://sample.cybozu.com/k/xx/';
|
アプリ画面の右上の歯車マークから、アプリの設定 > 設定タブ > JavaScript / CSSでカスタマイズの順番に遷移し、下図のように設定します。
本カスタマイズでは、
Cybozu CDN
の以下のライブラリーを使用します。
- jQuery
https://js.cybozu.com/jquery/3.3.1/jquery.min.js
jQueryはdailyReport.jsより上位に登録してください。
以上ですべての設定は完了です。
サンプルコード「dailyReport.js」について解説していきます。
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
|
// SOAPのXMLのヘッダー部分を作成する
const makeXMLHeader = function(service, action) {
let xmlns;
if (service === 'schedule') {
xmlns = 'schedule_services="http://wsdl.cybozu.co.jp/schedule/2008"';
} else {
return null;
}
return '<?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">' + 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>';
};
|
Garoon SOAP APIのヘッダー部分を作成する関数です。
今回はリクエストトークンを取得するために一度だけSOAP APIを実行します。
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
|
// ajaxを実行する
const runajax = function(url, method, dtype, sendobj, callback) {
const objajax = {type: method, url: url};
const headers = {'X-Requested-With': 'XMLHttpRequest'};
// データをxml形式で送信する場合
if (dtype === 'xml') {
headers['Content-Type'] = 'text/xml; charset=UTF-8';
objajax.data = sendobj;
// データをjson形式で送信する場合
} else if (dtype === 'json') {
headers['Content-Type'] = 'application/json';
objajax.contentType = 'application/json';
objajax.data = JSON.stringify(sendobj);
objajax.dataType = 'json';
}
objajax.headers = headers;
// ajaxを実行
return $.ajax(
objajax
);
};
|
jQueryのajaxを使用してHTTPリクエストを実行する関数です。
リクエストトークン取得と、通知登録でそれぞれSOAP API、REST APIを実行する必要があります。
そのため、引数の「dtype」により、処理を分岐させています。
sendNoticesendNotice
固定リンクがコピーされました
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
|
// Garoonに通知を送信
const sendNotice = function(rec, token) {
const arydest = [];
// 通知の送信先を配列にまとめる
for (let i = 0; i < grnNoticeUser.length; i += 1) {
arydest.push({type: 'USER', code: grnNoticeUser[i]});
}
// 送信する通知の情報
const sendobj = {
// リクエストトークン
__REQUEST_TOKEN__: token,
// Garoonで設定した外部通知コード
app: grnNoticeCode,
// 通知のキー(他のレコードと重複しないこと)
notificationKey: kntAppURL + rec.$id.value,
// kintoneのレコードのURL
url: kntAppURL + 'show#record=' + rec.$id.value,
// 通知のモード 「add: 追加, modify: 変更, remove: 削除」
operation: 'add',
// 通知のタイトル ※レコードのタイトルを出力
title: rec.title.value,
// 通知の本文 ※レコードの本文を出力
body: rec.body.value,
// 通知のアイコン
icon: 'https://static.cybozu.com/g/F19.11_379/grn/image/cybozu/image-common/kintone.svg',
// 通知の送信先
destinations: arydest
};
// 通知を送信
return runajax('/g/api/v1/notification/items', 'POST', 'json', sendobj).then((resp) => {
return resp;
}).catch((err) => {
return err;
});
};
|
Garoon通知APIを実行する関数です。sendobjがリクエストボディです。
APIの詳細は
通知を登録する
を確認してください。
104行目のiconオプションにkintone製品内の画像を設定しています。
前提条件と注意事項にもあるように、今後製品のアップデートにより正常に表示されなくなる可能性があるので注意してください。
getRequestToken
固定リンクがコピーされました
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
// Garoonのリクエストトークンを取得する
const getRequestToken = function() {
const xml = makeXMLHeader('schedule', 'UtilGetRequestToken') +
'<SOAP-ENV:Body>' +
'<UtilGetRequestToken></UtilGetRequestToken>' +
'</SOAP-ENV:Body>' +
'</SOAP-ENV:Envelope>';
let $resp, token;
// Garoonのリクエストトークンを取得
return runajax('/g/util_api/util/api.csp', 'POST', 'xml', xml).then((resp) => {
$resp = $(resp);
// リクエストトークンの文字列部分を抽出して返す
token = $resp.find('request_token').text();
return token;
}).catch((err) => {
return err;
});
};
|
リクエストトークンを取得する
関数を実行します。
makeXMLHeader関数で設定したSOAP API用のヘッダーと、この関数内で成型したボディを使用し、SOAP APIを実行しています。
今回のアップデートにより、Garoon以外の製品からGaroonへ通知を登録することが可能になりました。
本Tipsではkintoneから通知を登録してみましたが、他の製品からもGaroonへ通知を登録できそうですね。
ぜひGaroon REST APIを触ってみてください。