kintoneとOutlookを連携してスケジュール管理をする#04

## 経緯
kintoneのOutlookを連携してスケジュール管理をしたい。
けど検索して出てくる記事が古いため、アレンジしてなるべく最新のものに対応する。

要するに「[Outlook連携 - kintoneからOutlookスケジュールを登録しよう！！](https://developer.cybozu.io/hc/ja/articles/360022249111-Outlook%E9%80%A3%E6%90%BA-kintone%E3%81%8B%E3%82%89Outlook%E3%82%B9%E3%82%B1%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%82%92%E7%99%BB%E9%8C%B2%E3%81%97%E3%82%88%E3%81%86-)」のOutlook連携をほぼサンプルのまま使っていたのだけど、先日急に動かなくなったので最新化対応したいということ。

### やりたいこと
- MSAL v2 に対応してkintoneとOutlookのスケジュールを連携させたい。
- kintone UI Component v1 対応したUIを構築したい。
- FullCalendar.js を導入してカレンダー表示させたい。

## 参考サンプル
こちらの２つのサンプルを参考にOutlook連携カスタマイズを行います。
1. [Outlook連携 - kintoneからOutlookスケジュールを登録しよう！！](https://developer.cybozu.io/hc/ja/articles/360022249111-Outlook%E9%80%A3%E6%90%BA-kintone%E3%81%8B%E3%82%89Outlook%E3%82%B9%E3%82%B1%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%82%92%E7%99%BB%E9%8C%B2%E3%81%97%E3%82%88%E3%81%86-)
2. [クイックスタート: PKCE 対応の承認コード フローを使用して JavaScript SPA 内でユーザーをサインインさせ、アクセス トークンを取得する](https://docs.microsoft.com/ja-jp/azure/active-directory/develop/quickstart-v2-javascript-auth-code)

## 今回（本記事）のゴール
MS Graphを使用してOutlookスケジュールを取得

## 記事一覧
1. [#01.ボタンを表示](https://qiita.com/iNaoki04/items/237f3828d103a8dc684e)
2. [#02.サインイン](https://qiita.com/iNaoki04/items/207666c8daf3dcbd9ac8)
3. [#03.サインアウトとボタン表示制御](https://qiita.com/iNaoki04/items/059ef1d51f567416eb25)
4. MS Graphを使用してOutlookスケジュールを取得 ← 当記事

## 実装
Microsoftのサンプルを流用します。

### javascript
- https://js.cybozu.com/jquery/3.3.1/jquery.min.js
- https://unpkg.com/kintone-ui-component/umd/kuc.min.js
- https://alcdn.msauth.net/browser/2.13.1/js/msal-browser.js
- authConfig.js
- authPopup.js
- graphConfig.js ← ★追加
- graph.js ← ★追加
- buttonSettings.js
- ui.js

### css
- buttons.css

### Azure AD の設定
スケジュールの取得に `calendarview` を使用するため、APIのアクセス許可に「Calendar.Read」と「Calendar.ReadWrite」を追加します。

![azure.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126147/d937963f-d59b-19df-81c2-716cf17c89cc.png)

参考：https://docs.microsoft.com/ja-jp/graph/api/user-list-calendarview?view=graph-rest-1.0&tabs=http


Outlookのスケジュールを取得するためのエンドポイントの設定内容を記述します。
calendarviewには必須パラメータがあるので、必要な情報をひとまとめにし、エンドポイントURLを作成して返してくれる関数も追加しておきます。
日付は初期値を設定しています。確認用などで適宜入力してください。
ヘッダーにタイムゾーンを追加していますが、こちらは任意で設定してください。

```graphConfig.js
let graphConfig = {
    // カレンダー取得設定
    graphCalView: {
        url: 'https://graph.microsoft.com/v1.0/me/calendarview',
        tokenRequest: {
            scopes: ['Calendars.Read', 'Calendars.ReadWrite'],
            forceRefresh: false
        },
        headers: {
            'Content-Type': 'application/json',
            'Prefer': "outlook.timezone=\"Tokyo Standard Time\", outlook.body-content-type=\"text\""
        },
        startPalam: 'startDateTime',
        startDate: '2021/04/01',
        startTime: 'T00:00:00.000Z',
        endPalam: 'endDateTime',
        endDate: '2021/04/01',
        endTime: 'T23:59:59.999Z',
    },

    // カレンダー取得のためのURLを取得
    getCalViewEndpoint: function () {
        return this.graphCalView.url + '?' + this.graphCalView.startPalam + '=' + this.graphCalView.startDate + this.graphCalView.startTime + '&' + this.graphCalView.endPalam + '=' + this.graphCalView.endDate + this.graphCalView.endTime;
    }
};

```

graph.jsはトークンの他にヘッダーを追加できるようにします。
コールバック用にスケジュール取得後に動く関数を追加しておきます。
現状は確認のためにコンソールに結果を返すようにしておきます。

```graph.js
let graphService = {
    callMSGraph: function (endpoint, token, header, callback) {
        const headers = new Headers();
        const bearer = `Bearer ${token}`;

        // ヘッダー追加
        headers.append('Authorization', bearer);
        for (let key of Object.keys(header)) {
            headers.append(key, header[key]);
        }

        const options = {
            method: "GET",
            headers: headers
        };

        console.log('request made to Graph API at: ' + new Date().toString());

        fetch(endpoint, options)
            .then(response => response.json())
            .then(response => callback(response, endpoint))
            .catch(error => console.log(error));
    },

    // Outlookスケジュール取得
    getEvent: function (data, endpoint) {
        console.log(endpoint);
        console.log(data);
    }
}
```

`authPopup.js`に`grach.js`の`callMSGraph`の呼び出しを追加します。

```authPopup.js
let authPopupService = {
...
    // Outlookイベントを取得する
    getEvent: function () {
        this.getTokenPopup(graphConfig.graphCalView.tokenRequest)
            .then(function (response) {
                graphService.callMSGraph(graphConfig.getCalViewEndpoint(), response.accessToken, graphConfig.graphCalView.headers, graphService.getEvent);
            }).catch(function (error) {
                console.log(error);
            });
    }
...
}
```

予定を取得するためのボタンを追加し、今回追加した処理を登録します。

```ui.js
    // サインイン後のボタン表示設定
    uiSignedCreateForIndex: function (kintoneHeaderSpace) {
...
        // 予定を取得ボタン
        this.data.ui.btnSignOut = this.createButton(this.setting.ui.buttons.getEvent, this.setting.i18n.button);
        this.data.ui.btnSignOut.addEventListener('click', function (event) {
            authPopupService.getEvent();
        });
        this.data.ui.HeaderSigned.appendChild(this.data.ui.btnSignOut);
...
},
```

「予定を取得」ボタンをヘッダーに表示するために設定を追加します。

```buttonSettings.js
...
    setting: {
        lang: 'ja',
        i18n: {},
        ui: {
            buttons: {
                signIn: {
                    text: 'signIn',
                    type: 'submit',
                    className: 'header-not-signed'
                },
                signOut: {
                    text: 'signOut',
                    type: 'normal',
                    className: 'header-signed'
                },
                getEvent: {
                    text: 'getEvent',
                    type: 'submit',
                    className: 'header-signed'
                },
                sendEvent: {
                    text: 'addEvent',
                    type: 'submit',
                    className: 'header-signed'
                }
            }
        }
    },
...
```

## 確認
ボタンが表示されているので押下してみます。
![sc1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126147/83a27b81-97f7-9e69-13b6-51faac97fe44.png)
コンソールを確認してスケジュールのデータがjson形式で取得できていたらOKです。
![sc2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126147/e36ec587-2e31-5eb9-0359-ea41b7471010.png)

## 次回
取得したOutlookスケジュールをkintoneに登録