From 2b9e46d1f80159217cd263694df75e86a2613286 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 16 Feb 2022 17:14:33 +0100 Subject: [PATCH] Angular: Option to disable angular support and isolate angular dependencies (#45421) * Angular: Initial setting that disables angular, load angular support in separate chunk * Load angular panels on demand * Load alerting in separate chunk only when angularSupportEnabled * progress, do not export core_module if angular disabled * Progress * Update public/app/features/plugins/built_in_plugins.ts Co-authored-by: Ryan McKinley * Removing remaining usage of angular from outside angular app (not counting plugins) * Update config and docs * Fix sample.ini * Update public/app/features/alerting/AlertTab.tsx Co-authored-by: Levente Balogh * Fixing prettier issue Co-authored-by: Ryan McKinley Co-authored-by: Levente Balogh --- conf/defaults.ini | 3 ++ conf/sample.ini | 3 ++ docs/sources/administration/configuration.md | 15 +++++++ packages/grafana-data/src/types/config.ts | 1 + packages/grafana-runtime/src/config.ts | 1 + pkg/api/frontendsettings.go | 1 + pkg/setting/setting.go | 4 +- public/app/AppWrapper.tsx | 32 ++++++--------- public/app/angular/AngularApp.ts | 17 ++++++++ public/app/angular/index.ts | 2 + .../app/{core => angular}/jquery_extended.ts | 0 .../angular/loadAndInitAngularIfEnabled.ts | 22 +++++++++++ public/app/app.ts | 10 ----- public/app/core/core.ts | 2 - public/app/features/alerting/AlertTab.tsx | 15 ++++--- .../alerting/unified/utils/receiver-form.ts | 2 +- .../DashboardPrompt/DashboardPrompt.tsx | 5 +-- .../app/features/plugins/built_in_plugins.ts | 10 +++-- .../app/features/plugins/importPanelPlugin.ts | 39 +++++++++---------- public/app/features/plugins/plugin_loader.ts | 15 +------ .../app/features/variables/state/actions.ts | 3 +- .../__mocks__/query_ctrl.ts | 4 +- public/app/types/angular.ts | 5 --- public/app/types/index.ts | 1 - 24 files changed, 118 insertions(+), 94 deletions(-) rename public/app/{core => angular}/jquery_extended.ts (100%) create mode 100644 public/app/angular/loadAndInitAngularIfEnabled.ts delete mode 100644 public/app/types/angular.ts diff --git a/conf/defaults.ini b/conf/defaults.ini index a852dee4e75..1f48c9718d2 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -292,6 +292,9 @@ content_security_policy = false # $ROOT_PATH is server.root_url without the protocol. content_security_policy_template = """script-src 'self' 'unsafe-eval' 'unsafe-inline' 'strict-dynamic' $NONCE;object-src 'none';font-src 'self';style-src 'self' 'unsafe-inline' blob:;img-src * data:;base-uri 'self';connect-src 'self' grafana.com ws://$ROOT_PATH wss://$ROOT_PATH;manifest-src 'self';media-src 'none';form-action 'self';""" +# Controls if old angular plugins are supported or not. This will be disabled by default in Grafana v9. +angular_support_enabled = true + #################################### Snapshots ########################### [snapshots] # snapshot sharing options diff --git a/conf/sample.ini b/conf/sample.ini index 710a8ea4810..759fd56af35 100644 --- a/conf/sample.ini +++ b/conf/sample.ini @@ -292,6 +292,9 @@ # $ROOT_PATH is server.root_url without the protocol. ;content_security_policy_template = """script-src 'self' 'unsafe-eval' 'unsafe-inline' 'strict-dynamic' $NONCE;object-src 'none';font-src 'self';style-src 'self' 'unsafe-inline' blob:;img-src * data:;base-uri 'self';connect-src 'self' grafana.com ws://$ROOT_PATH wss://$ROOT_PATH;manifest-src 'self';media-src 'none';form-action 'self';""" +# Controls if old angular plugins are supported or not. This will be disabled by default in Grafana v9. +;angular_support_enabled = true + #################################### Snapshots ########################### [snapshots] # snapshot sharing options diff --git a/docs/sources/administration/configuration.md b/docs/sources/administration/configuration.md index ecdc40b5386..1600c0420b5 100644 --- a/docs/sources/administration/configuration.md +++ b/docs/sources/administration/configuration.md @@ -582,6 +582,21 @@ Set Content Security Policy template used when adding the Content-Security-Polic
+### angular_support_enabled + +This currently defaults to `true` but will in Grafana v9 default to `false`. When set to false the angular framework and support components will not be loaded. This means that +all plugins and core features that depend on angular support will stop working. + +Current core features that will stop working: + +- Heatmap panel +- Old graph panel +- Old table panel +- Postgres, MySQL and MSSQL data source query editors +- Legacy alerting edit rule UI + +Before we disable angular support by default we plan to migrate these remaining areas to React. + ## [snapshots] ### external_enabled diff --git a/packages/grafana-data/src/types/config.ts b/packages/grafana-data/src/types/config.ts index c07e212e9cd..f92c856c223 100644 --- a/packages/grafana-data/src/types/config.ts +++ b/packages/grafana-data/src/types/config.ts @@ -138,4 +138,5 @@ export interface GrafanaConfig { geomapDefaultBaseLayer?: MapLayerOptions; geomapDisableCustomBaseLayer?: boolean; unifiedAlertingEnabled: boolean; + angularSupportEnabled: boolean; } diff --git a/packages/grafana-runtime/src/config.ts b/packages/grafana-runtime/src/config.ts index d9258c84c71..4cf1813b984 100644 --- a/packages/grafana-runtime/src/config.ts +++ b/packages/grafana-runtime/src/config.ts @@ -41,6 +41,7 @@ export class GrafanaBootConfig implements GrafanaConfig { alertingErrorOrTimeout = ''; alertingNoDataOrNullValues = ''; alertingMinInterval = 1; + angularSupportEnabled = false; authProxyEnabled = false; exploreEnabled = false; ldapEnabled = false; diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go index f1ea4edaef1..f59fe8ffbeb 100644 --- a/pkg/api/frontendsettings.go +++ b/pkg/api/frontendsettings.go @@ -229,6 +229,7 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *models.ReqContext) (map[string]i "externalUserMngLinkUrl": setting.ExternalUserMngLinkUrl, "externalUserMngLinkName": setting.ExternalUserMngLinkName, "viewersCanEdit": setting.ViewersCanEdit, + "angularSupportEnabled": hs.Cfg.AngularSupportEnabled, "editorsCanAdmin": hs.Cfg.EditorsCanAdmin, "disableSanitizeHtml": hs.Cfg.DisableSanitizeHtml, "pluginsToPreload": pluginsToPreload, diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index b4999997dd3..51639e6748c 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -254,7 +254,8 @@ type Cfg struct { // CSPEnabled toggles Content Security Policy support. CSPEnabled bool // CSPTemplate contains the Content Security Policy template. - CSPTemplate string + CSPTemplate string + AngularSupportEnabled bool TempDataLifetime time.Duration PluginsEnableAlpha bool @@ -1191,6 +1192,7 @@ func readSecuritySettings(iniFile *ini.File, cfg *Cfg) error { cfg.StrictTransportSecuritySubDomains = security.Key("strict_transport_security_subdomains").MustBool(false) cfg.CSPEnabled = security.Key("content_security_policy").MustBool(false) cfg.CSPTemplate = security.Key("content_security_policy_template").MustString("") + cfg.AngularSupportEnabled = security.Key("angular_support_enabled").MustBool(true) // read data source proxy whitelist DataProxyWhiteList = make(map[string]bool) diff --git a/public/app/AppWrapper.tsx b/public/app/AppWrapper.tsx index 4bb5b60ce7f..72eecdee141 100644 --- a/public/app/AppWrapper.tsx +++ b/public/app/AppWrapper.tsx @@ -15,15 +15,16 @@ import { GrafanaRoute } from './core/navigation/GrafanaRoute'; import { AppNotificationList } from './core/components/AppNotifications/AppNotificationList'; import { SearchWrapper } from 'app/features/search'; import { LiveConnectionWarning } from './features/live/LiveConnectionWarning'; -import { AngularRoot } from './angular/AngularRoot'; import { I18nProvider } from './core/localisation'; +import { AngularRoot } from './angular/AngularRoot'; +import { loadAndInitAngularIfEnabled } from './angular/loadAndInitAngularIfEnabled'; interface AppWrapperProps { app: GrafanaApp; } interface AppWrapperState { - ngInjector: any; + ready?: boolean; } /** Used by enterprise */ @@ -39,27 +40,14 @@ export function addPageBanner(fn: ComponentType) { } export class AppWrapper extends React.Component { - container = React.createRef(); - constructor(props: AppWrapperProps) { super(props); - - this.state = { - ngInjector: null, - }; + this.state = {}; } - componentDidMount() { - if (this.container) { - this.bootstrapNgApp(); - } else { - throw new Error('Failed to boot angular app, no container to attach to'); - } - } - - bootstrapNgApp() { - const injector = this.props.app.angularApp.bootstrap(); - this.setState({ ngInjector: injector }); + async componentDidMount() { + await loadAndInitAngularIfEnabled(); + this.setState({ ready: true }); $('.preloader').remove(); } @@ -91,6 +79,8 @@ export class AppWrapper extends React.Component ))} - + - {this.state.ngInjector && this.renderRoutes()} + {ready && this.renderRoutes()} {bodyRenderHooks.map((Hook, index) => ( ))} diff --git a/public/app/angular/AngularApp.ts b/public/app/angular/AngularApp.ts index a746e355e1b..29977589ea9 100644 --- a/public/app/angular/AngularApp.ts +++ b/public/app/angular/AngularApp.ts @@ -14,6 +14,11 @@ import { extend } from 'lodash'; import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv'; import { getTemplateSrv } from '@grafana/runtime'; import { registerComponents } from './registerComponents'; +import { exposeToPlugin } from 'app/features/plugins/plugin_loader'; +import appEvents from 'app/core/app_events'; +import { contextSrv } from 'app/core/services/context_srv'; +import * as sdk from 'app/plugins/sdk'; +import { promiseToDigest } from './promiseToDigest'; export class AngularApp { ngModuleDependencies: any[]; @@ -93,6 +98,18 @@ export class AngularApp { registerComponents(); initAngularRoutingBridge(); + // Angular plugins import this + exposeToPlugin('angular', angular); + exposeToPlugin('app/core/utils/promiseToDigest', { promiseToDigest, __esModule: true }); + exposeToPlugin('app/plugins/sdk', sdk); + exposeToPlugin('app/core/core_module', coreModule); + exposeToPlugin('app/core/core', { + coreModule: coreModule, + appEvents: appEvents, + contextSrv: contextSrv, + __esModule: true, + }); + // disable tool tip animation $.fn.tooltip.defaults.animation = false; } diff --git a/public/app/angular/index.ts b/public/app/angular/index.ts index 2dcaee03cab..ada6fe8f6a5 100644 --- a/public/app/angular/index.ts +++ b/public/app/angular/index.ts @@ -9,6 +9,7 @@ import './services/popover_srv'; import './services/timer'; import './services/AngularLoader'; +import '../angular/jquery_extended'; import './dropdown_typeahead'; import './autofill_event_fix'; import './metric_segment'; @@ -37,3 +38,4 @@ import './components/plugin_component'; import './GrafanaCtrl'; export { AngularApp } from './AngularApp'; +export { coreModule } from './core_module'; diff --git a/public/app/core/jquery_extended.ts b/public/app/angular/jquery_extended.ts similarity index 100% rename from public/app/core/jquery_extended.ts rename to public/app/angular/jquery_extended.ts diff --git a/public/app/angular/loadAndInitAngularIfEnabled.ts b/public/app/angular/loadAndInitAngularIfEnabled.ts new file mode 100644 index 00000000000..211f44ae3b8 --- /dev/null +++ b/public/app/angular/loadAndInitAngularIfEnabled.ts @@ -0,0 +1,22 @@ +import { config, setAngularLoader } from '@grafana/runtime'; + +export async function loadAndInitAngularIfEnabled() { + if (config.angularSupportEnabled) { + const { AngularApp } = await import(/* webpackChunkName: "AngularApp" */ './index'); + const app = new AngularApp(); + app.init(); + app.bootstrap(); + } else { + setAngularLoader({ + load: (elem, scopeProps, template) => { + return { + destroy: () => {}, + digest: () => {}, + getScope: () => { + return {}; + }, + }; + }, + }); + } +} diff --git a/public/app/app.ts b/public/app/app.ts index 7f5bcb17836..48167320b11 100644 --- a/public/app/app.ts +++ b/public/app/app.ts @@ -62,7 +62,6 @@ import { setPanelRenderer } from '@grafana/runtime/src/components/PanelRenderer' import { PanelDataErrorView } from './features/panel/components/PanelDataErrorView'; import { setPanelDataErrorView } from '@grafana/runtime/src/components/PanelDataErrorView'; import { DatasourceSrv } from './features/plugins/datasource_srv'; -import { AngularApp } from './angular'; import { ModalManager } from './core/services/ModalManager'; import { initWindowRuntime } from './features/runtime/init'; import { createQueryVariableAdapter } from './features/variables/query/adapter'; @@ -89,12 +88,6 @@ if (process.env.NODE_ENV === 'development') { } export class GrafanaApp { - angularApp: AngularApp; - - constructor() { - this.angularApp = new AngularApp(); - } - async init() { try { setBackendSrv(backendSrv); @@ -148,9 +141,6 @@ export class GrafanaApp { const modalManager = new ModalManager(); modalManager.init(); - // Init angular - this.angularApp.init(); - // Preload selected app plugins await preloadPlugins(config.pluginsToPreload); diff --git a/public/app/core/core.ts b/public/app/core/core.ts index 04cf6dbbbd8..38e3808619d 100644 --- a/public/app/core/core.ts +++ b/public/app/core/core.ts @@ -1,5 +1,3 @@ -import './jquery_extended'; -import './services/search_srv'; import { colors, JsonExplorer } from '@grafana/ui/'; import appEvents from './app_events'; import { assignModelProperties } from './utils/model_utils'; diff --git a/public/app/features/alerting/AlertTab.tsx b/public/app/features/alerting/AlertTab.tsx index 3348293a19e..2c75d68fc49 100644 --- a/public/app/features/alerting/AlertTab.tsx +++ b/public/app/features/alerting/AlertTab.tsx @@ -2,13 +2,10 @@ import React, { PureComponent } from 'react'; import { connect, MapDispatchToProps, MapStateToProps } from 'react-redux'; import { Alert, Button, ConfirmModal, Container, CustomScrollbar, HorizontalGroup, IconName, Modal } from '@grafana/ui'; import { selectors } from '@grafana/e2e-selectors'; -import { AngularComponent, getAngularLoader, getDataSourceSrv } from '@grafana/runtime'; +import { AngularComponent, config, getAngularLoader, getDataSourceSrv } from '@grafana/runtime'; import { getAlertingValidationMessage } from './getAlertingValidationMessage'; - import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA'; import StateHistory from './StateHistory'; -import 'app/features/alerting/AlertTabCtrl'; - import { DashboardModel } from '../dashboard/state/DashboardModel'; import { PanelModel } from '../dashboard/state/PanelModel'; import { TestRuleResult } from './TestRuleResult'; @@ -57,8 +54,14 @@ class UnConnectedAlertTab extends PureComponent { showTestRule: false, }; - componentDidMount() { - this.loadAlertTab(); + async componentDidMount() { + if (config.angularSupportEnabled) { + await import(/* webpackChunkName: "AlertTabCtrl" */ 'app/features/alerting/AlertTabCtrl'); + this.loadAlertTab(); + } else { + // TODO probably need to migrate AlertTab to react + alert('Angular support disabled, legacy alerting cannot function without angular support'); + } } onAngularPanelUpdated = () => { diff --git a/public/app/features/alerting/unified/utils/receiver-form.ts b/public/app/features/alerting/unified/utils/receiver-form.ts index 801e5bfc997..f4aa3886fa6 100644 --- a/public/app/features/alerting/unified/utils/receiver-form.ts +++ b/public/app/features/alerting/unified/utils/receiver-form.ts @@ -1,4 +1,3 @@ -import { isArray } from 'angular'; import { AlertManagerCortexConfig, GrafanaManagedReceiverConfig, @@ -6,6 +5,7 @@ import { Route, } from 'app/plugins/datasource/alertmanager/types'; import { CloudNotifierType, NotifierDTO, NotifierType } from 'app/types'; +import { isArray } from 'lodash'; import { CloudChannelConfig, CloudChannelMap, diff --git a/public/app/features/dashboard/components/DashboardPrompt/DashboardPrompt.tsx b/public/app/features/dashboard/components/DashboardPrompt/DashboardPrompt.tsx index 24095f3320d..1a273bab2e4 100644 --- a/public/app/features/dashboard/components/DashboardPrompt/DashboardPrompt.tsx +++ b/public/app/features/dashboard/components/DashboardPrompt/DashboardPrompt.tsx @@ -5,7 +5,6 @@ import React, { useEffect, useState } from 'react'; import { Prompt } from 'react-router-dom'; import { DashboardModel } from '../../state/DashboardModel'; import { each, filter, find } from 'lodash'; -import angular from 'angular'; import { UnsavedChangesModal } from '../SaveDashboard/UnsavedChangesModal'; import * as H from 'history'; import { SaveLibraryPanelModal } from 'app/features/library-panels/components/SaveLibraryPanelModal/SaveLibraryPanelModal'; @@ -248,8 +247,8 @@ export function hasChanges(current: DashboardModel, original: any) { currentTimepicker.now = originalTimepicker.now; } - const currentJson = angular.toJson(currentClean); - const originalJson = angular.toJson(originalClean); + const currentJson = JSON.stringify(currentClean, null); + const originalJson = JSON.stringify(originalClean, null); return currentJson !== originalJson; } diff --git a/public/app/features/plugins/built_in_plugins.ts b/public/app/features/plugins/built_in_plugins.ts index 66cfd1d6bb0..c542aa7dbb4 100644 --- a/public/app/features/plugins/built_in_plugins.ts +++ b/public/app/features/plugins/built_in_plugins.ts @@ -45,15 +45,12 @@ import * as timeseriesPanel from 'app/plugins/panel/timeseries/module'; import * as stateTimelinePanel from 'app/plugins/panel/state-timeline/module'; import * as statusHistoryPanel from 'app/plugins/panel/status-history/module'; import * as candlestickPanel from 'app/plugins/panel/candlestick/module'; -import * as graphPanel from 'app/plugins/panel/graph/module'; import * as xyChartPanel from 'app/plugins/panel/xychart/module'; import * as dashListPanel from 'app/plugins/panel/dashlist/module'; import * as pluginsListPanel from 'app/plugins/panel/pluginlist/module'; import * as alertListPanel from 'app/plugins/panel/alertlist/module'; import * as annoListPanel from 'app/plugins/panel/annolist/module'; -import * as heatmapPanel from 'app/plugins/panel/heatmap/module'; import * as tablePanel from 'app/plugins/panel/table/module'; -import * as oldTablePanel from 'app/plugins/panel/table-old/module'; import * as statPanel from 'app/plugins/panel/stat/module'; import * as gettingStartedPanel from 'app/plugins/panel/gettingstarted/module'; import * as gaugePanel from 'app/plugins/panel/gauge/module'; @@ -73,6 +70,11 @@ import * as alertGroupsPanel from 'app/plugins/panel/alertGroups/module'; const geomapPanel = async () => await import(/* webpackChunkName: "geomapPanel" */ 'app/plugins/panel/geomap/module'); const canvasPanel = async () => await import(/* webpackChunkName: "canvasPanel" */ 'app/plugins/panel/canvas/module'); const iconPanel = async () => await import(/* webpackChunkName: "iconPanel" */ 'app/plugins/panel/icon/module'); +const graphPanel = async () => await import(/* webpackChunkName: "graphPlugin" */ 'app/plugins/panel/graph/module'); +const heatmapPanel = async () => + await import(/* webpackChunkName: "heatmapPlugin" */ 'app/plugins/panel/heatmap/module'); +const tableOldPanel = async () => + await import(/* webpackChunkName: "tableOldPlugin" */ 'app/plugins/panel/table-old/module'); const builtInPlugins: any = { 'app/plugins/datasource/graphite/module': graphitePlugin, @@ -112,7 +114,7 @@ const builtInPlugins: any = { 'app/plugins/panel/annolist/module': annoListPanel, 'app/plugins/panel/heatmap/module': heatmapPanel, 'app/plugins/panel/table/module': tablePanel, - 'app/plugins/panel/table-old/module': oldTablePanel, + 'app/plugins/panel/table-old/module': tableOldPanel, 'app/plugins/panel/news/module': newsPanel, 'app/plugins/panel/live/module': livePanel, 'app/plugins/panel/stat/module': statPanel, diff --git a/public/app/features/plugins/importPanelPlugin.ts b/public/app/features/plugins/importPanelPlugin.ts index ccb3bdf9251..40d4dc3549d 100644 --- a/public/app/features/plugins/importPanelPlugin.ts +++ b/public/app/features/plugins/importPanelPlugin.ts @@ -28,25 +28,22 @@ export function importPanelPluginFromMeta(meta: grafanaData.PanelPluginMeta): Pr return getPanelPlugin(meta); } -function getPanelPlugin(meta: grafanaData.PanelPluginMeta): Promise { - return importPluginModule(meta.module, meta.info?.version) - .then((pluginExports) => { - if (pluginExports.plugin) { - return pluginExports.plugin as grafanaData.PanelPlugin; - } else if (pluginExports.PanelCtrl) { - const plugin = new grafanaData.PanelPlugin(null); - plugin.angularPanelCtrl = pluginExports.PanelCtrl; - return plugin; - } - throw new Error('missing export: plugin or PanelCtrl'); - }) - .then((plugin) => { - plugin.meta = meta; - return plugin; - }) - .catch((err) => { - // TODO, maybe a different error plugin - console.warn('Error loading panel plugin: ' + meta.id, err); - return getPanelPluginLoadError(meta, err); - }); +async function getPanelPlugin(meta: grafanaData.PanelPluginMeta): Promise { + try { + const pluginExports = await importPluginModule(meta.module, meta.info?.version); + let plugin = pluginExports.plugin; + + if (!plugin && pluginExports.PanelCtrl) { + plugin = new grafanaData.PanelPlugin(null); + plugin.angularPanelCtrl = pluginExports.PanelCtrl; + } + + plugin.meta = meta; + + return plugin; + } catch (err) { + // TODO, maybe a different error plugin + console.warn('Error loading panel plugin: ' + meta.id, err); + return getPanelPluginLoadError(meta, err); + } } diff --git a/public/app/features/plugins/plugin_loader.ts b/public/app/features/plugins/plugin_loader.ts index 8bd0ded2976..831a5947762 100644 --- a/public/app/features/plugins/plugin_loader.ts +++ b/public/app/features/plugins/plugin_loader.ts @@ -1,9 +1,7 @@ // eslint-disable-next-line lodash/import-scope import _ from 'lodash'; -import * as sdk from 'app/plugins/sdk'; import kbn from 'app/core/utils/kbn'; import moment from 'moment'; // eslint-disable-line no-restricted-imports -import angular from 'angular'; import jquery from 'jquery'; // Experimental module exports @@ -21,12 +19,10 @@ import * as redux from 'redux'; import config from 'app/core/config'; import TimeSeries from 'app/core/time_series2'; import TableModel from 'app/core/table_model'; -import { coreModule } from 'app/angular/core_module'; import { appEvents, contextSrv } from 'app/core/core'; import * as flatten from 'app/core/utils/flatten'; import * as ticks from 'app/core/utils/ticks'; import { BackendSrv, getBackendSrv } from 'app/core/services/backend_srv'; -import { promiseToDigest } from 'app/angular/promiseToDigest'; import impressionSrv from 'app/core/services/impression_srv'; import builtInPlugins from './built_in_plugins'; import * as d3 from 'd3'; @@ -75,7 +71,7 @@ grafanaRuntime.SystemJS.config({ }, }); -function exposeToPlugin(name: string, component: any) { +export function exposeToPlugin(name: string, component: any) { grafanaRuntime.SystemJS.registerDynamic(name, [], true, (require: any, exports: any, module: { exports: any }) => { module.exports = component; }); @@ -87,7 +83,6 @@ exposeToPlugin('@grafana/runtime', grafanaRuntime); exposeToPlugin('lodash', _); exposeToPlugin('moment', moment); exposeToPlugin('jquery', jquery); -exposeToPlugin('angular', angular); exposeToPlugin('d3', d3); exposeToPlugin('rxjs', rxjs); exposeToPlugin('rxjs/operators', rxjsOperators); @@ -120,24 +115,16 @@ exposeToPlugin('app/core/services/backend_srv', { getBackendSrv, }); -exposeToPlugin('app/plugins/sdk', sdk); exposeToPlugin('app/core/utils/datemath', grafanaData.dateMath); exposeToPlugin('app/core/utils/flatten', flatten); exposeToPlugin('app/core/utils/kbn', kbn); exposeToPlugin('app/core/utils/ticks', ticks); -exposeToPlugin('app/core/utils/promiseToDigest', { - promiseToDigest: promiseToDigest, - __esModule: true, -}); - exposeToPlugin('app/core/config', config); exposeToPlugin('app/core/time_series', TimeSeries); exposeToPlugin('app/core/time_series2', TimeSeries); exposeToPlugin('app/core/table_model', TableModel); exposeToPlugin('app/core/app_events', appEvents); -exposeToPlugin('app/core/core_module', coreModule); exposeToPlugin('app/core/core', { - coreModule: coreModule, appEvents: appEvents, contextSrv: contextSrv, __esModule: true, diff --git a/public/app/features/variables/state/actions.ts b/public/app/features/variables/state/actions.ts index 4a32665f3d6..902fbba742e 100644 --- a/public/app/features/variables/state/actions.ts +++ b/public/app/features/variables/state/actions.ts @@ -1,4 +1,3 @@ -import angular from 'angular'; import { castArray, isEqual } from 'lodash'; import { DataQuery, @@ -601,7 +600,7 @@ const timeRangeUpdated = const updatedVariable = getVariable(identifier.id, getState()); const updatedOptions = updatedVariable.options; - if (angular.toJson(previousOptions) !== angular.toJson(updatedOptions)) { + if (JSON.stringify(previousOptions) !== JSON.stringify(updatedOptions)) { const dashboard = getState().dashboard.getModel(); dashboard?.templateVariableValueUpdated(); } diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/__mocks__/query_ctrl.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/__mocks__/query_ctrl.ts index f8885924173..7ae8bca81c0 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/__mocks__/query_ctrl.ts +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/__mocks__/query_ctrl.ts @@ -1,5 +1,3 @@ -import { auto } from 'angular'; - export class QueryCtrl { target: any; datasource: any; @@ -8,7 +6,7 @@ export class QueryCtrl { hasRawMode = false; error = ''; - constructor(public $scope: any, _$injector: auto.IInjectorService) { + constructor(public $scope: any) { this.panelCtrl = this.panelCtrl || { panel: {} }; this.target = this.target || { target: '' }; this.panel = this.panelCtrl.panel; diff --git a/public/app/types/angular.ts b/public/app/types/angular.ts deleted file mode 100644 index 05af2828765..00000000000 --- a/public/app/types/angular.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { IScope } from 'angular'; - -export interface Scope extends IScope { - [key: string]: any; -} diff --git a/public/app/types/index.ts b/public/app/types/index.ts index 275bafc09af..3ffade53998 100644 --- a/public/app/types/index.ts +++ b/public/app/types/index.ts @@ -15,7 +15,6 @@ export * from './explore'; export * from './store'; export * from './ldap'; export * from './appEvent'; -export * from './angular'; export * from './query'; export * from './preferences'; export * from './accessControl';