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
@@ -940,31 +940,12 @@ func applyPanelAutoMigration(panel map[string]interface{}) {
return
}
var newType string
// Graph needs special logic as it can be migrated to multiple panels
// Including graphite which was previously migrated to graph in the schema version 2 migration in DashboardMigrator.ts
// but this was a bug because in there graphite was set to graph, but since those migrations run
// after PanelModel.restoreModel where autoMigrateFrom is set, this caused the graph migration to be skipped.
// And this resulted in a dashboard with invalid panels.
if panelType == "graph" || panelType == "graphite" {
// Check xaxis mode for special cases
newType = getGraphAutoMigration(panel)
} else {
// Check autoMigrateAngular mapping
autoMigrateAngular := 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",
}
if mappedType, exists := autoMigrateAngular[panelType]; exists {
newType = mappedType
}
}
newType := schemaversion.GetAngularPanelMigration(panelType, panel)
// Apply auto-migration if a new type was determined
if newType != "" {
@@ -973,36 +954,6 @@ func applyPanelAutoMigration(panel map[string]interface{}) {
}
}
func getGraphAutoMigration(panel map[string]interface{}) string {
newType := ""
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
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"
}
}
}
// Default graph migration to timeseries
if newType == "" {
newType = "timeseries"
}
return newType
}
// removeNullValuesRecursively removes null values from nested objects and arrays
// This matches the frontend's JSON.stringify/parse behavior
func removeNullValuesRecursively(data interface{}) {