# 画面設計書 7-プラグイン管理画面

## 概要

本ドキュメントは、Etherpad Liteのプラグイン管理画面の設計内容を記述するものである。この画面は、インストール済みプラグインの一覧表示、新規プラグインの検索・インストール・アンインストール機能を提供する管理画面の中核機能である。

### 本画面の処理概要

**業務上の目的・背景**：Etherpadは豊富なプラグインエコシステムを持ち、プラグインによって機能を拡張できる。本画面は、システム管理者がプラグインのライフサイクル（検索、インストール、更新、アンインストール）を管理するためのインターフェースを提供する。npmレジストリから公開されているEtherpadプラグインを検索し、ワンクリックでインストールできる。

**画面へのアクセス方法**：管理者ログイン後、自動的にリダイレクトされるデフォルト画面。または管理画面のサイドメニューから「Plugins」を選択してアクセス。URLパスは `/admin/plugins` または `/admin/`（デフォルト）。

**主要な操作・処理内容**：
1. インストール済みプラグインの一覧表示
2. インストール済みプラグインのアンインストール
3. 利用可能なプラグインの検索
4. 新規プラグインのインストール
5. プラグインの更新（更新可能な場合）
6. プラグイン詳細ページ（npmjs.com）へのリンク

**画面遷移**：
- 遷移元: 管理者ログイン画面（認証成功後）、サイドメニュー
- 遷移先: サイドメニュー経由で他の管理画面、外部リンク（npmjs.com）

**権限による表示制御**：管理者権限（is_admin: true）を持つユーザーのみアクセス可能。WebSocket接続時にセッションの権限が検証される。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 61 | プラグイン管理 | 主機能 | プラグインのインストール・アンインストール・検索・更新確認 |
| 64 | 統計情報取得 | API連携 | 接続ユーザー数などの統計情報を取得して表示 |

## 画面種別

一覧 / 管理

## URL/ルーティング

- **URL**: `/admin/plugins` または `/admin/`
- **HTTPメソッド**: GET（画面表示）
- **WebSocket名前空間**: `/pluginfw/installer`
- **コンポーネント**: `admin/src/pages/HomePage.tsx`

## 入出力項目

| 項目名 | 項目ID | 入力/出力 | データ型 | 必須 | 最大長 | 説明 |
|--------|--------|----------|---------|------|--------|------|
| 検索キーワード | searchTerm | 入力 | テキスト | - | - | プラグイン検索用キーワード |

## 表示項目

| 項目名 | 項目ID | 説明 |
|--------|--------|------|
| ページタイトル | - | 「Plugins」（i18n: admin_plugins） |
| インストール済みプラグインセクション | - | 「Installed Plugins」（i18n: admin_plugins.installed） |
| インストール済みプラグインテーブル | installed-plugins | プラグイン名、バージョン、アクション列 |
| 利用可能プラグインセクション | - | 「Available Plugins」（i18n: admin_plugins.available） |
| 検索フィールド | - | SearchFieldコンポーネント |
| 利用可能プラグインテーブル | available-plugins | プラグイン名、説明、バージョン、更新日、アクション列 |
| アンインストールボタン | - | Trashアイコン |
| インストールボタン | - | Downloadアイコン |
| 更新ボタン | - | ArrowUpFromDotアイコン |

## イベント仕様

### 1-プラグイン検索

検索フィールドにキーワードを入力すると、500msのデバウンス後にWebSocket経由で検索リクエストが送信される（`search`イベント）。サーバーはnpmレジストリから「ep_」プレフィックスのプラグインを検索し、結果を返送する（`results:search`イベント）。結果はテーブルに表示される。

### 2-プラグインインストール

利用可能プラグイン一覧のインストールボタン（Downloadアイコン）をクリックすると、WebSocket経由でインストールリクエストが送信される（`install`イベント）。インストール完了後（`finished:install`イベント）、インストール済みプラグイン一覧が自動更新される。

### 3-プラグインアンインストール

インストール済みプラグイン一覧のアンインストールボタン（Trashアイコン）をクリックすると、WebSocket経由でアンインストールリクエストが送信される（`uninstall`イベント）。完了後（`finished:uninstall`イベント）、一覧から削除される。

**注意**: `ep_etherpad-lite`（コアパッケージ）はアンインストール不可（disabled属性）。

### 4-プラグイン更新

更新可能なプラグインがある場合、アンインストールボタンの代わりに更新ボタン（ArrowUpFromDotアイコン）が表示される。クリックすると`install`イベントで最新バージョンがインストールされる。

### 5-ソート切り替え

利用可能プラグインテーブルのヘッダーをクリックすると、その列でソートが切り替わる（name, version, last-updated）。昇順/降順がトグルで切り替わる。

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

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

プラグインのインストール/アンインストールはファイルシステムとnpmパッケージ管理に影響するが、Etherpadのメインデータベースには直接影響しない。

| 操作（イベント） | 対象 | 操作種別 | 概要 |
|----------------|------|---------|------|
| インストール | node_modules | npm install | プラグインパッケージをインストール |
| アンインストール | node_modules | npm uninstall | プラグインパッケージを削除 |
| 更新 | node_modules | npm install | 最新バージョンをインストール |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|---------|
| admin_plugins | タイトル | Plugins | ページタイトル |
| admin_plugins.installed | セクション | Installed Plugins | インストール済みセクション |
| admin_plugins.available | セクション | Available Plugins | 利用可能セクション |
| admin_plugins.name | ヘッダー | Name | テーブルヘッダー |
| admin_plugins.version | ヘッダー | Version | テーブルヘッダー |
| admin_plugins.description | ヘッダー | Description | テーブルヘッダー |
| admin_plugins.last-update | ヘッダー | Last Update | テーブルヘッダー |
| admin_plugins.available_search.placeholder | プレースホルダー | Search... | 検索フィールド |
| admin_plugins.available_install.value | ボタンタイトル | Install | インストールボタン |
| admin_plugins.installed_uninstall.value | ボタンタイトル | Uninstall | アンインストールボタン |
| admin_plugins.available_not-found | 情報 | No plugins found | 検索結果なし |
| pad.loading | 情報 | Loading... | 読み込み中 |
| - | エラー | Error retrieving plugins | プラグイン取得エラー時（トースト） |

## 例外処理

| 例外状態 | 対応処理 | 表示内容 |
|---------|---------|---------|
| 検索エラー | トースト通知 | 「Error retrieving plugins」 |
| インストールエラー | エラー情報付きで完了通知 | finished:installイベントにerror含む |
| アンインストールエラー | エラー情報付きで完了通知 | finished:uninstallイベントにerror含む |
| WebSocket切断 | 自動再接続 | 接続復帰時にgetInstalledを再送信 |
| 権限不足 | 接続拒否 | WebSocket接続が確立されない |

## 備考

- 5分ごとに更新確認を自動実行（checkUpdatesイベント）
- インストール済みプラグインはアルファベット順にソート
- 検索結果からインストール済みプラグインは除外される
- プラグイン名はnpmjs.comへのリンクとして表示
- ep_etherpad-liteはコアパッケージのため、アンインストール不可
- ソート対象: name, version, last-updated

---

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

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

### 推奨読解順序

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

プラグイン管理では、インストール済みプラグインと検索結果のプラグインの2種類のデータ構造を扱う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Plugin.ts | `admin/src/pages/Plugin.ts` | PluginDef, InstalledPlugin, SearchParams, HelpObj型定義 |
| 1-2 | store.ts | `admin/src/store/store.ts` | installedPlugins, pluginsSocket の状態管理 |

**読解のコツ**: `InstalledPlugin`にはupdatableフラグがあり、更新可能かどうかを示す。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | HomePage.tsx | `admin/src/pages/HomePage.tsx` | プラグイン管理画面コンポーネント全体 |

**主要処理フロー**:
1. **12行目**: HomePageコンポーネント定義
2. **13-23行目**: 状態変数の初期化
3. **70-120行目**: useEffect - WebSocketイベントリスナー設定
4. **75-78行目**: results:installed - インストール済みプラグイン受信
5. **81-91行目**: results:updatable - 更新可能情報受信
6. **94-100行目**: finished:install / finished:uninstall - 完了通知
7. **123-141行目**: useEffect - 検索イベント処理
8. **143-152行目**: uninstallPlugin / installPlugin 関数
9. **154-160行目**: useDebounce - 検索デバウンス処理
10. **168-191行目**: インストール済みプラグインテーブルレンダリング
11. **194-244行目**: 利用可能プラグインテーブルレンダリング

#### Step 3: サーバーサイドのプラグイン処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | adminplugins.ts | `src/node/hooks/express/adminplugins.ts` | WebSocketイベントハンドラー |
| 3-2 | installer.ts | `src/static/js/pluginfw/installer.ts` | install, uninstall, search関数 |

**主要処理フロー**:
- **17-19行目**: Socket.IO名前空間 `/pluginfw/installer`
- **20-22行目**: 管理者権限チェック
- **47-59行目**: getInstalled - インストール済みプラグイン取得
- **86-100行目**: search - プラグイン検索
- **102-112行目**: install - プラグインインストール
- **115-121行目**: uninstall - プラグインアンインストール

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

```
[ブラウザ] GET /admin/plugins
    │
    ├─ React SPA (HomePage.tsx)
    │      │
    │      ├─ WebSocket接続 (/pluginfw/installer)
    │      │      │
    │      │      └─ [サーバー] adminplugins.ts
    │      │              │
    │      │              ├─ getInstalled
    │      │              │      └─ pluginDefs.plugins 参照
    │      │              │
    │      │              ├─ search
    │      │              │      └─ installer.search()
    │      │              │             └─ npmレジストリ検索
    │      │              │
    │      │              ├─ install
    │      │              │      └─ installer.install()
    │      │              │             └─ npm install
    │      │              │
    │      │              └─ uninstall
    │      │                     └─ installer.uninstall()
    │      │                            └─ npm uninstall
    │      │
    │      └─ UIレンダリング
    │             ├─ インストール済みテーブル
    │             └─ 利用可能テーブル
```

### データフロー図

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

検索キーワード ─────▶ useDebounce (500ms) ────▶ WebSocket 'search'
                                                       │
                                                       ▼
                                               [サーバー]
                                               npmレジストリ検索
                                                       │
                                                       ▼
                                               'results:search' ────▶ テーブル表示

インストールボタン ──▶ WebSocket 'install' ────▶ npm install
                                                       │
                                                       ▼
                                               'finished:install' ──▶ 一覧更新

アンインストール ────▶ WebSocket 'uninstall' ──▶ npm uninstall
ボタン                                                 │
                                                       ▼
                                               'finished:uninstall' ▶ 一覧更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| HomePage.tsx | `admin/src/pages/HomePage.tsx` | ソース | プラグイン管理画面コンポーネント |
| Plugin.ts | `admin/src/pages/Plugin.ts` | ソース | プラグイン関連型定義 |
| store.ts | `admin/src/store/store.ts` | ソース | 状態管理ストア |
| adminplugins.ts | `src/node/hooks/express/adminplugins.ts` | ソース | WebSocketハンドラー |
| installer.ts | `src/static/js/pluginfw/installer.ts` | ソース | npmインストール処理 |
| plugin_defs.ts | `src/static/js/pluginfw/plugin_defs.ts` | ソース | プラグイン定義管理 |
| SearchField.tsx | `admin/src/components/SearchField.tsx` | ソース | 検索フィールドコンポーネント |
| IconButton.tsx | `admin/src/components/IconButton.tsx` | ソース | アイコンボタンコンポーネント |
| useDebounce.ts | `admin/src/utils/useDebounce.ts` | ソース | デバウンスフック |
