Dashboard Schema V2: Support panel actions (#110842)

* support panel actions

* refactor

* add test; move action transformer to utils

* refactor so v2 headers and queryParams are just a simple record

* update open api

* update actions to be same shape accross all dashboard schemas and add validation on the backend

* cleanup

* update snapshot

* add tests to validation
This commit is contained in:
Haris Rozajac
2025-09-12 11:31:05 -06:00
committed by GitHub
parent ccc87a03f0
commit de01b3e209
24 changed files with 2808 additions and 25 deletions
+97
View File
@@ -427,6 +427,8 @@ type FieldConfig struct {
Color *FieldColor `json:"color,omitempty"`
// The behavior when clicking on a result
Links []any `json:"links,omitempty"`
// Define interactive HTTP requests that can be triggered from data visualizations.
Actions []Action `json:"actions,omitempty"`
// Alternative to empty string
NoValue *string `json:"noValue,omitempty"`
// custom is specified by the FieldConfig field
@@ -654,6 +656,92 @@ const (
FieldColorSeriesByModeLast FieldColorSeriesByMode = "last"
)
// Dashboard action
type Action struct {
Type ActionType `json:"type"`
Title string `json:"title"`
Fetch *FetchOptions `json:"fetch,omitempty"`
Infinity *InfinityOptions `json:"infinity,omitempty"`
Confirmation *string `json:"confirmation,omitempty"`
OneClick *bool `json:"oneClick,omitempty"`
Variables []ActionVariable `json:"variables,omitempty"`
Style *DashboardActionStyle `json:"style,omitempty"`
}
// NewAction creates a new Action object.
func NewAction() *Action {
return &Action{}
}
// Dashboard action type
type ActionType string
const (
ActionTypeFetch ActionType = "fetch"
ActionTypeInfinity ActionType = "infinity"
)
// Fetch options
type FetchOptions struct {
Method HttpRequestMethod `json:"method"`
Url string `json:"url"`
Body *string `json:"body,omitempty"`
// These are 2D arrays of strings, each representing a key-value pair
// We are defining this way because we can't generate a go struct that
// that would have exactly two strings in each sub-array
QueryParams [][]string `json:"queryParams,omitempty"`
Headers [][]string `json:"headers,omitempty"`
}
// NewFetchOptions creates a new FetchOptions object.
func NewFetchOptions() *FetchOptions {
return &FetchOptions{}
}
type HttpRequestMethod string
const (
HttpRequestMethodGET HttpRequestMethod = "GET"
HttpRequestMethodPUT HttpRequestMethod = "PUT"
HttpRequestMethodPOST HttpRequestMethod = "POST"
HttpRequestMethodDELETE HttpRequestMethod = "DELETE"
HttpRequestMethodPATCH HttpRequestMethod = "PATCH"
)
// Infinity options
type InfinityOptions struct {
Method HttpRequestMethod `json:"method"`
Url string `json:"url"`
Body *string `json:"body,omitempty"`
// These are 2D arrays of strings, each representing a key-value pair
// We are defining them this way because we can't generate a go struct that
// that would have exactly two strings in each sub-array
QueryParams [][]string `json:"queryParams,omitempty"`
Headers [][]string `json:"headers,omitempty"`
DatasourceUid string `json:"datasourceUid"`
}
// NewInfinityOptions creates a new InfinityOptions object.
func NewInfinityOptions() *InfinityOptions {
return &InfinityOptions{}
}
type ActionVariable struct {
Key string `json:"key"`
Name string `json:"name"`
Type string `json:"type"`
}
// NewActionVariable creates a new ActionVariable object.
func NewActionVariable() *ActionVariable {
return &ActionVariable{
Type: ActionVariableType,
}
}
// Action variable type
const ActionVariableType = "string"
type DynamicConfigValue struct {
Id string `json:"id"`
Value any `json:"value,omitempty"`
@@ -1042,6 +1130,15 @@ func NewDashboardSpecialValueMapOptions() *DashboardSpecialValueMapOptions {
}
}
type DashboardActionStyle struct {
BackgroundColor *string `json:"backgroundColor,omitempty"`
}
// NewDashboardActionStyle creates a new DashboardActionStyle object.
func NewDashboardActionStyle() *DashboardActionStyle {
return &DashboardActionStyle{}
}
type PanelRepeatDirection string
const (
@@ -1060,6 +1060,71 @@
}
}
},
"com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardAction": {
"type": "object",
"required": [
"type",
"title"
],
"properties": {
"confirmation": {
"type": "string"
},
"fetch": {
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardFetchOptions"
},
"infinity": {
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardInfinityOptions"
},
"oneClick": {
"type": "boolean"
},
"style": {
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardV2alpha1ActionStyle"
},
"title": {
"type": "string",
"default": ""
},
"type": {
"type": "string",
"default": ""
},
"variables": {
"type": "array",
"items": {
"default": {},
"allOf": [
{
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardActionVariable"
}
]
}
}
}
},
"com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardActionVariable": {
"type": "object",
"required": [
"key",
"name",
"type"
],
"properties": {
"key": {
"type": "string",
"default": ""
},
"name": {
"type": "string",
"default": ""
},
"type": {
"type": "string",
"default": ""
}
}
},
"com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardAdHocFilterWithLabels": {
"description": "Define the AdHocFilterWithLabels type",
"type": "object",
@@ -2062,6 +2127,47 @@
}
}
},
"com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardFetchOptions": {
"type": "object",
"required": [
"method",
"url"
],
"properties": {
"body": {
"type": "string"
},
"headers": {
"type": "array",
"items": {
"type": "array",
"items": {
"type": "string",
"default": ""
}
}
},
"method": {
"type": "string",
"default": ""
},
"queryParams": {
"description": "These are 2D arrays of strings, each representing a key-value pair We are defining them this way because we can't generate a go struct that that would have exactly two strings in each sub-array",
"type": "array",
"items": {
"type": "array",
"items": {
"type": "string",
"default": ""
}
}
},
"url": {
"type": "string",
"default": ""
}
}
},
"com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardFieldColor": {
"description": "Map a field to a color.",
"type": "object",
@@ -2088,6 +2194,18 @@
"description": "The data model used in Grafana, namely the data frame, is a columnar-oriented table structure that unifies both time series and table query results. Each column within this structure is called a field. A field can represent a single time series or table column. Field options allow you to change how the data is displayed in your visualizations.",
"type": "object",
"properties": {
"actions": {
"description": "Define interactive HTTP requests that can be triggered from data visualizations.",
"type": "array",
"items": {
"default": {},
"allOf": [
{
"$ref": "#/components/schemas/com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardAction"
}
]
}
},
"color": {
"description": "Panel color configuration",
"allOf": [
@@ -2427,6 +2545,52 @@
}
}
},
"com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardInfinityOptions": {
"type": "object",
"required": [
"method",
"url",
"datasourceUid"
],
"properties": {
"body": {
"type": "string"
},
"datasourceUid": {
"type": "string",
"default": ""
},
"headers": {
"type": "array",
"items": {
"type": "array",
"items": {
"type": "string",
"default": ""
}
}
},
"method": {
"type": "string",
"default": ""
},
"queryParams": {
"description": "These are 2D arrays of strings, each representing a key-value pair We are defining them this way because we can't generate a go struct that that would have exactly two strings in each sub-array",
"type": "array",
"items": {
"type": "array",
"items": {
"type": "string",
"default": ""
}
}
},
"url": {
"type": "string",
"default": ""
}
}
},
"com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardIntervalVariableKind": {
"description": "Interval variable kind",
"type": "object",
@@ -3735,6 +3899,14 @@
}
}
},
"com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardV2alpha1ActionStyle": {
"type": "object",
"properties": {
"backgroundColor": {
"type": "string"
}
}
},
"com.github.grafana.grafana.apps.dashboard.pkg.apis.dashboard.v2alpha1.DashboardV2alpha1FieldConfigSourceOverrides": {
"type": "object",
"required": [