@adminforth/dashboard 1.5.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom/api/dashboardApi.ts +137 -1
- package/custom/model/dashboard.types.ts +32 -22
- package/custom/package.json +1 -0
- package/custom/pnpm-lock.yaml +31 -0
- package/custom/runtime/DashboardRuntime.vue +9 -15
- package/custom/runtime/YamlConfigEditor.vue +109 -0
- package/custom/skills/adminforth-dashboard/SKILL.md +66 -10
- package/custom/widgets/KpiCardWidget.vue +172 -9
- package/custom/widgets/chart/ChartWidget.vue +5 -5
- package/custom/widgets/registry.ts +4 -4
- package/dist/custom/api/dashboardApi.d.ts +46 -1
- package/dist/custom/api/dashboardApi.js +90 -0
- package/dist/custom/api/dashboardApi.ts +137 -1
- package/dist/custom/model/dashboard.types.d.ts +30 -14
- package/dist/custom/model/dashboard.types.js +2 -2
- package/dist/custom/model/dashboard.types.ts +32 -22
- package/dist/custom/package.json +1 -0
- package/dist/custom/pnpm-lock.yaml +31 -0
- package/dist/custom/queries/useDashboardConfig.d.ts +106 -104
- package/dist/custom/queries/useWidgetData.d.ts +106 -104
- package/dist/custom/runtime/DashboardRuntime.vue +9 -15
- package/dist/custom/runtime/YamlConfigEditor.vue +109 -0
- package/dist/custom/skills/adminforth-dashboard/SKILL.md +66 -10
- package/dist/custom/widgets/KpiCardWidget.vue +172 -9
- package/dist/custom/widgets/chart/ChartWidget.vue +5 -5
- package/dist/custom/widgets/registry.js +4 -4
- package/dist/custom/widgets/registry.ts +4 -4
- package/dist/endpoint/widgets.js +99 -14
- package/dist/schema/api.d.ts +11426 -1634
- package/dist/schema/api.js +118 -21
- package/dist/schema/widget.d.ts +425 -1980
- package/dist/schema/widget.js +13 -374
- package/dist/schema/widgets/charts.d.ts +1689 -0
- package/dist/schema/widgets/charts.js +92 -0
- package/dist/schema/widgets/common.d.ts +275 -0
- package/dist/schema/widgets/common.js +171 -0
- package/dist/schema/widgets/gauge-card.d.ts +172 -0
- package/dist/schema/widgets/gauge-card.js +28 -0
- package/dist/schema/widgets/kpi-card.d.ts +212 -0
- package/dist/schema/widgets/kpi-card.js +43 -0
- package/dist/schema/widgets/pivot-table.d.ts +196 -0
- package/dist/schema/widgets/pivot-table.js +17 -0
- package/dist/schema/widgets/table.d.ts +130 -0
- package/dist/schema/widgets/table.js +12 -0
- package/dist/services/widgetDataService.js +96 -2
- package/endpoint/widgets.ts +173 -26
- package/package.json +1 -1
- package/schema/api.ts +148 -22
- package/schema/widget.ts +43 -425
- package/schema/widgets/charts.ts +113 -0
- package/schema/widgets/common.ts +194 -0
- package/schema/widgets/gauge-card.ts +34 -0
- package/schema/widgets/kpi-card.ts +49 -0
- package/schema/widgets/pivot-table.ts +24 -0
- package/schema/widgets/table.ts +18 -0
- package/services/widgetDataService.ts +129 -3
- package/shims-vue.d.ts +11 -0
- package/tsconfig.json +3 -1
package/schema/api.ts
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
import { toJSONSchema, z } from 'zod'
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
import {
|
|
3
|
+
BarChartSchema,
|
|
4
|
+
FunnelChartSchema,
|
|
5
|
+
FunnelQueryConfigSchema,
|
|
6
|
+
GaugeCardViewConfigSchema,
|
|
7
|
+
HistogramChartSchema,
|
|
8
|
+
KpiCardViewConfigSchema,
|
|
9
|
+
LineChartSchema,
|
|
10
|
+
PieChartSchema,
|
|
11
|
+
PivotTableViewConfigSchema,
|
|
12
|
+
QueryConfigSchema,
|
|
13
|
+
StackedBarChartSchema,
|
|
14
|
+
TableViewConfigSchema,
|
|
15
|
+
WidgetEditableBaseSchema,
|
|
16
|
+
WidgetConfigSchema,
|
|
17
|
+
} from './widget.js'
|
|
7
18
|
|
|
8
19
|
export const DashboardErrorResponseZodSchema = z.object({
|
|
9
20
|
error: z.string(),
|
|
@@ -22,7 +33,7 @@ export const DashboardGroupZodSchema = z.object({
|
|
|
22
33
|
export const DashboardConfigZodSchema = z.object({
|
|
23
34
|
version: z.number(),
|
|
24
35
|
groups: z.array(DashboardGroupZodSchema),
|
|
25
|
-
widgets: z.array(
|
|
36
|
+
widgets: z.array(WidgetConfigSchema),
|
|
26
37
|
}).strict()
|
|
27
38
|
|
|
28
39
|
export const DashboardResponseZodSchema = z.object({
|
|
@@ -40,7 +51,7 @@ export const DashboardApiResponseZodSchema = z.union([
|
|
|
40
51
|
|
|
41
52
|
export const DashboardWidgetDataResponseZodSchema = z.union([
|
|
42
53
|
z.object({
|
|
43
|
-
widget:
|
|
54
|
+
widget: WidgetConfigSchema,
|
|
44
55
|
data: z.unknown(),
|
|
45
56
|
}),
|
|
46
57
|
DashboardErrorResponseZodSchema,
|
|
@@ -91,23 +102,138 @@ export const MoveWidgetRequestZodSchema = z.object({
|
|
|
91
102
|
direction: z.enum(['up', 'down']),
|
|
92
103
|
}).strict()
|
|
93
104
|
|
|
105
|
+
const ConfigurableTableWidgetConfigSchema = WidgetEditableBaseSchema.extend({
|
|
106
|
+
target: z.literal('table'),
|
|
107
|
+
table: TableViewConfigSchema.optional(),
|
|
108
|
+
query: QueryConfigSchema,
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
const ConfigurableKpiCardWidgetConfigSchema = WidgetEditableBaseSchema.extend({
|
|
112
|
+
target: z.literal('kpi_card'),
|
|
113
|
+
card: KpiCardViewConfigSchema,
|
|
114
|
+
query: QueryConfigSchema,
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
const ConfigurableGaugeCardWidgetConfigSchema = WidgetEditableBaseSchema.extend({
|
|
118
|
+
target: z.literal('gauge_card'),
|
|
119
|
+
card: GaugeCardViewConfigSchema,
|
|
120
|
+
query: QueryConfigSchema,
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
const ConfigurableLineChartWidgetConfigSchema = WidgetEditableBaseSchema.extend({
|
|
124
|
+
target: z.literal('chart'),
|
|
125
|
+
chart: LineChartSchema,
|
|
126
|
+
query: QueryConfigSchema,
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
const ConfigurableBarChartWidgetConfigSchema = WidgetEditableBaseSchema.extend({
|
|
130
|
+
target: z.literal('chart'),
|
|
131
|
+
chart: BarChartSchema,
|
|
132
|
+
query: QueryConfigSchema,
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
const ConfigurableStackedBarChartWidgetConfigSchema = WidgetEditableBaseSchema.extend({
|
|
136
|
+
target: z.literal('chart'),
|
|
137
|
+
chart: StackedBarChartSchema,
|
|
138
|
+
query: QueryConfigSchema,
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
const ConfigurablePieChartWidgetConfigSchema = WidgetEditableBaseSchema.extend({
|
|
142
|
+
target: z.literal('chart'),
|
|
143
|
+
chart: PieChartSchema,
|
|
144
|
+
query: QueryConfigSchema,
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
const ConfigurableHistogramChartWidgetConfigSchema = WidgetEditableBaseSchema.extend({
|
|
148
|
+
target: z.literal('chart'),
|
|
149
|
+
chart: HistogramChartSchema,
|
|
150
|
+
query: QueryConfigSchema,
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
const ConfigurableFunnelChartWidgetConfigSchema = WidgetEditableBaseSchema.extend({
|
|
154
|
+
target: z.literal('chart'),
|
|
155
|
+
chart: FunnelChartSchema,
|
|
156
|
+
query: FunnelQueryConfigSchema,
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
const ConfigurablePivotTableWidgetConfigSchema = WidgetEditableBaseSchema.extend({
|
|
160
|
+
target: z.literal('pivot_table'),
|
|
161
|
+
pivot: PivotTableViewConfigSchema,
|
|
162
|
+
query: QueryConfigSchema,
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
const ConfigurableChartWidgetConfigSchema = z.union([
|
|
166
|
+
ConfigurableLineChartWidgetConfigSchema,
|
|
167
|
+
ConfigurableBarChartWidgetConfigSchema,
|
|
168
|
+
ConfigurableStackedBarChartWidgetConfigSchema,
|
|
169
|
+
ConfigurablePieChartWidgetConfigSchema,
|
|
170
|
+
ConfigurableHistogramChartWidgetConfigSchema,
|
|
171
|
+
ConfigurableFunnelChartWidgetConfigSchema,
|
|
172
|
+
])
|
|
173
|
+
|
|
174
|
+
export const ConfigurableWidgetConfigSchema = z.union([
|
|
175
|
+
ConfigurableTableWidgetConfigSchema,
|
|
176
|
+
ConfigurableKpiCardWidgetConfigSchema,
|
|
177
|
+
ConfigurableGaugeCardWidgetConfigSchema,
|
|
178
|
+
ConfigurableChartWidgetConfigSchema,
|
|
179
|
+
ConfigurablePivotTableWidgetConfigSchema,
|
|
180
|
+
])
|
|
181
|
+
|
|
94
182
|
export const SetWidgetConfigRequestZodSchema = z.object({
|
|
95
183
|
slug: z.string(),
|
|
96
184
|
widgetId: z.string(),
|
|
97
|
-
config:
|
|
185
|
+
config: ConfigurableWidgetConfigSchema,
|
|
98
186
|
}).strict()
|
|
99
187
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
export const
|
|
109
|
-
export const
|
|
110
|
-
export const
|
|
111
|
-
export const
|
|
112
|
-
export const
|
|
113
|
-
export const
|
|
188
|
+
function configureWidgetRequestSchema<T extends z.ZodTypeAny>(configSchema: T) {
|
|
189
|
+
return z.object({
|
|
190
|
+
slug: z.string(),
|
|
191
|
+
widgetId: z.string(),
|
|
192
|
+
config: configSchema,
|
|
193
|
+
}).strict()
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export const ConfigureTableWidgetRequestZodSchema = configureWidgetRequestSchema(ConfigurableTableWidgetConfigSchema)
|
|
197
|
+
export const ConfigureKpiCardWidgetRequestZodSchema = configureWidgetRequestSchema(ConfigurableKpiCardWidgetConfigSchema)
|
|
198
|
+
export const ConfigureGaugeCardWidgetRequestZodSchema = configureWidgetRequestSchema(ConfigurableGaugeCardWidgetConfigSchema)
|
|
199
|
+
export const ConfigureLineChartWidgetRequestZodSchema = configureWidgetRequestSchema(ConfigurableLineChartWidgetConfigSchema)
|
|
200
|
+
export const ConfigureBarChartWidgetRequestZodSchema = configureWidgetRequestSchema(ConfigurableBarChartWidgetConfigSchema)
|
|
201
|
+
export const ConfigureStackedBarChartWidgetRequestZodSchema = configureWidgetRequestSchema(ConfigurableStackedBarChartWidgetConfigSchema)
|
|
202
|
+
export const ConfigurePieChartWidgetRequestZodSchema = configureWidgetRequestSchema(ConfigurablePieChartWidgetConfigSchema)
|
|
203
|
+
export const ConfigureHistogramChartWidgetRequestZodSchema = configureWidgetRequestSchema(ConfigurableHistogramChartWidgetConfigSchema)
|
|
204
|
+
export const ConfigureFunnelChartWidgetRequestZodSchema = configureWidgetRequestSchema(ConfigurableFunnelChartWidgetConfigSchema)
|
|
205
|
+
export const ConfigurePivotTableWidgetRequestZodSchema = configureWidgetRequestSchema(ConfigurablePivotTableWidgetConfigSchema)
|
|
206
|
+
|
|
207
|
+
export const DashboardMutationResponseZodSchema = z.union([
|
|
208
|
+
z.object({
|
|
209
|
+
ok: z.literal(true),
|
|
210
|
+
slug: z.string(),
|
|
211
|
+
widgetId: z.string().optional(),
|
|
212
|
+
groupId: z.string().optional(),
|
|
213
|
+
target: z.string().optional(),
|
|
214
|
+
revision: z.number().optional(),
|
|
215
|
+
}).strict(),
|
|
216
|
+
DashboardErrorResponseZodSchema,
|
|
217
|
+
])
|
|
218
|
+
|
|
219
|
+
export const DashboardApiResponseSchema = toJSONSchema(DashboardApiResponseZodSchema, { target: 'draft-07' })
|
|
220
|
+
export const DashboardWidgetDataResponseSchema = toJSONSchema(DashboardWidgetDataResponseZodSchema, { target: 'draft-07' })
|
|
221
|
+
export const SlugRequestSchema = toJSONSchema(SlugRequestZodSchema, { target: 'draft-07' })
|
|
222
|
+
export const GroupIdRequestSchema = toJSONSchema(GroupIdRequestZodSchema, { target: 'draft-07' })
|
|
223
|
+
export const MoveGroupRequestSchema = toJSONSchema(MoveGroupRequestZodSchema, { target: 'draft-07' })
|
|
224
|
+
export const SetGroupConfigRequestSchema = toJSONSchema(SetGroupConfigRequestZodSchema, { target: 'draft-07' })
|
|
225
|
+
export const WidgetIdRequestSchema = toJSONSchema(WidgetIdRequestZodSchema, { target: 'draft-07' })
|
|
226
|
+
export const WidgetDataRequestSchema = toJSONSchema(WidgetDataRequestZodSchema, { target: 'draft-07' })
|
|
227
|
+
export const MoveWidgetRequestSchema = toJSONSchema(MoveWidgetRequestZodSchema, { target: 'draft-07' })
|
|
228
|
+
export const DashboardMutationResponseSchema = toJSONSchema(DashboardMutationResponseZodSchema, { target: 'draft-07' })
|
|
229
|
+
export const SetWidgetConfigRequestSchema = toJSONSchema(SetWidgetConfigRequestZodSchema, { target: 'draft-07' })
|
|
230
|
+
export const ConfigureTableWidgetRequestSchema = toJSONSchema(ConfigureTableWidgetRequestZodSchema, { target: 'draft-07' })
|
|
231
|
+
export const ConfigureKpiCardWidgetRequestSchema = toJSONSchema(ConfigureKpiCardWidgetRequestZodSchema, { target: 'draft-07' })
|
|
232
|
+
export const ConfigureGaugeCardWidgetRequestSchema = toJSONSchema(ConfigureGaugeCardWidgetRequestZodSchema, { target: 'draft-07' })
|
|
233
|
+
export const ConfigureLineChartWidgetRequestSchema = toJSONSchema(ConfigureLineChartWidgetRequestZodSchema, { target: 'draft-07' })
|
|
234
|
+
export const ConfigureBarChartWidgetRequestSchema = toJSONSchema(ConfigureBarChartWidgetRequestZodSchema, { target: 'draft-07' })
|
|
235
|
+
export const ConfigureStackedBarChartWidgetRequestSchema = toJSONSchema(ConfigureStackedBarChartWidgetRequestZodSchema, { target: 'draft-07' })
|
|
236
|
+
export const ConfigurePieChartWidgetRequestSchema = toJSONSchema(ConfigurePieChartWidgetRequestZodSchema, { target: 'draft-07' })
|
|
237
|
+
export const ConfigureHistogramChartWidgetRequestSchema = toJSONSchema(ConfigureHistogramChartWidgetRequestZodSchema, { target: 'draft-07' })
|
|
238
|
+
export const ConfigureFunnelChartWidgetRequestSchema = toJSONSchema(ConfigureFunnelChartWidgetRequestZodSchema, { target: 'draft-07' })
|
|
239
|
+
export const ConfigurePivotTableWidgetRequestSchema = toJSONSchema(ConfigurePivotTableWidgetRequestZodSchema, { target: 'draft-07' })
|
package/schema/widget.ts
CHANGED
|
@@ -1,432 +1,50 @@
|
|
|
1
1
|
import { z } from 'zod'
|
|
2
2
|
export type { DashboardWidgetConfigValidationError } from '../custom/model/dashboard.types.js'
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
'large',
|
|
7
|
-
'wide',
|
|
8
|
-
'full',
|
|
9
|
-
])
|
|
10
|
-
|
|
11
|
-
const ValueFormatSchema = z.enum([
|
|
12
|
-
'number',
|
|
13
|
-
'compact_number',
|
|
14
|
-
'currency',
|
|
15
|
-
'percent',
|
|
16
|
-
'percent_delta',
|
|
17
|
-
'number_delta',
|
|
18
|
-
'currency_delta',
|
|
19
|
-
]).optional()
|
|
20
|
-
|
|
21
|
-
const ChartFieldRefSchema = z.object({
|
|
22
|
-
field: z.string(),
|
|
23
|
-
label: z.string().optional(),
|
|
24
|
-
format: ValueFormatSchema,
|
|
25
|
-
}).strict()
|
|
26
|
-
|
|
27
|
-
const FieldRefSchema = z.union([
|
|
28
|
-
z.string(),
|
|
29
|
-
z.object({
|
|
30
|
-
field: z.string(),
|
|
31
|
-
label: z.string().optional(),
|
|
32
|
-
format: ValueFormatSchema,
|
|
33
|
-
}).strict(),
|
|
34
|
-
])
|
|
35
|
-
|
|
36
|
-
const JsonValueSchema: z.ZodType = z.lazy(() => z.union([
|
|
37
|
-
z.string(),
|
|
38
|
-
z.number(),
|
|
39
|
-
z.boolean(),
|
|
40
|
-
z.null(),
|
|
41
|
-
z.array(JsonValueSchema),
|
|
42
|
-
z.record(z.string(), JsonValueSchema),
|
|
43
|
-
]))
|
|
44
|
-
|
|
45
|
-
const FilterExpressionSchema: z.ZodType = z.lazy(() => z.union([
|
|
46
|
-
z.array(FilterExpressionSchema),
|
|
47
|
-
z.object({
|
|
48
|
-
and: z.array(FilterExpressionSchema),
|
|
49
|
-
}).strict(),
|
|
50
|
-
z.object({
|
|
51
|
-
or: z.array(FilterExpressionSchema),
|
|
52
|
-
}).strict(),
|
|
53
|
-
z.object({
|
|
54
|
-
field: z.string(),
|
|
55
|
-
eq: JsonValueSchema.optional(),
|
|
56
|
-
neq: JsonValueSchema.optional(),
|
|
57
|
-
gt: JsonValueSchema.optional(),
|
|
58
|
-
gte: JsonValueSchema.optional(),
|
|
59
|
-
lt: JsonValueSchema.optional(),
|
|
60
|
-
lte: JsonValueSchema.optional(),
|
|
61
|
-
in: z.array(JsonValueSchema).optional(),
|
|
62
|
-
not_in: z.array(JsonValueSchema).optional(),
|
|
63
|
-
like: JsonValueSchema.optional(),
|
|
64
|
-
ilike: JsonValueSchema.optional(),
|
|
65
|
-
}).strict(),
|
|
66
|
-
]))
|
|
67
|
-
|
|
68
|
-
const QueryAggregateOperationSchema = z.enum([
|
|
69
|
-
'sum',
|
|
70
|
-
'count',
|
|
71
|
-
'count_distinct',
|
|
72
|
-
'avg',
|
|
73
|
-
'min',
|
|
74
|
-
'max',
|
|
75
|
-
'median',
|
|
76
|
-
])
|
|
77
|
-
|
|
78
|
-
const QueryFieldSelectItemSchema = z.object({
|
|
79
|
-
field: z.string(),
|
|
80
|
-
as: z.string().optional(),
|
|
81
|
-
grain: z.enum(['day', 'week', 'month', 'year']).optional(),
|
|
82
|
-
}).strict()
|
|
83
|
-
|
|
84
|
-
const QueryAggregateSelectItemSchema = z.object({
|
|
85
|
-
agg: QueryAggregateOperationSchema,
|
|
86
|
-
field: z.string().optional(),
|
|
87
|
-
as: z.string(),
|
|
88
|
-
filters: FilterExpressionSchema.optional(),
|
|
89
|
-
}).strict().superRefine((item, ctx) => {
|
|
90
|
-
if (!['count'].includes(item.agg) && !item.field) {
|
|
91
|
-
ctx.addIssue({
|
|
92
|
-
code: 'custom',
|
|
93
|
-
path: ['field'],
|
|
94
|
-
message: `field is required for ${item.agg}`,
|
|
95
|
-
})
|
|
96
|
-
}
|
|
97
|
-
})
|
|
98
|
-
|
|
99
|
-
const QueryCalcSelectItemSchema = z.object({
|
|
100
|
-
calc: z.string(),
|
|
101
|
-
as: z.string(),
|
|
102
|
-
}).strict()
|
|
103
|
-
|
|
104
|
-
const QuerySelectItemSchema = z.union([
|
|
105
|
-
QueryFieldSelectItemSchema,
|
|
106
|
-
QueryAggregateSelectItemSchema,
|
|
107
|
-
QueryCalcSelectItemSchema,
|
|
108
|
-
])
|
|
109
|
-
|
|
110
|
-
const QueryGroupByItemSchema = z.union([
|
|
111
|
-
z.string(),
|
|
112
|
-
z.object({
|
|
113
|
-
field: z.string(),
|
|
114
|
-
as: z.string().optional(),
|
|
115
|
-
grain: z.enum(['day', 'week', 'month', 'year']).optional(),
|
|
116
|
-
timezone: z.string().optional(),
|
|
117
|
-
}).strict(),
|
|
118
|
-
])
|
|
119
|
-
|
|
120
|
-
const QueryOrderByItemSchema = z.object({
|
|
121
|
-
field: z.string(),
|
|
122
|
-
direction: z.enum(['asc', 'desc']).optional(),
|
|
123
|
-
}).strict()
|
|
124
|
-
|
|
125
|
-
const TimeSeriesConfigSchema = z.object({
|
|
126
|
-
field: z.string(),
|
|
127
|
-
grain: z.enum(['day', 'week', 'month', 'year']),
|
|
128
|
-
timezone: z.string().optional(),
|
|
129
|
-
}).strict()
|
|
130
|
-
|
|
131
|
-
const PeriodConfigSchema = z.object({
|
|
132
|
-
field: z.string(),
|
|
133
|
-
gte: JsonValueSchema.optional(),
|
|
134
|
-
lt: JsonValueSchema.optional(),
|
|
135
|
-
}).strict()
|
|
136
|
-
|
|
137
|
-
const BucketConfigSchema = z.object({
|
|
138
|
-
field: z.string(),
|
|
139
|
-
buckets: z.array(z.object({
|
|
140
|
-
label: z.string(),
|
|
141
|
-
min: z.number().optional(),
|
|
142
|
-
max: z.number().optional(),
|
|
143
|
-
}).strict()),
|
|
144
|
-
}).strict()
|
|
145
|
-
|
|
146
|
-
const QueryCalcItemSchema = z.object({
|
|
147
|
-
calc: z.string(),
|
|
148
|
-
as: z.string(),
|
|
149
|
-
}).strict()
|
|
150
|
-
|
|
151
|
-
const FormattingConfigSchema = z.record(z.string(), JsonValueSchema)
|
|
152
|
-
const VariablesConfigSchema = z.record(z.string(), JsonValueSchema)
|
|
153
|
-
|
|
154
|
-
export const QueryConfigSchema = z.object({
|
|
155
|
-
resource: z.string(),
|
|
156
|
-
select: z.array(QuerySelectItemSchema).optional(),
|
|
157
|
-
filters: FilterExpressionSchema.optional(),
|
|
158
|
-
group_by: z.array(QueryGroupByItemSchema).optional(),
|
|
159
|
-
order_by: z.array(QueryOrderByItemSchema).optional(),
|
|
160
|
-
limit: z.number().int().positive().optional(),
|
|
161
|
-
offset: z.number().int().nonnegative().optional(),
|
|
162
|
-
time_series: TimeSeriesConfigSchema.optional(),
|
|
163
|
-
period: PeriodConfigSchema.optional(),
|
|
164
|
-
bucket: BucketConfigSchema.optional(),
|
|
165
|
-
calcs: z.array(QueryCalcItemSchema).optional(),
|
|
166
|
-
formatting: FormattingConfigSchema.optional(),
|
|
167
|
-
}).strict()
|
|
168
|
-
|
|
169
|
-
const FunnelQueryStepSchema = z.object({
|
|
170
|
-
name: z.string(),
|
|
171
|
-
resource: z.string(),
|
|
172
|
-
metric: QueryAggregateSelectItemSchema,
|
|
173
|
-
filters: FilterExpressionSchema.optional(),
|
|
174
|
-
}).strict()
|
|
175
|
-
|
|
176
|
-
export const FunnelQueryConfigSchema = z.object({
|
|
177
|
-
steps: z.array(FunnelQueryStepSchema).min(1),
|
|
178
|
-
calcs: z.array(QueryCalcItemSchema).optional(),
|
|
179
|
-
}).strict()
|
|
180
|
-
|
|
181
|
-
const EditableWidgetBaseSchema = z.object({
|
|
182
|
-
label: z.string().optional(),
|
|
183
|
-
variables: VariablesConfigSchema.optional(),
|
|
184
|
-
size: DashboardWidgetSizeSchema.optional(),
|
|
185
|
-
width: z.number().positive('Width must be greater than 0').optional(),
|
|
186
|
-
height: z.number().positive('Height must be greater than 0').optional(),
|
|
187
|
-
min_width: z.number().nonnegative('Min width must be a non-negative number').optional(),
|
|
188
|
-
max_width: z.number().nonnegative('Max width must be a non-negative number').nullable().optional(),
|
|
189
|
-
}).strict()
|
|
190
|
-
|
|
191
|
-
const StoredWidgetBaseSchema = EditableWidgetBaseSchema.extend({
|
|
192
|
-
id: z.string(),
|
|
193
|
-
group_id: z.string(),
|
|
194
|
-
order: z.number(),
|
|
195
|
-
})
|
|
196
|
-
|
|
197
|
-
const TableViewConfigSchema = z.object({
|
|
198
|
-
columns: z.array(FieldRefSchema).optional(),
|
|
199
|
-
pagination: z.boolean().optional(),
|
|
200
|
-
page_size: z.number().int().positive().optional(),
|
|
201
|
-
}).strict()
|
|
202
|
-
|
|
203
|
-
const ChartBaseSchema = z.object({
|
|
204
|
-
title: z.string().optional(),
|
|
205
|
-
}).strict()
|
|
206
|
-
|
|
207
|
-
const ChartBucketSchema = z.object({
|
|
208
|
-
label: z.string().min(1, 'Bucket label is required'),
|
|
209
|
-
min: z.number().optional(),
|
|
210
|
-
max: z.number().optional(),
|
|
211
|
-
}).strict()
|
|
212
|
-
|
|
213
|
-
const ChartSeriesRefSchema = z.object({
|
|
214
|
-
field: z.string(),
|
|
215
|
-
label: z.string().optional(),
|
|
216
|
-
}).strict()
|
|
217
|
-
|
|
218
|
-
const LineChartSchema = ChartBaseSchema.extend({
|
|
219
|
-
type: z.literal('line'),
|
|
220
|
-
x: ChartFieldRefSchema,
|
|
221
|
-
y: z.array(ChartFieldRefSchema).min(1),
|
|
222
|
-
series: ChartSeriesRefSchema.optional(),
|
|
223
|
-
color: z.string().optional(),
|
|
224
|
-
colors: z.array(z.string()).optional(),
|
|
225
|
-
})
|
|
226
|
-
|
|
227
|
-
const BarChartSchema = ChartBaseSchema.extend({
|
|
228
|
-
type: z.literal('bar'),
|
|
229
|
-
x: ChartFieldRefSchema,
|
|
230
|
-
y: ChartFieldRefSchema,
|
|
231
|
-
color: z.string().optional(),
|
|
232
|
-
})
|
|
233
|
-
|
|
234
|
-
const StackedBarChartSchema = ChartBaseSchema.extend({
|
|
235
|
-
type: z.literal('stacked_bar'),
|
|
236
|
-
x: ChartFieldRefSchema,
|
|
237
|
-
y: z.union([ChartFieldRefSchema, z.array(ChartFieldRefSchema).min(1)]),
|
|
238
|
-
series: ChartSeriesRefSchema.optional(),
|
|
239
|
-
colors: z.array(z.string()).optional(),
|
|
240
|
-
})
|
|
241
|
-
|
|
242
|
-
const PieChartSchema = ChartBaseSchema.extend({
|
|
243
|
-
type: z.literal('pie'),
|
|
244
|
-
label: ChartFieldRefSchema,
|
|
245
|
-
value: ChartFieldRefSchema,
|
|
246
|
-
colors: z.array(z.string()).optional(),
|
|
247
|
-
})
|
|
248
|
-
|
|
249
|
-
const HistogramChartSchema = ChartBaseSchema.extend({
|
|
250
|
-
type: z.literal('histogram'),
|
|
251
|
-
x: ChartFieldRefSchema,
|
|
252
|
-
y: ChartFieldRefSchema,
|
|
253
|
-
buckets: z.array(ChartBucketSchema).optional(),
|
|
254
|
-
color: z.string().optional(),
|
|
255
|
-
})
|
|
256
|
-
|
|
257
|
-
const FunnelChartSchema = ChartBaseSchema.extend({
|
|
258
|
-
type: z.literal('funnel'),
|
|
259
|
-
label: ChartFieldRefSchema.optional(),
|
|
260
|
-
value: ChartFieldRefSchema.optional(),
|
|
261
|
-
colors: z.array(z.string()).optional(),
|
|
262
|
-
})
|
|
263
|
-
|
|
264
|
-
export const ChartConfigSchema = z.discriminatedUnion('type', [
|
|
265
|
-
LineChartSchema,
|
|
3
|
+
export {
|
|
4
|
+
BarChartWidgetConfigSchema,
|
|
5
|
+
ChartWidgetTargetConfigSchema,
|
|
266
6
|
BarChartSchema,
|
|
267
|
-
|
|
268
|
-
PieChartSchema,
|
|
269
|
-
HistogramChartSchema,
|
|
7
|
+
FunnelChartWidgetConfigSchema,
|
|
270
8
|
FunnelChartSchema,
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
const PivotTableViewConfigSchema = z.object({
|
|
312
|
-
rows: z.array(FieldRefSchema).min(1),
|
|
313
|
-
columns: z.array(FieldRefSchema).optional(),
|
|
314
|
-
values: z.array(z.object({
|
|
315
|
-
field: z.string(),
|
|
316
|
-
label: z.string().optional(),
|
|
317
|
-
format: ValueFormatSchema,
|
|
318
|
-
aggregation: z.enum(['sum', 'count', 'avg', 'min', 'max']).optional(),
|
|
319
|
-
}).strict()).min(1),
|
|
320
|
-
}).strict()
|
|
321
|
-
|
|
322
|
-
const EditableEmptyWidgetConfigSchema = EditableWidgetBaseSchema.extend({
|
|
323
|
-
target: z.literal('empty'),
|
|
324
|
-
})
|
|
325
|
-
|
|
326
|
-
export const EmptyWidgetConfigSchema = StoredWidgetBaseSchema.extend({
|
|
327
|
-
target: z.literal('empty'),
|
|
328
|
-
})
|
|
329
|
-
|
|
330
|
-
const EditableTableWidgetConfigSchema = EditableWidgetBaseSchema.extend({
|
|
331
|
-
target: z.literal('table'),
|
|
332
|
-
table: TableViewConfigSchema.optional(),
|
|
333
|
-
query: QueryConfigSchema,
|
|
334
|
-
})
|
|
335
|
-
|
|
336
|
-
const TableWidgetConfigSchema = StoredWidgetBaseSchema.extend({
|
|
337
|
-
target: z.literal('table'),
|
|
338
|
-
table: TableViewConfigSchema.optional(),
|
|
339
|
-
query: QueryConfigSchema,
|
|
340
|
-
})
|
|
341
|
-
|
|
342
|
-
const EditableChartWidgetTargetConfigSchema = EditableWidgetBaseSchema.extend({
|
|
343
|
-
target: z.literal('chart'),
|
|
344
|
-
chart: ChartConfigSchema,
|
|
345
|
-
query: z.union([QueryConfigSchema, FunnelQueryConfigSchema]),
|
|
346
|
-
}).superRefine((widget, ctx) => {
|
|
347
|
-
const isFunnelChart = widget.chart.type === 'funnel'
|
|
348
|
-
const isFunnelQuery = 'steps' in widget.query
|
|
349
|
-
|
|
350
|
-
if (isFunnelChart && !isFunnelQuery) {
|
|
351
|
-
ctx.addIssue({
|
|
352
|
-
code: 'custom',
|
|
353
|
-
path: ['query'],
|
|
354
|
-
message: 'Funnel charts must use steps query',
|
|
355
|
-
})
|
|
356
|
-
}
|
|
357
|
-
})
|
|
358
|
-
|
|
359
|
-
const ChartWidgetTargetConfigSchema = StoredWidgetBaseSchema.extend({
|
|
360
|
-
target: z.literal('chart'),
|
|
361
|
-
chart: ChartConfigSchema,
|
|
362
|
-
query: z.union([QueryConfigSchema, FunnelQueryConfigSchema]),
|
|
363
|
-
}).superRefine((widget, ctx) => {
|
|
364
|
-
const isFunnelChart = widget.chart.type === 'funnel'
|
|
365
|
-
const isFunnelQuery = 'steps' in widget.query
|
|
366
|
-
|
|
367
|
-
if (isFunnelChart && !isFunnelQuery) {
|
|
368
|
-
ctx.addIssue({
|
|
369
|
-
code: 'custom',
|
|
370
|
-
path: ['query'],
|
|
371
|
-
message: 'Funnel charts must use steps query',
|
|
372
|
-
})
|
|
373
|
-
}
|
|
374
|
-
})
|
|
375
|
-
|
|
376
|
-
const EditableKpiCardWidgetConfigSchema = EditableWidgetBaseSchema.extend({
|
|
377
|
-
target: z.literal('kpi_card'),
|
|
378
|
-
card: KpiCardViewConfigSchema,
|
|
379
|
-
query: QueryConfigSchema,
|
|
380
|
-
})
|
|
381
|
-
|
|
382
|
-
const KpiCardWidgetConfigSchema = StoredWidgetBaseSchema.extend({
|
|
383
|
-
target: z.literal('kpi_card'),
|
|
384
|
-
card: KpiCardViewConfigSchema,
|
|
385
|
-
query: QueryConfigSchema,
|
|
386
|
-
})
|
|
387
|
-
|
|
388
|
-
const EditableGaugeCardWidgetConfigSchema = EditableWidgetBaseSchema.extend({
|
|
389
|
-
target: z.literal('gauge_card'),
|
|
390
|
-
card: GaugeCardViewConfigSchema,
|
|
391
|
-
query: QueryConfigSchema,
|
|
392
|
-
})
|
|
393
|
-
|
|
394
|
-
const GaugeCardWidgetConfigSchema = StoredWidgetBaseSchema.extend({
|
|
395
|
-
target: z.literal('gauge_card'),
|
|
396
|
-
card: GaugeCardViewConfigSchema,
|
|
397
|
-
query: QueryConfigSchema,
|
|
398
|
-
})
|
|
399
|
-
|
|
400
|
-
const EditablePivotTableWidgetConfigSchema = EditableWidgetBaseSchema.extend({
|
|
401
|
-
target: z.literal('pivot_table'),
|
|
402
|
-
pivot: PivotTableViewConfigSchema,
|
|
403
|
-
query: QueryConfigSchema,
|
|
404
|
-
})
|
|
405
|
-
|
|
406
|
-
const PivotTableWidgetConfigSchema = StoredWidgetBaseSchema.extend({
|
|
407
|
-
target: z.literal('pivot_table'),
|
|
408
|
-
pivot: PivotTableViewConfigSchema,
|
|
409
|
-
query: QueryConfigSchema,
|
|
410
|
-
})
|
|
411
|
-
|
|
412
|
-
export const EditableDashboardWidgetConfigSchema = z.discriminatedUnion('target', [
|
|
413
|
-
EditableEmptyWidgetConfigSchema,
|
|
414
|
-
EditableTableWidgetConfigSchema,
|
|
415
|
-
EditableChartWidgetTargetConfigSchema,
|
|
416
|
-
EditableKpiCardWidgetConfigSchema,
|
|
417
|
-
EditableGaugeCardWidgetConfigSchema,
|
|
418
|
-
EditablePivotTableWidgetConfigSchema,
|
|
419
|
-
])
|
|
420
|
-
|
|
421
|
-
export const WidgetConfigSchema = z.discriminatedUnion('target', [
|
|
422
|
-
EditableTableWidgetConfigSchema,
|
|
423
|
-
EditableChartWidgetTargetConfigSchema,
|
|
424
|
-
EditableKpiCardWidgetConfigSchema,
|
|
425
|
-
EditableGaugeCardWidgetConfigSchema,
|
|
426
|
-
EditablePivotTableWidgetConfigSchema,
|
|
427
|
-
])
|
|
428
|
-
|
|
429
|
-
export const StoredWidgetConfigSchema = z.discriminatedUnion('target', [
|
|
9
|
+
HistogramChartSchema,
|
|
10
|
+
HistogramChartWidgetConfigSchema,
|
|
11
|
+
LineChartWidgetConfigSchema,
|
|
12
|
+
LineChartSchema,
|
|
13
|
+
PieChartSchema,
|
|
14
|
+
PieChartWidgetConfigSchema,
|
|
15
|
+
StackedBarChartSchema,
|
|
16
|
+
StackedBarChartWidgetConfigSchema,
|
|
17
|
+
} from './widgets/charts.js'
|
|
18
|
+
export {
|
|
19
|
+
GaugeCardWidgetConfigSchema,
|
|
20
|
+
GaugeCardViewConfigSchema,
|
|
21
|
+
} from './widgets/gauge-card.js'
|
|
22
|
+
export {
|
|
23
|
+
KpiCardViewConfigSchema,
|
|
24
|
+
KpiCardWidgetConfigSchema,
|
|
25
|
+
} from './widgets/kpi-card.js'
|
|
26
|
+
export {
|
|
27
|
+
PivotTableViewConfigSchema,
|
|
28
|
+
PivotTableWidgetConfigSchema,
|
|
29
|
+
} from './widgets/pivot-table.js'
|
|
30
|
+
export {
|
|
31
|
+
TableViewConfigSchema,
|
|
32
|
+
TableWidgetConfigSchema,
|
|
33
|
+
} from './widgets/table.js'
|
|
34
|
+
export {
|
|
35
|
+
EmptyWidgetConfigSchema,
|
|
36
|
+
FunnelQueryConfigSchema,
|
|
37
|
+
QueryConfigSchema,
|
|
38
|
+
WidgetEditableBaseSchema,
|
|
39
|
+
} from './widgets/common.js'
|
|
40
|
+
import { ChartWidgetTargetConfigSchema } from './widgets/charts.js'
|
|
41
|
+
import { GaugeCardWidgetConfigSchema } from './widgets/gauge-card.js'
|
|
42
|
+
import { KpiCardWidgetConfigSchema } from './widgets/kpi-card.js'
|
|
43
|
+
import { PivotTableWidgetConfigSchema } from './widgets/pivot-table.js'
|
|
44
|
+
import { TableWidgetConfigSchema } from './widgets/table.js'
|
|
45
|
+
import { EmptyWidgetConfigSchema } from './widgets/common.js'
|
|
46
|
+
|
|
47
|
+
export const WidgetConfigSchema = z.union([
|
|
430
48
|
EmptyWidgetConfigSchema,
|
|
431
49
|
TableWidgetConfigSchema,
|
|
432
50
|
ChartWidgetTargetConfigSchema,
|