@adminforth/dashboard 1.2.0 → 1.3.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/README.md +47 -39
- package/custom/composables/useElementSize.ts +17 -2
- package/custom/model/dashboard.types.ts +327 -234
- package/custom/skills/adminforth-dashboard/SKILL.md +6 -2
- package/custom/widgets/chart/ChartWidget.vue +23 -55
- package/custom/widgets/chart/bar/BarChart.vue +20 -12
- package/custom/widgets/chart/chart.types.ts +17 -66
- package/custom/widgets/chart/chart.utils.ts +11 -0
- package/custom/widgets/chart/funnel/FunnelChart.vue +6 -4
- package/custom/widgets/chart/line/LineChart.vue +23 -15
- package/custom/widgets/chart/stacked-bar/StackedBarChart.vue +28 -43
- package/custom/widgets/gauge-card/GaugeCardWidget.vue +7 -12
- package/custom/widgets/kpi-card/KpiCardWidget.vue +6 -8
- package/custom/widgets/pivot-table/PivotTableWidget.vue +8 -7
- package/custom/widgets/table/TableWidget.vue +8 -3
- package/dist/custom/composables/useElementSize.js +14 -2
- package/dist/custom/composables/useElementSize.ts +17 -2
- package/dist/custom/model/dashboard.types.d.ts +178 -61
- package/dist/custom/model/dashboard.types.js +67 -92
- package/dist/custom/model/dashboard.types.ts +327 -234
- package/dist/custom/queries/useDashboardConfig.d.ts +832 -66
- package/dist/custom/queries/useWidgetData.d.ts +828 -62
- package/dist/custom/skills/adminforth-dashboard/SKILL.md +6 -2
- package/dist/custom/widgets/chart/ChartWidget.vue +23 -55
- package/dist/custom/widgets/chart/bar/BarChart.vue +20 -12
- package/dist/custom/widgets/chart/chart.types.d.ts +13 -22
- package/dist/custom/widgets/chart/chart.types.js +2 -25
- package/dist/custom/widgets/chart/chart.types.ts +17 -66
- package/dist/custom/widgets/chart/chart.utils.d.ts +1 -0
- package/dist/custom/widgets/chart/chart.utils.js +7 -0
- package/dist/custom/widgets/chart/chart.utils.ts +11 -0
- package/dist/custom/widgets/chart/funnel/FunnelChart.vue +6 -4
- package/dist/custom/widgets/chart/line/LineChart.vue +23 -15
- package/dist/custom/widgets/chart/stacked-bar/StackedBarChart.vue +28 -43
- package/dist/custom/widgets/gauge-card/GaugeCardWidget.vue +7 -12
- package/dist/custom/widgets/kpi-card/KpiCardWidget.vue +6 -8
- package/dist/custom/widgets/pivot-table/PivotTableWidget.vue +8 -7
- package/dist/custom/widgets/table/TableWidget.vue +8 -3
- package/dist/endpoint/widgets.js +5 -2
- package/dist/schema/api.d.ts +2680 -736
- package/dist/schema/widget.d.ts +1588 -476
- package/dist/schema/widget.js +205 -139
- package/dist/services/widgetConfigValidator.js +16 -40
- package/dist/services/widgetDataService.js +359 -82
- package/endpoint/dashboard.ts +1 -1
- package/endpoint/widgets.ts +5 -2
- package/package.json +1 -1
- package/schema/widget.ts +222 -139
- package/services/widgetConfigValidator.ts +29 -53
- package/services/widgetDataService.ts +484 -100
|
@@ -1,42 +1,5 @@
|
|
|
1
1
|
import type { ChartWidgetConfig } from '../widgets/chart/chart.types.js'
|
|
2
2
|
|
|
3
|
-
export type AggregationOperation = 'sum' | 'count' | 'avg' | 'min' | 'max' | 'median'
|
|
4
|
-
|
|
5
|
-
export type AggregationRule = {
|
|
6
|
-
operation: AggregationOperation
|
|
7
|
-
field?: string
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export type GroupByRule =
|
|
11
|
-
| {
|
|
12
|
-
type: 'field'
|
|
13
|
-
field: string
|
|
14
|
-
}
|
|
15
|
-
| {
|
|
16
|
-
type: 'date_trunc'
|
|
17
|
-
field: string
|
|
18
|
-
truncation: 'day' | 'week' | 'month' | 'year'
|
|
19
|
-
timezone?: string
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export type ResourceWidgetDataSource = {
|
|
23
|
-
type: 'resource'
|
|
24
|
-
resourceId: string
|
|
25
|
-
columns?: string[]
|
|
26
|
-
sort?: unknown
|
|
27
|
-
filters?: unknown
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export type AggregateWidgetDataSource = {
|
|
31
|
-
type: 'aggregate'
|
|
32
|
-
resourceId: string
|
|
33
|
-
aggregations: Record<string, AggregationRule>
|
|
34
|
-
groupBy?: GroupByRule
|
|
35
|
-
filters?: unknown
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export type WidgetDataSource = ResourceWidgetDataSource | AggregateWidgetDataSource
|
|
39
|
-
|
|
40
3
|
export type DashboardConfig = {
|
|
41
4
|
version: number
|
|
42
5
|
groups: DashboardGroupConfig[]
|
|
@@ -50,18 +13,19 @@ export type DashboardGroupConfig = {
|
|
|
50
13
|
}
|
|
51
14
|
|
|
52
15
|
export type DashboardGroupMoveDirection = 'up' | 'down'
|
|
53
|
-
|
|
54
16
|
export type DashboardWidgetMoveDirection = 'up' | 'down'
|
|
55
|
-
|
|
56
|
-
export type DashboardWidgetTarget =
|
|
57
|
-
| 'empty'
|
|
58
|
-
| 'table'
|
|
59
|
-
| 'chart'
|
|
60
|
-
| 'kpi_card'
|
|
61
|
-
| 'pivot_table'
|
|
62
|
-
| 'gauge_card'
|
|
63
|
-
|
|
17
|
+
export type DashboardWidgetTarget = 'empty' | 'table' | 'chart' | 'kpi_card' | 'pivot_table' | 'gauge_card'
|
|
64
18
|
export type DashboardWidgetSize = 'small' | 'medium' | 'large' | 'wide' | 'full'
|
|
19
|
+
export type QueryAggregateOperation = 'sum' | 'count' | 'count_distinct' | 'avg' | 'min' | 'max' | 'median'
|
|
20
|
+
export type TimeGrain = 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year'
|
|
21
|
+
export type ValueFormat =
|
|
22
|
+
| 'number'
|
|
23
|
+
| 'compact_number'
|
|
24
|
+
| 'currency'
|
|
25
|
+
| 'percent'
|
|
26
|
+
| 'percent_delta'
|
|
27
|
+
| 'number_delta'
|
|
28
|
+
| 'currency_delta'
|
|
65
29
|
|
|
66
30
|
export type WidgetLayout = {
|
|
67
31
|
size?: DashboardWidgetSize
|
|
@@ -71,7 +35,7 @@ export type WidgetLayout = {
|
|
|
71
35
|
height?: number
|
|
72
36
|
}
|
|
73
37
|
|
|
74
|
-
export type
|
|
38
|
+
export type WidgetBaseConfig = {
|
|
75
39
|
id: string
|
|
76
40
|
group_id: string
|
|
77
41
|
label?: string
|
|
@@ -81,15 +45,200 @@ export type DashboardWidgetConfig = {
|
|
|
81
45
|
minWidth?: number
|
|
82
46
|
maxWidth?: number | null
|
|
83
47
|
order: number
|
|
84
|
-
target: DashboardWidgetTarget
|
|
85
|
-
dataSource?: WidgetDataSource
|
|
86
|
-
chart?: ChartWidgetConfig
|
|
87
|
-
table?: unknown
|
|
88
|
-
kpi_card?: unknown
|
|
89
|
-
pivot_table?: unknown
|
|
90
|
-
gauge_card?: unknown
|
|
91
48
|
}
|
|
92
49
|
|
|
50
|
+
export type FilterExpression =
|
|
51
|
+
| { and: FilterExpression[] }
|
|
52
|
+
| { or: FilterExpression[] }
|
|
53
|
+
| Array<FilterExpression>
|
|
54
|
+
| {
|
|
55
|
+
field: string
|
|
56
|
+
eq?: unknown
|
|
57
|
+
neq?: unknown
|
|
58
|
+
gt?: unknown
|
|
59
|
+
gte?: unknown
|
|
60
|
+
lt?: unknown
|
|
61
|
+
lte?: unknown
|
|
62
|
+
in?: unknown[]
|
|
63
|
+
not_in?: unknown[]
|
|
64
|
+
like?: unknown
|
|
65
|
+
ilike?: unknown
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export type QueryFieldSelectItem = {
|
|
69
|
+
field: string
|
|
70
|
+
as?: string
|
|
71
|
+
grain?: TimeGrain
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export type QueryAggregateSelectItem = {
|
|
75
|
+
agg: QueryAggregateOperation
|
|
76
|
+
field?: string
|
|
77
|
+
as: string
|
|
78
|
+
filters?: FilterExpression
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export type QueryCalcSelectItem = {
|
|
82
|
+
calc: string
|
|
83
|
+
as: string
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export type QuerySelectItem = QueryFieldSelectItem | QueryAggregateSelectItem | QueryCalcSelectItem
|
|
87
|
+
|
|
88
|
+
export type QueryGroupByItem =
|
|
89
|
+
| string
|
|
90
|
+
| {
|
|
91
|
+
field: string
|
|
92
|
+
as?: string
|
|
93
|
+
grain?: TimeGrain
|
|
94
|
+
timezone?: string
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export type QueryOrderByItem = {
|
|
98
|
+
field: string
|
|
99
|
+
direction?: 'asc' | 'desc'
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export type QueryConfig = {
|
|
103
|
+
resource: string
|
|
104
|
+
select?: QuerySelectItem[]
|
|
105
|
+
filters?: FilterExpression
|
|
106
|
+
groupBy?: QueryGroupByItem[]
|
|
107
|
+
orderBy?: QueryOrderByItem[]
|
|
108
|
+
limit?: number
|
|
109
|
+
offset?: number
|
|
110
|
+
timeSeries?: {
|
|
111
|
+
field: string
|
|
112
|
+
grain: TimeGrain
|
|
113
|
+
timezone?: string
|
|
114
|
+
}
|
|
115
|
+
period?: {
|
|
116
|
+
field: string
|
|
117
|
+
gte?: unknown
|
|
118
|
+
lt?: unknown
|
|
119
|
+
}
|
|
120
|
+
bucket?: {
|
|
121
|
+
field: string
|
|
122
|
+
buckets: Array<{ label: string, min?: number, max?: number }>
|
|
123
|
+
}
|
|
124
|
+
calcs?: QueryCalcSelectItem[]
|
|
125
|
+
formatting?: Record<string, unknown>
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export type FunnelQueryConfig = {
|
|
129
|
+
steps: FunnelQueryStep[]
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export type FunnelQueryStep = {
|
|
133
|
+
name: string
|
|
134
|
+
resource: string
|
|
135
|
+
metric: QueryAggregateSelectItem
|
|
136
|
+
filters?: FilterExpression
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export type FieldRef = string | {
|
|
140
|
+
field: string
|
|
141
|
+
label?: string
|
|
142
|
+
format?: ValueFormat
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export type TableViewConfig = {
|
|
146
|
+
columns?: FieldRef[]
|
|
147
|
+
pagination?: boolean
|
|
148
|
+
pageSize?: number
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export type KpiCardViewConfig = {
|
|
152
|
+
title?: string
|
|
153
|
+
value: {
|
|
154
|
+
field: string
|
|
155
|
+
format?: ValueFormat
|
|
156
|
+
prefix?: string
|
|
157
|
+
suffix?: string
|
|
158
|
+
}
|
|
159
|
+
subtitle?: {
|
|
160
|
+
text?: string
|
|
161
|
+
field?: string
|
|
162
|
+
}
|
|
163
|
+
comparison?: unknown
|
|
164
|
+
sparkline?: unknown
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export type GaugeCardViewConfig = {
|
|
168
|
+
title?: string
|
|
169
|
+
value: {
|
|
170
|
+
field: string
|
|
171
|
+
format?: ValueFormat
|
|
172
|
+
prefix?: string
|
|
173
|
+
suffix?: string
|
|
174
|
+
}
|
|
175
|
+
target?: {
|
|
176
|
+
value?: number
|
|
177
|
+
field?: string
|
|
178
|
+
label?: string
|
|
179
|
+
}
|
|
180
|
+
progress?: {
|
|
181
|
+
valueField: string
|
|
182
|
+
targetValue?: number
|
|
183
|
+
targetField?: string
|
|
184
|
+
format?: ValueFormat
|
|
185
|
+
}
|
|
186
|
+
color?: string
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export type PivotTableViewConfig = {
|
|
190
|
+
rows: FieldRef[]
|
|
191
|
+
columns?: FieldRef[]
|
|
192
|
+
values: Array<{
|
|
193
|
+
field: string
|
|
194
|
+
label?: string
|
|
195
|
+
format?: ValueFormat
|
|
196
|
+
aggregation?: 'sum' | 'count' | 'avg' | 'min' | 'max'
|
|
197
|
+
}>
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export type EmptyWidgetConfig = WidgetBaseConfig & {
|
|
201
|
+
target: 'empty'
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export type TableWidgetConfig = WidgetBaseConfig & {
|
|
205
|
+
target: 'table'
|
|
206
|
+
table?: TableViewConfig
|
|
207
|
+
query: QueryConfig
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export type ChartDashboardWidgetConfig = WidgetBaseConfig & {
|
|
211
|
+
target: 'chart'
|
|
212
|
+
chart: ChartWidgetConfig
|
|
213
|
+
query: QueryConfig | FunnelQueryConfig
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export type KpiCardWidgetConfig = WidgetBaseConfig & {
|
|
217
|
+
target: 'kpi_card'
|
|
218
|
+
card: KpiCardViewConfig
|
|
219
|
+
query: QueryConfig
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export type GaugeCardWidgetConfig = WidgetBaseConfig & {
|
|
223
|
+
target: 'gauge_card'
|
|
224
|
+
card: GaugeCardViewConfig
|
|
225
|
+
query: QueryConfig
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export type PivotTableWidgetConfig = WidgetBaseConfig & {
|
|
229
|
+
target: 'pivot_table'
|
|
230
|
+
pivot: PivotTableViewConfig
|
|
231
|
+
query: QueryConfig
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export type DashboardWidgetConfig =
|
|
235
|
+
| EmptyWidgetConfig
|
|
236
|
+
| TableWidgetConfig
|
|
237
|
+
| ChartDashboardWidgetConfig
|
|
238
|
+
| KpiCardWidgetConfig
|
|
239
|
+
| GaugeCardWidgetConfig
|
|
240
|
+
| PivotTableWidgetConfig
|
|
241
|
+
|
|
93
242
|
export type DashboardWidgetTableData = {
|
|
94
243
|
kind?: 'table'
|
|
95
244
|
columns: string[]
|
|
@@ -107,34 +256,16 @@ export type DashboardWidgetAggregateData = {
|
|
|
107
256
|
columns: string[]
|
|
108
257
|
rows: Record<string, unknown>[]
|
|
109
258
|
values?: Record<string, unknown>
|
|
259
|
+
pagination?: {
|
|
260
|
+
page: number
|
|
261
|
+
pageSize: number
|
|
262
|
+
total: number
|
|
263
|
+
totalPages: number
|
|
264
|
+
}
|
|
110
265
|
}
|
|
111
266
|
|
|
112
267
|
export type DashboardWidgetData = DashboardWidgetTableData | DashboardWidgetAggregateData
|
|
113
268
|
|
|
114
|
-
export type NormalizedKpiCardWidgetConfig = {
|
|
115
|
-
valueField?: string
|
|
116
|
-
labelField?: string
|
|
117
|
-
prefix?: string
|
|
118
|
-
suffix?: string
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export type NormalizedGaugeCardWidgetConfig = {
|
|
122
|
-
valueField?: string
|
|
123
|
-
min?: number | string
|
|
124
|
-
max?: number | string
|
|
125
|
-
minField?: string
|
|
126
|
-
maxField?: string
|
|
127
|
-
suffix?: string
|
|
128
|
-
color?: string
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export type NormalizedPivotTableWidgetConfig = {
|
|
132
|
-
rowField?: string
|
|
133
|
-
columnField?: string
|
|
134
|
-
valueField?: string
|
|
135
|
-
aggregation?: 'count' | 'sum'
|
|
136
|
-
}
|
|
137
|
-
|
|
138
269
|
export function normalizeDashboardConfig(config: unknown): DashboardConfig {
|
|
139
270
|
const value = isRecord(config) ? config : {}
|
|
140
271
|
|
|
@@ -155,12 +286,20 @@ export function normalizeDashboardWidgetConfig(config: unknown) {
|
|
|
155
286
|
const normalized: Record<string, unknown> = { ...config }
|
|
156
287
|
normalizeWidgetLayoutConfig(normalized)
|
|
157
288
|
|
|
289
|
+
if (normalized.query !== undefined) {
|
|
290
|
+
normalized.query = normalizeQueryConfig(normalized.query)
|
|
291
|
+
}
|
|
292
|
+
|
|
158
293
|
if (normalized.table !== undefined) {
|
|
159
294
|
normalized.table = normalizeTableConfig(normalized.table)
|
|
160
295
|
}
|
|
161
296
|
|
|
162
|
-
if (normalized.
|
|
163
|
-
normalized.
|
|
297
|
+
if (normalized.card !== undefined) {
|
|
298
|
+
normalized.card = normalizeCardConfig(normalized.card)
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (normalized.pivot !== undefined) {
|
|
302
|
+
normalized.pivot = normalizePivotConfig(normalized.pivot)
|
|
164
303
|
}
|
|
165
304
|
|
|
166
305
|
const target = normalizeDashboardWidgetTarget(normalized.target)
|
|
@@ -185,82 +324,31 @@ export function serializeDashboardWidgetConfigForEditor(widget: DashboardWidgetC
|
|
|
185
324
|
delete serialized.maxWidth
|
|
186
325
|
}
|
|
187
326
|
|
|
188
|
-
if (
|
|
189
|
-
serialized.
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (widget.dataSource !== undefined) {
|
|
193
|
-
serialized.data_source = serializeWidgetDataSourceForEditor(widget.dataSource)
|
|
194
|
-
delete serialized.dataSource
|
|
327
|
+
if ('query' in widget) {
|
|
328
|
+
serialized.query = serializeQueryConfigForEditor(widget.query)
|
|
195
329
|
}
|
|
196
330
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
export function normalizeKpiCardWidgetConfig(value: unknown): NormalizedKpiCardWidgetConfig | undefined {
|
|
201
|
-
const config = asWidgetConfigRecord(value)
|
|
202
|
-
|
|
203
|
-
if (!config) {
|
|
204
|
-
return undefined
|
|
331
|
+
if ('table' in widget && widget.table !== undefined) {
|
|
332
|
+
serialized.table = serializeTableConfigForEditor(widget.table)
|
|
205
333
|
}
|
|
206
334
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
const prefix = getStringField(config, 'prefix')
|
|
210
|
-
const suffix = getStringField(config, 'suffix')
|
|
211
|
-
|
|
212
|
-
return {
|
|
213
|
-
...(valueField !== undefined ? { valueField } : {}),
|
|
214
|
-
...(labelField !== undefined ? { labelField } : {}),
|
|
215
|
-
...(prefix !== undefined ? { prefix } : {}),
|
|
216
|
-
...(suffix !== undefined ? { suffix } : {}),
|
|
335
|
+
if ('card' in widget && widget.card !== undefined) {
|
|
336
|
+
serialized.card = serializeCardConfigForEditor(widget.card)
|
|
217
337
|
}
|
|
218
|
-
}
|
|
219
338
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
if (!config) {
|
|
224
|
-
return undefined
|
|
339
|
+
if ('pivot' in widget && widget.pivot !== undefined) {
|
|
340
|
+
serialized.pivot = serializePivotConfigForEditor(widget.pivot)
|
|
225
341
|
}
|
|
226
342
|
|
|
227
|
-
|
|
228
|
-
const minField = getStringField(config, 'min_field')
|
|
229
|
-
const maxField = getStringField(config, 'max_field')
|
|
230
|
-
const suffix = getStringField(config, 'suffix')
|
|
231
|
-
const color = getStringField(config, 'color')
|
|
232
|
-
|
|
233
|
-
return {
|
|
234
|
-
...(valueField !== undefined ? { valueField } : {}),
|
|
235
|
-
...(config.min !== undefined ? { min: config.min as number | string } : {}),
|
|
236
|
-
...(config.max !== undefined ? { max: config.max as number | string } : {}),
|
|
237
|
-
...(minField !== undefined ? { minField } : {}),
|
|
238
|
-
...(maxField !== undefined ? { maxField } : {}),
|
|
239
|
-
...(suffix !== undefined ? { suffix } : {}),
|
|
240
|
-
...(color !== undefined ? { color } : {}),
|
|
241
|
-
}
|
|
343
|
+
return serialized
|
|
242
344
|
}
|
|
243
345
|
|
|
244
|
-
export function
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
if (!config) {
|
|
248
|
-
return undefined
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
const rowField = getStringField(config, 'row_field')
|
|
252
|
-
const columnField = getStringField(config, 'column_field')
|
|
253
|
-
const valueField = getStringField(config, 'value_field')
|
|
254
|
-
const aggregation = config.aggregation === 'count' || config.aggregation === 'sum'
|
|
255
|
-
? config.aggregation
|
|
256
|
-
: undefined
|
|
346
|
+
export function getFieldRefField(value: FieldRef | undefined) {
|
|
347
|
+
return typeof value === 'string' ? value : value?.field
|
|
348
|
+
}
|
|
257
349
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
...(columnField !== undefined ? { columnField } : {}),
|
|
261
|
-
...(valueField !== undefined ? { valueField } : {}),
|
|
262
|
-
...(aggregation !== undefined ? { aggregation } : {}),
|
|
263
|
-
}
|
|
350
|
+
export function getFieldRefLabel(value: FieldRef | undefined) {
|
|
351
|
+
return typeof value === 'string' ? value : value?.label
|
|
264
352
|
}
|
|
265
353
|
|
|
266
354
|
function normalizeDashboardWidgetTarget(value: unknown): DashboardWidgetTarget | undefined {
|
|
@@ -287,138 +375,143 @@ function normalizeWidgetLayoutConfig(value: Record<string, unknown>) {
|
|
|
287
375
|
}
|
|
288
376
|
}
|
|
289
377
|
|
|
290
|
-
function
|
|
378
|
+
function normalizeQueryConfig(value: unknown): unknown {
|
|
291
379
|
if (!isRecord(value)) {
|
|
292
380
|
return value
|
|
293
381
|
}
|
|
294
382
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
383
|
+
if (Array.isArray(value.steps)) {
|
|
384
|
+
return {
|
|
385
|
+
steps: value.steps.map((step) => normalizeFunnelQueryStep(step)),
|
|
386
|
+
}
|
|
299
387
|
}
|
|
300
388
|
|
|
301
|
-
return
|
|
389
|
+
return {
|
|
390
|
+
...value,
|
|
391
|
+
...(Array.isArray(value.group_by) ? { groupBy: value.group_by } : {}),
|
|
392
|
+
...(Array.isArray(value.order_by) ? { orderBy: value.order_by } : {}),
|
|
393
|
+
...(value.time_series !== undefined ? { timeSeries: value.time_series } : {}),
|
|
394
|
+
}
|
|
302
395
|
}
|
|
303
396
|
|
|
304
|
-
function
|
|
305
|
-
if (!isRecord(value)
|
|
397
|
+
function normalizeFunnelQueryStep(value: unknown) {
|
|
398
|
+
if (!isRecord(value)) {
|
|
306
399
|
return value
|
|
307
400
|
}
|
|
308
401
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
:
|
|
312
|
-
|
|
313
|
-
if (value.type === 'resource') {
|
|
314
|
-
return {
|
|
315
|
-
type: 'resource',
|
|
316
|
-
...(resourceId !== undefined ? { resourceId } : {}),
|
|
317
|
-
...(value.columns !== undefined ? { columns: value.columns } : {}),
|
|
318
|
-
...(value.filters !== undefined ? { filters: value.filters } : {}),
|
|
319
|
-
...(value.sort !== undefined ? { sort: value.sort } : {}),
|
|
320
|
-
}
|
|
402
|
+
return {
|
|
403
|
+
...value,
|
|
404
|
+
...(typeof value.resource_id === 'string' ? { resource: value.resource_id } : {}),
|
|
321
405
|
}
|
|
406
|
+
}
|
|
322
407
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
return {
|
|
327
|
-
type: 'aggregate',
|
|
328
|
-
...(resourceId !== undefined ? { resourceId } : {}),
|
|
329
|
-
...(value.aggregations !== undefined ? { aggregations: value.aggregations } : {}),
|
|
330
|
-
...(groupBy !== undefined ? { groupBy } : {}),
|
|
331
|
-
...(value.filters !== undefined ? { filters: value.filters } : {}),
|
|
332
|
-
}
|
|
408
|
+
function normalizeTableConfig(value: unknown) {
|
|
409
|
+
if (!isRecord(value)) {
|
|
410
|
+
return value
|
|
333
411
|
}
|
|
334
412
|
|
|
335
|
-
return
|
|
413
|
+
return {
|
|
414
|
+
...value,
|
|
415
|
+
...(value.page_size !== undefined ? { pageSize: value.page_size } : {}),
|
|
416
|
+
}
|
|
336
417
|
}
|
|
337
418
|
|
|
338
|
-
function
|
|
339
|
-
if (!isRecord(value)
|
|
419
|
+
function normalizeCardConfig(value: unknown): unknown {
|
|
420
|
+
if (!isRecord(value)) {
|
|
340
421
|
return value
|
|
341
422
|
}
|
|
342
423
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
424
|
+
const normalized = { ...value }
|
|
425
|
+
|
|
426
|
+
if (isRecord(normalized.progress)) {
|
|
427
|
+
normalized.progress = {
|
|
428
|
+
...normalized.progress,
|
|
429
|
+
...(normalized.progress.value_field !== undefined ? { valueField: normalized.progress.value_field } : {}),
|
|
430
|
+
...(normalized.progress.target_value !== undefined ? { targetValue: normalized.progress.target_value } : {}),
|
|
431
|
+
...(normalized.progress.target_field !== undefined ? { targetField: normalized.progress.target_field } : {}),
|
|
347
432
|
}
|
|
348
433
|
}
|
|
349
434
|
|
|
350
|
-
if (
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
...(
|
|
354
|
-
...(value.truncation !== undefined ? { truncation: value.truncation } : {}),
|
|
355
|
-
...(value.timezone !== undefined ? { timezone: value.timezone } : {}),
|
|
435
|
+
if (isRecord(normalized.comparison)) {
|
|
436
|
+
normalized.comparison = {
|
|
437
|
+
...normalized.comparison,
|
|
438
|
+
...(normalized.comparison.positive_is_good !== undefined ? { positiveIsGood: normalized.comparison.positive_is_good } : {}),
|
|
356
439
|
}
|
|
357
440
|
}
|
|
358
441
|
|
|
359
|
-
return
|
|
442
|
+
return normalized
|
|
360
443
|
}
|
|
361
444
|
|
|
362
|
-
function
|
|
363
|
-
|
|
364
|
-
return value
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
const serialized = { ...value }
|
|
368
|
-
|
|
369
|
-
if (Object.prototype.hasOwnProperty.call(serialized, 'pageSize')) {
|
|
370
|
-
serialized.page_size = serialized.pageSize
|
|
371
|
-
delete serialized.pageSize
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
return serialized
|
|
445
|
+
function normalizePivotConfig(value: unknown): unknown {
|
|
446
|
+
return value
|
|
375
447
|
}
|
|
376
448
|
|
|
377
|
-
function
|
|
378
|
-
if (
|
|
449
|
+
function serializeQueryConfigForEditor(value: QueryConfig | FunnelQueryConfig) {
|
|
450
|
+
if ('steps' in value) {
|
|
379
451
|
return {
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
452
|
+
steps: value.steps.map((step) => ({
|
|
453
|
+
...step,
|
|
454
|
+
resource_id: step.resource,
|
|
455
|
+
resource: undefined,
|
|
456
|
+
})).map((step) => removeUndefinedFields(step)),
|
|
385
457
|
}
|
|
386
458
|
}
|
|
387
459
|
|
|
388
|
-
return {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
460
|
+
return removeUndefinedFields({
|
|
461
|
+
...value,
|
|
462
|
+
group_by: value.groupBy,
|
|
463
|
+
groupBy: undefined,
|
|
464
|
+
order_by: value.orderBy,
|
|
465
|
+
orderBy: undefined,
|
|
466
|
+
time_series: value.timeSeries,
|
|
467
|
+
timeSeries: undefined,
|
|
468
|
+
})
|
|
395
469
|
}
|
|
396
470
|
|
|
397
|
-
function
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
471
|
+
function serializeTableConfigForEditor(value: TableViewConfig) {
|
|
472
|
+
return removeUndefinedFields({
|
|
473
|
+
...value,
|
|
474
|
+
page_size: value.pageSize,
|
|
475
|
+
pageSize: undefined,
|
|
476
|
+
})
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
function serializeCardConfigForEditor(value: KpiCardViewConfig | GaugeCardViewConfig) {
|
|
480
|
+
const serialized: Record<string, unknown> = { ...value }
|
|
481
|
+
|
|
482
|
+
if (isRecord(serialized.progress)) {
|
|
483
|
+
serialized.progress = removeUndefinedFields({
|
|
484
|
+
...serialized.progress,
|
|
485
|
+
value_field: serialized.progress.valueField,
|
|
486
|
+
valueField: undefined,
|
|
487
|
+
target_value: serialized.progress.targetValue,
|
|
488
|
+
targetValue: undefined,
|
|
489
|
+
target_field: serialized.progress.targetField,
|
|
490
|
+
targetField: undefined,
|
|
491
|
+
})
|
|
403
492
|
}
|
|
404
493
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
494
|
+
if (isRecord(serialized.comparison)) {
|
|
495
|
+
serialized.comparison = removeUndefinedFields({
|
|
496
|
+
...serialized.comparison,
|
|
497
|
+
positive_is_good: serialized.comparison.positiveIsGood,
|
|
498
|
+
positiveIsGood: undefined,
|
|
499
|
+
})
|
|
410
500
|
}
|
|
501
|
+
|
|
502
|
+
return removeUndefinedFields(serialized)
|
|
411
503
|
}
|
|
412
504
|
|
|
413
|
-
function
|
|
414
|
-
return
|
|
505
|
+
function serializePivotConfigForEditor(value: PivotTableViewConfig) {
|
|
506
|
+
return value
|
|
415
507
|
}
|
|
416
508
|
|
|
417
|
-
function
|
|
418
|
-
|
|
419
|
-
|
|
509
|
+
function removeUndefinedFields<T extends Record<string, unknown>>(value: T) {
|
|
510
|
+
return Object.fromEntries(
|
|
511
|
+
Object.entries(value).filter(([, item]) => item !== undefined),
|
|
512
|
+
)
|
|
420
513
|
}
|
|
421
514
|
|
|
422
|
-
function isRecord(value: unknown): value is Record<string,
|
|
515
|
+
function isRecord(value: unknown): value is Record<string, any> {
|
|
423
516
|
return typeof value === 'object' && value !== null
|
|
424
517
|
}
|