44 "context"
55 "fmt"
66 "net/url"
7+ "slices"
78 "strings"
89 "sync"
910
@@ -14,9 +15,13 @@ import (
1415)
1516
1617const (
17- pluginIDGraphOld = "graph"
18- pluginIDTable = "table"
19- pluginIDTableOld = "table-old"
18+ pluginIDGraphOld = "graph"
19+ pluginIDTable = "table"
20+ pluginIDTableOld = "table-old"
21+ pluginIDPiechart = "grafana-piechart-panel"
22+ pluginIDWorldmap = "grafana-worldmap-panel"
23+ pluginIDSinglestatOld = "grafana-singlestat-panel"
24+ pluginIDSinglestat = "singlestat"
2025)
2126
2227// GrafanaDetectorAPIClient is an interface that can be used to interact with the Grafana API for
@@ -236,15 +241,40 @@ func (d *Detector) checkPanels(dashboardDefinition *grafana.DashboardDefinition,
236241 return out , nil
237242}
238243
244+ // isLegacyPanel returns true if the panel is a legacy panel that can be automatically migrated to a React equivalent
245+ // by core Grafana upon opening the dashboard in the browser.
246+ func (d * Detector ) isLegacyPanel (pluginType string , dashboardSchemaVersion int ) bool {
247+ if slices .Contains ([]string {
248+ // "graph" has been replaced with timeseries
249+ pluginIDGraphOld ,
250+ // "table-old" is the old table panel (after it has been migrated)
251+ pluginIDTableOld ,
252+ // "grafana-piechart-panel" can be migrated by core:
253+ // https://github.com/grafana/grafana/blob/2638de6aeb6d780a2f51dd78f54e0ef7fcc25a7d/public/app/plugins/panel/piechart/migrations.ts#L11 ?
254+ pluginIDPiechart ,
255+ // "grafana-worldmap-panel" can be migrated to "geomap" by core:
256+ // https://github.com/grafana/grafana/blob/2638de6aeb6d780a2f51dd78f54e0ef7fcc25a7d/public/app/features/dashboard/state/getPanelPluginToMigrateTo.ts#L67-L72
257+ pluginIDWorldmap ,
258+ // "singlestat" and "grafana-singlestat-panel" can also be auto-migrated by core:
259+ // https://github.com/grafana/grafana/blob/2638de6aeb6d780a2f51dd78f54e0ef7fcc25a7d/public/app/plugins/panel/stat/StatMigrations.ts#L16-L17
260+ pluginIDSinglestatOld ,
261+ pluginIDSinglestat ,
262+ }, pluginType ) {
263+ return true
264+ }
265+ // "table" with a schema version < 24 is Angular table panel, which will be replaced by `table-old`
266+ // https://github.com/grafana/grafana/blob/7869ca1932c3a2a8f233acf35a3fe676187847bc/public/app/features/dashboard/state/DashboardMigrator.ts#L595-L610
267+ if pluginType == pluginIDTable && dashboardSchemaVersion < 24 {
268+ return true
269+ }
270+ return false
271+ }
272+
239273// checkPanel checks the given panel for Angular plugins.
240274func (d * Detector ) checkPanel (dashboardDefinition * grafana.DashboardDefinition , p * grafana.DashboardPanel ) ([]output.Detection , error ) {
241275 var out []output.Detection
242276
243277 // Check panel
244- // - "graph" has been replaced with timeseries
245- // - "table-old" is the old table panel (after it has been migrated)
246- // - "table" with a schema version < 24 is Angular table panel, which will be replaced by `table-old`:
247- // https://github.com/grafana/grafana/blob/7869ca1932c3a2a8f233acf35a3fe676187847bc/public/app/features/dashboard/state/DashboardMigrator.ts#L595-L610
248278 if p .Type == pluginIDGraphOld || p .Type == pluginIDTableOld || (p .Type == pluginIDTable && dashboardDefinition .Dashboard .SchemaVersion < 24 ) {
249279 // Different warning on legacy panel that can be migrated to React automatically
250280 out = append (out , output.Detection {
0 commit comments