From 58670836ed58423ab81a1679bd917a5c0977b925 Mon Sep 17 00:00:00 2001 From: os-zhuang Date: Thu, 11 Jun 2026 16:44:19 +0500 Subject: [PATCH] fix(app-todo): re-model count-only dashboard tables as ListViews (#1719) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `overdue_tasks_table` and `due_today` dashboard widgets were `type: 'table'` widgets bound to the `task_metrics` dataset selecting only the `task_count` count measure with no dimensions — a single summary row, not the per-record listing they intended. `objectstack validate`/`build` flagged both with the `table-count-only` warning. Per ADR-0017, model record listings as object-bound ListViews surfaced through app navigation (the same fix class as objectstack-ai/templates#27): - views: add a `due_today` grid ListView on `todo_task` filtered to `due_date = {today}` and incomplete; the `overdue` ListView already existed from the ADR-0021 Phase 2 report conversion. - app: point the existing "Overdue" / "Due Today" nav items at the views via `viewName`. - dashboard: drop the two table widgets; counts stay covered by the `overdue_tasks` / `completed_today` metric widgets. `objectstack validate` and `build` now pass with no warnings. Co-Authored-By: Claude Fable 5 --- examples/app-todo/src/apps/todo.app.ts | 4 +-- .../app-todo/src/dashboards/task.dashboard.ts | 25 +++++-------------- examples/app-todo/src/views/task.view.ts | 25 +++++++++++++++++++ 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/examples/app-todo/src/apps/todo.app.ts b/examples/app-todo/src/apps/todo.app.ts index f83b06a71d..d96d2df1a2 100644 --- a/examples/app-todo/src/apps/todo.app.ts +++ b/examples/app-todo/src/apps/todo.app.ts @@ -21,8 +21,8 @@ export const TodoApp = App.create({ children: [ { id: 'nav_all_tasks', type: 'object', objectName: 'todo_task', label: 'All Tasks', icon: 'list' }, { id: 'nav_my_tasks', type: 'object', objectName: 'todo_task', label: 'My Tasks', icon: 'user-check' }, - { id: 'nav_overdue', type: 'object', objectName: 'todo_task', label: 'Overdue', icon: 'alert-circle' }, - { id: 'nav_today', type: 'object', objectName: 'todo_task', label: 'Due Today', icon: 'calendar' }, + { id: 'nav_overdue', type: 'object', objectName: 'todo_task', viewName: 'overdue', label: 'Overdue', icon: 'alert-circle' }, + { id: 'nav_today', type: 'object', objectName: 'todo_task', viewName: 'due_today', label: 'Due Today', icon: 'calendar' }, { id: 'nav_upcoming', type: 'object', objectName: 'todo_task', label: 'Upcoming', icon: 'calendar-plus' }, ] }, diff --git a/examples/app-todo/src/dashboards/task.dashboard.ts b/examples/app-todo/src/dashboards/task.dashboard.ts index 51c2f4750a..826159db4f 100644 --- a/examples/app-todo/src/dashboards/task.dashboard.ts +++ b/examples/app-todo/src/dashboards/task.dashboard.ts @@ -115,24 +115,11 @@ export const TaskDashboard: Dashboard = { options: { showLegend: true } }, - // Row 4: Tables - { - id: 'overdue_tasks_table', - title: 'Overdue Tasks', - type: 'table', - filter: { is_overdue: true, is_completed: false }, - dataset: 'task_metrics', - values: ['task_count'], - layout: { x: 0, y: 10, w: 6, h: 4 }, - }, - { - id: 'due_today', - title: 'Due Today', - type: 'table', - filter: { due_date: '{today}', is_completed: false }, - dataset: 'task_metrics', - values: ['task_count'], - layout: { x: 6, y: 10, w: 6, h: 4 }, - }, + // The former Row 4 count-only `table` widgets (`overdue_tasks_table`, + // `due_today`) rendered a single summary row, not the record listing + // they intended (#1719). Those listings live as ListViews on + // `todo_task` (`overdue`, `due_today` — ADR-0017), reachable from the + // app navigation; the `overdue_tasks` / `completed_today` metric + // widgets above keep the counts. ], }; diff --git a/examples/app-todo/src/views/task.view.ts b/examples/app-todo/src/views/task.view.ts index 2c17738e00..25eaa2c842 100644 --- a/examples/app-todo/src/views/task.view.ts +++ b/examples/app-todo/src/views/task.view.ts @@ -11,6 +11,12 @@ const data = { provider: 'object' as const, object: 'todo_task' }; * (no grouping / aggregation), which is a ListView concern, not analytics. It * is converted here to an `overdue` grid view filtered to incomplete, overdue * tasks — replacing the report entirely. + * + * Issue #1719: the dashboard's `overdue_tasks_table` / `due_today` widgets + * were count-only `table` widgets on the `task_metrics` dataset — a single + * summary row, not the record listing they intended. They are re-modelled + * here as the `overdue` / `due_today` views, surfaced via app navigation; + * the dashboard keeps the counts on its `metric` widgets. */ export const TaskViews = defineView({ list: { @@ -46,5 +52,24 @@ export const TaskViews = defineView({ ], sort: [{ field: 'due_date', order: 'asc' }], }, + + // Replaces the dashboard's count-only `due_today` table widget (#1719). + due_today: { + label: 'Due Today', + type: 'grid', + data, + columns: [ + { field: 'subject' }, + { field: 'priority' }, + { field: 'status' }, + { field: 'owner' }, + { field: 'category' }, + ], + filter: [ + { field: 'due_date', operator: 'equals', value: '{today}' }, + { field: 'is_completed', operator: 'equals', value: false }, + ], + sort: [{ field: 'priority', order: 'desc' }], + }, }, });