@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
package/README.md
CHANGED
|
@@ -31,60 +31,68 @@ Each widget has common fields:
|
|
|
31
31
|
| `order` | Widget order inside its group. |
|
|
32
32
|
| `size` | Preset width: `small`, `medium`, `large`, `wide`, or `full`. |
|
|
33
33
|
| `width`, `height`, `min_width`, `max_width` | Optional explicit layout constraints. |
|
|
34
|
-
| `
|
|
34
|
+
| `query` | Data query definition. |
|
|
35
35
|
|
|
36
36
|
## Widget Support Matrix
|
|
37
37
|
|
|
38
38
|
| Widget target | Config field | Main settings | Data usage |
|
|
39
39
|
| --- | --- | --- | --- |
|
|
40
|
-
| `table` | `table` | `pagination`, `page_size` | Uses `
|
|
41
|
-
| `chart` | `chart` | `type`, `
|
|
42
|
-
| `kpi_card` | `
|
|
43
|
-
| `gauge_card` | `
|
|
44
|
-
| `pivot_table` | `
|
|
40
|
+
| `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`; funnel charts use `query.steps`. |
|
|
42
|
+
| `kpi_card` | `card` | `value`, `subtitle`, `comparison`, `sparkline` | Reads the first returned query row. |
|
|
43
|
+
| `gauge_card` | `card` | `value`, `target`, `progress`, `color` | Reads the first returned query row. |
|
|
44
|
+
| `pivot_table` | `pivot` | `rows`, `columns`, `values` | Uses query rows to build a pivot table. |
|
|
45
45
|
|
|
46
46
|
Chart widget types:
|
|
47
47
|
|
|
48
48
|
| Chart type | Notes |
|
|
49
49
|
| --- | --- |
|
|
50
|
-
| `line` | Uses `
|
|
51
|
-
| `pie` | Uses `
|
|
52
|
-
| `bar` | Uses `
|
|
53
|
-
| `stacked_bar` | Uses `
|
|
54
|
-
| `funnel` | Uses `
|
|
55
|
-
| `histogram` | Uses
|
|
50
|
+
| `line` | Uses `x` and `y`; `y` may contain multiple fields in config. |
|
|
51
|
+
| `pie` | Uses `label` and `value`. |
|
|
52
|
+
| `bar` | Uses `x` and `y`. |
|
|
53
|
+
| `stacked_bar` | Uses `x`, `y`, and `series`. |
|
|
54
|
+
| `funnel` | Uses `query.steps` and optional `label`, `value`, `colors`. |
|
|
55
|
+
| `histogram` | Uses `x`, `y`, and optional `buckets`. |
|
|
56
56
|
|
|
57
|
-
##
|
|
57
|
+
## Query Shape
|
|
58
58
|
|
|
59
59
|
```ts
|
|
60
|
-
type
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
| {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
field?: string
|
|
74
|
-
}>
|
|
75
|
-
group_by?:
|
|
76
|
-
| { type: 'field'; field: string }
|
|
77
|
-
| {
|
|
78
|
-
type: 'date_trunc'
|
|
79
|
-
field: string
|
|
80
|
-
truncation: 'day' | 'week' | 'month' | 'year'
|
|
81
|
-
timezone?: string
|
|
82
|
-
}
|
|
83
|
-
filters?: unknown
|
|
84
|
-
}
|
|
60
|
+
type QueryConfig = {
|
|
61
|
+
resource: string
|
|
62
|
+
select?: Array<
|
|
63
|
+
| { field: string; as?: string; grain?: 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year' }
|
|
64
|
+
| { agg: 'sum' | 'count' | 'count_distinct' | 'avg' | 'min' | 'max' | 'median'; field?: string; as: string; filters?: unknown }
|
|
65
|
+
| { calc: string; as: string }
|
|
66
|
+
>
|
|
67
|
+
filters?: unknown
|
|
68
|
+
group_by?: Array<string | { field: string; as?: string; grain?: 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year'; timezone?: string }>
|
|
69
|
+
order_by?: Array<{ field: string; direction?: 'asc' | 'desc' }>
|
|
70
|
+
limit?: number
|
|
71
|
+
offset?: number
|
|
72
|
+
}
|
|
85
73
|
```
|
|
86
74
|
|
|
87
|
-
|
|
75
|
+
Funnel charts use a steps query:
|
|
76
|
+
|
|
77
|
+
```yaml
|
|
78
|
+
target: chart
|
|
79
|
+
chart:
|
|
80
|
+
type: funnel
|
|
81
|
+
title: Sales funnel
|
|
82
|
+
query:
|
|
83
|
+
steps:
|
|
84
|
+
- name: Leads
|
|
85
|
+
resource: leads
|
|
86
|
+
metric:
|
|
87
|
+
agg: count
|
|
88
|
+
as: value
|
|
89
|
+
- name: Customers
|
|
90
|
+
resource: orders
|
|
91
|
+
metric:
|
|
92
|
+
agg: count_distinct
|
|
93
|
+
field: customer_id
|
|
94
|
+
as: value
|
|
95
|
+
```
|
|
88
96
|
|
|
89
97
|
## Runtime Structure
|
|
90
98
|
|
|
@@ -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
|
|