# 画面設計書 146-ラベル新規作成

## 概要

本ドキュメントは、GitLabにおけるグループラベル新規作成画面の設計仕様を定義するものである。グループに新しいラベルを作成するための入力フォームを提供する。

### 本画面の処理概要

グループラベル新規作成画面は、グループに対して新しいラベルを作成するためのフォーム画面である。ラベルは課題やマージリクエストの分類に使用され、グループレベルで定義されたラベルは配下のすべてのプロジェクトで利用可能となる。

**業務上の目的・背景**：プロジェクト横断的な課題管理を効率化するため、共通のラベルをグループレベルで定義する必要がある。例えば、「Bug」「Enhancement」「Priority::High」などのラベルを作成し、グループ全体で統一した分類体系を構築できる。

**画面へのアクセス方法**：以下のいずれかの方法でアクセス可能である。
- グループラベル一覧画面の「New label」ボタンをクリック
- URL直接アクセス: `/groups/{group_path}/-/labels/new`

**主要な操作・処理内容**：
1. ラベルタイトルの入力（必須）
2. ラベル説明の入力（任意）
3. ラベル色（背景色）の選択
4. ラベルの作成実行

**画面遷移**：
- 遷移元：グループラベル一覧画面
- 遷移先：グループラベル一覧画面（作成成功時）、同画面（バリデーションエラー時）

**権限による表示制御**：
- Maintainer以上：ラベル作成が可能（admin_label権限）
- 権限がない場合は404エラー

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 40 | ラベル管理 | 主機能 | グループラベルの新規作成 |

## 画面種別

登録

## URL/ルーティング

- パス: `/groups/{group_path}/-/labels/new`
- ルーティング: `groups/labels#new`
- HTTPメソッド: GET（フォーム表示）、POST（作成処理）
- 対応フォーマット: HTML, JSON

## 入出力項目

| 項目名 | 種別 | 必須 | データ型 | 説明 |
|--------|------|------|----------|------|
| title | フォーム入力 | 必須 | String | ラベルタイトル（255文字以内） |
| description | フォーム入力 | 任意 | Text | ラベルの説明（512KB以内） |
| color | フォーム入力 | 任意 | String | 背景色（CSSカラーコード） |

## 表示項目

| 項目名 | データ型 | 説明 | 表示条件 |
|--------|----------|------|----------|
| ページヘッダー | Component | 「New label」タイトル | 常時 |
| タイトル入力欄 | TextInput | ラベル名入力 | 常時 |
| 説明入力欄 | TextArea | ラベル説明入力 | 常時 |
| カラーピッカー | ColorPicker | 背景色選択 | 常時 |
| カラープリセット | ColorSwatches | 推奨色一覧 | 常時 |
| 作成ボタン | Button | ラベル作成実行 | 常時 |
| キャンセルボタン | Button | ラベル一覧へ戻る | 常時 |
| バリデーションエラー | Alert | 入力エラー表示 | エラー時 |

## イベント仕様

### 1-フォーム表示（GET new）

1. `authorize_group_for_admin_labels!`による権限チェック（7行目）
2. `@label = @group.labels.new`で新規ラベルインスタンス作成（35行目）
3. `previous_labels_path`でリターンパス設定（36行目）
4. 共有フォームパーシャル（`shared/labels/_form`）をレンダリング

### 2-ラベル作成（POST create）

1. `authorize_group_for_admin_labels!`による権限チェック
2. `Labels::CreateService`による作成処理（40行目）
3. グループコンテキストで`labels.create`を実行
4. バリデーション成功時：ラベル一覧へリダイレクト（45行目）
5. バリデーション失敗時：フォームを再表示（47行目）

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| フォーム表示 | - | - | データベース操作なし |
| ラベル作成 | labels | INSERT | ラベルレコード作成 |

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

#### labels

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | title | 入力値 | 必須 |
| INSERT | description | 入力値 | 任意 |
| INSERT | color | 入力値（HEX変換後） | デフォルト値あり |
| INSERT | group_id | @group.id | グループラベル |
| INSERT | type | 'GroupLabel' | STI |
| INSERT | created_at | 現在時刻 | 自動設定 |
| INSERT | updated_at | 現在時刻 | 自動設定 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| MSG-001 | エラー | Title can't be blank | タイトル未入力時 |
| MSG-002 | エラー | Title has already been taken | 同名ラベル存在時 |
| MSG-003 | エラー | Color is invalid | 不正なカラーコード |

## 例外処理

| 例外条件 | 処理内容 | 遷移先 |
|----------|----------|--------|
| 管理権限なし | 404エラー | エラーページ |
| グループ不存在 | 404エラー | エラーページ |
| バリデーションエラー | エラーメッセージ表示 | 同画面 |

## 備考

- ラベルの色はCSSカラーコードで指定（#RRGGBB形式）
- カラー名（例：red, blue）を入力した場合、HEXコードに自動変換される
- グループラベルは配下の全プロジェクトで利用可能
- ラベルタイトルはグループ内で一意である必要がある
- 説明は512KBが上限（DESCRIPTION_LENGTH_MAX）

---

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

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

### 推奨読解順序

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

ラベルモデルの構造とバリデーションを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | label.rb | `app/models/label.rb` | ラベルモデル、バリデーション、スコープ |
| 1-2 | group_label.rb | `app/models/group_label.rb` | グループラベル固有の実装 |

**読解のコツ**: `validates :title, uniqueness: { scope: [:group_id, :project_id] }`でタイトルの一意性を確認。`DESCRIPTION_LENGTH_MAX = 512.kilobytes`で説明の上限を把握。

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

コントローラーの`new`と`create`アクションがエントリーポイント。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | labels_controller.rb | `app/controllers/groups/labels_controller.rb` | new/createアクション |

**主要処理フロー**:
1. **7行目**: `authorize_group_for_admin_labels!`で権限チェック
2. **34-37行目**: newアクションでラベルインスタンス生成
3. **39-55行目**: createアクションでLabels::CreateService呼び出し
4. **40行目**: `Labels::CreateService.new(label_params).execute(group: group)`

#### Step 3: サービスクラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | create_service.rb | `app/services/labels/create_service.rb` | ラベル作成ロジック |

**主要処理フロー**:
- **11行目**: カラー名からHEXへの変換
- **16行目**: `lock_on_merge`サポートチェック
- **18行目**: `project_or_group.labels.create(params)`で作成

#### Step 4: ビューレイヤーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | new.html.haml | `app/views/groups/labels/new.html.haml` | メインテンプレート |
| 4-2 | _form.html.haml | `app/views/shared/labels/_form.html.haml` | 共有フォームパーシャル |

**主要処理フロー**:
- **5行目**: PageHeadingComponentでヘッダー表示
- **7行目**: 共有フォームパーシャルをレンダリング
- フォームパーシャル**14行目**: `gitlab_ui_form_for`でフォーム生成
- フォームパーシャル**20行目**: タイトル入力（必須、autofocus）
- フォームパーシャル**26行目**: 説明入力（TextArea）
- フォームパーシャル**29-36行目**: カラーピッカーと推奨色

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

```
Groups::LabelsController#new
    │
    ├─ authorize_group_for_admin_labels! (before_action)
    │      └─ can?(current_user, :admin_label, @group)
    │
    └─ @label = @group.labels.new
           │
           └─ render 'shared/labels/form'

Groups::LabelsController#create
    │
    ├─ authorize_group_for_admin_labels! (before_action)
    │
    └─ Labels::CreateService.new(label_params).execute(group: group)
           │
           ├─ convert_color_name_to_hex (if color present)
           │
           └─ group.labels.create(params)
                  │
                  ├─ Label validations
                  │    ├─ title presence
                  │    ├─ title uniqueness (scope: group_id)
                  │    └─ description bytesize
                  │
                  └─ labels table (INSERT)
```

### データフロー図

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

Form params ─────────────▶ LabelsController#create ─────▶ Redirect/Render
(title, description,              │
 color)                           │
                                  ▼
                          Labels::CreateService
                                  │
                                  ├── color conversion
                                  │     (name → hex)
                                  │
                                  └── group.labels.create
                                          │
                                          ├── validations
                                          │
                                          └── labels table (INSERT)
                                                  │
                                                  ▼
                                          [成功] → redirect_to group_labels_path
                                          [失敗] → render :new
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| labels_controller.rb | `app/controllers/groups/labels_controller.rb` | コントローラー | new/createアクション定義 |
| label.rb | `app/models/label.rb` | モデル | ラベル基底モデル |
| group_label.rb | `app/models/group_label.rb` | モデル | グループラベル |
| new.html.haml | `app/views/groups/labels/new.html.haml` | ビュー | メインテンプレート |
| _form.html.haml | `app/views/shared/labels/_form.html.haml` | ビュー | 共有フォームパーシャル |
| create_service.rb | `app/services/labels/create_service.rb` | サービス | ラベル作成ロジック |
| base_service.rb | `app/services/labels/base_service.rb` | サービス | 基底サービス（カラー変換） |
