Bunchee
Back to Blog

แก้ปัญหา Charts และ Number Cards ไม่แสดงใน Frappe Workspace

เรียนรู้สาเหตุที่ Charts และ Number Cards ไม่แสดงใน Frappe Workspace และวิธีแก้ปัญหา Label Matching ที่นักพัฒนาหลายคนไม่รู้

แก้ปัญหา Charts และ Number Cards ไม่แสดงใน Frappe Workspace

ปัญหาที่นักพัฒนา Frappe หลายคนเจอคือ Charts และ Number Cards ไม่แสดงใน Workspace แม้ว่าจะตั้งค่าทุกอย่างถูกต้อง ข้อมูลมีใน Database และ API ก็ Return ค่าถูก บทความนี้จะเปิดเผยสาเหตุที่ซ่อนอยู่

Critical Discovery: Label Matching Requirement

ปัญหา

Charts และ Number Cards ไม่ Render ใน Workspace แม้ว่า:

  • Database มีข้อมูลถูกต้อง
  • API Return ค่าถูก
  • Content JSON Reference ชื่อถูก
  • Permissions ถูกต้อง

สาเหตุ

Frappe's Workspace Block Rendering Code (frappe/public/js/frappe/views/workspace/blocks/block.js) ใช้ Label Matching ในการหา Chart และ Number Card Data:

// block.js lines 8-14
make(block, block_name, widget_type = block) {
    let block_data = this.config.page_data[block + "s"].items.find((obj) => {
        return (
            frappe.utils.unescape_html(obj.label) == frappe.utils.unescape_html(__(block_name))
        );
    });
    if (!block_data) return false;  // Silent failure!

Key Insight: Code เปรียบเทียบ obj.label กับ block_name (ซึ่งมาจาก chart_name หรือ number_card_name ใน Content JSON) ถ้าไม่ตรงกัน Block จะ Return false และไม่ Render อะไรเลย - แบบ Silent

วิธีแก้ไข

กฎสำคัญ

ใน Workspace Child Tables, ฟิลด์ label ต้องตรงกับ chart_name หรือ number_card_name เป๊ะ

ผิด (ไม่ Render)

"number_cards": [
  {
    "label": "Active Items",
    "number_card_name": "App Active Items"
  }
]

ปัญหา: "Active Items" ≠ "App Active Items"

ถูก (Render)

"number_cards": [
  {
    "label": "App Active Items",
    "number_card_name": "App Active Items"
  }
]

Label และ number_card_name ตรงกัน

โครงสร้าง Workspace JSON ที่ถูกต้อง

Charts

"charts": [
  {
    "chart_name": "Sales Trend",
    "label": "Sales Trend"  // ต้องตรงกับ chart_name
  }
]

Number Cards

"number_cards": [
  {
    "number_card_name": "Active Items",
    "label": "Active Items"  // ต้องตรงกับ number_card_name
  }
]

Content JSON

[
  {"type": "header", "data": {"text": "<span class=\"h4\"><b>Dashboard</b></span>", "col": 12}},
  {"type": "chart", "data": {"chart_name": "Sales Trend", "col": 6}},
  {"type": "number_card", "data": {"number_card_name": "Active Items", "col": 2}}
]

Shortcuts

"shortcuts": [
  {
    "label": "Sales Order",
    "link_to": "Sales Order",
    "type": "DocType",
    "color": "Blue",
    "doc_view": "List"
  }
]

Links (Card Sections)

"links": [
  {
    "label": "Masters",
    "type": "Card Break",
    "link_count": 8
  },
  {
    "label": "Item",
    "link_to": "Item",
    "link_type": "DocType",
    "type": "Link",
    "onboard": 1
  }
]

Debugging Steps

Step 1: ตรวจสอบ Label Matching

# ใน bench console
ws = frappe.get_doc('Workspace', 'Your Workspace')

print("Number Cards Label Check:")
for card in ws.number_cards:
    match = card.label == card.number_card_name
    status = "✓" if match else "✗ MISMATCH"
    print(f"  {status} label: '{card.label}' vs name: '{card.number_card_name}'")

print("\nCharts Label Check:")
for chart in ws.charts:
    match = chart.label == chart.chart_name
    status = "✓" if match else "✗ MISMATCH"
    print(f"  {status} label: '{chart.label}' vs name: '{chart.chart_name}'")

Step 2: Clear All Caches

frappe.cache().flushall()
frappe.clear_cache()
frappe.clear_document_cache('Workspace', 'Your Workspace')
frappe.db.commit()

หรือใช้ Bash:

bench --site your-site.local clear-cache
redis-cli FLUSHALL

Step 3: Browser-Side Debugging

  1. Hard Refresh: Cmd+Shift+R (Mac) หรือ Ctrl+Shift+R (Windows)
  2. Incognito Mode: ทดสอบใน Private Browsing เพื่อ Bypass Browser Cache
  3. DevTools Console: ตรวจสอบ JavaScript Errors (F12)

Common Pitfalls

| ปัญหา | อาการ | วิธีแก้ | |-------|-------|--------| | Label Mismatch | Charts/Cards ไม่ Render, ไม่มี Error | Match label กับ chart_name/number_card_name | | Module Mismatch | บาง Elements หายไป | ใช้ Module เดียวกันสำหรับ Workspace, Charts, Cards | | Permission Issues | Charts/Cards ว่างเปล่า | Set is_public: 1 บน Charts และ Cards | | Cache Not Cleared | แสดงข้อมูลเก่า | Clear Cache ทั้ง Server และ Browser |

ตัวอย่าง Workspace JSON ที่สมบูรณ์

{
  "doctype": "Workspace",
  "name": "Sales Dashboard",
  "label": "Sales Dashboard",
  "module": "Selling",
  "icon": "chart-line",
  "public": 1,
  "content": "[{\"type\":\"header\",\"data\":{\"text\":\"<b>Sales Overview</b>\",\"col\":12}},{\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Sales\",\"col\":3}},{\"type\":\"chart\",\"data\":{\"chart_name\":\"Monthly Sales\",\"col\":6}}]",
  "charts": [
    {
      "chart_name": "Monthly Sales",
      "label": "Monthly Sales"
    }
  ],
  "number_cards": [
    {
      "number_card_name": "Total Sales",
      "label": "Total Sales"
    }
  ],
  "shortcuts": [
    {
      "label": "Sales Order",
      "link_to": "Sales Order",
      "type": "DocType",
      "doc_view": "List"
    }
  ]
}

Best Practices

  1. Always Match Labels - label = chart_name = number_card_name
  2. Use Workspace Manager - อย่าแก้ไข Database โดยตรง
  3. Version Control JSON - Track Workspace Definitions ใน Git
  4. Clear Cache After Sync - Flush Redis หลัง Update Workspace
  5. Test in Incognito - ตรวจสอบ Changes โดยไม่มี Browser Cache
  6. Consistent Naming - ใช้ Prefix เดียวกัน เช่น App_ สำหรับทุก Elements

สรุป

ปัญหา Charts และ Number Cards ไม่แสดงใน Frappe Workspace มักเกิดจาก Label Mismatch กฎง่ายๆ คือ:

Label ต้องตรงกับ chart_name/number_card_name เป๊ะ!

Frappe ไม่แสดง Error เมื่อหาไม่เจอ ทำให้ Debug ยาก แต่เมื่อรู้สาเหตุแล้ว การแก้ไขก็ตรงไปตรงมา

เอกสารอ้างอิง