# 機能設計書 22-コレクション表示

## 概要

本ドキュメントは、Decap CMSにおけるコレクション表示機能について、フォルダベースおよびファイルベースのコレクションをサイドバーとメインエリアで表示する処理の全体構造を記述した機能設計書である。

### 本機能の処理概要

CMS管理画面のメインビューとして、コレクション一覧をサイドバーのナビゲーションとメインエリアのエントリ一覧で表示する機能である。Collectionコンポーネントを中心に、Sidebar、CollectionTop、CollectionControls、EntriesCollectionの各サブコンポーネントを統合して画面を構成する。

**業務上の目的・背景**：CMSのコンテンツ管理において、コレクション（記事、ページ等のコンテンツタイプ）を一覧表示し、エントリの閲覧・作成・編集へのナビゲーションを提供することが基本的な要件である。フォルダベースとファイルベースの2種類のコレクション構造をサポートすることで、多様なコンテンツ管理ニーズに対応する。

**機能の利用シーン**：
- CMS管理画面にログイン後、最初に表示されるメイン画面
- サイドバーからコレクションを選択してエントリ一覧を表示する場合
- 検索結果画面での検索結果一覧表示
- ネストされたコレクションのツリーナビゲーション

**主要な処理内容**：
1. Redux Storeからコレクション情報・エントリ一覧を取得しコンポーネントに渡す
2. Sidebarコンポーネントでコレクション一覧をナビゲーションリンクとして表示（ネストコレクションの場合はツリー表示）
3. CollectionTopコンポーネントでコレクション名・説明・新規作成ボタンを表示
4. CollectionControlsコンポーネントでソート・フィルタ・グループ・ビュースタイルの制御UI表示
5. EntriesCollectionコンポーネントでエントリ一覧をカード形式で表示（ページネーション対応）
6. 検索結果モードではEntriesSearchコンポーネントに切り替え

**関連システム・外部連携**：バックエンドAPIを通じてエントリデータを読み込む。Algolia等の統合検索との連携も対応。

**権限による制御**：コレクション設定の`create`プロパティにより新規作成ボタンの表示/非表示が制御される。`hide`プロパティによりサイドバーからのコレクション非表示が可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 3 | コレクション一覧画面 | 主画面 | サイドバーとメインエリアでのコレクション表示。CollectionTopとEntriesCollectionコンポーネントによる描画 |
| 4 | コレクション検索結果画面 | 参照画面 | 検索結果のコレクション表示。isSearchResultsプロップで検索結果モードに切り替え |
| 5 | コレクションフィルター画面 | 参照画面 | フィルター適用後のエントリ一覧表示。filterTermパラメータに基づくネストコレクションのフィルタリング |

## 機能種別

表示処理 / ナビゲーション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | string | No | URLパラメータからのコレクション名 | 未指定時はcollections.first()を使用 |
| searchTerm | string | No | URLパラメータからの検索クエリ | 空文字デフォルト |
| filterTerm | string | No | URLパラメータからのフィルタパス | 空文字デフォルト |
| isSearchResults | boolean | No | 検索結果表示モードかどうか | ownPropsから取得 |
| isSingleSearchResult | boolean | No | 単一コレクション検索結果モード | ownPropsから取得 |

### 入力データソース

- React RouterのURLパラメータ（match.params）
- Redux Store: state.collections（コレクション定義）
- Redux Store: state.entries（エントリデータ）
- Redux Store: state.config（CMS設定）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Sidebar | ReactElement | サイドバーナビゲーション（コレクション一覧） |
| CollectionTop | ReactElement | コレクション見出し・新規作成ボタン |
| CollectionControls | ReactElement | ソート・フィルタ・グループ・ビュースタイル制御 |
| EntriesCollection / EntriesSearch | ReactElement | エントリ一覧またはサーチ結果一覧 |

### 出力先

- 画面表示（DOM描画）

## 処理フロー

### 処理シーケンス

```
1. React RouterからURLパラメータ（name, searchTerm, filterTerm）を取得
   └─ match.paramsから抽出
2. mapStateToPropsでRedux Stateからデータを取得
   └─ collections, sort, sortableFields, viewFilters, viewGroups, filter, group, viewStyle
3. Collectionコンポーネントのrender()を実行
   └─ isSearchResultsフラグに応じて表示モードを切り替え
4a. 通常モード:
   └─ Sidebar + CollectionTop + CollectionControls + EntriesCollection を描画
4b. 検索結果モード:
   └─ Sidebar + SearchResultHeading + EntriesSearch を描画
5. EntriesCollectionのcomponentDidMountでloadEntries()を実行
   └─ バックエンドからエントリデータを取得
6. カーソルベースのページネーションでハンドルCursorActionsを実行
   └─ Waypointコンポーネントで追加読み込みをトリガー
```

### フローチャート

```mermaid
flowchart TD
    A[URLパラメータ取得] --> B[mapStateToProps実行]
    B --> C{isSearchResults?}
    C -->|Yes| D[SearchResultHeading + EntriesSearch描画]
    C -->|No| E[CollectionTop + CollectionControls描画]
    E --> F{ネストコレクション?}
    F -->|Yes| G[filterNestedEntriesでフィルタ]
    F -->|No| H[全エントリ表示]
    G --> I[EntriesCollection描画]
    H --> I
    D --> J[終了]
    I --> J
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-22-01 | コレクション名未指定時のデフォルト | URLにコレクション名がない場合、最初のコレクション（collections.first()）を表示 | コレクション名パラメータ未指定時 |
| BR-22-02 | 非表示コレクション | collection.hide === trueのコレクションはサイドバーに表示されない | Sidebarのコレクション一覧描画時 |
| BR-22-03 | 新規作成ボタン表示条件 | collection.create === trueの場合のみ新規作成ボタンを表示 | CollectionTopコンポーネント描画時 |
| BR-22-04 | ネストコレクションの分岐 | collection.nestedプロパティが存在する場合、NestedCollectionコンポーネントを使用 | Sidebar描画時 |
| BR-22-05 | 検索結果モード切替 | isSearchResultsプロップがtrueの場合、EntriesSearchコンポーネントに切り替え | Collectionコンポーネント描画時 |

### 計算ロジック

- 新規エントリURL: `getNewEntryUrl(collectionName)` + filterTermがある場合`?path=${filterTerm}`を付加

## データベース操作仕様

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| コレクション一覧取得 | Redux Store: state.collections | SELECT | コレクション定義の参照 |
| エントリ一覧取得 | Redux Store: state.entries | SELECT | エントリデータの参照 |
| ソート状態取得 | Redux Store: state.entries (sort) | SELECT | ソート設定の参照 |
| フィルタ状態取得 | Redux Store: state.entries (filter) | SELECT | フィルタ設定の参照 |
| グループ状態取得 | Redux Store: state.entries (group) | SELECT | グループ設定の参照 |
| ビュースタイル取得 | Redux Store: state.entries (viewStyle) | SELECT | 表示スタイル設定の参照 |

### テーブル別操作詳細

#### Redux Store: state.collections

| 操作 | 項目（キー） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | collections.get(name) | URLパラメータのnameで取得 | name未指定時はcollections.first() |
| SELECT | collection.get('name') | コレクション名 | サイドバーリンク生成に使用 |
| SELECT | collection.get('label') | コレクション表示名 | ヘッダー表示に使用 |
| SELECT | collection.get('create') | 新規作成可否 | true/false |
| SELECT | collection.get('hide') | 非表示設定 | trueの場合サイドバーに非表示 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | コレクション未存在 | URLパラメータのコレクション名が存在しない | 最初のコレクションにフォールバック |
| - | エントリ読み込み失敗 | バックエンドAPIからのエントリ取得失敗 | EntriesCollectionコンポーネント内でisFetchingフラグによるローディング表示 |

### リトライ仕様

エントリ読み込みの自動リトライは実装されていない。画面のリフレッシュ（コレクション切り替え）で再読み込みが行われる。

## トランザクション仕様

本機能は読み取り専用のため、トランザクション管理は不要。

## パフォーマンス要件

- カーソルベースのページネーションにより、大量エントリの段階的読み込みを実現
- Waypointコンポーネントによるスクロールベースの遅延読み込み

## セキュリティ考慮事項

- 認証済みユーザーのみがコレクション画面にアクセス可能
- コレクション設定によるアクセス制御（hide, create プロパティ）

## 備考

- Collectionコンポーネントはreact-reduxのconnect HOCとreact-polyglotのtranslate HOCで包まれている
- mergePropsで、onSortClick・onFilterClick・onGroupClick・onChangeViewStyleがバインドされる
- コレクション間のナビゲーションはReact Routerのナビゲーションで実現

---

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

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

### 推奨読解順序

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

Redux Storeのコレクション・エントリ状態構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | collections.ts (reducer) | `packages/decap-cms-core/src/reducers/collections.ts` | コレクションのImmutable.js Map構造。selectSortableFields, selectViewFilters, selectViewGroups関数 |
| 1-2 | entries.ts (reducer) | `packages/decap-cms-core/src/reducers/entries.ts` | selectEntriesSort, selectEntriesFilter, selectEntriesGroup, selectViewStyle関数 |

**読解のコツ**: Immutable.jsのMapとListで状態が管理されている。`get`/`getIn`メソッドでネストされた値にアクセスする。

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

Collection.jsがこの機能のエントリーポイント。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Collection.js | `packages/decap-cms-core/src/components/Collection/Collection.js` | Collectionクラスコンポーネント。mapStateToProps（157-187行目）でRedux Stateからpropsを生成。mergeProps（196-206行目）でアクションをバインド |

**主要処理フロー**:
1. **157-187行目**: mapStateToPropsでURLパラメータとRedux Stateからコンポーネントpropsを生成
2. **104-110行目**: newEntryUrlの生成ロジック（create設定チェック + filterTerm付加）
3. **116-153行目**: render()でSidebar + CollectionMain（CollectionTop + CollectionControls + エントリ表示）を描画
4. **63-67行目**: renderEntriesCollection()でEntriesCollectionを描画
5. **70-78行目**: renderEntriesSearch()でEntriesSearchを描画

#### Step 3: サイドバーコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Sidebar.js | `packages/decap-cms-core/src/components/Collection/Sidebar.js` | コレクション一覧をナビゲーションリンクとして描画。**85-110行目**: renderLink()でネストコレクション/通常コレクションの分岐 |
| 3-2 | CollectionTop.js | `packages/decap-cms-core/src/components/Collection/CollectionTop.js` | **50-73行目**: コレクション見出し・説明・新規作成ボタンの描画 |
| 3-3 | CollectionControls.js | `packages/decap-cms-core/src/components/Collection/CollectionControls.js` | **23-56行目**: ViewStyleControl, SortControl, FilterControl, GroupControlの統合 |

#### Step 4: エントリ一覧コンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | EntriesCollection.js | `packages/decap-cms-core/src/components/Collection/Entries/EntriesCollection.js` | **83-103行目**: componentDidMountでloadEntries()を実行。**175-199行目**: filterNestedEntries()でネストコレクションのフィルタリング |
| 4-2 | EntryListing.js | `packages/decap-cms-core/src/components/Collection/Entries/EntryListing.js` | **39-48行目**: Waypointによるページネーション制御。**97-113行目**: 単一コレクションのカード描画 |

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

```
Collection.js (メインコンポーネント)
    |
    +-- Sidebar.js
    |   +-- CollectionSearch.js (検索有効時)
    |   +-- NestedCollection.js (nested設定時)
    |   +-- SidebarNavLink (通常コレクション)
    |
    +-- CollectionTop.js
    |   +-- CollectionTopNewButton (create設定時)
    |
    +-- CollectionControls.js
    |   +-- ViewStyleControl.js
    |   +-- SortControl.js
    |   +-- FilterControl.js
    |   +-- GroupControl.js
    |
    +-- EntriesCollection.js (通常モード)
    |   +-- Entries.js
    |       +-- EntryListing.js
    |           +-- EntryCard.js
    |
    +-- EntriesSearch.js (検索結果モード)
```

### データフロー図

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

URLパラメータ         mapStateToProps                    DOM描画
(name, searchTerm,       |                               (サイドバー +
 filterTerm)             v                                メインエリア)
        |            Redux State参照
        +---------> (collections, entries,               ユーザー操作
                     sort, filter, group)               (ソート/フィルタ/
                         |                                グループ変更)
                         v
                    Collectionコンポーネント描画
                         |
                    +----+----+----+
                    |    |    |    |
                 Sidebar Top Ctrl Entries
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Collection.js | `packages/decap-cms-core/src/components/Collection/Collection.js` | ソース | メインコレクションコンポーネント |
| Sidebar.js | `packages/decap-cms-core/src/components/Collection/Sidebar.js` | ソース | サイドバーナビゲーション |
| CollectionTop.js | `packages/decap-cms-core/src/components/Collection/CollectionTop.js` | ソース | コレクション見出し・新規作成ボタン |
| CollectionControls.js | `packages/decap-cms-core/src/components/Collection/CollectionControls.js` | ソース | ソート・フィルタ・グループ・ビュースタイル制御統合 |
| EntriesCollection.js | `packages/decap-cms-core/src/components/Collection/Entries/EntriesCollection.js` | ソース | エントリ一覧表示 |
| EntriesSearch.js | `packages/decap-cms-core/src/components/Collection/Entries/EntriesSearch.js` | ソース | 検索結果表示 |
| EntryListing.js | `packages/decap-cms-core/src/components/Collection/Entries/EntryListing.js` | ソース | エントリカード一覧・ページネーション |
| EntryCard.js | `packages/decap-cms-core/src/components/Collection/Entries/EntryCard.js` | ソース | 個別エントリカード |
| CollectionSearch.js | `packages/decap-cms-core/src/components/Collection/CollectionSearch.js` | ソース | コレクション検索フォーム |
| NestedCollection.js | `packages/decap-cms-core/src/components/Collection/NestedCollection.js` | ソース | ネストコレクションツリー表示 |
| ViewStyleControl.js | `packages/decap-cms-core/src/components/Collection/ViewStyleControl.js` | ソース | リスト/グリッド表示切替 |
| SortControl.js | `packages/decap-cms-core/src/components/Collection/SortControl.js` | ソース | ソート制御UI |
| FilterControl.js | `packages/decap-cms-core/src/components/Collection/FilterControl.js` | ソース | フィルタ制御UI |
| GroupControl.js | `packages/decap-cms-core/src/components/Collection/GroupControl.js` | ソース | グループ制御UI |
| collectionViews.js | `packages/decap-cms-core/src/constants/collectionViews.js` | ソース | VIEW_STYLE_LIST, VIEW_STYLE_GRID定数 |
