kintoneからOutlookのスケジュールを登録できるサンプルです。
Outlookスケジュールの「イベントタイトル」「開始日時」「終了日時」「詳細内容」「添付ファイル」をkintoneから登録できます。
また、kintoneのレコードを変更した場合や、レコードを削除した場合にも、Outlookのイベントも更新されます。
Outlookのイベントを変更した場合は、kintoneのレコードには反映されません。
メリットとしては、kintoneに登録したレコードの内容をイベントとしてOutlookのスケジュールに登録し共有できることです。
また、kintoneのプロセス管理機能を使用してステータスを管理できます。
Outlook側への認証にOAuth2.0を利用しています。
少し敷居が高く感じられるかもしれませんが、詳しい手順の解説とサンプルコードを公開していますのでぜひ参考にしてください。
サンプルコードは
SAMPLE-kintone-connect-azure
に公開しています。
Microsoftが提供している
MSAL.js (外部サイト)
を利用することで、Outlook(Microsoftアカウント)とのOAuth2.0を利用した認証をkintone上で行うことができます。
連携の流れは以下となっています。
- kintoneからOAuth認証を用いてEntra ID V2 Endpointへサインイン
- kintoneからAzureへアクセストークンを取得
- アクセストークンを使ってGraph APIをたたく。
- kintoneからデータをOutlookスケジュールに登録
Graph APIはMicrosoft Cloudサービスリソースへのアクセスを可能にするAPIです。
kintoneアプリの作成
固定リンクがコピーされました
kintoneアプリストア
にある「
To Do
」アプリを使います。
アプリに以下のフィールドを追加してください。
フィールド名 |
フィールドタイプ |
フィールドコード |
イベントID |
文字列(1行) |
EventId |
また、アプリストアの「To Do」アプリは「開始日」「終了日」が「日付」フィールドとなっているため、「日時」フィールドに変更してください。
フィールド名 |
フィールドタイプ |
フィールドコード |
開始日時 |
日時 |
From |
終了日時 |
日時 |
To |
こちらがアプリの配置したフィールドのフォーム画面です。
Microsoft Entra IDアプリケーションの登録
固定リンクがコピーされました
Outlookとkintoneを連携させるために、Microsoft Entra IDへアプリケーションを登録する必要があります。
事前に以下を行ってください。
- Microsoftアカウントを取得します。
- 1で取得したアカウントを使って
Azure Portal
へログインします。
アプリケーションの登録
固定リンクがコピーされました
Outlook連携 - kintoneからOutlookメールの送受信をしよう
の
Microsoft Entra IDアプリケーションの登録
を参考に作成します。
今回使用するプログラムの準備
固定リンクがコピーされました
サンプルプログラム一式
固定リンクがコピーされました
SAMPLE-kintone-connect-azure
にプログラムを置いています。
入手方法
-
https://github.com/kintone-samples/SAMPLE-kintone-connect-azure/releases/tag/1.1.0
へアクセスします。
- [Assets]の「Source code(zip)」をクリックし、zipファイルをダウンロードします。
- ファイルを解凍します。
利用するプログラムファイル
common-js-functions.min.js
共通処理を記述するプログラムです。
commonディレクトリ内にあります。
kintone-connect-outlook-schedule-common.js
kintoneアプリ/Microsoftアプリの設定を記述するプログラムです。
環境に合わせて修正する部分があります(後述)。
outlook-scheduleディレクトリ内にあります。
oauth.js
OAuth2.0を利用してAzureへの認証処理を行うプログラムです。
commonディレクトリ内にあります。
kintone-connect-outlook-schedule.js
アクセストークンを用いてOutlookへスケジュールデータの登録/更新/削除するプログラムです。
outlook-scheduleディレクトリ内にあります。
kintone REST APIを便利に扱うことができるライブラリです。
詳しくは
kintone JS SDK
を参照してください。
入手方法
-
kintone-labs/kintone-js-sdk
にアクセスします。
- [Clone or download]ボタンをクリックし、zipファイルをダウンロードします。
- ファイルを解凍し、dist下の「kintone-js-sdk.min.js」を利用します。
kintoneライクなUIパーツを簡単に作成できるライブラリです。
詳しくは以下の記事を参照してください。
「kintone UI Component v0」を使って簡単にkintoneライクなUIを設置する
入手方法
-
kintone-labs/kintone-ui-component v0.4.2
にアクセスします。
- 「Assets」の[Source code]をクリックし、zipファイルをダウンロードします。
- ファイルを解凍し、dist下の「kintone-ui-component.min.js」「kintone-ui-component.min.css」を利用します。
また、今回は上記プログラム以外に次のライブラリを利用します。
- MSAL.js
AzureからOAuth認証でアクセストークンを取得するプログラムです。
https://secure.aadcdn.microsoftonline-p.com/lib/1.0.0/js/msal.js
- jQuery v3.4.1
https://js.cybozu.com/jquery/3.4.1/jquery.min.js
- Sweet Alert2 v8.17.6
- https://js.cybozu.com/sweetalert2/v8.17.6/sweetalert2.min.js
- https://js.cybozu.com/sweetalert2/v8.17.6/sweetalert2.min.css
kintone-connect-outlook-schedule-common.jsを修正します。
プログラムの7行目を
アプリケーションの登録
でメモしておいたアプリケーションIDに変更してください。
kintoneアプリのフィールドコードが
kintoneアプリの作成
に記載したフィールドコードと異なる場合には、25行目〜41行目を修正してください。
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
|
// kintone-connect-outlook-schedule-common.js
window.kintoneAzureConnect = {
config: {
auth: {
clientId: '####################',
authority: 'https://login.microsoftonline.com/common'
},
cache: {
cacheLocation: 'localStorage',
storeAuthStateInCookie: true
}
},
graphApiScorp: {
scopes: ['calendars.readwrite'],
},
eventUrl: 'https://graph.microsoft.com/v1.0/me/events',
kintone: {
fieldCode: {
// Field code of subject
subject: 'To_Do',
// Field code of body
body: 'Details',
// Field code of start
startDate: 'From',
// Field code of end
endDate: 'To',
// Field code of eventId
eventId: 'EventId',
// Field code of attachFile
attachFile: 'Attachments'
}
}
};
|
これらのプログラムを「アプリの設定 > JavaScript/CSSでカスタマイズ」下に配置します。
Azureへの認証処理 (oauth.js
)
固定リンクがコピーされました
Azureとの認証部分の処理をまとめています。
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
|
// oauth.js
/* global Msal */
(function() {
'use strict';
var KAC = window.kintoneAzureConnect;
var azureOauth = {
userAgentApplication: null,
getUserInfo: function() {
return this.userAgentApplication.getAccount().userName;
},
init: function() {
var self = this;
self.userAgentApplication = new Msal.UserAgentApplication(KAC.config);
},
signIn: function() {
var self = this;
return self.userAgentApplication.loginPopup(KAC.graphApiScorp);
},
signOut: function() {
var self = this;
self.userAgentApplication.logout();
},
callGraphApi: function() {
var self = this;
return self.userAgentApplication.acquireTokenSilent(KAC.graphApiScorp);
}
};
window.azureOauth = azureOauth || {};
}());
|
kintoneイベントの処理 (kintone-connect-outlook-schedule.js
)
固定リンクがコピーされました
kintoneの各イベント処理は以下となっています。
レコード一覧画面を表示した後のイベント
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
|
kintone.events.on('app.record.index.show', function(event) {
kintoneScheduleService.init();
/* create kintone ui */
kintoneScheduleService.uiCreateForIndex(kintone.app.getHeaderSpaceElement());
// init process
outlookAPI.init();
// click sign in button
kintoneScheduleService.data.ui.btnSignIn.on('click', function() {
outlookAPI.signIn();
});
// click sign out button
kintoneScheduleService.data.ui.btnSignOut.on('click', function() {
outlookAPI.signOut();
});
});
|
レコード詳細画面を表示した後のイベント
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
|
kintone.events.on('app.record.detail.show', function(event) {
var record = event.record;
kintoneScheduleService.init();
kintoneScheduleService.uicreateForDetail();
kintoneScheduleService.data.ui.btnSendEvent.on('click', function() {
// Confirm whether to execute
Swal.fire({
title: kintoneScheduleService.setting.i18n.message.info.confirmRegister,
type: 'warning',
confirmButtonColor: '#DD6B55',
confirmButtonText: kintoneScheduleService.setting.i18n.button.registerExec,
cancelButtonText: kintoneScheduleService.setting.i18n.button.cancelExec,
showCancelButton: 'true',
allowOutsideClick: false
}).then(function(isConfirm) {
if (isConfirm.value) {
return kintoneScheduleService.checkDateTime(record).then(function(isAllDay) {
outlookAPI.setDataForRegistration(record, isAllDay);
}, function() {
KC.ui.loading.hide();
});
}
}, function(dismiss) {
KC.ui.loading.hide();
});
});
});
|
レコード作成/編集画面を表示した後のイベント
801
802
803
804
805
806
807
808
809
810
|
kintone.events.on(['app.record.create.show',
'app.record.edit.show', 'app.record.index.edit.show'], function(event) {
var record = event.record;
if (event.type === 'app.record.create.show') {
record[EVENT_ID_FIELD_CODE].value = '';
}
record[EVENT_ID_FIELD_CODE].disabled = true;
return event;
});
|
レコードの保存に成功した後のイベント
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
|
kintone.events.on('app.record.edit.submit.success', function(event) {
var record, eventId;
record = event.record;
kintoneScheduleService.init();
if (record[EVENT_ID_FIELD_CODE] === undefined) {
return event;
}
eventId = record[EVENT_ID_FIELD_CODE].value;
if (eventId === '' || !kintoneScheduleService.isExpireAccessToken()) {
return event;
}
return new kintone.Promise(function(resolve, reject) {
Swal.fire({
title: kintoneScheduleService.setting.i18n.message.info.confirmUpdate,
type: 'warning',
confirmButtonColor: '#DD6B55',
confirmButtonText: kintoneScheduleService.setting.i18n.button.updateExec,
cancelButtonText: kintoneScheduleService.setting.i18n.button.cancelExec,
showCancelButton: 'true',
allowOutsideClick: false
}).then(function(isConfirm) {
if (isConfirm.dismiss === 'cancel') {
event.error = 'ダメです';
return event;
}
return kintone.Promise.all([kintoneScheduleService.checkDateTime(record), outlookAPI.getToOutlook(record)]);
}).then(function(respdata) {
if (respdata.type === 'app.record.edit.submit.success') {
return resolve(event);
}
return outlookAPI.setDataForUpdate(record, respdata[0]);
}).then(function() {
resolve(event);
}).catch(function(error) {
return Swal.fire({
title: 'Error!',
type: 'error',
text: kintoneScheduleService.setting.i18n.message.error.updateFailure,
allowOutsideClick: false
}).then(function() {
KC.ui.loading.hide();
resolve(event);
});
});
});
});
|
レコードを削除する前のイベント
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
|
kintone.events.on('app.record.detail.delete.submit', function(event) {
var record = event.record;
var eventId = record[EVENT_ID_FIELD_CODE].value;
if (!kintoneScheduleService.isExpireAccessToken() || eventId === '') {
return event;
}
return new kintone.Promise(function(resolve, reject) {
Swal.fire({
title: kintoneScheduleService.setting.i18n.message.info.confirmDelete,
type: 'warning',
confirmButtonColor: '#DD6B55',
confirmButtonText: kintoneScheduleService.setting.i18n.button.deleteExec,
cancelButtonText: kintoneScheduleService.setting.i18n.button.cancelExec,
showCancelButton: 'true',
allowOutsideClick: false
}).then(function(isConfirm) {
if (isConfirm.dismiss === 'cancel') {
return resolve(false);
}
return outlookAPI.getToOutlook(record);
}).then(function(respdata) {
if (respdata === undefined) {
KC.ui.loading.hide();
return resolve(false);
}
return outlookAPI.setDataForDelete(record);
}).then(function(resp) {
resolve(event);
}).catch(function() {
Swal.fire({
title: 'Error!',
type: 'error',
text: kintoneScheduleService.setting.i18n.message.error.deleteFailure,
allowOutsideClick: false
}).then(function() {
KC.ui.loading.hide();
resolve(true);
});
});
});
});
|
Outlookモジュール (kintone-connect-outlook-schedule.js
)
固定リンクがコピーされました
kintoneとOutlookのコネクション部分を一部抜粋して説明します。
MSAL.jsのインスタンス化
userAgentApplicationとしてインスタンス化し、以降の処理に利用します。
oauth.js
の処理を呼び出しています。
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
|
var outlookAPI = {
init: function() {
AO.init();
if (!kintoneScheduleService.isExpireAccessToken() || !kintoneScheduleService.isSignUserDispInfo()) {
kintoneScheduleService.data.ui.kintoneCustomizeOutlookHeaderNotSigned.style.display = 'inline-block';
kintoneScheduleService.data.ui.kintoneCustomizeOutlookHeaderSigned.style.display = 'none';
} else {
kintoneScheduleService.data.ui.kintoneCustomizeOutlookUserInfo.setText(storage.getItem('SIGN_USER_DISPINFO'));
kintoneScheduleService.data.ui.kintoneCustomizeOutlookHeaderNotSigned.style.display = 'none';
kintoneScheduleService.data.ui.kintoneCustomizeOutlookHeaderSigned.style.display = 'inline-block';
kintoneScheduleService.data.ui.kintoneCustomizeOutlookUserInfo.element.style.display = 'inline-block';
kintoneScheduleService.data.isLoginOutlook = true;
}
},
|
Azureからトークンを取得する
サインイン処理では、まずAzureからIDトークンを取得します。
oauth.js
の処理を呼び出しています。
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
|
signIn: function() {
var self = this;
KC.ui.loading.show();
AO.signIn().then(function(id_token) {
self.callGraphApi();
KC.ui.loading.hide();
}, function(error) {
Swal.fire({
title: 'Error!',
type: 'error',
text: kintoneScheduleService.setting.i18n.message.error.signInFailure,
allowOutsideClick: false
});
KC.ui.loading.hide();
});
},
signOut: function() {
KC.ui.loading.show();
storage.clear();
AO.signOut();
KC.ui.loading.hide();
},
|
そして取得したIDトークンを用いてアクセストークンを取得します。
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
|
callGraphApi: function() {
var self = this;
AO.callGraphApi().then(function(token) {
var userInfo = AO.getUserInfo();
kintoneScheduleService.data.ui.kintoneCustomizeOutlookHeaderNotSigned.style.display = 'none';
kintoneScheduleService.data.ui.kintoneCustomizeOutlookHeaderSigned.style.display = 'inline-block';
kintoneScheduleService.data.ui.kintoneCustomizeOutlookUserInfo.setText(userInfo);
kintoneScheduleService.data.ui.kintoneCustomizeOutlookUserInfo.element.style.display = 'inline-block';
kintoneScheduleService.data.isLoginOutlook = true;
storage.setItem('SESSION_KEY_TO_ACCESS_TOKEN', token.accessToken);
storage.setItem('SIGN_USER_DISPINFO', userInfo);
KC.ui.loading.hide();
}, function(error) {
if (error) {
Swal.fire({
title: 'Error!',
type: 'error',
text: kintoneScheduleService.setting.i18n.message.error.getAccessTokenFailure,
allowOutsideClick: false
});
self.userAgentApplication = null;
KC.ui.loading.hide();
}
}).then(function() {
KC.ui.loading.hide();
}).catch(function() {
KC.ui.loading.hide();
});
},
|
取得したアクセストークンを用いたスケジュールデータの登録
GraphAPIをkintone上で叩いてOutlookのスケジュールデータを登録しています。
外部APIをkintone上でたたく方法は
外部のAPIを実行する
を参照してください。
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
|
registerToOutlookForAttachement: function(index, file, eventId, accessToken) {
var self = this;
var url = EVENT_URL + '/' + eventId + '/attachments';
var header = {
'Authorization': 'Bearer ' + accessToken,
'Content-Type': 'application/json'
};
return kintone.proxy(url, 'POST', header, file[index]).then(function(respdata) {
var responseDataJson = window.JSON.parse(!respdata[0] ? '{}' : respdata[0]);
if (typeof responseDataJson.error !== 'undefined') {
throw responseDataJson;
}
if (index + 1 < file.length) {
self.registerToOutlookForAttachement(index + 1, file, eventId, accessToken);
}
});
},
|
kintoneアプリのレコード一覧画面を開きます。
「Outlookにログイン」というボタンが表示されるので、ボタンをクリックします。
OAuth認証画面が表示されるので、「Microsoft Entra IDアプリケーションの登録」の
下準備
で準備したMicrosoftアカウントを使ってログインします。
メールアドレスを入力したあとにエラーが表示される場合、Microsoftアプリの設定を確認してください。
ログインに成功した場合、先ほどまで「Outlookにログイン」だったボタンが「Outlookからログアウト」に変わります。
kintoneのレコードを追加します。
レコードを保存すると、レコード詳細画面の上部に「予定を登録」というボタンが表示されるので、ボタンをクリックすればイベントを登録できます。
無事kintoneのレコードの内容がOutlookのスケジュールに登録されました。
- 2019/11/18
以下の利用ライブラリ変更に伴い、ソースコードを修正しました。
- kintone Utility Library for JavaScriptからkintone JS SDKに変更
- kintone UI Componentを追加
- jQuery v3.2.1からv3.4.1に変更
- SweetAlert2 v6.10.1からv8.17.6に変更
- Microsoft Graph v1からv2に変更