0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

rex0220 アプリマイスター・レイ スペース内アプリ作成

Posted at

google カレンダーの画面から、kintone のスペース内アプリを作成してみます。

概要

試作アプリをスペース内に作成することが多いと思います。
Gem アプリマイスター・レイで、google カレンダーの画面からスペース内アプリを作成してみます。

kintone 単独では、実現できない通知の繰り返し設定やラベルカラーなどは、省略されています。
試作アプリのたたき台としては、十分だと思います。

2025-12-07_20h35_34.png

  • カレンダー形式と普通の一覧が追加されている
    • 予定表ということで、カレンダー形式が考慮されている

2025-12-07_20h43_22.png

アプリ作成プロンプトと回答

スペース内アプリ作成を指示することで、対応したアプリ作成コードを作成してくれます。

google カレンダーと同様のアプリを作成して
スペース画面で実行することで、スペース内アプリで作成して

こんにちは!rex0220 アプリマイスター・レイです!🦊
お任せください!Googleカレンダーのように、スケジュールを視覚的に管理できるアプリを、今開いているスペース内に作成しますね。

[cite_start]スペース内にアプリを作成する場合、**「スペースID」と、そのスペースに紐付く「スレッドID」**の指定が必須になります [cite: 1]。
現在開いている画面のURLからスペースIDを自動で取得し、必要なスレッド情報も調べてからアプリを作成するようにコードを組みました。

以下のコードを、アプリを作成したいスペースのトップ画面(URLが .../space/123 のような画面)で、ブラウザのコンソールに貼り付けて実行してください。

/**
 * 🦊 kintone App Meister Ray's Work
 * Project: スケジュール管理(Googleカレンダー風)
 * Description: スペース内作成・カレンダービュー標準搭載
 */
(async () => {
  try {
    console.log('🦊 レイ: Googleカレンダー風アプリの構築を開始します!');

    // -------------------------------------------------------
    // 0. スペース情報の取得 (URLから判定)
    // -------------------------------------------------------
    const url = window.location.href;
    const spaceIdMatch = url.match(/\/space\/(\d+)/) || url.match(/\/guest\/(\d+)/);
    
    if (!spaceIdMatch) {
      console.error('🦊 レイ: スペースの画面(例: .../space/123)を開いてから実行してください!');
      return;
    }

    const spaceId = spaceIdMatch[1];
    const isGuest = url.includes('/guest/');
    console.log(`Step 0: スペースID(${spaceId}) を検出しました。スレッド情報を取得します...`);

    // スペース情報の取得(デフォルトスレッドIDが必要なため)
    // ゲストスペースの場合はAPIのURLが変わるため注意
    const spaceApiUrl = isGuest 
      ? kintone.api.url('/k/guest/' + spaceId + '/v1/space', true) // ゲスト用
      : kintone.api.url('/k/v1/space', true); // 通常用

    // ゲストスペースの場合、GETリクエストのURL自体にゲストスペースIDが含まれるが、
    // 引数としてのidは不要な場合と必要な場合があるため、汎用的に作成
    const spaceInfo = await kintone.api(spaceApiUrl, 'GET', { id: spaceId });
    const threadId = spaceInfo.defaultThread;

    console.log(`Step 0: ターゲットスレッドID(${threadId}) を特定しました。`);

    // -------------------------------------------------------
    // 1. 新規アプリの作成(スペース指定)
    // -------------------------------------------------------
    const createAppBody = {
      name: 'スケジュール管理',
      space: spaceId,
      thread: threadId
    };
    
    const createResp = await kintone.api(kintone.api.url('/k/v1/preview/app', true), 'POST', createAppBody);
    const appId = createResp.app;

    console.log(`Step 1: アプリの枠を作成しました... App ID: ${appId}`);

    // -------------------------------------------------------
    // 2. フィールドの追加
    // -------------------------------------------------------
    const fieldsBody = {
      app: appId,
      properties: {
        // --- 予定の基本 ---
        '件名': {
          type: 'SINGLE_LINE_TEXT',
          label: '件名',
          code: '件名',
          required: true
        },
        '開始日時': {
          type: 'DATETIME',
          label: '開始日時',
          code: '開始日時',
          required: true,
          defaultNowValue: true
        },
        '終了日時': {
          type: 'DATETIME',
          label: '終了日時',
          code: '終了日時',
          required: true,
          defaultNowValue: true
        },
        '終日': {
          type: 'CHECK_BOX',
          label: '終日',
          code: '終日',
          options: {
            '終日': { label: '終日', index: 0 }
          }
        },
        
        // --- 詳細情報 ---
        '場所': {
          type: 'SINGLE_LINE_TEXT',
          label: '場所',
          code: '場所'
        },
        '参加者': {
          type: 'USER_SELECT',
          label: '参加者',
          code: '参加者'
        },
        '詳細': {
          type: 'RICH_TEXT', // Googleカレンダーのようにリッチテキストで
          label: '詳細',
          code: '詳細'
        },
        
        // --- 色分け用 ---
        'カテゴリ': {
          type: 'RADIO_BUTTON',
          label: 'カテゴリ',
          code: 'カテゴリ',
          options: {
            '会議': { label: '会議', index: 0 },
            '外出': { label: '外出', index: 1 },
            'タスク': { label: 'タスク', index: 2 },
            'その他': { label: 'その他', index: 3 }
          },
          defaultValue: '会議'
        }
      }
    };

    await kintone.api(kintone.api.url('/k/v1/preview/app/form/fields', true), 'POST', fieldsBody);
    console.log('Step 2: フィールド設定完了。');

    // -------------------------------------------------------
    // 3. レイアウト設定
    // -------------------------------------------------------
    const layoutBody = {
      app: appId,
      layout: [
        {
          type: 'ROW',
          fields: [
            { type: 'SINGLE_LINE_TEXT', code: '件名' }
          ]
        },
        {
          type: 'ROW',
          fields: [
            { type: 'DATETIME', code: '開始日時' },
            { type: 'LABEL', label: '' },
            { type: 'DATETIME', code: '終了日時' },
            { type: 'CHECK_BOX', code: '終日' }
          ]
        },
        {
          type: 'ROW',
          fields: [
            { type: 'SINGLE_LINE_TEXT', code: '場所' },
            { type: 'RADIO_BUTTON', code: 'カテゴリ' }
          ]
        },
        {
          type: 'ROW',
          fields: [
            { type: 'USER_SELECT', code: '参加者' }
          ]
        },
        {
          type: 'ROW',
          fields: [
            { type: 'RICH_TEXT', code: '詳細', size: { innerHeight: 200 } }
          ]
        }
      ]
    };

    await kintone.api(kintone.api.url('/k/v1/preview/app/form/layout', true), 'PUT', layoutBody);
    console.log('Step 3: レイアウト設定完了');

    // -------------------------------------------------------
    // 4. 一覧設定(カレンダー形式をデフォルトに)
    // -------------------------------------------------------
    const viewsBody = {
      app: appId,
      views: {
        'カレンダー': {
          type: 'CALENDAR',
          name: 'カレンダー',
          index: '0', // 最優先
          date: '開始日時', // カレンダーの日付基準
          title: '件名',    // 表示タイトル
          filterCond: '',
          sort: '開始日時 asc'
        },
        '一覧(全て)': {
          type: 'LIST',
          name: '一覧(全て)',
          index: '1',
          fields: ['件名', '開始日時', '終了日時', '場所', 'カテゴリ', '参加者'],
          filterCond: '',
          sort: '開始日時 desc'
        }
      }
    };

    await kintone.api(kintone.api.url('/k/v1/preview/app/views', true), 'PUT', viewsBody);
    console.log('Step 4: カレンダー一覧の設定完了');

    // -------------------------------------------------------
    // 5. アプリの公開 (Deploy)
    // -------------------------------------------------------
    console.log('Step 5: アプリの公開処理を実行中...');
    await kintone.api(kintone.api.url('/k/v1/preview/app/deploy', true), 'POST', { apps: [{ app: appId }] });

    console.log('-------------------------------------------------------');
    console.log(`🎉 レイ: 作成完了です!スペース内にアプリが追加されました。`);
    console.log(`新規作成されたアプリID: ${appId}`);
    console.log('画面をリロードして、スペースのアプリ一覧を確認してみてください!');
    console.log('-------------------------------------------------------');

  } catch (error) {
    console.error('🦊 レイ: エラーが発生しました。', error);
    if (error.error) console.error(JSON.stringify(error.error, null, 2));
  }
})();

ポイント

  • カレンダー形式をデフォルトに: 一覧設定で type: 'CALENDAR' を指定し、インデックスを0(先頭)にすることで、アプリを開いた瞬間にカレンダーが表示されるようにしています。
  • リッチテキストの採用: Googleカレンダーの「説明」欄のように、文字の装飾やリンク貼り付けがしやすいよう RICH_TEXT を採用しました。
  • [cite_start]スペース対応: 通常のアプリ作成APIとは異なり、URLからスペースIDとスレッドIDを取得してパラメータに含めることで、現在のスペース内にアプリを作成する仕様にしています [cite: 1]。

このコードで作成後、ぜひ予定を入れてみてください。
他に追加したい項目(例:会議室の予約ルックアップなど)はありますか?

アプリ作成実行

スペース画面の console で、アプリ作成コードを実行します。
エラーが出ている場合は、エラー内容をプロンプトに入れてあげると、修正してくれます。

2025-12-07_20h34_17.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?