Dashboards
Gateway prefix: ${API_BASE}/metadata/dashboards/...
Dashboard configuration can be stored in DB (jsonb) with classpath fallback. Backend controller: DashboardController (/api/v1/dashboards).
Save/update dashboard configuration (upsert by code)
- POST
/dashboards - Permissions:
admin/tenant:admin - Description: save or update (upsert) by
codein the configuration. Request body field isconfig, whose value is the full dashboard configuration JSON string. - Headers:
Authorization: Bearer <token>Content-Type: application/jsonX-Tenant-Id: <tenantId>(optional, recommended in multi-tenant scenarios)
- Reference config:
ai-daas-metadata-service/src/main/resources/dashboards/analytics.json
Example structure (excerpt):
{
"code": "analytics",
"title": "Business Cockpit",
"grid": { "cols": 12, "rowHeight": 40, "gutter": 12 },
"widgets": [
{ "id": "kpi_revenue_30d", "type": "kpi", "title": "Revenue (last 30 days)" },
{ "id": "trend_revenue_30d", "type": "chart", "title": "Revenue (last 30 days)" }
]
}
Example call (simplified with manual escaping):
curl -X POST "${API_BASE}/metadata/dashboards" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-H "X-Tenant-Id: <tenantId>" \
-d '{
"config": "{ \"code\": \"analytics\", \"title\": \"Business Cockpit\", \"grid\": { \"cols\": 12 }, \"widgets\": [] }"
}'
Recommended call (use file content and let jq escape):
curl -X POST "${API_BASE}/metadata/dashboards" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-H "X-Tenant-Id: <tenantId>" \
--data "{\"config\": \"$(jq -Rs . < ai-daas-metadata-service/src/main/resources/dashboards/analytics.json)\"}"
Example response:
{
"success": true,
"message": "Dashboard saved",
"data": {
"id": "<id>",
"code": "analytics",
"title": "Business Cockpit",
"config": "{ ... }",
"tenantId": "<tenantId>",
"createdAt": "2024-10-01T12:00:00Z",
"updatedAt": "2024-10-01T12:00:00Z"
}
}
Note: data.config in the response is a JSON string (the server stores and returns it as a pretty-printed string).
Update by code via PUT (optional)
- PUT
/dashboards/{code} - Permissions:
admin/tenant:admin - Description: upsert by path parameter
code, body isDashboardDtowhereconfigis the full JSON string.
Example:
curl -X PUT "${API_BASE}/metadata/dashboards/analytics" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-H "X-Tenant-Id: <tenantId>" \
-d "{ \"config\": \"{
\"code\": \"analytics\",
\"title\": \"Business Cockpit\",
\"grid\": { \"cols\": 12, \"rowHeight\": 40, \"gutter\": 12 },
\"widgets\": [
{
\"id\": \"kpi_revenue_30d\",
\"type\": \"kpi\",
\"title\": \"Revenue (last 30 days)\",
\"grid\": { \"x\": 0, \"y\": 0, \"w\": 3, \"h\": 2 },
\"style\": { \"unit\": \"¥\", \"valueFormat\": \",0.00\" },
\"dataSource\": { \"type\": \"view\", \"viewId\": \"metric.revenue_30d\" }
},
{
\"id\": \"trend_revenue_30d\",
\"type\": \"chart\",
\"title\": \"Revenue (last 30 days)\",
\"grid\": { \"x\": 3, \"y\": 0, \"w\": 6, \"h\": 6 },
\"chart\": { \"kind\": \"line\", \"xField\": \"date\", \"yField\": \"amount\", \"area\": true, \"smooth\": true },
\"dataSource\": { \"type\": \"view\", \"viewId\": \"view.revenue_by_day\" }
},
{
\"id\": \"top5_customers\",
\"type\": \"chart\",
\"title\": \"Top 5 Customers by Revenue\",
\"grid\": { \"x\": 9, \"y\": 0, \"w\": 3, \"h\": 6 },
\"chart\": { \"kind\": \"bar\", \"categoryField\": \"customer\", \"valueField\": \"amount\", \"orientation\": \"horizontal\", \"limit\": 5, \"sort\": \"-value\" },
\"dataSource\": { \"type\": \"view\", \"viewId\": \"view.revenue_by_customer\" }
},
{
\"id\": \"table_orders\",
\"type\": \"table\",
\"title\": \"Orders table (example)\",
\"grid\": { \"x\": 0, \"y\": 6, \"w\": 12, \"h\": 6 },
\"table\": {
\"columns\": [
{ \"key\": \"order_id\", \"title\": \"Order\", \"width\": 100, \"align\": \"left\" },
{ \"key\": \"customer\", \"title\": \"Customer\", \"width\": 160, \"align\": \"left\" },
{ \"key\": \"date\", \"title\": \"Date\", \"width\": 120, \"align\": \"center\" },
{ \"key\": \"amount\", \"title\": \"Amount\", \"width\": 120, \"align\": \"right\" }
],
\"rowHeight\": 32,
\"autoScroll\": true,
\"scroll\": { \"step\": 1, \"interval\": 16, \"pauseMs\": 1200 }
},
\"dataSource\": { \"type\": \"view\", \"viewId\": \"view.orders_recent\" }
}
]
}\" }"
Get dashboard by code
- GET
/dashboards/by-code/{code} - Permissions:
admin/tenant:admin/read
Headers:
Authorization: Bearer <token>X-Tenant-Id: <tenantId>(optional)
Example:
curl -X GET "${API_BASE}/metadata/dashboards/by-code/analytics" \
-H "Authorization: Bearer <token>" \
-H "X-Tenant-Id: <tenantId>"
Example response:
{
"success": true,
"message": "Dashboard found",
"data": {
"id": "<id>",
"code": "analytics",
"title": "Business Cockpit",
"config": "{ ... }"
}
}
Remarks:
PUT /dashboards/{code}is also supported for save/update (same effect as POST, body isDashboardDtowith JSON stringconfig). POST is generally recommended.- See backend controller reference:
ai-daas-metadata-service/src/main/java/com/aidaas/metadata/controller/DashboardController.java#L36-44for reading by code, and the@PostMapping/@PutMappingin the same file for saving. - Full sample configuration:
ai-daas-metadata-service/src/main/resources/dashboards/analytics.json
Get dashboard by ID
- GET
/dashboards/{id} - Permissions:
admin/tenant:admin/read
Paginated list of dashboards
- GET
/dashboards?page=1&pageSize=20 - Permissions:
admin/tenant:admin/read - Returns:
ApiResponse<PageResponse<DashboardDto>>
Configuration structure (based on analytics.json)
code: unique dashboard identifier (required)title: display titlegrid: layout configuration (colsnumber of columns,rowHeightrow height,gutterspacing)widgets: widget list, each item:id: widget IDtype:kpi|chart|tabletitle: widget titlegrid: widget’s position and size (x,y,w,h)style/chart/table: display/chart/table configuration by typedataSource: data source (for example{ "type": "view", "viewId": "view.revenue_by_day" })