# 機能設計書 48-エディタツールバー

## 概要

本ドキュメントは、Decap CMSのエディタツールバー（`EditorToolbar`コンポーネント）の機能設計を記述する。保存・公開・ステータス変更・削除・複製・デプロイプレビューなどの操作ボタンを提供するツールバーUIである。

### 本機能の処理概要

**業務上の目的・背景**：エントリ編集画面において、コンテンツの保存・公開・ステータス変更などの主要操作を一箇所にまとめたツールバーが必要である。EditorToolbarは、シンプルモードとワークフローモードの両方に対応し、エントリの状態（新規/既存/未公開/公開済み）に応じて適切なコントロールを動的に表示する。

**機能の利用シーン**：エントリ編集画面（画面No.6）およびエントリ新規作成画面（画面No.7）の上部に常に表示される。コレクション一覧への戻りリンク、保存状態表示、操作ボタン群、デプロイプレビュー、ユーザー設定ドロップダウンを含む。

**主要な処理内容**：
1. コレクション一覧への戻りリンクと保存状態表示（保存済み/未保存）
2. シンプルモード: 公開/公開＆新規作成/公開＆複製のドロップダウン
3. ワークフローモード: 保存ボタン、ステータス変更ドロップダウン（Draft/In Review/Ready）、公開ドロップダウン
4. 既存エントリ: 公開済み表示、非公開化、複製
5. 削除ボタン表示（showDelete条件に応じて）
6. デプロイプレビューURL表示/更新ボタン
7. ユーザー設定ドロップダウン（SettingsDropdown）

**関連システム・外部連携**：デプロイプレビュー機能（No.51）と連携。

**権限による制御**：コレクション設定の`create`、`publish`、`delete`フラグで各操作ボタンの表示を制御。Open Authoring時は公開ボタンと一部削除ボタンを非表示。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 6 | エントリ編集画面 | 補助機能 | 保存・公開・ステータス変更・削除・複製操作ボタンの提供 |
| 7 | エントリ新規作成画面 | 補助機能 | 新規エントリ用の保存・公開ボタンの提供 |

## 機能種別

UI表示 / ユーザーインタラクション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| isPersisting | boolean | No | 保存中フラグ | - |
| isPublishing | boolean | No | 公開中フラグ | - |
| isUpdatingStatus | boolean | No | ステータス更新中フラグ | - |
| isDeleting | boolean | No | 削除中フラグ | - |
| onPersist | function | Yes | 保存ハンドラ | - |
| onPersistAndNew | function | Yes | 保存＆新規作成ハンドラ | - |
| onPersistAndDuplicate | function | Yes | 保存＆複製ハンドラ | - |
| showDelete | boolean | Yes | 削除ボタン表示フラグ | - |
| onDelete | function | Yes | 削除ハンドラ | - |
| onDeleteUnpublishedChanges | function | Yes | 未公開変更削除ハンドラ | - |
| onChangeStatus | function | Yes | ステータス変更ハンドラ | - |
| onPublish | function | Yes | 公開ハンドラ | - |
| unPublish | function | Yes | 非公開化ハンドラ | - |
| onDuplicate | function | Yes | 複製ハンドラ | - |
| hasChanged | boolean | No | 変更有無フラグ | - |
| hasWorkflow | boolean | No | ワークフロー有効フラグ | - |
| useOpenAuthoring | boolean | No | Open Authoringフラグ | - |
| hasUnpublishedChanges | boolean | No | 未公開変更有無フラグ | - |
| isNewEntry | boolean | No | 新規エントリフラグ | - |
| isModification | boolean | No | 既存エントリ修正フラグ | - |
| currentStatus | string | No | 現在のワークフローステータス | - |
| deployPreview | object | No | デプロイプレビュー情報 | - |
| loadDeployPreview | function | Yes | デプロイプレビュー読み込み | - |
| editorBackLink | string | Yes | 戻りリンクURL | - |
| collection | ImmutableMap | Yes | コレクション設定 | - |
| t | function | Yes | 翻訳関数 | - |

### 入力データソース

- Redux Store: エントリ状態、コレクション設定、ワークフロー設定
- 親コンポーネント（EditorInterface）: 各操作ハンドラ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ToolbarContainer | JSX.Element | ツールバー全体のUI |

### 出力先

- ブラウザDOM: ツールバーUI表示

## 処理フロー

### 処理シーケンス

```
1. componentDidMount
   └─ 既存エントリの場合: loadDeployPreview(maxAttempts: 3)
2. componentDidUpdate
   └─ 保存完了後に再度loadDeployPreview実行
3. render
   └─ ToolbarSectionBackLink: コレクション戻りリンク + 保存状態表示
   └─ ToolbarSectionMain:
       └─ hasWorkflow ? renderWorkflowControls() : renderSimpleControls()
       └─ hasWorkflow ? renderWorkflowDeployPreviewControls() : renderSimpleDeployPreviewControls()
   └─ ToolbarSectionMeta: SettingsDropdown
```

### フローチャート

```mermaid
flowchart TD
    A[EditorToolbar render] --> B{hasWorkflow?}
    B -->|Yes| C[renderWorkflowControls]
    B -->|No| D[renderSimpleControls]
    C --> E[SaveButton + StatusDropdown + PublishDropdown + DeleteButton]
    D --> F{isNewEntry or hasChanged?}
    F -->|Yes| G[renderNewEntrySimplePublishControls]
    F -->|No| H[renderExistingEntrySimplePublishControls]
    G --> I[PublishButton + Dropdown]
    H --> J[PublishedButton + DuplicateDropdown]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-48-01 | ワークフロー/シンプル分岐 | hasWorkflowでワークフローモードとシンプルモードを切り替え | render時 |
| BR-48-02 | 保存ボタン無効化 | hasChangedがfalseの場合、保存ボタンをdisabled | ワークフローモード |
| BR-48-03 | 公開可否 | collection.publishがtrueかつuseOpenAuthoringがfalseの場合に公開可能 | ワークフローモード |
| BR-48-04 | 作成可否 | collection.createがtrueの場合に「公開＆新規作成」「複製」を表示 | 両モード |
| BR-48-05 | 削除可否 | collection.deleteがtrueの場合に削除可能（デフォルトtrue） | ワークフローモード |
| BR-48-06 | デプロイプレビュー読み込み | 既存エントリのmount時と保存完了後にmaxAttempts:3で読み込み | componentDidMount/Update |
| BR-48-07 | デプロイプレビュー表示 | status==='SUCCESS'かつisFetchingがfalseの場合にリンク表示。それ以外は更新ボタン | renderDeployPreviewControls |
| BR-48-08 | ステータス変更 | Draft/Pending Review/Pending Publishの3つのステータスをドロップダウンで選択 | ワークフローモード |
| BR-48-09 | Open Authoringステータス制限 | Open Authoring時はPending Publishステータスを非表示 | ワークフローモード |
| BR-48-10 | 削除ラベル動的表示 | hasUnpublishedChanges/isModification/isNewEntryに応じて削除ボタンのラベルを動的変更 | ワークフローモード |

### 計算ロジック

- `deleteLabel`の算出: hasUnpublishedChanges && isModification ? '未公開変更を削除' : hasUnpublishedChanges && (isNewEntry || !isModification) ? '未公開エントリを削除' : '公開済みエントリを削除'

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

本機能はデータベースを操作しない。

## エラー処理

### エラーケース一覧

特筆すべきエラー処理なし。操作ハンドラは親コンポーネントに委譲される。

### リトライ仕様

デプロイプレビューの読み込みはmaxAttempts: 3で実行される。

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

フロントエンドコンポーネントのため、トランザクション制御は不要。

## パフォーマンス要件

特筆すべき要件なし。

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

- デプロイプレビューリンクは`rel="noopener noreferrer" target="_blank"`で安全に開く

## 備考

- ToolbarContainerの高さは66px、z-index: 300
- react-polyglotのtranslate()でラップされてエクスポートされる
- ステータスツールチップはDraft/Pending Review時に表示される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | EditorToolbar.js | `packages/decap-cms-core/src/components/Editor/EditorToolbar.js` | PropTypes定義（248-280行目）でコンポーネントのインターフェースを把握 |

**読解のコツ**: styled-componentsとemotion/styledが多用されている。スタイル定義（23-42行目のstyles）とボタンバリアント（167-205行目）を先に把握すると見通しが良くなる。

#### Step 2: ライフサイクルを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | EditorToolbar.js | `packages/decap-cms-core/src/components/Editor/EditorToolbar.js` | componentDidMount（282-290行目）とcomponentDidUpdate（292-297行目） |

**主要処理フロー**:
- **282-290行目**: `componentDidMount()` - 既存エントリの場合にデプロイプレビューを読み込み
- **292-297行目**: `componentDidUpdate()` - 保存完了検知（isPersisting遷移）後にデプロイプレビュー再読み込み

#### Step 3: シンプルモードのコントロール

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | EditorToolbar.js | `packages/decap-cms-core/src/components/Editor/EditorToolbar.js` | renderSimpleControls（299-315行目）、renderNewEntrySimplePublishControls（510-549行目）、renderExistingEntrySimplePublishControls（487-508行目） |

#### Step 4: ワークフローモードのコントロール

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | EditorToolbar.js | `packages/decap-cms-core/src/components/Editor/EditorToolbar.js` | renderWorkflowControls（559-623行目）、renderWorkflowStatusControls（364-407行目）、renderNewEntryWorkflowPublishControls（409-448行目） |

**主要処理フロー**:
- **559-623行目**: `renderWorkflowControls()` - SaveButton + ステータスコントロール + 公開コントロール + 削除ボタン
- **364-407行目**: `renderWorkflowStatusControls()` - Draft/In Review/Readyのドロップダウン
- **409-448行目**: `renderNewEntryWorkflowPublishControls()` - 公開/公開＆新規/公開＆複製

#### Step 5: メインrender

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | EditorToolbar.js | `packages/decap-cms-core/src/components/Editor/EditorToolbar.js` | render（640-689行目） - ToolbarContainer全体の組み立て |

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

```
EditorToolbar.render()
    |
    +-- ToolbarSectionBackLink (戻りリンク)
    |       +-- BackCollection (コレクション名)
    |       +-- BackStatusChanged / BackStatusUnchanged (保存状態)
    |
    +-- ToolbarSectionMain
    |       +-- [hasWorkflow] renderWorkflowControls()
    |       |       +-- SaveButton
    |       |       +-- renderWorkflowStatusControls()
    |       |       |       +-- StatusDropdown (Draft/Review/Ready)
    |       |       +-- renderNewEntryWorkflowPublishControls()
    |       |       +-- renderExistingEntryWorkflowPublishControls()
    |       |       +-- DeleteButton
    |       |
    |       +-- [!hasWorkflow] renderSimpleControls()
    |       |       +-- renderNewEntrySimplePublishControls()
    |       |       +-- renderExistingEntrySimplePublishControls()
    |       |       +-- DeleteButton
    |       |
    |       +-- renderDeployPreviewControls()
    |
    +-- ToolbarSectionMeta
            +-- SettingsDropdown
```

### データフロー図

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

エントリ状態       ──▶  hasWorkflow判定             ──▶  ボタン群構築
(isPersisting等)          renderSimple/Workflow            (JSX Elements)

コレクション設定   ──▶  create/publish/delete判定  ──▶  ボタン表示/非表示
(collection)              各フラグチェック                  (条件レンダリング)

デプロイプレビュー ──▶  renderDeployPreviewControls ──▶  リンク/更新ボタン
(deployPreview)           status判定                       (UI表示)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| EditorToolbar.js | `packages/decap-cms-core/src/components/Editor/EditorToolbar.js` | ソース | ツールバー本体 |
| EditorInterface.js | `packages/decap-cms-core/src/components/Editor/EditorInterface.js` | ソース | 親コンポーネント（ツールバーを含む） |
| publishModes.js | `packages/decap-cms-core/src/constants/publishModes.js` | ソース | ステータス定数 |
| EditorToolbar.spec.js | `packages/decap-cms-core/src/components/Editor/__tests__/EditorToolbar.spec.js` | テスト | ツールバーのユニットテスト |
