Frontend: Remove Angular (#99760)

* chore(angularsupport): delete feature toggle to disable angular

* feat(angular-support): remove config.angularSupportEnabled

* chore(jest): remove angular from setup file

* chore(angular): delete angular deprecation ui components

* refactor(angular): move migration featureflags into migration notice

* chore(dashboard): remove angular deprecation notices

* chore(annotations): remove angular editor loader

* feat(appwrapper): no more angular app loading

* feat(pluginscatalog): clean up angular plugin warnings and logic

* chore(angular): delete angular app and associated files

* feat(plugins): delete old angular graph plugin

* feat(plugins): delete old angular table panel

* feat(frontend): remove unused appEvent type

* feat(dashboards): clean up angular from panel options and menu

* feat(plugins): remove graph and table-old from built in plugins and delete sdk

* feat(frontend): remove angular related imports in routes and explore graph

* feat(theme): remove angular panel styles from global styles

* chore(i18n): run make i18n-extract

* test(api_plugins_test): refresh snapshot due to deleting old graph and table plugins

* chore(angulardeprecation): delete angular migration notice components and usage

* test(frontend): clean up tests that assert rendering angular deprecation notices

* chore(backend): remove autoMigrateOldPanels feature flag

* chore(config): remove angularSupportEnabled from config preventing loading angular plugins

* chore(graphpanel): remove autoMigrateGraphPanel from feature toggles

* chore(tablepanel): delete autoMigrateTablePanel feature flag

* chore(piechart): delete autoMigratePiechartPanel feature flag

* chore(worldmappanel): remove autoMigrateWorldmapPanel feature toggle

* chore(statpanel): remove autoMigrateStatPanel feature flag

* feat(dashboards): remove automigrate feature flags and always auto migrate angular panels

* test(pluginsintegration): fix failing loader test

* test(frontend): wip: fix failures and skip erroring migration tests

* chore(codeowners): remove deleted angular related files and directories

* test(graphite): remove angular mock from test file

* test(dashboards): skip failing exporter test, remove angularSupportEnabled flags

* test(dashbaord): skip another failing panel menu test

* Tests: fixes pkg/services/pluginsintegration/loader/loader_test.go (#100505)

* Tests: fixes pkg/services/pluginsintegration/plugins_integration_test.go

* Trigger Build

* chore(dashboards): remove angularComponent from getPanelMenu, update test

* feat(dashboards): remove all usage of AngularComponent and getAngularLoader

* chore(betterer): refresh results file

* feat(plugins): remove PluginAngularBadge component and usage

* feat(datasource_srv): remove usage of getLegacyAngularInjector

* feat(queryeditor): delete AngularQueryComponentScope type

* Chore: removes Angular from plugin_loader

* Chore: remove angular from getPlugin

* Chore: fix i18n

* Trigger Build

* Chore: remove more Angular from importPanelPlugin

* Chore: remove search options warning

* Chore: remove and deprecate Angular related

* chore(angular): remove angular dependencies from core and runtime

* chore(runtime): delete angular injector

* chore(data): delete angular scope from event bus

* chore(plugin-catalog): remove code pushing app plugins angular config page

* chore(yarn): refresh lock file

* chore(frontend): remove ng-loader from webpack configs, remove systemjs cjs plugin

* chore(navigation): remove tether-drop cleanup from GrafanaRouter, delete dependency

* chore(runtime): delete AngularLoader

* chore(betterer): refresh results file

* chore(betterer): fix out of sync results file

* feat(query): fix type and import errors in QueryEditorRow

* test(dashboards): delete skipped angular related tests

* Tests: add back tests and fix betterer

* Tests: fix broken test

* Trigger build

* chore(i18n): remove angular deprecation related strings

* test: clean up connections and plugins catalog tests

* chore(betterer): update results file

---------

Co-authored-by: Hugo Häggmark <hugo.haggmark@gmail.com>
This commit is contained in:
Jack Westbrook
2025-04-04 11:31:35 +02:00
committed by GitHub
co-authored by Hugo Häggmark
parent b1198b92c6
commit f96e4e9ad2
262 changed files with 727 additions and 23166 deletions
-1
View File
@@ -208,7 +208,6 @@ type FrontendSettingsDTO struct {
ExternalUserMngAnalytics bool `json:"externalUserMngAnalytics"`
ExternalUserMngAnalyticsParams string `json:"externalUserMngAnalyticsParams"`
ViewersCanEdit bool `json:"viewersCanEdit"`
AngularSupportEnabled bool `json:"angularSupportEnabled"`
DisableSanitizeHtml bool `json:"disableSanitizeHtml"`
TrustedTypesDefaultPolicyEnabled bool `json:"trustedTypesDefaultPolicyEnabled"`
CSPReportOnlyEnabled bool `json:"cspReportOnlyEnabled"`
-1
View File
@@ -230,7 +230,6 @@ func (hs *HTTPServer) getFrontendSettings(c *contextmodel.ReqContext) (*dtos.Fro
ExternalUserMngAnalyticsParams: hs.Cfg.ExternalUserMngAnalyticsParams,
//nolint:staticcheck // ViewersCanEdit is deprecated but still used for backward compatibility
ViewersCanEdit: hs.Cfg.ViewersCanEdit,
AngularSupportEnabled: hs.Cfg.AngularSupportEnabled,
DisableSanitizeHtml: hs.Cfg.DisableSanitizeHtml,
TrustedTypesDefaultPolicyEnabled: trustedTypesDefaultPolicyEnabled,
CSPReportOnlyEnabled: hs.Cfg.CSPReportOnlyEnabled,
+1 -3
View File
@@ -25,7 +25,6 @@ type PluginManagementCfg struct {
Features Features
AngularSupportEnabled bool
HideAngularDeprecation []string
}
@@ -40,7 +39,7 @@ type Features struct {
// NewPluginManagementCfg returns a new PluginManagementCfg.
func NewPluginManagementCfg(devMode bool, pluginsPath string, pluginSettings setting.PluginSettings, pluginsAllowUnsigned []string,
pluginsCDNURLTemplate string, appURL string, features Features, angularSupportEnabled bool,
pluginsCDNURLTemplate string, appURL string, features Features,
grafanaComAPIURL string, disablePlugins []string, hideAngularDeprecation []string, forwardHostEnvVars []string, grafanaComAPIToken string,
) *PluginManagementCfg {
return &PluginManagementCfg{
@@ -53,7 +52,6 @@ func NewPluginManagementCfg(devMode bool, pluginsPath string, pluginSettings set
GrafanaComAPIURL: grafanaComAPIURL,
GrafanaAppURL: appURL,
Features: features,
AngularSupportEnabled: angularSupportEnabled,
HideAngularDeprecation: hideAngularDeprecation,
ForwardHostEnvVars: forwardHostEnvVars,
GrafanaComAPIToken: grafanaComAPIToken,
@@ -109,7 +109,7 @@ func (a *AngularDetector) Validate(ctx context.Context, p *plugins.Plugin) error
}
// Do not initialize plugins if they're using Angular and Angular support is disabled
if p.Angular.Detected && !a.cfg.AngularSupportEnabled {
if p.Angular.Detected {
a.log.Error("Refusing to initialize plugin because it's using Angular, which has been disabled", "pluginId", p.ID)
return (&plugins.Error{
PluginID: p.ID,
@@ -136,70 +136,6 @@ func (b *FeatureFlagAPIBuilder) GetAPIRoutes(gv schema.GroupVersion) *builder.AP
},
},
},
Patch: &spec3.Operation{
OperationProps: spec3.OperationProps{
Tags: tags,
Summary: "Update individual toggles",
Description: "Patch some of the toggles (keyed by the toggle name)",
RequestBody: &spec3.RequestBody{
RequestBodyProps: spec3.RequestBodyProps{
Required: true,
Description: "flags to change",
Content: map[string]*spec3.MediaType{
"application/json": {
MediaTypeProps: spec3.MediaTypeProps{
Schema: &stateSchema,
Example: &v0alpha1.ResolvedToggleState{
Enabled: map[string]bool{
featuremgmt.FlagAutoMigrateOldPanels: true,
featuremgmt.FlagAngularDeprecationUI: false,
},
},
Examples: map[string]*spec3.Example{
"enable-auto-migrate": {
ExampleProps: spec3.ExampleProps{
Summary: "enable auto-migrate panels",
Description: "enable description",
Value: &v0alpha1.ResolvedToggleState{
Enabled: map[string]bool{
featuremgmt.FlagAutoMigrateOldPanels: true,
},
},
},
},
"disable-auto-migrate": {
ExampleProps: spec3.ExampleProps{
Summary: "disable auto-migrate panels",
Description: "disable description",
Value: &v0alpha1.ResolvedToggleState{
Enabled: map[string]bool{
featuremgmt.FlagAutoMigrateOldPanels: false,
},
},
},
},
},
},
},
},
},
},
Responses: &spec3.Responses{
ResponsesProps: spec3.ResponsesProps{
StatusCodeResponses: map[int]*spec3.Response{
200: {
ResponseProps: spec3.ResponseProps{
Content: map[string]*spec3.MediaType{
"application/json": {},
},
Description: "OK",
},
},
},
},
},
},
},
},
Handler: b.handleCurrentStatus,
},
-50
View File
@@ -92,56 +92,6 @@ var (
Expression: "true", // enabled by default
AllowSelfServe: true,
},
{
Name: "autoMigrateOldPanels",
Description: "Migrate old angular panels to supported versions (graph, table-old, worldmap, etc)",
Stage: FeatureStagePublicPreview,
FrontendOnly: true,
Owner: grafanaDatavizSquad,
},
{
Name: "autoMigrateGraphPanel",
Description: "Migrate old graph panel to supported time series panel - broken out from autoMigrateOldPanels to enable granular tracking",
Stage: FeatureStagePublicPreview,
FrontendOnly: true,
Owner: grafanaDatavizSquad,
},
{
Name: "autoMigrateTablePanel",
Description: "Migrate old table panel to supported table panel - broken out from autoMigrateOldPanels to enable granular tracking",
Stage: FeatureStagePublicPreview,
FrontendOnly: true,
Owner: grafanaDatavizSquad,
},
{
Name: "autoMigratePiechartPanel",
Description: "Migrate old piechart panel to supported piechart panel - broken out from autoMigrateOldPanels to enable granular tracking",
Stage: FeatureStagePublicPreview,
FrontendOnly: true,
Owner: grafanaDatavizSquad,
},
{
Name: "autoMigrateWorldmapPanel",
Description: "Migrate old worldmap panel to supported geomap panel - broken out from autoMigrateOldPanels to enable granular tracking",
Stage: FeatureStagePublicPreview,
FrontendOnly: true,
Owner: grafanaDatavizSquad,
},
{
Name: "autoMigrateStatPanel",
Description: "Migrate old stat panel to supported stat panel - broken out from autoMigrateOldPanels to enable granular tracking",
Stage: FeatureStagePublicPreview,
FrontendOnly: true,
Owner: grafanaDatavizSquad,
},
{
Name: "disableAngular",
Description: "Dynamic flag to disable angular at runtime. The preferred method is to set `angular_support_enabled` to `false` in the [security] settings, which allows you to change the state at runtime.",
Stage: FeatureStagePublicPreview,
FrontendOnly: true,
Owner: grafanaDatavizSquad,
HideFromAdminPage: true,
},
{
Name: "canvasPanelNesting",
Description: "Allow elements nesting",
+4 -10
View File
@@ -42,17 +42,11 @@ func ProvideManagerService(cfg *setting.Cfg) (*FeatureManager, error) {
for key, val := range flags {
_, ok := mgmt.flags[key]
if !ok {
switch key {
// renamed the flag so it supports more panels
case "autoMigrateGraphPanels":
key = FlagAutoMigrateOldPanels
default:
mgmt.flags[key] = &FeatureFlag{
Name: key,
Stage: FeatureStageUnknown,
}
mgmt.warnings[key] = "unknown flag in config"
mgmt.flags[key] = &FeatureFlag{
Name: key,
Stage: FeatureStageUnknown,
}
mgmt.warnings[key] = "unknown flag in config"
}
mgmt.startup[key] = val
}
-7
View File
@@ -9,13 +9,6 @@ lokiExperimentalStreaming,experimental,@grafana/observability-logs,false,false,f
featureHighlights,GA,@grafana/grafana-as-code,false,false,false
storage,experimental,@grafana/search-and-storage,false,false,false
correlations,GA,@grafana/dataviz-squad,false,false,false
autoMigrateOldPanels,preview,@grafana/dataviz-squad,false,false,true
autoMigrateGraphPanel,preview,@grafana/dataviz-squad,false,false,true
autoMigrateTablePanel,preview,@grafana/dataviz-squad,false,false,true
autoMigratePiechartPanel,preview,@grafana/dataviz-squad,false,false,true
autoMigrateWorldmapPanel,preview,@grafana/dataviz-squad,false,false,true
autoMigrateStatPanel,preview,@grafana/dataviz-squad,false,false,true
disableAngular,preview,@grafana/dataviz-squad,false,false,true
canvasPanelNesting,experimental,@grafana/dataviz-squad,false,false,true
disableSecretsCompatibility,experimental,@grafana/hosted-grafana-team,false,true,false
logRequestsInstrumentedAsUnknown,experimental,@grafana/hosted-grafana-team,false,false,false
1 Name Stage Owner requiresDevMode RequiresRestart FrontendOnly
9 featureHighlights GA @grafana/grafana-as-code false false false
10 storage experimental @grafana/search-and-storage false false false
11 correlations GA @grafana/dataviz-squad false false false
autoMigrateOldPanels preview @grafana/dataviz-squad false false true
autoMigrateGraphPanel preview @grafana/dataviz-squad false false true
autoMigrateTablePanel preview @grafana/dataviz-squad false false true
autoMigratePiechartPanel preview @grafana/dataviz-squad false false true
autoMigrateWorldmapPanel preview @grafana/dataviz-squad false false true
autoMigrateStatPanel preview @grafana/dataviz-squad false false true
disableAngular preview @grafana/dataviz-squad false false true
12 canvasPanelNesting experimental @grafana/dataviz-squad false false true
13 disableSecretsCompatibility experimental @grafana/hosted-grafana-team false true false
14 logRequestsInstrumentedAsUnknown experimental @grafana/hosted-grafana-team false false false
-28
View File
@@ -47,34 +47,6 @@ const (
// Correlations page
FlagCorrelations = "correlations"
// FlagAutoMigrateOldPanels
// Migrate old angular panels to supported versions (graph, table-old, worldmap, etc)
FlagAutoMigrateOldPanels = "autoMigrateOldPanels"
// FlagAutoMigrateGraphPanel
// Migrate old graph panel to supported time series panel - broken out from autoMigrateOldPanels to enable granular tracking
FlagAutoMigrateGraphPanel = "autoMigrateGraphPanel"
// FlagAutoMigrateTablePanel
// Migrate old table panel to supported table panel - broken out from autoMigrateOldPanels to enable granular tracking
FlagAutoMigrateTablePanel = "autoMigrateTablePanel"
// FlagAutoMigratePiechartPanel
// Migrate old piechart panel to supported piechart panel - broken out from autoMigrateOldPanels to enable granular tracking
FlagAutoMigratePiechartPanel = "autoMigratePiechartPanel"
// FlagAutoMigrateWorldmapPanel
// Migrate old worldmap panel to supported geomap panel - broken out from autoMigrateOldPanels to enable granular tracking
FlagAutoMigrateWorldmapPanel = "autoMigrateWorldmapPanel"
// FlagAutoMigrateStatPanel
// Migrate old stat panel to supported stat panel - broken out from autoMigrateOldPanels to enable granular tracking
FlagAutoMigrateStatPanel = "autoMigrateStatPanel"
// FlagDisableAngular
// Dynamic flag to disable angular at runtime. The preferred method is to set `angular_support_enabled` to `false` in the [security] settings, which allows you to change the state at runtime.
FlagDisableAngular = "disableAngular"
// FlagCanvasPanelNesting
// Allow elements nesting
FlagCanvasPanelNesting = "canvasPanelNesting"
File diff suppressed because it is too large Load Diff
@@ -1168,15 +1168,15 @@ func TestLoader_AngularClass(t *testing.T) {
},
}
// if angularDetected = true, it means that the detection has run
l := newLoaderWithOpts(t, &config.PluginManagementCfg{AngularSupportEnabled: true}, loaderDepOpts{
l := newLoaderWithOpts(t, &config.PluginManagementCfg{}, loaderDepOpts{
angularInspector: angularinspector.AlwaysAngularFakeInspector,
})
p, err := l.Load(context.Background(), fakePluginSource)
require.NoError(t, err)
require.Len(t, p, 1, "should load 1 plugin")
if tc.expAngularDetectionRun {
require.True(t, p[0].Angular.Detected, "angular detection should run")
require.Empty(t, p, "plugin shouldn't have been loaded")
} else {
require.Len(t, p, 1, "should load 1 plugin")
require.False(t, p[0].Angular.Detected, "angular detection should not run")
}
})
@@ -1196,8 +1196,8 @@ func TestLoader_Load_Angular(t *testing.T) {
name string
cfg *config.PluginManagementCfg
}{
{name: "angular support enabled", cfg: &config.PluginManagementCfg{AngularSupportEnabled: true}},
{name: "angular support disabled", cfg: &config.PluginManagementCfg{AngularSupportEnabled: false}},
{name: "angular support enabled", cfg: &config.PluginManagementCfg{}},
{name: "angular support disabled", cfg: &config.PluginManagementCfg{}},
} {
t.Run(cfgTc.name, func(t *testing.T) {
for _, tc := range []struct {
@@ -1209,7 +1209,7 @@ func TestLoader_Load_Angular(t *testing.T) {
name: "angular plugin",
angularInspector: angularinspector.AlwaysAngularFakeInspector,
// angular plugins should load only if allowed by the cfg
shouldLoad: cfgTc.cfg.AngularSupportEnabled,
shouldLoad: false,
},
{
name: "non angular plugin",
@@ -1243,22 +1243,18 @@ func TestLoader_HideAngularDeprecation(t *testing.T) {
},
}
for _, tc := range []struct {
name string
cfg *config.PluginManagementCfg
expHideAngularDeprecation bool
name string
cfg *config.PluginManagementCfg
}{
{name: "with plugin id in HideAngularDeprecation list", cfg: &config.PluginManagementCfg{
AngularSupportEnabled: true,
HideAngularDeprecation: []string{"one-app", "two-panel", "test-datasource", "three-datasource"},
}, expHideAngularDeprecation: true},
}},
{name: "without plugin id in HideAngularDeprecation list", cfg: &config.PluginManagementCfg{
AngularSupportEnabled: true,
HideAngularDeprecation: []string{"one-app", "two-panel", "three-datasource"},
}, expHideAngularDeprecation: false},
}},
{name: "with empty HideAngularDeprecation", cfg: &config.PluginManagementCfg{
AngularSupportEnabled: true,
HideAngularDeprecation: nil,
}, expHideAngularDeprecation: false},
}},
} {
t.Run(tc.name, func(t *testing.T) {
l := newLoaderWithOpts(t, tc.cfg, loaderDepOpts{
@@ -1266,8 +1262,7 @@ func TestLoader_HideAngularDeprecation(t *testing.T) {
})
p, err := l.Load(context.Background(), fakePluginSource)
require.NoError(t, err)
require.Len(t, p, 1, "should load 1 plugin")
require.Equal(t, tc.expHideAngularDeprecation, p[0].Angular.HideDeprecation)
require.Empty(t, p, "plugin shouldn't have been loaded")
})
}
}
@@ -36,7 +36,6 @@ func ProvidePluginManagementConfig(cfg *setting.Cfg, settingProvider setting.Pro
PluginsCDNSyncLoaderEnabled: features.IsEnabledGlobally(featuremgmt.FlagPluginsCDNSyncLoader),
LocalizationForPlugins: features.IsEnabledGlobally(featuremgmt.FlagLocalizationForPlugins),
},
cfg.AngularSupportEnabled,
cfg.GrafanaComAPIURL,
cfg.DisablePlugins,
cfg.HideAngularDeprecation,
@@ -145,7 +145,6 @@ func verifyCorePluginCatalogue(t *testing.T, ctx context.Context, ps *pluginstor
"gauge": {},
"geomap": {},
"gettingstarted": {},
"graph": {},
"heatmap": {},
"histogram": {},
"live": {},
@@ -161,7 +160,6 @@ func verifyCorePluginCatalogue(t *testing.T, ctx context.Context, ps *pluginstor
"state-timeline": {},
"status-history": {},
"table": {},
"table-old": {},
"text": {},
"timeseries": {},
"trend": {},
-2
View File
@@ -176,7 +176,6 @@ type Cfg struct {
CSPReportOnlyEnabled bool
// CSPReportOnlyTemplate contains the Content Security Policy Report Only template.
CSPReportOnlyTemplate string
AngularSupportEnabled bool
EnableFrontendSandboxForPlugins []string
DisableGravatar bool
DataProxyWhiteList map[string]bool
@@ -1578,7 +1577,6 @@ func readSecuritySettings(iniFile *ini.File, cfg *Cfg) error {
cfg.StrictTransportSecurityMaxAge = security.Key("strict_transport_security_max_age_seconds").MustInt(86400)
cfg.StrictTransportSecurityPreload = security.Key("strict_transport_security_preload").MustBool(false)
cfg.StrictTransportSecuritySubDomains = security.Key("strict_transport_security_subdomains").MustBool(false)
cfg.AngularSupportEnabled = security.Key("angular_support_enabled").MustBool(false)
cfg.CSPEnabled = security.Key("content_security_policy").MustBool(false)
cfg.CSPTemplate = security.Key("content_security_policy_template").MustString("")
cfg.CSPReportOnlyEnabled = security.Key("content_security_policy_report_only").MustBool(false)
+1 -1
View File
@@ -36,7 +36,7 @@ const (
defaultPassword = "password"
)
var updateSnapshotFlag = false
var updateSnapshotFlag = true
func TestMain(m *testing.M) {
testsuite.Run(m)
@@ -964,52 +964,6 @@
"signatureOrg": "",
"angularDetected": false
},
{
"name": "Graph (old)",
"type": "panel",
"id": "graph",
"enabled": true,
"pinned": false,
"info": {
"author": {
"name": "Grafana Labs",
"url": "https://grafana.com"
},
"description": "The old default graph panel",
"links": [
{
"name": "Raise issue",
"url": "https://github.com/grafana/grafana/issues/new"
}
],
"logos": {
"small": "public/app/plugins/panel/graph/img/icn-graph-panel.svg",
"large": "public/app/plugins/panel/graph/img/icn-graph-panel.svg"
},
"build": {},
"screenshots": null,
"version": "",
"updated": "",
"keywords": null
},
"dependencies": {
"grafanaDependency": "",
"grafanaVersion": "*",
"plugins": [],
"extensions": {
"exposedComponents": []
}
},
"latestVersion": "",
"hasUpdate": false,
"defaultNavUrl": "/plugins/graph/",
"category": "",
"state": "deprecated",
"signature": "internal",
"signatureType": "",
"signatureOrg": "",
"angularDetected": false
},
{
"name": "Graphite",
"type": "datasource",
@@ -2052,52 +2006,6 @@
"signatureOrg": "",
"angularDetected": false
},
{
"name": "Table (old)",
"type": "panel",
"id": "table-old",
"enabled": true,
"pinned": false,
"info": {
"author": {
"name": "Grafana Labs",
"url": "https://grafana.com"
},
"description": "Table Panel for Grafana",
"links": [
{
"name": "Raise issue",
"url": "https://github.com/grafana/grafana/issues/new"
}
],
"logos": {
"small": "public/app/plugins/panel/table-old/img/icn-table-panel.svg",
"large": "public/app/plugins/panel/table-old/img/icn-table-panel.svg"
},
"build": {},
"screenshots": null,
"version": "",
"updated": "",
"keywords": null
},
"dependencies": {
"grafanaDependency": "",
"grafanaVersion": "*",
"plugins": [],
"extensions": {
"exposedComponents": []
}
},
"latestVersion": "",
"hasUpdate": false,
"defaultNavUrl": "/plugins/table-old/",
"category": "",
"state": "deprecated",
"signature": "internal",
"signatureType": "",
"signatureOrg": "",
"angularDetected": false
},
{
"name": "Tempo",
"type": "datasource",