Skip to content

Repository files navigation

@adminforth/dashboard

Dashboard plugin for AdminForth.

It adds configurable dashboard pages backed by an AdminForth resource. Dashboard records define groups and widgets, the plugin renders them under /dashboard/:slug, contributes a Dashboards sidebar group, and exposes endpoints for editing groups and widgets from the AdminForth UI.

Full setup guide: https://adminforth.dev/docs/tutorial/Plugins/dashboard/

Editing access

Dashboard editing is limited to superadmin by default. Set editRoles when registering the plugin to allow other roles:

newDashboardPlugin({dashboardConfigsResourceId: 'dashboard_configs',editRoles: ['superadmin','developer'],})

Dashboard Config Shape

typeDashboardConfig={version: numbergroups: {id: stringlabel: stringorder: number}[]widgets: DashboardWidgetConfig[]}

Each widget has common fields:

FieldDescription
idPersisted widget id.
group_idGroup where the widget is rendered.
labelOptional widget title.
targetWidget type: table, chart, kpi_card, pivot_table, or gauge_card.
orderWidget order inside its group.
variablesOptional widget variables passed to widget data loading. Variables are not available inside query.calcs.
sizePreset width: small, medium, large, wide, or full.
width, height, min_width, max_widthOptional explicit layout constraints.
queryData query definition.

Widget Support Matrix

Widget targetConfig fieldMain settingsData usage
tabletablepagination, page_size, columnsUses query to display raw or aggregate rows.
chartcharttype, x, y, label, value, series, buckets, color, colorsUses the same query shape for most chart types. Multi-resource charts use query.source: steps; add query.bucket for shared numeric buckets across resources.
kpi_cardcardvalue, subtitle, comparison, sparklineReads the first returned query row.
gauge_cardcardvalue, target, progress, colorReads the first returned query row.
pivot_tablepivotrows, columns, valuesUses query rows to build a pivot table.

Chart widget types:

Chart typeNotes
lineUses x and y; y may contain multiple fields in config.
pieUses label and value.
barUses x and y.
stacked_barUses x, y, and series.
funnelUses label, value, and optional colors. Data comes from the same query shapes as every other chart.
histogramUses x, y, and optional buckets. Current histogram runtime support is single-resource only: provide raw rows for the numeric field and let chart.buckets derive counts on the frontend. For multi-resource bucket distributions, use stacked_bar with query.source: steps and query.bucket.

Query Shape

typeQueryConfig={source?: 'resource'resource: stringselect?: Array<|{field: string;as?: string;grain?: 'day'|'week'|'month'|'year'}|{agg: 'sum'|'count'|'count_distinct'|'avg'|'min'|'max'|'median';field?: string;as: string;filters?: DashboardFilter|DashboardFilter[]}|{calc: string;as: string}>filters?: DashboardFilter|DashboardFilter[]group_by?: Array<string|{field: string;as?: string;grain?: 'day'|'week'|'month'|'year';timezone?: string}>order_by?: Array<{field: string;direction?: 'asc'|'desc'}>limit?: numberoffset?: numberbucket?: {field: string;buckets: Array<{label: string;min?: number;max?: number}>}calcs?: Array<{calc: string;as: string}>formatting?: Record<string,JsonValue>}|{source: 'steps'steps: Array<{name: stringresource: stringselect: Array<{agg: 'sum'|'count'|'count_distinct'|'avg'|'min'|'max'|'median';field?: string;as: string;filters?: DashboardFilter|DashboardFilter[]}>filters?: DashboardFilter|DashboardFilter[]}>calcs?: Array<{calc: string;as: string}>order_by?: Array<{field: string;direction?: 'asc'|'desc'}>limit?: numberoffset?: numberformatting?: Record<string,JsonValue>}
`source: 'steps'` returnsoneaggregaterowperstepbydefault.Eachstepsupportsaggregate `select` itemsplusoptional `filters`;itdoesnotsupportper-step`field`selects,`calc`selects,or`group_by`.Add`query.bucket`whenmultipleresourcesneedthesamenumericbuckets,forexampleastackedbardistributionbypricerange.typeDashboardFilter=|{and: DashboardFilter[]}|{or: DashboardFilter[]}|{field: stringeq?: FilterValueneq?: FilterValuegt?: FilterValuegte?: FilterValuelt?: FilterValuelte?: FilterValuein?: FilterValue[]not_in?: FilterValue[]like?: FilterValueilike?: FilterValue}typeJsonValue=string|number|boolean|null|JsonValue[]|{[key: string]: JsonValue}typeRelativeDateValue={now: true}|{now_minus: `${number}${'h'|'d'|'w'|'mo'|'y'}`}typeFilterValue=JsonValue|RelativeDateValue

Use filters for rolling date ranges. Do not hard-code dates for dashboards that should move with time:

query:
resource: ordersfilters:
and:
- field: created_atgte:
now_minus: 30d
- field: created_atlt:
now: true

Multi-resource queries use source: steps. Each step uses select, even if it has only one aggregate:

target: chartlabel: Average price by databasechart:
type: bartitle: Average price by databasex:
field: namey:
field: valuequery:
source: stepssteps:
- name: SQLiteresource: cars_slselect:
- agg: avgfield: priceas: value
- name: MySQLresource: cars_mysqlselect:
- agg: avgfield: priceas: value

Bucketed multi-resource queries use query.bucket. The dashboard runs each step once per bucket and returns rows with label, name, resource, and the selected aggregate aliases:

target: chartlabel: Cars by price range and databasechart:
type: stacked_bartitle: Cars by price range and databasex:
field: labely:
field: countseries:
field: namequery:
source: stepsbucket:
field: pricebuckets:
- label: Budgetmax: 3500
- label: Mid-rangemin: 3500max: 7000
- label: Premiummin: 7000steps:
- name: SQLiteresource: cars_slselect:
- agg: countas: count
- name: MySQLresource: cars_mysqlselect:
- agg: countas: count

Cost calculation example:

target: chartlabel: Model costschart:
type: stacked_bartitle: GPT-5.4 costs by dayx:
field: dayy:
- field: input_cost
- field: output_cost
- field: cached_costquery:
resource: model_usagefilters:
and:
- field: modeleq: gpt-5.4
- field: used_atgte:
now_minus: 7d
- field: used_atlt:
now: trueselect:
- field: used_atas: daygrain: day
- agg: sumfield: input_tokensas: input_tokens
- agg: sumfield: output_tokensas: output_tokens
- agg: sumfield: cached_tokensas: cached_tokensgroup_by:
- field: used_atas: daygrain: daycalcs:
- calc: input_tokens / 1000000 * 2.5as: input_cost
- calc: output_tokens / 1000000 * 15as: output_cost
- calc: cached_tokens / 1000000 * 0.25as: cached_cost

Runtime Structure

DashboardPage.vue
└── DashboardRuntime.vue
└── DashboardGroup.vue
└── WidgetShell.vue
└── WidgetRenderer.vue
├── TableWidget.vue
├── ChartWidget.vue
├── KpiCardWidget.vue
├── PivotTableWidget.vue
└── GaugeCardWidget.vue

DashboardPage.vue loads a dashboard by slug, DashboardRuntime.vue renders ordered groups, WidgetShell.vue provides the widget frame and editor actions, and WidgetRenderer.vue selects the widget component by target.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages