# 画面設計書 66-ダッシュボードアプリ設定

## 概要

本ドキュメントは、Chatwootのダッシュボードアプリ設定画面の設計仕様を記述したものです。

### 本画面の処理概要

本画面は、ダッシュボードに埋め込むカスタムアプリケーション（iframe）を管理するための画面です。外部のWebアプリケーションをChatwootのダッシュボード内に表示することで、エージェントが複数のツールを切り替えることなく作業を行えるようになります。

**業務上の目的・背景**：カスタマーサポート業務では、CRMシステム、注文管理システム、顧客情報データベースなど、複数の外部ツールを参照しながら対応することがあります。ダッシュボードアプリ機能を使用することで、これらの外部ツールをChatwoot内にiframeとして埋め込み、エージェントのワークフローを効率化します。

**画面へのアクセス方法**：連携アプリ一覧画面から「ダッシュボードアプリ」を選択、または直接 `/app/accounts/:accountId/settings/integrations/dashboard_apps` にアクセスします。

**主要な操作・処理内容**：
1. ダッシュボードアプリの一覧表示（名前、エンドポイントURL）
2. 新規ダッシュボードアプリの作成
3. 既存アプリの編集
4. アプリの削除

**画面遷移**：
- 遷移元：連携アプリ一覧画面
- 遷移先：なし（モーダル内で操作完結）

**権限による表示制御**：管理者（administrator）権限を持つユーザーのみがアクセス可能です。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 143 | Hooks（Integrations） | 主機能 | ダッシュボードアプリの設定 |

## 画面種別

一覧・登録・編集

## URL/ルーティング

| 項目 | 値 |
|------|-----|
| パス | `/app/accounts/:accountId/settings/integrations/dashboard_apps` |
| ルート名 | `settings_integrations_dashboard_apps` |
| コンポーネント | `app/javascript/dashboard/routes/dashboard/settings/integrations/DashboardApps/Index.vue` |
| 権限 | `administrator` |
| フィーチャーフラグ | `INTEGRATIONS` |

## 入出力項目

### 入力項目（作成/編集モーダル）

| 項目名 | 項目ID | 型 | 必須 | 説明 |
|--------|--------|-----|------|------|
| アプリ名 | title | string | 必須 | ダッシュボードアプリの名称 |
| エンドポイントURL | content.url | string | 必須 | 埋め込むiframeのURL（http/https） |
| タイプ | content.type | string | 必須 | 常に `frame` |

## 表示項目

### 一覧テーブル

| 項目名 | 項目ID | 型 | 説明 |
|--------|--------|-----|------|
| アプリ名 | title | string | ダッシュボードアプリの名称 |
| エンドポイント | content.url | string | 埋め込みURL |

### アクションボタン

| ボタン名 | アイコン | 説明 |
|---------|---------|------|
| 編集 | - | アプリを編集 |
| 削除 | - | アプリを削除 |

## イベント仕様

### 1-アプリ追加ボタン押下

ヘッダー部の「+ Add a new dashboard app」ボタンをクリックすると、作成用のモーダルダイアログが表示されます。

**処理フロー**：
1. `openCreatePopup()` が呼び出される
2. `mode` が `'CREATE'` に設定される
3. `selectedApp` がクリアされる
4. `showDashboardAppPopup` が `true` に設定される
5. `DashboardAppModal` コンポーネントが表示される

### 2-アプリ編集ボタン押下

一覧の各行にある編集ボタンをクリックすると、編集用のモーダルダイアログが表示されます。

**処理フロー**：
1. `editApp(app)` が呼び出される
2. `mode` が `'UPDATE'` に設定される
3. `selectedApp` に選択したアプリが格納される
4. `showDashboardAppPopup` が `true` に設定される
5. `DashboardAppModal` コンポーネントが表示される

### 3-アプリ削除ボタン押下

一覧の各行にある削除ボタンをクリックすると、確認ダイアログが表示されます。

**処理フロー**：
1. `openDeletePopup(app)` が呼び出される
2. `selectedApp` に選択したアプリが格納される
3. `showDeleteConfirmationPopup` が `true` に設定される
4. 確認後、`confirmDeletion()` が呼び出される
5. `deleteApp(id)` が呼び出される
6. `this.$store.dispatch('dashboardApps/delete', id)` でAPIを呼び出し
7. 成功時：成功メッセージを表示
8. 失敗時：エラーメッセージを表示

## データベース更新仕様

### 操作別データベース影響一覧

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| アプリ一覧取得 | dashboard_apps | SELECT | アカウントに紐づく全アプリを取得 |
| アプリ作成 | dashboard_apps | INSERT | 新しいダッシュボードアプリを作成 |
| アプリ更新 | dashboard_apps | UPDATE | 既存アプリを更新 |
| アプリ削除 | dashboard_apps | DELETE | 指定されたアプリを削除 |

### テーブル別更新項目詳細

#### dashboard_apps

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | id | シーケンス自動採番 | 主キー |
| INSERT | title | フォーム入力値 | アプリ名 |
| INSERT | content | JSON形式 [{url, type}] | 埋め込み情報 |
| INSERT | account_id | Current.account.id | アカウントID |
| INSERT | user_id | Current.user.id | 作成者ID |
| INSERT | created_at | 現在日時 | 作成日時 |
| INSERT | updated_at | 現在日時 | 更新日時 |
| UPDATE | title, content | フォーム入力値 | 編集時 |
| UPDATE | updated_at | 現在日時 | 更新日時 |
| DELETE | - | WHERE id = :id | 指定IDのレコードを削除 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示タイミング |
|-------------|------|---------------|---------------|
| INTEGRATION_SETTINGS.DASHBOARD_APPS.DELETE.API_SUCCESS | 成功 | アプリ削除成功 | 削除成功時 |
| INTEGRATION_SETTINGS.DASHBOARD_APPS.DELETE.API_ERROR | エラー | アプリ削除失敗 | 削除失敗時 |
| INTEGRATION_SETTINGS.DASHBOARD_APPS.DELETE.TITLE | 確認 | 削除確認タイトル | 削除ボタン押下時 |
| INTEGRATION_SETTINGS.DASHBOARD_APPS.DELETE.MESSAGE | 確認 | 削除確認メッセージ | 削除ボタン押下時 |
| INTEGRATION_SETTINGS.DASHBOARD_APPS.LIST.404 | 情報 | アプリがありません | アプリが0件の場合 |
| INTEGRATION_SETTINGS.DASHBOARD_APPS.LIST.LOADING | 情報 | 読み込み中 | データ取得中 |

## 例外処理

| 例外状況 | 処理内容 |
|---------|---------|
| データ取得失敗 | エラーを無視し、空のリストを表示 |
| 作成/更新失敗 | エラーメッセージをアラート表示 |
| 削除失敗 | エラーメッセージをアラート表示 |
| URLバリデーションエラー | JSONSchemaによるバリデーションエラー |

## 備考

- `content` カラムはJSON配列形式で、`[{url: "https://...", type: "frame"}]` の形式
- URLは `http://` または `https://` で始まる必要がある（JSONSchemaでバリデーション）
- 作成者は `user_id` で追跡される
- Options APIを使用したコンポーネント実装

---

## コードリーディングガイド

本画面を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

ダッシュボードアプリのデータ構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | dashboard_app.rb | `app/models/dashboard_app.rb` | モデル定義、contentのJSONSchemaバリデーションを確認 |

**読解のコツ**: `content` カラムは配列形式のJSONBで、`url` と `type` を持つオブジェクトの配列です。`type` は `frame` のみ許可されています。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Index.vue | `app/javascript/dashboard/routes/dashboard/settings/integrations/DashboardApps/Index.vue` | 画面の構成、CRUD操作を確認 |

**主要処理フロー**:
1. **39-41行目**: `mounted` で `store.dispatch('dashboardApps/get')` を呼び出し
2. **51-55行目**: `openCreatePopup()` で作成モード
3. **59-64行目**: `editApp()` で編集モード
4. **65-69行目**: `confirmDeletion()` で削除処理

#### Step 3: Vuex Store層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | dashboardApps.js | `app/javascript/dashboard/store/modules/dashboardApps.js` | CRUD操作のアクションを確認 |

**主要処理フロー**:
- **23-34行目**: `get` アクションで一覧取得
- **35-45行目**: `create` アクションで作成
- **47-57行目**: `update` アクションで更新
- **58-68行目**: `delete` アクションで削除

#### Step 4: バックエンド層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | dashboard_apps_controller.rb | `app/controllers/api/v1/accounts/dashboard_apps_controller.rb` | コントローラのアクション、許可パラメータを確認 |

**主要処理フロー**:
- **9-13行目**: `create` アクションで `user_id` を付与
- **15-17行目**: `update` アクションで更新
- **34-38行目**: `permitted_payload` で許可パラメータ定義

### プログラム呼び出し階層図

```
Index.vue (エントリーポイント)
    │
    ├─ mounted()
    │      └─ store.dispatch('dashboardApps/get')
    │             └─ DashboardAppsAPI.get()
    │                    └─ GET /api/v1/accounts/:account_id/dashboard_apps
    │
    ├─ DashboardAppModal.vue (作成/編集)
    │      └─ store.dispatch('dashboardApps/create' or 'update')
    │             └─ DashboardAppsAPI.create() or update()
    │
    └─ deleteApp()
           └─ store.dispatch('dashboardApps/delete')
                  └─ DashboardAppsAPI.delete()
```

### データフロー図

```
[入力]                    [処理]                         [出力]

ユーザー操作 ────────▶ Index.vue ─────────────▶ 画面表示更新
                           │
                           ▼
                      Vuex Store
                    (dashboardApps)
                           │
                           ▼
                  DashboardAppsAPI
                           │
                           ▼
                  Rails Controller
            (dashboard_apps_controller.rb)
                           │
                           ▼
                    DashboardApp
                       (Model)
                           │
                           ▼
                    PostgreSQL
                  (dashboard_apps)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Index.vue | `app/javascript/dashboard/routes/dashboard/settings/integrations/DashboardApps/Index.vue` | ソース | メイン画面コンポーネント |
| DashboardAppModal.vue | `app/javascript/dashboard/routes/dashboard/settings/integrations/DashboardApps/DashboardAppModal.vue` | ソース | 作成/編集モーダル |
| DashboardAppsRow.vue | `app/javascript/dashboard/routes/dashboard/settings/integrations/DashboardApps/DashboardAppsRow.vue` | ソース | 一覧行コンポーネント |
| dashboardApps.js | `app/javascript/dashboard/store/modules/dashboardApps.js` | ソース | Vuexストアモジュール |
| dashboardApps.js | `app/javascript/dashboard/api/dashboardApps.js` | ソース | APIクライアント |
| dashboard_apps_controller.rb | `app/controllers/api/v1/accounts/dashboard_apps_controller.rb` | ソース | Railsコントローラ |
| dashboard_app.rb | `app/models/dashboard_app.rb` | ソース | モデル定義 |
