# 通知設計書 33-パッド作成エラー通知

## 概要

本ドキュメントは、Etherpad管理画面におけるパッド作成エラー通知の設計を記載する。この通知は、管理者が管理画面からパッドを新規作成しようとした際に、何らかの理由で作成に失敗した場合に表示されるトースト通知である。

### 本通知の処理概要

管理画面のパッド管理ページにおいて、管理者がパッド作成ダイアログからパッド名を入力して作成を実行した際、サーバー側でエラーが発生した場合（主に同名パッドが既に存在する場合）に、エラー通知を表示する処理を行う。

**業務上の目的・背景**：Etherpadの管理者がパッドを作成しようとした際、既に同じ名前のパッドが存在する場合は作成に失敗する。この失敗を明確に管理者に伝え、別のパッド名で再試行するよう促す必要がある。本通知は、作成失敗の原因を即座に伝え、管理者が適切な対応を取れるようにする。

**通知の送信タイミング**：管理者がパッド作成ダイアログでパッド名を入力し、作成ボタンを押した後、サーバー側で`createPad`イベントが処理され、エラーが発生した場合（パッドが既に存在する場合）に`results:createPad`イベント（errorプロパティ付き）がクライアントに送信される。

**通知の受信者**：管理画面にログインしている管理者ユーザー（`is_admin`が`true`のユーザー）のみが受信対象となる。

**通知内容の概要**：サーバーから返されたエラーメッセージ（例：「Pad already exists」）がトースト通知として表示される。エラーの具体的な内容が含まれるため、管理者は問題の原因を把握できる。

**期待されるアクション**：管理者はエラー通知を確認し、エラー内容に応じた対応を取る。同名パッドが存在する場合は、別のパッド名を入力して再試行するか、既存のパッドを使用する。

## 通知種別

アプリ内通知（トースト通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（Socket.IO経由のリアルタイム通知） |
| 優先度 | 高 |
| リトライ | なし |

### 送信先決定ロジック

管理画面のパッドページ（`/admin/pads`）にアクセスしている管理者ユーザーに対して通知が送信される。Socket.IO接続を通じて特定され、認証済みの管理者セッションを持つクライアントのみが対象となる。

## 通知テンプレート

### トースト通知の場合

| 項目 | 内容 |
|-----|------|
| タイトル | {エラーメッセージ}（例：Pad already exists） |
| 説明 | なし（titleのみ表示） |
| 表示スタイル | ToastRootFailure（エラースタイル） |

### 本文テンプレート

```
Pad already exists
```
（または他のエラーメッセージ）

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| title | 通知タイトル（エラーメッセージ） | サーバーレスポンス.error | Yes |
| success | 成功/失敗フラグ | false固定 | Yes |
| open | 表示状態 | true固定 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | createPadボタンクリック | フォームバリデーション通過 | パッド作成ダイアログで作成ボタンを押下 |
| Socket.IOイベント | results:createPad | error プロパティが存在 | サーバー側でパッド作成に失敗 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 管理者以外のユーザー | is_adminがfalseの場合、Socket.IO接続自体が拒否される |
| パッド名が空 | react-hook-formのバリデーションで送信が阻止される |
| パッド作成成功 | successプロパティが返され、成功通知が送信される |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[管理者がパッドページにアクセス] --> B[パッド作成ダイアログを開く]
    B --> C[パッド名を入力]
    C --> D[作成ボタンをクリック]
    D --> E[react-hook-form バリデーション]
    E -->|失敗| F[フォームエラー表示]
    E -->|成功| G[settingsSocket.emit 'createPad']
    G --> H[サーバー: createPad イベント処理]
    H --> I{パッド存在チェック}
    I -->|存在しない| J[パッド作成処理]
    I -->|存在する| K[results:createPad error送信]
    K --> L[クライアント: エラーイベント受信]
    L --> M[setToastState でエラートースト表示]
    M --> N[ダイアログは開いたまま]
    J --> O[成功通知表示]
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| pad:* | パッド存在確認 | doesPadExistsでKey-Valueストア参照 |

### テーブル別参照項目詳細

#### pad:{padName}

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| 存在確認 | 同名パッドの重複チェック | padManager.doesPadExists(padName) |

### 更新テーブル一覧

エラー時はデータベース更新は発生しない。

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| パッド重複 | 同名のパッドが既に存在 | 別のパッド名で再試行 |
| バリデーションエラー | パッド名が空 | パッド名を入力して再試行 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（自動リトライなし） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（管理画面操作時に随時送信）

## セキュリティ考慮事項

- 管理者認証が必須であり、認証されていないユーザーにはSocket.IO接続が拒否される
- エラーメッセージは「Pad already exists」など一般的な内容であり、機密情報は含まれない
- パッド名はユーザー入力であるが、エラーメッセージにはパッド名は含まれない

## 備考

- エラー通知表示後も、パッド作成ダイアログは開いたままになる（成功時と異なる動作）
- 管理者は別のパッド名を入力して再試行できる
- 現在の実装では「Pad already exists」エラーのみが発生する可能性があるが、将来的に他のエラーケースが追加される可能性がある

---

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

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

### 推奨読解順序

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

まず、通知に関連するデータ構造とサーバーレスポンスの型を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | store.ts | `admin/src/store/store.ts` | ToastState型（6-11行目）で通知状態の構造を確認 |
| 1-2 | PadPage.tsx | `admin/src/pages/PadPage.tsx` | SettingsSocketCreateReponse型（80-84行目）でエラーレスポンスの構造を確認 |

**読解のコツ**: TypeScriptの型ガードパターン（`'error' in rep`）を理解していると、成功/エラー分岐のロジックが把握しやすい。

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

クライアント側のパッド作成処理とエラー通知表示の起点となるファイルを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | PadPage.tsx | `admin/src/pages/PadPage.tsx` | results:createPadイベントリスナー（86-103行目）でエラー分岐を確認 |
| 2-2 | PadPage.tsx | `admin/src/pages/PadPage.tsx` | エラー時の処理（87-92行目）を詳細に確認 |

**主要処理フロー**:
1. **86行目**: `settingsSocket.on('results:createPad', ...)` - レスポンスイベントのリスナー
2. **87行目**: `if ('error' in rep)` - 型ガードでエラーケースを判定
3. **88-92行目**: エラー時のトースト表示設定（title: rep.error, success: false）
4. **注意**: エラー時はダイアログを閉じない（99行目の`setCreatePadDialogOpen(false)`は成功時のみ）

#### Step 3: サーバー側のエラー発生処理を理解する

サーバー側でエラーが発生する条件とレスポンス送信を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | adminsettings.ts | `src/node/hooks/express/adminsettings.ts` | createPadイベントハンドラ（258-271行目）でエラー発生条件を確認 |

**主要処理フロー**:
- **258行目**: `socket.on('createPad', async ({padName}: PadCreationOptions) => {...})` - 作成イベントハンドラ
- **259行目**: `padManager.doesPadExists(padName)` - パッド存在チェック
- **260-265行目**: `if (padExists)` - 既存パッドの場合、`{error: 'Pad already exists'}`を送信

#### Step 4: トースト表示コンポーネントを理解する

エラー通知の表示を担当するコンポーネントを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Toast.tsx | `admin/src/utils/Toast.tsx` | ToastDialogコンポーネント（5-26行目）でエラースタイルの適用を確認 |

**主要処理フロー**:
- **7-9行目**: `success`が`false`の場合は`ToastRootFailure`クラスを適用
- **19行目**: タイトル（エラーメッセージ）を表示

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

```
[クライアント] PadPage.tsx
    │
    ├─ onPadCreate() [134-138行目]
    │      │
    │      └─ settingsSocket.emit('createPad', {padName})
    │             │
    │             └─ [サーバー] adminsettings.ts: socket.on('createPad')
    │                    │
    │                    ├─ padManager.doesPadExists(padName)
    │                    │
    │                    └─ 存在する場合:
    │                           │
    │                           └─ socket.emit('results:createPad', {error: 'Pad already exists'})
    │
    └─ settingsSocket.on('results:createPad') [86-103行目]
           │
           └─ 'error' in rep の場合:
                  │
                  └─ setToastState({success: false, title: rep.error, ...})
                         │
                         └─ Toast.tsx: ToastDialog表示（エラースタイル）
```

### データフロー図

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

フォーム入力 ─────────▶ PadPage.tsx
(padName)               │
                        └─ onPadCreate()
                           │
                           └─▶ createPad ─────────────────▶ adminsettings.ts
                               (Socket.IO)                  │
                                                            └─ doesPadExists()
                                                               │
                                                               └─ [存在する]
                                                                  │
                                                                  └─▶ results:createPad ──▶ PadPage.tsx
                                                                      {error: "Pad          │
                                                                       already exists"}     ├─▶ ToastState
                                                                                            │   (success: false)
                                                                                            │
                                                                                            └─▶ Toast.tsx表示
                                                                                                (エラースタイル)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| PadPage.tsx | `admin/src/pages/PadPage.tsx` | ソース | パッド管理ページ、作成フォーム、エラーイベントリスナー |
| adminsettings.ts | `src/node/hooks/express/adminsettings.ts` | ソース | サーバー側パッド存在チェック、エラーイベント送信 |
| store.ts | `admin/src/store/store.ts` | ソース | Zustandストア、ToastState管理 |
| Toast.tsx | `admin/src/utils/Toast.tsx` | ソース | トースト通知表示コンポーネント、エラースタイル適用 |
| PadManager.js | `src/node/db/PadManager.js` | ソース | パッド管理、doesPadExists関数 |
