# 画面設計書 3-コレクション一覧画面

## 概要

本ドキュメントは、Decap CMS のコレクション一覧画面（Collection）の画面設計書である。認証後のメイン画面として、選択されたコレクションのエントリ一覧を表示し、ソート・フィルター・グループ・表示スタイルの切り替え等の操作を提供する。

### 本画面の処理概要

**業務上の目的・背景**：コンテンツ管理者が管理対象のコンテンツ（エントリ）を一覧表示し、目的のエントリを素早く見つけて編集・作成等の操作に遷移するための中核画面である。config.ymlに定義されたコレクション（フォルダ型・ファイル型）ごとにエントリを管理し、サイドバーでのコレクション切り替え、検索、ネストコレクションのツリー表示をサポートする。

**画面へのアクセス方法**：ログイン成功後に自動的にリダイレクトされるデフォルト画面。ルートURL（`/`）へのアクセス時は最初の非非表示コレクションにリダイレクトされる（App.js `getDefaultPath`関数、行50-57）。ヘッダーの「Content」リンク、サイドバーでのコレクション選択、エディタの「戻る」リンクからも遷移する。

**主要な操作・処理内容**：
1. サイドバーでコレクションを選択し、エントリ一覧を切り替える
2. エントリ一覧をソート（昇順・降順）する
3. エントリ一覧にフィルターを適用する
4. エントリ一覧をグループ化して表示する
5. 表示スタイル（リスト/グリッド）を切り替える
6. 「New」ボタンから新規エントリ作成画面に遷移する
7. エントリをクリックしてエントリ編集画面に遷移する
8. 検索フィールドからコレクション内検索を実行する

**画面遷移**：
- 遷移元：ログイン画面（認証成功後）、PKCE認証画面（認証成功後）、エントリ編集画面（戻るリンク）、エントリ新規作成画面（戻るリンク）、ワークフロー画面（Contentリンク）
- 遷移先：エントリ編集画面（エントリ選択）、エントリ新規作成画面（新規作成ボタン）、コレクション検索結果画面（検索実行）、コレクションフィルター画面（ネストコレクションフィルター）、メディアライブラリ画面（ヘッダーMediaボタン）、ワークフロー画面（ヘッダーWorkflowリンク）

**権限による表示制御**：コレクション設定の`create`フラグがfalseの場合、新規作成ボタンは非表示となる（Collection.js 行104）。`hide: true`のコレクションはサイドバーに表示されない（Sidebar.js 行128）。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 7 | エントリ読み込み | 主機能 | 選択されたコレクションのエントリ一覧をバックエンドから読み込み。カーソルベースのページネーションに対応 |
| 13 | エントリソート | 補助機能 | ソートコントロールによるエントリ一覧の昇降順ソート。sortByFieldアクションを実行 |
| 14 | エントリフィルタ | 補助機能 | フィルターコントロールによるエントリ一覧のフィルタリング。filterByFieldアクションを実行 |
| 15 | エントリグルーピング | 補助機能 | グループコントロールによるエントリ一覧のグルーピング表示。groupByFieldアクションを実行 |
| 22 | コレクション表示 | 主機能 | サイドバーとメインエリアでのコレクション表示 |
| 23 | ネストコレクション | 補助機能 | サイドバーでのツリー構造のネストコレクション表示 |
| 24 | ビュースタイル切替 | 補助機能 | エントリ一覧の表示スタイル（リスト/グリッド）の切り替え |
| 33 | エントリ検索 | 補助機能 | サイドバーのCollectionSearchによるコレクション内検索 |
| 73 | ヘッダー | 補助機能 | ヘッダーからのメディアライブラリオープン・新規エントリ作成・ワークフロー画面遷移・ログアウト |
| 8 | エントリ作成・編集 | 遷移先機能 | 新規エントリ作成ボタン押下時にエントリ新規作成画面を開く |

## 画面種別

一覧

## URL/ルーティング

| パス | 説明 |
|------|------|
| `/collections/:name` | コレクション一覧画面のメインルート |
| `/` | 最初の非非表示コレクションにリダイレクト |

## 入出力項目

### 入力項目

| 項目名 | 項目ID | 型 | 必須 | 説明 |
|--------|--------|-----|------|------|
| 検索クエリ | searchTerm | text | No | CollectionSearchコンポーネントの検索入力フィールド |

### URLパラメータ

| パラメータ名 | 型 | 説明 |
|-------------|-----|------|
| name | string | コレクション名。config.ymlで定義されたコレクション識別子 |

## 表示項目

| 項目名 | 表示条件 | 説明 |
|--------|---------|------|
| サイドバー | 常時 | コレクションリスト、検索フィールド、ネストコレクションツリー |
| コレクションラベル | 常時 | 選択中コレクションのlabel |
| コレクション説明 | collection.descriptionが設定されている場合 | コレクションの説明文 |
| 新規作成ボタン | collection.create === true | 「New {collectionLabel}」ボタン |
| ソートコントロール | sortableFieldsが1件以上 | ソートフィールド選択と昇降順切り替え |
| フィルターコントロール | viewFiltersが1件以上 | フィルター条件の選択 |
| グループコントロール | viewGroupsが1件以上 | グルーピング条件の選択 |
| 表示スタイル切替 | 常時 | リスト/グリッドの切り替えボタン |
| エントリ一覧 | 常時 | EntriesCollectionコンポーネントによるエントリカード/リスト表示 |
| ヘッダー | 常時 | Content/Workflow/Mediaリンク、Quick Addドロップダウン、SettingsDropdown |

## イベント仕様

### 1-コレクション選択（サイドバー）

1. サイドバーのNavLinkをクリック（Sidebar.js 行100-107）
2. React Routerにより`/collections/:name`に遷移
3. mapStateToPropsで新しいコレクションのデータを取得（Collection.js 行157-187）
4. EntriesCollectionコンポーネントがエントリ一覧を再描画

### 2-新規作成ボタン押下

1. CollectionTopの「New {collectionLabel}」ボタンをクリック（CollectionTop.js 行61-65）
2. React Router Linkにより`/collections/:name/new`に遷移
3. filterTermが存在する場合は`?path={filterTerm}`がクエリパラメータとして付加（Collection.js 行105-110）

### 3-ソート実行

1. SortControlでソートフィールドと方向を選択
2. `onSortClick(key, direction)`が呼ばれる（Collection.js 行200-201）
3. `sortByField(collection, key, direction)`アクションがdispatchされる
4. Redux stateのentries.sortが更新され、エントリ一覧が再描画

### 4-フィルター適用

1. FilterControlでフィルター条件を選択
2. `onFilterClick(filter)`が呼ばれる（Collection.js 行202）
3. `filterByField(collection, filter)`アクションがdispatchされる
4. Redux stateのentries.filterが更新され、エントリ一覧が再描画

### 5-グループ化

1. GroupControlでグルーピング条件を選択
2. `onGroupClick(group)`が呼ばれる（Collection.js 行203）
3. `groupByField(collection, group)`アクションがdispatchされる
4. Redux stateのentries.groupが更新され、エントリ一覧が再描画

### 6-表示スタイル切替

1. ViewStyleControlでリスト/グリッドを選択
2. `onChangeViewStyle(viewStyle)`が呼ばれる（Collection.js 行204）
3. `changeViewStyle(viewStyle)`アクションがdispatchされる
4. Redux stateのentries.viewStyleが更新され、表示スタイルが変更

### 7-検索実行

1. CollectionSearchの検索フィールドにクエリを入力して送信
2. `searchCollections(query, collection)`アクションが実行（Sidebar.js 行123）
3. 検索結果画面（`/collections/:name/search/:searchTerm`または`/search/:searchTerm`）に遷移

### 8-エントリ選択

1. エントリ一覧からエントリをクリック
2. React Routerにより`/collections/:name/entries/:slug`に遷移
3. エントリ編集画面が表示される

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| コレクション選択 | Redux State (entries) | SELECT | コレクションのエントリ一覧を取得 |
| ソート実行 | Redux State (entries.sort) | UPDATE | ソート条件を更新 |
| フィルター適用 | Redux State (entries.filter) | UPDATE | フィルター条件を更新 |
| グループ化 | Redux State (entries.group) | UPDATE | グルーピング条件を更新 |
| 表示スタイル切替 | Redux State (entries.viewStyle) | UPDATE | 表示スタイルを更新 |

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

#### Redux State: entries

| 操作 | 項目（キー） | 更新値・取得条件 | 備考 |
|-----|-------------|-----------------|------|
| UPDATE | sort | OrderedMap({ fieldName, direction }) | sortByFieldアクションで更新 |
| UPDATE | filter | Map({ fieldName, fieldValue, active }) | filterByFieldアクションで更新 |
| UPDATE | group | Map({ fieldName, pattern }) | groupByFieldアクションで更新 |
| UPDATE | viewStyle | 'VIEW_STYLE_LIST' / 'VIEW_STYLE_GRID' | changeViewStyleアクションで更新 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|---------|
| collection.sidebar.collections | 情報 | サイドバー見出し「Collections」 | 常時 |
| collection.collectionTop.newButton | 情報 | 新規作成ボタン「New {collectionLabel}」 | create=trueのコレクション |
| app.header.content | 情報 | ヘッダー「Content」リンク | 常時 |
| app.header.workflow | 情報 | ヘッダー「Workflow」リンク | Editorial Workflow有効時 |
| app.header.media | 情報 | ヘッダー「Media」リンク | showMediaButton=true時 |
| app.header.quickAdd | 情報 | ヘッダー「Quick Add」ドロップダウン | create=trueのコレクションが1件以上 |

## 例外処理

| 例外条件 | 処理内容 | 画面表示 |
|---------|---------|---------|
| 存在しないコレクション名をURLに指定 | デフォルトコレクションにリダイレクト | RouteInCollectionでリダイレクト（App.js 行59-69） |
| 非表示コレクションが全てのコレクション | Error例外をスロー | 「Could not find a non hidden collection」エラー |
| エントリ読み込み失敗 | エラーハンドリングはバックエンド層で処理 | エラー通知が表示される |

## 備考

- サイドバーの幅は250px固定（Sidebar.js）、メインコンテンツはpadding-left: 280pxで配置（Collection.js 行33）。
- ネストコレクションはNestedCollectionコンポーネントでツリー表示される（Sidebar.js 行87-96）。
- 検索機能はconfig.searchがfalseの場合に無効化される（Collection.js 行159）。
- Quick Addドロップダウンは`create: true`のコレクションのみ表示（Header.js 行186-188）。
- ヘッダーはposition: stickyで固定表示される（Header.js 行35-36）。

---

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

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

### 推奨読解順序

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

コレクションとエントリのRedux state構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Collection.js | `packages/decap-cms-core/src/components/Collection/Collection.js` | mapStateToProps（行157-187）でRedux stateからどのデータを取得しているか |
| 1-2 | collections.js (reducer) | `packages/decap-cms-core/src/reducers/collections.js` | selectSortableFields, selectViewFilters, selectViewGroupsの定義 |

**読解のコツ**: Immutable.jsのMap/OrderedMapが多用されているため、`.get()`, `.getIn()`, `.filter()`, `.toList()`等のAPIに注意。

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

App.jsのルーティングからCollectionコンポーネントへの遷移を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | App.js | `packages/decap-cms-core/src/components/App/App.js` | ルーティング定義（行198-253）。RouteInCollectionでのコレクション存在チェック |

**主要処理フロー**:
1. **行199**: `/`から`defaultPath`（最初の非非表示コレクション）にリダイレクト
2. **行214-219**: `/collections/:name`でCollectionコンポーネントを描画
3. **行50-57**: `getDefaultPath`で最初の非非表示コレクションパスを生成

#### Step 3: Collectionコンポーネントの描画を理解する

Collection.jsのrenderメソッドと各子コンポーネントの関係を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Collection.js | `packages/decap-cms-core/src/components/Collection/Collection.js` | renderメソッド（行80-154）の構造。isSearchResultsによる表示切り替え |
| 3-2 | Sidebar.js | `packages/decap-cms-core/src/components/Collection/Sidebar.js` | サイドバーの描画。コレクションリストとNestedCollection |
| 3-3 | CollectionTop.js | `packages/decap-cms-core/src/components/Collection/CollectionTop.js` | コレクション見出しと新規作成ボタン |
| 3-4 | CollectionControls.js | `packages/decap-cms-core/src/components/Collection/CollectionControls.js` | ソート・フィルター・グループ・表示スタイルのコントロール |

**主要処理フロー**:
- **行104-110**: newEntryUrlの生成。create=trueの場合のみ、filterTermの付加
- **行116-153**: Sidebar + CollectionMain（CollectionTop + CollectionControls + Entries）の構造

#### Step 4: Reduxアクションとstateの更新を理解する

ソート・フィルター等のアクションによるstate更新フローを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | entries.ts (actions) | `packages/decap-cms-core/src/actions/entries.ts` | sortByField, filterByField, changeViewStyle, groupByFieldアクション |

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

```
App.js (render)
    |
    +-- Header
    |       +-- Content NavLink -> /collections/:name
    |       +-- Workflow NavLink -> /workflow
    |       +-- Media Button -> openMediaLibrary
    |       +-- Quick Add Dropdown -> createNewEntry
    |       +-- SettingsDropdown -> logoutUser
    |
    +-- Route /collections/:name -> Collection
            |
            +-- Sidebar
            |       +-- CollectionSearch -> searchCollections
            |       +-- SidebarNavList
            |       |       +-- NavLink -> /collections/:collectionName
            |       |       +-- NestedCollection (ネストコレクション用)
            |
            +-- CollectionMain
                    +-- CollectionTop
                    |       +-- CollectionLabel
                    |       +-- NewButton -> /collections/:name/new
                    |
                    +-- CollectionControls
                    |       +-- SortControl -> sortByField
                    |       +-- FilterControl -> filterByField
                    |       +-- GroupControl -> groupByField
                    |       +-- ViewStyleControl -> changeViewStyle
                    |
                    +-- EntriesCollection
                            +-- エントリカード/リスト
```

### データフロー図

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

URLパラメータ        ──▶  mapStateToProps                    ──▶  画面表示
(:name)                   |                                       |
                          +-- collections.get(name)               +-- Sidebar
                          +-- selectEntriesSort                   +-- CollectionTop
                          +-- selectViewFilters                   +-- CollectionControls
                          +-- selectViewGroups                    +-- EntriesCollection
                          +-- selectViewStyle

ソート操作          ──▶  sortByField(collection, key, dir)  ──▶  entries.sort更新
フィルター操作      ──▶  filterByField(collection, filter)  ──▶  entries.filter更新
グループ操作        ──▶  groupByField(collection, group)    ──▶  entries.group更新
スタイル変更        ──▶  changeViewStyle(viewStyle)         ──▶  entries.viewStyle更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| 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` | ソース | ソート・フィルター等のコントロール |
| CollectionSearch.js | `packages/decap-cms-core/src/components/Collection/CollectionSearch.js` | ソース | 検索フィールドコンポーネント |
| NestedCollection.js | `packages/decap-cms-core/src/components/Collection/NestedCollection.js` | ソース | ネストコレクションのツリー表示 |
| EntriesCollection.js | `packages/decap-cms-core/src/components/Collection/Entries/EntriesCollection.js` | ソース | エントリ一覧の描画 |
| Header.js | `packages/decap-cms-core/src/components/App/Header.js` | ソース | アプリケーションヘッダー |
| App.js | `packages/decap-cms-core/src/components/App/App.js` | ソース | ルーティング定義 |
| entries.ts | `packages/decap-cms-core/src/actions/entries.ts` | ソース | エントリ関連のReduxアクション |
