kintoneのイベント・フェアカレンダーの日程をGoogleカレンダーに公開しよう!

目次

はじめに

kintoneアプリのイベント・フェアカレンダーを利用して、イベントの日程をGoogle WorkspaceのGoogleカレンダーに連携して社内で共有します。

有料のGoogle WorkspaceのGoogleカレンダーの場合、社内でイベントの日程を管理し、承認後に社内でカレンダー日程をセキュアに共有したい場合などに利用できます。
また、設定で一般公開すれば、社外にもEメール等でイベントの告知とカレンダー日程の同期が可能になります。

事前に必要なもの

  • Google Workspaceアカウント(有料アカウント)
  • kintoneアカウント

開発の流れ

  1. Googleカレンダーの作成・設定
  2. kintoneアプリの設定・変更
  3. JavaScriptによるプログラムの作成
  4. 動作の確認

以上の手順で開発していきます。

1. Googleカレンダーの作成・設定

ステップ1

Google.com (External link) より、ログインし、右上Googleアプリアイコンより、カレンダーを選択します。

左サイドメニューの他のカレンダーの右側の「+」をクリックして、「新しいカレンダーを作成」を選択します。

カレンダー名を入力し、「カレンダーを作成」ボタンをクリックし、カレンダーを作成します。

次に左メニューより、新しく作成されたカレンダーのオーバーフローメニューより、「設定と共有」を選択します。

「アクセス権限」のセクションにおいて、「{組織名}で利用できるようにする」をチェックします。
ドロップダウンより「予定の表示(すべての予定の詳細)」を選択します。

次に「特定ユーザーとの共有」設定で、「ユーザーを追加」をクリックし、組織内のユーザーのメールアドレスを追加します。
また「権限」のドロップダウンで「予定の変更」を選択します。

「送信」ボタンをクリックすると指定したユーザーに招待状が送信されます。
指定したユーザーが招待状を承認することにより、作成した「イベント・フェアカレンダー」が共有できます。

「設定」画面で下にスクロールすると、「カレンダーの統合」の項目内に「カレンダーID」が表示されているので、メモしておきます。
後のプログラミングで必要です。

ステップ2

次にGoogle APIを利用するためにGoogleカレンダーAPIの認証情報を設定します。
まず、 Google APIのデベロッパーコンソール (External link) にログインします。
ダッシュボード画面が表示されたら、下の画像のように右上の「プロジェクト作成」をクリックします。

プロジェクト名を入力し、「作成」ボタンをクリックすると、新規プロジェクトが作成されます。

ステップ3

「APIとサービスの有効化」をクリックして、「APIライブラリ」設定画面へ移行します。

G Suiteカテゴリーより、「Google Calendar API」を選択します。

「有効にする」をクリックして、Google Calendar APIを有効にします。

ステップ4

右上の「認証情報を作成」をクリックします。

使用するAPIに「Google Calendar API」を選択し、次の内容を入力します。

  • APIを呼び出す場所:Webブラウザー(JavaScript)
  • アクセスするデータの種類:ユーザーデータ

入力したら「必要な認証情報」をクリックします。

「OAuth同意画面の設定」が表示されるので、「同意画面を設定」をクリックします。

ステップ5

アプリを使用するユーザーのタイプを選択し、「作成」をクリックします。
今回は、「内部」を選択しました。なお、このオプションは、有料アカウントの場合のみ選択可能です。

OAuth同意画面にて、「同意を求めるアプリの名前」を入力し、「ユーザーサポートメール」を選択します。

「承認済みドメイン」にお使いのkintoneのドメイン名を入力(例:cybozu.com)し、「デベロッパーの連絡先情報」にメールアドレスを入力、「保存して次へ」をクリックします。

スコープに「Google Calendar API」を選択し、「更新」をクリックします。

内容を確認して、「保存して次へ」をクリックします。

アプリ登録の概要を確認し、「ダッシュボードに戻る」をクリックし、「OAuth同意画面」の設定を完了します。

ステップ6

認証情報設定の画面に戻り、OAuth 2.0クライアントに適当な名前を入力します。
また、それぞれ次の情報を入力します。

  • 承認済みのJavaScript生成元:kintoneのURL(例;https://{サブドメイン}.cybozu.com)
  • 承認済みのリダイレクトURL:kintoneアプリのURL(例:https://{サブドメイン}.cybozu.com/k/{アプリケーションID}/)
    kintoneアプリは後で作成します。

最後に「OAuthクライアントIDの作成」ボタンをクリックして、クライアントIDを生成します。

クライアントIDが作成されますので、メモしておきます。(後のカスタマイズのプログラミングで使用します)

「完了」ボタンをクリックして、終了します。

ステップ7

再び、「認証情報を作成」メニューから、今度は、「APIキー」を選択します。

APIキーが作成されますので、メモしておきます。

tips
補足

「キーの制限」の設定をすることにより、キーの不正仕様や盗用を防止できます。必要に応じて設定してください。
詳細は、 Googleのドキュメント:APIキーの使用 (External link) を参照してください。

左サイドメニューの「認証情報」をクリックすると生成した認証情報が確認できます。

以上でGoogleカレンダー側の設定は終了です。

2. kintoneアプリの設定・変更

ステップ1

今回は、kintoneアプリの「イベント・フェアカレンダー」を元にアプリを設定・変更します。
kintoneアプリストアより、左サイドメニュー上部のアプリストア検索欄に「イベント」と入力し、検索します。
「イベント・フェアカレンダー」が表示されますので、「このアプリを追加」をクリックします。

ステップ2

アプリを開いて、右上のギアアイコンをクリックして、アプリの設定画面に移行します。

ステップ3

下記テーブルを参考にして、フォームにフィールドを追加・変更します。

フィールドの種類 フィールド名 フィールドコード
日付 開催日 event_date
文字列(1行) イベント名 event_name
日時 開催日時 start_datetime
日時 終了日時 end_datetime
文字列(複数行) 開催場所 event_location
文字列(複数行) イベント詳細 event_description
スペース publish_button_space
文字列(1行) GoogleイベントID event_id

フィールドの設定、変更後、「フォームを保存」し、最後に「アプリを更新」します。

これで、kintoneアプリの設定は終了です。

3. JavaScriptによるプログラムの作成

下記サンプルコードを参考にプログラムを作成します。

サンプルコード

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

  // APIキー
  const api_key = 'Your Google API key';
  // クライアントID
  const client_id = 'Your Google Client ID';
  // カレンダーID
  const calendar_id = 'Your Google Calendar ID';
  // 認証用URL(読み取り/更新)
  const scope = 'https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/calendar.events';
  // Discovery Docs
  const discovery_docs = ['https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest'];

  // APIクライアントライブラリの初期化とサインイン
  function initClient() {
    gapi.client.init({
      apiKey: api_key,
      discoveryDocs: discovery_docs,
      clientId: client_id,
      scope: scope
    }, (error) => {
      alert('Googleへの認証に失敗しました。: ' + error);
    });
  }

  // APIクライアントとOAuth2ライブラリのロード
  gapi.load('client:auth2', initClient);

  // レコード詳細画面の表示後イベント
  kintone.events.on('app.record.detail.show', (event) => {
    // 増殖バグ回避
    if (document.getElementById('publish_button') !== null) {
      return event;
    }
    // 画面下部にボタンを設置
    const publishButton = document.createElement('button');
    publishButton.id = 'publish_button';
    publishButton.innerHTML = '公開する';
    publishButton.className = 'button-simple-cybozu geo-search-btn';
    publishButton.style = 'margin-top: 30px; margin-left: 10px;';
    publishButton.addEventListener('click', () => {
      publishEvent();
    });
    kintone.app.record.getSpaceElement('publish_button_space').appendChild(publishButton);
    return event;
  });

  kintone.events.on(['app.record.create.show', 'app.record.edit.show'], (event) => {
    // フィールドを編集不可へ
    event.record.event_id.disabled = true;
    return event;
  });

  async function publishEvent() {
    // レコードのデータの取得
    const record = kintone.app.record.get().record;
    if (record) {
      // Google認証済みのチェック
      if (!gapi.auth2.getAuthInstance().isSignedIn.get()) {
        // Google認証の呼び出し
        await gapi.auth2.getAuthInstance().signIn();
      }
      // APIリクエスト
      // リクエストパラメータの設定
      const params = {
        // イベントのタイトル
        summary: record.event_name.value,
        start: {
          // 開始日・時刻
          dateTime: record.start_datetime.value,
          timeZone: 'Asia/Tokyo'
        },
        end: {
          // 終了日・時刻
          dateTime: record.end_datetime.value,
          timeZone: 'Asia/Tokyo'
        },
        // 場所の指定
        location: record.event_location.value,
        // イベントの説明
        description: record.event_description.value
      };
      let request;
      // リクエストメソッドとパラメータの設定
      if (record.event_id.value) { // 公開済みイベントを更新
        request = gapi.client.calendar.events.update(
          {
            calendarId: calendar_id,
            eventId: record.event_id.value,
            resource: params
          });
      } else { // 未公開のイベントを追加
        request = gapi.client.calendar.events.insert(
          {
            calendarId: calendar_id,
            resource: params
          });
      }
      // Googleカレンダーへのイベント登録の実行
      request.execute((resp) => {
        if (resp.error) {
          alert('イベントの登録に失敗しました。' + resp.error.message);
        } else {
          const body = {
            app: kintone.app.getId(),
            id: record.$id.value,
            record: {
              event_id: {
                value: resp.result.id
              }
            }
          };
          return kintone.api(kintone.api.url('/k/v1/record', true), 'PUT', body).then((success) => {
            alert('カレンダーにイベントを登録しました。');
            location.reload();
          }).catch((error) => {
            alert('GoogleイベントIDの登録に失敗しました。' + error);
          });
        }
        return true;
      }, (error) => {
        alert('GoogleイベントIDの登録に失敗しました。' + error);
      });
    }
  }
})();

コードのアップロード

作成したコードに適当な名前をつけ、保存します。(例:google-calendar.js)
保存したコードを「アプリの設定」から、「JavaScript/CSSでカスタマイズ」を選択し、アップロードします。

また、Google APIのJavaScriptクライアントを以下のURLを指定して参照します。
https://apis.google.com/js/api.js

設定を「保存」して、「アプリを更新」します。

4. 動作の確認

上記で作成したイベント・フェアカレンダーのアプリを開き、新規イベントを追加します。

イベント情報を入力して、「保存」します。

保存後、「公開する」ボタンをクリックするとGoogleアカウントへの認証画面が表示されるので、メールアドレスとパスワードを入力してGoogleアカウントへログインします。

認証に成功すると登録したイベントがGoogleカレンダーに公開され、GoogleイベントIDが設定されます。

Googleカレンダーを確認するとイベント情報が公開されています。

公開済みのイベントをGoogleカレンダーに同期するには、イベント・フェアカレンダーでイベント情報を更新し、公開ボタンを再びクリックします。
なお、このコードでは削除機能を実装していません。

プログラムの解説

Google API認証情報の設定

Googleカレンダーの作成・設定 で取得した値を変数にセットします。

  • api_key:Google APIキー
  • client_id:クライアントID
  • calendar_id:カレンダーID
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// APIキー
const api_key = 'Your Google API key';
// クライアントID
const client_id = 'Your Google Client ID';
// カレンダーID
const calendar_id = 'Your Google Calendar ID';
// 認証用URL(読み取り/更新)
const scope = 'https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/calendar.events';
// Discovery Docs
const discovery_docs = ['https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest'];

スコープとディスカバリードックの情報の詳細は Google Calendar APIのガイド (External link) を参照してください。

Google APIクライアントとOAuth2.0ライブラリ

Google APIのJavaScriptクライアントとOAuth2.0モジュールのライブラリーをロードし、ロード完了時に呼び出すコールバック関数を設定しています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// APIクライアントライブラリの初期化とサインイン
function initClient() {
  gapi.client.init({
    apiKey: api_key,
    discoveryDocs: discovery_docs,
    clientId: client_id,
    scope: scope
  }, (error) => {
    alert('Googleへの認証に失敗しました。: ' + error);
  });
}

// APIクライアントとOAuth2ライブラリのロード
gapi.load('client:auth2', initClient);

JavaScriptクライアントとOAuth 2.0の認証情報の詳細に関しましては、 OAuth 2.0 for Client-side web applications (External link) を参照してください。

レコード詳細画面の表示後イベント

レコード詳細画面の表示後イベントは以下の関数内に記述します。

1
kintone.events.on('app.record.detail.show', (event) => {});

Googleカレンダーにイベントを公開するためのボタンを画面下部スペースに設置します。
イベントリスナーには、ボタンのクリック時に呼び出される関数を設定しています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// 画面下部にボタンを設置
const publishButton = document.createElement('button');
publishButton.id = 'publish_button';
publishButton.innerHTML = '公開する';
publishButton.className = 'button-simple-cybozu geo-search-btn';
publishButton.style = 'margin-top: 30px; margin-left: 10px;';
publishButton.addEventListener('click', () => {
  publishEvent();
});
kintone.app.record.getSpaceElement('publish_button_space').appendChild(publishButton);

レコード追加時、編集時の表示後イベント

GoogleカレンダーのイベントIDは自動設定されるので、レコード追加時および編集時には編集できないように設定しています。

1
2
3
4
5
kintone.events.on(['app.record.create.show', 'app.record.edit.show'], (event) => {
  // フィールドを編集不可へ
  event.record.event_id.disabled = true;
  return event;
});

Googleカレンダーへのイベント公開

まずは、イベント・フェアカレンダーで設定したレコードのデータを取得します。

1
const record = kintone.app.record.get().record;

レコードのデータ取得後、Googleアカウントへ認証済みかチェックし、認証済みでない場合は、Google認証画面を呼び出します。
Google APIへの認証は、非同期となるため、非同期関数として宣言し、認証処理を待ちます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
async function publishEvent() {
  // レコードのデータの取得
  const record = kintone.app.record.get().record;
  if (record) {
    // Google認証済みのチェック
    if (!gapi.auth2.getAuthInstance().isSignedIn.get()) {
      // Google認証の呼び出し
      await gapi.auth2.getAuthInstance().signIn();
    }
  // ...

次にGoogleカレンダーへ送るイベントデータのパラメーターをJSON形式で設定します。

イベントデータのパラメーターの設定は、 Google Calendar API ReferenceのEventの項目 (External link) を参照してください。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// リクエストパラメータの設定
const params = {
  // イベントのタイトル
  summary: record.event_name.value,
  start: {
    // 開始日・時刻
    dateTime: record.start_datetime.value,
    timeZone: 'Asia/Tokyo'
  },
  end: {
    // 終了日・時刻
    dateTime: record.end_datetime.value,
    timeZone: 'Asia/Tokyo'
  },
  // 場所の指定
  location: record.event_location.value,
  // イベントの説明
  description: record.event_description.value
};

イベント・フェアカレンダーのデータに、Google Event IDが設定済みかをチェックします。
設定済みならGoogle Event IDをもとにデータを更新し、未設定ならイベントを追加します。

Googleカレンダーの操作に関するドキュメントは、次を参照してください。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
let request;
// リクエストメソッドとパラメータの設定
if (record.event_id.value) { // 公開済みイベントを更新
  request = gapi.client.calendar.events.update(
    {
      calendarId: calendar_id,
      eventId: record.event_id.value,
      resource: params
    });
} else { // 未公開のイベントを追加
  request = gapi.client.calendar.events.insert(
    {
      calendarId: calendar_id,
      resource: params
    });
}
 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
// Googleカレンダーへのイベント登録の実行
request.execute((resp) => {
  if (resp.error) {
    alert('イベントの登録に失敗しました。' + resp.error.message);
  } else {
    const body = {
      app: kintone.app.getId(),
      id: record.$id.value,
      record: {
        event_id: {
          value: resp.result.id
        }
      }
    };
    return kintone.api(kintone.api.url('/k/v1/record', true), 'PUT', body).then((success) => {
      alert('カレンダーにイベントを登録しました。');
      location.reload();
    }).catch((error) => {
      alert('GoogleイベントIDの登録に失敗しました。' + error);
    });
  }
  return true;
}, (error) => {
  alert('GoogleイベントIDの登録に失敗しました。' + error);
});

上記で設定したリクエストを実行します。Googleカレンダーへの登録実行後、生成されたGoogleカレンダー側のイベントIDを取得し、kintone APIを呼び出し、event_idフィールドを更新しています。

まとめ

今回は、kintoneのイベント・フェアカレンダーを使って管理しているイベントの情報を、社内で共有できるようにGoogleカレンダーへ連携してみました。
他のGoogle Workspaceのサービスもkintoneと連携して、kintoneで管理しているさまざまな業務データを社内共有できます。

参照サイト

information

このTipsは、2020年12月版kintoneで動作を確認しています。