Angular: Isolate angular more (#41440)

* Getting close

* Restore angular app boot at startup

* Moving angular annotations dependencies to app/angular or old graph

* Remove redundant setLinkSrv call

* Fixing graph test

* Minor refactor based on review feedback

* Create in get function
This commit is contained in:
Torkel Ödegaard 2021-11-10 11:05:36 +01:00 committed by GitHub
parent e7fd41d779
commit c96c92d712
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
51 changed files with 201 additions and 227 deletions

View File

@ -15,6 +15,7 @@ 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';
interface AppWrapperProps {
app: GrafanaApp;
@ -57,6 +58,7 @@ export class AppWrapper extends React.Component<AppWrapperProps, AppWrapperState
bootstrapNgApp() {
const injector = this.props.app.angularApp.bootstrap();
this.setState({ ngInjector: injector });
$('.preloader').remove();
}
renderRoute = (route: RouteDescriptor) => {
@ -89,8 +91,6 @@ export class AppWrapper extends React.Component<AppWrapperProps, AppWrapperState
render() {
navigationLogger('AppWrapper', false, 'rendering');
// @ts-ignore
const appSeed = `<grafana-app ng-cloak></app-notifications-list></grafana-app>`;
const newNavigationEnabled = config.featureToggles.newNavigation;
return (
@ -108,17 +108,10 @@ export class AppWrapper extends React.Component<AppWrapperProps, AppWrapperState
<Banner key={index.toString()} />
))}
<div
id="ngRoot"
ref={this.container}
dangerouslySetInnerHTML={{
__html: appSeed,
}}
/>
<AngularRoot ref={this.container} />
<AppNotificationList />
<SearchWrapper />
{this.state.ngInjector && this.container && this.renderRoutes()}
{this.state.ngInjector && this.renderRoutes()}
{bodyRenderHooks.map((Hook, index) => (
<Hook key={index.toString()} />
))}

View File

@ -92,6 +92,9 @@ export class AngularApp {
registerAngularDirectives();
registerComponents();
initAngularRoutingBridge();
// disable tool tip animation
$.fn.tooltip.defaults.animation = false;
}
useModule(module: angular.IModule) {

View File

@ -0,0 +1,15 @@
import React from 'react';
export const AngularRoot = React.forwardRef<HTMLDivElement, {}>((props, ref) => {
return (
<div
id="ngRoot"
ref={ref}
dangerouslySetInnerHTML={{
__html: '<grafana-app ng-cloak></grafana-app>',
}}
/>
);
});
AngularRoot.displayName = 'AngularRoot';

View File

@ -5,27 +5,16 @@ import $ from 'jquery';
// Utils and servies
import { colors } from '@grafana/ui';
import {
setDataSourceSrv,
setLegacyAngularInjector,
setLocationSrv,
locationService,
setAppEvents,
setAngularLoader,
} from '@grafana/runtime';
import { setLegacyAngularInjector, setAppEvents, setAngularLoader } from '@grafana/runtime';
import config from 'app/core/config';
import coreModule from 'app/angular/core_module';
import { profiler } from 'app/core/profiler';
import appEvents from 'app/core/app_events';
import { DatasourceSrv } from 'app/features/plugins/datasource_srv';
import { AngularLoader } from 'app/angular/services/AngularLoader';
// Types
import { CoreEvents, AppEventEmitter, AppEventConsumer } from 'app/types';
import { setLinkSrv, LinkSrv } from 'app/angular/panel/panellinks/link_srv';
import { UtilSrv } from 'app/core/services/util_srv';
import { ContextSrv } from 'app/core/services/context_srv';
import { DashboardSrv, setDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
import { IRootScopeService, IAngularEvent, auto } from 'angular';
import { AppEvent } from '@grafana/data';
import { initGrafanaLive } from 'app/features/live';
@ -39,22 +28,12 @@ export class GrafanaCtrl {
utilSrv: UtilSrv,
$rootScope: GrafanaRootScope,
contextSrv: ContextSrv,
linkSrv: LinkSrv,
datasourceSrv: DatasourceSrv,
dashboardSrv: DashboardSrv,
angularLoader: AngularLoader,
$injector: auto.IInjectorService
) {
// make angular loader service available to react components
setAngularLoader(angularLoader);
setDataSourceSrv(datasourceSrv);
setLinkSrv(linkSrv);
setDashboardSrv(dashboardSrv);
setLegacyAngularInjector($injector);
datasourceSrv.init(config.datasources, config.defaultDatasource);
setLocationSrv(locationService);
setAppEvents(appEvents);
initGrafanaLive();
@ -63,8 +42,6 @@ export class GrafanaCtrl {
$scope.contextSrv = contextSrv;
$scope.appSubUrl = config.appSubUrl;
$scope._ = _;
profiler.init(config, $rootScope);
utilSrv.init();
};
@ -116,8 +93,6 @@ export function grafanaAppDirective() {
// see https://github.com/zenorocha/clipboard.js/issues/155
$.fn.modal.Constructor.prototype.enforceFocus = () => {};
$('.preloader').remove();
appEvents.on(CoreEvents.toggleSidemenuHidden, () => {
body.toggleClass('sidemenu-hidden');
});

View File

@ -1,6 +1,6 @@
import angular from 'angular';
import coreModule from './core_module';
import { GrafanaRootScope } from 'app/routes/GrafanaCtrl';
import { GrafanaRootScope } from 'app/angular/GrafanaCtrl';
export class DeltaCtrl {
observer: any;

View File

@ -31,5 +31,6 @@ import './components/info_popover';
import './components/spectrum_picker';
import './components/code_editor/code_editor';
import './components/sql_part/sql_part_editor';
import './GrafanaCtrl';
export { AngularApp } from './AngularApp';

View File

@ -0,0 +1,23 @@
import { auto } from 'angular';
let injector: auto.IInjectorService | undefined;
/**
* Future poc to lazy load angular app, not yet used
*/
export async function getAngularInjector(): Promise<auto.IInjectorService> {
if (injector) {
return injector;
}
const { AngularApp } = await import(/* webpackChunkName: "AngularApp" */ './index');
if (injector) {
return injector;
}
const app = new AngularApp();
app.init();
injector = app.bootstrap();
return injector;
}

View File

@ -1,8 +1,15 @@
import { getBackendSrv } from '@grafana/runtime';
import { getBackendSrv, getDataSourceSrv } from '@grafana/runtime';
import { contextSrv } from 'app/core/core';
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
import { getLinkSrv } from 'app/features/panel/panellinks/link_srv';
import coreModule from './core_module';
import { AnnotationsSrv } from './services/annotations_srv';
export function registerComponents() {
coreModule.factory('backendSrv', () => getBackendSrv());
coreModule.factory('contextSrv', () => contextSrv);
coreModule.factory('dashboardSrv', () => getDashboardSrv());
coreModule.factory('datasourceSrv', () => getDataSourceSrv());
coreModule.factory('linkSrv', () => getLinkSrv());
coreModule.service('annotationsSrv', AnnotationsSrv);
}

View File

@ -3,7 +3,7 @@ import coreModule from 'app/angular/core_module';
import { assign } from 'lodash';
import { AngularComponent, AngularLoader as AngularLoaderInterface } from '@grafana/runtime';
import { GrafanaRootScope } from 'app/routes/GrafanaCtrl';
import { GrafanaRootScope } from 'app/angular/GrafanaCtrl';
export class AngularLoader implements AngularLoaderInterface {
/** @ngInject */

View File

@ -1,4 +1,4 @@
import { AnnotationsSrv } from '../annotations_srv';
import { AnnotationsSrv } from './annotations_srv';
describe('AnnotationsSrv', () => {
const annotationsSrv = new AnnotationsSrv();

View File

@ -1,26 +1,9 @@
import { cloneDeep } from 'lodash';
import { Observable, of } from 'rxjs';
import { map, mergeMap } from 'rxjs/operators';
import {
AnnotationEvent,
CoreApp,
DataQueryRequest,
DataSourceApi,
deprecationWarning,
rangeUtil,
ScopedVars,
} from '@grafana/data';
import { AnnotationEvent, deprecationWarning } from '@grafana/data';
import coreModule from 'app/angular/core_module';
import { AnnotationQueryOptions, AnnotationQueryResponse } from './types';
import { standardAnnotationSupport } from './standardAnnotationSupport';
import { runRequest } from '../query/state/runRequest';
import { deleteAnnotation, saveAnnotation, updateAnnotation } from './api';
import { deleteAnnotation, saveAnnotation, updateAnnotation } from 'app/features/annotations/api';
import { AnnotationQueryOptions } from 'app/features/annotations/types';
let counter = 100;
function getNextRequestId() {
return 'AQ' + counter++;
}
/**
* @deprecated AnnotationsSrv is deprecated in favor of DashboardQueryRunner
*/
@ -102,67 +85,3 @@ export class AnnotationsSrv {
return results;
}
}
export function executeAnnotationQuery(
options: AnnotationQueryOptions,
datasource: DataSourceApi,
savedJsonAnno: any
): Observable<AnnotationQueryResponse> {
const processor = {
...standardAnnotationSupport,
...datasource.annotations,
};
const annotation = processor.prepareAnnotation!(savedJsonAnno);
if (!annotation) {
return of({});
}
const query = processor.prepareQuery!(annotation);
if (!query) {
return of({});
}
// No more points than pixels
const maxDataPoints = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
// Add interval to annotation queries
const interval = rangeUtil.calculateInterval(options.range, maxDataPoints, datasource.interval);
const scopedVars: ScopedVars = {
__interval: { text: interval.interval, value: interval.interval },
__interval_ms: { text: interval.intervalMs.toString(), value: interval.intervalMs },
__annotation: { text: annotation.name, value: annotation },
};
const queryRequest: DataQueryRequest = {
startTime: Date.now(),
requestId: getNextRequestId(),
range: options.range,
maxDataPoints,
scopedVars,
...interval,
app: CoreApp.Dashboard,
timezone: options.dashboard.timezone,
targets: [
{
...query,
refId: 'Anno',
},
],
};
return runRequest(datasource, queryRequest).pipe(
mergeMap((panelData) => {
if (!panelData.series) {
return of({ panelData, events: [] });
}
return processor.processEvents!(annotation, panelData.series).pipe(map((events) => ({ panelData, events })));
})
);
}
coreModule.service('annotationsSrv', AnnotationsSrv);

View File

@ -2,7 +2,7 @@ import { extend } from 'lodash';
import coreModule from 'app/angular/core_module';
// @ts-ignore
import Drop from 'tether-drop';
import { GrafanaRootScope } from 'app/routes/GrafanaCtrl';
import { GrafanaRootScope } from 'app/angular/GrafanaCtrl';
/** @ngInject */
function popoverSrv(this: any, $compile: any, $rootScope: GrafanaRootScope, $timeout: any) {

View File

@ -27,16 +27,18 @@ import {
import { arrayMove } from 'app/core/utils/arrayMove';
import { importPluginModule } from 'app/features/plugins/plugin_loader';
import {
locationService,
registerEchoBackend,
setBackendSrv,
setDataSourceSrv,
setEchoSrv,
setLocationSrv,
setPanelRenderer,
setQueryRunnerFactory,
} from '@grafana/runtime';
import { Echo } from './core/services/echo/Echo';
import { reportPerformance } from './core/services/echo/EchoSrv';
import { PerformanceBackend } from './core/services/echo/backends/PerformanceBackend';
import 'app/routes/GrafanaCtrl';
import 'app/features/all';
import { getScrollbarWidth, getStandardFieldConfigs } from '@grafana/ui';
import { getDefaultVariableAdapters, variableAdapters } from './features/variables/adapters';
@ -47,7 +49,6 @@ import { setVariableQueryRunner, VariableQueryRunner } from './features/variable
import { configureStore } from './store/configureStore';
import { AppWrapper } from './AppWrapper';
import { interceptLinkClicks } from './core/navigation/patch/interceptLinkClicks';
import { AngularApp } from './angular';
import { PanelRenderer } from './features/panel/components/PanelRenderer';
import { QueryRunner } from './features/query/state/QueryRunner';
import { getTimeSrv } from './features/dashboard/services/TimeSrv';
@ -59,6 +60,8 @@ import { ApplicationInsightsBackend } from './core/services/echo/backends/analyt
import { RudderstackBackend } from './core/services/echo/backends/analytics/RudderstackBackend';
import { getAllOptionEditors } from './core/components/editors/registry';
import { backendSrv } from './core/services/backend_srv';
import { DatasourceSrv } from './features/plugins/datasource_srv';
import { AngularApp } from './angular';
// add move to lodash for backward compatabilty with plugins
// @ts-ignore
@ -89,6 +92,7 @@ export class GrafanaApp {
setLocale(config.bootData.user.locale);
setWeekStart(config.bootData.user.weekStart);
setPanelRenderer(PanelRenderer);
setLocationSrv(locationService);
setTimeZoneResolver(() => config.bootData.user.timezone);
// Important that extensions are initialized before store
initExtensions();
@ -112,9 +116,12 @@ export class GrafanaApp {
// intercept anchor clicks and forward it to custom history instead of relying on browser's history
document.addEventListener('click', interceptLinkClicks);
// disable tool tip animation
$.fn.tooltip.defaults.animation = false;
// Init DataSourceSrv
const dataSourceSrv = new DatasourceSrv();
dataSourceSrv.init(config.datasources, config.defaultDatasource);
setDataSourceSrv(dataSourceSrv);
// Init angular
this.angularApp.init();
// Preload selected app plugins

View File

@ -1,19 +1,6 @@
import { GrafanaRootScope } from 'app/routes/GrafanaCtrl';
export class Profiler {
panelsRendered = 0;
enabled?: boolean = undefined;
$rootScope?: GrafanaRootScope = undefined;
window?: any = undefined;
init(config: any, $rootScope: GrafanaRootScope) {
this.$rootScope = $rootScope;
this.window = window;
if (!this.enabled) {
return;
}
}
renderingCompleted() {
// add render counter to root scope
@ -22,7 +9,7 @@ export class Profiler {
// this window variable is used by backend rendering tools to know
// all panels have completed rendering
this.window.panelsRendered = this.panelsRendered;
(window as any).panelsRendered = this.panelsRendered;
}
}

View File

@ -3,8 +3,7 @@ import ReactDOM from 'react-dom';
import coreModule from 'app/angular/core_module';
import appEvents from 'app/core/app_events';
import { GrafanaRootScope } from 'app/routes/GrafanaCtrl';
import { GrafanaRootScope } from 'app/angular/GrafanaCtrl';
import { AngularModalProxy } from '../components/modals/AngularModalProxy';
import { provideTheme } from '../utils/ConfigProvider';
import {

View File

@ -1,4 +1,3 @@
import './annotations/all';
import './plugins/all';
import './dashboard';
import './manage-dashboards';

View File

@ -1,5 +0,0 @@
import { AnnotationsSrv } from './annotations_srv';
import { eventEditor } from './event_editor';
import { EventManager } from './event_manager';
import { annotationTooltipDirective } from './annotation_tooltip';
export { AnnotationsSrv, eventEditor, EventManager, annotationTooltipDirective };

View File

@ -7,7 +7,7 @@ import { Button, Icon, IconName, Spinner } from '@grafana/ui';
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { standardAnnotationSupport } from '../standardAnnotationSupport';
import { executeAnnotationQuery } from '../annotations_srv';
import { executeAnnotationQuery } from '../executeAnnotationQuery';
import { PanelModel } from 'app/features/dashboard/state';
import { AnnotationQueryResponse } from '../types';
import { AnnotationFieldMapper } from './AnnotationResultMapper';

View File

@ -1,4 +1,4 @@
import { dedupAnnotations } from '../events_processing';
import { dedupAnnotations } from './events_processing';
describe('Annotations deduplication', () => {
it('should remove duplicated annotations', () => {

View File

@ -0,0 +1,74 @@
import { Observable, of } from 'rxjs';
import { map, mergeMap } from 'rxjs/operators';
import { CoreApp, DataQueryRequest, DataSourceApi, rangeUtil, ScopedVars } from '@grafana/data';
import { AnnotationQueryOptions, AnnotationQueryResponse } from './types';
import { standardAnnotationSupport } from './standardAnnotationSupport';
import { runRequest } from '../query/state/runRequest';
let counter = 100;
function getNextRequestId() {
return 'AQ' + counter++;
}
export function executeAnnotationQuery(
options: AnnotationQueryOptions,
datasource: DataSourceApi,
savedJsonAnno: any
): Observable<AnnotationQueryResponse> {
const processor = {
...standardAnnotationSupport,
...datasource.annotations,
};
const annotation = processor.prepareAnnotation!(savedJsonAnno);
if (!annotation) {
return of({});
}
const query = processor.prepareQuery!(annotation);
if (!query) {
return of({});
}
// No more points than pixels
const maxDataPoints = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
// Add interval to annotation queries
const interval = rangeUtil.calculateInterval(options.range, maxDataPoints, datasource.interval);
const scopedVars: ScopedVars = {
__interval: { text: interval.interval, value: interval.interval },
__interval_ms: { text: interval.intervalMs.toString(), value: interval.intervalMs },
__annotation: { text: annotation.name, value: annotation },
};
const queryRequest: DataQueryRequest = {
startTime: Date.now(),
requestId: getNextRequestId(),
range: options.range,
maxDataPoints,
scopedVars,
...interval,
app: CoreApp.Dashboard,
timezone: options.dashboard.timezone,
targets: [
{
...query,
refId: 'Anno',
},
],
};
return runRequest(datasource, queryRequest).pipe(
mergeMap((panelData) => {
if (!panelData.series) {
return of({ panelData, events: [] });
}
return processor.processEvents!(annotation, panelData.series).pipe(map((events) => ({ panelData, events })));
})
);
}

View File

@ -14,7 +14,7 @@ import { OptionPaneRenderProps } from './types';
import { OptionsPaneItemDescriptor } from './OptionsPaneItemDescriptor';
import { OptionsPaneCategoryDescriptor } from './OptionsPaneCategoryDescriptor';
import { DynamicConfigValueEditor } from './DynamicConfigValueEditor';
import { getDataLinksVariableSuggestions } from 'app/angular/panel/panellinks/link_srv';
import { getDataLinksVariableSuggestions } from 'app/features/panel/panellinks/link_srv';
import { OverrideCategoryTitle } from './OverrideCategoryTitle';
import { css } from '@emotion/css';

View File

@ -1,5 +1,5 @@
import { DataLinksInlineEditor, Input, RadioButtonGroup, Select, Switch, TextArea } from '@grafana/ui';
import { getPanelLinksVariableSuggestions } from 'app/angular/panel/panellinks/link_srv';
import { getPanelLinksVariableSuggestions } from 'app/features/panel/panellinks/link_srv';
import React from 'react';
import { RepeatRowSelect } from '../RepeatRowSelect/RepeatRowSelect';
import { OptionsPaneItemDescriptor } from './OptionsPaneItemDescriptor';

View File

@ -1,7 +1,7 @@
import React from 'react';
import { StandardEditorContext, VariableSuggestionsScope } from '@grafana/data';
import { get as lodashGet } from 'lodash';
import { getDataLinksVariableSuggestions } from 'app/angular/panel/panellinks/link_srv';
import { getDataLinksVariableSuggestions } from 'app/features/panel/panellinks/link_srv';
import { OptionPaneRenderProps } from './types';
import { updateDefaultFieldConfigValue, setOptionImmutably } from './utils';
import { OptionsPaneItemDescriptor } from './OptionsPaneItemDescriptor';

View File

@ -2,7 +2,7 @@ import React, { FC } from 'react';
import { Icon, IconName, Tooltip, useForceUpdate } from '@grafana/ui';
import { sanitizeUrl } from '@grafana/data/src/text/sanitize';
import { DashboardLinksDashboard } from './DashboardLinksDashboard';
import { getLinkSrv } from '../../../../angular/panel/panellinks/link_srv';
import { getLinkSrv } from '../../../panel/panellinks/link_srv';
import { DashboardModel } from '../../state';
import { DashboardLink } from '../../state/DashboardModel';

View File

@ -2,7 +2,7 @@ import React, { useRef, useState, useLayoutEffect } from 'react';
import { Icon, ToolbarButton, Tooltip, useStyles2 } from '@grafana/ui';
import { sanitize, sanitizeUrl } from '@grafana/data/src/text/sanitize';
import { getBackendSrv } from 'app/core/services/backend_srv';
import { getLinkSrv } from '../../../../angular/panel/panellinks/link_srv';
import { getLinkSrv } from '../../../panel/panellinks/link_srv';
import { DashboardLink } from '../../state/DashboardModel';
import { DashboardSearchHit } from 'app/features/search/types';
import { selectors } from '@grafana/e2e-selectors';

View File

@ -1,5 +1,4 @@
import { isNumber } from 'lodash';
import coreModule from 'app/angular/core_module';
import { DashboardModel } from '../../state/DashboardModel';
import { getBackendSrv } from '@grafana/runtime';
@ -45,5 +44,3 @@ export class HistorySrv {
const historySrv = new HistorySrv();
export { historySrv };
coreModule.service('historySrv', HistorySrv);

View File

@ -7,7 +7,7 @@ import { selectors } from '@grafana/e2e-selectors';
import PanelHeaderCorner from './PanelHeaderCorner';
import { DashboardModel } from 'app/features/dashboard/state/DashboardModel';
import { PanelModel } from 'app/features/dashboard/state/PanelModel';
import { getPanelLinksSupplier } from 'app/angular/panel/panellinks/linkSuppliers';
import { getPanelLinksSupplier } from 'app/features/panel/panellinks/linkSuppliers';
import { PanelHeaderNotices } from './PanelHeaderNotices';
import { PanelHeaderMenuTrigger } from './PanelHeaderMenuTrigger';
import { PanelHeaderLoadingIndicator } from './PanelHeaderLoadingIndicator';

View File

@ -1,4 +1,3 @@
import coreModule from 'app/angular/core_module';
import { appEvents } from 'app/core/app_events';
import { DashboardModel } from '../state/DashboardModel';
import { removePanel } from '../utils/panel';
@ -67,8 +66,6 @@ export class DashboardSrv {
}
}
coreModule.service('dashboardSrv', DashboardSrv);
//
// Code below is to export the service to React components
//
@ -80,5 +77,8 @@ export function setDashboardSrv(instance: DashboardSrv) {
}
export function getDashboardSrv(): DashboardSrv {
if (!singletonInstance) {
singletonInstance = new DashboardSrv();
}
return singletonInstance;
}

View File

@ -3,7 +3,7 @@ import { setDataSourceSrv, setTemplateSrv } from '@grafana/runtime';
import { createSpanLinkFactory } from './createSpanLink';
import { TraceSpan } from '@jaegertracing/jaeger-ui-components';
import { TraceToLogsOptions } from '../../../core/components/TraceToLogsSettings';
import { LinkSrv, setLinkSrv } from '../../../angular/panel/panellinks/link_srv';
import { LinkSrv, setLinkSrv } from '../../panel/panellinks/link_srv';
import { TemplateSrv } from '../../templating/template_srv';
describe('createSpanLinkFactory', () => {

View File

@ -9,7 +9,7 @@ import {
LinkModel,
TimeRange,
} from '@grafana/data';
import { setLinkSrv } from '../../../angular/panel/panellinks/link_srv';
import { setLinkSrv } from '../../panel/panellinks/link_srv';
import { setContextSrv } from '../../../core/services/context_srv';
describe('getFieldLinksForExplore', () => {

View File

@ -11,7 +11,7 @@ import {
SplitOpen,
} from '@grafana/data';
import { getTemplateSrv } from '@grafana/runtime';
import { getLinkSrv } from '../../../angular/panel/panellinks/link_srv';
import { getLinkSrv } from '../../panel/panellinks/link_srv';
import { contextSrv } from 'app/core/services/context_srv';
/**

View File

@ -1,7 +1,7 @@
import { getFieldLinksSupplier } from './linkSuppliers';
import { applyFieldOverrides, createTheme, DataFrameView, dateTime, FieldDisplay, toDataFrame } from '@grafana/data';
import { getLinkSrv, LinkService, LinkSrv, setLinkSrv } from './link_srv';
import { TemplateSrv } from '../../../features/templating/template_srv';
import { TemplateSrv } from '../../templating/template_srv';
// We do not need more here and TimeSrv is hard to setup fully.
jest.mock('app/features/dashboard/services/TimeSrv', () => ({

View File

@ -1,7 +1,6 @@
import { chain } from 'lodash';
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { getTemplateSrv } from '@grafana/runtime';
import coreModule from 'app/angular/core_module';
import { getConfig } from 'app/core/config';
import {
DataFrame,
@ -15,7 +14,6 @@ import {
KeyValue,
LinkModel,
locationUtil,
PanelPlugin,
ScopedVars,
textUtil,
urlUtil,
@ -23,7 +21,7 @@ import {
VariableSuggestion,
VariableSuggestionsScope,
} from '@grafana/data';
import { getVariablesUrlParams } from '../../../features/variables/getAllVariableValuesForUrl';
import { getVariablesUrlParams } from '../../variables/getAllVariableValuesForUrl';
const timeRangeVars = [
{
@ -242,20 +240,6 @@ export const getCalculationValueDataLinksVariableSuggestions = (dataFrames: Data
return [...seriesVars, ...fieldVars, ...valueVars, valueCalcVar, ...getPanelLinksVariableSuggestions()];
};
export const getPanelOptionsVariableSuggestions = (plugin: PanelPlugin, data?: DataFrame[]): VariableSuggestion[] => {
const dataVariables = plugin.meta.skipDataQuery ? [] : getDataFrameVars(data || []);
return [
...dataVariables, // field values
...getTemplateSrv()
.getVariables()
.map((variable) => ({
value: variable.name as string,
label: variable.name,
origin: VariableOrigin.Template,
})),
];
};
export interface LinkService {
getDataLinkUIModel: <T>(link: DataLink, replaceVariables: InterpolateFunction | undefined, origin: T) => LinkModel<T>;
getAnchorInfo: (link: any) => any;
@ -263,8 +247,6 @@ export interface LinkService {
}
export class LinkSrv implements LinkService {
constructor() {}
getLinkUrl(link: any) {
let url = locationUtil.assureBaseUrl(getTemplateSrv().replace(link.url || ''));
let params: { [key: string]: any } = {};
@ -353,14 +335,15 @@ export class LinkSrv implements LinkService {
}
}
let singleton: LinkService;
let singleton: LinkService | undefined;
export function setLinkSrv(srv: LinkService) {
singleton = srv;
}
export function getLinkSrv(): LinkService {
if (!singleton) {
singleton = new LinkSrv();
}
return singleton;
}
coreModule.service('linkSrv', LinkSrv);

View File

@ -1,5 +1,3 @@
// Libraries
import coreModule from 'app/angular/core_module';
// Services & Utils
import { importDataSourcePlugin } from './plugin_loader';
import {
@ -7,6 +5,7 @@ import {
DataSourceSrv as DataSourceService,
getDataSourceSrv as getDataSourceService,
TemplateSrv,
getTemplateSrv,
} from '@grafana/runtime';
// Types
import {
@ -17,8 +16,6 @@ import {
DataSourceSelectItem,
ScopedVars,
} from '@grafana/data';
import { auto } from 'angular';
import { GrafanaRootScope } from 'app/routes/GrafanaCtrl';
// Pretend Datasource
import {
dataSource as expressionDatasource,
@ -27,6 +24,8 @@ import {
} from 'app/features/expressions/ExpressionDatasource';
import { DataSourceVariableModel } from '../variables/types';
import { ExpressionDatasourceRef } from '@grafana/runtime/src/utils/DataSourceWithBackend';
import appEvents from 'app/core/app_events';
import { getAngularInjector } from 'app/angular/lazyBootAngular';
export class DatasourceSrv implements DataSourceService {
private datasources: Record<string, DataSourceApi> = {}; // UID
@ -35,12 +34,7 @@ export class DatasourceSrv implements DataSourceService {
private settingsMapById: Record<string, DataSourceInstanceSettings> = {};
private defaultName = ''; // actually UID
/** @ngInject */
constructor(
private $injector: auto.IInjectorService,
private $rootScope: GrafanaRootScope,
private templateSrv: TemplateSrv
) {}
constructor(private templateSrv: TemplateSrv = getTemplateSrv()) {}
init(settingsMapByName: Record<string, DataSourceInstanceSettings>, defaultName: string) {
this.datasources = {};
@ -164,11 +158,15 @@ export class DatasourceSrv implements DataSourceService {
// If there is only one constructor argument it is instanceSettings
const useAngular = dsPlugin.DataSourceClass.length !== 1;
const instance: DataSourceApi = useAngular
? this.$injector.instantiate(dsPlugin.DataSourceClass, {
instanceSettings: dsConfig,
})
: new dsPlugin.DataSourceClass(dsConfig);
let instance: DataSourceApi<any, any>;
if (useAngular) {
instance = (await getAngularInjector()).instantiate(dsPlugin.DataSourceClass, {
instanceSettings: dsConfig,
});
} else {
instance = new dsPlugin.DataSourceClass(dsConfig);
}
instance.components = dsPlugin.components;
instance.meta = dsConfig.meta;
@ -178,9 +176,7 @@ export class DatasourceSrv implements DataSourceService {
this.datasources[instance.uid] = instance;
return instance;
} catch (err) {
if (this.$rootScope) {
this.$rootScope.appEvent(AppEvents.alertError, [dsConfig.name + ' plugin failed', err.toString()]);
}
appEvents.emit(AppEvents.alertError, [dsConfig.name + ' plugin failed', err.toString()]);
return Promise.reject({ message: `Datasource: ${key} was not found` });
}
}
@ -321,5 +317,4 @@ export const getDatasourceSrv = (): DatasourceSrv => {
return getDataSourceService() as DatasourceSrv;
};
coreModule.service('datasourceSrv', DatasourceSrv);
export default DatasourceSrv;

View File

@ -8,7 +8,7 @@ import { DataSourceApi, PanelEvents } from '@grafana/data';
import { importDataSourcePlugin, importAppPlugin } from './plugin_loader';
import { importPanelPlugin } from './importPanelPlugin';
import DatasourceSrv from './datasource_srv';
import { GrafanaRootScope } from 'app/routes/GrafanaCtrl';
import { GrafanaRootScope } from 'app/angular/GrafanaCtrl';
/** @ngInject */
function pluginDirectiveLoader(

View File

@ -3,7 +3,7 @@ import { find } from 'lodash';
import { getPluginSettings } from './PluginSettingsCache';
import { PluginMeta, AppEvents } from '@grafana/data';
import { GrafanaRootScope } from 'app/routes/GrafanaCtrl';
import { GrafanaRootScope } from 'app/angular/GrafanaCtrl';
import { promiseToDigest } from '../../angular/promiseToDigest';
import { NavModelSrv } from 'app/angular/services/nav_model_srv';

View File

@ -37,7 +37,7 @@ jest.mock('../plugin_loader', () => ({
}));
describe('datasource_srv', () => {
const dataSourceSrv = new DatasourceSrv({} as any, {} as any, templateSrv);
const dataSourceSrv = new DatasourceSrv(templateSrv);
const dataSourceInit = {
mmm: {
type: 'test-db',

View File

@ -4,7 +4,7 @@ import { AnnotationsQueryRunner } from './AnnotationsQueryRunner';
import { AnnotationQueryRunnerOptions } from './types';
import { silenceConsoleOutput } from '../../../../../test/core/utils/silenceConsoleOutput';
import * as store from '../../../../store/store';
import * as annotationsSrv from '../../../annotations/annotations_srv';
import * as annotationsSrv from '../../../annotations/executeAnnotationQuery';
import { Observable, of, throwError } from 'rxjs';
import { toAsyncOfResult } from './testHelpers';

View File

@ -4,7 +4,7 @@ import { AnnotationEvent, DataSourceApi } from '@grafana/data';
import { AnnotationQueryRunner, AnnotationQueryRunnerOptions } from './types';
import { PanelModel } from '../../../dashboard/state';
import { executeAnnotationQuery } from '../../../annotations/annotations_srv';
import { executeAnnotationQuery } from '../../../annotations/executeAnnotationQuery';
import { handleAnnotationQueryRunnerError } from './utils';
export class AnnotationsQueryRunner implements AnnotationQueryRunner {

View File

@ -2,7 +2,7 @@ import { Subject, throwError } from 'rxjs';
import { setDataSourceSrv } from '@grafana/runtime';
import { AnnotationsWorker } from './AnnotationsWorker';
import * as annotationsSrv from '../../../annotations/annotations_srv';
import * as annotationsSrv from '../../../annotations/executeAnnotationQuery';
import { getDefaultOptions, LEGACY_DS_NAME, NEXT_GEN_DS_NAME, toAsyncOfResult } from './testHelpers';
import { silenceConsoleOutput } from '../../../../../test/core/utils/silenceConsoleOutput';
import { createDashboardQueryRunner, setDashboardQueryRunnerFactory } from './DashboardQueryRunner';

View File

@ -3,7 +3,7 @@ import { delay } from 'rxjs/operators';
import { setDataSourceSrv } from '@grafana/runtime';
import { AlertState, AlertStateInfo } from '@grafana/data';
import * as annotationsSrv from '../../../annotations/annotations_srv';
import * as annotationsSrv from '../../../annotations/executeAnnotationQuery';
import { getDefaultOptions, LEGACY_DS_NAME, NEXT_GEN_DS_NAME, toAsyncOfResult } from './testHelpers';
import { backendSrv } from '../../../../core/services/backend_srv';
import { DashboardQueryRunner, DashboardQueryRunnerResult } from './types';

View File

@ -1,7 +1,7 @@
import React from 'react';
import { DebugSection } from './DebugSection';
import { mount } from 'enzyme';
import { getLinkSrv, LinkService, LinkSrv, setLinkSrv } from '../../../../angular/panel/panellinks/link_srv';
import { getLinkSrv, LinkService, LinkSrv, setLinkSrv } from '../../../../features/panel/panellinks/link_srv';
import { dateTime } from '@grafana/data';
// We do not need more here and TimeSrv is hard to setup fully.

View File

@ -1,8 +1,8 @@
import { isString, escape } from 'lodash';
import $ from 'jquery';
import coreModule from 'app/angular/core_module';
import alertDef from '../alerting/state/alertDef';
import { DashboardSrv } from '../dashboard/services/DashboardSrv';
import alertDef from 'app/features/alerting/state/alertDef';
import { DashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
import { ContextSrv } from 'app/core/services/context_srv';
/** @ngInject */

View File

@ -2,8 +2,8 @@ import { cloneDeep, isNumber } from 'lodash';
import { coreModule } from 'app/angular/core_module';
import { AnnotationEvent, dateTime } from '@grafana/data';
import { MetricsPanelCtrl } from 'app/angular/panel/metrics_panel_ctrl';
import { deleteAnnotation, saveAnnotation, updateAnnotation } from './api';
import { getDashboardQueryRunner } from '../query/state/DashboardQueryRunner/DashboardQueryRunner';
import { deleteAnnotation, saveAnnotation, updateAnnotation } from '../../../features/annotations/api';
import { getDashboardQueryRunner } from '../../../features/query/state/DashboardQueryRunner/DashboardQueryRunner';
export class EventEditorCtrl {
// @ts-ignore initialized through Angular not constructor

View File

@ -16,7 +16,7 @@ import { coreModule } from 'app/angular/core_module';
import GraphTooltip from './graph_tooltip';
import { ThresholdManager } from './threshold_manager';
import { TimeRegionManager } from './time_region_manager';
import { EventManager } from 'app/features/annotations/all';
import { EventManager } from './event_manager';
import { convertToHistogramData } from './histogram';
import { alignYLevel } from './align_yaxes';
import config from 'app/core/config';
@ -52,7 +52,7 @@ import {
import { GraphContextMenuCtrl } from './GraphContextMenuCtrl';
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { ContextSrv } from 'app/core/services/context_srv';
import { getFieldLinksSupplier } from 'app/angular/panel/panellinks/linkSuppliers';
import { getFieldLinksSupplier } from 'app/features/panel/panellinks/linkSuppliers';
import { DashboardModel } from '../../../features/dashboard/state';
import { isLegacyGraphHoverEvent } from './utils';

View File

@ -2,6 +2,8 @@ import './graph';
import './series_overrides_ctrl';
import './thresholds_form';
import './time_regions_form';
import './annotation_tooltip';
import './event_editor';
import template from './template';
import { defaults, find, without } from 'lodash';

View File

@ -9,7 +9,7 @@ import { graphDirective, GraphElement } from '../graph';
import { dateTime, EventBusSrv } from '@grafana/data';
import { DashboardModel } from '../../../../features/dashboard/state';
jest.mock('app/features/annotations/all', () => ({
jest.mock('../event_manager', () => ({
EventManager: () => {
return {
on: () => {},

View File

@ -4,7 +4,7 @@ import config from 'app/core/config';
import { angularMocks, sinon } from '../lib/common';
import { PanelModel } from 'app/features/dashboard/state/PanelModel';
import { RawTimeRange, PanelPluginMeta, dateMath } from '@grafana/data';
import { GrafanaRootScope } from 'app/routes/GrafanaCtrl';
import { GrafanaRootScope } from 'app/angular/GrafanaCtrl';
export function ControllerTestContext(this: any) {
const self = this;