You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Use a unique `slug`, for example `sales`. The plugin will expose it as `/dashboard/sales` and add it to the **Dashboards** sidebar group.
192
192
193
-
## Widget Data Sources
193
+
## Widget Queries
194
194
195
-
Widgets can load data from any AdminForth resource by using `dataSource`.
196
-
197
-
### Resource Data Source
195
+
Widgets load data through `query`. The same query shape supports raw rows, grouped aggregate rows, per-measure filters, ordering, and calculated fields.
198
196
199
197
```yaml
200
-
type: resource
201
-
resourceId: cars
202
-
columns:
203
-
- model
204
-
- price
205
-
- body_type
206
-
sort:
207
-
field: price
208
-
direction: desc
209
-
```
210
-
211
-
Resource data source fields:
212
-
213
-
- `resourceId`: AdminForth `resourceId`
214
-
- `columns`: optional list of columns returned to the widget
215
-
- `sort`: optional sort field and direction
216
-
- `filters`: optional AdminForth filter tree
217
-
218
-
### Aggregate Data Source
219
-
220
-
```yaml
221
-
type: aggregate
222
-
resourceId: cars
223
-
aggregations:
224
-
value:
225
-
operation: count
226
-
groupBy:
227
-
type: field
228
-
field: body_type
229
-
```
230
-
231
-
Aggregate data source fields:
232
-
233
-
- `aggregations`: named aggregation rules exposed to widgets as output fields
234
-
- `groupBy`: optional grouping rule; use `field` for raw values or `date_trunc` for time buckets
235
-
- grouped aggregate rows expose the grouping key as `group`
236
-
- `filters`: optional AdminForth filter tree
237
-
238
-
### Legacy Query Format
239
-
240
-
The legacy `query` shape is still supported for backwards compatibility.
241
-
242
-
```yaml
243
-
resource: cars
244
-
select:
245
-
- model
246
-
- price
247
-
- body_type
248
-
order:
249
-
field: price
250
-
direction: desc
251
-
limit: 10
198
+
query:
199
+
resource: cars
200
+
select:
201
+
- field: body_type
202
+
as: body_type
203
+
- agg: count
204
+
as: total_cars
205
+
- agg: avg
206
+
field: price
207
+
as: avg_price
208
+
group_by:
209
+
- body_type
210
+
order_by:
211
+
- field: total_cars
212
+
direction: desc
252
213
```
253
214
254
-
Legacy query fields:
255
-
256
-
- `resource`: AdminForth `resourceId`
257
-
- `select`: optional list of columns returned to the widget
258
-
- `order`: optional sort field and direction
259
-
- `limit`: optional maximum number of records
215
+
Funnel charts use a steps query because each step can use its own resource, metric, and filters.
260
216
261
217
## Widget Examples
262
218
@@ -275,44 +231,42 @@ table:
275
231
- price
276
232
- body_type
277
233
- production_year
278
-
pageSize: 10
279
-
dataSource:
280
-
type: resource
281
-
resourceId: cars
282
-
columns:
283
-
- model
284
-
- price
285
-
- body_type
286
-
- production_year
287
-
sort:
288
-
field: production_year
289
-
direction: desc
234
+
page_size: 10
235
+
query:
236
+
resource: cars
237
+
select:
238
+
- field: model
239
+
- field: price
240
+
- field: body_type
241
+
- field: production_year
242
+
order_by:
243
+
- field: production_year
244
+
direction: desc
290
245
```
291
246
292
-
Table widgets use backend pagination by default. Set `table.pageSize` to choose how many rows each backend request loads, or `table.pagination` to `false` to request all rows at once. If you still use legacy `query`, `query.limit` is used as the maximum number of rows available across all pages.
247
+
Table widgets use pagination by default. Set `table.page_size` to choose how many rows each request loads, or `table.pagination` to `false` to request all rows at once.
293
248
294
249
### Pie Chart
295
250
296
-
When a chart uses aggregate data with `groupBy`, the grouped key is available in the `group` field.
297
-
298
251
```yaml
299
252
label: Cars by Body Type
300
253
target: chart
301
254
size: medium
302
255
height: 360
303
256
chart:
304
257
type: pie
305
-
label_field: group
306
-
value_field: value
307
-
dataSource:
308
-
type: aggregate
309
-
resourceId: cars
310
-
aggregations:
311
-
value:
312
-
operation: count
313
-
groupBy:
314
-
type: field
258
+
label:
315
259
field: body_type
260
+
value:
261
+
field: value
262
+
query:
263
+
resource: cars
264
+
select:
265
+
- field: body_type
266
+
- agg: count
267
+
as: value
268
+
group_by:
269
+
- body_type
316
270
```
317
271
318
272
### Bar Chart
@@ -324,17 +278,54 @@ size: wide
324
278
height: 360
325
279
chart:
326
280
type: bar
327
-
label_field: group
328
-
value_field: value
329
-
dataSource:
330
-
type: aggregate
331
-
resourceId: cars
332
-
aggregations:
333
-
value:
334
-
operation: count
335
-
groupBy:
336
-
type: field
281
+
x:
337
282
field: production_year
283
+
y:
284
+
field: value
285
+
query:
286
+
resource: cars
287
+
select:
288
+
- field: production_year
289
+
- agg: count
290
+
as: value
291
+
group_by:
292
+
- production_year
293
+
```
294
+
295
+
### Chart With Multiple Sources
296
+
297
+
Use `query.steps` when funnel steps come from different resources. Each step returns one row with `name` and the metric alias.
298
+
299
+
```yaml
300
+
label: Sales Funnel
301
+
target: chart
302
+
size: large
303
+
height: 360
304
+
chart:
305
+
type: funnel
306
+
title: Sales funnel
307
+
query:
308
+
steps:
309
+
- name: Leads
310
+
resource: leads
311
+
metric:
312
+
agg: count
313
+
as: value
314
+
- name: Qualified
315
+
resource: leads
316
+
metric:
317
+
agg: count
318
+
as: value
319
+
filters:
320
+
and:
321
+
- field: status
322
+
eq: qualified
323
+
- name: Customers
324
+
resource: orders
325
+
metric:
326
+
agg: count_distinct
327
+
field: customer_id
328
+
as: value
338
329
```
339
330
340
331
### KPI Card
@@ -343,16 +334,16 @@ dataSource:
343
334
label: Average Car Price
344
335
target: kpi_card
345
336
size: small
346
-
kpi_card:
347
-
value_field: value
348
-
prefix: $
349
-
dataSource:
350
-
type: aggregate
351
-
resourceId: cars
352
-
aggregations:
353
-
value:
354
-
operation: avg
337
+
card:
338
+
value:
339
+
field: value
340
+
prefix: $
341
+
query:
342
+
resource: cars
343
+
select:
344
+
- agg: avg
355
345
field: price
346
+
as: value
356
347
```
357
348
358
349
### Gauge Card
@@ -361,25 +352,22 @@ dataSource:
361
352
label: Average Car Price
362
353
target: gauge_card
363
354
size: small
364
-
gauge_card:
365
-
value_field: value
366
-
min_field: min
367
-
max_field: max
368
-
suffix: $
355
+
card:
356
+
value:
357
+
field: value
358
+
suffix: $
359
+
target:
360
+
field: max
369
361
color: '#2563eb'
370
-
dataSource:
371
-
type: aggregate
372
-
resourceId: cars
373
-
aggregations:
374
-
value:
375
-
operation: avg
376
-
field: price
377
-
min:
378
-
operation: min
362
+
query:
363
+
resource: cars
364
+
select:
365
+
- agg: avg
379
366
field: price
380
-
max:
381
-
operation: max
367
+
as: value
368
+
- agg: max
382
369
field: price
370
+
as: max
383
371
```
384
372
385
373
### Pivot Table
@@ -389,23 +377,26 @@ label: Cars Summary by Body Type
389
377
target: pivot_table
390
378
size: full
391
379
height: 420
392
-
pivot_table:
393
-
row_field: group
394
-
dataSource:
395
-
type: aggregate
396
-
resourceId: cars
397
-
aggregations:
398
-
total_cars:
399
-
operation: count
400
-
avg_price:
401
-
operation: avg
380
+
pivot:
381
+
rows:
382
+
- body_type
383
+
values:
384
+
- field: total_cars
385
+
- field: avg_price
386
+
query:
387
+
resource: cars
388
+
select:
389
+
- field: body_type
390
+
- agg: count
391
+
as: total_cars
392
+
- agg: avg
402
393
field: price
403
-
groupBy:
404
-
type: field
405
-
field: body_type
394
+
as: avg_price
395
+
group_by:
396
+
- body_type
406
397
```
407
398
408
-
For aggregate pivot examples, the grouping key is available as `group`, and aggregation aliases such as `total_cars` and `avg_price` become table columns.
399
+
Aggregation aliases such as `total_cars` and `avg_price` become table columns.
0 commit comments