# 画面設計書 11-404 Not Found画面

## 概要

本ドキュメントは、Decap CMS における404 Not Found画面の画面設計書である。存在しないURLルートにアクセスした場合に表示されるフォールバックページの仕様を定義する。

### 本画面の処理概要

404 Not Found画面は、ユーザーがDecap CMS内の存在しないURLにアクセスした際に表示されるエラーページである。React RouterのSwitchコンポーネント内で、いずれのルート定義にもマッチしなかった場合のフォールバックとして機能する。

**業務上の目的・背景**：CMSの管理画面において、ユーザーが手動でURLを入力したり、古いブックマークからアクセスしたりした場合に、存在しないページへのアクセスを適切にハンドリングする必要がある。本画面は、ユーザーにアクセスしたページが存在しないことを明確に伝え、混乱を防止する役割を担う。SPAアーキテクチャにおいて、サーバーサイドの404レスポンスではなくクライアントサイドで404状態を検知・表示する仕組みである。

**画面へのアクセス方法**：React Router（HashHistory）のSwitchコンポーネント内で、定義済みルート（`/collections/:name`、`/workflow`、`/search/:searchTerm`等）のいずれにもマッチしなかったURLパスにアクセスした場合に自動的に表示される。例えば、`#/invalid-path` のような存在しないハッシュルートにアクセスした場合が該当する。ただし、本画面はユーザーが認証済みの場合にのみ表示される（未認証の場合はログイン画面が表示される）。

**主要な操作・処理内容**：
1. 「Not Found」（日本語：「ページが見つかりません」）というヘッダーテキストを表示する
2. テキストはreact-polyglotによるローカライズに対応しており、設定されたロケールに応じた言語で表示される

**画面遷移**：
- この画面に遷移してくる経路：定義済みルートに一致しない任意のURLパスへのアクセス
- この画面から遷移できる画面：ヘッダーナビゲーション（Content、Workflow、Mediaリンク）を介して各画面に遷移可能。ブラウザの戻るボタンで前の画面に戻ることも可能

**権限による表示制御**：権限やロールによる表示制御は存在しない。ただし、認証済みユーザーのみがこの画面を見ることができる（未認証の場合はログイン画面にリダイレクトされる）。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 3 | ルーティング | 主機能 | React RouterのSwitch最後のフォールバックルートとしてNotFoundPageコンポーネントを表示 |
| 70 | CMS UIローカライズ | 補助機能 | 404ページのヘッダーテキストのローカライズ表示。`t('app.notFoundPage.header')`による多言語対応 |

## 画面種別

エラー（情報表示）

## URL/ルーティング

- パス: `*`（上記定義済みルートに一致しない全てのパス）
- ルーティング定義箇所: `App.js` 252行目 `<Route component={NotFoundPage} />`
- React RouterのSwitchコンポーネント内の最後に配置されたフォールバックルート
- HashHistoryを使用しているため、実際のURLは `/#/任意の不正パス` の形式

## 入出力項目

本画面にはユーザー入力項目は存在しない。

| 項目名 | 入出力 | 型 | 説明 |
|--------|--------|------|------|
| t（翻訳関数） | 入力（props） | Function | react-polyglotの翻訳関数。HOC `translate()` により注入される |

## 表示項目

| 項目名 | 表示内容 | データソース | 備考 |
|--------|----------|-------------|------|
| ヘッダーテキスト | 「Not Found」（英語）/「ページが見つかりません」（日本語） | ロケールファイル `t('app.notFoundPage.header')` | h2タグで表示 |
| ヘッダーナビゲーション | Content / Workflow / Media リンク | Appコンポーネント内のHeaderコンポーネント | 認証済みの場合はHeaderが表示される |

## イベント仕様

### 1-ページ表示

本画面固有のイベントは存在しない。画面表示はReact Routerのルートマッチング処理によりフォールバックとして自動的にレンダリングされる。

- **トリガー**: 定義済みルートに一致しないURLへのアクセス
- **処理内容**: NotFoundPageコンポーネントのレンダリング。NotFoundContainerスタイルドコンポーネント（`margin: 28px 18px`）内にh2要素でローカライズされたテキストを表示
- **遷移元**: ブラウザのアドレスバーからの直接入力、外部リンク、古いブックマーク等

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

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

本画面にはデータベースへの操作は存在しない。

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| なし | - | - | 本画面は静的な表示のみで、データベース操作を行わない |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容（英語） | メッセージ内容（日本語） | 表示条件 |
|-------------|------|----------------------|----------------------|---------|
| app.notFoundPage.header | 情報 | Not Found | ページが見つかりません | 常時表示 |

## 例外処理

- **翻訳関数の欠如**: `translate()` HOCにより`t`関数がpropsとして必ず注入されるため、通常は発生しない。PropTypesにより`t`は`isRequired`として定義されている（NotFoundPage.js 20行目）
- **ロケールキーの未定義**: ロケールファイルに `app.notFoundPage.header` キーが定義されていない場合、react-polyglotはキー文字列をそのまま表示する

## 備考

- 本画面は非常にシンプルなコンポーネントであり、テキストの表示のみを行う静的ページである
- NotFoundPageコンポーネントはReactの関数コンポーネントとして実装されている（全23行のシンプルなファイル）
- `@emotion/styled` を使用したスタイルドコンポーネント `NotFoundContainer` でマージン（`lengths.pageMargin` = `28px 18px`）が設定されている
- `decap-cms-ui-default` パッケージの `lengths` 定数を使用して、他画面と一貫したマージンを適用している
- ヘッダーコンポーネント（Header）はAppコンポーネント側で描画されるため、NotFoundPage自体にはナビゲーション要素は含まれない
- `prop-types` パッケージを使用してランタイムの型チェックを行っている

---

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

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

### 推奨読解順序

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

本画面で扱うデータ構造は非常にシンプルで、主にローカライズ用のテキストデータのみである。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.js（英語ロケール） | `packages/decap-cms-locales/src/en/index.js` | 32-34行目: `app.notFoundPage` オブジェクト内の `header: 'Not Found'` を確認 |
| 1-2 | index.js（日本語ロケール） | `packages/decap-cms-locales/src/ja/index.js` | 32-34行目: `app.notFoundPage` オブジェクト内の `header: 'ページが見つかりません'` を確認 |
| 1-3 | styles.js | `packages/decap-cms-ui-default/src/styles.js` | 96行目: `pageMargin: '28px 18px'` の定数定義を確認 |

**読解のコツ**: Decap CMSではreact-polyglotライブラリを使用してi18nを実現している。`translate()` HOCでラップしたコンポーネントには自動的に`t`関数がpropsとして注入され、`t('key.path')` でロケールファイルの値を取得できる。ドット区切りのキーパスはネストされたオブジェクトの階層に対応する。

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

本画面のエントリーポイントはApp.jsのルーティング定義である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | App.js | `packages/decap-cms-core/src/components/App/App.js` | 252行目: `<Route component={NotFoundPage} />` - Switchの最後にフォールバックルートとして配置されている点を確認 |

**主要処理フロー**:
1. **147-258行目（renderメソッド）**: config読込中・エラー・未認証のチェックを順に行い、いずれにも該当しない場合にルーティング定義を描画
2. **161-163行目**: `config === null` の場合はnullを返す（初期化前ガード）
3. **165-167行目**: `config.error` がある場合はエラー画面を表示
4. **169-171行目**: `config.isFetching` がtrueの場合はローディング画面を表示
5. **173-175行目**: `user == null` の場合は認証画面を表示
6. **198-253行目（Switch内）**: 各ルート定義を順番にマッチングし、いずれにも一致しない場合に252行目のフォールバックルートが適用される
7. **252行目**: `path` プロパティなしの `<Route component={NotFoundPage} />` により、全てのURLにマッチするフォールバックとして機能

#### Step 3: NotFoundPageコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | NotFoundPage.js | `packages/decap-cms-core/src/components/App/NotFoundPage.js` | コンポーネント全体（23行）を確認。translate() HOCでラップされた関数コンポーネント |

**主要処理フロー**:
- **1-5行目**: React、@emotion/styled、react-polyglot（translate）、decap-cms-ui-default（lengths）、PropTypesのインポート
- **7-9行目**: NotFoundContainerスタイルドコンポーネントの定義。`lengths.pageMargin`（= `28px 18px`）を使用
- **11-16行目**: NotFoundPage関数コンポーネント。propsから`t`関数を受け取り、`t('app.notFoundPage.header')`で翻訳テキストをh2要素内に表示
- **19-21行目**: PropTypesによる型定義（`t: PropTypes.func.isRequired`）
- **23行目**: `translate()(NotFoundPage)` でHOCラップしたものをデフォルトエクスポート

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

```
App.js (render) [147行目]
    |
    +-- Switch (React Router) [198行目]
    |       |
    |       +-- Route "/" --> Redirect to defaultPath [199行目]
    |       +-- RouteInCollection "/collections/:name" --> Collection [214行目]
    |       +-- RouteInCollection "/collections/:name/new" --> Editor [220行目]
    |       +-- RouteInCollection "/collections/:name/entries/*" --> Editor [225行目]
    |       +-- RouteInCollection "/collections/:name/search/:searchTerm" --> Collection [230行目]
    |       +-- RouteInCollection "/collections/:name/filter/:filterTerm*" --> Collection [235行目]
    |       +-- Route "/search/:searchTerm" --> Collection [240行目]
    |       +-- RouteInCollection "/edit/:name/:entryName" --> Redirect [244行目]
    |       +-- ... (その他のルート定義)
    |       |
    |       +-- Route (フォールバック) --> NotFoundPage [252行目]  <-- 本画面
    |               |
    |               +-- translate() HOC (react-polyglot)
    |                       |
    |                       +-- NotFoundContainer (styled.div) [7-9行目]
    |                               |
    |                               +-- h2 [14行目]
    |                                       |
    |                                       +-- t('app.notFoundPage.header')
    |                                               |
    |                                               +-- ロケールファイル参照
    |
    +-- Header (認証済みの場合) [183-195行目]
    +-- MediaLibrary (useMediaLibraryがtrueの場合) [254行目]
```

### データフロー図

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

URLパス          ───▶ React Router Switch         ───▶ ルートマッチング
(定義外のパス)          (App.js 198-253行目)              結果: マッチなし
                                |
                                v
                    フォールバックRoute           ───▶ NotFoundPageレンダリング
                    (App.js 252行目)
                                |
                                v
ロケール設定     ───▶ translate() HOC              ───▶ t関数をpropsに注入
(config.locale)        (react-polyglot)
                                |
                                v
ロケールファイル  ───▶ t('app.notFoundPage.header') ───▶ "Not Found" / "ページが見つかりません"
(en/ja/etc)                                              (h2要素として描画)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| NotFoundPage.js | `packages/decap-cms-core/src/components/App/NotFoundPage.js` | ソース | 404画面のメインコンポーネント（全23行） |
| App.js | `packages/decap-cms-core/src/components/App/App.js` | ソース | ルーティング定義。252行目でNotFoundPageをフォールバックルートとして配置 |
| Header.js | `packages/decap-cms-core/src/components/App/Header.js` | ソース | ヘッダーナビゲーション。App.jsで認証済みの場合に表示 |
| history.ts | `packages/decap-cms-core/src/routing/history.ts` | ソース | HashHistoryの生成（`createHashHistory()`）とナビゲーション関数の定義 |
| styles.js | `packages/decap-cms-ui-default/src/styles.js` | ソース | UI共通スタイル定数。`lengths.pageMargin`（96行目: `'28px 18px'`）の定義元 |
| index.js（英語） | `packages/decap-cms-locales/src/en/index.js` | ロケール | 英語ロケールファイル。33行目: `header: 'Not Found'` |
| index.js（日本語） | `packages/decap-cms-locales/src/ja/index.js` | ロケール | 日本語ロケールファイル。33行目: `header: 'ページが見つかりません'` |
