# 通知設計書 32-パッド作成成功通知

## 概要

本ドキュメントは、Etherpad管理画面におけるパッド作成成功通知の設計を記載する。この通知は、管理者が管理画面からパッドを新規作成し、その処理が正常に完了した場合に表示されるトースト通知である。

### 本通知の処理概要

管理画面のパッド管理ページにおいて、管理者がパッド作成ダイアログからパッド名を入力して作成を実行し、サーバー側で正常にパッドが作成された場合に、成功通知を表示する処理を行う。

**業務上の目的・背景**：Etherpadの管理者は、ユーザーからの依頼や運用上の必要性に応じて、特定の名前を持つパッドを事前に作成することがある。パッド作成処理は非同期で行われるため、処理が正常に完了したことを管理者に明示的に伝える必要がある。本通知は、パッド作成の成功を確認し、管理者が次のアクションに移れるようにする。

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

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

**通知内容の概要**：「Pad created {パッド名}」という動的メッセージがトースト通知として表示される。作成されたパッド名が含まれるため、どのパッドが作成されたかを確認できる。

**期待されるアクション**：管理者は通知を確認し、作成されたパッドが一覧に追加されていることを確認する。必要に応じて、作成したパッドを開いて初期設定を行う。

## 通知種別

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

## 送信仕様

### 基本情報

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

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

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

## 通知テンプレート

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

| 項目 | 内容 |
|-----|------|
| タイトル | Pad created {padName} |
| 説明 | なし（titleのみ表示） |
| 表示スタイル | ToastRootSuccess（成功スタイル） |

### 本文テンプレート

```
Pad created {padName}
```

### 添付ファイル

該当なし

## テンプレート変数

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

## 送信トリガー・条件

### トリガー一覧

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

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 管理者以外のユーザー | is_adminがfalseの場合、Socket.IO接続自体が拒否される |
| パッド名が空 | react-hook-formのバリデーションで送信が阻止される |
| 同名パッドが存在 | サーバー側でエラーとなり、エラー通知が送信される |

## 処理フロー

### 送信フロー

```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[results:createPad error送信]
    I -->|存在しない| K[パッド作成処理]
    K --> L[results:createPad success送信]
    L --> M[クライアント: 成功イベント受信]
    M --> N[setToastState で成功トースト表示]
    N --> O[ダイアログを閉じる]
    O --> P[パッド一覧を再読み込み]
    J --> Q[エラー通知表示]
```

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

### 参照テーブル一覧

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

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

#### pad:{padName}

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

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| pad:{padName} | CREATE | 新規パッドのメタデータ作成 |

#### パッド作成

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| CREATE | pad:{padName} | 初期パッドデータ | padManager.getPad()で自動作成 |

## エラー処理

### エラーケース一覧

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

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

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

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

- 管理者認証が必須であり、認証されていないユーザーにはSocket.IO接続が拒否される
- パッド名はユーザー入力であるが、特殊文字のサニタイズはEtherpad標準のパッド名バリデーションに従う
- 成功メッセージにはパッド名のみが含まれ、機密情報は含まれない

## 備考

- 成功通知表示後、パッド作成ダイアログは自動的に閉じられる
- パッド一覧は自動的に再読み込みされ、作成したパッドが表示される
- パッドの作成は`padManager.getPad()`を呼び出すことで暗黙的に行われる

---

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

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

### 推奨読解順序

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

まず、通知に関連するデータ構造とパッド関連の型を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | store.ts | `admin/src/store/store.ts` | ToastState型（6-11行目）とsetToastState関数（41行目）の構造を確認 |
| 1-2 | PadSearch.ts | `admin/src/utils/PadSearch.ts` | PadSearchQueryとPadSearchResult型（1-20行目）を確認 |

**読解のコツ**: Zustandストアのパターンとreact-hook-formの使い方を理解していると、状態管理とフォーム処理の流れが把握しやすい。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | PadPage.tsx | `admin/src/pages/PadPage.tsx` | PadCreateProps型（13-15行目）とonPadCreate関数（134-138行目）がエントリーポイント |
| 2-2 | PadPage.tsx | `admin/src/pages/PadPage.tsx` | results:createPadイベントリスナー（86-103行目）で成功/エラー分岐を確認 |

**主要処理フロー**:
1. **34行目**: `useForm<PadCreateProps>()` - react-hook-formでフォーム管理
2. **134-138行目**: `onPadCreate` - フォーム送信時にcreatePadイベントを送信
3. **86-103行目**: `results:createPad`リスナー - サーバーレスポンスに応じてトースト表示
4. **93-98行目**: 成功時の処理 - トースト表示、ダイアログを閉じ、パッド一覧を再読み込み

#### 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行目**: 既存パッドの場合はエラーレスポンス
- **266-270行目**: 新規パッドを作成し、成功レスポンスを送信

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

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

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

**主要処理フロー**:
- **6行目**: Zustandストアからtoast状態を取得
- **7-9行目**: `success`が`true`の場合は`ToastRootSuccess`クラスを適用
- **19行目**: タイトル（成功メッセージ）を表示

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

```
[クライアント] PadPage.tsx
    │
    ├─ onPadCreate() [134-138行目]
    │      │
    │      └─ settingsSocket.emit('createPad', {padName})
    │             │
    │             └─ [サーバー] adminsettings.ts: socket.on('createPad')
    │                    │
    │                    ├─ padManager.doesPadExists(padName)
    │                    │
    │                    └─ 存在しない場合:
    │                           │
    │                           ├─ padManager.getPad(padName) [パッド作成]
    │                           │
    │                           └─ socket.emit('results:createPad', {success: ...})
    │
    └─ settingsSocket.on('results:createPad') [86-103行目]
           │
           ├─ 'success' in rep の場合:
           │      │
           │      ├─ setToastState({success: true, ...})
           │      │
           │      ├─ setCreatePadDialogOpen(false)
           │      │
           │      └─ settingsSocket.emit('padLoad', searchParams)
           │
           └─ Toast.tsx: ToastDialog表示
```

### データフロー図

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

フォーム入力 ─────────▶ PadPage.tsx
(padName)               │
                        └─ onPadCreate()
                           │
                           └─▶ createPad ─────────────────▶ adminsettings.ts
                               (Socket.IO)                  │
                                                            ├─ doesPadExists()
                                                            │
                                                            └─ getPad() [作成]
                                                               │
                                                               └─▶ results:createPad ──▶ PadPage.tsx
                                                                   {success: "Pad       │
                                                                    created {name}"}    ├─▶ ToastState
                                                                                        │
                                                                                        └─▶ 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` | ソース | トースト通知表示コンポーネント |
| PadSearch.ts | `admin/src/utils/PadSearch.ts` | ソース | パッド検索関連の型定義 |
| PadManager.js | `src/node/db/PadManager.js` | ソース | パッド管理、doesPadExists、getPad関数 |
