# 通知設計書 21-padHasData

## 概要

本ドキュメントは、Etherpadにおいて既存コンテンツがあるパッドへのファイルインポートを試みた際に表示される「padHasData」エラー通知の設計について記載する。

### 本通知の処理概要

この通知は、ユーザーがEtherpadファイル(.etherpad形式)をインポートしようとした際に、対象のパッドが既に編集履歴を持っている場合に表示されるエラーメッセージである。

**業務上の目的・背景**：Etherpadファイル(.etherpad形式)のインポートは、パッドのデータベースを直接操作するため、既存のコンテンツがあるパッドに対して実行すると、データの整合性が保証できなくなる。この通知により、ユーザーにデータ損失や不整合のリスクを事前に伝え、新しいパッドへのインポートを促すことで、安全な操作を誘導する。

**通知の送信タイミング**：ユーザーがインポートフォームから.etherpadファイルをアップロードし、サーバーサイドでファイル処理が開始された時点で、対象パッドのリビジョン数（head count）が10以上であることが検出された際に発生する。

**通知の受信者**：インポート操作を実行したブラウザセッションのユーザー。クライアントサイドのJavaScriptによって表示されるため、操作を行った本人のみが受信する。

**通知内容の概要**：「このファイルをインポートできませんでした。このパッドは既に変更が加えられています。新しいパッドにインポートしてください。」という趣旨のエラーメッセージが表示される。

**期待されるアクション**：ユーザーは新しいパッドを作成し、そこで改めてインポート操作を実行することが期待される。または、既存のパッドのコンテンツをクリアしてからインポートを再試行する。

## 通知種別

アプリ内通知（フロントエンド表示）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（HTTP レスポンス） |
| 優先度 | 高 |
| リトライ | なし |

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

インポートリクエストを送信したクライアントに対してのみ、HTTP レスポンスとしてエラーステータスを返却する。クライアントサイドJavaScriptがこのステータスを解釈し、通知を表示する。

## 通知テンプレート

### アプリ内通知

| 項目 | 内容 |
|-----|------|
| 表示位置 | インポートフォーム内のメッセージエリア |
| スタイルクラス | error（赤色テキスト） |
| 表示方式 | フェードイン |

### 本文テンプレート

```
Import failed: We were not able to import this file because this Pad has already had changes, please import to a new pad
```

日本語（参考）:
```
インポートに失敗しました: このパッドは既に変更されているため、このファイルをインポートできませんでした。新しいパッドにインポートしてください。
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| status | エラーステータスコード | サーバーレスポンス | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | インポートフォーム送信 | 対象パッドのheadCount >= 10 かつ .etherpad形式ファイル | Etherpadファイルのインポート時に既存コンテンツがある場合 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| headCount < 10 | パッドのリビジョン数が10未満の場合はインポートを許可 |
| 非.etherpad形式 | .etherpad以外のファイル形式の場合は本チェックをスキップ |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ユーザーがファイルを選択してインポート] --> B[サーバーにPOSTリクエスト]
    B --> C{ファイル形式チェック}
    C -->|.etherpad| D[パッドの取得]
    C -->|その他| E[通常インポート処理]
    D --> F{headCount >= 10?}
    F -->|Yes| G[ImportError padHasData をスロー]
    F -->|No| H[直接データベースアクセスによるインポート]
    G --> I[HTTPステータス400でエラーレスポンス返却]
    I --> J[クライアントがエラーメッセージを表示]
    H --> K[成功レスポンス]
    E --> K
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| pad:{padId} | パッドのメタデータ取得 | headプロパティでリビジョン数を確認 |

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

#### pad:{padId}

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| head | リビジョン数の確認 | padId指定で取得 |

### 更新テーブル一覧

該当なし（エラー発生時は更新を行わない）

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| padHasData | パッドのheadCount >= 10 | クライアントにエラーメッセージを表示 |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

制限なし（24時間対応）

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

- インポート操作はパッドへの書き込み権限を持つユーザーのみ実行可能
- エラーメッセージには機密情報を含まない
- クロスサイトスクリプティング対策としてメッセージはテキストとしてエスケープ処理される

## 備考

- headCount の閾値（10）はハードコードされており、設定での変更は不可
- この制限は.etherpad形式ファイルのみに適用され、他の形式（HTML、TXT等）には適用されない
- ユーザーは新しいパッドを作成してインポートを再試行することが推奨される

---

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

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

### 推奨読解順序

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

クライアント・サーバー間のデータ構造と、インポートエラーの定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ImportHandler.ts | `src/node/handler/ImportHandler.ts` | ImportErrorクラスの定義（39-49行目）、エラーステータスの構造を確認 |

**読解のコツ**: TypeScriptのクラス拡張パターンを理解していると、カスタムエラークラスの構造が把握しやすい。

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

インポート処理の起点となるコードを特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | pad_impexp.ts | `src/static/js/pad_impexp.ts` | fileInputSubmit関数（49-81行目）がフォーム送信を処理 |
| 2-2 | pad_impexp.ts | `src/static/js/pad_impexp.ts` | importErrorMessage関数（83-108行目）でエラーメッセージを表示 |

**主要処理フロー**:
1. **49行目**: fileInputSubmit関数でフォーム送信をキャプチャ
2. **57-69行目**: ajaxでサーバーにPOSTリクエスト送信
3. **70-71行目**: エラーコードチェックとimportErrorMessage呼び出し
4. **84-88行目**: 既知のエラーステータス一覧（padHasData含む）

#### Step 3: サーバーサイド処理を理解する

サーバーでのファイル処理とエラー発生ロジックを追跡する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ImportHandler.ts | `src/node/handler/ImportHandler.ts` | doImport関数（82-239行目）メイン処理 |
| 3-2 | ImportHandler.ts | `src/node/handler/ImportHandler.ts` | 146-153行目でpadHasDataエラーをスロー |

**主要処理フロー**:
- **141行目**: fileIsEtherpadフラグで.etherpad形式を判定
- **146-148行目**: パッドを取得しheadCountを確認
- **150-153行目**: headCount >= 10の場合、ImportError('padHasData')をスロー
- **249-264行目**: エクスポート関数でエラーをキャッチし、HTTPレスポンスを生成

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

```
[Client] pad_impexp.ts
    │
    ├─ fileInputSubmit() [49行目]
    │      │
    │      ├─ $.ajax() POST /p/{padId}/import
    │      │      │
    │      │      └─ [Server] ImportHandler.ts
    │      │             │
    │      │             ├─ doImport() [82行目]
    │      │             │      │
    │      │             │      ├─ padManager.getPad() [148行目]
    │      │             │      │
    │      │             │      └─ throw ImportError('padHasData') [152行目]
    │      │             │
    │      │             └─ exports.doImport() [249行目]
    │      │                    └─ res.status(400).json({code: 1, message: 'padHasData'})
    │      │
    │      └─ importErrorMessage('padHasData') [71行目]
    │
    └─ importErrorMessage() [83行目]
           └─ html10n.get('pad.impexp.padHasData')
```

### データフロー図

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

.etherpadファイル ───▶ ImportHandler.doImport() ───▶ HTTPレスポンス(400)
                              │                              │
                              ├─ padManager.getPad()         │
                              │                              │
                              └─ headCount >= 10 チェック    ▼
                                                      importErrorMessage()
                                                              │
                                                              ▼
                                                      エラー通知表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| pad_impexp.ts | `src/static/js/pad_impexp.ts` | ソース | クライアント側インポート処理とエラー表示 |
| ImportHandler.ts | `src/node/handler/ImportHandler.ts` | ソース | サーバー側インポート処理とエラー判定 |
| en.json | `src/locales/en.json` | 設定 | 国際化メッセージ定義（204行目: pad.impexp.padHasData） |
| PadManager.ts | `src/node/db/PadManager.ts` | ソース | パッドの取得とメタデータアクセス |
| html10n.ts | `src/static/js/vendors/html10n.ts` | ソース | 国際化ライブラリ |
