# 画面設計書 68-Slack連携画面

## 概要

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

### 本画面の処理概要

本画面は、SlackとChatwootを連携するための設定画面です。Slack連携により、Chatwootの会話をSlackチャンネルに通知したり、Slackから直接会話に返信したりすることができます。

**業務上の目的・背景**：多くのチームがコミュニケーションツールとしてSlackを使用しています。Chatwootとの連携により、エージェントはSlack上で顧客からの問い合わせを確認し、迅速に対応できるようになります。特にリモートワーク環境において、Slack通知による即時対応は顧客満足度向上に貢献します。

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

**主要な操作・処理内容**：
1. Slack連携の接続（OAuth認証）
2. 通知先チャンネルの選択
3. Slack連携の切断

**画面遷移**：
- 遷移元：連携アプリ一覧画面
- 遷移先：Slack OAuth認証画面（外部）、連携アプリ一覧画面（切断後）

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

## 関連機能

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

## 画面種別

設定

## URL/ルーティング

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

## 入出力項目

### クエリパラメータ

| パラメータ名 | 型 | 説明 |
|-------------|-----|------|
| code | string | Slack OAuth認証後のコード |

## 表示項目

### 連携情報カード

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

### アクションボタン

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

### ヘルプテキスト

| 項目名 | 表示条件 | 説明 |
|--------|---------|------|
| SelectChannelWarning | フックあり＆未有効時 | チャンネル選択の警告表示 |
| SlackIntegrationHelpText | フックあり時 | 選択中のチャンネル名を表示 |

## イベント仕様

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

「Connect」ボタンをクリックすると、Slackの認証画面にリダイレクトされます。

**処理フロー**：
1. `integrationAction` のURLにリダイレクト
2. Slack側で認証完了後、`code` パラメータ付きでコールバック
3. 本画面に戻り、`intializeSlackIntegration()` が呼び出される
4. `store.dispatch('integrations/connectSlack', code)` でAPIを呼び出し
5. 成功後、URLから `code` パラメータを削除

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

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

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

### 3-画面初期化

画面表示時に、Slack連携情報を取得し、OAuthコードがあれば接続処理を行います。

**処理フロー**：
1. `onMounted` で `intializeSlackIntegration()` が呼び出される
2. `store.dispatch('integrations/get', 'slack')` で連携情報を取得
3. `code` プロパティが存在する場合、`store.dispatch('integrations/connectSlack', code)` を呼び出し
4. 成功後、`router.replace(route.path)` でクエリパラメータをクリア

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

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

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

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示タイミング |
|-------------|------|---------------|---------------|
| INTEGRATION_SETTINGS.DELETE.API.SUCCESS_MESSAGE | 成功 | 連携削除成功 | 切断成功時 |
| INTEGRATION_SETTINGS.WEBHOOK.DELETE.API.ERROR_MESSAGE | エラー | 連携削除失敗 | 切断失敗時 |
| INTEGRATION_SETTINGS.SLACK.DELETE_CONFIRMATION.TITLE | 確認 | 切断確認タイトル | 切断ボタン押下時 |
| INTEGRATION_SETTINGS.SLACK.DELETE_CONFIRMATION.MESSAGE | 確認 | 切断確認メッセージ | 切断ボタン押下時 |
| INTEGRATION_SETTINGS.SLACK.HELP_TEXT.SELECTED | 情報 | 選択中チャンネル | 連携有効時 |

## 例外処理

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

## 備考

- Slack OAuth認証フローを使用
- OAuth認証後のコードは1回限り有効
- 認証成功後は即座にURLからcodeパラメータを削除（再読み込み時のエラー防止）
- 連携が有効な場合、`hook.status` が `true` になる
- チャンネル名は `hook.settings.channel_name` から取得（デフォルトは `customer-conversations`）
- `isCreatingSlack` フラグで接続処理中のローディング表示を制御

---

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

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

### 推奨読解順序

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

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

**主要処理フロー**:
1. **62-71行目**: `intializeSlackIntegration()` で初期化処理
2. **22-28行目**: `areHooksAvailable`, `hook` で連携状態を取得
3. **37-43行目**: `hasConnectedAChannel`, `selectedChannelName` でチャンネル情報を取得

**読解のコツ**: `code` プロパティはルートの `props` から渡されます（URLクエリパラメータ）。OAuth認証後のコールバックで使用されます。

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

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

**主要処理フロー**:
- **35-45行目**: 削除ポップアップの制御
- **47-54行目**: `deleteIntegration()` で連携削除
- **56-60行目**: `confirmDeletion()` で確認後の処理

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

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

**主要処理フロー**:
- **51-63行目**: `connectSlack` アクションでOAuthコードを送信
- **92-104行目**: `deleteIntegration` アクションで連携削除

#### Step 4: API層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | integrations.js | `app/javascript/dashboard/api/integrations.js` | connectSlack、deleteメソッドを確認 |

**主要処理フロー**:
- **10-12行目**: `connectSlack` で `/integrations/slack` にPOST
- **24-26行目**: `delete` で `/integrations/{integrationId}` にDELETE

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

```
Slack.vue (エントリーポイント)
    │
    ├─ onMounted()
    │      └─ intializeSlackIntegration()
    │             │
    │             ├─ store.dispatch('integrations/get', 'slack')
    │             │      └─ IntegrationsAPI.get()
    │             │
    │             └─ [code 存在時]
    │                    └─ store.dispatch('integrations/connectSlack', code)
    │                           └─ IntegrationsAPI.connectSlack()
    │                                  └─ POST /api/v1/accounts/:id/integrations/slack
    │
    └─ Integration.vue
           │
           ├─ [接続時] Connect ボタン
           │      └─ Slack OAuth画面へリダイレクト
           │
           └─ [切断時] confirmDeletion()
                  └─ store.dispatch('integrations/deleteIntegration')
                         └─ IntegrationsAPI.delete()
                                └─ DELETE /api/v1/accounts/:id/integrations/slack
```

### データフロー図

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

Slack OAuth ─────────▶ Callback URL ────────────▶ Slack.vue
(認証完了)                (code付き)
                              │
                              ▼
                    store.dispatch('connectSlack')
                              │
                              ▼
                    IntegrationsAPI.connectSlack()
                              │
                              ▼
                    Rails Controller
               (POST /integrations/slack)
                              │
                              ▼
                    integrations_hooks
                         (INSERT)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Slack.vue | `app/javascript/dashboard/routes/dashboard/settings/integrations/Slack.vue` | ソース | メイン画面コンポーネント |
| Integration.vue | `app/javascript/dashboard/routes/dashboard/settings/integrations/Integration.vue` | ソース | 連携カード共通コンポーネント |
| SelectChannelWarning.vue | `app/javascript/dashboard/routes/dashboard/settings/integrations/Slack/SelectChannelWarning.vue` | ソース | チャンネル選択警告 |
| SlackIntegrationHelpText.vue | `app/javascript/dashboard/routes/dashboard/settings/integrations/Slack/SlackIntegrationHelpText.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` | ソース | ルート定義 |
