diff --git a/.betterer.results b/.betterer.results index f9e1356e3e1..953b94bc7b5 100644 --- a/.betterer.results +++ b/.betterer.results @@ -393,8 +393,7 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "8"] ], "packages/grafana-data/test/helpers/pluginMocks.ts:5381": [ - [0, 0, 0, "Do not use any type assertions.", "0"], - [0, 0, 0, "Unexpected any. Specify a different type.", "1"] + [0, 0, 0, "Do not use any type assertions.", "0"] ], "packages/grafana-e2e-selectors/src/resolver.ts:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"] @@ -465,11 +464,6 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "3"], [0, 0, 0, "Unexpected any. Specify a different type.", "4"] ], - "packages/grafana-runtime/src/services/AngularLoader.ts:5381": [ - [0, 0, 0, "Unexpected any. Specify a different type.", "0"], - [0, 0, 0, "Unexpected any. Specify a different type.", "1"], - [0, 0, 0, "Unexpected any. Specify a different type.", "2"] - ], "packages/grafana-runtime/src/services/EchoSrv.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"], [0, 0, 0, "Unexpected any. Specify a different type.", "1"], @@ -2889,8 +2883,7 @@ exports[`better eslint`] = { ], "public/app/features/dashboard/components/PanelEditor/OptionsPaneOptions.tsx:5381": [ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"], - [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"], - [0, 0, 0, "No untranslated strings. Wrap text with ", "2"] + [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"] ], "public/app/features/dashboard/components/PanelEditor/OverrideCategoryTitle.tsx:5381": [ [0, 0, 0, "\'HorizontalGroup\' import from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "0"] @@ -2998,10 +2991,9 @@ exports[`better eslint`] = { "public/app/features/dashboard/containers/DashboardPage.tsx:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"], [0, 0, 0, "Do not use any type assertions.", "1"], - [0, 0, 0, "Do not use any type assertions.", "2"], + [0, 0, 0, "Unexpected any. Specify a different type.", "2"], [0, 0, 0, "Unexpected any. Specify a different type.", "3"], - [0, 0, 0, "Unexpected any. Specify a different type.", "4"], - [0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "5"] + [0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "4"] ], "public/app/features/dashboard/containers/DashboardPageProxy.tsx:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"] @@ -3033,9 +3025,7 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "6"], [0, 0, 0, "Unexpected any. Specify a different type.", "7"], [0, 0, 0, "Unexpected any. Specify a different type.", "8"], - [0, 0, 0, "Unexpected any. Specify a different type.", "9"], - [0, 0, 0, "Unexpected any. Specify a different type.", "10"], - [0, 0, 0, "Unexpected any. Specify a different type.", "11"] + [0, 0, 0, "Unexpected any. Specify a different type.", "9"] ], "public/app/features/dashboard/state/DashboardMigrator.ts:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"], @@ -3728,16 +3718,12 @@ exports[`better eslint`] = { [0, 0, 0, "Do not re-export imported variable (\`./remotePlugin.mock\`)", "1"], [0, 0, 0, "Do not use export all (\`export * from ...\`)", "2"] ], - "public/app/features/plugins/admin/components/Badges/PluginAngularBadge.tsx:5381": [ - [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"] - ], "public/app/features/plugins/admin/components/Badges/index.ts:5381": [ - [0, 0, 0, "Do not re-export imported variable (\`./PluginAngularBadge\`)", "0"], - [0, 0, 0, "Do not re-export imported variable (\`./PluginDeprecatedBadge\`)", "1"], - [0, 0, 0, "Do not re-export imported variable (\`./PluginDisabledBadge\`)", "2"], - [0, 0, 0, "Do not re-export imported variable (\`./PluginEnterpriseBadge\`)", "3"], - [0, 0, 0, "Do not re-export imported variable (\`./PluginInstallBadge\`)", "4"], - [0, 0, 0, "Do not re-export imported variable (\`./PluginUpdateAvailableBadge\`)", "5"] + [0, 0, 0, "Do not re-export imported variable (\`./PluginDeprecatedBadge\`)", "0"], + [0, 0, 0, "Do not re-export imported variable (\`./PluginDisabledBadge\`)", "1"], + [0, 0, 0, "Do not re-export imported variable (\`./PluginEnterpriseBadge\`)", "2"], + [0, 0, 0, "Do not re-export imported variable (\`./PluginInstallBadge\`)", "3"], + [0, 0, 0, "Do not re-export imported variable (\`./PluginUpdateAvailableBadge\`)", "4"] ], "public/app/features/plugins/admin/components/GetStartedWithPlugin/GetStartedWithDataSource.tsx:5381": [ [0, 0, 0, "Do not use any type assertions.", "0"] @@ -3759,8 +3745,7 @@ exports[`better eslint`] = { [0, 0, 0, "Do not re-export imported variable (\`./InstallControlsWarning\`)", "1"] ], "public/app/features/plugins/admin/components/PluginDetailsBody.tsx:5381": [ - [0, 0, 0, "Do not use any type assertions.", "0"], - [0, 0, 0, "No untranslated strings. Wrap text with ", "1"] + [0, 0, 0, "No untranslated strings. Wrap text with ", "0"] ], "public/app/features/plugins/admin/components/PluginDetailsDeprecatedWarning.tsx:5381": [ [0, 0, 0, "No untranslated strings. Wrap text with ", "0"] @@ -3799,12 +3784,6 @@ exports[`better eslint`] = { "public/app/features/plugins/admin/types.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], - "public/app/features/plugins/angularDeprecation/AngularDeprecationNotice.tsx:5381": [ - [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"] - ], - "public/app/features/plugins/angularDeprecation/AngularMigrationNotice.tsx:5381": [ - [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"] - ], "public/app/features/plugins/components/PluginsErrorsInfo.tsx:5381": [ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"], [0, 0, 0, "No untranslated strings. Wrap text with ", "1"], @@ -3873,8 +3852,7 @@ exports[`better eslint`] = { [0, 0, 0, "Do not use any type assertions.", "0"], [0, 0, 0, "Do not use any type assertions.", "1"], [0, 0, 0, "Do not use any type assertions.", "2"], - [0, 0, 0, "Do not use any type assertions.", "3"], - [0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "4"] + [0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "3"] ], "public/app/features/query/components/QueryEditorRowHeader.tsx:5381": [ [0, 0, 0, "No untranslated strings. Wrap text with ", "0"], @@ -5351,9 +5329,6 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "16"], [0, 0, 0, "Unexpected any. Specify a different type.", "17"] ], - "public/app/plugins/sdk.ts:5381": [ - [0, 0, 0, "Do not re-export imported variable (\`loadPluginCss\`)", "0"] - ], "public/app/routes/RoutesWrapper.tsx:5381": [ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"] ], @@ -5374,13 +5349,6 @@ exports[`better eslint`] = { [0, 0, 0, "Unexpected any. Specify a different type.", "3"], [0, 0, 0, "Unexpected any. Specify a different type.", "4"] ], - "public/app/types/appEvent.ts:5381": [ - [0, 0, 0, "Unexpected any. Specify a different type.", "0"], - [0, 0, 0, "Unexpected any. Specify a different type.", "1"], - [0, 0, 0, "Unexpected any. Specify a different type.", "2"], - [0, 0, 0, "Unexpected any. Specify a different type.", "3"], - [0, 0, 0, "Unexpected any. Specify a different type.", "4"] - ], "public/app/types/dashboard.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], @@ -5416,8 +5384,7 @@ exports[`better eslint`] = { [0, 0, 0, "Do not use export all (\`export * from ...\`)", "17"], [0, 0, 0, "Do not use export all (\`export * from ...\`)", "18"], [0, 0, 0, "Do not use export all (\`export * from ...\`)", "19"], - [0, 0, 0, "Do not use export all (\`export * from ...\`)", "20"], - [0, 0, 0, "Do not use export all (\`export * from ...\`)", "21"] + [0, 0, 0, "Do not use export all (\`export * from ...\`)", "20"] ], "public/app/types/jquery/jquery.d.ts:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"], @@ -5678,89 +5645,6 @@ exports[`no gf-form usage`] = { [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] ], - "public/app/angular/components/PageHeader/PageHeader.tsx:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], - "public/app/angular/components/code_editor/code_editor.ts:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], - "public/app/angular/components/form_dropdown/form_dropdown.ts:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], - "public/app/angular/components/info_popover.ts:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], - "public/app/angular/components/switch.ts:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], - "public/app/angular/dropdown_typeahead.ts:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], - "public/app/angular/metric_segment.ts:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], - "public/app/angular/misc.ts:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], - "public/app/angular/panel/partials/query_editor_row.html:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], - "public/app/angular/partials/tls_auth_settings.html:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], "public/app/core/components/AccessControl/PermissionList.tsx:5381": [ [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] ], @@ -5808,9 +5692,6 @@ exports[`no gf-form usage`] = { "public/app/features/datasources/components/DataSourceTestingStatus.tsx:5381": [ [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] ], - "public/app/features/plugins/admin/components/AppConfigWrapper.tsx:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], "public/app/features/query/components/QueryEditorRow.tsx:5381": [ [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] ], @@ -5977,239 +5858,6 @@ exports[`no gf-form usage`] = { [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] ], - "public/app/plugins/panel/graph/axes_editor.html:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], - "public/app/plugins/panel/graph/tab_display.html:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], - "public/app/plugins/panel/graph/tab_legend.html:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], - "public/app/plugins/panel/graph/tab_series_overrides.html:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], - "public/app/plugins/panel/graph/thresholds_form.html:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], - "public/app/plugins/panel/graph/time_regions_form.html:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], "public/app/plugins/panel/heatmap/partials/axes_editor.html:5381": [ [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], @@ -6317,123 +5965,6 @@ exports[`no gf-form usage`] = { [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], - "public/app/plugins/panel/table-old/column_options.html:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] - ], - "public/app/plugins/panel/table-old/editor.html:5381": [ - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"], - [0, 0, 0, "gf-form usage has been deprecated. Use a component from @grafana/ui or custom CSS instead.", "5381"] ] }` }; diff --git a/.bingo/README.md b/.bingo/README.md index 7a5c2d4f6da..1d8a1360ccf 100644 --- a/.bingo/README.md +++ b/.bingo/README.md @@ -2,13 +2,13 @@ This is directory which stores Go modules with pinned buildable package that is used within this repository, managed by https://github.com/bwplotka/bingo. -* Run `bingo get` to install all tools having each own module file in this directory. -* Run `bingo get ` to install that have own module file in this directory. -* For Makefile: Make sure to put `include .bingo/Variables.mk` in your Makefile, then use $() variable where is the .bingo/.mod. -* For shell: Run `source .bingo/variables.env` to source all environment variable for each tool. -* For go: Import `.bingo/variables.go` to for variable names. -* See https://github.com/bwplotka/bingo or -h on how to add, remove or change binaries dependencies. +- Run `bingo get` to install all tools having each own module file in this directory. +- Run `bingo get ` to install that have own module file in this directory. +- For Makefile: Make sure to put `include .bingo/Variables.mk` in your Makefile, then use $() variable where is the .bingo/.mod. +- For shell: Run `source .bingo/variables.env` to source all environment variable for each tool. +- For go: Import `.bingo/variables.go` to for variable names. +- See https://github.com/bwplotka/bingo or -h on how to add, remove or change binaries dependencies. ## Requirements -* Go 1.14+ +- Go 1.14+ diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 2de6c285a10..6cdfd44466b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -543,7 +543,6 @@ playwright.config.ts @grafana/plugins-platform-frontend /public/app/plugins/panel/datagrid/ @grafana/dataviz-squad /public/app/plugins/panel/gauge/ @grafana/dataviz-squad /public/app/plugins/panel/gettingstarted/ @grafana/grafana-frontend-platform -/public/app/plugins/panel/graph/ @grafana/dataviz-squad /public/app/plugins/panel/heatmap/ @grafana/dataviz-squad /public/app/plugins/panel/histogram/ @grafana/dataviz-squad /public/app/plugins/panel/logs/ @grafana/observability-logs @@ -556,7 +555,6 @@ playwright.config.ts @grafana/plugins-platform-frontend /public/app/plugins/panel/status-history/ @grafana/dataviz-squad /public/app/plugins/panel/table/ @grafana/dataviz-squad /public/app/plugins/panel/table/cells/SparklineCellOptionsEditor.tsx @grafana/dataviz-squad @grafana/app-o11y-visualizations -/public/app/plugins/panel/table-old/ @grafana/dataviz-squad /public/app/plugins/panel/timeseries/ @grafana/dataviz-squad /public/app/plugins/panel/trend/ @grafana/dataviz-squad /public/app/plugins/panel/geomap/ @grafana/dataviz-squad @@ -568,7 +566,6 @@ playwright.config.ts @grafana/plugins-platform-frontend /public/app/plugins/panel/text/ @grafana/grafana-frontend-platform /public/app/plugins/panel/welcome/ @grafana/grafana-frontend-platform /public/app/plugins/panel/xychart/ @grafana/dataviz-squad -/public/app/plugins/sdk.ts @grafana/plugins-platform-frontend /public/app/routes/ @grafana/grafana-frontend-platform /public/app/store/ @grafana/grafana-frontend-platform /public/app/types/ @grafana/grafana-frontend-platform @@ -601,7 +598,6 @@ playwright.config.ts @grafana/plugins-platform-frontend /public/api-merged.json @grafana/grafana-backend-group /public/api-enterprise-spec.json @grafana/grafana-backend-group /public/openapi3.json @grafana/grafana-backend-group -/public/app/angular/ @torkelo /public/app/app.ts @grafana/frontend-ops /public/app/dev.ts @grafana/frontend-ops /public/app/core/utils/metrics.ts @grafana/plugins-platform-frontend diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 5d75c9b82b8..59c388840b2 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -6,7 +6,6 @@ "history", // we should bump this together with react-router-dom (see https://github.com/grafana/grafana/issues/76744) "react-router", // we should bump this together with history and react-router-dom "react-router-dom", // we should bump this together with history (see https://github.com/grafana/grafana/issues/76744) - "loader-utils", // v3 requires upstream changes in ngtemplate-loader. ignore, and remove when we remove angular. "monaco-editor", // due to us exposing this via @grafana/ui/CodeEditor's props bumping can break plugins "@fingerprintjs/fingerprintjs", // we don't want to bump to v4 due to licensing changes "slate", // we don't want to continue using this on the long run, use Monaco editor instead of Slate diff --git a/.prettierignore b/.prettierignore index b9f59a37afb..23d9231bc49 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,7 +1,6 @@ .git .github .yarn -.bingo build compiled data diff --git a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md index 4e533356d89..dcc1a40655e 100644 --- a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md +++ b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md @@ -91,38 +91,31 @@ Most [generally available](https://grafana.com/docs/release-life-cycle/#general- [Public preview](https://grafana.com/docs/release-life-cycle/#public-preview) features are supported by our Support teams, but might be limited to enablement, configuration, and some troubleshooting. -| Feature toggle name | Description | -| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `panelTitleSearch` | Search for dashboards using panel title | -| `autoMigrateOldPanels` | Migrate old angular panels to supported versions (graph, table-old, worldmap, etc) | -| `autoMigrateGraphPanel` | Migrate old graph panel to supported time series panel - broken out from autoMigrateOldPanels to enable granular tracking | -| `autoMigrateTablePanel` | Migrate old table panel to supported table panel - broken out from autoMigrateOldPanels to enable granular tracking | -| `autoMigratePiechartPanel` | Migrate old piechart panel to supported piechart panel - broken out from autoMigrateOldPanels to enable granular tracking | -| `autoMigrateWorldmapPanel` | Migrate old worldmap panel to supported geomap panel - broken out from autoMigrateOldPanels to enable granular tracking | -| `autoMigrateStatPanel` | Migrate old stat panel to supported stat panel - broken out from autoMigrateOldPanels to enable granular tracking | -| `disableAngular` | 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. | -| `grpcServer` | Run the GRPC server | -| `renderAuthJWT` | Uses JWT-based auth for rendering instead of relying on remote cache | -| `refactorVariablesTimeRange` | Refactor time range variables flow to reduce number of API calls made when query variables are chained | -| `faroDatasourceSelector` | Enable the data source selector within the Frontend Apps section of the Frontend Observability | -| `enableDatagridEditing` | Enables the edit functionality in the datagrid panel | -| `sqlDatasourceDatabaseSelection` | Enables previous SQL data source dataset dropdown behavior | -| `reportingRetries` | Enables rendering retries for the reporting feature | -| `externalServiceAccounts` | Automatic service account and token setup for plugins | -| `cloudWatchBatchQueries` | Runs CloudWatch metrics queries as separate batches | -| `pdfTables` | Enables generating table data as PDF in reporting | -| `canvasPanelPanZoom` | Allow pan and zoom in canvas panel | -| `regressionTransformation` | Enables regression analysis transformation | -| `onPremToCloudMigrations` | Enable the Grafana Migration Assistant, which helps you easily migrate on-prem resources, such as dashboards, folders, and data source configurations, to your Grafana Cloud stack. | -| `alertingSaveStateCompressed` | Enables the compressed protobuf-based alert state storage | -| `ssoSettingsLDAP` | Use the new SSO Settings API to configure LDAP | -| `improvedExternalSessionHandling` | Enables improved support for OAuth external sessions. After enabling this feature, users might need to re-authenticate themselves. | -| `elasticsearchCrossClusterSearch` | Enables cross cluster search in the Elasticsearch datasource | -| `improvedExternalSessionHandlingSAML` | Enables improved support for SAML external sessions. Ensure the NameID format is correctly configured in Grafana for SAML Single Logout to function properly. | -| `teamHttpHeadersMimir` | Enables LBAC for datasources for Mimir to apply LBAC filtering of metrics to the client requests for users in teams | -| `exploreMetricsUseExternalAppPlugin` | Use the externalized Grafana Metrics Drilldown (formerly known as Explore Metrics) app plugin | -| `alertRuleRestore` | Enables the alert rule restore feature | -| `azureMonitorLogsBuilderEditor` | Enables the logs builder mode for the Azure Monitor data source | +| Feature toggle name | Description | +| ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `panelTitleSearch` | Search for dashboards using panel title | +| `grpcServer` | Run the GRPC server | +| `renderAuthJWT` | Uses JWT-based auth for rendering instead of relying on remote cache | +| `refactorVariablesTimeRange` | Refactor time range variables flow to reduce number of API calls made when query variables are chained | +| `faroDatasourceSelector` | Enable the data source selector within the Frontend Apps section of the Frontend Observability | +| `enableDatagridEditing` | Enables the edit functionality in the datagrid panel | +| `sqlDatasourceDatabaseSelection` | Enables previous SQL data source dataset dropdown behavior | +| `reportingRetries` | Enables rendering retries for the reporting feature | +| `externalServiceAccounts` | Automatic service account and token setup for plugins | +| `cloudWatchBatchQueries` | Runs CloudWatch metrics queries as separate batches | +| `pdfTables` | Enables generating table data as PDF in reporting | +| `canvasPanelPanZoom` | Allow pan and zoom in canvas panel | +| `regressionTransformation` | Enables regression analysis transformation | +| `onPremToCloudMigrations` | Enable the Grafana Migration Assistant, which helps you easily migrate on-prem resources, such as dashboards, folders, and data source configurations, to your Grafana Cloud stack. | +| `alertingSaveStateCompressed` | Enables the compressed protobuf-based alert state storage | +| `ssoSettingsLDAP` | Use the new SSO Settings API to configure LDAP | +| `improvedExternalSessionHandling` | Enables improved support for OAuth external sessions. After enabling this feature, users might need to re-authenticate themselves. | +| `elasticsearchCrossClusterSearch` | Enables cross cluster search in the Elasticsearch datasource | +| `improvedExternalSessionHandlingSAML` | Enables improved support for SAML external sessions. Ensure the NameID format is correctly configured in Grafana for SAML Single Logout to function properly. | +| `teamHttpHeadersMimir` | Enables LBAC for datasources for Mimir to apply LBAC filtering of metrics to the client requests for users in teams | +| `exploreMetricsUseExternalAppPlugin` | Use the externalized Grafana Metrics Drilldown (formerly known as Explore Metrics) app plugin | +| `alertRuleRestore` | Enables the alert rule restore feature | +| `azureMonitorLogsBuilderEditor` | Enables the logs builder mode for the Azure Monitor data source | ## Experimental feature toggles diff --git a/e2e/old-arch/various-suite/graph-auto-migrate.spec.ts b/e2e/old-arch/various-suite/graph-auto-migrate.spec.ts index edbfd0ecab0..cddf07d0660 100644 --- a/e2e/old-arch/various-suite/graph-auto-migrate.spec.ts +++ b/e2e/old-arch/various-suite/graph-auto-migrate.spec.ts @@ -9,32 +9,12 @@ describe('Auto-migrate graph panel', () => { e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); }); - it('Graph panel is migrated with `autoMigrateOldPanels` feature toggle', () => { + it('Graph panel is auto-migrated', () => { e2e.flows.openDashboard({ uid: DASHBOARD_ID }); cy.contains(DASHBOARD_NAME).should('be.visible'); cy.get(UPLOT_MAIN_DIV_SELECTOR).should('not.exist'); - e2e.flows.openDashboard({ uid: DASHBOARD_ID, queryParams: { '__feature.autoMigrateOldPanels': true } }); - - cy.get(UPLOT_MAIN_DIV_SELECTOR).should('exist'); - }); - - it('Graph panel is migrated with config `disableAngular` feature toggle', () => { - e2e.flows.openDashboard({ uid: DASHBOARD_ID }); - cy.contains(DASHBOARD_NAME).should('be.visible'); - cy.get(UPLOT_MAIN_DIV_SELECTOR).should('not.exist'); - - e2e.flows.openDashboard({ uid: DASHBOARD_ID, queryParams: { '__feature.disableAngular': true } }); - - cy.get(UPLOT_MAIN_DIV_SELECTOR).should('exist'); - }); - - it('Graph panel is migrated with `autoMigrateGraphPanel` feature toggle', () => { e2e.flows.openDashboard({ uid: DASHBOARD_ID }); - cy.contains(DASHBOARD_NAME).should('be.visible'); - cy.get(UPLOT_MAIN_DIV_SELECTOR).should('not.exist'); - - e2e.flows.openDashboard({ uid: DASHBOARD_ID, queryParams: { '__feature.autoMigrateGraphPanel': true } }); cy.get(UPLOT_MAIN_DIV_SELECTOR).should('exist'); }); @@ -44,7 +24,7 @@ describe('Auto-migrate graph panel', () => { cy.contains(DASHBOARD_NAME).should('be.visible'); cy.get(UPLOT_MAIN_DIV_SELECTOR).should('not.exist'); - e2e.flows.openDashboard({ uid: DASHBOARD_ID, queryParams: { '__feature.autoMigrateGraphPanel': true } }); + e2e.flows.openDashboard({ uid: DASHBOARD_ID }); e2e.components.Panels.Panel.title('Business Hours') .should('exist') diff --git a/e2e/various-suite/graph-auto-migrate.spec.ts b/e2e/various-suite/graph-auto-migrate.spec.ts index edbfd0ecab0..cddf07d0660 100644 --- a/e2e/various-suite/graph-auto-migrate.spec.ts +++ b/e2e/various-suite/graph-auto-migrate.spec.ts @@ -9,32 +9,12 @@ describe('Auto-migrate graph panel', () => { e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); }); - it('Graph panel is migrated with `autoMigrateOldPanels` feature toggle', () => { + it('Graph panel is auto-migrated', () => { e2e.flows.openDashboard({ uid: DASHBOARD_ID }); cy.contains(DASHBOARD_NAME).should('be.visible'); cy.get(UPLOT_MAIN_DIV_SELECTOR).should('not.exist'); - e2e.flows.openDashboard({ uid: DASHBOARD_ID, queryParams: { '__feature.autoMigrateOldPanels': true } }); - - cy.get(UPLOT_MAIN_DIV_SELECTOR).should('exist'); - }); - - it('Graph panel is migrated with config `disableAngular` feature toggle', () => { - e2e.flows.openDashboard({ uid: DASHBOARD_ID }); - cy.contains(DASHBOARD_NAME).should('be.visible'); - cy.get(UPLOT_MAIN_DIV_SELECTOR).should('not.exist'); - - e2e.flows.openDashboard({ uid: DASHBOARD_ID, queryParams: { '__feature.disableAngular': true } }); - - cy.get(UPLOT_MAIN_DIV_SELECTOR).should('exist'); - }); - - it('Graph panel is migrated with `autoMigrateGraphPanel` feature toggle', () => { e2e.flows.openDashboard({ uid: DASHBOARD_ID }); - cy.contains(DASHBOARD_NAME).should('be.visible'); - cy.get(UPLOT_MAIN_DIV_SELECTOR).should('not.exist'); - - e2e.flows.openDashboard({ uid: DASHBOARD_ID, queryParams: { '__feature.autoMigrateGraphPanel': true } }); cy.get(UPLOT_MAIN_DIV_SELECTOR).should('exist'); }); @@ -44,7 +24,7 @@ describe('Auto-migrate graph panel', () => { cy.contains(DASHBOARD_NAME).should('be.visible'); cy.get(UPLOT_MAIN_DIV_SELECTOR).should('not.exist'); - e2e.flows.openDashboard({ uid: DASHBOARD_ID, queryParams: { '__feature.autoMigrateGraphPanel': true } }); + e2e.flows.openDashboard({ uid: DASHBOARD_ID }); e2e.components.Panels.Panel.title('Business Hours') .should('exist') diff --git a/package.json b/package.json index 43e6102ebb7..93fbe086f19 100644 --- a/package.json +++ b/package.json @@ -101,8 +101,6 @@ "@testing-library/jest-dom": "6.6.3", "@testing-library/react": "16.2.0", "@testing-library/user-event": "14.6.1", - "@types/angular": "1.8.9", - "@types/angular-route": "1.7.6", "@types/babel__core": "^7", "@types/babel__preset-env": "^7", "@types/chance": "^1.1.3", @@ -214,7 +212,6 @@ "mini-css-extract-plugin": "2.9.2", "msw": "2.7.0", "mutationobserver-shim": "0.3.7", - "ngtemplate-loader": "2.1.0", "node-notifier": "10.0.1", "nx": "20.7.1", "openapi-types": "^12.1.3", @@ -310,10 +307,6 @@ "@visx/shape": "3.12.0", "@visx/tooltip": "3.12.0", "@welldone-software/why-did-you-render": "8.0.3", - "angular": "1.8.3", - "angular-bindonce": "0.3.1", - "angular-route": "1.8.3", - "angular-sanitize": "1.8.3", "ansicolor": "2.0.3", "baron": "3.0.3", "brace": "0.11.1", @@ -412,8 +405,6 @@ "swagger-ui-react": "5.20.5", "symbol-observable": "4.0.0", "systemjs": "6.15.1", - "systemjs-cjs-extra": "0.2.1", - "tether-drop": "https://github.com/torkelo/drop", "tinycolor2": "1.6.0", "tslib": "2.8.1", "tween-functions": "^1.2.0", @@ -426,7 +417,6 @@ "resolutions": { "underscore": "1.13.7", "@types/slate": "0.47.11", - "ngtemplate-loader/loader-utils": "^2.0.0", "semver@~7.0.0": "7.5.4", "semver@7.3.4": "7.5.4", "debug@npm:^0.7.2": "2.6.9", diff --git a/packages/grafana-data/src/events/EventBus.ts b/packages/grafana-data/src/events/EventBus.ts index cdcd16b2e89..39cd895c37a 100644 --- a/packages/grafana-data/src/events/EventBus.ts +++ b/packages/grafana-data/src/events/EventBus.ts @@ -1,4 +1,3 @@ -import { IScope } from 'angular'; import EventEmitter from 'eventemitter3'; import { Unsubscribable, Observable, Subscriber } from 'rxjs'; import { filter } from 'rxjs/operators'; @@ -66,7 +65,7 @@ export class EventBusSrv implements EventBus, LegacyEmitter { } } - on(event: AppEvent | string, handler: LegacyEventHandler, scope?: IScope) { + on(event: AppEvent | string, handler: LegacyEventHandler) { // console.log(`Deprecated emitter function used (on), use $on`); // need this wrapper to make old events compatible with old handlers @@ -79,13 +78,6 @@ export class EventBusSrv implements EventBus, LegacyEmitter { } else { this.emitter.on(event.name, handler.wrapper); } - - if (scope) { - const unbind = scope.$on('$destroy', () => { - this.off(event, handler); - unbind(); - }); - } } off(event: AppEvent | string, handler: LegacyEventHandler) { diff --git a/packages/grafana-data/src/events/types.ts b/packages/grafana-data/src/events/types.ts index ad4fec0a025..514b980d1b4 100644 --- a/packages/grafana-data/src/events/types.ts +++ b/packages/grafana-data/src/events/types.ts @@ -1,4 +1,3 @@ -import { IScope } from 'angular'; import { Unsubscribable, Observable } from 'rxjs'; /** @@ -129,7 +128,7 @@ export interface LegacyEmitter { /** * @deprecated use $on */ - on(event: AppEvent | string, handler: LegacyEventHandler, scope?: IScope): void; + on(event: AppEvent | string, handler: LegacyEventHandler): void; /** * @deprecated use $on diff --git a/packages/grafana-data/src/index.ts b/packages/grafana-data/src/index.ts index ce7a0339f67..a3af39ded7c 100644 --- a/packages/grafana-data/src/index.ts +++ b/packages/grafana-data/src/index.ts @@ -257,6 +257,7 @@ export { toOption } from './utils/selectUtils'; export * as arrayUtils from './utils/arrayUtils'; export { store, Store } from './utils/store'; export { LocalStorageValueProvider } from './utils/LocalStorageValueProvider'; +export { throwIfAngular } from './utils/throwIfAngular'; // Tranformations export { standardTransformers } from './transformations/transformers'; diff --git a/packages/grafana-data/src/types/app.ts b/packages/grafana-data/src/types/app.ts index 38a20ad12b8..e9e792dfc7e 100644 --- a/packages/grafana-data/src/types/app.ts +++ b/packages/grafana-data/src/types/app.ts @@ -1,5 +1,7 @@ import { ComponentType } from 'react'; +import { throwIfAngular } from '../utils/throwIfAngular'; + import { KeyValue } from './data'; import { NavModel } from './navModel'; import { PluginMeta, GrafanaPlugin, PluginIncludeType } from './plugin'; @@ -85,9 +87,7 @@ export class AppPlugin extends GrafanaPlugin { + /** @deprecated it will be removed in a future release */ QueryCtrl?: any; + /** @deprecated it will be removed in a future release */ AnnotationsQueryCtrl?: any; VariableQueryEditor?: any; QueryEditor?: ComponentType>; diff --git a/packages/grafana-data/src/types/featureToggles.gen.ts b/packages/grafana-data/src/types/featureToggles.gen.ts index 2ffc97577c3..c8ed12cb035 100644 --- a/packages/grafana-data/src/types/featureToggles.gen.ts +++ b/packages/grafana-data/src/types/featureToggles.gen.ts @@ -63,34 +63,6 @@ export interface FeatureToggles { */ correlations?: boolean; /** - * Migrate old angular panels to supported versions (graph, table-old, worldmap, etc) - */ - autoMigrateOldPanels?: boolean; - /** - * Migrate old graph panel to supported time series panel - broken out from autoMigrateOldPanels to enable granular tracking - */ - autoMigrateGraphPanel?: boolean; - /** - * Migrate old table panel to supported table panel - broken out from autoMigrateOldPanels to enable granular tracking - */ - autoMigrateTablePanel?: boolean; - /** - * Migrate old piechart panel to supported piechart panel - broken out from autoMigrateOldPanels to enable granular tracking - */ - autoMigratePiechartPanel?: boolean; - /** - * Migrate old worldmap panel to supported geomap panel - broken out from autoMigrateOldPanels to enable granular tracking - */ - autoMigrateWorldmapPanel?: boolean; - /** - * Migrate old stat panel to supported stat panel - broken out from autoMigrateOldPanels to enable granular tracking - */ - autoMigrateStatPanel?: boolean; - /** - * 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. - */ - disableAngular?: boolean; - /** * Allow elements nesting */ canvasPanelNesting?: boolean; diff --git a/packages/grafana-data/src/types/plugin.ts b/packages/grafana-data/src/types/plugin.ts index b279d885db6..045dfdcee0b 100644 --- a/packages/grafana-data/src/types/plugin.ts +++ b/packages/grafana-data/src/types/plugin.ts @@ -239,6 +239,7 @@ export class GrafanaPlugin { loadError?: boolean; // Config control (app/datasource) + /** @deprecated it will be removed in a future release */ angularConfigCtrl?: any; // Show configuration tabs on the plugin page diff --git a/packages/grafana-data/src/utils/throwIfAngular.test.ts b/packages/grafana-data/src/utils/throwIfAngular.test.ts new file mode 100644 index 00000000000..6e3bf3c0f83 --- /dev/null +++ b/packages/grafana-data/src/utils/throwIfAngular.test.ts @@ -0,0 +1,63 @@ +import { PanelPlugin, PluginMeta, PluginType } from '@grafana/data'; + +import { throwIfAngular } from './throwIfAngular'; + +const plugin: PluginMeta = { + id: 'test', + name: 'Test', + type: PluginType.datasource, + info: { + author: { name: 'Test', url: 'https://test.com' }, + description: 'Test', + links: [], + logos: { large: '', small: '' }, + screenshots: [], + updated: '2021-01-01', + version: '1.0.0', + }, + module: 'test', + baseUrl: 'test', +}; + +describe('throwIfAngular', () => { + it('should throw if angular plugin', () => { + const underTest = { ...plugin, angular: { detected: true, hideDeprecation: false } }; + expect(() => throwIfAngular(underTest)).toThrow('Angular plugins are not supported'); + }); + + it('should throw if angular plugin', () => { + const underTest = { ...plugin, angularDetected: true }; + expect(() => throwIfAngular(underTest)).toThrow('Angular plugins are not supported'); + }); + + it('should throw if angular panel', () => { + const underTest = new PanelPlugin(null); + underTest.angularPanelCtrl = {}; + expect(() => throwIfAngular(underTest)).toThrow('Angular plugins are not supported'); + }); + + it('should throw if angular module', () => { + const underTest: System.Module = { PanelCtrl: {} }; + expect(() => throwIfAngular(underTest)).toThrow('Angular plugins are not supported'); + }); + + it('should throw if angular module', () => { + const underTest: System.Module = { ConfigCtrl: {} }; + expect(() => throwIfAngular(underTest)).toThrow('Angular plugins are not supported'); + }); + + it('should not throw if not angular plugin', () => { + const underTest = { ...plugin, angular: { detected: false, hideDeprecation: false } }; + expect(() => throwIfAngular(underTest)).not.toThrow(); + }); + + it('should not throw if not angular panel', () => { + const underTest = new PanelPlugin(null); + expect(() => throwIfAngular(underTest)).not.toThrow(); + }); + + it('should not throw if not angular module', () => { + const underTest: System.Module = {}; + expect(() => throwIfAngular(underTest)).not.toThrow(); + }); +}); diff --git a/packages/grafana-data/src/utils/throwIfAngular.ts b/packages/grafana-data/src/utils/throwIfAngular.ts new file mode 100644 index 00000000000..7e542b14462 --- /dev/null +++ b/packages/grafana-data/src/utils/throwIfAngular.ts @@ -0,0 +1,15 @@ +import { PanelPlugin } from '../panel/PanelPlugin'; +import { PluginMeta } from '../types/plugin'; + +export function throwIfAngular(module?: System.Module): void; +export function throwIfAngular(panel?: PanelPlugin): void; +export function throwIfAngular(plugin?: PluginMeta): void; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function throwIfAngular(data?: any): void { + const isAngularPlugin = data?.angular?.detected ?? data?.angularDetected ?? false; + const isAngularPanel = data?.angularPanelCtrl ?? false; + const isAngularModule = data.PanelCtrl ?? data?.ConfigCtrl ?? false; + if (isAngularPlugin || isAngularPanel || isAngularModule) { + throw new Error('Angular plugins are not supported'); + } +} diff --git a/packages/grafana-data/test/helpers/pluginMocks.ts b/packages/grafana-data/test/helpers/pluginMocks.ts index 226d6eb87cb..66139a02e2a 100644 --- a/packages/grafana-data/test/helpers/pluginMocks.ts +++ b/packages/grafana-data/test/helpers/pluginMocks.ts @@ -37,13 +37,8 @@ export const getMockPlugins = (amount: number): PluginMeta[] => { return plugins; }; -export function getPanelPlugin( - options: Partial, - reactPanel?: ComponentType, - angularPanel?: any -): PanelPlugin { +export function getPanelPlugin(options: Partial, reactPanel?: ComponentType): PanelPlugin { const plugin = new PanelPlugin(reactPanel!); - plugin.angularPanelCtrl = angularPanel; plugin.meta = { id: options.id!, type: PluginType.panel, diff --git a/packages/grafana-runtime/package.json b/packages/grafana-runtime/package.json index a03d9fbc051..fe80ca32676 100644 --- a/packages/grafana-runtime/package.json +++ b/packages/grafana-runtime/package.json @@ -73,7 +73,6 @@ "@testing-library/dom": "10.4.0", "@testing-library/react": "16.2.0", "@testing-library/user-event": "14.6.1", - "@types/angular": "1.8.9", "@types/history": "4.7.11", "@types/jest": "29.5.14", "@types/lodash": "4.17.15", diff --git a/packages/grafana-runtime/src/config.ts b/packages/grafana-runtime/src/config.ts index 47342cc0dbf..e6444cdb80c 100644 --- a/packages/grafana-runtime/src/config.ts +++ b/packages/grafana-runtime/src/config.ts @@ -78,7 +78,6 @@ export class GrafanaBootConfig implements GrafanaConfig { feedbackLinksEnabled = true; disableLoginForm = false; defaultDatasource = ''; // UID - angularSupportEnabled = false; authProxyEnabled = false; exploreEnabled = false; queryHistoryEnabled = false; @@ -240,10 +239,6 @@ export class GrafanaBootConfig implements GrafanaConfig { overrideFeatureTogglesFromUrl(this); overrideFeatureTogglesFromLocalStorage(this); - if (this.featureToggles.disableAngular) { - this.angularSupportEnabled = false; - } - // Creating theme after applying feature toggle overrides in case we need to toggle anything this.theme2 = getThemeById(this.bootData.user.theme); this.bootData.user.lightTheme = this.theme2.isLight; diff --git a/packages/grafana-runtime/src/services/AngularLoader.ts b/packages/grafana-runtime/src/services/AngularLoader.ts deleted file mode 100644 index c7beac4fbb5..00000000000 --- a/packages/grafana-runtime/src/services/AngularLoader.ts +++ /dev/null @@ -1,87 +0,0 @@ -/** - * Used to enable rendering of Angular components within a - * React component without losing proper typings. - * - * @example - * ```typescript - * class Component extends PureComponent { - * element: HTMLElement; - * angularComponent: AngularComponent; - * - * componentDidMount() { - * const template = '' // angular template here; - * const scopeProps = { ctrl: angularController }; // angular scope properties here - * const loader = getAngularLoader(); - * this.angularComponent = loader.load(this.element, scopeProps, template); - * } - * - * componentWillUnmount() { - * if (this.angularComponent) { - * this.angularComponent.destroy(); - * } - * } - * - * render() { - * return ( - *
(this.element = element)} /> - * ); - * } - * } - * ``` - * - * @public - */ -export interface AngularComponent { - /** - * Should be called when the React component will unmount. - */ - destroy(): void; - /** - * Can be used to trigger a re-render of the Angular component. - */ - digest(): void; - /** - * Used to access the Angular scope from the React component. - */ - getScope(): any; -} - -/** - * Used to load an Angular component from the context of a React component. - * Please see the {@link AngularComponent} for a proper example. - * - * @public - */ -export interface AngularLoader { - /** - * - * @param elem - the element that the Angular component will be loaded into. - * @param scopeProps - values that will be accessed via the Angular scope. - * @param template - template used by the Angular component. - */ - load(elem: any, scopeProps: any, template: string): AngularComponent; -} - -let instance: AngularLoader; - -/** - * Used during startup by Grafana to set the AngularLoader so it is available - * via the {@link getAngularLoader} to the rest of the application. - * - * @internal - */ -export function setAngularLoader(v: AngularLoader) { - instance = v; -} - -/** - * Used to retrieve the {@link AngularLoader} that enables the use of Angular - * components within a React component. - * - * Please see the {@link AngularComponent} for a proper example. - * - * @public - */ -export function getAngularLoader(): AngularLoader { - return instance; -} diff --git a/packages/grafana-runtime/src/services/index.ts b/packages/grafana-runtime/src/services/index.ts index 9503007d68c..c8bf24d6cb5 100644 --- a/packages/grafana-runtime/src/services/index.ts +++ b/packages/grafana-runtime/src/services/index.ts @@ -1,10 +1,8 @@ export * from './backendSrv'; -export * from './AngularLoader'; export * from './dataSourceSrv'; export * from './LocationSrv'; export * from './EchoSrv'; export * from './templateSrv'; -export * from './legacyAngularInjector'; export * from './live'; export * from './LocationService'; export * from './appEvents'; diff --git a/packages/grafana-runtime/src/services/legacyAngularInjector.ts b/packages/grafana-runtime/src/services/legacyAngularInjector.ts deleted file mode 100644 index 4c581ffd97d..00000000000 --- a/packages/grafana-runtime/src/services/legacyAngularInjector.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { auto } from 'angular'; - -let singleton: auto.IInjectorService; - -/** - * Used during startup by Grafana to temporarily expose the angular injector to - * pure javascript plugins using {@link getLegacyAngularInjector}. - * - * @internal - */ -export const setLegacyAngularInjector = (instance: auto.IInjectorService) => { - singleton = instance; -}; - -/** - * WARNING: this function provides a temporary way for plugins to access anything in the - * angular injector. While the migration from angular to react continues, there are a few - * options that do not yet have good alternatives. Note that use of this function will - * be removed in the future. - * - * @beta - */ -export const getLegacyAngularInjector = (): auto.IInjectorService => singleton; diff --git a/packages/grafana-ui/src/themes/GlobalStyles/GlobalStyles.tsx b/packages/grafana-ui/src/themes/GlobalStyles/GlobalStyles.tsx index 06c6801aae5..f0952c4ccaf 100644 --- a/packages/grafana-ui/src/themes/GlobalStyles/GlobalStyles.tsx +++ b/packages/grafana-ui/src/themes/GlobalStyles/GlobalStyles.tsx @@ -4,7 +4,6 @@ import { useTheme2 } from '../ThemeContext'; import { getAccessibilityStyles } from './accessibility'; import { getAlertingStyles } from './alerting'; -import { getAgularPanelStyles } from './angularPanelStyles'; import { getCardStyles } from './card'; import { getCodeStyles } from './code'; import { getDashboardGridStyles } from './dashboardGrid'; @@ -39,7 +38,6 @@ export function GlobalStyles(props: GlobalStylesProps) { { } async componentDidMount() { - await loadAndInitAngularIfEnabled(); this.setState({ ready: true }); $('.preloader').remove(); diff --git a/public/app/angular/AngularApp.ts b/public/app/angular/AngularApp.ts deleted file mode 100644 index 438cbd1a637..00000000000 --- a/public/app/angular/AngularApp.ts +++ /dev/null @@ -1,166 +0,0 @@ -import 'angular'; -import 'angular-route'; -import 'angular-sanitize'; -import 'angular-bindonce'; -import 'vendor/bootstrap/bootstrap'; - -import angular from 'angular'; // eslint-disable-line no-duplicate-imports -import { extend } from 'lodash'; - -import { getTemplateSrv } from '@grafana/runtime'; -import { coreModule, angularModules } from 'app/angular/core_module'; -import appEvents from 'app/core/app_events'; -import { config } from 'app/core/config'; -import { contextSrv } from 'app/core/services/context_srv'; -import { DashboardLoaderSrv } from 'app/features/dashboard/services/DashboardLoaderSrv'; -import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv'; -import { setAngularPanelReactWrapper } from 'app/features/plugins/importPanelPlugin'; -import { SystemJS } from 'app/features/plugins/loader/systemjs'; -import { buildImportMap } from 'app/features/plugins/loader/utils'; -import * as sdk from 'app/plugins/sdk'; - -import { registerAngularDirectives } from './angular_wrappers'; -import { initAngularRoutingBridge } from './bridgeReactAngularRouting'; -import { monkeyPatchInjectorWithPreAssignedBindings } from './injectorMonkeyPatch'; -import { getAngularPanelReactWrapper } from './panel/AngularPanelReactWrapper'; -import { promiseToDigest } from './promiseToDigest'; -import { registerComponents } from './registerComponents'; - -// Angular plugin dependencies map -const importMap = { - angular: { - ...angular, - default: angular, - }, - 'app/core/core_module': { - default: coreModule, - __useDefault: true, - }, - 'app/core/core': { - appEvents: appEvents, - contextSrv: contextSrv, - coreModule: coreModule, - }, - 'app/plugins/sdk': sdk, - 'app/core/utils/promiseToDigest': { promiseToDigest }, -} as Record; - -export class AngularApp { - ngModuleDependencies: any[]; - preBootModules: any[]; - registerFunctions: any; - - constructor() { - this.preBootModules = []; - this.ngModuleDependencies = []; - this.registerFunctions = {}; - } - - init() { - const app = angular.module('grafana', []); - - setAngularPanelReactWrapper(getAngularPanelReactWrapper); - - app.config([ - '$controllerProvider', - '$compileProvider', - '$filterProvider', - '$httpProvider', - '$provide', - '$sceDelegateProvider', - ( - $controllerProvider: angular.IControllerProvider, - $compileProvider: angular.ICompileProvider, - $filterProvider: angular.IFilterProvider, - $httpProvider: angular.IHttpProvider, - $provide: angular.auto.IProvideService, - $sceDelegateProvider: angular.ISCEDelegateProvider - ) => { - if (config.buildInfo.env !== 'development') { - $compileProvider.debugInfoEnabled(false); - } - - $httpProvider.useApplyAsync(true); - - if (Boolean(config.pluginsCDNBaseURL)) { - $sceDelegateProvider.trustedResourceUrlList(['self', `${config.pluginsCDNBaseURL}/**`]); - } - - this.registerFunctions.controller = $controllerProvider.register; - this.registerFunctions.directive = $compileProvider.directive; - this.registerFunctions.factory = $provide.factory; - this.registerFunctions.service = $provide.service; - this.registerFunctions.filter = $filterProvider.register; - - $provide.decorator('$http', [ - '$delegate', - '$templateCache', - ($delegate: any, $templateCache: any) => { - const get = $delegate.get; - $delegate.get = (url: string, config: any) => { - if (url.match(/\.html$/)) { - // some template's already exist in the cache - if (!$templateCache.get(url)) { - url += '?v=' + new Date().getTime(); - } - } - return get(url, config); - }; - return $delegate; - }, - ]); - }, - ]); - - this.ngModuleDependencies = ['grafana.core', 'ngSanitize', 'grafana', 'pasvaz.bindonce', 'react']; - - // makes it possible to add dynamic stuff - angularModules.forEach((m: angular.IModule) => { - this.useModule(m); - }); - - // register react angular wrappers - angular.module('grafana.services').service('dashboardLoaderSrv', DashboardLoaderSrv); - - coreModule.factory('timeSrv', () => getTimeSrv()); - coreModule.factory('templateSrv', () => getTemplateSrv()); - - registerAngularDirectives(); - registerComponents(); - initAngularRoutingBridge(); - - const imports = buildImportMap(importMap); - // pass the map of module names so systemjs can resolve them - SystemJS.addImportMap({ imports }); - - // disable tool tip animation - $.fn.tooltip.defaults.animation = false; - } - - useModule(module: angular.IModule) { - if (this.preBootModules) { - this.preBootModules.push(module); - } else { - extend(module, this.registerFunctions); - } - this.ngModuleDependencies.push(module.name); - return module; - } - - bootstrap() { - const injector = angular.bootstrap(document.getElementById('ngRoot')!, this.ngModuleDependencies); - - monkeyPatchInjectorWithPreAssignedBindings(injector); - - injector.invoke(() => { - this.preBootModules.forEach((module) => { - extend(module, this.registerFunctions); - }); - - // I don't know - return () => {}; - }); - - return injector; - } -} diff --git a/public/app/angular/AngularLocationWrapper.test.ts b/public/app/angular/AngularLocationWrapper.test.ts deleted file mode 100644 index 7bd20c89f8c..00000000000 --- a/public/app/angular/AngularLocationWrapper.test.ts +++ /dev/null @@ -1,209 +0,0 @@ -import { HistoryWrapper, locationService, setLocationService } from '@grafana/runtime'; - -import { AngularLocationWrapper } from './AngularLocationWrapper'; - -// The methods in this file are deprecated -// Stub the deprecation warning here to prevent polluting the test output -jest.mock('@grafana/data', () => ({ - ...jest.requireActual('@grafana/data'), - deprecationWarning: () => {}, -})); - -describe('AngularLocationWrapper', () => { - const { location } = window; - - beforeEach(() => { - setLocationService(new HistoryWrapper()); - }); - - beforeAll(() => { - // @ts-ignore - delete window.location; - - window.location = { - ...location, - hash: '#hash', - host: 'localhost:3000', - hostname: 'localhost', - href: 'http://www.domain.com:9877/path/b?search=a&b=c&d#hash', - origin: 'http://www.domain.com:9877', - pathname: '/path/b', - port: '9877', - protocol: 'http:', - search: '?search=a&b=c&d', - }; - }); - - afterAll(() => { - window.location = location; - }); - - const wrapper = new AngularLocationWrapper(); - it('should provide common getters', () => { - locationService.push('/path/b?search=a&b=c&d#hash'); - - expect(wrapper.absUrl()).toBe('http://www.domain.com:9877/path/b?search=a&b=c&d#hash'); - expect(wrapper.protocol()).toBe('http'); - expect(wrapper.host()).toBe('www.domain.com'); - expect(wrapper.port()).toBe(9877); - expect(wrapper.path()).toBe('/path/b'); - expect(wrapper.search()).toEqual({ search: 'a', b: 'c', d: true }); - expect(wrapper.hash()).toBe('hash'); - expect(wrapper.url()).toBe('/path/b?search=a&b=c&d#hash'); - }); - - describe('path', () => { - it('should change path', function () { - locationService.push('/path/b?search=a&b=c&d#hash'); - wrapper.path('/new/path'); - - expect(wrapper.path()).toBe('/new/path'); - expect(wrapper.absUrl()).toBe('http://www.domain.com:9877/new/path?search=a&b=c&d#hash'); - }); - - it('should not break on numeric values', function () { - locationService.push('/path/b?search=a&b=c&d#hash'); - wrapper.path(1); - expect(wrapper.path()).toBe('/1'); - expect(wrapper.absUrl()).toBe('http://www.domain.com:9877/1?search=a&b=c&d#hash'); - }); - - it('should allow using 0 as path', function () { - locationService.push('/path/b?search=a&b=c&d#hash'); - wrapper.path(0); - expect(wrapper.path()).toBe('/0'); - expect(wrapper.absUrl()).toBe('http://www.domain.com:9877/0?search=a&b=c&d#hash'); - }); - it('should set to empty path on null value', function () { - locationService.push('/path/b?search=a&b=c&d#hash'); - wrapper.path('/foo'); - expect(wrapper.path()).toBe('/foo'); - wrapper.path(null); - expect(wrapper.path()).toBe('/'); - }); - }); - - describe('search', () => { - it('should accept string', function () { - locationService.push('/path/b'); - wrapper.search('x=y&c'); - expect(wrapper.search()).toEqual({ x: 'y', c: true }); - expect(wrapper.absUrl()).toBe('http://www.domain.com:9877/path/b?x=y&c'); - }); - - it('search() should accept object', function () { - locationService.push('/path/b'); - wrapper.search({ one: '1', two: true }); - expect(wrapper.search()).toEqual({ one: '1', two: true }); - expect(wrapper.absUrl()).toBe('http://www.domain.com:9877/path/b?one=1&two'); - }); - - it('should copy object', function () { - locationService.push('/path/b'); - const obj: Record = { one: '1', two: true, three: null }; - wrapper.search(obj); - expect(obj).toEqual({ one: '1', two: true, three: null }); - obj.one = 'changed'; - - expect(wrapper.search()).toEqual({ one: '1', two: true }); - expect(wrapper.absUrl()).toBe('http://www.domain.com:9877/path/b?one=1&two'); - }); - - it('should change single parameter', function () { - wrapper.search({ id: 'old', preserved: true }); - wrapper.search('id', 'new'); - - expect(wrapper.search()).toEqual({ id: 'new', preserved: true }); - }); - - it('should remove single parameter', function () { - wrapper.search({ id: 'old', preserved: true }); - wrapper.search('id', null); - - expect(wrapper.search()).toEqual({ preserved: true }); - }); - - it('should remove multiple parameters', function () { - locationService.push('/path/b'); - wrapper.search({ one: '1', two: true }); - expect(wrapper.search()).toEqual({ one: '1', two: true }); - - wrapper.search({ one: null, two: null }); - expect(wrapper.search()).toEqual({}); - expect(wrapper.absUrl()).toBe('http://www.domain.com:9877/path/b'); - }); - - it('should accept numeric keys', function () { - locationService.push('/path/b'); - wrapper.search({ 1: 'one', 2: 'two' }); - expect(wrapper.search()).toEqual({ '1': 'one', '2': 'two' }); - expect(wrapper.absUrl()).toBe('http://www.domain.com:9877/path/b?1=one&2=two'); - }); - - it('should handle multiple value', function () { - wrapper.search('a&b'); - expect(wrapper.search()).toEqual({ a: true, b: true }); - - wrapper.search('a', null); - - expect(wrapper.search()).toEqual({ b: true }); - - wrapper.search('b', undefined); - expect(wrapper.search()).toEqual({}); - }); - - it('should handle single value', function () { - wrapper.search('ignore'); - expect(wrapper.search()).toEqual({ ignore: true }); - wrapper.search(1); - expect(wrapper.search()).toEqual({ 1: true }); - }); - }); - - describe('url', () => { - it('should change the path, search and hash', function () { - wrapper.url('/some/path?a=b&c=d#hhh'); - expect(wrapper.url()).toBe('/some/path?a=b&c=d#hhh'); - expect(wrapper.absUrl()).toBe('http://www.domain.com:9877/some/path?a=b&c=d#hhh'); - expect(wrapper.path()).toBe('/some/path'); - expect(wrapper.search()).toEqual({ a: 'b', c: 'd' }); - expect(wrapper.hash()).toBe('hhh'); - }); - - it('should change only hash when no search and path specified', function () { - locationService.push('/path/b?search=a&b=c&d'); - wrapper.url('#some-hash'); - - expect(wrapper.hash()).toBe('some-hash'); - expect(wrapper.url()).toBe('/path/b?search=a&b=c&d#some-hash'); - expect(wrapper.absUrl()).toBe('http://www.domain.com:9877/path/b?search=a&b=c&d#some-hash'); - }); - - it('should change only search and hash when no path specified', function () { - locationService.push('/path/b'); - wrapper.url('?a=b'); - - expect(wrapper.search()).toEqual({ a: 'b' }); - expect(wrapper.hash()).toBe(''); - expect(wrapper.path()).toBe('/path/b'); - }); - - it('should reset search and hash when only path specified', function () { - locationService.push('/path/b?search=a&b=c&d#hash'); - wrapper.url('/new/path'); - - expect(wrapper.path()).toBe('/new/path'); - expect(wrapper.search()).toEqual({}); - expect(wrapper.hash()).toBe(''); - }); - - it('should change path when empty string specified', function () { - locationService.push('/path/b?search=a&b=c&d#hash'); - wrapper.url(''); - - expect(wrapper.path()).toBe('/'); - expect(wrapper.search()).toEqual({}); - expect(wrapper.hash()).toBe(''); - }); - }); -}); diff --git a/public/app/angular/AngularLocationWrapper.ts b/public/app/angular/AngularLocationWrapper.ts deleted file mode 100644 index 05e82e2e245..00000000000 --- a/public/app/angular/AngularLocationWrapper.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { deprecationWarning, urlUtil } from '@grafana/data'; -import { locationSearchToObject, locationService, navigationLogger } from '@grafana/runtime'; - -// Ref: https://github.com/angular/angular.js/blob/ae8e903edf88a83fedd116ae02c0628bf72b150c/src/ng/location.js#L5 -const DEFAULT_PORTS: Record = { http: 80, https: 443, ftp: 21 }; - -export class AngularLocationWrapper { - constructor() { - this.absUrl = this.wrapInDeprecationWarning(this.absUrl); - this.hash = this.wrapInDeprecationWarning(this.hash); - this.host = this.wrapInDeprecationWarning(this.host); - this.path = this.wrapInDeprecationWarning(this.path); - this.port = this.wrapInDeprecationWarning(this.port, 'window.location'); - this.protocol = this.wrapInDeprecationWarning(this.protocol, 'window.location'); - this.replace = this.wrapInDeprecationWarning(this.replace); - this.search = this.wrapInDeprecationWarning(this.search); - this.state = this.wrapInDeprecationWarning(this.state); - this.url = this.wrapInDeprecationWarning(this.url); - } - - wrapInDeprecationWarning(fn: Function, replacement?: string) { - let self = this; - - return function wrapper() { - deprecationWarning('$location', fn.name, replacement || 'locationService'); - return fn.apply(self, arguments); - }; - } - - absUrl(): string { - return `${window.location.origin}${this.url()}`; - } - - hash(newHash?: string | null) { - navigationLogger('AngularLocationWrapper', false, 'Angular compat layer: hash'); - - if (!newHash) { - return locationService.getLocation().hash.slice(1); - } else { - throw new Error('AngularLocationWrapper method not implemented.'); - } - } - - host(): string { - return new URL(window.location.href).hostname; - } - - path(pathname?: any) { - navigationLogger('AngularLocationWrapper', false, 'Angular compat layer: path'); - - const location = locationService.getLocation(); - - if (pathname !== undefined && pathname !== null) { - let parsedPath = String(pathname); - parsedPath = parsedPath.startsWith('/') ? parsedPath : `/${parsedPath}`; - const url = new URL(`${window.location.origin}${parsedPath}`); - - locationService.push({ - pathname: url.pathname, - search: url.search.length > 0 ? url.search : location.search, - hash: url.hash.length > 0 ? url.hash : location.hash, - }); - return this; - } - - if (pathname === null) { - locationService.push('/'); - return this; - } - - return location.pathname; - } - - port(): number | null { - const url = new URL(window.location.href); - return parseInt(url.port, 10) || DEFAULT_PORTS[url.protocol] || null; - } - - protocol(): string { - return new URL(window.location.href).protocol.slice(0, -1); - } - - replace() { - throw new Error('AngularLocationWrapper method not implemented.'); - } - - search(search?: any, paramValue?: any) { - navigationLogger('AngularLocationWrapper', false, 'Angular compat layer: search'); - if (!search) { - return locationService.getSearchObject(); - } - - if (search && arguments.length > 1) { - locationService.partial({ - [search]: paramValue, - }); - - return this; - } - - if (search) { - let newQuery; - - if (typeof search === 'object') { - newQuery = { ...search }; - } else { - newQuery = locationSearchToObject(search); - } - - for (const key in newQuery) { - // removing params with null | undefined - if (newQuery[key] === null || newQuery[key] === undefined) { - delete newQuery[key]; - } - } - - const updatedUrl = urlUtil.renderUrl(locationService.getLocation().pathname, newQuery); - locationService.push(updatedUrl); - } - - return this; - } - - state(state?: any) { - navigationLogger('AngularLocationWrapper', false, 'Angular compat layer: state'); - throw new Error('AngularLocationWrapper method not implemented.'); - } - - url(newUrl?: any) { - navigationLogger('AngularLocationWrapper', false, 'Angular compat layer: url'); - - if (newUrl !== undefined) { - if (newUrl.startsWith('#')) { - locationService.push({ ...locationService.getLocation(), hash: newUrl }); - } else if (newUrl.startsWith('?')) { - locationService.push({ ...locationService.getLocation(), search: newUrl }); - } else if (newUrl.trim().length === 0) { - locationService.push('/'); - } else { - locationService.push(newUrl); - } - - return locationService; - } - - const location = locationService.getLocation(); - return `${location.pathname}${location.search}${location.hash}`; - } -} diff --git a/public/app/angular/AngularRoot.tsx b/public/app/angular/AngularRoot.tsx deleted file mode 100644 index d780685c97c..00000000000 --- a/public/app/angular/AngularRoot.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { forwardRef } from 'react'; - -export const AngularRoot = forwardRef((props, ref) => { - return ( -
', - }} - /> - ); -}); - -AngularRoot.displayName = 'AngularRoot'; diff --git a/public/app/angular/GrafanaCtrl.ts b/public/app/angular/GrafanaCtrl.ts deleted file mode 100644 index cb6a144c224..00000000000 --- a/public/app/angular/GrafanaCtrl.ts +++ /dev/null @@ -1,158 +0,0 @@ -import { IRootScopeService, IAngularEvent, auto } from 'angular'; -import $ from 'jquery'; -import _ from 'lodash'; // eslint-disable-line lodash/import-scope - -import { AppEvent } from '@grafana/data'; -import { setLegacyAngularInjector, setAngularLoader } from '@grafana/runtime'; -import { colors } from '@grafana/ui'; -import coreModule from 'app/angular/core_module'; -import { AngularLoader } from 'app/angular/services/AngularLoader'; -import appEvents from 'app/core/app_events'; -import config from 'app/core/config'; -import { ContextSrv } from 'app/core/services/context_srv'; -import { AppEventEmitter, AppEventConsumer } from 'app/types'; - -import { UtilSrv } from './services/UtilSrv'; - -export type GrafanaRootScope = IRootScopeService & AppEventEmitter & AppEventConsumer & { colors: string[] }; - -export class GrafanaCtrl { - static $inject = ['$scope', 'utilSrv', '$rootScope', 'contextSrv', 'angularLoader', '$injector']; - - constructor( - $scope: any, - utilSrv: UtilSrv, - $rootScope: GrafanaRootScope, - contextSrv: ContextSrv, - angularLoader: AngularLoader, - $injector: auto.IInjectorService - ) { - // make angular loader service available to react components - setAngularLoader(angularLoader); - setLegacyAngularInjector($injector); - - $scope.init = () => { - $scope.contextSrv = contextSrv; - $scope.appSubUrl = config.appSubUrl; - $scope._ = _; - utilSrv.init(); - }; - - $rootScope.colors = colors; - - $rootScope.onAppEvent = function ( - event: AppEvent | string, - callback: (event: IAngularEvent, ...args: any[]) => void, - localScope?: any - ) { - let unbind; - if (typeof event === 'string') { - unbind = $rootScope.$on(event, callback); - } else { - unbind = $rootScope.$on(event.name, callback); - } - - let callerScope = this; - if (callerScope.$id === 1 && !localScope) { - console.warn('warning rootScope onAppEvent called without localscope'); - } - if (localScope) { - callerScope = localScope; - } - callerScope.$on('$destroy', unbind); - }; - - $rootScope.appEvent = (event: AppEvent | string, payload?: T | any) => { - if (typeof event === 'string') { - $rootScope.$emit(event, payload); - appEvents.emit(event, payload); - } else { - $rootScope.$emit(event.name, payload); - appEvents.emit(event, payload); - } - }; - - $scope.init(); - } -} - -export function grafanaAppDirective() { - return { - restrict: 'E', - controller: GrafanaCtrl, - link: (scope: IRootScopeService & AppEventEmitter, elem: JQuery) => { - const body = $('body'); - // see https://github.com/zenorocha/clipboard.js/issues/155 - $.fn.modal.Constructor.prototype.enforceFocus = () => {}; - - // handle in active view state class - let lastActivity = new Date().getTime(); - let activeUser = true; - const inActiveTimeLimit = 60 * 5000; - - function checkForInActiveUser() { - if (!activeUser) { - return; - } - // only go to activity low mode on dashboard page - if (!body.hasClass('page-dashboard')) { - return; - } - - if (new Date().getTime() - lastActivity > inActiveTimeLimit) { - activeUser = false; - body.addClass('view-mode--inactive'); - } - } - - function userActivityDetected() { - lastActivity = new Date().getTime(); - if (!activeUser) { - activeUser = true; - body.removeClass('view-mode--inactive'); - } - } - - // mouse and keyboard is user activity - body.mousemove(userActivityDetected); - body.keydown(userActivityDetected); - // set useCapture = true to catch event here - document.addEventListener('wheel', userActivityDetected, { capture: true, passive: true }); - // treat tab change as activity - document.addEventListener('visibilitychange', userActivityDetected); - - // check every 2 seconds - setInterval(checkForInActiveUser, 2000); - - // handle document clicks that should hide things - body.click((evt) => { - const target = $(evt.target); - if (target.parents().length === 0) { - return; - } - - // ensure dropdown menu doesn't impact on z-index - body.find('.dropdown-menu-open').removeClass('dropdown-menu-open'); - - // for stuff that animates, slides out etc, clicking it needs to - // hide it right away - const clickAutoHide = target.closest('[data-click-hide]'); - if (clickAutoHide.length) { - const clickAutoHideParent = clickAutoHide.parent(); - clickAutoHide.detach(); - setTimeout(() => { - clickAutoHideParent.append(clickAutoHide); - }, 100); - } - - // hide popovers - const popover = elem.find('.popover'); - if (popover.length > 0 && target.parents('.graph-legend').length === 0) { - popover.hide(); - } - }); - }, - }; -} - -coreModule.directive('grafanaApp', grafanaAppDirective); diff --git a/public/app/angular/angular_wrappers.ts b/public/app/angular/angular_wrappers.ts deleted file mode 100644 index 57d2508b69b..00000000000 --- a/public/app/angular/angular_wrappers.ts +++ /dev/null @@ -1,153 +0,0 @@ -import { - ClipboardButton, - ColorPicker, - DataLinksInlineEditor, - DataSourceHttpSettings, - GraphContextMenu, - Icon, - LegacyForms, - SeriesColorPickerPopoverWithTheme, - Spinner, - UnitPicker, -} from '@grafana/ui'; -import { react2AngularDirective } from 'app/angular/react2angular'; -import { OldFolderPicker } from 'app/core/components/Select/OldFolderPicker'; -import { TimePickerSettings } from 'app/features/dashboard/components/DashboardSettings/TimePickerSettings'; -import { QueryEditor as CloudMonitoringQueryEditor } from 'app/plugins/datasource/cloud-monitoring/components/QueryEditor'; - -import EmptyListCTA from '../core/components/EmptyListCTA/EmptyListCTA'; -import { Footer } from '../core/components/Footer/Footer'; -import { MetricSelect } from '../core/components/Select/MetricSelect'; -import { TagFilter } from '../core/components/TagFilter/TagFilter'; -import { HelpModal } from '../core/components/help/HelpModal'; - -import { PageHeader } from './components/PageHeader/PageHeader'; - -const { SecretFormField } = LegacyForms; - -export function registerAngularDirectives() { - react2AngularDirective('footer', Footer, []); - react2AngularDirective('icon', Icon, [ - 'name', - 'size', - 'type', - ['onClick', { watchDepth: 'reference', wrapApply: true }], - ]); - react2AngularDirective('spinner', Spinner, ['inline']); - react2AngularDirective('helpModal', HelpModal, []); - react2AngularDirective('pageHeader', PageHeader, ['model', 'noTabs']); - react2AngularDirective('emptyListCta', EmptyListCTA, [ - 'title', - 'buttonIcon', - 'buttonLink', - 'buttonTitle', - ['onClick', { watchDepth: 'reference', wrapApply: true }], - 'proTip', - 'proTipLink', - 'proTipLinkTitle', - 'proTipTarget', - 'infoBox', - 'infoBoxTitle', - ]); - react2AngularDirective('tagFilter', TagFilter, [ - 'tags', - ['onChange', { watchDepth: 'reference' }], - ['tagOptions', { watchDepth: 'reference' }], - ]); - react2AngularDirective('colorPicker', ColorPicker, [ - 'color', - ['onChange', { watchDepth: 'reference', wrapApply: true }], - ]); - react2AngularDirective('seriesColorPickerPopover', SeriesColorPickerPopoverWithTheme, [ - 'color', - 'series', - 'onColorChange', - 'onToggleAxis', - ]); - react2AngularDirective('unitPicker', UnitPicker, [ - 'value', - 'width', - ['onChange', { watchDepth: 'reference', wrapApply: true }], - ]); - react2AngularDirective('metricSelect', MetricSelect, [ - 'options', - 'onChange', - 'value', - 'isSearchable', - 'className', - 'placeholder', - ['variables', { watchDepth: 'reference' }], - ]); - react2AngularDirective('cloudMonitoringQueryEditor', CloudMonitoringQueryEditor, [ - 'target', - 'onQueryChange', - 'onExecuteQuery', - ['events', { watchDepth: 'reference' }], - ['datasource', { watchDepth: 'reference' }], - ['templateSrv', { watchDepth: 'reference' }], - ]); - react2AngularDirective('secretFormField', SecretFormField, [ - 'value', - 'isConfigured', - 'inputWidth', - 'labelWidth', - 'aria-label', - ['onReset', { watchDepth: 'reference', wrapApply: true }], - ['onChange', { watchDepth: 'reference', wrapApply: true }], - ]); - react2AngularDirective('graphContextMenu', GraphContextMenu, [ - 'x', - 'y', - 'itemsGroup', - ['onClose', { watchDepth: 'reference', wrapApply: true }], - ['getContextMenuSource', { watchDepth: 'reference', wrapApply: true }], - ['timeZone', { watchDepth: 'reference', wrapApply: true }], - ]); - - // We keep the drilldown terminology here because of as using data-* directive - // being in conflict with HTML data attributes - react2AngularDirective('drilldownLinksEditor', DataLinksInlineEditor, [ - 'value', - 'links', - 'suggestions', - ['onChange', { watchDepth: 'reference', wrapApply: true }], - ]); - - react2AngularDirective('datasourceHttpSettingsNext', DataSourceHttpSettings, [ - 'defaultUrl', - 'showAccessOptions', - 'dataSourceConfig', - 'showForwardOAuthIdentityOption', - ['onChange', { watchDepth: 'reference', wrapApply: true }], - ]); - react2AngularDirective('folderPicker', OldFolderPicker, [ - 'labelClass', - 'rootName', - 'enableCreateNew', - 'enableReset', - 'initialTitle', - 'initialFolderId', - 'dashboardId', - 'onCreateFolder', - ['enterFolderCreation', { watchDepth: 'reference', wrapApply: true }], - ['exitFolderCreation', { watchDepth: 'reference', wrapApply: true }], - ['onLoad', { watchDepth: 'reference', wrapApply: true }], - ['onChange', { watchDepth: 'reference', wrapApply: true }], - ]); - - react2AngularDirective('timePickerSettings', TimePickerSettings, [ - 'renderCount', - 'refreshIntervals', - 'timePickerHidden', - 'nowDelay', - 'timezone', - ['onTimeZoneChange', { watchDepth: 'reference', wrapApply: true }], - ['onRefreshIntervalChange', { watchDepth: 'reference', wrapApply: true }], - ['onNowDelayChange', { watchDepth: 'reference', wrapApply: true }], - ['onHideTimePickerChange', { watchDepth: 'reference', wrapApply: true }], - ]); - - react2AngularDirective('clipboardButton', ClipboardButton, [ - ['getText', { watchDepth: 'reference', wrapApply: true }], - ]); -} diff --git a/public/app/angular/array_join.ts b/public/app/angular/array_join.ts deleted file mode 100644 index b57e1157b5f..00000000000 --- a/public/app/angular/array_join.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { isArray } from 'lodash'; - -import coreModule from './core_module'; - -export function arrayJoin() { - 'use strict'; - - return { - restrict: 'A', - require: 'ngModel', - link: (scope: any, element: any, attr: any, ngModel: any) => { - function split_array(text: string) { - return (text || '').split(','); - } - - function join_array(text: string) { - if (isArray(text)) { - return ((text || '') as any).join(','); - } else { - return text; - } - } - - ngModel.$parsers.push(split_array); - ngModel.$formatters.push(join_array); - }, - }; -} - -coreModule.directive('arrayJoin', arrayJoin); diff --git a/public/app/angular/autofill_event_fix.ts b/public/app/angular/autofill_event_fix.ts deleted file mode 100644 index ca185cfb863..00000000000 --- a/public/app/angular/autofill_event_fix.ts +++ /dev/null @@ -1,34 +0,0 @@ -import coreModule from './core_module'; - -export function autofillEventFix($compile: any) { - return { - link: ($scope: any, elem: any) => { - const input = elem[0]; - const dispatchChangeEvent = () => { - const event = new Event('change'); - return input.dispatchEvent(event); - }; - const onAnimationStart = ({ animationName }: AnimationEvent) => { - switch (animationName) { - case 'onAutoFillStart': - return dispatchChangeEvent(); - case 'onAutoFillCancel': - return dispatchChangeEvent(); - } - return null; - }; - - // const onChange = (evt: Event) => console.log(evt); - - input.addEventListener('animationstart', onAnimationStart); - // input.addEventListener('change', onChange); - - $scope.$on('$destroy', () => { - input.removeEventListener('animationstart', onAnimationStart); - // input.removeEventListener('change', onChange); - }); - }, - }; -} - -coreModule.directive('autofillEventFix', ['$compile', autofillEventFix]); diff --git a/public/app/angular/bridgeReactAngularRouting.ts b/public/app/angular/bridgeReactAngularRouting.ts deleted file mode 100644 index 1b10ce4da95..00000000000 --- a/public/app/angular/bridgeReactAngularRouting.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { ILocationService } from 'angular'; - -import { RouteParamsProvider } from '../core/navigation/patch/RouteParamsProvider'; -import { RouteProvider } from '../core/navigation/patch/RouteProvider'; - -import { AngularLocationWrapper } from './AngularLocationWrapper'; -import { coreModule } from './core_module'; - -// Neutralizing Angular’s location tampering -// https://stackoverflow.com/a/19825756 -const tamperAngularLocation = () => { - coreModule.config([ - '$provide', - ($provide: any) => { - $provide.decorator('$browser', [ - '$delegate', - ($delegate: any) => { - $delegate.onUrlChange = () => {}; - $delegate.url = () => ''; - - return $delegate; - }, - ]); - }, - ]); -}; - -// Intercepting $location service with implementation based on history -const interceptAngularLocation = () => { - coreModule.config([ - '$provide', - ($provide: any) => { - $provide.decorator('$location', [ - '$delegate', - ($delegate: ILocationService) => { - $delegate = new AngularLocationWrapper() as unknown as ILocationService; - return $delegate; - }, - ]); - }, - ]); - coreModule.provider('$route', RouteProvider); - coreModule.provider('$routeParams', RouteParamsProvider); -}; - -export function initAngularRoutingBridge() { - tamperAngularLocation(); - interceptAngularLocation(); -} diff --git a/public/app/angular/bsTooltip.ts b/public/app/angular/bsTooltip.ts deleted file mode 100644 index 3f2d6302ecc..00000000000 --- a/public/app/angular/bsTooltip.ts +++ /dev/null @@ -1,59 +0,0 @@ -import angular from 'angular'; -import $ from 'jquery'; - -import coreModule from './core_module'; - -coreModule.directive('bsTooltip', [ - '$parse', - '$compile', - function ($parse: any, $compile: any) { - return { - restrict: 'A', - scope: true, - link: function postLink(scope: any, element: any, attrs: any) { - let getter = $parse(attrs.bsTooltip), - value = getter(scope); - scope.$watch(attrs.bsTooltip, function (newValue: any, oldValue: any) { - if (newValue !== oldValue) { - value = newValue; - } - }); - // Grafana change, always hide other tooltips - if (true) { - element.on('show', function (ev: any) { - $('.tooltip.in').each(function () { - const $this = $(this), - tooltip = $this.data('tooltip'); - if (tooltip && !tooltip.$element.is(element)) { - $this.tooltip('hide'); - } - }); - }); - } - element.tooltip({ - title: function () { - return angular.isFunction(value) ? value.apply(null, arguments) : value; - }, - html: true, - container: 'body', // Grafana change - }); - const tooltip = element.data('tooltip'); - tooltip.show = function () { - const r = $.fn.tooltip.Constructor.prototype.show.apply(this, arguments); - this.tip().data('tooltip', this); - return r; - }; - scope._tooltip = function (event: any) { - element.tooltip(event); - }; - scope.hide = function () { - element.tooltip('hide'); - }; - scope.show = function () { - element.tooltip('show'); - }; - scope.dismiss = scope.hide; - }, - }; - }, -]); diff --git a/public/app/angular/bsTypeahead.ts b/public/app/angular/bsTypeahead.ts deleted file mode 100644 index 696a3678b68..00000000000 --- a/public/app/angular/bsTypeahead.ts +++ /dev/null @@ -1,63 +0,0 @@ -import angular from 'angular'; -import $ from 'jquery'; -import { isFunction } from 'lodash'; - -import coreModule from './core_module'; - -coreModule.directive('bsTypeahead', [ - '$parse', - function ($parse: any) { - return { - restrict: 'A', - require: '?ngModel', - link: function postLink(scope: any, element: any, attrs: any, controller: any) { - let getter = $parse(attrs.bsTypeahead), - value = getter(scope); - scope.$watch(attrs.bsTypeahead, function (newValue: any, oldValue: any) { - if (newValue !== oldValue) { - value = newValue; - } - }); - element.attr('data-provide', 'typeahead'); - element.typeahead({ - source: function () { - return angular.isFunction(value) ? value.apply(null, arguments) : value; - }, - minLength: attrs.minLength || 1, - items: attrs.item, - updater: function (value: any) { - if (controller) { - scope.$apply(function () { - controller.$setViewValue(value); - }); - } - scope.$emit('typeahead-updated', value); - return value; - }, - }); - const typeahead = element.data('typeahead'); - typeahead.lookup = function () { - let items; - this.query = this.$element.val() || ''; - if (this.query.length < this.options.minLength) { - return this.shown ? this.hide() : this; - } - items = isFunction(this.source) ? this.source(this.query, $.proxy(this.process, this)) : this.source; - return items ? this.process(items) : this; - }; - if (!!attrs.matchAll) { - typeahead.matcher = function () { - return true; - }; - } - if (attrs.minLength === '0') { - setTimeout(function () { - element.on('focus', function () { - element.val().length === 0 && setTimeout(element.typeahead.bind(element, 'lookup'), 200); - }); - }); - } - }, - }; - }, -]); diff --git a/public/app/angular/components/HttpSettingsCtrl.ts b/public/app/angular/components/HttpSettingsCtrl.ts deleted file mode 100644 index 611dd12be7a..00000000000 --- a/public/app/angular/components/HttpSettingsCtrl.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { coreModule } from 'app/angular/core_module'; - -coreModule.directive('datasourceHttpSettings', () => { - return { - scope: { - current: '=', - suggestUrl: '@', - noDirectAccess: '@', - showForwardOAuthIdentityOption: '@', - }, - templateUrl: 'public/app/angular/partials/http_settings_next.html', - link: { - pre: ($scope: any) => { - // do not show access option if direct access is disabled - $scope.showAccessOption = $scope.noDirectAccess !== 'true'; - $scope.onChange = (datasourceSetting: any) => { - $scope.current = datasourceSetting; - }; - }, - }, - }; -}); diff --git a/public/app/angular/components/PageHeader/PageHeader.test.tsx b/public/app/angular/components/PageHeader/PageHeader.test.tsx deleted file mode 100644 index f6853e73e69..00000000000 --- a/public/app/angular/components/PageHeader/PageHeader.test.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { render, screen } from '@testing-library/react'; - -import { NavModelItem } from '@grafana/data'; - -import { PageHeader } from './PageHeader'; - -describe('PageHeader', () => { - describe('when the nav tree has a node with a title', () => { - it('should render the title', async () => { - const nav: NavModelItem = { - icon: 'folder-open', - id: 'node', - subTitle: 'node subtitle', - url: '', - text: 'node', - }; - - render(); - - expect(screen.getByRole('heading', { name: 'node' })).toBeInTheDocument(); - }); - }); -}); diff --git a/public/app/angular/components/PageHeader/PageHeader.tsx b/public/app/angular/components/PageHeader/PageHeader.tsx deleted file mode 100644 index a56301c3121..00000000000 --- a/public/app/angular/components/PageHeader/PageHeader.tsx +++ /dev/null @@ -1,165 +0,0 @@ -import { css, cx } from '@emotion/css'; -import * as React from 'react'; - -import { NavModelItem, GrafanaTheme2 } from '@grafana/data'; -import { Tab, TabsBar, Icon, useStyles2, toIconName } from '@grafana/ui'; - -import { PageInfoItem } from '../../../core/components/Page/types'; -import { PageInfo } from '../../../core/components/PageInfo/PageInfo'; -import { ProBadge } from '../../../core/components/Upgrade/ProBadge'; - -import { PanelHeaderMenuItem } from './PanelHeaderMenuItem'; - -export interface Props { - navItem: NavModelItem; - renderTitle?: (title: string) => React.ReactNode; - actions?: React.ReactNode; - info?: PageInfoItem[]; - subTitle?: React.ReactNode; -} - -const SelectNav = ({ children, customCss }: { children: NavModelItem[]; customCss: string }) => { - if (!children || children.length === 0) { - return null; - } - - const defaultSelectedItem = children.find((navItem) => { - return navItem.active === true; - }); - - return ( -
-
- -
    - {children.map((navItem: NavModelItem) => { - if (navItem.hideFromTabs) { - // TODO: Rename hideFromTabs => hideFromNav - return null; - } - return ( - - ); - })} -
-
-
- ); -}; - -const Navigation = ({ children }: { children: NavModelItem[] }) => { - if (!children || children.length === 0) { - return null; - } - - return ( - - ); -}; - -export const PageHeader = ({ navItem: model, renderTitle, actions, info, subTitle }: Props) => { - const styles = useStyles2(getStyles); - - if (!model) { - return null; - } - - const renderHeader = (main: NavModelItem) => { - const marginTop = main.icon === 'grafana' ? 12 : 14; - const icon = main.icon && toIconName(main.icon); - const sub = subTitle ?? main.subTitle; - - return ( -
- - {icon && } - {main.img && } - - -
- {renderTitle ? renderTitle(main.text) : renderHeaderTitle(main.text, main.highlightText)} - {info && } - {sub &&
{sub}
} - {actions &&
{actions}
} -
-
- ); - }; - - return ( -
-
-
- {renderHeader(model)} - {model.children && model.children.length > 0 && {model.children}} -
-
-
- ); -}; - -function renderHeaderTitle(title: string, highlightText: NavModelItem['highlightText']) { - if (!title) { - return null; - } - - return ( -

- {title} - {highlightText && ( - - )} -

- ); -} - -const getStyles = (theme: GrafanaTheme2) => ({ - actions: css({ - display: 'flex', - flexDirection: 'row', - gap: theme.spacing(1), - }), - headerText: css({ - display: 'flex', - flexDirection: 'column', - gap: theme.spacing(1), - }), - headerCanvas: css({ - background: theme.colors.background.canvas, - }), -}); diff --git a/public/app/angular/components/PageHeader/PanelHeaderMenuItem.tsx b/public/app/angular/components/PageHeader/PanelHeaderMenuItem.tsx deleted file mode 100644 index de3daf901b4..00000000000 --- a/public/app/angular/components/PageHeader/PanelHeaderMenuItem.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import { css } from '@emotion/css'; -import { useState } from 'react'; -import * as React from 'react'; - -import { PanelMenuItem, GrafanaTheme2 } from '@grafana/data'; -import { selectors } from '@grafana/e2e-selectors'; -import { Icon, toIconName, useStyles2 } from '@grafana/ui'; - -interface Props { - children?: React.ReactNode; -} - -export const PanelHeaderMenuItem = (props: Props & PanelMenuItem) => { - const [ref, setRef] = useState(null); - const isSubMenu = props.type === 'submenu'; - const styles = useStyles2(getStyles); - const icon = props.iconClassName ? toIconName(props.iconClassName) : undefined; - - switch (props.type) { - case 'divider': - return
  • ; - case 'group': - return ( -
  • - {props.text} -
  • - ); - default: - return ( -
  • - - {icon && } - - {props.text} - {isSubMenu && } - - - {props.shortcut && ( - - {props.shortcut} - - )} - - {props.children} -
  • - ); - } -}; - -function getDropdownLocationCssClass(element: HTMLElement | null) { - if (!element) { - return 'invisible'; - } - - const wrapperPos = element.parentElement!.getBoundingClientRect(); - const pos = element.getBoundingClientRect(); - - if (pos.width === 0) { - return 'invisible'; - } - - if (wrapperPos.right + pos.width + 10 > window.innerWidth) { - return 'pull-left'; - } else { - return 'pull-right'; - } -} - -function getStyles(theme: GrafanaTheme2) { - return { - menuIconClassName: css({ - marginRight: theme.spacing(1), - 'a::after': { - display: 'none', - }, - }), - shortcutIconClassName: css({ - position: 'absolute', - top: '7px', - right: theme.spacing(0.5), - color: theme.colors.text.secondary, - }), - groupLabel: css({ - color: theme.colors.text.secondary, - fontSize: theme.typography.size.sm, - padding: theme.spacing(0.5, 1), - }), - }; -} diff --git a/public/app/angular/components/TlsAuthSettingsCtrl.ts b/public/app/angular/components/TlsAuthSettingsCtrl.ts deleted file mode 100644 index a6e85aa1baf..00000000000 --- a/public/app/angular/components/TlsAuthSettingsCtrl.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { coreModule } from 'app/angular/core_module'; - -coreModule.directive('datasourceTlsAuthSettings', () => { - return { - scope: { - current: '=', - }, - templateUrl: 'public/app/angular/partials/tls_auth_settings.html', - }; -}); diff --git a/public/app/angular/components/code_editor/brace.d.ts b/public/app/angular/components/code_editor/brace.d.ts deleted file mode 100644 index 65d694e914e..00000000000 --- a/public/app/angular/components/code_editor/brace.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module 'brace/*' { - let brace: any; - export default brace; -} diff --git a/public/app/angular/components/code_editor/code_editor.ts b/public/app/angular/components/code_editor/code_editor.ts deleted file mode 100644 index 64723b24b64..00000000000 --- a/public/app/angular/components/code_editor/code_editor.ts +++ /dev/null @@ -1,200 +0,0 @@ -/** - * codeEditor directive based on Ace code editor - * https://github.com/ajaxorg/ace - * - * Basic usage: - * - * - * - * Params: - * content: Editor content. - * onChange: Function called on content change (invoked on editor blur, ctrl+enter, not on every change). - * getCompleter: Function returned external completer. Completer is an object implemented getCompletions() method, - * see Prometheus Data Source implementation for details. - * - * Some Ace editor options available via data-* attributes: - * data-mode - Language mode (text, sql, javascript, etc.). Default is 'text'. - * data-theme - Editor theme (eg 'solarized_dark'). - * data-max-lines - Max editor height in lines. Editor grows automatically from 1 to maxLines. - * data-show-gutter - Show gutter (contains line numbers and additional info). - * data-tab-size - Tab size, default is 2. - * data-behaviours-enabled - Specifies whether to use behaviors or not. "Behaviors" in this case is the auto-pairing of - * special characters, like quotation marks, parenthesis, or brackets. - * data-snippets-enabled - Specifies whether to use snippets or not. "Snippets" are small pieces of code that can be - * inserted via the completion box. - * - * Keybindings: - * Ctrl-Enter (Command-Enter): run onChange() function - */ - -import coreModule from 'app/angular/core_module'; -import config from 'app/core/config'; - -const DEFAULT_THEME_DARK = 'ace/theme/grafana-dark'; -const DEFAULT_THEME_LIGHT = 'ace/theme/textmate'; -const DEFAULT_MODE = 'text'; -const DEFAULT_MAX_LINES = 10; -const DEFAULT_TAB_SIZE = 2; -const DEFAULT_BEHAVIORS = true; -const DEFAULT_SNIPPETS = true; - -const editorTemplate = `
    `; - -async function link(scope: any, elem: any, attrs: any) { - // Options - const langMode = attrs.mode || DEFAULT_MODE; - const maxLines = attrs.maxLines || DEFAULT_MAX_LINES; - const showGutter = attrs.showGutter !== undefined; - const tabSize = attrs.tabSize || DEFAULT_TAB_SIZE; - const behavioursEnabled = attrs.behavioursEnabled ? attrs.behavioursEnabled === 'true' : DEFAULT_BEHAVIORS; - const snippetsEnabled = attrs.snippetsEnabled ? attrs.snippetsEnabled === 'true' : DEFAULT_SNIPPETS; - - // Initialize editor - const aceElem = elem.get(0); - const { default: ace } = await import(/* webpackChunkName: "brace" */ 'brace'); - await import('brace/ext/language_tools'); - await import('brace/theme/textmate'); - await import('brace/mode/text'); - await import('brace/snippets/text'); - await import('brace/mode/sql'); - await import('brace/snippets/sql'); - await import('brace/mode/sqlserver'); - await import('brace/snippets/sqlserver'); - await import('brace/mode/markdown'); - await import('brace/snippets/markdown'); - await import('brace/mode/json'); - await import('brace/snippets/json'); - - // @ts-ignore - await import('./theme-grafana-dark'); - - const codeEditor = ace.edit(aceElem); - const editorSession = codeEditor.getSession(); - - const editorOptions = { - maxLines: maxLines, - showGutter: showGutter, - tabSize: tabSize, - behavioursEnabled: behavioursEnabled, - highlightActiveLine: false, - showPrintMargin: false, - autoScrollEditorIntoView: true, // this is needed if editor is inside scrollable page - }; - - // Set options - codeEditor.setOptions(editorOptions); - // disable depreacation warning - codeEditor.$blockScrolling = Infinity; - // Padding hacks - (codeEditor.renderer as any).setScrollMargin(10, 10); - codeEditor.renderer.setPadding(10); - - setThemeMode(); - setLangMode(langMode); - setEditorContent(scope.content); - - // Add classes - elem.addClass('gf-code-editor'); - const textarea = elem.find('textarea'); - textarea.addClass('gf-form-input'); - - // All aria-label to be set for accessibility - textarea.attr('aria-label', attrs.textareaLabel); - - if (scope.codeEditorFocus) { - setTimeout(() => { - textarea.focus(); - const domEl = textarea[0]; - if (domEl.setSelectionRange) { - const pos = textarea.val().length * 2; - domEl.setSelectionRange(pos, pos); - } - }, 100); - } - - // Event handlers - editorSession.on('change', (e) => { - scope.$apply(() => { - const newValue = codeEditor.getValue(); - scope.content = newValue; - }); - }); - - // Sync with outer scope - update editor content if model has been changed from outside of directive. - scope.$watch('content', (newValue: any, oldValue: any) => { - const editorValue = codeEditor.getValue(); - if (newValue !== editorValue && newValue !== oldValue) { - scope.$$postDigest(() => { - setEditorContent(newValue); - }); - } - }); - - codeEditor.on('blur', () => { - scope.onChange(); - }); - - scope.$on('$destroy', () => { - codeEditor.destroy(); - }); - - // Keybindings - codeEditor.commands.addCommand({ - name: 'executeQuery', - bindKey: { win: 'Ctrl-Enter', mac: 'Command-Enter' }, - exec: () => { - scope.onChange(); - }, - }); - - function setLangMode(lang: string) { - ace.acequire('ace/ext/language_tools'); - codeEditor.setOptions({ - enableBasicAutocompletion: true, - enableLiveAutocompletion: true, - enableSnippets: snippetsEnabled, - }); - - if (scope.getCompleter()) { - // make copy of array as ace seems to share completers array between instances - const anyEditor = codeEditor as any; - anyEditor.completers = anyEditor.completers.slice(); - anyEditor.completers.push(scope.getCompleter()); - } - - const aceModeName = `ace/mode/${lang}`; - editorSession.setMode(aceModeName); - } - - function setThemeMode() { - let theme = DEFAULT_THEME_DARK; - if (config.bootData.user.lightTheme) { - theme = DEFAULT_THEME_LIGHT; - } - - codeEditor.setTheme(theme); - } - - function setEditorContent(value: string) { - codeEditor.setValue(value); - codeEditor.clearSelection(); - } -} - -export function codeEditorDirective() { - return { - restrict: 'E', - template: editorTemplate, - scope: { - content: '=', - datasource: '=', - codeEditorFocus: '<', - onChange: '&', - getCompleter: '&', - }, - link: link, - }; -} - -coreModule.directive('codeEditor', codeEditorDirective); diff --git a/public/app/angular/components/code_editor/theme-grafana-dark.js b/public/app/angular/components/code_editor/theme-grafana-dark.js deleted file mode 100644 index c1ac75534cc..00000000000 --- a/public/app/angular/components/code_editor/theme-grafana-dark.js +++ /dev/null @@ -1,117 +0,0 @@ -ace.define( - 'ace/theme/grafana-dark', - ['require', 'exports', 'module', 'ace/lib/dom'], - function (acequire, exports, module) { - 'use strict'; - - exports.isDark = true; - exports.cssClass = 'gf-code-dark'; - exports.cssText = - '.gf-code-dark .ace_gutter {\ - background: #2f3129;\ - color: #8f908a\ - }\ - .gf-code-dark .ace_print-margin {\ - width: 1px;\ - background: #555651\ - }\ - .gf-code-dark {\ - background-color: #09090b;\ - color: #e0e0e0\ - }\ - .gf-code-dark .ace_cursor {\ - color: #f8f8f0\ - }\ - .gf-code-dark .ace_marker-layer .ace_selection {\ - background: #49483e\ - }\ - .gf-code-dark.ace_multiselect .ace_selection.ace_start {\ - box-shadow: 0 0 3px 0px #272822;\ - }\ - .gf-code-dark .ace_marker-layer .ace_step {\ - background: rgb(102, 82, 0)\ - }\ - .gf-code-dark .ace_marker-layer .ace_bracket {\ - margin: -1px 0 0 -1px;\ - border: 1px solid #49483e\ - }\ - .gf-code-dark .ace_marker-layer .ace_active-line {\ - background: #202020\ - }\ - .gf-code-dark .ace_gutter-active-line {\ - background-color: #272727\ - }\ - .gf-code-dark .ace_marker-layer .ace_selected-word {\ - border: 1px solid #49483e\ - }\ - .gf-code-dark .ace_invisible {\ - color: #52524d\ - }\ - .gf-code-dark .ace_entity.ace_name.ace_tag,\ - .gf-code-dark .ace_keyword,\ - .gf-code-dark .ace_meta.ace_tag,\ - .gf-code-dark .ace_storage {\ - color: #66d9ef\ - }\ - .gf-code-dark .ace_punctuation,\ - .gf-code-dark .ace_punctuation.ace_tag {\ - color: #fff\ - }\ - .gf-code-dark .ace_constant.ace_character,\ - .gf-code-dark .ace_constant.ace_language,\ - .gf-code-dark .ace_constant.ace_numeric,\ - .gf-code-dark .ace_constant.ace_other {\ - color: #fe85fc\ - }\ - .gf-code-dark .ace_invalid {\ - color: #f8f8f0;\ - background-color: #f92672\ - }\ - .gf-code-dark .ace_invalid.ace_deprecated {\ - color: #f8f8f0;\ - background-color: #ae81ff\ - }\ - .gf-code-dark .ace_support.ace_constant,\ - .gf-code-dark .ace_support.ace_function {\ - color: #59e6e3\ - }\ - .gf-code-dark .ace_fold {\ - background-color: #a6e22e;\ - border-color: #f8f8f2\ - }\ - .gf-code-dark .ace_storage.ace_type,\ - .gf-code-dark .ace_support.ace_class,\ - .gf-code-dark .ace_support.ace_type {\ - font-style: italic;\ - color: #66d9ef\ - }\ - .gf-code-dark .ace_entity.ace_name.ace_function,\ - .gf-code-dark .ace_entity.ace_other,\ - .gf-code-dark .ace_entity.ace_other.ace_attribute-name,\ - .gf-code-dark .ace_variable {\ - color: #a6e22e\ - }\ - .gf-code-dark .ace_variable.ace_parameter {\ - font-style: italic;\ - color: #fd971f\ - }\ - .gf-code-dark .ace_string {\ - color: #74e680\ - }\ - .gf-code-dark .ace_paren {\ - color: #f0a842\ - }\ - .gf-code-dark .ace_operator {\ - color: #FFF\ - }\ - .gf-code-dark .ace_comment {\ - color: #75715e\ - }\ - .gf-code-dark .ace_indent-guide {\ - background: url(data:image/png;base64,ivborw0kggoaaaansuheugaaaaeaaaaccayaaaczgbynaaaaekleqvqimwpq0fd0zxbzd/wpaajvaoxesgneaaaaaelftksuqmcc) right repeat-y\ - }'; - - const dom = acequire('../lib/dom'); - dom.importCssString(exports.cssText, exports.cssClass); - } -); diff --git a/public/app/angular/components/form_dropdown/form_dropdown.ts b/public/app/angular/components/form_dropdown/form_dropdown.ts deleted file mode 100644 index dc3716615bd..00000000000 --- a/public/app/angular/components/form_dropdown/form_dropdown.ts +++ /dev/null @@ -1,286 +0,0 @@ -import { ISCEService } from 'angular'; -import { debounce, find, indexOf, map, isObject, escape, unescape } from 'lodash'; - -import coreModule from '../../core_module'; -import { promiseToDigest } from '../../promiseToDigest'; - -function typeaheadMatcher(this: any, item: string) { - let str = this.query; - if (str === '') { - return true; - } - if (str[0] === '/') { - str = str.substring(1); - } - if (str[str.length - 1] === '/') { - str = str.substring(0, str.length - 1); - } - return item.toLowerCase().match(str.toLowerCase()); -} - -export class FormDropdownCtrl { - inputElement: JQLite; - linkElement: JQLite; - model: any; - display: any; - text: any; - options: any; - cssClass: any; - cssClasses: any; - allowCustom: any; - labelMode: boolean; - linkMode: boolean; - cancelBlur: any; - onChange: any; - getOptions: any; - optionCache: any; - lookupText: boolean; - placeholder: any; - startOpen: any; - debounce: boolean; - - static $inject = ['$scope', '$element', '$sce', 'templateSrv']; - - constructor( - private $scope: any, - $element: JQLite, - private $sce: ISCEService, - private templateSrv: any - ) { - this.inputElement = $element.find('input').first(); - this.linkElement = $element.find('a').first(); - this.linkMode = true; - this.cancelBlur = null; - this.labelMode = false; - this.lookupText = false; - this.debounce = false; - - // listen to model changes - $scope.$watch('ctrl.model', this.modelChanged.bind(this)); - } - - $onInit() { - if (this.labelMode) { - this.cssClasses = 'gf-form-label ' + this.cssClass; - } else { - this.cssClasses = 'gf-form-input gf-form-input--dropdown ' + this.cssClass; - } - - if (this.placeholder) { - this.inputElement.attr('placeholder', this.placeholder); - } - - this.inputElement.attr('data-provide', 'typeahead'); - this.inputElement.typeahead({ - source: this.typeaheadSource.bind(this), - minLength: 0, - items: 10000, - updater: this.typeaheadUpdater.bind(this), - matcher: typeaheadMatcher, - }); - - // modify typeahead lookup - // this = typeahead - const typeahead = this.inputElement.data('typeahead'); - typeahead.lookup = function () { - this.query = this.$element.val() || ''; - this.source(this.query, this.process.bind(this)); - }; - - if (this.debounce) { - typeahead.lookup = debounce(typeahead.lookup, 500, { leading: true }); - } - - this.linkElement.keydown((evt) => { - // trigger typeahead on down arrow or enter key - if (evt.keyCode === 40 || evt.keyCode === 13) { - this.linkElement.click(); - } - }); - - this.inputElement.keydown((evt) => { - if (evt.keyCode === 13) { - setTimeout(() => { - this.inputElement.blur(); - }, 300); - } - }); - - this.inputElement.blur(this.inputBlur.bind(this)); - - if (this.startOpen) { - setTimeout(this.open.bind(this), 0); - } - } - - getOptionsInternal(query: string) { - return promiseToDigest(this.$scope)(Promise.resolve(this.getOptions({ $query: query }))); - } - - isPromiseLike(obj: any) { - return obj && typeof obj.then === 'function'; - } - - modelChanged() { - if (isObject(this.model)) { - this.updateDisplay((this.model as any).text); - } else { - // if we have text use it - if (this.lookupText) { - this.getOptionsInternal('').then((options: any) => { - const item: any = find(options, { value: this.model }); - this.updateDisplay(item ? item.text : this.model); - }); - } else { - this.updateDisplay(this.model); - } - } - } - - typeaheadSource(query: string, callback: (res: any) => void) { - this.getOptionsInternal(query).then((options: any) => { - this.optionCache = options; - - // extract texts - const optionTexts = map(options, (op: any) => { - return escape(op.text); - }); - - // add custom values - if (this.allowCustom && this.text !== '') { - if (indexOf(optionTexts, this.text) === -1) { - optionTexts.unshift(this.text); - } - } - - callback(optionTexts); - }); - } - - typeaheadUpdater(text: string) { - if (text === this.text) { - clearTimeout(this.cancelBlur); - this.inputElement.focus(); - return text; - } - - this.inputElement.val(text); - this.switchToLink(true); - return text; - } - - switchToLink(fromClick: boolean) { - if (this.linkMode && !fromClick) { - return; - } - - clearTimeout(this.cancelBlur); - this.cancelBlur = null; - this.linkMode = true; - this.inputElement.hide(); - this.linkElement.show(); - this.updateValue(this.inputElement.val() as string); - } - - inputBlur() { - // happens long before the click event on the typeahead options - // need to have long delay because the blur - this.cancelBlur = setTimeout(this.switchToLink.bind(this), 200); - } - - updateValue(text: string) { - text = unescape(text); - - if (text === '' || this.text === text) { - return; - } - - this.$scope.$apply(() => { - const option: any = find(this.optionCache, { text: text }); - - if (option) { - if (isObject(this.model)) { - this.model = option; - } else { - this.model = option.value; - } - this.text = option.text; - } else if (this.allowCustom) { - if (isObject(this.model)) { - (this.model as any).text = (this.model as any).value = text; - } else { - this.model = text; - } - this.text = text; - } - - // needs to call this after digest so - // property is synced with outerscope - this.$scope.$$postDigest(() => { - this.$scope.$apply(() => { - this.onChange({ $option: option }); - }); - }); - }); - } - - updateDisplay(text: string) { - this.text = text; - this.display = this.$sce.trustAsHtml(this.templateSrv.highlightVariablesAsHtml(text)); - } - - open() { - this.inputElement.css('width', Math.max(this.linkElement.width()!, 80) + 16 + 'px'); - - this.inputElement.show(); - this.inputElement.focus(); - - this.linkElement.hide(); - this.linkMode = false; - - const typeahead = this.inputElement.data('typeahead'); - if (typeahead) { - this.inputElement.val(''); - typeahead.lookup(); - } - } -} - -const template = ` - - - - -`; - -export function formDropdownDirective() { - return { - restrict: 'E', - template: template, - controller: FormDropdownCtrl, - bindToController: true, - controllerAs: 'ctrl', - scope: { - model: '=', - getOptions: '&', - onChange: '&', - cssClass: '@', - allowCustom: '@', - labelMode: '@', - lookupText: '@', - placeholder: '@', - startOpen: '@', - debounce: '@', - }, - }; -} - -coreModule.directive('gfFormDropdown', formDropdownDirective); diff --git a/public/app/angular/components/info_popover.ts b/public/app/angular/components/info_popover.ts deleted file mode 100644 index 41417f5a680..00000000000 --- a/public/app/angular/components/info_popover.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { each } from 'lodash'; -// @ts-ignore -import Drop from 'tether-drop'; - -import coreModule from 'app/angular/core_module'; - -export function infoPopover() { - return { - restrict: 'E', - template: ``, - transclude: true, - link: (scope: any, elem: any, attrs: any, ctrl: any, transclude: any) => { - const offset = attrs.offset || '0 -10px'; - const position = attrs.position || 'right middle'; - let classes = 'drop-help drop-hide-out-of-bounds'; - const openOn = 'hover'; - - elem.addClass('gf-form-help-icon'); - - if (attrs.wide) { - classes += ' drop-wide'; - } - - if (attrs.mode) { - elem.addClass('gf-form-help-icon--' + attrs.mode); - } - - transclude((clone: any, newScope: any) => { - const content = document.createElement('div'); - content.className = 'markdown-html'; - - each(clone, (node) => { - content.appendChild(node); - }); - - const dropOptions = { - target: elem[0], - content: content, - position: position, - classes: classes, - openOn: openOn, - hoverOpenDelay: 400, - tetherOptions: { - offset: offset, - constraints: [ - { - to: 'window', - attachment: 'together', - pin: true, - }, - ], - }, - }; - - // Create drop in next digest after directive content is rendered. - scope.$applyAsync(() => { - const drop = new Drop(dropOptions); - - const unbind = scope.$on('$destroy', () => { - drop.destroy(); - unbind(); - }); - }); - }); - }, - }; -} - -coreModule.directive('infoPopover', infoPopover); diff --git a/public/app/angular/components/jsontree.ts b/public/app/angular/components/jsontree.ts deleted file mode 100644 index 4721ffcccaa..00000000000 --- a/public/app/angular/components/jsontree.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { JsonExplorer } from '@grafana/ui'; -import coreModule from 'app/angular/core_module'; - -coreModule.directive('jsonTree', [ - function jsonTreeDirective() { - return { - restrict: 'E', - scope: { - object: '=', - startExpanded: '@', - rootName: '@', - }, - link: (scope: any, elem) => { - let expansionLevel = scope.startExpanded; - if (scope.startExpanded === 'true') { - expansionLevel = 2; - } else if (scope.startExpanded === 'false') { - expansionLevel = 1; - } - const jsonObject = { [scope.rootName]: scope.object }; - const jsonExp = new JsonExplorer(jsonObject, expansionLevel, { - animateOpen: true, - }); - const html = jsonExp.render(true); - elem.append(html); - }, - }; - }, -]); diff --git a/public/app/angular/components/plugin_component.ts b/public/app/angular/components/plugin_component.ts deleted file mode 100644 index 3eccc7e0d18..00000000000 --- a/public/app/angular/components/plugin_component.ts +++ /dev/null @@ -1,249 +0,0 @@ -import angular, { ILocationService } from 'angular'; -import { each } from 'lodash'; - -import { DataSourceApi, PanelEvents } from '@grafana/data'; -import coreModule from 'app/angular/core_module'; -import config from 'app/core/config'; - -import { importPanelPlugin } from '../../features/plugins/importPanelPlugin'; -import { importDataSourcePlugin, importAppPlugin } from '../../features/plugins/plugin_loader'; - -coreModule.directive('pluginComponent', ['$compile', '$http', '$templateCache', '$location', pluginDirectiveLoader]); - -function pluginDirectiveLoader($compile: any, $http: any, $templateCache: any, $location: ILocationService) { - function getTemplate(component: { template: any; templateUrl: any }) { - if (component.template) { - return Promise.resolve(component.template); - } - const cached = $templateCache.get(component.templateUrl); - if (cached) { - return Promise.resolve(cached); - } - return $http.get(component.templateUrl).then((res: any) => { - return res.data; - }); - } - - function relativeTemplateUrlToAbs(templateUrl: string, baseUrl: string) { - if (!templateUrl) { - return undefined; - } - if (templateUrl.indexOf('public') === 0) { - return templateUrl; - } - - return baseUrl + '/' + templateUrl; - } - - function getPluginComponentDirective(options: any) { - // handle relative template urls for plugin templates - options.Component.templateUrl = relativeTemplateUrlToAbs(options.Component.templateUrl, options.baseUrl); - - return () => { - return { - templateUrl: options.Component.templateUrl, - template: options.Component.template, - restrict: 'E', - controller: options.Component, - controllerAs: 'ctrl', - bindToController: true, - scope: options.bindings, - link: (scope: any, elem: any, attrs: any, ctrl: any) => { - if (ctrl.link) { - ctrl.link(scope, elem, attrs, ctrl); - } - if (ctrl.init) { - ctrl.init(); - } - }, - }; - }; - } - - function loadPanelComponentInfo(scope: any, attrs: any) { - const componentInfo: any = { - name: 'panel-plugin-' + scope.panel.type, - bindings: { dashboard: '=', panel: '=', row: '=' }, - attrs: { - dashboard: 'dashboard', - panel: 'panel', - class: 'panel-height-helper', - }, - }; - - const panelInfo = config.panels[scope.panel.type]; - return importPanelPlugin(panelInfo.id).then((panelPlugin) => { - const PanelCtrl = panelPlugin.angularPanelCtrl; - componentInfo.Component = PanelCtrl; - - if (!PanelCtrl || PanelCtrl.registered) { - return componentInfo; - } - - if (PanelCtrl.templatePromise) { - return PanelCtrl.templatePromise.then((res: any) => { - return componentInfo; - }); - } - - if (panelInfo) { - PanelCtrl.templateUrl = relativeTemplateUrlToAbs(PanelCtrl.templateUrl, panelInfo.baseUrl); - } - - PanelCtrl.templatePromise = getTemplate(PanelCtrl).then((template: any) => { - PanelCtrl.templateUrl = null; - PanelCtrl.template = `${template}`; - return { ...componentInfo, baseUrl: panelInfo.baseUrl }; - }); - - return PanelCtrl.templatePromise; - }); - } - - function getModule(scope: any, attrs: any): any { - switch (attrs.type) { - // QueryCtrl - case 'query-ctrl': { - const ds: DataSourceApi = scope.ctrl.datasource as DataSourceApi; - - return Promise.resolve({ - baseUrl: ds.meta.baseUrl, - name: 'query-ctrl-' + ds.meta.id, - bindings: { target: '=', panelCtrl: '=', datasource: '=' }, - attrs: { - target: 'ctrl.target', - 'panel-ctrl': 'ctrl', - datasource: 'ctrl.datasource', - }, - Component: ds.components!.QueryCtrl, - }); - } - // Annotations - case 'annotations-query-ctrl': { - const baseUrl = scope.ctrl.currentDatasource.meta.baseUrl; - const pluginId = scope.ctrl.currentDatasource.meta.id; - - return importDataSourcePlugin(scope.ctrl.currentDatasource.meta).then((dsPlugin) => { - return { - baseUrl, - name: 'annotations-query-ctrl-' + pluginId, - bindings: { annotation: '=', datasource: '=' }, - attrs: { - annotation: 'ctrl.currentAnnotation', - datasource: 'ctrl.currentDatasource', - }, - Component: dsPlugin.components.AnnotationsQueryCtrl, - }; - }); - } - // Datasource ConfigCtrl - case 'datasource-config-ctrl': { - const dsMeta = scope.ctrl.datasourceMeta; - const angularUrl = $location.url(); - return importDataSourcePlugin(dsMeta).then((dsPlugin) => { - scope.$watch( - 'ctrl.current', - () => { - // This watcher can trigger when we navigate away due to late digests - // This check is to stop onModelChanged from being called when navigating away - // as it triggers a redux action which comes before the angular $routeChangeSucces and - // This makes the bridgeSrv think location changed from redux before detecting it was actually - // changed from angular. - if (angularUrl === $location.url()) { - scope.onModelChanged(scope.ctrl.current); - } - }, - true - ); - - return { - baseUrl: dsMeta.baseUrl, - name: 'ds-config-' + dsMeta.id, - bindings: { meta: '=', current: '=' }, - attrs: { meta: 'ctrl.datasourceMeta', current: 'ctrl.current' }, - Component: dsPlugin.angularConfigCtrl, - }; - }); - } - // AppConfigCtrl - case 'app-config-ctrl': { - const model = scope.ctrl.model; - return importAppPlugin(model).then((appPlugin) => { - return { - baseUrl: model.baseUrl, - name: 'app-config-' + model.id, - bindings: { appModel: '=', appEditCtrl: '=' }, - attrs: { 'app-model': 'ctrl.model', 'app-edit-ctrl': 'ctrl' }, - Component: appPlugin.angularConfigCtrl, - }; - }); - } - // Panel - case 'panel': { - return loadPanelComponentInfo(scope, attrs); - } - default: { - return Promise.reject({ - message: 'Could not find component type: ' + attrs.type, - }); - } - } - } - - function appendAndCompile(scope: any, elem: JQuery, componentInfo: any) { - const child = angular.element(document.createElement(componentInfo.name)); - each(componentInfo.attrs, (value, key) => { - child.attr(key, value); - }); - - $compile(child)(scope); - elem.empty(); - - // let a binding digest cycle complete before adding to dom - setTimeout(() => { - scope.$applyAsync(() => { - elem.append(child); - setTimeout(() => { - scope.$applyAsync(() => { - scope.$broadcast(PanelEvents.componentDidMount.name); - }); - }); - }); - }); - } - - function registerPluginComponent(scope: any, elem: JQuery, attrs: any, componentInfo: any) { - if (componentInfo.notFound) { - elem.empty(); - return; - } - - if (!componentInfo.Component) { - throw { - message: 'Failed to find exported plugin component for ' + componentInfo.name, - }; - } - - if (!componentInfo.Component.registered) { - const directiveName = attrs.$normalize(componentInfo.name); - const directiveFn = getPluginComponentDirective(componentInfo); - coreModule.directive(directiveName, directiveFn); - componentInfo.Component.registered = true; - } - - appendAndCompile(scope, elem, componentInfo); - } - - return { - restrict: 'E', - link: (scope: any, elem: JQuery, attrs: any) => { - getModule(scope, attrs) - .then((componentInfo: any) => { - registerPluginComponent(scope, elem, attrs, componentInfo); - }) - .catch((err: any) => { - console.error('Plugin component error', err); - }); - }, - }; -} diff --git a/public/app/angular/components/query_part_editor.ts b/public/app/angular/components/query_part_editor.ts deleted file mode 100644 index 22a0958b69d..00000000000 --- a/public/app/angular/components/query_part_editor.ts +++ /dev/null @@ -1,186 +0,0 @@ -import $ from 'jquery'; -import { debounce, each, map, partial, escape, unescape } from 'lodash'; - -import coreModule from 'app/angular/core_module'; - -import { promiseToDigest } from '../promiseToDigest'; - -const template = ` -