frappe-impl-workspace について
Frappe Desk の Workspace ページを作成・カスタマイズするためのワークフローリファレンスです。Frappe アプリ開発者や管理者向けに、ブロック配置、アクセス制御、バージョン差分、依存要素を含むアプリへの同梱方法を説明します。
主な機能
- 01UI またはコードでワークスペースを作成
- 02グリッド上でダッシュボードブロックを配置
- 03モジュールとロールのアクセス設定
- 04チャート、ショートカット、数値カードの管理
- 05ワークスペースのエクスポートと依存要素の同梱
活用シーン
- 01指標付きのモジュールダッシュボードを構築
- 02ロール制限付きのワークスペース表示を作成
- 03Frappe アプリと共にワークスペースページを配布
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ impertio-studio/ frappe_claude_skill_package --skill frappe-impl-workspaceインストール後、Claude Code で/frappe-impl-workspaceを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/anti-patterns.mdshipping-with-app.mdworkspace-components.md詳細
Frappe ワークスペースの実装ワークフロー
ワークスペースページを作成・カスタマイズするためのステップごとのワークフローです。ワークスペースは、Frappe Desk のブロックベースのダッシュボード/ナビゲーションページです。
バージョン: v14/v15/v16(バージョン固有の機能は注記しています)
クイックリファレンス
| 概念 | 説明 |
|---|---|
| ワークスペース | 12 列のグリッドレイアウトを持つブロックベースのページ |
| パブリックワークスペース | 権限を持つすべてのユーザーに表示されます。編集には Workspace Manager ロールが必要です |
| プライベートワークスペース | 「My Workspaces」に表示されるユーザーごとのダッシュボードです。Desk User であれば誰でも作成できます |
| コンテンツフィールド | ブロックレイアウトを格納する JSON 配列 |
| 子テーブル | 6 つのテーブル:charts、shortcuts、links、quick_lists、number_cards、custom_blocks |
| モジュールとの関連付け | 主なアクセス制御メカニズム |
主な判断:何が必要ですか?
NEED A WORKSPACE?
│
├─► Default DocType landing page?
│ └─► NO workspace needed — Frappe auto-generates list views
│
├─► Custom dashboard for a module?
│ └─► Create PUBLIC Workspace (Workspace Manager role required)
│
├─► Personal dashboard for a user?
│ └─► Create PRIVATE Workspace (appears under "My Workspaces")
│
└─► Navigation link in sidebar?
└─► type="Link" (internal) or type="URL" (external)
ADDING COMPONENTS?
│
├─► Key metrics (counts, sums) → Number Cards
├─► Trend / time-series data → Dashboard Charts
├─► Quick navigation links → Shortcuts
├─► Grouped link categories → Link Cards (Card Break + Links)
├─► Custom HTML/JS content → Custom HTML Blocks
└─► Recent record lists → Quick Lists
Workspace DocType の構造
主なフィールド
| フィールド | 型 | 目的 |
|---|---|---|
label | Data | サイドバーに表示する名前 |
title | Data | ページタイトル(デフォルトでは label) |
module | Link → Module Def | アクセス制御のためにワークスペースをモジュールに関連付けます |
parent_page | Link → Workspace | サイドバーで別のワークスペースの下にネストします |
icon | Data | サイドバーアイコン(例:"chart-line") |
type | Select | Workspace / Link / URL(v15 以降) |
sequence_id | Int | サイドバーでの表示順 |
content | JSON | ブロックレイアウトを表す JSON 配列 |
for_user | Data | 設定されている場合、そのユーザー専用のプライベートワークスペースになります |
roles | Table → Has Role | ロールベースのアクセス制限 |
app | Data | 所有アプリの識別子(v15 以降) |
indicator_color | Color | サイドバーのインジケーターのドット(v15 以降) |
子テーブル(合計 6 つ)
| 子テーブル | DocType | 目的 |
|---|---|---|
charts | Workspace Chart | Dashboard Chart への参照 |
shortcuts | Workspace Shortcut | DocType/Report/Page/URL のショートカット |
links | Workspace Link | グループ化されたナビゲーションリンク |
quick_lists | Workspace Quick List | 最近のレコード一覧 |
number_cards | Workspace Number Card | 指標カードへの参照 |
custom_blocks | Workspace Custom Block | HTML ブロックへの参照 |
重要:
contentJSON と子テーブルは必ず同期させる必要があります。必ず Workspace Builder UI またはプログラム API を使用してください。子テーブルを更新せずにcontentJSON を手動で編集してはいけません。references/anti-patterns.mdを参照してください。
Content JSON の形式
content フィールドは JSON 配列です。各要素は 12 列グリッド内のブロックを表します。
[
{
"id": "unique-block-id",
"type": "header",
"data": {"text": "Overview", "level": 4, "col": 12}
},
{
"id": "unique-block-id-2",
"type": "chart",
"data": {
"chart_name": "Sales Trends",
"col": 12
}
},
{
"id": "unique-block-id-3",
"type": "number_card",
"data": {
"number_card_name": "Open Orders",
"col": 4
}
},
{
"id": "unique-block-id-4",
"type": "shortcut",
"data": {
"shortcut_name": "New Sales Order",
"col": 4
}
},
{
"id": "unique-block-id-5",
"type": "spacer",
"data": {"col": 12}
}
]
ブロックタイプ
| タイプ | data フィールド | 説明 |
|---|---|---|
header | text, level, col | セクション見出し(h3/h4/h5) |
chart | chart_name, col | Dashboard Chart ドキュメントを参照します |
number_card | number_card_name, col | Number Card ドキュメントを参照します |
shortcut | shortcut_name, col | Workspace Shortcut 子レコードを参照します |
card | card_name, col | リンクをグループ化するためのカード区切り |
quick_list | quick_list_name, col | DocType の最近のレコード |
custom_block | custom_block_name, col | Custom HTML Block ドキュメントを参照します |
text | body, col | リッチテキスト/Markdown ブロック |
spacer | col | 空の垂直スペース |
onboarding | onboarding_name, col | モジュールのオンボーディングウィジェット |
colの値は 1~12 である必要があり、グリッド列の幅を表します。同じ行のブロックの合計は 12 以下である必要があります。
実装ワークフロー
ワークフロー 1:UI からパブリックワークスペースを作成する
/app/workspaceに移動し、+ New Workspace をクリックします- Label(サイドバーに表示されます)、Module、Icon を設定します
- Workspace Builder を使ってブロックをドラッグ&ドロップします
- コンポーネントを追加します:Charts、Number Cards、Shortcuts、Links
- Save をクリックすると、権限を持つユーザーのサイドバーにワークスペースが表示されます
- 開発者モードでは、JSON がアプリのディレクトリに自動エクスポートされます
ワークフロー 2:プログラムでワークスペースを作成する
import frappe
import json
workspace = frappe.new_doc("Workspace")
workspace.label = "Project Dashboard"
workspace.module = "Projects"
workspace.icon = "project"
workspace.type = "Workspace"
workspace.sequence_id = 10
# Build content blocks
workspace.content = json.dumps([
{
"id": frappe.generate_hash(length=10),
"type": "header",
"data": {"text": "Project Overview", "level": 4, "col": 12}
},
{
"id": frappe.generate_hash(length=10),
"type": "number_card",
"data": {"number_card_name": "Active Projects", "col": 4}
},
{
"id": frappe.generate_hash(length=10),
"type": "chart",
"data": {"chart_name": "Project Status", "col": 12}
}
])
# Add child table entries (MUST match content JSON)
workspace.append("number_cards", {
"number_card_name": "Active Projects"
})
workspace.append("charts", {
"chart_name": "Project Status"
})
# Role restrictions (optional)
workspace.append("roles", {"role": "Projects Manager"})
workspace.insert(ignore_permissions=True)
frappe.db.commit()
contentJSON をプログラムで設定する場合は、必ず対応する子テーブルの行も追加してください。
ワークフロー 3:先に関連ドキュメントを作成する
ワークスペースにコンポーネントを追加する前に、参照先のドキュメントを作成してください。
数値カード:
card = frappe.new_doc("Number Card")
card.label = "Active Projects"
card.document_type = "Project"
card.function = "Count"
card.filters_json = json.dumps([["Project", "status", "=", "Open"]])
card.is_public = 1
card.insert(ignore_permissions=True)
ダッシュボードチャート:
chart = frappe.new_doc("Dashboard Chart")
chart.chart_name = "Project Status"
chart.chart_type = "Group By"
chart.document_type = "Project"
chart.group_by_type = "Count"
chart.group_by_based_on = "status"
chart.type = "Donut"
chart.is_public = 1
chart.insert(ignore_permissions=True)
ショートカット: ショートカットは Workspace の子テーブルのエントリーであり、単独のドキュメントではありません。
workspace.append("shortcuts", {
"label": "New Project",
"type": "DocType",
"link_to": "Project",
"color": "Blue",
"format": "{} Active",
"stats_filter": json.dumps([["Project", "status", "=", "Open"]])
})
コンポーネントの詳細については、references/workspace-components.md を参照してください。
権限モデル
3 層のアクセス制御
Layer 1: Module Access (PRIMARY)
└─► User must have access to the workspace's module
└─► Controlled via "Module Def" and user's "Block Modules" list
Layer 2: Role Restrictions (OPTIONAL)
└─► workspace.roles child table
└─► If populated: ONLY users with listed roles see the workspace
└─► If empty: ALL users with module access see it
Layer 3: Workspace Manager Role
└─► Required to create/edit PUBLIC workspaces
└─► NOT required for private workspaces
ルール
- パブリックワークスペースには必ず
moduleを設定してください。設定しない場合、すべての Desk ユーザーに表示されます - 機密性の高いダッシュボード(財務、人事)には、必ずロール制限を追加してください
- アプリに同梱するワークスペースには、
for_userを絶対に設定しないでください。プライベートワークスペースが作成されます
バージョン間の違い
| 機能 | v14 | v15 | v16 |
|---|---|---|---|
| Workspace Builder UI | 基本機能 | 再設計(ドラッグ&ドロップのグリッド) | 段階的な修正 |
type フィールド(Workspace/Link/URL) | 利用不可 | 追加 | 利用可能 |
app フィールド | 利用不可 | 追加 | 利用可能 |
indicator_color | 利用不可 | 追加 | 利用可能 |
| 名前の重複防止 | 手動 | 手動 | 自動で重複を解消 |
| ウェルカムヘッダーの設定 | 利用不可 | 利用不可 | 追加 |
| Content JSON 形式 | 同じ | 同じ | 同じ |
移行に関する注意事項
- v14 → v15:Workspace Builder UI が大幅に変更されました。既存の JSON コンテンツには引き続き互換性があります
- v15 → v16:フィールドが若干追加されました。ワークスペース構造に破壊的変更はありません
- メジャーバージョンのアップグレード後は、必ずワークスペースの表示をテストしてください
カスタムアプリへのワークスペースの同梱
ディレクトリ構成
myapp/
└── mymodule/
└── workspace/
└── my_workspace/
└── my_workspace.json
エクスポート手順
- Developer Mode(
frappe.conf.developer_mode = 1)を有効にします - Workspace Builder UI でワークスペースを作成または編集します
- 保存すると、Frappe が上記のアプリディレクトリに自動エクスポートします
- JSON ファイルをバージョン管理にコミットします
重要:依存関係も同梱してください
ワークスペースの JSON だけでは不十分です。次のものも必ず同梱してください。
| コンポーネント | 同梱方法 |
|---|---|
| 数値カード | hooks.py のフィクスチャ、または myapp/fixtures/ |
| ダッシュボードチャート | hooks.py のフィクスチャ、または myapp/fixtures/ |
| カスタム HTML ブロック | hooks.py のフィクスチャ、または myapp/fixtures/ |
| リンクされたレポート | レポートのディレクトリ構成によって同梱済み |
| リンクされたページ | ページのディレクトリ構成によって同梱済み |
# hooks.py
fixtures = [
{"dt": "Number Card", "filters": [["module", "=", "My Module"]]},
{"dt": "Dashboard Chart", "filters": [["module", "=", "My Module"]]},
{"dt": "Custom HTML Block", "filters": [["name", "in", ["My Block"]]]},
]
同梱方法の詳細については、references/shipping-with-app.md を参照してください。
よくあるパターン
パターン 1:KPI を含むモジュールダッシュボード
[Header: "Key Metrics"]
[Number Card: Open Orders (col=3)] [Number Card: Revenue (col=3)]
[Number Card: Pending (col=3)] [Number Card: Overdue (col=3)]
[Spacer]
[Header: "Trends"]
[Chart: Monthly Revenue (col=12)]
[Header: "Quick Access"]
[Shortcut: New Order (col=4)] [Shortcut: Reports (col=4)] [Shortcut: Settings (col=4)]
パターン 2:ロールベースのワークスペース
# Sales Manager sees full dashboard; Sales User sees limited view
# Option A: Two separate workspaces with different role restrictions
# Option B: One workspace — use Number Card/Chart permissions to filter
# Option A implementation:
ws_manager = frappe.get_doc({"doctype": "Workspace", "label": "Sales Management", ...})
ws_manager.append("roles", {"role": "Sales Manager"})
ws_user = frappe.get_doc({"doctype": "Workspace", "label": "Sales Overview", ...})
ws_user.append("roles", {"role": "Sales User"})
パターン 3:サイドバーの階層構造
# Parent workspace
parent = frappe.get_doc({"doctype": "Workspace", "label": "CRM", "module": "CRM"})
# Child workspaces (nested in sidebar)
child = frappe.get_doc({
"doctype": "Workspace",
"label": "Lead Pipeline",
"module": "CRM",
"parent_page": "CRM" # References parent workspace label
})
参照ファイル
| ファイル | 内容 |
|---|---|
references/workspace-components.md | 数値カード、ダッシュボードチャート、ショートカット、カスタムブロック — API 全般 |
references/shipping-with-app.md | JSON 形式、フィクスチャ、モジュール構成、インストールフック |
references/anti-patterns.md | よくあるワークスペースの誤りとその回避方法 |