# 画面設計書 49-課題詳細

## 概要

本ドキュメントは、GitLabの課題詳細（Issue Detail）画面の設計仕様を記載したものである。

### 本画面の処理概要

課題詳細画面は、個別の課題（Issue）の詳細情報を表示し、編集や各種操作を行うための画面である。課題の内容確認、ステータス変更、コメント追加、関連情報の管理など、課題に関するすべての操作を集約している。

**業務上の目的・背景**：課題の詳細情報を一箇所で確認・操作できることは、プロジェクト管理の効率化に不可欠である。本画面は、課題に関連するすべての情報（説明、コメント、関連MR、タイムトラッキング等）を統合的に表示し、チームメンバーが課題の状況を正確に把握できるようにする。

**画面へのアクセス方法**：以下のいずれかの方法でアクセス可能
1. 課題一覧から課題タイトルをクリック
2. 通知メールのリンクをクリック
3. 検索結果から課題を選択
4. 直接URL（`/:namespace/:project/-/issues/:id`）を指定

**主要な操作・処理内容**：
1. 課題情報の表示（タイトル、説明、メタデータ）
2. 課題のステータス変更（Open/Close）
3. コメント・ディスカッションの追加
4. 絵文字リアクションの追加
5. 担当者、ラベル、マイルストーンの変更
6. タイムトラッキング（作業時間の記録）
7. 関連課題のリンク管理
8. 関連マージリクエストの確認
9. デザイン管理（Designs機能）

**画面遷移**：
- 遷移元: 課題一覧、ダッシュボード、通知、検索結果
- 遷移先: 課題編集、関連MR詳細、関連課題詳細

**権限による表示制御**：
- 課題閲覧には`read_issue`権限が必要
- 課題編集には`update_issue`権限が必要
- コメント追加には`create_note`権限が必要

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 37 | イシュー編集 | 主機能 | 課題の詳細表示・編集 |
| 38 | イシュークローズ/再オープン | 補助機能 | 課題のクローズ・再オープン |
| 42 | イシューリンク | 補助機能 | 関連イシューのリンク管理 |
| 43 | タイムトラッキング | 補助機能 | 作業時間の記録 |

## 画面種別

詳細

## URL/ルーティング

```
GET /:namespace/:project/-/issues/:id
GET /:namespace/:project/-/issues/:id/discussions (JSON)
GET /:namespace/:project/-/issues/:id/realtime_changes
GET /:namespace/:project/-/issues/:id/related_branches (JSON)
GET /:namespace/:project/-/issues/:id/can_create_branch (JSON)
POST /:namespace/:project/-/issues/:id/toggle_subscription
POST /:namespace/:project/-/issues/:id/toggle_award_emoji
POST /:namespace/:project/-/issues/:id/move
PUT /:namespace/:project/-/issues/:id/reorder
GET /:namespace/:project/-/issues/:id/designs/*
```

## 入出力項目

| 項目名 | I/O | 型 | 必須 | 説明 |
|--------|-----|-----|------|------|
| id | 入力 | Integer | 必須 | 課題IID |
| edit | 入力 | String | 任意 | 編集モードフラグ（"true"） |
| incident_tab | 入力 | String | 任意 | インシデントタブ（timeline/metrics/alerts） |

## 表示項目

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 課題タイトル | String | 課題のタイトル |
| 課題参照番号 | String | #xxx形式の参照番号 |
| ステータス | Badge | Open/Closed |
| 課題説明 | Markdown | 課題の詳細説明 |
| 作成者 | User | 課題作成者情報 |
| 作成日時 | DateTime | 作成日時 |
| 更新日時 | DateTime | 最終更新日時 |
| 担当者 | Array | 担当者一覧 |
| ラベル | Array | 付与されたラベル |
| マイルストーン | Link | 関連マイルストーン |
| 期限 | Date | 期限日 |
| 重み | Integer | 課題の重み |
| タイムトラッキング | Object | 見積り/使用時間 |
| 絵文字リアクション | Array | リアクション一覧 |
| コメント/ディスカッション | Array | コメント一覧 |
| 関連課題 | Array | リンクされた課題 |
| 関連マージリクエスト | Array | 関連MR一覧 |
| 関連ブランチ | Array | 関連ブランチ一覧 |
| サイドバー | Component | 各種メタデータ編集 |

## イベント仕様

### 1-Close/Reopenボタン押下

1. 現在のステータスに応じて逆の状態に変更
2. `Issues::UpdateService`を実行
3. ステータスバッジを更新

### 2-コメント投稿

1. コメント内容を入力
2. 送信ボタン押下で`Notes::CreateService`を実行
3. ディスカッション一覧を更新

### 3-絵文字リアクション追加

1. 絵文字を選択
2. `toggle_award_emoji`エンドポイントへPOST
3. リアクション一覧を更新

### 4-担当者/ラベル/マイルストーン変更

サイドバーのセレクターで選択し、即座に`Issues::UpdateService`で更新。

### 5-関連課題リンク追加

1. リンクする課題を検索・選択
2. `IssueLinks::CreateService`を実行
3. 関連課題セクションを更新

### 6-購読切り替え

`toggle_subscription`エンドポイントへPOSTし、通知の購読状態を切り替え。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| ステータス変更 | issues | UPDATE | state_id更新 |
| コメント投稿 | notes | INSERT | ノート追加 |
| 絵文字追加 | award_emoji | INSERT/DELETE | リアクション管理 |
| 担当者変更 | issue_assignees | INSERT/DELETE | 担当者更新 |
| ラベル変更 | label_links | INSERT/DELETE | ラベル更新 |
| 関連課題追加 | issue_links | INSERT | リンク作成 |
| 購読変更 | subscriptions | INSERT/UPDATE/DELETE | 購読状態 |

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

#### issues

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | state_id | 1(open)/2(closed) | ステータス変更 |
| UPDATE | closed_at | 現在時刻/null | クローズ時のみ |
| UPDATE | closed_by_id | current_user.id/null | クローズ時のみ |
| UPDATE | updated_at | 現在時刻 | 常に更新 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ | 表示条件 |
|-------------|------|-----------|----------|
| MSG-001 | 成功 | 更新成功メッセージ | 各種更新成功時 |
| MSG-002 | エラー | "You don't have permission to do this" | 権限不足時 |

## 例外処理

| 例外状態 | 処理内容 |
|---------|----------|
| 課題が存在しない | 404 Not Foundを返却 |
| 権限不足 | 403 Forbiddenを返却 |
| ロックバージョン不一致 | コンフリクトエラーを返却 |

## 備考

- Work Items機能が有効な場合、Work Item詳細画面にリダイレクトされる可能性あり
- `@right_sidebar = false`でサイドバーを非表示にする場合あり
- インシデントタイプの場合、追加タブ（timeline/metrics/alerts）が表示される
- リアルタイム更新に対応（`realtime_changes`エンドポイント）

---

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

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

### 推奨読解順序

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

課題（Issue）モデルと関連データを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | issue.rb | `app/models/issue.rb` | 課題のデータ構造、アソシエーション |
| 1-2 | noteable.rb | `app/models/concerns/noteable.rb` | コメント機能 |

**読解のコツ**: `Issue`は`Issuable`、`Noteable`、`Awardable`など多くのモジュールをインクルードしている。

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

コントローラーの`show`アクションが処理の起点。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | issues_controller.rb | `app/controllers/projects/issues_controller.rb` | showアクション |

**主要処理フロー**:
1. **行30**: `issue` - before_actionで課題取得
2. **行40-41**: `redirect_if_work_item` - Work Itemリダイレクト判定
3. **行134-151**: showアクション

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | show.html.haml | `app/views/projects/issues/show.html.haml` | メインビュー |
| 3-2 | _details_content.html.haml | `app/views/projects/issues/_details_content.html.haml` | 詳細コンテンツ |

**主要処理フロー**:
- **行21**: `_details_content`パーシャル呼び出し
- **details_content行8-9**: `#js-issuable-app`でVueコンポーネント

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

```
IssuesController#show
    │
    ├─ before_action :issue
    │      └─ @project.issues.find_by_iid(id)
    │
    ├─ redirect_if_work_item (条件付き)
    │      └─ redirect_to project_work_item_path
    │
    └─ render "show"
           └─ render "_details_content"
                  ├─ #js-issuable-app (Vue component)
                  ├─ render "_emoji_block"
                  ├─ render "_related_issues"
                  └─ render "_discussion"
```

### データフロー図

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

Issue IID ───▶ IssuesController#show ───▶ HTML Response
                       │
                       ├─▶ Issue.find_by_iid()
                       │       └─▶ Issue object
                       │
                       ├─▶ inc_relations_for_view
                       │       └─▶ Eager loaded data
                       │
                       └─▶ Presenter/Serializer
                               └─▶ View data
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| issues_controller.rb | `app/controllers/projects/issues_controller.rb` | コントローラー | リクエスト処理 |
| show.html.haml | `app/views/projects/issues/show.html.haml` | テンプレート | メインビュー |
| _details_content.html.haml | `app/views/projects/issues/_details_content.html.haml` | パーシャル | 詳細コンテンツ |
| issue.rb | `app/models/issue.rb` | モデル | 課題データ構造 |
| update_service.rb | `app/services/issues/update_service.rb` | サービス | 課題更新処理 |
| issues.rb | `config/routes/issues.rb` | ルーティング | URL定義 |
| issuable_actions.rb | `app/controllers/concerns/issuable_actions.rb` | Concern | 共通アクション |
