Dashboard: Support Angular panel migrations in v2 schema (#115368)

* V2: Support angular panel migrations

* Add autoMigrateFrom and update ensureV2

* Remove context files

* Simplify angular migration handler

* linter

* Only include angular options in angular panel data
This commit is contained in:
Ivan Ortega Alba
2025-12-16 22:39:21 +01:00
committed by GitHub
parent c647140475
commit dfd396b06c
142 changed files with 37679 additions and 653 deletions
@@ -102,3 +102,71 @@ func IsArray(value interface{}) bool {
_, ok := value.([]interface{})
return ok
}
// AngularPanelMigrations maps deprecated Angular panel types to their modern equivalents.
// Used by both v0→v1 and v1→v2 conversions to ensure consistent migration behavior.
var AngularPanelMigrations = map[string]string{
"table-old": "table",
"singlestat": "stat",
"grafana-singlestat-panel": "stat",
"grafana-piechart-panel": "piechart",
"grafana-worldmap-panel": "geomap",
"natel-discrete-panel": "state-timeline",
}
// GetAngularPanelMigration checks if a panel type is an Angular panel and returns the new type to migrate to.
// Returns the new panel type if migration is needed, empty string otherwise.
// This handles both simple mappings and special cases like graph panel.
func GetAngularPanelMigration(panelType string, panel map[string]interface{}) string {
// Handle graph panel specially - it can migrate to different panel types
// based on xaxis.mode
if panelType == "graph" || panelType == "graphite" {
return GetGraphMigrationTarget(panel)
}
// Check simple Angular panel mappings
if newType, isAngular := AngularPanelMigrations[panelType]; isAngular {
return newType
}
return ""
}
// GetGraphMigrationTarget determines the target panel type for graph panel migration.
// Graph panels can migrate to timeseries, barchart, bargauge, or histogram depending on xaxis.mode.
func GetGraphMigrationTarget(panel map[string]interface{}) string {
// Default to timeseries
newType := "timeseries"
// Check xaxis mode for special cases
if xaxis, ok := panel["xaxis"].(map[string]interface{}); ok {
if mode, ok := xaxis["mode"].(string); ok {
switch mode {
case "series":
// Check legend values for bargauge vs barchart
if legend, ok := panel["legend"].(map[string]interface{}); ok {
if values, ok := legend["values"].(bool); ok && values {
newType = "bargauge"
} else {
newType = "barchart"
}
} else {
newType = "barchart"
}
case "histogram":
newType = "histogram"
}
}
}
return newType
}
// IsAngularPanelType checks if a panel type is a known Angular panel type.
func IsAngularPanelType(panelType string) bool {
if panelType == "graph" || panelType == "graphite" {
return true
}
_, isAngular := AngularPanelMigrations[panelType]
return isAngular
}