# 画面設計書 74-外観設定

## 概要

本ドキュメントは、Jenkinsの外観（テーマ、ヘッダー、フッターなど）を設定する画面の設計仕様を記述したものです。

### 本画面の処理概要

この画面はJenkinsのビジュアル外観をカスタマイズするための管理画面です。UIテーマプラグインを通じてインストールされたテーマの選択や、ConsoleUrlProviderなどの外観関連設定を一元的に管理します。プラグインにより提供される外観設定を動的に収集し、フォームとして表示・編集することができます。

**業務上の目的・背景**：企業のCI/CD環境では、ブランディングや視認性の向上のためにJenkinsの外観をカスタマイズしたいニーズがあります。この画面は、UIテーマプラグイン（Dark Theme、Material Themeなど）で追加される設定項目を統合的に管理する場所を提供します。また、プラグインがインストールされていない場合は適切な案内を表示し、ユーザーをプラグインマネージャーへ誘導します。

**画面へのアクセス方法**：Jenkins管理画面（Manage Jenkins）から「Appearance」リンクをクリックしてアクセスします。URLは`/manage/appearance`です。

**主要な操作・処理内容**：
1. インストールされている外観関連プラグインの設定項目を表示
2. 各プラグインの設定値を編集
3. 「Save」ボタンで設定を保存
4. 「Apply」ボタンで設定を適用（ページ遷移なし）
5. プラグイン未インストール時は「Find Plugins」リンクでプラグインマネージャーへ誘導

**画面遷移**：
- 遷移元：Jenkins管理画面（28-Jenkins管理）
- 遷移先：
  - Jenkins管理画面（設定保存後）
  - プラグインマネージャー（利用可能なプラグイン、UI Themesフィルター適用）

**権限による表示制御**：
- MANAGE権限：設定の編集と保存が可能
- SYSTEM_READ権限：設定の閲覧のみ可能（読み取り専用モード）
- 権限なし：アクセス不可

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 45 | システム設定 | 主機能 | Jenkinsの外観（テーマ等）設定 |

## 画面種別

設定画面（フォーム編集）

## URL/ルーティング

- URL: `/manage/appearance`
- 設定保存エンドポイント: `POST /manage/appearance/configure`

## 入出力項目

| 項目名 | 入出力 | 必須 | 型 | 説明 |
|--------|--------|------|-----|------|
| 各プラグイン設定項目 | 入出力 | プラグイン依存 | 可変 | 外観関連プラグインが提供する設定項目（動的） |

## 表示項目

| 項目名 | 表示形式 | 説明 |
|--------|----------|------|
| ページタイトル | テキスト | AppearanceGlobalConfiguration.displayName（「Appearance」） |
| ページ説明 | テキスト | AppearanceGlobalConfiguration.description |
| Find Pluginsボタン | リンクボタン | プラグインマネージャーへのリンク（プラグインがある場合のみヘッダーに表示） |
| プラグイン設定フォーム | フォーム | 各外観プラグインの設定項目（動的に生成） |
| Empty State通知 | 通知パネル | プラグイン未インストール時の案内メッセージ |
| Save/Applyボタン | ボタン | 設定保存・適用ボタン |

## イベント仕様

### 1-設定保存（Save）

「Save」ボタン押下時に、フォームの内容をサーバーに送信し、設定を永続化します。

**処理フロー**:
1. フォームデータをJSON形式でPOST送信
2. 各プラグインのDescriptor.configure()メソッドを呼び出し
3. Jenkins.save()で設定を永続化
4. Jenkins管理画面（/manage）へリダイレクト

### 2-設定適用（Apply）

「Apply」ボタン押下時に、フォームの内容をサーバーに送信し、設定を適用します（ページ遷移なし）。

**処理フロー**:
1. フォームデータをJSON形式でPOST送信
2. 各プラグインのDescriptor.configure()メソッドを呼び出し
3. Jenkins.save()で設定を永続化
4. 同じページに留まる

### 3-プラグイン検索（Find Plugins）

「Find Plugins」ボタン押下時に、プラグインマネージャーのUI Themesカテゴリへ遷移します。

**処理フロー**:
1. `/manage/pluginManager/available?filter=UI Themes`へ遷移

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 設定保存（Save/Apply） | - | ファイル更新 | 各プラグインの設定がXMLファイルに保存される |

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

Jenkinsは設定をXMLファイルで管理しているため、データベーステーブルは使用しません。

#### 設定ファイル

| 操作 | ファイル | 更新内容 | 備考 |
|-----|---------|---------|------|
| 設定保存 | 各プラグインの設定ファイル | プラグイン依存 | `$JENKINS_HOME/`配下 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| displayName | タイトル | Appearance | 常時表示 |
| description | 説明 | （設定画面の説明） | 常時表示 |
| noPlugins | 通知 | No appearance plugins are installed | プラグイン未インストール時 |
| findPlugins | リンク | Find plugins | プラグイン検索リンク |

## 例外処理

| 例外条件 | 処理内容 |
|---------|----------|
| 権限不足 | アクセス拒否画面を表示 |
| 設定保存エラー | エラーメッセージを表示 |
| プラグイン未インストール | Empty State通知を表示し、プラグインマネージャーへの誘導リンクを提供 |

## 備考

- この画面は`AppearanceCategory`を持つDescriptorのみを表示対象とします
- `ConsoleUrlProviderGlobalConfiguration`は特別なケースとして、カスタムプロバイダーがない場合は非表示となります
- プラグインがインストールされていない場合は、設定フォームの代わりにEmpty State UIが表示されます
- 設定の永続化は各プラグインのDescriptorが担当し、Jenkins.save()を通じて行われます

---

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

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

### 推奨読解順序

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

まず、外観設定画面の制御に使用されるクラス構造を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | AppearanceGlobalConfiguration.java | `core/src/main/java/jenkins/appearance/AppearanceGlobalConfiguration.java` | 外観設定画面のManagementLinkクラス |
| 1-2 | AppearanceCategory.java | `core/src/main/java/jenkins/appearance/AppearanceCategory.java` | 外観カテゴリのDescriptorCategory |

**読解のコツ**: `AppearanceGlobalConfiguration`は`ManagementLink`を継承しており、Jenkins管理画面からアクセスできる管理リンクとして機能します。`FILTER`プレディケートにより、`AppearanceCategory`を持つDescriptorのみが表示対象となります。

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

リクエスト処理の起点を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AppearanceGlobalConfiguration.java | `core/src/main/java/jenkins/appearance/AppearanceGlobalConfiguration.java` | doConfigure()メソッドが設定保存のエントリーポイント |

**主要処理フロー**:
1. **53-64行目**: FILTERプレディケートでAppearanceCategoryを持つDescriptorをフィルタリング
2. **74-77行目**: hasPlugins()でプラグイン有無を判定
3. **100-105行目**: doConfigure()で設定保存を処理
4. **107-118行目**: configure()で各Descriptorのconfigureを呼び出し

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

画面の実際のレンダリング処理を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.jelly | `core/src/main/resources/jenkins/appearance/AppearanceGlobalConfiguration/index.jelly` | Jellyテンプレートによる画面レンダリング |

**主要処理フロー**:
- **27-45行目**: ヘッダー部分（タイトル、Find Pluginsボタン）
- **47行目**: l:settings-subpageで権限チェック（MANAGE_AND_SYSTEM_READ）
- **52-58行目**: プラグイン未インストール時のEmpty State通知
- **60-75行目**: プラグインがある場合の設定フォーム
- **67-71行目**: 各DescriptorのglobalConfigPageをインクルード
- **74行目**: Save/Applyボタン

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

```
/manage/appearance (GET)
    │
    └─ AppearanceGlobalConfiguration
           │
           ├─ hasPlugins()
           │      │
           │      └─ Functions.getSortedDescriptorsForGlobalConfigByDescriptor(FILTER)
           │
           └─ index.jelly
                  │
                  ├─ [プラグインなし] l:notice (Empty State)
                  │
                  └─ [プラグインあり] f:form
                         │
                         └─ 各Descriptor.globalConfigPage

/manage/appearance/configure (POST)
    │
    └─ AppearanceGlobalConfiguration.doConfigure()
           │
           ├─ configure(req, json)
           │      │
           │      └─ 各Descriptor.configure()
           │
           └─ Jenkins.save()
                  │
                  └─ FormApply.success() → /manage へリダイレクト
```

### データフロー図

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

GETリクエスト ───▶ AppearanceGlobalConfiguration ───▶ index.jelly HTML
                   │                                    │
                   └─ hasPlugins()判定                  ├─ [あり] 設定フォーム
                                                        └─ [なし] Empty State

POSTリクエスト ───▶ doConfigure()              ───▶ /manage へリダイレクト
(設定JSON)          │
                    ├─ 各Descriptor.configure()
                    │
                    └─ Jenkins.save()
                           │
                           └─ 各プラグイン設定ファイル更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AppearanceGlobalConfiguration.java | `core/src/main/java/jenkins/appearance/AppearanceGlobalConfiguration.java` | ソース | 外観設定画面のManagementLinkクラス |
| AppearanceCategory.java | `core/src/main/java/jenkins/appearance/AppearanceCategory.java` | ソース | 外観カテゴリのDescriptorCategory |
| index.jelly | `core/src/main/resources/jenkins/appearance/AppearanceGlobalConfiguration/index.jelly` | テンプレート | 外観設定画面のJellyテンプレート |
| Messages.properties | `core/src/main/resources/jenkins/appearance/Messages.properties` | リソース | メッセージリソース |
| ConsoleUrlProviderGlobalConfiguration.java | `core/src/main/java/jenkins/console/ConsoleUrlProviderGlobalConfiguration.java` | ソース | コンソールURLプロバイダー設定（特殊ケース） |
