diff --git a/ROADMAP.md b/ROADMAP.md index 18b0fdbdd1..363dd0bc85 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -391,7 +391,53 @@ The following renames are planned for packages that implement core service contr - [ ] Real-time collaborative page editing - [ ] Page analytics โ€” page views, element interactions, user engagement -### 8.2 Studio IDE +### 8.2 Dashboard Enhancement โ€” Airtable Dashboard Parity + +> See [Airtable Dashboard Gap Analysis](content/docs/guides/airtable-dashboard-analysis.mdx) for the full evaluation and implementation examples. +> **Related Issues:** [#712](https://github.com/objectstack-ai/spec/issues/712), [#713](https://github.com/objectstack-ai/spec/issues/713), [#714](https://github.com/objectstack-ai/spec/issues/714), [objectui#585](https://github.com/objectstack-ai/objectui/issues/585), [objectui#586](https://github.com/objectstack-ai/objectui/issues/586), [objectui#587](https://github.com/objectstack-ai/objectui/issues/587), [objectui#588](https://github.com/objectstack-ai/objectui/issues/588) + +#### Phase 1: Foundation (Sprint 1-2) โ€” 2 weeks ๐Ÿ”ด + +Protocol enhancements and core component implementations for dashboard feature parity. + +**Spec Protocol Changes:** +- [ ] Add `colorVariant`, `actionUrl`, `description`, `actionType`, `actionIcon` to `DashboardWidgetSchema` ([#713](https://github.com/objectstack-ai/spec/issues/713)) +- [ ] Enhance `globalFilters` with `options`, `optionsFrom`, `defaultValue`, `scope`, `targetWidgets` ([#712](https://github.com/objectstack-ai/spec/issues/712)) +- [ ] Add `header` configuration to `DashboardSchema` with `showTitle`, `showDescription`, `actions` ([#714](https://github.com/objectstack-ai/spec/issues/714)) +- [ ] Add `pivotConfig` and `measures` array to `DashboardWidgetSchema` for multi-measure pivots ([#714](https://github.com/objectstack-ai/spec/issues/714)) + +**ObjectUI Component Implementations:** +- [ ] Implement `DashboardFilterBar` component for global filters ([objectui#588](https://github.com/objectstack-ai/objectui/issues/588)) +- [ ] Add color variants + action button support to `MetricCard` component ([objectui#587](https://github.com/objectstack-ai/objectui/issues/587)) +- [ ] Add description + action button to widget headers ([objectui#586](https://github.com/objectstack-ai/objectui/issues/586)) + +**Total Effort:** ~7.5 days + +#### Phase 2: Advanced Widgets (Sprint 3-4) โ€” 2 weeks ๐ŸŸก + +Advanced widget types and chart implementations. + +- [ ] Implement `PivotTable` component with row/column totals and multi-measure support ([objectui#585](https://github.com/objectstack-ai/objectui/issues/585)) +- [ ] Implement `funnel` chart type in `plugin-charts` ([#713](https://github.com/objectstack-ai/spec/issues/713)) +- [ ] Implement `grouped-bar` chart type in `plugin-charts` ([#713](https://github.com/objectstack-ai/spec/issues/713)) +- [ ] Implement `stacked-bar` chart type in `plugin-charts` ([#713](https://github.com/objectstack-ai/spec/issues/713)) +- [ ] Implement `horizontal-bar` chart variant in `plugin-charts` ([#713](https://github.com/objectstack-ai/spec/issues/713)) + +**Total Effort:** ~8.5 days + +#### Phase 3: Polish & Enhancement (Sprint 5) โ€” 1 week ๐ŸŸข + +Final polish and advanced features. + +- [ ] Implement `DashboardHeader` composite component ([objectui#586](https://github.com/objectstack-ai/objectui/issues/586)) +- [ ] Implement `gauge` chart type in `plugin-charts` ([#713](https://github.com/objectstack-ai/spec/issues/713)) +- [ ] Add dashboard export (PDF/Image) functionality + +**Total Effort:** ~6 days + +**Total Project Timeline:** ~22 days (4.5 weeks) + +### 8.3 Studio IDE - [x] Object Designer Protocol โ€” field editor, relationship mapper, ER diagram, object manager schemas defined (`studio/object-designer.zod.ts`) - [ ] Object Designer Runtime โ€” visual field editor with inline editing, drag-reorder, type-aware property panels @@ -407,21 +453,21 @@ The following renames are planned for packages that implement core service contr > See [`apps/studio/ROADMAP.md`](apps/studio/ROADMAP.md) for detailed Studio phases. -### 8.3 Developer Experience +### 8.4 Developer Experience - [ ] VS Code Extension โ€” full IntelliSense, diagnostics, and code actions for `.object.ts`, `.view.ts` - [ ] `create-objectstack` scaffolding โ€” templates for app, plugin, driver, adapter - [ ] Documentation site โ€” interactive tutorials, API playground - [ ] CLI enhancements โ€” `objectstack migrate`, `objectstack deploy` -### 8.4 Marketplace & Cloud +### 8.5 Marketplace & Cloud - [ ] Plugin marketplace โ€” publish, discover, install community plugins - [ ] App store โ€” pre-built applications (CRM, HRM, Project Management) - [ ] Developer portal โ€” API keys, usage metrics, billing - [ ] Managed cloud offering โ€” ObjectStack-as-a-Service -### 8.5 Example Applications +### 8.6 Example Applications - [x] **app-todo** โ€” Beginner reference (objects, actions, flows, dashboards, reports, i18n) โœ… - [x] **app-crm** โ€” Enterprise reference (10 objects, 5 AI agents, 4 RAG pipelines, security profiles) โœ… @@ -541,6 +587,7 @@ The following renames are planned for packages that implement core service contr | [`ARCHITECTURE.md`](ARCHITECTURE.md) | Microkernel design, package structure, three-layer protocol stack | | [`docs/design/driver-turso.md`](docs/design/driver-turso.md) | Turso/libSQL driver design document โ€” architecture impact, capabilities, implementation phases | | [`docs/design/airtable-interface-gap-analysis.md`](docs/design/airtable-interface-gap-analysis.md) | Airtable Interface gap analysis โ€” UI protocol comparison, schema proposals, implementation roadmap | +| [`content/docs/guides/airtable-dashboard-analysis.mdx`](content/docs/guides/airtable-dashboard-analysis.mdx) | Airtable Dashboard gap analysis โ€” Dashboard protocol & component enhancements, pivot tables, global filters, implementation roadmap | | [`docs/design/visual-design-ux-optimization.md`](docs/design/visual-design-ux-optimization.md) | Visual Design UX optimization plan โ€” Airtable benchmark, spec coverage audit, Studio builder alignment | | [`apps/studio/ROADMAP.md`](apps/studio/ROADMAP.md) | Studio IDE development phases (v2.1 โ†’ v3.0) | | [`docs/DX_ROADMAP.md`](docs/DX_ROADMAP.md) | Developer experience improvements | diff --git a/content/docs/guides/airtable-dashboard-analysis.mdx b/content/docs/guides/airtable-dashboard-analysis.mdx new file mode 100644 index 0000000000..ed4dd785e5 --- /dev/null +++ b/content/docs/guides/airtable-dashboard-analysis.mdx @@ -0,0 +1,1144 @@ +--- +title: Airtable Dashboard Gap Analysis +description: Comprehensive gap analysis comparing ObjectStack Dashboard protocol and components against Airtable's Sales Performance Dashboard +--- + +# Airtable Dashboard Gap Analysis + +> **Created:** 2026-02-18 +> **Context:** Sales Performance & Team Dashboard UI benchmarking +> **Scope:** Protocol enhancements (spec) + Component implementations (objectui) +> **Related Issues:** [#712](https://github.com/objectstack-ai/spec/issues/712), [#713](https://github.com/objectstack-ai/spec/issues/713), [#714](https://github.com/objectstack-ai/spec/issues/714), [objectui#585](https://github.com/objectstack-ai/objectui/issues/585), [objectui#586](https://github.com/objectstack-ai/objectui/issues/586), [objectui#587](https://github.com/objectstack-ai/objectui/issues/587), [objectui#588](https://github.com/objectstack-ai/objectui/issues/588) + +--- + +## Table of Contents + +- [1. Executive Summary](#1-executive-summary) +- [2. Target Interface Breakdown](#2-target-interface-breakdown) +- [3. Protocol Enhancements (spec)](#3-protocol-enhancements-spec) +- [4. Component Enhancements (objectui)](#4-component-enhancements-objectui) +- [5. Complete Implementation Example](#5-complete-implementation-example) +- [6. Implementation Roadmap](#6-implementation-roadmap) +- [7. Related Resources](#7-related-resources) + +--- + +## 1. Executive Summary + +This document provides a comprehensive gap analysis comparing the ObjectStack Dashboard protocol and ObjectUI components against **Airtable's "Sales Performance & Team Dashboard"** interface. The analysis identifies missing protocol features, component gaps, and provides a prioritized implementation roadmap. + +### Key Findings + +| Area | Status | Summary | +|:-----|:-------|:--------| +| **Core Protocol** | ๐ŸŸก **Mostly Complete** | Dashboard & widget schemas exist; need enhancements for color variants, actions, and header configuration | +| **Global Filters** | โš ๏ธ **Protocol Only** | `globalFilters` defined in schema but lacks dynamic data binding (`optionsFrom`) and no component implementation | +| **Chart Types** | โœ… **Complete** | All basic chart types (line, bar, pie) supported; advanced types (funnel, grouped-bar) defined in `ChartTypeSchema` | +| **Pivot Table** | โŒ **Missing** | Widget type defined in protocol but no component implementation | +| **KPI Cards** | โš ๏ธ **Partial** | `MetricCard` exists but lacks color variants and action buttons | +| **Widget Actions** | โŒ **Missing** | No support for external links or action buttons on widgets | +| **Dashboard Header** | โš ๏ธ **Partial** | No structured configuration for title, description, and actions | + +--- + +## 2. Target Interface Breakdown + +The Airtable Sales Performance Dashboard contains the following UI zones: + +### Zone A: Global Filter Bar + +**Airtable Feature:** Time period, team, and product line dropdown filters at the top of the dashboard. + +**Current Coverage:** +- โœ… Protocol defined (`DashboardSchema.globalFilters`) +- โŒ No dynamic options support (`optionsFrom` for lookup fields) +- โŒ No component implementation (`DashboardFilterBar`) + +**Required Changes:** +```typescript +// Enhanced protocol +globalFilters: [ + { + field: 'time_period', + label: 'Time Period', + type: 'select', + options: [ + { value: 'this_month', label: 'This Month' }, + { value: 'last_month', label: 'Last Month' }, + { value: 'this_quarter', label: 'This Quarter' } + ], + defaultValue: 'this_quarter', + scope: 'dashboard', // NEW: Filter scope + targetWidgets: ['*'] // NEW: Which widgets to filter + }, + { + field: 'team', + label: 'Team', + type: 'lookup', + optionsFrom: { // NEW: Dynamic data binding + object: 'team', + valueField: 'id', + labelField: 'name' + }, + defaultValue: null + } +] +``` + +--- + +### Zone B: KPI Card Row + +**Airtable Feature:** 3 colored KPI cards (orange, teal, blue) with metric values and external-link icons. + +**Current Coverage:** +- โœ… `MetricCard` component exists +- โŒ No color variant support +- โŒ No action button/link support + +**Required Changes:** +```typescript +// Enhanced widget schema +{ + title: 'Total Revenue', + type: 'metric', + object: 'opportunity', + valueField: 'amount', + aggregate: 'sum', + layout: { x: 0, y: 0, w: 4, h: 2 }, + + // NEW properties + colorVariant: 'orange', // orange | teal | blue | purple | green + actionUrl: '/reports/revenue', // External link or internal route + actionType: 'external', // external | internal | custom + description: 'YTD revenue across all regions' +} +``` + +--- + +### Zone C-E: Chart Widgets + +**Airtable Features:** +- **C:** Line chart (monthly revenue trend) +- **D:** Bar chart (funnel stage distribution) +- **E:** Pie/Donut chart (conversion rate by stage) + +**Current Coverage:** +- โœ… All supported in `ChartTypeSchema` (line, bar, pie, donut) +- โœ… Chart configuration via `ChartConfigSchema` + +**No changes needed** โ€” these are already fully supported. + +--- + +### Zone F: Grouped Bar Chart + +**Airtable Feature:** Team performance comparison with grouped bars (multiple series per category). + +**Current Coverage:** +- โœ… `grouped-bar` defined in `ChartTypeSchema` +- โŒ No component implementation in ObjectUI + +**Required Changes:** +```typescript +// Widget definition (protocol already supports this) +{ + title: 'Team Performance', + type: 'grouped-bar', + object: 'opportunity', + categoryField: 'team', + valueField: 'amount', + aggregate: 'sum', + chartConfig: { + series: [ + { name: 'closed_won', label: 'Won', color: '#10b981' }, + { name: 'closed_lost', label: 'Lost', color: '#ef4444' } + ] + }, + layout: { x: 0, y: 6, w: 6, h: 4 } +} +``` + +**Action:** Implement `grouped-bar` renderer in `plugin-charts`. + +--- + +### Zone G: Pivot Table + +**Airtable Feature:** Owner ร— Stage cross-tabulation with sum rows and columns. + +**Current Coverage:** +- โœ… `pivot` defined in `ChartTypeSchema` +- โŒ No `PivotTable` component +- โŒ No multi-measure support + +**Required Changes:** +```typescript +// Enhanced protocol for pivot widgets +{ + title: 'Revenue by Owner & Stage', + type: 'pivot', + object: 'opportunity', + + // NEW: Structured pivot configuration + pivotConfig: { + rows: ['owner'], // Row dimensions + columns: ['stage'], // Column dimensions + measures: [ // NEW: Support multiple measures + { + field: 'amount', + aggregate: 'sum', + label: 'Total Amount', + format: '$0,0' + }, + { + field: 'id', + aggregate: 'count', + label: 'Count', + format: '0,0' + } + ], + showRowTotals: true, + showColumnTotals: true, + showGrandTotal: true + }, + layout: { x: 6, y: 6, w: 6, h: 4 } +} +``` + +**Action:** +1. Add `pivotConfig` and `measures` to `DashboardWidgetSchema` +2. Implement `PivotTable` component in `plugin-report` + +--- + +### Zone H: Widget Action Button + +**Airtable Feature:** External-link icon on each widget header for drill-down or navigation. + +**Current Coverage:** +- โŒ Widget headers do not support action buttons +- โŒ No `description` field for widgets + +**Required Changes:** +```typescript +// Enhanced widget schema +{ + title: 'Monthly Revenue', + description: 'YTD revenue trend by month', // NEW + actionUrl: '/reports/revenue-detail', // NEW + actionType: 'internal', // NEW + actionIcon: 'external-link', // NEW + + // ... rest of widget config +} +``` + +--- + +### Zone I: Dashboard Title/Description + +**Airtable Feature:** Page header with title, subtitle, and optional action buttons. + +**Current Coverage:** +- โœ… `DashboardSchema.label` and `DashboardSchema.description` exist +- โŒ No structured header configuration +- โŒ No support for header actions + +**Required Changes:** +```typescript +// Enhanced DashboardSchema +export const DashboardSchema = z.object({ + name: SnakeCaseIdentifierSchema, + label: I18nLabelSchema, + description: I18nLabelSchema.optional(), + + // NEW: Structured header configuration + header: z.object({ + showTitle: z.boolean().default(true), + showDescription: z.boolean().default(true), + actions: z.array(z.object({ + label: I18nLabelSchema, + icon: z.string().optional(), + url: z.string().optional(), + type: z.enum(['primary', 'secondary', 'ghost']).default('secondary') + })).optional().describe('Header action buttons') + }).optional(), + + widgets: z.array(DashboardWidgetSchema), + // ... +}); +``` + +--- + +## 3. Protocol Enhancements (spec) + +The following enhancements are needed in `packages/spec/src/ui/dashboard.zod.ts`: + +### 3.1 Widget Color Variants & Actions + +```typescript +export const DashboardWidgetSchema = z.object({ + title: I18nLabelSchema.optional(), + type: ChartTypeSchema.default('metric'), + + // NEW: Visual styling + colorVariant: z.enum([ + 'default', 'orange', 'teal', 'blue', 'purple', + 'green', 'red', 'yellow', 'indigo', 'pink' + ]).optional().describe('Color variant for metric cards'), + + // NEW: Widget description + description: I18nLabelSchema.optional().describe('Widget description or subtitle'), + + // NEW: Widget actions + actionUrl: z.string().optional().describe('Action URL (external link or route)'), + actionType: z.enum(['external', 'internal', 'custom']).optional().describe('Action type'), + actionIcon: z.string().optional().describe('Action icon identifier'), + + // Existing fields + chartConfig: ChartConfigSchema.optional(), + object: z.string().optional(), + filter: FilterConditionSchema.optional(), + categoryField: z.string().optional(), + valueField: z.string().optional(), + aggregate: z.enum(['count', 'sum', 'avg', 'min', 'max']).optional().default('count'), + layout: z.object({ + x: z.number(), + y: z.number(), + w: z.number(), + h: z.number(), + }), + options: z.unknown().optional(), + responsive: ResponsiveConfigSchema.optional(), + aria: AriaPropsSchema.optional(), +}); +``` + +**Related Issue:** [#713](https://github.com/objectstack-ai/spec/issues/713) + +--- + +### 3.2 Enhanced Global Filters + +```typescript +export const GlobalFilterSchema = z.object({ + field: z.string().describe('Field name to filter on'), + label: I18nLabelSchema.optional().describe('Display label for the filter'), + type: z.enum(['text', 'select', 'date', 'number', 'lookup']).optional().describe('Filter input type'), + + // NEW: Static options (for select type) + options: z.array(z.object({ + value: z.any(), + label: I18nLabelSchema + })).optional().describe('Static filter options'), + + // NEW: Dynamic data binding (for lookup type) + optionsFrom: z.object({ + object: z.string().describe('Source object name'), + valueField: z.string().describe('Field to use as option value'), + labelField: z.string().describe('Field to use as option label'), + filter: FilterConditionSchema.optional().describe('Filter to apply to source object') + }).optional().describe('Dynamic filter options from object'), + + // NEW: Default value + defaultValue: z.any().optional().describe('Default filter value'), + + // NEW: Filter scope + scope: z.enum(['dashboard', 'widget']).default('dashboard').describe('Filter application scope'), + + // NEW: Target widgets (for selective filtering) + targetWidgets: z.array(z.string()).optional().describe('Widget IDs to apply this filter to (* for all)') +}); + +export const DashboardSchema = z.object({ + // ... existing fields + globalFilters: z.array(GlobalFilterSchema).optional(), + // ... +}); +``` + +**Related Issue:** [#712](https://github.com/objectstack-ai/spec/issues/712) + +--- + +### 3.3 Dashboard Header Configuration + +```typescript +export const DashboardHeaderSchema = z.object({ + showTitle: z.boolean().default(true).describe('Show dashboard title'), + showDescription: z.boolean().default(true).describe('Show dashboard description'), + + actions: z.array(z.object({ + label: I18nLabelSchema.describe('Action button label'), + icon: z.string().optional().describe('Action button icon'), + url: z.string().optional().describe('Action URL'), + onClick: z.string().optional().describe('Custom action handler ID'), + type: z.enum(['primary', 'secondary', 'ghost']).default('secondary').describe('Button variant'), + permission: z.string().optional().describe('Required permission to show action') + })).optional().describe('Header action buttons') +}); + +export const DashboardSchema = z.object({ + // ... existing fields + header: DashboardHeaderSchema.optional().describe('Dashboard header configuration'), + // ... +}); +``` + +**Related Issue:** [#714](https://github.com/objectstack-ai/spec/issues/714) + +--- + +### 3.4 Pivot Configuration & Multi-Measure Support + +```typescript +export const PivotConfigSchema = z.object({ + rows: z.array(z.string()).describe('Row dimension fields'), + columns: z.array(z.string()).describe('Column dimension fields'), + + // NEW: Multi-measure support + measures: z.array(z.object({ + field: z.string().describe('Field to aggregate'), + aggregate: z.enum(['count', 'sum', 'avg', 'min', 'max']).describe('Aggregation function'), + label: I18nLabelSchema.optional().describe('Measure display label'), + format: z.string().optional().describe('Value format string') + })).describe('Measures to calculate in pivot'), + + showRowTotals: z.boolean().default(true).describe('Show row totals'), + showColumnTotals: z.boolean().default(true).describe('Show column totals'), + showGrandTotal: z.boolean().default(true).describe('Show grand total'), + + sortRows: z.array(z.object({ + field: z.string(), + order: z.enum(['asc', 'desc']).default('asc') + })).optional().describe('Row sorting configuration'), + + sortColumns: z.array(z.object({ + field: z.string(), + order: z.enum(['asc', 'desc']).default('asc') + })).optional().describe('Column sorting configuration') +}); + +export const DashboardWidgetSchema = z.object({ + // ... existing fields + + // NEW: Pivot-specific configuration + pivotConfig: PivotConfigSchema.optional().describe('Pivot table configuration (when type=pivot)') +}); +``` + +**Related Issue:** [#714](https://github.com/objectstack-ai/spec/issues/714) + +--- + +## 4. Component Enhancements (objectui) + +The following components need to be implemented or enhanced in the ObjectUI ecosystem: + +### 4.1 DashboardFilterBar Component + +**Purpose:** Render global filter controls at the top of dashboards. + +**Package:** `@objectstack/plugin-dashboard` + +**Interface:** +```typescript +interface DashboardFilterBarProps { + filters: GlobalFilter[]; + values: Record; + onChange: (field: string, value: any) => void; + variant?: 'default' | 'compact' | 'inline'; +} + +export const DashboardFilterBar: React.FC = ({ + filters, + values, + onChange, + variant = 'default' +}) => { + // Render filter controls (select, date picker, lookup, etc.) + // Support dynamic options via optionsFrom + // Handle filter value changes +}; +``` + +**Related Issue:** [objectui#588](https://github.com/objectstack-ai/objectui/issues/588) + +--- + +### 4.2 MetricCard Color Variants & Actions + +**Purpose:** Enhance `MetricCard` with color variants and action buttons. + +**Package:** `@objectstack/plugin-dashboard` + +**Changes:** +```typescript +interface MetricCardProps { + title: string; + value: number | string; + + // NEW + colorVariant?: 'default' | 'orange' | 'teal' | 'blue' | 'purple' | 'green' | 'red'; + description?: string; + actionUrl?: string; + actionType?: 'external' | 'internal' | 'custom'; + actionIcon?: string; + onAction?: () => void; + + // Existing + format?: string; + trend?: { value: number; direction: 'up' | 'down' }; + loading?: boolean; +} + +export const MetricCard: React.FC = ({ + title, + value, + colorVariant = 'default', + description, + actionUrl, + actionType, + actionIcon = 'external-link', + onAction, + ...rest +}) => { + // Apply color variant styling + // Render action button if actionUrl or onAction provided + // Support description subtitle +}; +``` + +**Related Issue:** [objectui#587](https://github.com/objectstack-ai/objectui/issues/587) + +--- + +### 4.3 PivotTable Component + +**Purpose:** Render cross-tabulation matrices with row/column totals. + +**Package:** `@objectstack/plugin-report` + +**Interface:** +```typescript +interface PivotTableProps { + data: any[]; + config: PivotConfig; + loading?: boolean; + onCellClick?: (row: any, column: any, measure: any) => void; +} + +export const PivotTable: React.FC = ({ + data, + config, + loading, + onCellClick +}) => { + // Compute pivot matrix from flat data + // Render row headers (left sticky column) + // Render column headers (top sticky row) + // Render cells with measures + // Render row/column/grand totals + // Support multi-measure display (stacked or side-by-side) +}; +``` + +**Related Issue:** [objectui#585](https://github.com/objectstack-ai/objectui/issues/585) + +--- + +### 4.4 Widget Header with Description & Action + +**Purpose:** Standardize widget headers with optional description and action button. + +**Package:** `@objectstack/plugin-dashboard` + +**Interface:** +```typescript +interface WidgetHeaderProps { + title: string; + description?: string; + actionUrl?: string; + actionType?: 'external' | 'internal' | 'custom'; + actionIcon?: string; + onAction?: () => void; +} + +export const WidgetHeader: React.FC = ({ + title, + description, + actionUrl, + actionType, + actionIcon = 'external-link', + onAction +}) => { + // Render title + // Render optional description (smaller, muted text) + // Render action button (icon only, top-right) +}; +``` + +**Related Issue:** [objectui#586](https://github.com/objectstack-ai/objectui/issues/586) + +--- + +### 4.5 Advanced Chart Types + +**Purpose:** Implement missing chart types in `AdvancedChartImpl`. + +**Package:** `@objectstack/plugin-charts` + +**Missing Types:** +- `funnel` โ€” Funnel chart for conversion stages +- `grouped-bar` โ€” Grouped bar chart for multi-series comparison +- `stacked-bar` โ€” Stacked bar chart for composition +- `horizontal-bar` โ€” Horizontal bar chart variant +- `gauge` โ€” Gauge/speedometer for progress metrics + +**Related Issue:** [#713](https://github.com/objectstack-ai/spec/issues/713) + +--- + +### 4.6 DashboardHeader Component + +**Purpose:** Render dashboard page header with title, description, and actions. + +**Package:** `@objectstack/plugin-dashboard` + +**Interface:** +```typescript +interface DashboardHeaderProps { + title: string; + description?: string; + actions?: Array<{ + label: string; + icon?: string; + url?: string; + onClick?: () => void; + type?: 'primary' | 'secondary' | 'ghost'; + }>; + showTitle?: boolean; + showDescription?: boolean; +} + +export const DashboardHeader: React.FC = ({ + title, + description, + actions = [], + showTitle = true, + showDescription = true +}) => { + // Render title (h1 or h2) + // Render description (muted paragraph) + // Render action buttons (right-aligned) +}; +``` + +**Related Issue:** [objectui#586](https://github.com/objectstack-ai/objectui/issues/586) + +--- + +## 5. Complete Implementation Example + +### 5.1 Full Dashboard Definition (TypeScript) + +```typescript +import { Dashboard } from '@objectstack/spec'; + +export const salesPerformanceDashboard = Dashboard.create({ + name: 'sales_performance', + label: 'Sales Performance & Team Dashboard', + description: 'Executive overview of sales metrics and team performance', + + // Dashboard header configuration + header: { + showTitle: true, + showDescription: true, + actions: [ + { + label: 'Export PDF', + icon: 'download', + onClick: 'exportDashboard', + type: 'secondary' + }, + { + label: 'Configure', + icon: 'settings', + url: '/settings/dashboards/sales_performance', + type: 'ghost' + } + ] + }, + + // Global filters + globalFilters: [ + { + field: 'time_period', + label: 'Time Period', + type: 'select', + options: [ + { value: 'this_month', label: 'This Month' }, + { value: 'last_month', label: 'Last Month' }, + { value: 'this_quarter', label: 'This Quarter' }, + { value: 'last_quarter', label: 'Last Quarter' } + ], + defaultValue: 'this_quarter', + scope: 'dashboard' + }, + { + field: 'team', + label: 'Team', + type: 'lookup', + optionsFrom: { + object: 'team', + valueField: 'id', + labelField: 'name', + filter: { field: 'active', operator: 'eq', value: true } + }, + scope: 'dashboard' + }, + { + field: 'product_line', + label: 'Product Line', + type: 'select', + optionsFrom: { + object: 'product', + valueField: 'category', + labelField: 'category' + }, + scope: 'dashboard' + } + ], + + // Widgets + widgets: [ + // Row 1: KPI Cards + { + title: 'Total Revenue', + description: 'YTD revenue across all regions', + type: 'metric', + object: 'opportunity', + valueField: 'amount', + aggregate: 'sum', + filter: { field: 'stage', operator: 'eq', value: 'closed_won' }, + colorVariant: 'orange', + actionUrl: '/reports/revenue-detail', + actionType: 'internal', + layout: { x: 0, y: 0, w: 4, h: 2 } + }, + { + title: 'Win Rate', + description: 'Percentage of opportunities closed won', + type: 'kpi', + object: 'opportunity', + valueField: 'stage', + aggregate: 'count', + colorVariant: 'teal', + actionUrl: '/reports/win-rate', + actionType: 'internal', + layout: { x: 4, y: 0, w: 4, h: 2 } + }, + { + title: 'Active Deals', + description: 'Opportunities in pipeline', + type: 'metric', + object: 'opportunity', + valueField: 'id', + aggregate: 'count', + filter: { + field: 'stage', + operator: 'nin', + value: ['closed_won', 'closed_lost'] + }, + colorVariant: 'blue', + actionUrl: '/views/active-deals', + actionType: 'internal', + layout: { x: 8, y: 0, w: 4, h: 2 } + }, + + // Row 2: Line Chart - Monthly Revenue Trend + { + title: 'Monthly Revenue Trend', + description: 'Revenue by month for selected period', + type: 'line', + object: 'opportunity', + categoryField: 'close_date', + valueField: 'amount', + aggregate: 'sum', + filter: { field: 'stage', operator: 'eq', value: 'closed_won' }, + chartConfig: { + xAxis: { field: 'close_date', format: 'MMM YYYY' }, + yAxis: { field: 'amount', format: '$0,0' }, + series: [ + { name: 'amount', label: 'Revenue', color: '#fb923c' } + ] + }, + actionUrl: '/reports/revenue-trend', + actionType: 'internal', + layout: { x: 0, y: 2, w: 6, h: 4 } + }, + + // Row 2: Bar Chart - Funnel Stage Distribution + { + title: 'Pipeline by Stage', + description: 'Deal distribution across stages', + type: 'bar', + object: 'opportunity', + categoryField: 'stage', + valueField: 'amount', + aggregate: 'sum', + chartConfig: { + xAxis: { field: 'stage' }, + yAxis: { field: 'amount', format: '$0,0.0a' } + }, + actionUrl: '/reports/pipeline', + actionType: 'internal', + layout: { x: 6, y: 2, w: 6, h: 4 } + }, + + // Row 3: Pie Chart - Conversion Rate + { + title: 'Conversion Rate by Stage', + description: 'Win/loss distribution', + type: 'donut', + object: 'opportunity', + categoryField: 'stage', + valueField: 'id', + aggregate: 'count', + chartConfig: { + colors: ['#10b981', '#ef4444', '#f59e0b', '#6366f1'] + }, + layout: { x: 0, y: 6, w: 6, h: 4 } + }, + + // Row 3: Grouped Bar Chart - Team Performance + { + title: 'Team Performance Comparison', + description: 'Won vs. lost by team', + type: 'grouped-bar', + object: 'opportunity', + categoryField: 'team', + valueField: 'amount', + aggregate: 'sum', + chartConfig: { + series: [ + { name: 'closed_won', label: 'Won', color: '#10b981' }, + { name: 'closed_lost', label: 'Lost', color: '#ef4444' } + ] + }, + actionUrl: '/reports/team-performance', + actionType: 'internal', + layout: { x: 6, y: 6, w: 6, h: 4 } + }, + + // Row 4: Pivot Table - Owner ร— Stage + { + title: 'Revenue by Owner & Stage', + description: 'Cross-tabulation of deals', + type: 'pivot', + object: 'opportunity', + pivotConfig: { + rows: ['owner'], + columns: ['stage'], + measures: [ + { + field: 'amount', + aggregate: 'sum', + label: 'Total Amount', + format: '$0,0' + }, + { + field: 'id', + aggregate: 'count', + label: 'Count', + format: '0,0' + } + ], + showRowTotals: true, + showColumnTotals: true, + showGrandTotal: true + }, + actionUrl: '/reports/pivot-detail', + actionType: 'internal', + layout: { x: 0, y: 10, w: 12, h: 6 } + } + ], + + // Auto-refresh every 5 minutes + refreshInterval: 300, + + // Performance optimization + performance: { + lazyLoad: true, + cacheTimeout: 300 + } +}); +``` + +--- + +### 5.2 JSON Schema Example + +For reference, here's the same dashboard definition in pure JSON format: + +```json +{ + "name": "sales_performance", + "label": "Sales Performance & Team Dashboard", + "description": "Executive overview of sales metrics and team performance", + + "header": { + "showTitle": true, + "showDescription": true, + "actions": [ + { + "label": "Export PDF", + "icon": "download", + "onClick": "exportDashboard", + "type": "secondary" + }, + { + "label": "Configure", + "icon": "settings", + "url": "/settings/dashboards/sales_performance", + "type": "ghost" + } + ] + }, + + "globalFilters": [ + { + "field": "time_period", + "label": "Time Period", + "type": "select", + "options": [ + { "value": "this_month", "label": "This Month" }, + { "value": "last_month", "label": "Last Month" }, + { "value": "this_quarter", "label": "This Quarter" }, + { "value": "last_quarter", "label": "Last Quarter" } + ], + "defaultValue": "this_quarter", + "scope": "dashboard" + }, + { + "field": "team", + "label": "Team", + "type": "lookup", + "optionsFrom": { + "object": "team", + "valueField": "id", + "labelField": "name", + "filter": { "field": "active", "operator": "eq", "value": true } + }, + "scope": "dashboard" + } + ], + + "widgets": [ + { + "title": "Total Revenue", + "description": "YTD revenue across all regions", + "type": "metric", + "object": "opportunity", + "valueField": "amount", + "aggregate": "sum", + "filter": { "field": "stage", "operator": "eq", "value": "closed_won" }, + "colorVariant": "orange", + "actionUrl": "/reports/revenue-detail", + "actionType": "internal", + "layout": { "x": 0, "y": 0, "w": 4, "h": 2 } + }, + { + "title": "Monthly Revenue Trend", + "type": "line", + "object": "opportunity", + "categoryField": "close_date", + "valueField": "amount", + "aggregate": "sum", + "layout": { "x": 0, "y": 2, "w": 6, "h": 4 } + } + ], + + "refreshInterval": 300 +} +``` + +--- + +## 6. Implementation Roadmap + +### Priority Classification + +- ๐Ÿ”ด **P0 (Critical):** Required for Airtable feature parity; blocking user workflows +- ๐ŸŸก **P1 (Important):** Enhances user experience; should be in next release +- ๐ŸŸข **P2 (Nice-to-have):** Polishing; can be deferred + +--- + +### Phase 1: Foundation (Sprint 1-2) โ€” 2 weeks + +| Priority | Task | Package | Effort | Issue | +|:--------:|:-----|:--------|:-------|:------| +| ๐Ÿ”ด P0 | Add `colorVariant`, `actionUrl`, `description` to `DashboardWidgetSchema` | `spec` | 0.5d | [#713](https://github.com/objectstack-ai/spec/issues/713) | +| ๐Ÿ”ด P0 | Enhance `globalFilters` with `options`, `optionsFrom`, `defaultValue`, `scope`, `targetWidgets` | `spec` | 0.5d | [#712](https://github.com/objectstack-ai/spec/issues/712) | +| ๐Ÿ”ด P0 | Add `header` configuration to `DashboardSchema` | `spec` | 0.5d | [#714](https://github.com/objectstack-ai/spec/issues/714) | +| ๐Ÿ”ด P0 | Add `pivotConfig` and `measures` to `DashboardWidgetSchema` | `spec` | 0.5d | [#714](https://github.com/objectstack-ai/spec/issues/714) | +| ๐Ÿ”ด P0 | Implement `DashboardFilterBar` component | `plugin-dashboard` | 3d | [objectui#588](https://github.com/objectstack-ai/objectui/issues/588) | +| ๐Ÿ”ด P0 | Add color variants + action button to `MetricCard` | `plugin-dashboard` | 1d | [objectui#587](https://github.com/objectstack-ai/objectui/issues/587) | +| ๐Ÿ”ด P0 | Add description + action button to widget headers | `plugin-dashboard` | 1d | [objectui#586](https://github.com/objectstack-ai/objectui/issues/586) | + +**Total Effort:** ~7.5 days + +--- + +### Phase 2: Advanced Widgets (Sprint 3-4) โ€” 2 weeks + +| Priority | Task | Package | Effort | Issue | +|:--------:|:-----|:--------|:-------|:------| +| ๐Ÿ”ด P0 | Implement `PivotTable` component | `plugin-report` | 5d | [objectui#585](https://github.com/objectstack-ai/objectui/issues/585) | +| ๐ŸŸก P1 | Implement `funnel` chart type | `plugin-charts` | 1d | [#713](https://github.com/objectstack-ai/spec/issues/713) | +| ๐ŸŸก P1 | Implement `grouped-bar` chart type | `plugin-charts` | 1d | [#713](https://github.com/objectstack-ai/spec/issues/713) | +| ๐ŸŸก P1 | Implement `stacked-bar` chart type | `plugin-charts` | 1d | [#713](https://github.com/objectstack-ai/spec/issues/713) | +| ๐ŸŸก P1 | Implement `horizontal-bar` chart type | `plugin-charts` | 0.5d | [#713](https://github.com/objectstack-ai/spec/issues/713) | + +**Total Effort:** ~8.5 days + +--- + +### Phase 3: Polish & Enhancement (Sprint 5) โ€” 1 week + +| Priority | Task | Package | Effort | Issue | +|:--------:|:-----|:--------|:-------|:------| +| ๐ŸŸก P1 | Implement `DashboardHeader` composite component | `plugin-dashboard` | 1d | [objectui#586](https://github.com/objectstack-ai/objectui/issues/586) | +| ๐ŸŸข P2 | Implement `gauge` chart type | `plugin-charts` | 2d | [#713](https://github.com/objectstack-ai/spec/issues/713) | +| ๐ŸŸข P2 | Add dashboard export (PDF/Image) action | `plugin-dashboard` | 3d | N/A | + +**Total Effort:** ~6 days + +--- + +### Total Project Timeline + +- **Total Effort:** ~22 days (4.5 weeks) +- **Recommended Team:** 2 engineers (1 spec + 1 objectui) +- **Target Completion:** End of Q1 2026 + +--- + +## 7. Related Resources + +### GitHub Issues + +**Spec Repository (objectstack-ai/spec):** +- [#712](https://github.com/objectstack-ai/spec/issues/712) โ€” DashboardSchema.globalFilters ๅ่ฎฎๆ”ฏๆŒๅŠจๆ€้€‰้กนไธŽๆ•ฐๆฎ็ป‘ๅฎš้ซ˜็บง้…็ฝฎ +- [#713](https://github.com/objectstack-ai/spec/issues/713) โ€” DashboardWidget type ๆ”ฏๆŒ pivot/funnel/grouped-bar็ญ‰็ฑปๅž‹๏ผˆๅ่ฎฎ+objectuiๅฎž็ŽฐๅๅŒ๏ผ‰ +- [#714](https://github.com/objectstack-ai/spec/issues/714) โ€” Spec: DashboardSchema ๆ”ฏๆŒ่‡ชๅฎšไน‰ header ๅ’Œ multi-measure ๅˆ†ๆž้…็ฝฎ + +**ObjectUI Repository (objectstack-ai/objectui):** +- [#585](https://github.com/objectstack-ai/objectui/issues/585) โ€” PivotTable ็ป„ไปถ๏ผˆไบคๅ‰็Ÿฉ้˜ต/้€่ง†่กจ๏ผ‰ๆ”ฏๆŒ +- [#586](https://github.com/objectstack-ai/objectui/issues/586) โ€” ๆ–ฐๅขžๆ”ฏๆŒ widget header ๆ่ฟฐไธŽๆ“ไฝœๆŒ‰้’ฎ +- [#587](https://github.com/objectstack-ai/objectui/issues/587) โ€” MetricCard KPI ๅกๆ”ฏๆŒๅฝฉ่‰ฒๅ˜ไฝ“ๅ’Œๆ“ไฝœๆŒ‰้’ฎ +- [#588](https://github.com/objectstack-ai/objectui/issues/588) โ€” DashboardFilterBar ็ป„ไปถ๏ผšๅฎž็Žฐๅ…จๅฑ€็ญ›้€‰ๆกๆธฒๆŸ“ๅ่ฎฎ + +--- + +### Internal Documentation + +- [Dashboard Metadata Guide](/docs/guides/metadata/dashboard) โ€” Current dashboard protocol documentation +- [Chart Configuration Reference](/docs/references/ui/chart) โ€” Chart type taxonomy and configuration +- [Airtable Interface Gap Analysis](/docs/design/airtable-interface-gap-analysis) โ€” Interface-level gap analysis (superseded) + +--- + +### External References + +- [Airtable Interfaces Documentation](https://support.airtable.com/docs/creating-interfaces) โ€” Official Airtable interface builder guide +- [React Grid Layout](https://github.com/react-grid-layout/react-grid-layout) โ€” Dashboard grid layout library +- [Recharts Documentation](https://recharts.org/) โ€” Chart visualization library + +--- + +## Appendix: Protocol Migration Guide + +If you have existing dashboard definitions, here's how to migrate to the new protocol: + +### Before (v3.0) + +```typescript +{ + name: 'sales_dashboard', + label: 'Sales Dashboard', + globalFilters: [ + { field: 'region', label: 'Region', type: 'select' } + ], + widgets: [ + { + title: 'Revenue', + type: 'metric', + object: 'opportunity', + valueField: 'amount', + aggregate: 'sum', + layout: { x: 0, y: 0, w: 4, h: 2 } + } + ] +} +``` + +### After (v3.2+) + +```typescript +{ + name: 'sales_dashboard', + label: 'Sales Dashboard', + + // NEW: Header configuration + header: { + showTitle: true, + showDescription: true, + actions: [ + { label: 'Export', icon: 'download', onClick: 'export', type: 'secondary' } + ] + }, + + // ENHANCED: Global filters with dynamic options + globalFilters: [ + { + field: 'region', + label: 'Region', + type: 'select', + optionsFrom: { + object: 'region', + valueField: 'id', + labelField: 'name' + }, + defaultValue: null, + scope: 'dashboard' + } + ], + + widgets: [ + { + title: 'Revenue', + description: 'YTD revenue across all regions', // NEW + type: 'metric', + object: 'opportunity', + valueField: 'amount', + aggregate: 'sum', + colorVariant: 'orange', // NEW + actionUrl: '/reports/revenue', // NEW + actionType: 'internal', // NEW + layout: { x: 0, y: 0, w: 4, h: 2 } + } + ] +} +``` + +--- + +**Document Version:** 1.0 +**Last Updated:** 2026-02-18 +**Maintainer:** ObjectStack Core Team diff --git a/content/docs/guides/meta.json b/content/docs/guides/meta.json index a4bb118702..5ce534f324 100644 --- a/content/docs/guides/meta.json +++ b/content/docs/guides/meta.json @@ -5,6 +5,7 @@ "metadata", "data-modeling", "common-patterns", + "airtable-dashboard-analysis", "---Building---", "plugins", "plugin-development",