Skip to content

refactor: replace DesignDrawer+DashboardEditor with inline config panels in DashboardView#810

Merged
hotlong merged 5 commits intomainfrom
copilot/refactor-dashboard-attribute-panel
Feb 24, 2026
Merged

refactor: replace DesignDrawer+DashboardEditor with inline config panels in DashboardView#810
hotlong merged 5 commits intomainfrom
copilot/refactor-dashboard-attribute-panel

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Feb 23, 2026

Dashboard design mode rendered the full DashboardEditor (widget card list, toolbar, preview) inside a right-side DesignDrawer, violating the "main area = WYSIWYG preview, right panel = property config" pattern used by ListView/PageDesigner.

Changes

  • DashboardView.tsx — Replace DesignDrawer + lazy DashboardEditor with inline DashboardConfigPanel / WidgetConfigPanel from @object-ui/plugin-dashboard, matching the ListView ViewConfigPanel pattern:

    • No widget selected → DashboardConfigPanel (columns, gap, refresh, theme)
    • Widget selected → WidgetConfigPanel (title, type, data binding, layout, appearance)
    • Add-widget toolbar rendered in main area header (edit mode only)
    • Config panels use standard ConfigPanelRenderer save/discard footer
    • Auto-save wired through useAdapter().update()
    • Config draft stabilized via configVersion counter pattern (matching ViewConfigPanel's stableActiveView approach) — prevents useConfigDraft from resetting the draft on every live field change, ensuring Save/Discard footer works correctly
    • Widget delete via headerExtra delete button in WidgetConfigPanel header — deletion deselects the widget, switches to dashboard config, and persists to backend
    • Live preview updates via onFieldChange with proper type handling (e.g. refreshInterval → number)
  • WidgetConfigPanel.tsx — Added headerExtra prop to support custom header actions (e.g. delete button) via ConfigPanelRenderer

  • Integration tests — Rewrote DashboardDesignInteraction (10 tests) and DashboardViewSelection (11 tests) to verify config panel switching, selection sync, widget deletion, live preview stability, and backend persistence against the new architecture

  • ROADMAP.md — Added Phase 8 entry

{/* Right-side config panel — switches based on selection */}
{selectedWidget ? (
  <WidgetConfigPanel
    key={selectedWidgetId}
    open={configPanelOpen}
    onClose={handleCloseConfigPanel}
    config={widgetConfig}
    onSave={handleWidgetConfigSave}
    onFieldChange={handleWidgetFieldChange}
    headerExtra={
      <Button variant="ghost" onClick={() => removeWidget(selectedWidgetId!)}>
        <Trash2 />
      </Button>
    }
  />
) : (
  <DashboardConfigPanel
    open={configPanelOpen}
    onClose={handleCloseConfigPanel}
    config={dashboardConfig}
    onSave={handleDashboardConfigSave}
    onFieldChange={handleDashboardFieldChange}
  />
)}

DashboardEditor remains available for standalone use (e.g. DashboardDesignPage at /design/dashboard/:name). 175 dashboard-related tests pass across 18 test files.

Original prompt

This section details on the original issue you should resolve

<issue_title>重构仪表盘设计模式右侧为固定属性面板/配置页,与ListView一致</issue_title>
<issue_description># 问题

目前设计模式下右侧 DesignDrawer 渲染的并非真正的属性配置页,而是"DashboardEditor"(包含卡片列表、工具栏、预览等),严重背离了 Airtable/Notion"主区预览 + 右侧表单属性面板"最佳实践,导致:

  • 右侧操作混乱,属性编辑、卡片列表混在一起、无法专注于 widget 配置
  • 无法实现所见即所得、实时属性配置联动
  • 代码重复,未复用已有成熟的 ConfigPanelRenderer、WidgetConfigPanel 架构

目标

  • 向 ListView/PageDesigner/WorkflowDesigner 等看齐,右侧属性 Drawer 必须始终只做属性配置
  • 未选中任何 widget 时,显示 DashboardConfigPanel(dashboard 级总属性)
  • 选中任一 widget 时,右侧固定切换为 WidgetConfigPanel(所有可编辑属性、布局、数据源、样式…)
  • 配置项和业务 schema 严格对齐,支持协议扩展
  • 不再在右侧 drawer 中做 widget 卡片的 preview 或列表,主区才��所见即所得 preview
  • 指定属性表单的 sticky/save/discard/footer 全面回归 ConfigPanelRenderer 通用实现

技术建议

  • 复用 packages/plugin-dashboard/src/DashboardConfigPanel.tsx、WidgetConfigPanel.tsx
  • drawer 内容结构见 ListViewConfigPanel 参考实现
  • 编辑模式下,主区与右侧属性随选中联动,属性改动主区实时反映

验收标准

  • 所有属性配置体验与 ListView/PageDesigner 完全统一,且和 schema/协议保持同步
  • 新/老模式无割裂,所有面板配置支持自动保存/撤销,还原等所有 ConfigPanelRenderer 标准交互

详见相关 issue #808</issue_description>

Comments on the Issue (you are @copilot in this section)


🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

@vercel
Copy link
Copy Markdown

vercel Bot commented Feb 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
objectui Ready Ready Preview, Comment Feb 23, 2026 5:01pm
objectui-demo Ready Ready Preview, Comment Feb 23, 2026 5:01pm
objectui-storybook Ready Ready Preview, Comment Feb 23, 2026 5:01pm

Request Review

…els in DashboardView

Replace the right-side drawer that contained the full DashboardEditor (widget
list, toolbar, preview) with inline DashboardConfigPanel / WidgetConfigPanel,
following the same pattern as ListView.

- No widget selected: shows DashboardConfigPanel (dashboard-level properties)
- Widget selected: shows WidgetConfigPanel (widget configuration)
- Add-widget toolbar moved to the main area header
- Config panels use standard ConfigPanelRenderer with save/discard footer
- Main area remains WYSIWYG preview via DashboardRenderer

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
…ROADMAP

Addresses code review feedback:
- Guard base.layout with fallback to empty object in unflattenWidgetConfig
- Add Phase 8 to ROADMAP documenting the inline config panel refactor

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Copilot AI changed the title [WIP] Refactor dashboard design pattern for consistent attribute panel refactor: replace DesignDrawer+DashboardEditor with inline config panels in DashboardView Feb 23, 2026
Copilot AI requested a review from hotlong February 23, 2026 16:25
@hotlong
Copy link
Copy Markdown
Collaborator

hotlong commented Feb 23, 2026

@copilot 仔细评估是否完整实现的任务中要求的所有功能

Critical fixes for complete ListView-parity:

1. Stabilize config references using configVersion counter pattern
   (matching ViewConfigPanel's stableActiveView approach) — prevents
   useConfigDraft from resetting the draft on every field change,
   so Save/Discard footer works correctly.

2. Add widget delete button via WidgetConfigPanel's new headerExtra
   prop — renders a Trash2 icon in the config panel header.

3. Fix dashboard config live preview — properly convert refreshInterval
   to number when updating editSchema.

4. Add headerExtra prop to WidgetConfigPanel component.

5. Add tests for widget deletion, live field change preview, and
   config panel header actions.

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
…comments

- Restore rowHeight/showDescription/theme in handleDashboardConfigSave
  (prevents data loss on save)
- Simplify dashboardConfig memo dep to [configVersion] alone
- Improve comments explaining the configVersion stabilization pattern
- Update ROADMAP with widget delete and config stabilization entries

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Feb 23, 2026

@copilot 仔细评估是否完整实现的任务中要求的所有功能

完整评估后发现了 3 个关键缺失,已在 2e0c98806b5967 中修复:

1. Config draft 重置 Bug(最关键)
onFieldChange 更新 editSchema → 重新计算 widgetConfig/dashboardConfiguseConfigDraft 重置 draft → isDirty 永远无法为 true → Save/Discard footer 完全失效。
→ 修复:引入 configVersion 计数器做 memo 依赖(对标 ViewConfigPanel 的 stableActiveView 模式),仅在 save/add 等显式操作时递增。

2. Widget 删除能力丢失
老 DashboardEditor 有 remove 按钮,重构后丢失了。
→ 修复:给 WidgetConfigPanel 新增 headerExtra prop,在 DashboardView 中传入 Trash2 删除按钮,删除后自动取消选中并持久化。

3. Dashboard config save 属性丢失
handleDashboardConfigSave 遗漏了 rowHeight/showDescription/theme,会导致保存时数据丢失。
→ 修复:完整保留所有 config 字段。

新增 5 个测试覆盖:widget 删除、删除后切回 dashboard config、删除持久化、onFieldChange 实时预览不重置面板。全部 175 个 dashboard 相关测试通过。

@hotlong hotlong marked this pull request as ready for review February 24, 2026 00:35
Copilot AI review requested due to automatic review settings February 24, 2026 00:35
@hotlong hotlong merged commit 6bd658c into main Feb 24, 2026
5 checks passed
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors Console dashboard “design mode” to follow the consistent ObjectUI pattern: WYSIWYG preview in the main area with a right-side, schema-driven property/config panel (instead of rendering the full DashboardEditor inside a drawer).

Changes:

  • DashboardView now renders inline DashboardConfigPanel / WidgetConfigPanel, adds an add-widget toolbar, supports widget delete, and stabilizes config drafts via a configVersion pattern.
  • WidgetConfigPanel gains a headerExtra slot to support header actions (e.g., delete).
  • Console integration tests are rewritten to validate selection → panel switching, live preview updates, deletion, and persistence; ROADMAP updated.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
packages/plugin-dashboard/src/WidgetConfigPanel.tsx Adds headerExtra passthrough to ConfigPanelRenderer for custom header actions.
apps/console/src/components/DashboardView.tsx Replaces DesignDrawer/DashboardEditor edit UX with inline config panels + live preview and persistence wiring.
apps/console/src/tests/DashboardViewSelection.test.tsx Updates selection-sync integration tests for new inline config panel architecture.
apps/console/src/tests/DashboardDesignInteraction.test.tsx Updates design interaction tests for inline panels, toolbar, and widget deletion.
ROADMAP.md Adds Phase 8 entry for the inline config panel refactor.

Comment on lines +338 to +342
title={`Add ${label}`}
>
<Plus className="h-3 w-3" />
<Icon className="h-3 w-3" />
</button>
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The add-widget toolbar buttons are icon-only and rely on the title attribute for description. title is not a reliable accessible name for screen readers. Add an aria-label (e.g., “Add Bar Chart”) or include visually-hidden text inside the button so the controls are accessible.

Copilot uses AI. Check for mistakes.
onClick={() => removeWidget(selectedWidgetId!)}
className="h-7 w-7 p-0 text-destructive hover:text-destructive"
data-testid="widget-delete-button"
title="Delete widget"
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The delete button in the widget config panel header is icon-only. Add an explicit accessible name (e.g., aria-label="Delete widget" or a <span className="sr-only">…</span>), since title alone is not consistently announced by assistive tech.

Suggested change
title="Delete widget"
title="Delete widget"
aria-label="Delete widget"

Copilot uses AI. Check for mistakes.
Comment on lines +43 to +46
{ type: 'pie', label: 'Pie Chart', Icon: PieChart },
{ type: 'table', label: 'Table', Icon: Table2 },
{ type: 'grid', label: 'Grid', Icon: LayoutGrid },
];
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The add-widget palette includes a grid widget type, but WidgetConfigPanel's type select options (in plugin-dashboard) don’t include grid. This can lead to the widget type field displaying as an unknown value or being impossible to reselect after adding a grid widget. Consider aligning the palette and the widget type options (either add grid to the config panel options, or remove it from the palette if it isn’t supported here).

Copilot uses AI. Check for mistakes.
Comment on lines +214 to +218
rowHeight: config.rowHeight,
refreshInterval: Number(config.refreshInterval) || 0,
title: config.title,
showDescription: config.showDescription,
theme: config.theme,
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The DashboardConfigPanel fields showDescription (and potentially theme) are being persisted onto the dashboard schema as top-level properties, but the dashboard rendering logic uses schema.header.showDescription to control description visibility. As a result, toggling “Show description” won’t affect the preview/rendered output. Map this config to schema.header.showDescription (creating/updating header) and ensure the view header uses that value for rendering.

Copilot uses AI. Check for mistakes.
Comment on lines 322 to 325
@@ -85,9 +325,27 @@ export function DashboardView({ dataSource }: { dataSource?: any }) {
)}
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The page header is rendered from metadata (dashboard.label / dashboard.description) rather than the live previewSchema. This means edits made in the config panel (e.g., title / show/hide description) won’t be reflected in the header while editing, and may appear to have no effect. Consider sourcing the displayed title/description from previewSchema (or explicitly documenting that these fields don’t affect the console header).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

重构仪表盘设计模式右侧为固定属性面板/配置页,与ListView一致

3 participants