-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdashboard.zod.ts
More file actions
115 lines (97 loc) · 3.54 KB
/
dashboard.zod.ts
File metadata and controls
115 lines (97 loc) · 3.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import { z } from 'zod';
import { FilterConditionSchema } from '../data/filter.zod';
import { ChartTypeSchema, ChartConfigSchema } from './chart.zod';
import { SnakeCaseIdentifierSchema } from '../shared/identifiers.zod';
/**
* Dashboard Widget Schema
* A single component on the dashboard grid.
*/
export const DashboardWidgetSchema = z.object({
/** Widget Title */
title: z.string().optional().describe('Widget title'),
/** Visualization Type */
type: ChartTypeSchema.default('metric').describe('Visualization type'),
/** Chart Configuration */
chartConfig: ChartConfigSchema.optional().describe('Chart visualization configuration'),
/** Data Source Object */
object: z.string().optional().describe('Data source object name'),
/** Data Filter (MongoDB-style FilterCondition) */
filter: FilterConditionSchema.optional().describe('Data filter criteria'),
/** Category Field (X-Axis / Group By) */
categoryField: z.string().optional().describe('Field for grouping (X-Axis)'),
/** Value Field (Y-Axis) */
valueField: z.string().optional().describe('Field for values (Y-Axis)'),
/** Aggregate operation */
aggregate: z.enum(['count', 'sum', 'avg', 'min', 'max']).optional().default('count').describe('Aggregate function'),
/**
* Layout Position (React-Grid-Layout style)
* x: column (0-11)
* y: row
* w: width (1-12)
* h: height
*/
layout: z.object({
x: z.number(),
y: z.number(),
w: z.number(),
h: z.number(),
}).describe('Grid layout position'),
/** Widget specific options (colors, legend, etc.) */
options: z.unknown().optional().describe('Widget specific configuration'),
});
/**
* Dashboard Schema
* Represents a page containing multiple visualizations.
*
* @example Sales Executive Dashboard
* {
* name: "sales_overview",
* label: "Sales Executive Overview",
* widgets: [
* {
* title: "Total Pipe",
* type: "metric",
* object: "opportunity",
* valueField: "amount",
* aggregate: "sum",
* layout: { x: 0, y: 0, w: 3, h: 2 }
* },
* {
* title: "Revenue by Region",
* type: "bar",
* object: "order",
* categoryField: "region",
* valueField: "total",
* aggregate: "sum",
* layout: { x: 3, y: 0, w: 6, h: 4 }
* }
* ]
* }
*/
export const DashboardSchema = z.object({
/** Machine name */
name: SnakeCaseIdentifierSchema.describe('Dashboard unique name'),
/** Display label */
label: z.string().describe('Dashboard label'),
/** Description */
description: z.string().optional().describe('Dashboard description'),
/** Collection of widgets */
widgets: z.array(DashboardWidgetSchema).describe('Widgets to display'),
/** Auto-refresh */
refreshInterval: z.number().optional().describe('Auto-refresh interval in seconds'),
/** Global Filters */
globalFilters: z.array(z.object({
field: z.string().describe('Field name to filter on'),
label: z.string().optional().describe('Display label for the filter'),
type: z.enum(['text', 'select', 'date', 'number']).optional().describe('Filter input type'),
})).optional().describe('Global filters that apply to all widgets in the dashboard'),
});
export type Dashboard = z.infer<typeof DashboardSchema>;
export type DashboardInput = z.input<typeof DashboardSchema>;
export type DashboardWidget = z.infer<typeof DashboardWidgetSchema>;
/**
* Dashboard Factory Helper
*/
export const Dashboard = {
create: (config: z.input<typeof DashboardSchema>): Dashboard => DashboardSchema.parse(config),
} as const;