@adminforth/dashboard 1.3.0 → 1.4.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 +80 -11
- package/custom/api/dashboardApi.ts +4 -0
- package/custom/model/dashboard.types.ts +16 -8
- package/custom/skills/adminforth-dashboard/SKILL.md +108 -1
- package/custom/widgets/chart/ChartWidget.vue +20 -3
- package/dist/custom/api/dashboardApi.d.ts +1 -0
- package/dist/custom/api/dashboardApi.js +5 -0
- package/dist/custom/api/dashboardApi.ts +4 -0
- package/dist/custom/model/dashboard.types.d.ts +3 -0
- package/dist/custom/model/dashboard.types.js +19 -5
- package/dist/custom/model/dashboard.types.ts +16 -8
- package/dist/custom/queries/useDashboardConfig.d.ts +20 -0
- package/dist/custom/queries/useWidgetData.d.ts +20 -0
- package/dist/custom/skills/adminforth-dashboard/SKILL.md +108 -1
- package/dist/custom/widgets/chart/ChartWidget.vue +20 -3
- package/dist/endpoint/dashboard.d.ts +7 -2
- package/dist/endpoint/dashboard.js +45 -1
- package/dist/endpoint/widgets.d.ts +2 -1
- package/dist/endpoint/widgets.js +1 -0
- package/dist/schema/api.d.ts +109 -16
- package/dist/schema/api.js +5 -0
- package/dist/schema/widget.d.ts +72 -12
- package/dist/schema/widget.js +7 -4
- package/dist/services/widgetDataService.d.ts +2 -1
- package/dist/services/widgetDataService.js +50 -20
- package/endpoint/dashboard.ts +76 -3
- package/endpoint/widgets.ts +6 -2
- package/package.json +1 -1
- package/schema/api.ts +6 -0
- package/schema/widget.ts +7 -4
- package/services/widgetDataService.ts +53 -15
package/README.md
CHANGED
|
@@ -29,6 +29,7 @@ Each widget has common fields:
|
|
|
29
29
|
| `label` | Optional widget title. |
|
|
30
30
|
| `target` | Widget type: `table`, `chart`, `kpi_card`, `pivot_table`, or `gauge_card`. |
|
|
31
31
|
| `order` | Widget order inside its group. |
|
|
32
|
+
| `variables` | Optional static maps/constants available inside widget `query.calcs` via `lookup($variables.path, field, default)`. |
|
|
32
33
|
| `size` | Preset width: `small`, `medium`, `large`, `wide`, or `full`. |
|
|
33
34
|
| `width`, `height`, `min_width`, `max_width` | Optional explicit layout constraints. |
|
|
34
35
|
| `query` | Data query definition. |
|
|
@@ -38,7 +39,7 @@ Each widget has common fields:
|
|
|
38
39
|
| Widget target | Config field | Main settings | Data usage |
|
|
39
40
|
| --- | --- | --- | --- |
|
|
40
41
|
| `table` | `table` | `pagination`, `page_size`, `columns` | Uses `query` to display raw or aggregate rows. |
|
|
41
|
-
| `chart` | `chart` | `type`, `x`, `y`, `label`, `value`, `series`, `buckets`, `color`, `colors` | Uses `query`;
|
|
42
|
+
| `chart` | `chart` | `type`, `x`, `y`, `label`, `value`, `series`, `buckets`, `color`, `colors` | Uses `query`; step-based charts may use `query.steps` with optional `calcs`. |
|
|
42
43
|
| `kpi_card` | `card` | `value`, `subtitle`, `comparison`, `sparkline` | Reads the first returned query row. |
|
|
43
44
|
| `gauge_card` | `card` | `value`, `target`, `progress`, `color` | Reads the first returned query row. |
|
|
44
45
|
| `pivot_table` | `pivot` | `rows`, `columns`, `values` | Uses query rows to build a pivot table. |
|
|
@@ -72,26 +73,94 @@ type QueryConfig = {
|
|
|
72
73
|
}
|
|
73
74
|
```
|
|
74
75
|
|
|
75
|
-
|
|
76
|
+
Step-based chart queries use `steps` and may include `calcs`:
|
|
76
77
|
|
|
77
78
|
```yaml
|
|
78
79
|
target: chart
|
|
80
|
+
label: Average price by database
|
|
81
|
+
variables:
|
|
82
|
+
price_multipliers:
|
|
83
|
+
cars_sl: 0.84
|
|
84
|
+
cars_mysql: 1.12
|
|
85
|
+
cars_pg: 0.91
|
|
86
|
+
cars_mongo: 1.07
|
|
87
|
+
cars_ch: 0.76
|
|
79
88
|
chart:
|
|
80
|
-
type:
|
|
81
|
-
title:
|
|
89
|
+
type: bar
|
|
90
|
+
title: Average price by database
|
|
91
|
+
x:
|
|
92
|
+
field: name
|
|
93
|
+
y:
|
|
94
|
+
field: adjusted_value
|
|
82
95
|
query:
|
|
83
96
|
steps:
|
|
84
|
-
- name:
|
|
85
|
-
resource:
|
|
97
|
+
- name: SQLite
|
|
98
|
+
resource: cars_sl
|
|
86
99
|
metric:
|
|
87
|
-
agg:
|
|
100
|
+
agg: avg
|
|
101
|
+
field: price
|
|
88
102
|
as: value
|
|
89
|
-
- name:
|
|
90
|
-
resource:
|
|
103
|
+
- name: MySQL
|
|
104
|
+
resource: cars_mysql
|
|
91
105
|
metric:
|
|
92
|
-
agg:
|
|
93
|
-
field:
|
|
106
|
+
agg: avg
|
|
107
|
+
field: price
|
|
94
108
|
as: value
|
|
109
|
+
calcs:
|
|
110
|
+
- calc: value * lookup($variables.price_multipliers, resource, 1)
|
|
111
|
+
as: adjusted_value
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Widget-level variables example:
|
|
115
|
+
|
|
116
|
+
```yaml
|
|
117
|
+
target: chart
|
|
118
|
+
label: Model costs
|
|
119
|
+
variables:
|
|
120
|
+
token_prices_per_1m:
|
|
121
|
+
input:
|
|
122
|
+
gpt-4.1: 2.00
|
|
123
|
+
gpt-4.1-mini: 0.40
|
|
124
|
+
gpt-4o-mini: 0.15
|
|
125
|
+
output:
|
|
126
|
+
gpt-4.1: 8.00
|
|
127
|
+
gpt-4.1-mini: 1.60
|
|
128
|
+
gpt-4o-mini: 0.60
|
|
129
|
+
cached:
|
|
130
|
+
gpt-4.1: 0.50
|
|
131
|
+
gpt-4.1-mini: 0.10
|
|
132
|
+
gpt-4o-mini: 0.075
|
|
133
|
+
chart:
|
|
134
|
+
type: stacked_bar
|
|
135
|
+
title: LLM costs by model
|
|
136
|
+
x:
|
|
137
|
+
field: model
|
|
138
|
+
y:
|
|
139
|
+
- field: input_cost
|
|
140
|
+
- field: output_cost
|
|
141
|
+
- field: cached_cost
|
|
142
|
+
query:
|
|
143
|
+
resource: model_usage
|
|
144
|
+
select:
|
|
145
|
+
- field: model
|
|
146
|
+
- agg: sum
|
|
147
|
+
field: input_tokens
|
|
148
|
+
as: input_tokens
|
|
149
|
+
- agg: sum
|
|
150
|
+
field: output_tokens
|
|
151
|
+
as: output_tokens
|
|
152
|
+
- agg: sum
|
|
153
|
+
field: cached_tokens
|
|
154
|
+
as: cached_tokens
|
|
155
|
+
group_by:
|
|
156
|
+
- model
|
|
157
|
+
calcs:
|
|
158
|
+
- calc: input_tokens / 1000000 * lookup($variables.token_prices_per_1m.input, model, 0)
|
|
159
|
+
as: input_cost
|
|
160
|
+
- calc: output_tokens / 1000000 * lookup($variables.token_prices_per_1m.output, model, 0)
|
|
161
|
+
as: output_cost
|
|
162
|
+
- calc: cached_tokens / 1000000 * lookup($variables.token_prices_per_1m.cached, model, 0)
|
|
163
|
+
as: cached_cost
|
|
95
164
|
```
|
|
96
165
|
|
|
97
166
|
## Runtime Structure
|
|
@@ -143,6 +143,10 @@ export const dashboardApi = {
|
|
|
143
143
|
return callDashboardApi('/adminapi/v1/dashboard/get-config', { slug })
|
|
144
144
|
},
|
|
145
145
|
|
|
146
|
+
async setDashboardConfig(slug: string, config: DashboardConfig): Promise<DashboardResponse> {
|
|
147
|
+
return callDashboardApi('/adminapi/v1/dashboard/set_dashboard_config', { slug, config })
|
|
148
|
+
},
|
|
149
|
+
|
|
146
150
|
async addDashboardGroup(slug: string): Promise<DashboardResponse> {
|
|
147
151
|
return callDashboardApi('/adminapi/v1/dashboard/add_dashboard_group', { slug })
|
|
148
152
|
},
|
|
@@ -6,6 +6,8 @@ export type DashboardConfig = {
|
|
|
6
6
|
widgets: DashboardWidgetConfig[]
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
+
export type DashboardVariables = Record<string, unknown>
|
|
10
|
+
|
|
9
11
|
export type DashboardGroupConfig = {
|
|
10
12
|
id: string
|
|
11
13
|
label: string
|
|
@@ -39,6 +41,7 @@ export type WidgetBaseConfig = {
|
|
|
39
41
|
id: string
|
|
40
42
|
group_id: string
|
|
41
43
|
label?: string
|
|
44
|
+
variables?: DashboardVariables
|
|
42
45
|
size?: DashboardWidgetSize
|
|
43
46
|
width?: number
|
|
44
47
|
height?: number
|
|
@@ -127,6 +130,7 @@ export type QueryConfig = {
|
|
|
127
130
|
|
|
128
131
|
export type FunnelQueryConfig = {
|
|
129
132
|
steps: FunnelQueryStep[]
|
|
133
|
+
calcs?: QueryCalcSelectItem[]
|
|
130
134
|
}
|
|
131
135
|
|
|
132
136
|
export type FunnelQueryStep = {
|
|
@@ -381,9 +385,10 @@ function normalizeQueryConfig(value: unknown): unknown {
|
|
|
381
385
|
}
|
|
382
386
|
|
|
383
387
|
if (Array.isArray(value.steps)) {
|
|
384
|
-
return {
|
|
388
|
+
return removeUndefinedFields({
|
|
385
389
|
steps: value.steps.map((step) => normalizeFunnelQueryStep(step)),
|
|
386
|
-
|
|
390
|
+
calcs: Array.isArray(value.calcs) ? value.calcs as QueryCalcSelectItem[] : undefined,
|
|
391
|
+
})
|
|
387
392
|
}
|
|
388
393
|
|
|
389
394
|
return {
|
|
@@ -399,10 +404,12 @@ function normalizeFunnelQueryStep(value: unknown) {
|
|
|
399
404
|
return value
|
|
400
405
|
}
|
|
401
406
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
407
|
+
const { resource_id, ...rest } = value
|
|
408
|
+
|
|
409
|
+
return removeUndefinedFields({
|
|
410
|
+
...rest,
|
|
411
|
+
resource: typeof resource_id === 'string' ? resource_id : rest.resource,
|
|
412
|
+
})
|
|
406
413
|
}
|
|
407
414
|
|
|
408
415
|
function normalizeTableConfig(value: unknown) {
|
|
@@ -448,13 +455,14 @@ function normalizePivotConfig(value: unknown): unknown {
|
|
|
448
455
|
|
|
449
456
|
function serializeQueryConfigForEditor(value: QueryConfig | FunnelQueryConfig) {
|
|
450
457
|
if ('steps' in value) {
|
|
451
|
-
return {
|
|
458
|
+
return removeUndefinedFields({
|
|
452
459
|
steps: value.steps.map((step) => ({
|
|
453
460
|
...step,
|
|
454
461
|
resource_id: step.resource,
|
|
455
462
|
resource: undefined,
|
|
456
463
|
})).map((step) => removeUndefinedFields(step)),
|
|
457
|
-
|
|
464
|
+
calcs: value.calcs,
|
|
465
|
+
})
|
|
458
466
|
}
|
|
459
467
|
|
|
460
468
|
return removeUndefinedFields({
|
|
@@ -41,6 +41,7 @@ If the user asks how the schema works, how to implement the API, or how to chang
|
|
|
41
41
|
Use these tools whenever available:
|
|
42
42
|
|
|
43
43
|
- `dashboard_get_config`
|
|
44
|
+
- `dashboard_set_dashboard_config`
|
|
44
45
|
- `dashboard_add_dashboard_group`
|
|
45
46
|
- `dashboard_set_dashboard_group_config`
|
|
46
47
|
- `dashboard_move_dashboard_group`
|
|
@@ -58,6 +59,7 @@ If a dashboard tool is known by name but its argument schema is not loaded, call
|
|
|
58
59
|
Do not pass fields between dashboard tools by analogy. Use each tool's schema.
|
|
59
60
|
|
|
60
61
|
- `dashboard_add_dashboard_group` creates a new group. It accepts the dashboard slug only. Never pass `groupId` to this tool.
|
|
62
|
+
- `dashboard_set_dashboard_config` replaces the full dashboard config. Use it when the user explicitly asks to edit the whole dashboard config.
|
|
61
63
|
- `dashboard_add_dashboard_widget` creates a widget inside an existing group. Use it when you already have a `groupId`.
|
|
62
64
|
- `dashboard_set_dashboard_group_config`, `dashboard_move_dashboard_group`, and `dashboard_remove_dashboard_group` operate on an existing group and need `groupId`.
|
|
63
65
|
- `dashboard_set_widget_config`, `dashboard_move_dashboard_widget`, `dashboard_remove_dashboard_widget`, and `dashboard_get_dashboard_widget_data` operate on an existing widget and need `widgetId`.
|
|
@@ -113,6 +115,24 @@ For group requests:
|
|
|
113
115
|
|
|
114
116
|
If slug is missing, use `default`.
|
|
115
117
|
|
|
118
|
+
## Dashboard Config Workflow
|
|
119
|
+
|
|
120
|
+
Use `dashboard_set_dashboard_config` only when the user explicitly asks to edit the whole dashboard root config.
|
|
121
|
+
|
|
122
|
+
For requests like:
|
|
123
|
+
|
|
124
|
+
- "update root dashboard config"
|
|
125
|
+
- "replace the whole dashboard config"
|
|
126
|
+
|
|
127
|
+
do this:
|
|
128
|
+
|
|
129
|
+
1. Call `dashboard_get_config`.
|
|
130
|
+
2. Modify the returned root config, preserving existing `version`, `groups`, and `widgets` unless the user asked to change them.
|
|
131
|
+
3. Call `dashboard_set_dashboard_config` with the full updated config.
|
|
132
|
+
4. Return a short summary of the root-level fields changed.
|
|
133
|
+
|
|
134
|
+
Do not use `dashboard_set_dashboard_config` to store reusable widget variables.
|
|
135
|
+
|
|
116
136
|
## Widget Config Rules
|
|
117
137
|
|
|
118
138
|
Use the current schema keys exactly:
|
|
@@ -124,6 +144,93 @@ Use the current schema keys exactly:
|
|
|
124
144
|
- Use `group_by`, not `groupBy`.
|
|
125
145
|
- Use `order_by`, not `orderBy`.
|
|
126
146
|
- Use `page_size`, not `pageSize`.
|
|
127
|
-
- For
|
|
147
|
+
- For step-based chart queries, use `query.steps` as an ordered array of `{ name, resource, metric, filters }` steps and add `query.calcs` when derived fields are needed.
|
|
128
148
|
- Use `card` for KPI and gauge widget view config.
|
|
129
149
|
- Use `pivot` for pivot table view config.
|
|
150
|
+
- Use `variables` for reusable static maps or constants at widget level.
|
|
151
|
+
- In `query.calcs`, use `lookup($variables.some.map, row_field, default_number)` to read a numeric value from a variable map by the current row/group field.
|
|
152
|
+
|
|
153
|
+
## Variables And Lookup Calcs
|
|
154
|
+
|
|
155
|
+
Widget config can define variables:
|
|
156
|
+
|
|
157
|
+
```yaml
|
|
158
|
+
variables:
|
|
159
|
+
token_prices_per_1m:
|
|
160
|
+
input:
|
|
161
|
+
gpt-4.1: 2.00
|
|
162
|
+
gpt-4.1-mini: 0.40
|
|
163
|
+
gpt-4o-mini: 0.15
|
|
164
|
+
output:
|
|
165
|
+
gpt-4.1: 8.00
|
|
166
|
+
gpt-4.1-mini: 1.60
|
|
167
|
+
gpt-4o-mini: 0.60
|
|
168
|
+
cached:
|
|
169
|
+
gpt-4.1: 0.50
|
|
170
|
+
gpt-4.1-mini: 0.10
|
|
171
|
+
gpt-4o-mini: 0.075
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Use variables when a calculation needs a static rate table, threshold table, coefficient map, or other reusable constants. In calcs, `lookup($variables.path.to.map, field_name, 0)` returns the value from the map using `field_name` from the current row/group. The third argument is the numeric fallback when the key is missing.
|
|
175
|
+
|
|
176
|
+
Example widget:
|
|
177
|
+
|
|
178
|
+
```yaml
|
|
179
|
+
target: chart
|
|
180
|
+
label: Model costs
|
|
181
|
+
size: large
|
|
182
|
+
variables:
|
|
183
|
+
token_prices_per_1m:
|
|
184
|
+
input:
|
|
185
|
+
gpt-4.1: 2.00
|
|
186
|
+
gpt-4.1-mini: 0.40
|
|
187
|
+
gpt-4o-mini: 0.15
|
|
188
|
+
output:
|
|
189
|
+
gpt-4.1: 8.00
|
|
190
|
+
gpt-4.1-mini: 1.60
|
|
191
|
+
gpt-4o-mini: 0.60
|
|
192
|
+
cached:
|
|
193
|
+
gpt-4.1: 0.50
|
|
194
|
+
gpt-4.1-mini: 0.10
|
|
195
|
+
gpt-4o-mini: 0.075
|
|
196
|
+
|
|
197
|
+
chart:
|
|
198
|
+
type: stacked_bar
|
|
199
|
+
title: LLM costs by model
|
|
200
|
+
x:
|
|
201
|
+
field: model
|
|
202
|
+
label: Model
|
|
203
|
+
y:
|
|
204
|
+
- field: input_cost
|
|
205
|
+
label: Input
|
|
206
|
+
format: currency
|
|
207
|
+
- field: output_cost
|
|
208
|
+
label: Output
|
|
209
|
+
format: currency
|
|
210
|
+
- field: cached_cost
|
|
211
|
+
label: Cached
|
|
212
|
+
format: currency
|
|
213
|
+
|
|
214
|
+
query:
|
|
215
|
+
resource: model_usage
|
|
216
|
+
select:
|
|
217
|
+
- field: model
|
|
218
|
+
- agg: sum
|
|
219
|
+
field: input_tokens
|
|
220
|
+
as: input_tokens
|
|
221
|
+
- agg: sum
|
|
222
|
+
field: output_tokens
|
|
223
|
+
as: output_tokens
|
|
224
|
+
- agg: sum
|
|
225
|
+
field: cached_tokens
|
|
226
|
+
as: cached_tokens
|
|
227
|
+
group_by:
|
|
228
|
+
- model
|
|
229
|
+
calcs:
|
|
230
|
+
- calc: input_tokens / 1000000 * lookup($variables.token_prices_per_1m.input, model, 0)
|
|
231
|
+
as: input_cost
|
|
232
|
+
- calc: output_tokens / 1000000 * lookup($variables.token_prices_per_1m.output, model, 0)
|
|
233
|
+
as: output_cost
|
|
234
|
+
- calc: cached_tokens / 1000000 * lookup($variables.token_prices_per_1m.cached, model, 0)
|
|
235
|
+
as: cached_cost
|
|
236
|
+
```
|
|
@@ -69,10 +69,10 @@
|
|
|
69
69
|
|
|
70
70
|
<StackedBarChart
|
|
71
71
|
v-else-if="chartConfig?.type === 'stacked_bar'"
|
|
72
|
-
:rows="
|
|
72
|
+
:rows="stackedBarRows"
|
|
73
73
|
:x-field="xField"
|
|
74
|
-
:y-field="
|
|
75
|
-
:series-field="
|
|
74
|
+
:y-field="stackedBarYField"
|
|
75
|
+
:series-field="stackedBarSeriesField"
|
|
76
76
|
:colors="chartConfig.colors"
|
|
77
77
|
:height="chartHeight"
|
|
78
78
|
/>
|
|
@@ -155,6 +155,21 @@ const valueField = computed(() => chartConfig.value?.value?.field || columns.val
|
|
|
155
155
|
const pieRows = computed(() => rows.value)
|
|
156
156
|
const pieLabelField = computed(() => labelField.value)
|
|
157
157
|
const pieValueField = computed(() => valueField.value)
|
|
158
|
+
const stackedBarYItems = computed(() => {
|
|
159
|
+
const y = chartConfig.value?.y
|
|
160
|
+
return Array.isArray(y) ? y : []
|
|
161
|
+
})
|
|
162
|
+
const stackedBarRows = computed(() => {
|
|
163
|
+
if (chartConfig.value?.type !== 'stacked_bar' || !stackedBarYItems.value.length) {
|
|
164
|
+
return rows.value
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return rows.value.flatMap((row) => stackedBarYItems.value.map((item) => ({
|
|
168
|
+
[xField.value]: row[xField.value],
|
|
169
|
+
__series: item.label ?? item.field,
|
|
170
|
+
__value: row[item.field],
|
|
171
|
+
})))
|
|
172
|
+
})
|
|
158
173
|
const barRows = computed(() => {
|
|
159
174
|
const bucketField = chartConfig.value?.type === 'histogram'
|
|
160
175
|
? chartConfig.value.x?.field
|
|
@@ -178,6 +193,8 @@ const barRows = computed(() => {
|
|
|
178
193
|
const barLabelField = computed(() => chartConfig.value?.type === 'histogram' && chartConfig.value.buckets ? 'label' : xField.value)
|
|
179
194
|
const barValueField = computed(() => chartConfig.value?.type === 'histogram' && chartConfig.value.buckets ? 'count' : yField.value)
|
|
180
195
|
const seriesField = computed(() => chartConfig.value?.series?.field || columns.value[2] || '')
|
|
196
|
+
const stackedBarYField = computed(() => stackedBarYItems.value.length ? '__value' : yField.value)
|
|
197
|
+
const stackedBarSeriesField = computed(() => stackedBarYItems.value.length ? '__series' : seriesField.value)
|
|
181
198
|
const lineSeriesName = computed(() => {
|
|
182
199
|
const y = chartConfig.value?.y
|
|
183
200
|
return Array.isArray(y) ? y[0]?.label : undefined
|
|
@@ -26,6 +26,7 @@ export declare class DashboardApiError extends Error {
|
|
|
26
26
|
}
|
|
27
27
|
export declare const dashboardApi: {
|
|
28
28
|
getDashboardConfig(slug: string): Promise<DashboardResponse>;
|
|
29
|
+
setDashboardConfig(slug: string, config: DashboardConfig): Promise<DashboardResponse>;
|
|
29
30
|
addDashboardGroup(slug: string): Promise<DashboardResponse>;
|
|
30
31
|
moveDashboardGroup(slug: string, groupId: string, direction: DashboardGroupMoveDirection): Promise<DashboardResponse>;
|
|
31
32
|
removeDashboardGroup(slug: string, groupId: string): Promise<DashboardResponse>;
|
|
@@ -103,6 +103,11 @@ exports.dashboardApi = {
|
|
|
103
103
|
return callDashboardApi('/adminapi/v1/dashboard/get-config', { slug });
|
|
104
104
|
});
|
|
105
105
|
},
|
|
106
|
+
setDashboardConfig(slug, config) {
|
|
107
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
108
|
+
return callDashboardApi('/adminapi/v1/dashboard/set_dashboard_config', { slug, config });
|
|
109
|
+
});
|
|
110
|
+
},
|
|
106
111
|
addDashboardGroup(slug) {
|
|
107
112
|
return __awaiter(this, void 0, void 0, function* () {
|
|
108
113
|
return callDashboardApi('/adminapi/v1/dashboard/add_dashboard_group', { slug });
|
|
@@ -143,6 +143,10 @@ export const dashboardApi = {
|
|
|
143
143
|
return callDashboardApi('/adminapi/v1/dashboard/get-config', { slug })
|
|
144
144
|
},
|
|
145
145
|
|
|
146
|
+
async setDashboardConfig(slug: string, config: DashboardConfig): Promise<DashboardResponse> {
|
|
147
|
+
return callDashboardApi('/adminapi/v1/dashboard/set_dashboard_config', { slug, config })
|
|
148
|
+
},
|
|
149
|
+
|
|
146
150
|
async addDashboardGroup(slug: string): Promise<DashboardResponse> {
|
|
147
151
|
return callDashboardApi('/adminapi/v1/dashboard/add_dashboard_group', { slug })
|
|
148
152
|
},
|
|
@@ -4,6 +4,7 @@ export type DashboardConfig = {
|
|
|
4
4
|
groups: DashboardGroupConfig[];
|
|
5
5
|
widgets: DashboardWidgetConfig[];
|
|
6
6
|
};
|
|
7
|
+
export type DashboardVariables = Record<string, unknown>;
|
|
7
8
|
export type DashboardGroupConfig = {
|
|
8
9
|
id: string;
|
|
9
10
|
label: string;
|
|
@@ -27,6 +28,7 @@ export type WidgetBaseConfig = {
|
|
|
27
28
|
id: string;
|
|
28
29
|
group_id: string;
|
|
29
30
|
label?: string;
|
|
31
|
+
variables?: DashboardVariables;
|
|
30
32
|
size?: DashboardWidgetSize;
|
|
31
33
|
width?: number;
|
|
32
34
|
height?: number;
|
|
@@ -108,6 +110,7 @@ export type QueryConfig = {
|
|
|
108
110
|
};
|
|
109
111
|
export type FunnelQueryConfig = {
|
|
110
112
|
steps: FunnelQueryStep[];
|
|
113
|
+
calcs?: QueryCalcSelectItem[];
|
|
111
114
|
};
|
|
112
115
|
export type FunnelQueryStep = {
|
|
113
116
|
name: string;
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
2
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
14
|
exports.normalizeDashboardConfig = normalizeDashboardConfig;
|
|
4
15
|
exports.normalizeDashboardWidgetConfig = normalizeDashboardWidgetConfig;
|
|
@@ -95,9 +106,10 @@ function normalizeQueryConfig(value) {
|
|
|
95
106
|
return value;
|
|
96
107
|
}
|
|
97
108
|
if (Array.isArray(value.steps)) {
|
|
98
|
-
return {
|
|
109
|
+
return removeUndefinedFields({
|
|
99
110
|
steps: value.steps.map((step) => normalizeFunnelQueryStep(step)),
|
|
100
|
-
|
|
111
|
+
calcs: Array.isArray(value.calcs) ? value.calcs : undefined,
|
|
112
|
+
});
|
|
101
113
|
}
|
|
102
114
|
return Object.assign(Object.assign(Object.assign(Object.assign({}, value), (Array.isArray(value.group_by) ? { groupBy: value.group_by } : {})), (Array.isArray(value.order_by) ? { orderBy: value.order_by } : {})), (value.time_series !== undefined ? { timeSeries: value.time_series } : {}));
|
|
103
115
|
}
|
|
@@ -105,7 +117,8 @@ function normalizeFunnelQueryStep(value) {
|
|
|
105
117
|
if (!isRecord(value)) {
|
|
106
118
|
return value;
|
|
107
119
|
}
|
|
108
|
-
|
|
120
|
+
const { resource_id } = value, rest = __rest(value, ["resource_id"]);
|
|
121
|
+
return removeUndefinedFields(Object.assign(Object.assign({}, rest), { resource: typeof resource_id === 'string' ? resource_id : rest.resource }));
|
|
109
122
|
}
|
|
110
123
|
function normalizeTableConfig(value) {
|
|
111
124
|
if (!isRecord(value)) {
|
|
@@ -131,9 +144,10 @@ function normalizePivotConfig(value) {
|
|
|
131
144
|
}
|
|
132
145
|
function serializeQueryConfigForEditor(value) {
|
|
133
146
|
if ('steps' in value) {
|
|
134
|
-
return {
|
|
147
|
+
return removeUndefinedFields({
|
|
135
148
|
steps: value.steps.map((step) => (Object.assign(Object.assign({}, step), { resource_id: step.resource, resource: undefined }))).map((step) => removeUndefinedFields(step)),
|
|
136
|
-
|
|
149
|
+
calcs: value.calcs,
|
|
150
|
+
});
|
|
137
151
|
}
|
|
138
152
|
return removeUndefinedFields(Object.assign(Object.assign({}, value), { group_by: value.groupBy, groupBy: undefined, order_by: value.orderBy, orderBy: undefined, time_series: value.timeSeries, timeSeries: undefined }));
|
|
139
153
|
}
|
|
@@ -6,6 +6,8 @@ export type DashboardConfig = {
|
|
|
6
6
|
widgets: DashboardWidgetConfig[]
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
+
export type DashboardVariables = Record<string, unknown>
|
|
10
|
+
|
|
9
11
|
export type DashboardGroupConfig = {
|
|
10
12
|
id: string
|
|
11
13
|
label: string
|
|
@@ -39,6 +41,7 @@ export type WidgetBaseConfig = {
|
|
|
39
41
|
id: string
|
|
40
42
|
group_id: string
|
|
41
43
|
label?: string
|
|
44
|
+
variables?: DashboardVariables
|
|
42
45
|
size?: DashboardWidgetSize
|
|
43
46
|
width?: number
|
|
44
47
|
height?: number
|
|
@@ -127,6 +130,7 @@ export type QueryConfig = {
|
|
|
127
130
|
|
|
128
131
|
export type FunnelQueryConfig = {
|
|
129
132
|
steps: FunnelQueryStep[]
|
|
133
|
+
calcs?: QueryCalcSelectItem[]
|
|
130
134
|
}
|
|
131
135
|
|
|
132
136
|
export type FunnelQueryStep = {
|
|
@@ -381,9 +385,10 @@ function normalizeQueryConfig(value: unknown): unknown {
|
|
|
381
385
|
}
|
|
382
386
|
|
|
383
387
|
if (Array.isArray(value.steps)) {
|
|
384
|
-
return {
|
|
388
|
+
return removeUndefinedFields({
|
|
385
389
|
steps: value.steps.map((step) => normalizeFunnelQueryStep(step)),
|
|
386
|
-
|
|
390
|
+
calcs: Array.isArray(value.calcs) ? value.calcs as QueryCalcSelectItem[] : undefined,
|
|
391
|
+
})
|
|
387
392
|
}
|
|
388
393
|
|
|
389
394
|
return {
|
|
@@ -399,10 +404,12 @@ function normalizeFunnelQueryStep(value: unknown) {
|
|
|
399
404
|
return value
|
|
400
405
|
}
|
|
401
406
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
407
|
+
const { resource_id, ...rest } = value
|
|
408
|
+
|
|
409
|
+
return removeUndefinedFields({
|
|
410
|
+
...rest,
|
|
411
|
+
resource: typeof resource_id === 'string' ? resource_id : rest.resource,
|
|
412
|
+
})
|
|
406
413
|
}
|
|
407
414
|
|
|
408
415
|
function normalizeTableConfig(value: unknown) {
|
|
@@ -448,13 +455,14 @@ function normalizePivotConfig(value: unknown): unknown {
|
|
|
448
455
|
|
|
449
456
|
function serializeQueryConfigForEditor(value: QueryConfig | FunnelQueryConfig) {
|
|
450
457
|
if ('steps' in value) {
|
|
451
|
-
return {
|
|
458
|
+
return removeUndefinedFields({
|
|
452
459
|
steps: value.steps.map((step) => ({
|
|
453
460
|
...step,
|
|
454
461
|
resource_id: step.resource,
|
|
455
462
|
resource: undefined,
|
|
456
463
|
})).map((step) => removeUndefinedFields(step)),
|
|
457
|
-
|
|
464
|
+
calcs: value.calcs,
|
|
465
|
+
})
|
|
458
466
|
}
|
|
459
467
|
|
|
460
468
|
return removeUndefinedFields({
|
|
@@ -16,6 +16,7 @@ export declare function useDashboardConfig(slug: Ref<string>): {
|
|
|
16
16
|
id: string;
|
|
17
17
|
group_id: string;
|
|
18
18
|
label?: string | undefined;
|
|
19
|
+
variables?: import("../model/dashboard.types.js").DashboardVariables | undefined;
|
|
19
20
|
size?: import("../model/dashboard.types.js").DashboardWidgetSize | undefined;
|
|
20
21
|
width?: number | undefined;
|
|
21
22
|
height?: number | undefined;
|
|
@@ -27,6 +28,7 @@ export declare function useDashboardConfig(slug: Ref<string>): {
|
|
|
27
28
|
id: string;
|
|
28
29
|
group_id: string;
|
|
29
30
|
label?: string | undefined;
|
|
31
|
+
variables?: import("../model/dashboard.types.js").DashboardVariables | undefined;
|
|
30
32
|
size?: import("../model/dashboard.types.js").DashboardWidgetSize | undefined;
|
|
31
33
|
width?: number | undefined;
|
|
32
34
|
height?: number | undefined;
|
|
@@ -99,6 +101,7 @@ export declare function useDashboardConfig(slug: Ref<string>): {
|
|
|
99
101
|
id: string;
|
|
100
102
|
group_id: string;
|
|
101
103
|
label?: string | undefined;
|
|
104
|
+
variables?: import("../model/dashboard.types.js").DashboardVariables | undefined;
|
|
102
105
|
size?: import("../model/dashboard.types.js").DashboardWidgetSize | undefined;
|
|
103
106
|
width?: number | undefined;
|
|
104
107
|
height?: number | undefined;
|
|
@@ -209,11 +212,16 @@ export declare function useDashboardConfig(slug: Ref<string>): {
|
|
|
209
212
|
};
|
|
210
213
|
filters?: any;
|
|
211
214
|
}[];
|
|
215
|
+
calcs?: {
|
|
216
|
+
calc: string;
|
|
217
|
+
as: string;
|
|
218
|
+
}[] | undefined;
|
|
212
219
|
};
|
|
213
220
|
} | {
|
|
214
221
|
id: string;
|
|
215
222
|
group_id: string;
|
|
216
223
|
label?: string | undefined;
|
|
224
|
+
variables?: import("../model/dashboard.types.js").DashboardVariables | undefined;
|
|
217
225
|
size?: import("../model/dashboard.types.js").DashboardWidgetSize | undefined;
|
|
218
226
|
width?: number | undefined;
|
|
219
227
|
height?: number | undefined;
|
|
@@ -292,6 +300,7 @@ export declare function useDashboardConfig(slug: Ref<string>): {
|
|
|
292
300
|
id: string;
|
|
293
301
|
group_id: string;
|
|
294
302
|
label?: string | undefined;
|
|
303
|
+
variables?: import("../model/dashboard.types.js").DashboardVariables | undefined;
|
|
295
304
|
size?: import("../model/dashboard.types.js").DashboardWidgetSize | undefined;
|
|
296
305
|
width?: number | undefined;
|
|
297
306
|
height?: number | undefined;
|
|
@@ -376,6 +385,7 @@ export declare function useDashboardConfig(slug: Ref<string>): {
|
|
|
376
385
|
id: string;
|
|
377
386
|
group_id: string;
|
|
378
387
|
label?: string | undefined;
|
|
388
|
+
variables?: import("../model/dashboard.types.js").DashboardVariables | undefined;
|
|
379
389
|
size?: import("../model/dashboard.types.js").DashboardWidgetSize | undefined;
|
|
380
390
|
width?: number | undefined;
|
|
381
391
|
height?: number | undefined;
|
|
@@ -471,6 +481,7 @@ export declare function useDashboardConfig(slug: Ref<string>): {
|
|
|
471
481
|
id: string;
|
|
472
482
|
group_id: string;
|
|
473
483
|
label?: string | undefined;
|
|
484
|
+
variables?: import("../model/dashboard.types.js").DashboardVariables | undefined;
|
|
474
485
|
size?: import("../model/dashboard.types.js").DashboardWidgetSize | undefined;
|
|
475
486
|
width?: number | undefined;
|
|
476
487
|
height?: number | undefined;
|
|
@@ -482,6 +493,7 @@ export declare function useDashboardConfig(slug: Ref<string>): {
|
|
|
482
493
|
id: string;
|
|
483
494
|
group_id: string;
|
|
484
495
|
label?: string | undefined;
|
|
496
|
+
variables?: import("../model/dashboard.types.js").DashboardVariables | undefined;
|
|
485
497
|
size?: import("../model/dashboard.types.js").DashboardWidgetSize | undefined;
|
|
486
498
|
width?: number | undefined;
|
|
487
499
|
height?: number | undefined;
|
|
@@ -554,6 +566,7 @@ export declare function useDashboardConfig(slug: Ref<string>): {
|
|
|
554
566
|
id: string;
|
|
555
567
|
group_id: string;
|
|
556
568
|
label?: string | undefined;
|
|
569
|
+
variables?: import("../model/dashboard.types.js").DashboardVariables | undefined;
|
|
557
570
|
size?: import("../model/dashboard.types.js").DashboardWidgetSize | undefined;
|
|
558
571
|
width?: number | undefined;
|
|
559
572
|
height?: number | undefined;
|
|
@@ -664,11 +677,16 @@ export declare function useDashboardConfig(slug: Ref<string>): {
|
|
|
664
677
|
};
|
|
665
678
|
filters?: any;
|
|
666
679
|
}[];
|
|
680
|
+
calcs?: {
|
|
681
|
+
calc: string;
|
|
682
|
+
as: string;
|
|
683
|
+
}[] | undefined;
|
|
667
684
|
};
|
|
668
685
|
} | {
|
|
669
686
|
id: string;
|
|
670
687
|
group_id: string;
|
|
671
688
|
label?: string | undefined;
|
|
689
|
+
variables?: import("../model/dashboard.types.js").DashboardVariables | undefined;
|
|
672
690
|
size?: import("../model/dashboard.types.js").DashboardWidgetSize | undefined;
|
|
673
691
|
width?: number | undefined;
|
|
674
692
|
height?: number | undefined;
|
|
@@ -747,6 +765,7 @@ export declare function useDashboardConfig(slug: Ref<string>): {
|
|
|
747
765
|
id: string;
|
|
748
766
|
group_id: string;
|
|
749
767
|
label?: string | undefined;
|
|
768
|
+
variables?: import("../model/dashboard.types.js").DashboardVariables | undefined;
|
|
750
769
|
size?: import("../model/dashboard.types.js").DashboardWidgetSize | undefined;
|
|
751
770
|
width?: number | undefined;
|
|
752
771
|
height?: number | undefined;
|
|
@@ -831,6 +850,7 @@ export declare function useDashboardConfig(slug: Ref<string>): {
|
|
|
831
850
|
id: string;
|
|
832
851
|
group_id: string;
|
|
833
852
|
label?: string | undefined;
|
|
853
|
+
variables?: import("../model/dashboard.types.js").DashboardVariables | undefined;
|
|
834
854
|
size?: import("../model/dashboard.types.js").DashboardWidgetSize | undefined;
|
|
835
855
|
width?: number | undefined;
|
|
836
856
|
height?: number | undefined;
|