# 画面設計書 242-トピック編集

## 概要

本ドキュメントは、GitLab管理者が既存のトピック（Topic）の情報を編集する画面の設計書です。

### 本画面の処理概要

トピック編集画面は、GitLabインスタンス内で既存のトピック情報を更新する管理者専用画面です。トピックの詳細表示画面は存在せず、本画面が詳細表示と編集の両方の役割を担います。

**業務上の目的・背景**：GitLabのトピック機能はプロジェクトの分類・整理に使用されます。時間の経過とともにトピックの名称変更、説明の更新、アバター画像の変更などが必要になります。管理者はこの画面からトピック情報を更新し、最新の状態を維持することができます。また、不要になったトピックはこの画面から削除することも可能です。

**画面へのアクセス方法**：
1. 管理者としてGitLabにログイン
2. 左サイドメニューから「Admin Area」をクリック
3. 「Overview」セクションの「Topics」をクリック
4. 編集したいトピック名をクリック

**主要な操作・処理内容**：
1. トピックスラッグ（name）の編集
2. トピックタイトル（title）の編集
3. 説明（description）の編集 - Markdown対応
4. アバター画像の変更・削除
5. 「Save changes」ボタンで変更保存
6. トピック削除（別機能として実装）

**画面遷移**：
- 遷移元：トピック一覧画面（Admin > Topics）
- 遷移先（成功時）：本画面（成功メッセージ付き）
- 遷移先（失敗時）：本画面（エラーメッセージ表示）
- キャンセル時：トピック一覧画面

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

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 102 | グローバル検索 | 主機能 | トピックの編集処理 |

## 画面種別

編集

## URL/ルーティング

- URL: `/admin/topics/:id/edit`
- HTTP メソッド: GET（画面表示）/ PATCH/PUT（トピック更新）
- ルート名: `edit_admin_topic` / `admin_topic`

## 入出力項目

| 項目名 | 項目ID | 型 | 必須 | 最大長 | バリデーション | 備考 |
|--------|--------|-----|------|--------|----------------|------|
| トピックスラッグ | name | String | ○ | 255 | ASCII文字のみ、改行禁止、一意性 | URL識別子として使用 |
| トピックタイトル | title | String | ○ | 255 | - | 表示名 |
| 説明 | description | Text | - | 1024 | - | Markdown対応 |
| アバター | avatar | File | - | - | 画像ファイル | CarrierWave使用 |

## 表示項目

| 項目名 | 表示形式 | 備考 |
|--------|----------|------|
| ページタイトル | テキスト | "Edit topic: {topic_name}" |
| パンくずリスト | リンク | Topics > {topic_name} > Edit |
| 現在のアバター | 画像 | 設定済みの場合のみ表示 |
| アバター削除リンク | リンク | 設定済みの場合のみ表示 |
| 入力フォーム | フォーム | 既存値がプリセット |
| Markdownプレビュー | ボタン/パネル | 説明フィールド用 |

## イベント仕様

### 1-トピック更新（Save changes）

**トリガー**: 「Save changes」ボタンクリック

**処理フロー**:
1. フォームデータのサーバー送信
2. `Admin::TopicsController#update`アクション呼び出し
3. `@topic.update(topic_params)`実行
4. バリデーション実行
5. 成功時: 本画面へリダイレクト（成功メッセージ付き）
6. 失敗時: 本画面再表示（エラーメッセージ表示）

### 2-キャンセル

**トリガー**: 「Cancel」ボタンクリック

**処理フロー**: トピック一覧画面へ遷移

### 3-アバター削除

**トリガー**: アバター削除リンククリック

**処理フロー**:
1. JavaScript モーダル確認
2. `Admin::Topics::AvatarsController#destroy`へDELETEリクエスト
3. アバター画像削除
4. 画面更新

### 4-Markdownプレビュー

**トリガー**: プレビュータブクリック

**処理フロー**:
1. `preview_markdown_admin_topics_path`へAjaxリクエスト
2. 入力されたMarkdownをHTMLにレンダリング
3. プレビューパネルに表示

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| Save changes押下 | projects_topics | UPDATE | トピックレコード更新 |
| アバター削除 | projects_topics | UPDATE | avatarカラムをNULL化 |
| アバター削除 | uploads | DELETE | アップロードファイル削除 |

### テーブル別更新項目詳細

#### projects_topics

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | name | フォーム入力値 | トピックスラッグ |
| UPDATE | title | フォーム入力値 | トピックタイトル |
| UPDATE | description | フォーム入力値 | 説明テキスト |
| UPDATE | avatar | アップロードファイル/NULL | アバター画像 |
| UPDATE | updated_at | 現在日時 | 更新日時 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| MSG001 | 成功 | Topic was successfully updated. | トピック更新成功時 |
| MSG002 | エラー | Please fill in a name for your topic. | name未入力時 |
| MSG003 | エラー | Please fill in a title for your topic. | title未入力時 |
| MSG004 | エラー | has characters that are not allowed | name に改行文字が含まれる場合 |
| MSG005 | エラー | must only include ASCII characters | name に非ASCII文字が含まれる場合 |
| MSG006 | エラー | has already been taken | 同一組織内でnameが重複 |

## 例外処理

| 例外条件 | 処理内容 | 表示メッセージ |
|----------|----------|---------------|
| 権限不足 | 403エラー画面へリダイレクト | アクセスが拒否されました |
| トピック未検出 | 404エラー画面表示 | ページが見つかりません |
| 異なる組織のトピック | 404エラー画面表示 | ページが見つかりません |
| バリデーションエラー | 画面再表示 | 各フィールドにエラーメッセージ表示 |

## 備考

- トピック詳細表示画面は存在しないため、編集画面が詳細表示を兼ねる
- `find_by_id_and_organization_id!`メソッドにより、組織が一致しないトピックはアクセス不可
- アバター削除は別コントローラ（`Admin::Topics::AvatarsController`）で処理
- トピック削除は本画面からではなく、一覧画面から実行可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | topic.rb | `app/models/projects/topic.rb` | トピックモデルの定義、バリデーション、アソシエーション |

**読解のコツ**:
- `validates`でバリデーションルール確認
- `if: :name_changed?`などの条件付きバリデーションに注目

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | topics_controller.rb | `app/controllers/admin/topics_controller.rb` | edit/updateアクションの処理フロー |

**主要処理フロー**:
1. **7行目**: `before_action :topic`でトピックをロード
2. **22行目**: `edit`アクション（空メソッド、インスタンス変数@topicは`before_action`で設定）
3. **35-40行目**: `update`アクション - 更新処理
4. **65-67行目**: `topic`メソッド - 組織とIDでトピック検索

#### Step 3: ビュー層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | edit.html.haml | `app/views/admin/topics/edit.html.haml` | 編集画面レイアウト |
| 3-2 | _form.html.haml | `app/views/admin/topics/_form.html.haml` | 共通フォームパーシャル |

**主要処理フロー**:
- **2行目**: パンくずリストでedit_admin_topic_path使用（詳細画面がないため）
- **6行目**: ページ見出しに現在のトピック名を表示
- **7行目**: フォームのURLがadmin_topic_path(@topic)（PATCH/PUT）

#### Step 4: アバター削除機能を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | admin.rb | `config/routes/admin.rb` | avatarリソースのネスト定義 |

**主要処理フロー**:
- **85行目**: `resource :avatar, controller: 'topics/avatars', only: [:destroy]`

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

```
ブラウザ (GET /admin/topics/:id/edit)
    │
    ├─ before_action :topic
    │      └─ Projects::Topic.find_by_id_and_organization_id!
    │
    ├─ Admin::TopicsController#edit
    │
    └─ View: admin/topics/edit.html.haml
           └─ Partial: admin/topics/_form.html.haml
                  ├─ 既存値のプリセット
                  └─ アバター表示・削除リンク

ブラウザ (PATCH /admin/topics/:id)
    │
    ├─ before_action :topic
    │
    └─ Admin::TopicsController#update
           ├─ @topic.update(topic_params)
           │      └─ ActiveRecord validations
           └─ redirect_to edit_admin_topic_path (成功時)
              または render "edit" (失敗時)
```

### データフロー図

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

フォームデータ ───────▶ TopicsController#update ───────▶ 成功: 編集画面
  - name                      │                              (フラッシュメッセージ)
  - title                     ├─ topic_params
  - description               ├─ @topic.update
  - avatar                    │     └─ バリデーション
                              │
                              └───────────────────────▶ 失敗: 編集画面
                                                            (エラーメッセージ)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| topics_controller.rb | `app/controllers/admin/topics_controller.rb` | コントローラ | リクエスト処理 |
| topic.rb | `app/models/projects/topic.rb` | モデル | データ定義 |
| edit.html.haml | `app/views/admin/topics/edit.html.haml` | ビュー | 編集画面レイアウト |
| _form.html.haml | `app/views/admin/topics/_form.html.haml` | ビュー | 入力フォーム |
| admin.rb | `config/routes/admin.rb` | 設定 | ルーティング |
| avatars_controller.rb | `app/controllers/admin/topics/avatars_controller.rb` | コントローラ | アバター削除 |
