# 画面設計書 271-外見設定

## 概要

本ドキュメントは、GitLab管理者画面における「外見設定（Appearance）」画面の設計書です。システム全体のビジュアルカスタマイズを管理者が行うための画面仕様を記載しています。

### 本画面の処理概要

**業務上の目的・背景**：組織のブランディング要件を満たすため、GitLabインスタンス全体の外観をカスタマイズする必要があります。ログイン画面のロゴ、ファビコン、ヘッダーメッセージ、フッターメッセージなどを設定することで、社内システムとしての統一感を出したり、利用規約やお知らせを全ユーザーに周知したりすることができます。

**画面へのアクセス方法**：管理者エリア > 設定 > 外見（Admin Area > Settings > Appearance）からアクセスします。管理者権限を持つユーザーのみがアクセス可能です。

**主要な操作・処理内容**：
1. ファビコンのアップロード・削除
2. ナビゲーションバーのヘッダーロゴ設定
3. サインイン/サインアップページのロゴ・タイトル・説明文設定
4. PWA（Progressive Web App）の名前・説明・アイコン設定
5. メンバーガイドライン、新規プロジェクトガイドライン、プロフィール画像ガイドラインの設定
6. システムヘッダー/フッターメッセージの設定
7. 設定のプレビュー表示

**画面遷移**：管理者ダッシュボードから遷移。設定保存後は同画面にリダイレクトされ、成功メッセージが表示されます。プレビューボタンからサインインページプレビュー、新規プロジェクトページへ遷移できます。

**権限による表示制御**：管理者（admin）権限を持つユーザーのみがアクセス・編集可能です。一般ユーザーがアクセスを試みると404エラーが表示されます。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 114 | アプリケーション設定 | 主機能 | システム外見設定の管理 |

## 画面種別

編集

## URL/ルーティング

```
GET/PATCH /admin/application_settings/appearances
```

## 入出力項目

| 項目名 | 入出力 | 型 | 必須 | 説明 |
|--------|--------|-----|------|------|
| title | 入力 | String | - | サインインページのタイトル |
| description | 入力 | Text | - | サインインページの説明文（Markdown対応） |
| logo | 入力 | File | - | サインインページのロゴ画像（最大1MB） |
| header_logo | 入力 | File | - | ナビゲーションバーのロゴ画像（最大1MB、推奨24px高） |
| favicon | 入力 | File | - | ファビコン（32x32px、最大1MB） |
| pwa_name | 入力 | String | - | PWA名（最大255文字） |
| pwa_short_name | 入力 | String | - | PWA短縮名（最大255文字） |
| pwa_description | 入力 | Text | - | PWA説明文（最大2048文字） |
| pwa_icon | 入力 | File | - | PWAアイコン（最大1MB） |
| member_guidelines | 入力 | Text | - | メンバーガイドライン（Markdown対応） |
| new_project_guidelines | 入力 | Text | - | 新規プロジェクトガイドライン（Markdown対応） |
| profile_image_guidelines | 入力 | Text | - | プロフィール画像ガイドライン（最大4096文字、Markdown対応） |
| header_message | 入力 | Text | - | システムヘッダーメッセージ |
| footer_message | 入力 | Text | - | システムフッターメッセージ |
| message_background_color | 入力 | String | - | メッセージ背景色（デフォルト: #E75E40） |
| message_font_color | 入力 | String | - | メッセージ文字色（デフォルト: #FFFFFF） |
| email_header_and_footer_enabled | 入力 | Boolean | - | メールヘッダー/フッター有効化フラグ |

## 表示項目

| 項目名 | 説明 |
|--------|------|
| 現在のファビコン | アップロード済みファビコンのプレビュー |
| 現在のロゴ | アップロード済みロゴのプレビュー |
| 現在のヘッダーロゴ | アップロード済みヘッダーロゴのプレビュー |
| 現在のPWAアイコン | アップロード済みPWAアイコンのプレビュー |
| 最終更新日時 | 設定の最終更新日時 |

## イベント仕様

### 1-外見設定の更新

**トリガー**: 「Update appearance settings」ボタン押下

**処理フロー**:
1. フォームデータのバリデーション実行
2. Appearanceモデルの更新または新規作成
3. アップロード画像のCarrierWaveによる処理
4. Markdownフィールドのキャッシュ更新
5. 成功時: 同画面にリダイレクト、成功メッセージ表示
6. 失敗時: エラーメッセージを表示し、フォームを再表示

### 2-ロゴの削除

**トリガー**: 各ロゴの「Remove」ボタン押下（確認ダイアログ後）

**処理フロー**:
1. 削除確認ダイアログ表示
2. 確認後、対象画像フィールドをnilに設定
3. Appearanceモデルを保存
4. アップロードファイルの物理削除
5. 同画面にリダイレクト、成功メッセージ表示

### 3-プレビュー表示

**トリガー**: 「Sign-in page」「New project page」ボタン押下

**処理フロー**:
1. 新しいタブでプレビューページを表示
2. 現在保存されている設定でプレビューレンダリング

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 設定更新 | appearances | INSERT/UPDATE | 外見設定の保存 |
| ロゴ削除 | appearances | UPDATE | 画像カラムをnullに更新 |
| 設定更新 | uploads | INSERT/DELETE | CarrierWaveによるアップロード管理 |

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

#### appearances

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT/UPDATE | title | フォーム入力値 | |
| INSERT/UPDATE | description | フォーム入力値 | |
| INSERT/UPDATE | description_html | Markdownレンダリング結果 | キャッシュ |
| INSERT/UPDATE | logo | アップロードファイルパス | CarrierWave管理 |
| INSERT/UPDATE | header_logo | アップロードファイルパス | CarrierWave管理 |
| INSERT/UPDATE | favicon | アップロードファイルパス | CarrierWave管理 |
| INSERT/UPDATE | pwa_name | フォーム入力値 | |
| INSERT/UPDATE | pwa_short_name | フォーム入力値 | |
| INSERT/UPDATE | pwa_description | フォーム入力値 | |
| INSERT/UPDATE | pwa_icon | アップロードファイルパス | CarrierWave管理 |
| INSERT/UPDATE | member_guidelines | フォーム入力値 | |
| INSERT/UPDATE | member_guidelines_html | Markdownレンダリング結果 | キャッシュ |
| INSERT/UPDATE | new_project_guidelines | フォーム入力値 | |
| INSERT/UPDATE | new_project_guidelines_html | Markdownレンダリング結果 | キャッシュ |
| INSERT/UPDATE | profile_image_guidelines | フォーム入力値 | |
| INSERT/UPDATE | profile_image_guidelines_html | Markdownレンダリング結果 | キャッシュ |
| INSERT/UPDATE | header_message | フォーム入力値 | |
| INSERT/UPDATE | header_message_html | Markdownレンダリング結果 | キャッシュ |
| INSERT/UPDATE | footer_message | フォーム入力値 | |
| INSERT/UPDATE | footer_message_html | Markdownレンダリング結果 | キャッシュ |
| INSERT/UPDATE | message_background_color | フォーム入力値 | |
| INSERT/UPDATE | message_font_color | フォーム入力値 | |
| INSERT/UPDATE | email_header_and_footer_enabled | フォーム入力値 | |
| INSERT/UPDATE | updated_at | 現在日時 | |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|---------|
| MSG001 | 成功 | Appearance was successfully created. | 新規作成成功時 |
| MSG002 | 成功 | Appearance was successfully updated. | 更新成功時 |
| MSG003 | 成功 | Logo was successfully removed. | ロゴ削除成功時 |
| MSG004 | 成功 | Header logo was successfully removed. | ヘッダーロゴ削除成功時 |
| MSG005 | 成功 | Favicon was successfully removed. | ファビコン削除成功時 |
| MSG006 | 成功 | Progressive Web App (PWA) icon was successfully removed. | PWAアイコン削除成功時 |
| MSG007 | エラー | Only 1 appearances row can exist | 2つ目のappearanceレコード作成試行時 |
| MSG008 | エラー | is too long (maximum is 255 characters) | pwa_name, pwa_short_nameが255文字超過時 |
| MSG009 | エラー | is too long (maximum is 2048 characters) | pwa_descriptionが2048文字超過時 |

## 例外処理

| 例外 | 処理内容 |
|------|---------|
| ファイルサイズ超過 | バリデーションエラーを表示し、フォームを再表示 |
| 画像形式不正 | バリデーションエラーを表示し、フォームを再表示 |
| 管理者権限なし | 404エラーページを表示 |
| CSRF トークン不正 | 422エラーを返却 |

## 備考

- appearancesテーブルには1レコードのみ存在可能（シングルトンパターン）
- CacheableAttributesモジュールにより設定値はキャッシュされる
- 画像アップロードにはCarrierWaveを使用
- Markdownフィールドはcache_markdown_fieldによりHTMLがキャッシュされる
- ファビコンサイズは32x32pxが推奨（異なるサイズの場合は表示が不正になる可能性あり）

---

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

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

### 推奨読解順序

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

外見設定のデータモデルとバリデーションルールを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | appearance.rb | `app/models/appearance.rb` | Appearanceモデルの属性、バリデーション、Markdownキャッシュ設定を理解 |

**読解のコツ**:
- `cache_markdown_field`でキャッシュされるフィールドを確認
- `mount_uploader`でCarrierWaveによるファイルアップロード設定を確認
- `single_appearance_row`バリデーションでシングルトン制約を確認

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

ルーティングとコントローラの処理フローを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | admin.rb | `config/routes/admin.rb` | 外見設定のルーティング定義（204行目付近） |
| 2-2 | appearances_controller.rb | `app/controllers/admin/application_settings/appearances_controller.rb` | コントローラの各アクション |

**主要処理フロー**:
1. **9行目**: `show`アクションで現在の設定を取得
2. **15-22行目**: `create`アクションで新規作成
3. **25-30行目**: `update`アクションで更新
4. **33-61行目**: 各画像削除アクション
5. **67-68行目**: `set_appearance`で現在の設定またはnewオブジェクトを取得

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

画面表示とフォーム構成を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | show.html.haml | `app/views/admin/application_settings/appearances/show.html.haml` | メインビューテンプレート |
| 3-2 | _form.html.haml | `app/views/admin/application_settings/appearances/_form.html.haml` | フォームの詳細構成 |

**主要処理フロー**:
- **7行目（show）**: フォームパーシャルのレンダリング
- **3行目（form）**: gitlab_ui_form_forによるフォーム生成
- **6-23行目（form）**: ファビコン設定セクション
- **36-51行目（form）**: ナビゲーションバー設定
- **101-124行目（form）**: サインイン/サインアップページ設定

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

```
Admin::ApplicationSettings::AppearancesController#show
    │
    ├─ set_appearance (before_action)
    │      └─ Appearance.current || Appearance.new
    │
    └─ render 'form'
           └─ _form.html.haml
                  ├─ Layouts::SettingsSectionComponent
                  └─ Pajamas::ButtonComponent
```

### データフロー図

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

フォーム入力データ ───▶ AppearancesController#update
                              │
                              ├─▶ appearance_params（許可パラメータ抽出）
                              │
                              ├─▶ Appearance#update
                              │       │
                              │       ├─▶ バリデーション実行
                              │       │
                              │       ├─▶ CarrierWave（画像保存）
                              │       │
                              │       └─▶ cache_markdown_field（Markdownキャッシュ）
                              │
                              └─▶ redirect / render ───▶ 画面表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| appearance.rb | `app/models/appearance.rb` | モデル | 外見設定データモデル |
| appearances_controller.rb | `app/controllers/admin/application_settings/appearances_controller.rb` | コントローラ | 外見設定の表示・更新処理 |
| show.html.haml | `app/views/admin/application_settings/appearances/show.html.haml` | ビュー | メイン画面テンプレート |
| _form.html.haml | `app/views/admin/application_settings/appearances/_form.html.haml` | ビュー | フォームパーシャル |
| _system_header_footer_form.html.haml | `app/views/admin/application_settings/appearances/_system_header_footer_form.html.haml` | ビュー | ヘッダー/フッター設定パーシャル |
| attachment_uploader.rb | `app/uploaders/attachment_uploader.rb` | アップローダー | ロゴ等のアップロード処理 |
| favicon_uploader.rb | `app/uploaders/favicon_uploader.rb` | アップローダー | ファビコンのアップロード処理 |
| admin.rb | `config/routes/admin.rb` | ルーティング | URL定義 |
