# 画面設計書 13-フォルダブラウズ画面

## 概要

本ドキュメントは、Payload CMSの管理画面における「フォルダブラウズ画面」の設計仕様を定義するものである。複数のコレクションを横断してフォルダ構造でブラウズできる画面である。

### 本画面の処理概要

フォルダブラウズ画面は、フォルダ機能が有効な全てのコレクションを横断的にブラウズするための統合ビューである。

**業務上の目的・背景**：大規模なCMSでは複数のコレクション（記事、画像、動画、PDFなど）が存在し、それぞれをフォルダで整理している場合がある。フォルダブラウズ画面は、特定のコレクションに依存せず、全てのフォルダ対応コレクションを統合的に閲覧・管理できるビューを提供する。これにより、ユーザーはファイルエクスプローラのような直感的なUIで、コレクションを意識せずにコンテンツをブラウズできる。

**画面へのアクセス方法**：ダッシュボード画面のナビゲーションから「フォルダをブラウズ」を選択、またはURLで `/{admin}/browse-by-folder` に直接アクセスすることで表示される。特定のフォルダを開く場合は `/{admin}/browse-by-folder/{folderID}` となる。

**主要な操作・処理内容**：
1. 全コレクションを横断したフォルダ階層の表示
2. 複数コレクションのドキュメントを統合表示
3. コレクション種別によるフィルタリング
4. フォルダ間のナビゲーション
5. パンくずリストによる階層確認
6. フォルダ・ドキュメントの作成（フォルダ内での作成）
7. 表示形式の切り替え（グリッド/リスト）

**画面遷移**：
- 遷移元：ダッシュボード画面
- 遷移先：フォルダ表示画面（フォルダ選択時）、ドキュメント編集画面（ドキュメント選択時）

**権限による表示制御**：各コレクションの `read` 権限に基づき、ユーザーが閲覧可能なコレクションのみが表示される。フォルダ作成にはフォルダコレクションの `create` 権限、ドキュメント作成には各コレクションの `create` 権限が必要。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | コレクション管理 | 主機能 | フォルダ階層のブラウズ・ナビゲーション |
| 30 | Admin UI | 補助機能 | フォルダブラウズUIのレンダリング |

## 画面種別

一覧（フォルダ横断ブラウズ）

## URL/ルーティング

- ルート: `/{adminRoute}/browse-by-folder`
- サブフォルダ: `/{adminRoute}/browse-by-folder/{folderID}`

パラメータ:
- `{adminRoute}`: 管理画面のベースパス（デフォルト: `/admin`）
- `{folderID}`: 表示するフォルダのID（省略時はルート）

クエリパラメータ:
- `sort`: ソートキー
- `relationTo`: 表示対象のコレクションスラッグ（JSON配列）

## 入出力項目

| 項目名 | 入力/出力 | データ型 | 必須 | 説明 |
|--------|----------|---------|------|------|
| folderID | 入力 | string/number | No | 表示するフォルダID（URLパラメータ） |
| sort | 入力 | FolderSortKeys | No | ソートキー（クエリパラメータ） |
| relationTo | 入力 | string[] | No | 表示対象コレクション（クエリパラメータ） |
| viewPreference | 入力 | 'grid'/'list' | No | 表示形式（プリファレンス） |
| subfolders | 出力 | array | - | サブフォルダの配列 |
| documents | 出力 | array | - | 複数コレクションのドキュメント配列 |
| breadcrumbs | 出力 | array | - | パンくずリスト情報 |
| folderAssignedCollections | 出力 | array | - | フォルダに関連付けられたコレクション |

## 表示項目

| 項目名 | データ型 | 説明 |
|--------|---------|------|
| フォルダ名 | string | フォルダの名前 |
| コレクション種別バッジ | string | ドキュメントが属するコレクション名 |
| サムネイル | image | ドキュメントのサムネイル画像 |
| ドキュメントタイトル | string | ドキュメントのタイトル |
| 更新日時 | datetime | 最終更新日時 |
| パンくずリスト | array | 現在の階層パス |
| コレクションフィルター | array | 表示コレクションの選択UI |

## イベント仕様

### 1-フォルダ・ドキュメント一覧表示

画面表示時に全コレクションのフォルダとドキュメントを取得して表示する。

**処理フロー**：
1. ユーザーがread権限を持つコレクションを特定
2. URLパラメータからfolderIDを取得（なければルート）
3. プリファレンス（ソート、表示形式）を取得
4. `getFolderResultsComponentAndData()` でフォルダデータを取得
5. パンくずリストを構築
6. グリッドまたはリスト形式で表示

### 2-フォルダナビゲーション

フォルダをクリックしてサブフォルダに移動する。

**処理フロー**：
1. クリックされたフォルダのIDを取得
2. URLを `/browse-by-folder/{folderID}` に更新
3. フォルダ内容を取得して表示

### 3-コレクションフィルタリング

特定のコレクションのみを表示するフィルターを適用する。

**処理フロー**：
1. 選択されたコレクションスラッグを取得
2. URLクエリパラメータ `relationTo` を更新
3. フィルタリングされた結果を表示

### 4-ドキュメント選択

ドキュメントをクリックして編集画面に遷移する。

**処理フロー**：
1. クリックされたドキュメントのIDとコレクションを取得
2. 該当コレクションのドキュメント編集画面へリダイレクト

### 5-フォルダ作成

ルートまたは現在のフォルダにサブフォルダを作成する。

**処理フロー**：
1. フォルダ作成ダイアログを表示
2. フォルダ名を入力
3. 親フォルダIDを設定してフォルダを作成
4. 一覧を再取得

### 6-ドキュメント作成

現在のフォルダ内にドキュメントを作成する。

**処理フロー**：
1. 作成するコレクションを選択
2. ドキュメント作成画面に遷移（フォルダIDを引き継ぎ）

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 一覧表示 | {foldersSlug}, 複数コレクション | SELECT | フォルダと複数コレクションのドキュメント取得 |
| フォルダ作成 | {foldersSlug} | INSERT | 新規フォルダを作成 |
| ドキュメント作成 | 各コレクション | INSERT | フォルダ紐付けでドキュメント作成 |

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

#### {foldersSlug}（フォルダコレクション）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | - | WHERE parent = {folderID} または parent IS NULL | サブフォルダ取得 |
| INSERT | name, parent | フォルダ名、親フォルダID | フォルダ作成 |

#### 各コレクション

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | - | WHERE {folderFieldName} = {folderID} | フォルダ内ドキュメント取得 |
| INSERT | {folderFieldName}, ... | フォルダID、その他フィールド | ドキュメント作成 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| folder.created | 成功 | フォルダが作成されました | フォルダ作成成功時 |
| folder.noPermission | エラー | フォルダを作成する権限がありません | 権限不足時 |
| browseByFolder.empty | 情報 | フォルダまたはドキュメントがありません | 空のフォルダ表示時 |

## 例外処理

| 例外状態 | 対応 |
|---------|------|
| フォルダ機能が無効（config.folders = false） | not-foundエラーを投げる |
| browseByFolderが無効 | not-foundエラーを投げる |
| フォルダIDが無効 | ルートフォルダにリダイレクト |
| 全コレクションのread権限がない | 空の一覧を表示 |

## 備考

- BrowseByFolder機能は `config.folders.browseByFolder` で有効化される
- ルート表示時（folderIDなし）はフォルダのみが表示される
- フォルダ内表示時はサブフォルダと全対応コレクションのドキュメントが表示される
- プリファレンスは `PREFERENCE_KEYS.BROWSE_BY_FOLDER` キーで保存される
- `activeCollectionFolderSlugs` で現在表示中のコレクションを管理
- ドキュメント作成はフォルダ内でのみ可能（ルートでは不可）

---

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

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

### 推奨読解順序

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

フォルダブラウズ画面で扱うデータ構造の理解が重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | buildView.tsx | `packages/next/src/views/BrowseByFolder/buildView.tsx` | BuildFolderViewArgs型（行18-27） |
| 1-2 | types | `packages/payload/src/admin/types.ts` | FolderListViewClientProps, FolderSortKeys |

**読解のコツ**: CollectionFolderViewとの違いは `browseByFolder: true` の設定と、複数コレクションを扱う点である。

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

フォルダブラウズ画面のエントリーポイントとなるファイルを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.tsx | `packages/next/src/views/BrowseByFolder/index.tsx` | BrowseByFolderコンポーネントの構造 |

**主要処理フロー**:
1. **行9**: BrowseByFolderコンポーネント定義
2. **行10-11**: buildBrowseByFolderViewを呼び出し、Viewを取得
3. **行13-21**: エラーハンドリング（NEXT_REDIRECT, not-found）

#### Step 3: ビュー構築ロジックを理解する

フォルダブラウズビューを構築するロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | buildView.tsx | `packages/next/src/views/BrowseByFolder/buildView.tsx` | buildBrowseByFolderView関数の実装 |

**主要処理フロー**:
- **行58-59**: config.folders.browseByFolderが無効な場合のエラー処理
- **行67-71**: 権限チェック（allowReadCollectionSlugs）
- **行91-100**: collectionsToDisplayの決定（ルートか否かで変わる）
- **行111-120**: upsertPreferencesでプリファレンス取得・保存
- **行125-134**: getFolderResultsComponentAndDataでデータ取得
- **行138-148**: フォルダIDの検証とリダイレクト
- **行172-197**: allowCreateCollectionSlugsの決定ロジック

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

```
BrowseByFolder (BrowseByFolder/index.tsx)
    │
    └─ buildBrowseByFolderView (buildView.tsx)
           │
           ├─ 権限チェック
           │   └─ allowReadCollectionSlugs計算
           │      └─ 各コレクションのread権限 && visibleEntities
           │
           ├─ collectionsToDisplay決定
           │   ├─ ルート: [foldersSlug]のみ
           │   └─ フォルダ内: [allowReadCollectionSlugs, foldersSlug]
           │
           ├─ upsertPreferences() - ソート・表示形式設定
           │   └─ key: PREFERENCE_KEYS.BROWSE_BY_FOLDER
           │
           ├─ getFolderResultsComponentAndData()
           │   ├─ browseByFolder: true
           │   ├─ collectionsToDisplay
           │   └─ folderAssignedCollections
           │
           ├─ フォルダID検証・リダイレクト
           │
           └─ RenderServerComponent()
                  │
                  └─ DefaultBrowseByFolderView
                         │
                         ├─ FolderResultsComponent
                         ├─ Breadcrumbs
                         ├─ CollectionFilter
                         └─ Create buttons
```

### データフロー図

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

URLパラメータ ───▶ BrowseByFolder ───▶ 全コレクション統合表示
  - folderID                  │
                              ├─▶ buildBrowseByFolderView()
クエリパラメータ ─────────────┤      │
  - sort                      │      ├─▶ 権限フィルタリング
  - relationTo                │      │      └─▶ allowReadCollectionSlugs
                              │      │
プリファレンス ───────────────┤      ├─▶ collectionsToDisplay決定
  - viewPreference            │      │      ├─▶ ルート: フォルダのみ
                              │      │      └─▶ サブフォルダ: 全コレクション
                              │      │
                              │      ├─▶ getFolderResultsComponentAndData()
                              │      │      ├─▶ サブフォルダ取得
                              │      │      └─▶ 複数コレクションドキュメント取得
                              │      │
                              │      └─▶ allowCreateCollectionSlugs決定
                              │
                              └─▶ DefaultBrowseByFolderView表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.tsx | `packages/next/src/views/BrowseByFolder/index.tsx` | ソース | フォルダブラウズ画面のエントリーポイント |
| buildView.tsx | `packages/next/src/views/BrowseByFolder/buildView.tsx` | ソース | ビュー構築ロジック |
| DefaultBrowseByFolderView | `packages/ui/src/views/FolderView/BrowseByFolder.tsx` | ソース | クライアント側ブラウズビューコンポーネント |
| getFolderResultsComponentAndData | `packages/ui/src/rsc/getFolderResultsComponentAndData.ts` | ソース | フォルダデータ取得ロジック |
| upsertPreferences | `packages/ui/src/rsc/upsertPreferences.ts` | ソース | プリファレンス管理 |
| PREFERENCE_KEYS | `packages/payload/src/shared/constants.ts` | 定数 | プリファレンスキー定義 |
