# 画面設計書 153-ボード表示

## 概要

本ドキュメントは、GitLabのグループ課題ボード表示画面の設計仕様を定義するものです。

### 本画面の処理概要

この画面では、グループレベルで作成された課題ボード（Issue Board）をカンバン形式で表示し、課題のドラッグ&ドロップによる移動や、課題の詳細表示・編集を行います。グループ配下の複数プロジェクトの課題を横断的に管理できます。

**業務上の目的・背景**：カンバンボードは、課題の進捗状況を視覚的に把握するための重要なツールです。「To Do」「Doing」「Done」などのリストに課題をドラッグ&ドロップで移動させることで、直感的なワークフロー管理が可能になります。グループボードを使用することで、複数プロジェクトにまたがる課題を一元管理できます。

**画面へのアクセス方法**：グループのサイドバーから「課題」>「ボード」を選択し、ボード一覧から特定のボードを選択することでアクセスできます。直接URLからもアクセス可能です。

**主要な操作・処理内容**：
1. ボードのリスト（列）と課題カードを表示する
2. 課題カードをドラッグ&ドロップしてリスト間で移動する
3. 課題カードをクリックして詳細サイドバーを表示する
4. 新規課題を作成する
5. リストを追加・編集・削除する（権限がある場合）
6. フィルターで表示する課題を絞り込む

**画面遷移**：ボード一覧画面から遷移してきます。課題カードをクリックすると右サイドバーに詳細が表示されます。課題詳細画面への遷移も可能です。

**権限による表示制御**：グループの「read_issue_board」権限を持つユーザーがこの画面にアクセスできます。課題の移動には「admin_issue」権限、リストの追加・編集・削除には「admin_issue_board_list」権限が必要です。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 39 | イシューボード | 主機能 | グループ課題ボードの表示・操作 |

## 画面種別

詳細（カンバンビュー）

## URL/ルーティング

- パス: `/groups/:group_id/-/boards/:id`
- HTTPメソッド: GET
- コントローラー: `Groups::BoardsController#show`

## 入出力項目

| 項目名 | 項目ID | 型 | 必須 | 説明 |
|--------|--------|-----|------|------|
| ボードID | id | 数値 | ○ | 表示するボードのID |
| フィルター条件 | filter | クエリパラメータ | - | ラベル、担当者、マイルストーン等 |

## 表示項目

| 項目名 | 説明 |
|--------|------|
| ページタイトル | ボード名とともに「Issue Boards」と表示 |
| ボードセレクター | 利用可能なボードのドロップダウン |
| リスト（列） | ラベルごとのカンバン列 |
| 課題カード | 各課題を表すカード |
| フィルターバー | 課題の絞り込み条件 |
| 右サイドバー | 課題詳細表示エリア（#js-right-sidebar-portal） |
| Vueアプリケーション | `#js-issuable-board-app`にマウントされるSPA |

## イベント仕様

### 1-課題カードのドラッグ&ドロップ

課題カードを別のリストにドラッグ&ドロップすると、課題のラベルが更新され、対応するリストに移動します。

### 2-課題カードのクリック

課題カードをクリックすると、右サイドバーに課題の詳細情報が表示されます。サイドバーから課題の編集も可能です。

### 3-リストの追加

「Create new list」ボタンをクリックすると、ラベルを選択して新しいリストを追加できます。

### 4-リストの削除

リストのメニューから「Remove list」を選択すると、リストが削除されます（課題は削除されません）。

### 5-新規課題作成

リストの「+」ボタンをクリックすると、そのリストのラベルが付与された新規課題を作成できます。

### 6-フィルター適用

フィルターバーで条件を設定すると、表示される課題が絞り込まれます。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | boards, lists, issues | SELECT | ボード・リスト・課題の取得 |
| カードのD&D | label_links | UPDATE | 課題のラベル変更 |
| リスト追加 | lists | INSERT | 新規リストの作成 |
| リスト削除 | lists | DELETE | リストの削除 |
| 新規課題作成 | issues, label_links | INSERT | 課題と関連データの作成 |

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

#### lists

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, board_id, label_id, position | WHERE board_id = :board_id | リスト一覧取得 |
| INSERT | board_id, label_id, position | フォーム入力値 | リスト追加時 |
| DELETE | - | WHERE id = :list_id | リスト削除時 |

#### label_links

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | label_id | 移動先リストのラベルID | カードD&D時 |

## メッセージ仕様

| メッセージID | メッセージ種別 | メッセージ内容 | 表示条件 |
|-------------|--------------|---------------|---------|
| M001 | 確認 | "Are you sure you want to remove this list?" | リスト削除時 |
| M002 | 情報 | "No issues to show" | リストに課題がない場合 |
| M003 | エラー | "Failed to update issue" | 課題更新失敗時 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| read_issue_board権限なし | アクセス拒否ページを表示 |
| ボードが見つからない | 404エラーページを表示 |
| 課題更新失敗 | エラーメッセージを表示し、元の状態に戻す |

## 備考

- ボードはVue.jsによるSPAとして実装されており、リアルタイムな更新が可能
- グループボードでは、グループ配下のすべてのプロジェクトの課題を表示
- 課題のポジショニング無効化設定がある場合、ドラッグ&ドロップが制限される
- タイムトラッキングの時間制限設定（`time_tracking_limit_to_hours`）が適用される
- 共有テンプレート（`shared/boards/_show.html.haml`）を`group: true`オプションで使用

---

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

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

### 推奨読解順序

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

まず、ボードとリスト、課題の関連を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | board.rb | `app/models/board.rb` | ボードモデルと関連付けを理解する |
| 1-2 | list.rb | `app/models/list.rb` | リストモデル（カンバン列）を理解する |

**読解のコツ**: Board has_many List、List belongs_to Labelの関連に注目。`group_board?`メソッドでグループボードかどうかを判別。

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

コントローラーでのリクエスト処理フローを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | boards_controller.rb | `app/controllers/groups/boards_controller.rb` | showアクションの実装を理解する |
| 2-2 | boards_actions.rb | `app/controllers/concerns/boards_actions.rb` | 共通ロジックを理解する |

**主要処理フロー**:
1. **行8-13**: before_actionでフィーチャーフラグ設定
2. **行20-23**: `board_finder`でボードを検索
3. **行30-32**: `authorize_read_board!`で権限チェック

#### Step 3: ビューテンプレートを理解する

画面のレンダリング構造を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | show.html.haml | `app/views/groups/boards/show.html.haml` | ボード表示画面テンプレートを理解する |
| 3-2 | _show.html.haml | `app/views/shared/boards/_show.html.haml` | 共有ボードテンプレートを理解する |

**主要処理フロー**:
- **show行1**: `group: true`オプションで共有テンプレートをレンダリング
- **_show行15-16**: 右サイドバーのポータル設定
- **_show行22**: Vue.jsアプリケーションのマウントポイント

#### Step 4: ヘルパーを理解する

ビューで使用されるヘルパーメソッドを確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | boards_helper.rb | `app/helpers/boards_helper.rb` | board_dataメソッドの実装を理解する |

**主要処理フロー**:
- **行8-30**: `board_data`メソッドでVueアプリに渡すデータを生成
- **行36-40**: `group_id`の取得ロジック
- **行50-56**: `build_issue_link_base`でリンクベースパスを生成

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

```
Groups::BoardsController#show
    │
    ├─ include BoardsActions
    │      │
    │      ├─ before_action :authorize_read_board!
    │      │      └─ can?(current_user, :read_issue_board, group)
    │      │
    │      └─ show アクション（BoardsActions内）
    │             └─ board_finder.execute
    │
    ├─ board_finder (行20-23)
    │      └─ Boards::BoardsFinder.new(parent, current_user, board_id: params[:id])
    │
    └─ render (show.html.haml)
           └─ shared/boards/_show (group: true)
                  │
                  ├─ board_data ヘルパー呼び出し
                  │      ├─ board.id, board.name
                  │      ├─ can_update?, can_admin_list?
                  │      └─ work_items_data
                  │
                  └─ #js-issuable-board-app
                         └─ Vue.jsアプリケーション
                                │
                                ├─ GraphQL API呼び出し
                                │
                                └─ リアルタイム課題管理
```

### データフロー図

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

URLパラメータ        Groups::BoardsController
(group_id,                 │
 board_id,                 │
 filter)                   │
        ─────────▶   BoardsActions
                           │
                           ├──▶ Boards::BoardsFinder
                           │         │
                           │         ▼
                           │     boards, lists テーブル
                           │
                           ├──▶ BoardsHelper.board_data
                           │         │
                           │         ▼
                           │     JSON データ
                           │
                           └──▶ Vue.js SPA
                                     │
                                     ├──▶ GraphQL API
                                     │         │
                                     │         ▼
                                     │     issues, labels テーブル
                                     │
                                     └──▶ カンバンボード表示
                                              │
                                              ▼
                                     ユーザー操作（D&D）
                                              │
                                              ▼
                                     API経由でDB更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| boards_controller.rb | `app/controllers/groups/boards_controller.rb` | コントローラー | グループボード用コントローラー |
| boards_actions.rb | `app/controllers/concerns/boards_actions.rb` | Concern | ボードの共通ロジック |
| show.html.haml | `app/views/groups/boards/show.html.haml` | ビュー | ボード表示画面テンプレート |
| _show.html.haml | `app/views/shared/boards/_show.html.haml` | 部分ビュー | 共有ボードテンプレート |
| boards_helper.rb | `app/helpers/boards_helper.rb` | ヘルパー | ボードデータ生成ヘルパー |
| board.rb | `app/models/board.rb` | モデル | ボードモデル |
| list.rb | `app/models/list.rb` | モデル | リストモデル |
| group.rb | `config/routes/group.rb` | ルーティング | URLルーティング定義（行154） |
