# 画面設計書 69-Linear連携画面

## 概要

本ドキュメントは、ChatwootのLinear連携画面の設計仕様を記述したものです。

### 本画面の処理概要

本画面は、Linear（プロジェクト管理ツール）とChatwootを連携するための設定画面です。Linear連携により、Chatwootの会話からLinearのイシューを作成したり、関連するイシューを追跡したりすることができます。

**業務上の目的・背景**：カスタマーサポートチームと開発チームの連携を効率化するため、顧客からの問い合わせを直接Linearのイシューとして登録できる機能が求められています。これにより、バグ報告や機能リクエストを開発チームに迅速に伝達し、対応状況を追跡できます。

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

**主要な操作・処理内容**：
1. Linear連携の接続
2. Linear連携の切断

**画面遷移**：
- 遷移元：連携アプリ一覧画面
- 遷移先：連携アプリ一覧画面（切断後）

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

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 146 | Linear統合 | 主機能 | Linear連携の設定 |

## 画面種別

設定

## URL/ルーティング

| 項目 | 値 |
|------|-----|
| パス | `/app/accounts/:accountId/settings/integrations/linear` |
| ルート名 | `settings_integrations_linear` |
| コンポーネント | `app/javascript/dashboard/routes/dashboard/settings/integrations/Linear.vue` |
| 権限 | `administrator` |

## 入出力項目

### クエリパラメータ

| パラメータ名 | 型 | 説明 |
|-------------|-----|------|
| code | string | Linear OAuth認証後のコード（将来的な使用のため） |

## 表示項目

### 連携情報カード

| 項目名 | 項目ID | 型 | 説明 |
|--------|--------|-----|------|
| ロゴ | integrationLogo | string | Linearのロゴ画像 |
| 名前 | integrationName | string | 「Linear」 |
| 説明 | integrationDescription | string | Linear連携の説明文 |
| 有効状態 | integrationEnabled | boolean | 連携が有効かどうか |

### アクションボタン

| ボタン名 | 表示条件 | 説明 |
|---------|---------|------|
| Connect | 未接続時 | Linear連携を開始 |
| Disconnect | 接続時 | Linear連携を切断 |

## イベント仕様

### 1-Linear接続ボタン押下

「Connect」ボタンをクリックすると、Linear連携が開始されます。

**処理フロー**：
1. `integrationAction` のURLにリダイレクト（または認証処理を実行）
2. Linear APIとの連携が確立される

### 2-Linear切断ボタン押下

「Disconnect」ボタンをクリックすると、確認ダイアログが表示されます。

**処理フロー**：
1. `Integration.vue` の `openDeletePopup()` が呼び出される
2. 確認ダイアログが表示される
3. 確認後、`confirmDeletion()` が呼び出される
4. `store.dispatch('integrations/deleteIntegration', 'linear')` でAPIを呼び出し
5. 成功時：成功メッセージを表示し、連携アプリ一覧画面に遷移

### 3-画面初期化

画面表示時に、Linear連携情報を取得します。

**処理フロー**：
1. `onMounted` で `initializeLinearIntegration()` が呼び出される
2. `store.dispatch('integrations/get', 'linear')` で連携情報を取得
3. `integrationLoaded` が `true` に設定される

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 連携情報取得 | integrations_hooks | SELECT | Linear連携情報を取得 |
| Linear接続 | integrations_hooks | INSERT/UPDATE | Linear連携を登録/更新 |
| Linear切断 | integrations_hooks | DELETE | Linear連携を削除 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示タイミング |
|-------------|------|---------------|---------------|
| INTEGRATION_SETTINGS.DELETE.API.SUCCESS_MESSAGE | 成功 | 連携削除成功 | 切断成功時 |
| INTEGRATION_SETTINGS.WEBHOOK.DELETE.API.ERROR_MESSAGE | エラー | 連携削除失敗 | 切断失敗時 |
| INTEGRATION_SETTINGS.LINEAR.DELETE.TITLE | 確認 | 切断確認タイトル | 切断ボタン押下時 |
| INTEGRATION_SETTINGS.LINEAR.DELETE.MESSAGE | 確認 | 切断確認メッセージ | 切断ボタン押下時 |

## 例外処理

| 例外状況 | 処理内容 |
|---------|---------|
| 連携接続失敗 | エラーメッセージを表示 |
| 連携削除失敗 | エラーメッセージを表示 |
| 連携情報取得失敗 | ローディング状態を解除 |

## 備考

- Linear連携はSlackと異なり、フィーチャーフラグが不要
- `useFunctionGetter` を使用して integration を取得
- `isCreatingLinear` フラグで接続処理中のローディング表示を制御
- 連携が有効な場合、`integrationAction` は `'disconnect'` になる
- 連携の詳細設定は `IntegrationHooks.vue` で行う（会話サイドバーでの操作）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Linear.vue | `app/javascript/dashboard/routes/dashboard/settings/integrations/Linear.vue` | 画面の構成、初期化処理を確認 |

**主要処理フロー**:
1. **27-30行目**: `initializeLinearIntegration()` で初期化処理
2. **16-18行目**: `useFunctionGetter` でLinear連携情報を取得
3. **20-25行目**: `integrationAction` で接続/切断状態を判定

**読解のコツ**: Slack.vue と比較して、シンプルな構成になっています。OAuth認証フローがなく、連携情報の取得と表示が主な処理です。

#### Step 2: 共通連携コンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Integration.vue | `app/javascript/dashboard/routes/dashboard/settings/integrations/Integration.vue` | 連携カードの共通コンポーネントを確認 |

（Slack連携画面と同様）

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | integrations.js | `app/javascript/dashboard/store/modules/integrations.js` | get、deleteIntegration アクションを確認 |

**主要処理フロー**:
- **40-48行目**: `get` アクションで連携情報取得
- **92-104行目**: `deleteIntegration` アクションで連携削除

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

```
Linear.vue (エントリーポイント)
    │
    ├─ onMounted()
    │      └─ initializeLinearIntegration()
    │             └─ store.dispatch('integrations/get', 'linear')
    │                    └─ IntegrationsAPI.get()
    │                           └─ GET /api/v1/accounts/:id/integrations/apps
    │
    └─ Integration.vue
           │
           ├─ [接続時] Connect ボタン
           │      └─ integrationAction (URL)
           │
           └─ [切断時] confirmDeletion()
                  └─ store.dispatch('integrations/deleteIntegration')
                         └─ IntegrationsAPI.delete()
                                └─ DELETE /api/v1/accounts/:id/integrations/linear
```

### データフロー図

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

なし ────────────────▶ Linear.vue ────────────────▶ カード表示
                           │
                           ▼
                    store.dispatch('get')
                           │
                           ▼
                    IntegrationsAPI.get()
                           │
                           ▼
                 integrations_hooks
                      (SELECT)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Linear.vue | `app/javascript/dashboard/routes/dashboard/settings/integrations/Linear.vue` | ソース | メイン画面コンポーネント |
| Integration.vue | `app/javascript/dashboard/routes/dashboard/settings/integrations/Integration.vue` | ソース | 連携カード共通コンポーネント |
| integrations.js | `app/javascript/dashboard/store/modules/integrations.js` | ソース | Vuexストアモジュール |
| integrations.js | `app/javascript/dashboard/api/integrations.js` | ソース | APIクライアント |
| integrations.routes.js | `app/javascript/dashboard/routes/dashboard/settings/integrations/integrations.routes.js` | ソース | ルート定義 |
