@adminforth/dashboard 1.2.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 +116 -39
- package/custom/api/dashboardApi.ts +4 -0
- package/custom/composables/useElementSize.ts +17 -2
- package/custom/model/dashboard.types.ts +337 -236
- package/custom/skills/adminforth-dashboard/SKILL.md +113 -2
- package/custom/widgets/chart/ChartWidget.vue +38 -53
- 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/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/composables/useElementSize.js +14 -2
- package/dist/custom/composables/useElementSize.ts +17 -2
- package/dist/custom/model/dashboard.types.d.ts +181 -61
- package/dist/custom/model/dashboard.types.js +82 -93
- package/dist/custom/model/dashboard.types.ts +337 -236
- package/dist/custom/queries/useDashboardConfig.d.ts +852 -66
- package/dist/custom/queries/useWidgetData.d.ts +848 -62
- package/dist/custom/skills/adminforth-dashboard/SKILL.md +113 -2
- package/dist/custom/widgets/chart/ChartWidget.vue +38 -53
- 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/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 +6 -2
- package/dist/schema/api.d.ts +2773 -736
- package/dist/schema/api.js +5 -0
- package/dist/schema/widget.d.ts +1648 -476
- package/dist/schema/widget.js +208 -139
- package/dist/services/widgetConfigValidator.js +16 -40
- package/dist/services/widgetDataService.d.ts +2 -1
- package/dist/services/widgetDataService.js +389 -82
- package/endpoint/dashboard.ts +77 -4
- package/endpoint/widgets.ts +11 -4
- package/package.json +1 -1
- package/schema/api.ts +6 -0
- package/schema/widget.ts +225 -139
- package/services/widgetConfigValidator.ts +29 -53
- package/services/widgetDataService.ts +522 -100
package/README.md
CHANGED
|
@@ -29,62 +29,139 @@ 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. |
|
|
35
36
|
|
|
36
37
|
## Widget Support Matrix
|
|
37
38
|
|
|
38
39
|
| Widget target | Config field | Main settings | Data usage |
|
|
39
40
|
| --- | --- | --- | --- |
|
|
40
|
-
| `table` | `table` | `pagination`, `page_size` | Uses `
|
|
41
|
-
| `chart` | `chart` | `type`, `
|
|
42
|
-
| `kpi_card` | `
|
|
43
|
-
| `gauge_card` | `
|
|
44
|
-
| `pivot_table` | `
|
|
41
|
+
| `table` | `table` | `pagination`, `page_size`, `columns` | Uses `query` to display raw or aggregate rows. |
|
|
42
|
+
| `chart` | `chart` | `type`, `x`, `y`, `label`, `value`, `series`, `buckets`, `color`, `colors` | Uses `query`; step-based charts may use `query.steps` with optional `calcs`. |
|
|
43
|
+
| `kpi_card` | `card` | `value`, `subtitle`, `comparison`, `sparkline` | Reads the first returned query row. |
|
|
44
|
+
| `gauge_card` | `card` | `value`, `target`, `progress`, `color` | Reads the first returned query row. |
|
|
45
|
+
| `pivot_table` | `pivot` | `rows`, `columns`, `values` | Uses query rows to build a pivot table. |
|
|
45
46
|
|
|
46
47
|
Chart widget types:
|
|
47
48
|
|
|
48
49
|
| Chart type | Notes |
|
|
49
50
|
| --- | --- |
|
|
50
|
-
| `line` | Uses `
|
|
51
|
-
| `pie` | Uses `
|
|
52
|
-
| `bar` | Uses `
|
|
53
|
-
| `stacked_bar` | Uses `
|
|
54
|
-
| `funnel` | Uses `
|
|
55
|
-
| `histogram` | Uses
|
|
51
|
+
| `line` | Uses `x` and `y`; `y` may contain multiple fields in config. |
|
|
52
|
+
| `pie` | Uses `label` and `value`. |
|
|
53
|
+
| `bar` | Uses `x` and `y`. |
|
|
54
|
+
| `stacked_bar` | Uses `x`, `y`, and `series`. |
|
|
55
|
+
| `funnel` | Uses `query.steps` and optional `label`, `value`, `colors`. |
|
|
56
|
+
| `histogram` | Uses `x`, `y`, and optional `buckets`. |
|
|
56
57
|
|
|
57
|
-
##
|
|
58
|
+
## Query Shape
|
|
58
59
|
|
|
59
60
|
```ts
|
|
60
|
-
type
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
| {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
61
|
+
type QueryConfig = {
|
|
62
|
+
resource: string
|
|
63
|
+
select?: Array<
|
|
64
|
+
| { field: string; as?: string; grain?: 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year' }
|
|
65
|
+
| { agg: 'sum' | 'count' | 'count_distinct' | 'avg' | 'min' | 'max' | 'median'; field?: string; as: string; filters?: unknown }
|
|
66
|
+
| { calc: string; as: string }
|
|
67
|
+
>
|
|
68
|
+
filters?: unknown
|
|
69
|
+
group_by?: Array<string | { field: string; as?: string; grain?: 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year'; timezone?: string }>
|
|
70
|
+
order_by?: Array<{ field: string; direction?: 'asc' | 'desc' }>
|
|
71
|
+
limit?: number
|
|
72
|
+
offset?: number
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Step-based chart queries use `steps` and may include `calcs`:
|
|
77
|
+
|
|
78
|
+
```yaml
|
|
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
|
|
88
|
+
chart:
|
|
89
|
+
type: bar
|
|
90
|
+
title: Average price by database
|
|
91
|
+
x:
|
|
92
|
+
field: name
|
|
93
|
+
y:
|
|
94
|
+
field: adjusted_value
|
|
95
|
+
query:
|
|
96
|
+
steps:
|
|
97
|
+
- name: SQLite
|
|
98
|
+
resource: cars_sl
|
|
99
|
+
metric:
|
|
100
|
+
agg: avg
|
|
101
|
+
field: price
|
|
102
|
+
as: value
|
|
103
|
+
- name: MySQL
|
|
104
|
+
resource: cars_mysql
|
|
105
|
+
metric:
|
|
106
|
+
agg: avg
|
|
107
|
+
field: price
|
|
108
|
+
as: value
|
|
109
|
+
calcs:
|
|
110
|
+
- calc: value * lookup($variables.price_multipliers, resource, 1)
|
|
111
|
+
as: adjusted_value
|
|
85
112
|
```
|
|
86
113
|
|
|
87
|
-
|
|
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
|
|
164
|
+
```
|
|
88
165
|
|
|
89
166
|
## Runtime Structure
|
|
90
167
|
|
|
@@ -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
|
},
|
|
@@ -13,6 +13,7 @@ export function useElementSize<T extends HTMLElement>(): ElementSizeState<T> {
|
|
|
13
13
|
const height = ref(0)
|
|
14
14
|
|
|
15
15
|
let observer: ResizeObserver | undefined
|
|
16
|
+
let frameId: number | undefined
|
|
16
17
|
|
|
17
18
|
onMounted(() => {
|
|
18
19
|
observer = new ResizeObserver(([entry]) => {
|
|
@@ -20,8 +21,18 @@ export function useElementSize<T extends HTMLElement>(): ElementSizeState<T> {
|
|
|
20
21
|
return
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
const nextWidth = Math.floor(entry.contentRect.width)
|
|
25
|
+
const nextHeight = Math.floor(entry.contentRect.height)
|
|
26
|
+
|
|
27
|
+
if (frameId !== undefined) {
|
|
28
|
+
cancelAnimationFrame(frameId)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
frameId = requestAnimationFrame(() => {
|
|
32
|
+
frameId = undefined
|
|
33
|
+
width.value = nextWidth
|
|
34
|
+
height.value = nextHeight
|
|
35
|
+
})
|
|
25
36
|
})
|
|
26
37
|
|
|
27
38
|
if (el.value) {
|
|
@@ -30,6 +41,10 @@ export function useElementSize<T extends HTMLElement>(): ElementSizeState<T> {
|
|
|
30
41
|
})
|
|
31
42
|
|
|
32
43
|
onBeforeUnmount(() => {
|
|
44
|
+
if (frameId !== undefined) {
|
|
45
|
+
cancelAnimationFrame(frameId)
|
|
46
|
+
}
|
|
47
|
+
|
|
33
48
|
observer?.disconnect()
|
|
34
49
|
})
|
|
35
50
|
|