mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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:
@@ -15,6 +15,7 @@ import { GrafanaRoute } from './core/navigation/GrafanaRoute';
|
|||||||
import { AppNotificationList } from './core/components/AppNotifications/AppNotificationList';
|
import { AppNotificationList } from './core/components/AppNotifications/AppNotificationList';
|
||||||
import { SearchWrapper } from 'app/features/search';
|
import { SearchWrapper } from 'app/features/search';
|
||||||
import { LiveConnectionWarning } from './features/live/LiveConnectionWarning';
|
import { LiveConnectionWarning } from './features/live/LiveConnectionWarning';
|
||||||
|
import { AngularRoot } from './angular/AngularRoot';
|
||||||
|
|
||||||
interface AppWrapperProps {
|
interface AppWrapperProps {
|
||||||
app: GrafanaApp;
|
app: GrafanaApp;
|
||||||
@@ -57,6 +58,7 @@ export class AppWrapper extends React.Component<AppWrapperProps, AppWrapperState
|
|||||||
bootstrapNgApp() {
|
bootstrapNgApp() {
|
||||||
const injector = this.props.app.angularApp.bootstrap();
|
const injector = this.props.app.angularApp.bootstrap();
|
||||||
this.setState({ ngInjector: injector });
|
this.setState({ ngInjector: injector });
|
||||||
|
$('.preloader').remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
renderRoute = (route: RouteDescriptor) => {
|
renderRoute = (route: RouteDescriptor) => {
|
||||||
@@ -89,8 +91,6 @@ export class AppWrapper extends React.Component<AppWrapperProps, AppWrapperState
|
|||||||
render() {
|
render() {
|
||||||
navigationLogger('AppWrapper', false, 'rendering');
|
navigationLogger('AppWrapper', false, 'rendering');
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
const appSeed = `<grafana-app ng-cloak></app-notifications-list></grafana-app>`;
|
|
||||||
const newNavigationEnabled = config.featureToggles.newNavigation;
|
const newNavigationEnabled = config.featureToggles.newNavigation;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -108,17 +108,10 @@ export class AppWrapper extends React.Component<AppWrapperProps, AppWrapperState
|
|||||||
<Banner key={index.toString()} />
|
<Banner key={index.toString()} />
|
||||||
))}
|
))}
|
||||||
|
|
||||||
<div
|
<AngularRoot ref={this.container} />
|
||||||
id="ngRoot"
|
|
||||||
ref={this.container}
|
|
||||||
dangerouslySetInnerHTML={{
|
|
||||||
__html: appSeed,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<AppNotificationList />
|
<AppNotificationList />
|
||||||
<SearchWrapper />
|
<SearchWrapper />
|
||||||
{this.state.ngInjector && this.container && this.renderRoutes()}
|
{this.state.ngInjector && this.renderRoutes()}
|
||||||
{bodyRenderHooks.map((Hook, index) => (
|
{bodyRenderHooks.map((Hook, index) => (
|
||||||
<Hook key={index.toString()} />
|
<Hook key={index.toString()} />
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -92,6 +92,9 @@ export class AngularApp {
|
|||||||
registerAngularDirectives();
|
registerAngularDirectives();
|
||||||
registerComponents();
|
registerComponents();
|
||||||
initAngularRoutingBridge();
|
initAngularRoutingBridge();
|
||||||
|
|
||||||
|
// disable tool tip animation
|
||||||
|
$.fn.tooltip.defaults.animation = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
useModule(module: angular.IModule) {
|
useModule(module: angular.IModule) {
|
||||||
|
|||||||
15
public/app/angular/AngularRoot.tsx
Normal file
15
public/app/angular/AngularRoot.tsx
Normal 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';
|
||||||
@@ -5,27 +5,16 @@ import $ from 'jquery';
|
|||||||
|
|
||||||
// Utils and servies
|
// Utils and servies
|
||||||
import { colors } from '@grafana/ui';
|
import { colors } from '@grafana/ui';
|
||||||
import {
|
import { setLegacyAngularInjector, setAppEvents, setAngularLoader } from '@grafana/runtime';
|
||||||
setDataSourceSrv,
|
|
||||||
setLegacyAngularInjector,
|
|
||||||
setLocationSrv,
|
|
||||||
locationService,
|
|
||||||
setAppEvents,
|
|
||||||
setAngularLoader,
|
|
||||||
} from '@grafana/runtime';
|
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
import coreModule from 'app/angular/core_module';
|
import coreModule from 'app/angular/core_module';
|
||||||
import { profiler } from 'app/core/profiler';
|
|
||||||
import appEvents from 'app/core/app_events';
|
import appEvents from 'app/core/app_events';
|
||||||
import { DatasourceSrv } from 'app/features/plugins/datasource_srv';
|
|
||||||
import { AngularLoader } from 'app/angular/services/AngularLoader';
|
import { AngularLoader } from 'app/angular/services/AngularLoader';
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import { CoreEvents, AppEventEmitter, AppEventConsumer } from 'app/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 { UtilSrv } from 'app/core/services/util_srv';
|
||||||
import { ContextSrv } from 'app/core/services/context_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 { IRootScopeService, IAngularEvent, auto } from 'angular';
|
||||||
import { AppEvent } from '@grafana/data';
|
import { AppEvent } from '@grafana/data';
|
||||||
import { initGrafanaLive } from 'app/features/live';
|
import { initGrafanaLive } from 'app/features/live';
|
||||||
@@ -39,22 +28,12 @@ export class GrafanaCtrl {
|
|||||||
utilSrv: UtilSrv,
|
utilSrv: UtilSrv,
|
||||||
$rootScope: GrafanaRootScope,
|
$rootScope: GrafanaRootScope,
|
||||||
contextSrv: ContextSrv,
|
contextSrv: ContextSrv,
|
||||||
linkSrv: LinkSrv,
|
|
||||||
datasourceSrv: DatasourceSrv,
|
|
||||||
dashboardSrv: DashboardSrv,
|
|
||||||
angularLoader: AngularLoader,
|
angularLoader: AngularLoader,
|
||||||
$injector: auto.IInjectorService
|
$injector: auto.IInjectorService
|
||||||
) {
|
) {
|
||||||
// make angular loader service available to react components
|
// make angular loader service available to react components
|
||||||
setAngularLoader(angularLoader);
|
setAngularLoader(angularLoader);
|
||||||
setDataSourceSrv(datasourceSrv);
|
|
||||||
setLinkSrv(linkSrv);
|
|
||||||
setDashboardSrv(dashboardSrv);
|
|
||||||
setLegacyAngularInjector($injector);
|
setLegacyAngularInjector($injector);
|
||||||
|
|
||||||
datasourceSrv.init(config.datasources, config.defaultDatasource);
|
|
||||||
|
|
||||||
setLocationSrv(locationService);
|
|
||||||
setAppEvents(appEvents);
|
setAppEvents(appEvents);
|
||||||
|
|
||||||
initGrafanaLive();
|
initGrafanaLive();
|
||||||
@@ -63,8 +42,6 @@ export class GrafanaCtrl {
|
|||||||
$scope.contextSrv = contextSrv;
|
$scope.contextSrv = contextSrv;
|
||||||
$scope.appSubUrl = config.appSubUrl;
|
$scope.appSubUrl = config.appSubUrl;
|
||||||
$scope._ = _;
|
$scope._ = _;
|
||||||
|
|
||||||
profiler.init(config, $rootScope);
|
|
||||||
utilSrv.init();
|
utilSrv.init();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -116,8 +93,6 @@ export function grafanaAppDirective() {
|
|||||||
// see https://github.com/zenorocha/clipboard.js/issues/155
|
// see https://github.com/zenorocha/clipboard.js/issues/155
|
||||||
$.fn.modal.Constructor.prototype.enforceFocus = () => {};
|
$.fn.modal.Constructor.prototype.enforceFocus = () => {};
|
||||||
|
|
||||||
$('.preloader').remove();
|
|
||||||
|
|
||||||
appEvents.on(CoreEvents.toggleSidemenuHidden, () => {
|
appEvents.on(CoreEvents.toggleSidemenuHidden, () => {
|
||||||
body.toggleClass('sidemenu-hidden');
|
body.toggleClass('sidemenu-hidden');
|
||||||
});
|
});
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import angular from 'angular';
|
import angular from 'angular';
|
||||||
import coreModule from './core_module';
|
import coreModule from './core_module';
|
||||||
import { GrafanaRootScope } from 'app/routes/GrafanaCtrl';
|
import { GrafanaRootScope } from 'app/angular/GrafanaCtrl';
|
||||||
|
|
||||||
export class DeltaCtrl {
|
export class DeltaCtrl {
|
||||||
observer: any;
|
observer: any;
|
||||||
|
|||||||
@@ -31,5 +31,6 @@ import './components/info_popover';
|
|||||||
import './components/spectrum_picker';
|
import './components/spectrum_picker';
|
||||||
import './components/code_editor/code_editor';
|
import './components/code_editor/code_editor';
|
||||||
import './components/sql_part/sql_part_editor';
|
import './components/sql_part/sql_part_editor';
|
||||||
|
import './GrafanaCtrl';
|
||||||
|
|
||||||
export { AngularApp } from './AngularApp';
|
export { AngularApp } from './AngularApp';
|
||||||
|
|||||||
23
public/app/angular/lazyBootAngular.ts
Normal file
23
public/app/angular/lazyBootAngular.ts
Normal 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;
|
||||||
|
}
|
||||||
@@ -1,8 +1,15 @@
|
|||||||
import { getBackendSrv } from '@grafana/runtime';
|
import { getBackendSrv, getDataSourceSrv } from '@grafana/runtime';
|
||||||
import { contextSrv } from 'app/core/core';
|
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 coreModule from './core_module';
|
||||||
|
import { AnnotationsSrv } from './services/annotations_srv';
|
||||||
|
|
||||||
export function registerComponents() {
|
export function registerComponents() {
|
||||||
coreModule.factory('backendSrv', () => getBackendSrv());
|
coreModule.factory('backendSrv', () => getBackendSrv());
|
||||||
coreModule.factory('contextSrv', () => contextSrv);
|
coreModule.factory('contextSrv', () => contextSrv);
|
||||||
|
coreModule.factory('dashboardSrv', () => getDashboardSrv());
|
||||||
|
coreModule.factory('datasourceSrv', () => getDataSourceSrv());
|
||||||
|
coreModule.factory('linkSrv', () => getLinkSrv());
|
||||||
|
coreModule.service('annotationsSrv', AnnotationsSrv);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import coreModule from 'app/angular/core_module';
|
|||||||
import { assign } from 'lodash';
|
import { assign } from 'lodash';
|
||||||
|
|
||||||
import { AngularComponent, AngularLoader as AngularLoaderInterface } from '@grafana/runtime';
|
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 {
|
export class AngularLoader implements AngularLoaderInterface {
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { AnnotationsSrv } from '../annotations_srv';
|
import { AnnotationsSrv } from './annotations_srv';
|
||||||
|
|
||||||
describe('AnnotationsSrv', () => {
|
describe('AnnotationsSrv', () => {
|
||||||
const annotationsSrv = new AnnotationsSrv();
|
const annotationsSrv = new AnnotationsSrv();
|
||||||
@@ -1,26 +1,9 @@
|
|||||||
import { cloneDeep } from 'lodash';
|
import { cloneDeep } from 'lodash';
|
||||||
import { Observable, of } from 'rxjs';
|
import { AnnotationEvent, deprecationWarning } from '@grafana/data';
|
||||||
import { map, mergeMap } from 'rxjs/operators';
|
|
||||||
import {
|
|
||||||
AnnotationEvent,
|
|
||||||
CoreApp,
|
|
||||||
DataQueryRequest,
|
|
||||||
DataSourceApi,
|
|
||||||
deprecationWarning,
|
|
||||||
rangeUtil,
|
|
||||||
ScopedVars,
|
|
||||||
} from '@grafana/data';
|
|
||||||
|
|
||||||
import coreModule from 'app/angular/core_module';
|
import { deleteAnnotation, saveAnnotation, updateAnnotation } from 'app/features/annotations/api';
|
||||||
import { AnnotationQueryOptions, AnnotationQueryResponse } from './types';
|
import { AnnotationQueryOptions } from 'app/features/annotations/types';
|
||||||
import { standardAnnotationSupport } from './standardAnnotationSupport';
|
|
||||||
import { runRequest } from '../query/state/runRequest';
|
|
||||||
import { deleteAnnotation, saveAnnotation, updateAnnotation } from './api';
|
|
||||||
|
|
||||||
let counter = 100;
|
|
||||||
function getNextRequestId() {
|
|
||||||
return 'AQ' + counter++;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* @deprecated AnnotationsSrv is deprecated in favor of DashboardQueryRunner
|
* @deprecated AnnotationsSrv is deprecated in favor of DashboardQueryRunner
|
||||||
*/
|
*/
|
||||||
@@ -102,67 +85,3 @@ export class AnnotationsSrv {
|
|||||||
return results;
|
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);
|
|
||||||
@@ -2,7 +2,7 @@ import { extend } from 'lodash';
|
|||||||
import coreModule from 'app/angular/core_module';
|
import coreModule from 'app/angular/core_module';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import Drop from 'tether-drop';
|
import Drop from 'tether-drop';
|
||||||
import { GrafanaRootScope } from 'app/routes/GrafanaCtrl';
|
import { GrafanaRootScope } from 'app/angular/GrafanaCtrl';
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
function popoverSrv(this: any, $compile: any, $rootScope: GrafanaRootScope, $timeout: any) {
|
function popoverSrv(this: any, $compile: any, $rootScope: GrafanaRootScope, $timeout: any) {
|
||||||
|
|||||||
@@ -27,16 +27,18 @@ import {
|
|||||||
import { arrayMove } from 'app/core/utils/arrayMove';
|
import { arrayMove } from 'app/core/utils/arrayMove';
|
||||||
import { importPluginModule } from 'app/features/plugins/plugin_loader';
|
import { importPluginModule } from 'app/features/plugins/plugin_loader';
|
||||||
import {
|
import {
|
||||||
|
locationService,
|
||||||
registerEchoBackend,
|
registerEchoBackend,
|
||||||
setBackendSrv,
|
setBackendSrv,
|
||||||
|
setDataSourceSrv,
|
||||||
setEchoSrv,
|
setEchoSrv,
|
||||||
|
setLocationSrv,
|
||||||
setPanelRenderer,
|
setPanelRenderer,
|
||||||
setQueryRunnerFactory,
|
setQueryRunnerFactory,
|
||||||
} from '@grafana/runtime';
|
} from '@grafana/runtime';
|
||||||
import { Echo } from './core/services/echo/Echo';
|
import { Echo } from './core/services/echo/Echo';
|
||||||
import { reportPerformance } from './core/services/echo/EchoSrv';
|
import { reportPerformance } from './core/services/echo/EchoSrv';
|
||||||
import { PerformanceBackend } from './core/services/echo/backends/PerformanceBackend';
|
import { PerformanceBackend } from './core/services/echo/backends/PerformanceBackend';
|
||||||
import 'app/routes/GrafanaCtrl';
|
|
||||||
import 'app/features/all';
|
import 'app/features/all';
|
||||||
import { getScrollbarWidth, getStandardFieldConfigs } from '@grafana/ui';
|
import { getScrollbarWidth, getStandardFieldConfigs } from '@grafana/ui';
|
||||||
import { getDefaultVariableAdapters, variableAdapters } from './features/variables/adapters';
|
import { getDefaultVariableAdapters, variableAdapters } from './features/variables/adapters';
|
||||||
@@ -47,7 +49,6 @@ import { setVariableQueryRunner, VariableQueryRunner } from './features/variable
|
|||||||
import { configureStore } from './store/configureStore';
|
import { configureStore } from './store/configureStore';
|
||||||
import { AppWrapper } from './AppWrapper';
|
import { AppWrapper } from './AppWrapper';
|
||||||
import { interceptLinkClicks } from './core/navigation/patch/interceptLinkClicks';
|
import { interceptLinkClicks } from './core/navigation/patch/interceptLinkClicks';
|
||||||
import { AngularApp } from './angular';
|
|
||||||
import { PanelRenderer } from './features/panel/components/PanelRenderer';
|
import { PanelRenderer } from './features/panel/components/PanelRenderer';
|
||||||
import { QueryRunner } from './features/query/state/QueryRunner';
|
import { QueryRunner } from './features/query/state/QueryRunner';
|
||||||
import { getTimeSrv } from './features/dashboard/services/TimeSrv';
|
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 { RudderstackBackend } from './core/services/echo/backends/analytics/RudderstackBackend';
|
||||||
import { getAllOptionEditors } from './core/components/editors/registry';
|
import { getAllOptionEditors } from './core/components/editors/registry';
|
||||||
import { backendSrv } from './core/services/backend_srv';
|
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
|
// add move to lodash for backward compatabilty with plugins
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@@ -89,6 +92,7 @@ export class GrafanaApp {
|
|||||||
setLocale(config.bootData.user.locale);
|
setLocale(config.bootData.user.locale);
|
||||||
setWeekStart(config.bootData.user.weekStart);
|
setWeekStart(config.bootData.user.weekStart);
|
||||||
setPanelRenderer(PanelRenderer);
|
setPanelRenderer(PanelRenderer);
|
||||||
|
setLocationSrv(locationService);
|
||||||
setTimeZoneResolver(() => config.bootData.user.timezone);
|
setTimeZoneResolver(() => config.bootData.user.timezone);
|
||||||
// Important that extensions are initialized before store
|
// Important that extensions are initialized before store
|
||||||
initExtensions();
|
initExtensions();
|
||||||
@@ -112,9 +116,12 @@ export class GrafanaApp {
|
|||||||
// intercept anchor clicks and forward it to custom history instead of relying on browser's history
|
// intercept anchor clicks and forward it to custom history instead of relying on browser's history
|
||||||
document.addEventListener('click', interceptLinkClicks);
|
document.addEventListener('click', interceptLinkClicks);
|
||||||
|
|
||||||
// disable tool tip animation
|
// Init DataSourceSrv
|
||||||
$.fn.tooltip.defaults.animation = false;
|
const dataSourceSrv = new DatasourceSrv();
|
||||||
|
dataSourceSrv.init(config.datasources, config.defaultDatasource);
|
||||||
|
setDataSourceSrv(dataSourceSrv);
|
||||||
|
|
||||||
|
// Init angular
|
||||||
this.angularApp.init();
|
this.angularApp.init();
|
||||||
|
|
||||||
// Preload selected app plugins
|
// Preload selected app plugins
|
||||||
|
|||||||
@@ -1,19 +1,6 @@
|
|||||||
import { GrafanaRootScope } from 'app/routes/GrafanaCtrl';
|
|
||||||
|
|
||||||
export class Profiler {
|
export class Profiler {
|
||||||
panelsRendered = 0;
|
panelsRendered = 0;
|
||||||
enabled?: boolean = undefined;
|
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() {
|
renderingCompleted() {
|
||||||
// add render counter to root scope
|
// add render counter to root scope
|
||||||
@@ -22,7 +9,7 @@ export class Profiler {
|
|||||||
|
|
||||||
// this window variable is used by backend rendering tools to know
|
// this window variable is used by backend rendering tools to know
|
||||||
// all panels have completed rendering
|
// all panels have completed rendering
|
||||||
this.window.panelsRendered = this.panelsRendered;
|
(window as any).panelsRendered = this.panelsRendered;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ import ReactDOM from 'react-dom';
|
|||||||
|
|
||||||
import coreModule from 'app/angular/core_module';
|
import coreModule from 'app/angular/core_module';
|
||||||
import appEvents from 'app/core/app_events';
|
import appEvents from 'app/core/app_events';
|
||||||
|
import { GrafanaRootScope } from 'app/angular/GrafanaCtrl';
|
||||||
import { GrafanaRootScope } from 'app/routes/GrafanaCtrl';
|
|
||||||
import { AngularModalProxy } from '../components/modals/AngularModalProxy';
|
import { AngularModalProxy } from '../components/modals/AngularModalProxy';
|
||||||
import { provideTheme } from '../utils/ConfigProvider';
|
import { provideTheme } from '../utils/ConfigProvider';
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import './annotations/all';
|
|
||||||
import './plugins/all';
|
import './plugins/all';
|
||||||
import './dashboard';
|
import './dashboard';
|
||||||
import './manage-dashboards';
|
import './manage-dashboards';
|
||||||
|
|||||||
@@ -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 };
|
|
||||||
@@ -7,7 +7,7 @@ import { Button, Icon, IconName, Spinner } from '@grafana/ui';
|
|||||||
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
||||||
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||||
import { standardAnnotationSupport } from '../standardAnnotationSupport';
|
import { standardAnnotationSupport } from '../standardAnnotationSupport';
|
||||||
import { executeAnnotationQuery } from '../annotations_srv';
|
import { executeAnnotationQuery } from '../executeAnnotationQuery';
|
||||||
import { PanelModel } from 'app/features/dashboard/state';
|
import { PanelModel } from 'app/features/dashboard/state';
|
||||||
import { AnnotationQueryResponse } from '../types';
|
import { AnnotationQueryResponse } from '../types';
|
||||||
import { AnnotationFieldMapper } from './AnnotationResultMapper';
|
import { AnnotationFieldMapper } from './AnnotationResultMapper';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { dedupAnnotations } from '../events_processing';
|
import { dedupAnnotations } from './events_processing';
|
||||||
|
|
||||||
describe('Annotations deduplication', () => {
|
describe('Annotations deduplication', () => {
|
||||||
it('should remove duplicated annotations', () => {
|
it('should remove duplicated annotations', () => {
|
||||||
74
public/app/features/annotations/executeAnnotationQuery.ts
Normal file
74
public/app/features/annotations/executeAnnotationQuery.ts
Normal 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 })));
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@ import { OptionPaneRenderProps } from './types';
|
|||||||
import { OptionsPaneItemDescriptor } from './OptionsPaneItemDescriptor';
|
import { OptionsPaneItemDescriptor } from './OptionsPaneItemDescriptor';
|
||||||
import { OptionsPaneCategoryDescriptor } from './OptionsPaneCategoryDescriptor';
|
import { OptionsPaneCategoryDescriptor } from './OptionsPaneCategoryDescriptor';
|
||||||
import { DynamicConfigValueEditor } from './DynamicConfigValueEditor';
|
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 { OverrideCategoryTitle } from './OverrideCategoryTitle';
|
||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { DataLinksInlineEditor, Input, RadioButtonGroup, Select, Switch, TextArea } from '@grafana/ui';
|
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 React from 'react';
|
||||||
import { RepeatRowSelect } from '../RepeatRowSelect/RepeatRowSelect';
|
import { RepeatRowSelect } from '../RepeatRowSelect/RepeatRowSelect';
|
||||||
import { OptionsPaneItemDescriptor } from './OptionsPaneItemDescriptor';
|
import { OptionsPaneItemDescriptor } from './OptionsPaneItemDescriptor';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { StandardEditorContext, VariableSuggestionsScope } from '@grafana/data';
|
import { StandardEditorContext, VariableSuggestionsScope } from '@grafana/data';
|
||||||
import { get as lodashGet } from 'lodash';
|
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 { OptionPaneRenderProps } from './types';
|
||||||
import { updateDefaultFieldConfigValue, setOptionImmutably } from './utils';
|
import { updateDefaultFieldConfigValue, setOptionImmutably } from './utils';
|
||||||
import { OptionsPaneItemDescriptor } from './OptionsPaneItemDescriptor';
|
import { OptionsPaneItemDescriptor } from './OptionsPaneItemDescriptor';
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { FC } from 'react';
|
|||||||
import { Icon, IconName, Tooltip, useForceUpdate } from '@grafana/ui';
|
import { Icon, IconName, Tooltip, useForceUpdate } from '@grafana/ui';
|
||||||
import { sanitizeUrl } from '@grafana/data/src/text/sanitize';
|
import { sanitizeUrl } from '@grafana/data/src/text/sanitize';
|
||||||
import { DashboardLinksDashboard } from './DashboardLinksDashboard';
|
import { DashboardLinksDashboard } from './DashboardLinksDashboard';
|
||||||
import { getLinkSrv } from '../../../../angular/panel/panellinks/link_srv';
|
import { getLinkSrv } from '../../../panel/panellinks/link_srv';
|
||||||
|
|
||||||
import { DashboardModel } from '../../state';
|
import { DashboardModel } from '../../state';
|
||||||
import { DashboardLink } from '../../state/DashboardModel';
|
import { DashboardLink } from '../../state/DashboardModel';
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { useRef, useState, useLayoutEffect } from 'react';
|
|||||||
import { Icon, ToolbarButton, Tooltip, useStyles2 } from '@grafana/ui';
|
import { Icon, ToolbarButton, Tooltip, useStyles2 } from '@grafana/ui';
|
||||||
import { sanitize, sanitizeUrl } from '@grafana/data/src/text/sanitize';
|
import { sanitize, sanitizeUrl } from '@grafana/data/src/text/sanitize';
|
||||||
import { getBackendSrv } from 'app/core/services/backend_srv';
|
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 { DashboardLink } from '../../state/DashboardModel';
|
||||||
import { DashboardSearchHit } from 'app/features/search/types';
|
import { DashboardSearchHit } from 'app/features/search/types';
|
||||||
import { selectors } from '@grafana/e2e-selectors';
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { isNumber } from 'lodash';
|
import { isNumber } from 'lodash';
|
||||||
import coreModule from 'app/angular/core_module';
|
|
||||||
import { DashboardModel } from '../../state/DashboardModel';
|
import { DashboardModel } from '../../state/DashboardModel';
|
||||||
import { getBackendSrv } from '@grafana/runtime';
|
import { getBackendSrv } from '@grafana/runtime';
|
||||||
|
|
||||||
@@ -45,5 +44,3 @@ export class HistorySrv {
|
|||||||
|
|
||||||
const historySrv = new HistorySrv();
|
const historySrv = new HistorySrv();
|
||||||
export { historySrv };
|
export { historySrv };
|
||||||
|
|
||||||
coreModule.service('historySrv', HistorySrv);
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { selectors } from '@grafana/e2e-selectors';
|
|||||||
import PanelHeaderCorner from './PanelHeaderCorner';
|
import PanelHeaderCorner from './PanelHeaderCorner';
|
||||||
import { DashboardModel } from 'app/features/dashboard/state/DashboardModel';
|
import { DashboardModel } from 'app/features/dashboard/state/DashboardModel';
|
||||||
import { PanelModel } from 'app/features/dashboard/state/PanelModel';
|
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 { PanelHeaderNotices } from './PanelHeaderNotices';
|
||||||
import { PanelHeaderMenuTrigger } from './PanelHeaderMenuTrigger';
|
import { PanelHeaderMenuTrigger } from './PanelHeaderMenuTrigger';
|
||||||
import { PanelHeaderLoadingIndicator } from './PanelHeaderLoadingIndicator';
|
import { PanelHeaderLoadingIndicator } from './PanelHeaderLoadingIndicator';
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import coreModule from 'app/angular/core_module';
|
|
||||||
import { appEvents } from 'app/core/app_events';
|
import { appEvents } from 'app/core/app_events';
|
||||||
import { DashboardModel } from '../state/DashboardModel';
|
import { DashboardModel } from '../state/DashboardModel';
|
||||||
import { removePanel } from '../utils/panel';
|
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
|
// Code below is to export the service to React components
|
||||||
//
|
//
|
||||||
@@ -80,5 +77,8 @@ export function setDashboardSrv(instance: DashboardSrv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getDashboardSrv(): DashboardSrv {
|
export function getDashboardSrv(): DashboardSrv {
|
||||||
|
if (!singletonInstance) {
|
||||||
|
singletonInstance = new DashboardSrv();
|
||||||
|
}
|
||||||
return singletonInstance;
|
return singletonInstance;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { setDataSourceSrv, setTemplateSrv } from '@grafana/runtime';
|
|||||||
import { createSpanLinkFactory } from './createSpanLink';
|
import { createSpanLinkFactory } from './createSpanLink';
|
||||||
import { TraceSpan } from '@jaegertracing/jaeger-ui-components';
|
import { TraceSpan } from '@jaegertracing/jaeger-ui-components';
|
||||||
import { TraceToLogsOptions } from '../../../core/components/TraceToLogsSettings';
|
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';
|
import { TemplateSrv } from '../../templating/template_srv';
|
||||||
|
|
||||||
describe('createSpanLinkFactory', () => {
|
describe('createSpanLinkFactory', () => {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
LinkModel,
|
LinkModel,
|
||||||
TimeRange,
|
TimeRange,
|
||||||
} from '@grafana/data';
|
} 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';
|
import { setContextSrv } from '../../../core/services/context_srv';
|
||||||
|
|
||||||
describe('getFieldLinksForExplore', () => {
|
describe('getFieldLinksForExplore', () => {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
SplitOpen,
|
SplitOpen,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { getTemplateSrv } from '@grafana/runtime';
|
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';
|
import { contextSrv } from 'app/core/services/context_srv';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { getFieldLinksSupplier } from './linkSuppliers';
|
import { getFieldLinksSupplier } from './linkSuppliers';
|
||||||
import { applyFieldOverrides, createTheme, DataFrameView, dateTime, FieldDisplay, toDataFrame } from '@grafana/data';
|
import { applyFieldOverrides, createTheme, DataFrameView, dateTime, FieldDisplay, toDataFrame } from '@grafana/data';
|
||||||
import { getLinkSrv, LinkService, LinkSrv, setLinkSrv } from './link_srv';
|
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.
|
// We do not need more here and TimeSrv is hard to setup fully.
|
||||||
jest.mock('app/features/dashboard/services/TimeSrv', () => ({
|
jest.mock('app/features/dashboard/services/TimeSrv', () => ({
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
import { chain } from 'lodash';
|
import { chain } from 'lodash';
|
||||||
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||||
import { getTemplateSrv } from '@grafana/runtime';
|
import { getTemplateSrv } from '@grafana/runtime';
|
||||||
import coreModule from 'app/angular/core_module';
|
|
||||||
import { getConfig } from 'app/core/config';
|
import { getConfig } from 'app/core/config';
|
||||||
import {
|
import {
|
||||||
DataFrame,
|
DataFrame,
|
||||||
@@ -15,7 +14,6 @@ import {
|
|||||||
KeyValue,
|
KeyValue,
|
||||||
LinkModel,
|
LinkModel,
|
||||||
locationUtil,
|
locationUtil,
|
||||||
PanelPlugin,
|
|
||||||
ScopedVars,
|
ScopedVars,
|
||||||
textUtil,
|
textUtil,
|
||||||
urlUtil,
|
urlUtil,
|
||||||
@@ -23,7 +21,7 @@ import {
|
|||||||
VariableSuggestion,
|
VariableSuggestion,
|
||||||
VariableSuggestionsScope,
|
VariableSuggestionsScope,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { getVariablesUrlParams } from '../../../features/variables/getAllVariableValuesForUrl';
|
import { getVariablesUrlParams } from '../../variables/getAllVariableValuesForUrl';
|
||||||
|
|
||||||
const timeRangeVars = [
|
const timeRangeVars = [
|
||||||
{
|
{
|
||||||
@@ -242,20 +240,6 @@ export const getCalculationValueDataLinksVariableSuggestions = (dataFrames: Data
|
|||||||
return [...seriesVars, ...fieldVars, ...valueVars, valueCalcVar, ...getPanelLinksVariableSuggestions()];
|
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 {
|
export interface LinkService {
|
||||||
getDataLinkUIModel: <T>(link: DataLink, replaceVariables: InterpolateFunction | undefined, origin: T) => LinkModel<T>;
|
getDataLinkUIModel: <T>(link: DataLink, replaceVariables: InterpolateFunction | undefined, origin: T) => LinkModel<T>;
|
||||||
getAnchorInfo: (link: any) => any;
|
getAnchorInfo: (link: any) => any;
|
||||||
@@ -263,8 +247,6 @@ export interface LinkService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class LinkSrv implements LinkService {
|
export class LinkSrv implements LinkService {
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
getLinkUrl(link: any) {
|
getLinkUrl(link: any) {
|
||||||
let url = locationUtil.assureBaseUrl(getTemplateSrv().replace(link.url || ''));
|
let url = locationUtil.assureBaseUrl(getTemplateSrv().replace(link.url || ''));
|
||||||
let params: { [key: string]: any } = {};
|
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) {
|
export function setLinkSrv(srv: LinkService) {
|
||||||
singleton = srv;
|
singleton = srv;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLinkSrv(): LinkService {
|
export function getLinkSrv(): LinkService {
|
||||||
|
if (!singleton) {
|
||||||
|
singleton = new LinkSrv();
|
||||||
|
}
|
||||||
return singleton;
|
return singleton;
|
||||||
}
|
}
|
||||||
|
|
||||||
coreModule.service('linkSrv', LinkSrv);
|
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
// Libraries
|
|
||||||
import coreModule from 'app/angular/core_module';
|
|
||||||
// Services & Utils
|
// Services & Utils
|
||||||
import { importDataSourcePlugin } from './plugin_loader';
|
import { importDataSourcePlugin } from './plugin_loader';
|
||||||
import {
|
import {
|
||||||
@@ -7,6 +5,7 @@ import {
|
|||||||
DataSourceSrv as DataSourceService,
|
DataSourceSrv as DataSourceService,
|
||||||
getDataSourceSrv as getDataSourceService,
|
getDataSourceSrv as getDataSourceService,
|
||||||
TemplateSrv,
|
TemplateSrv,
|
||||||
|
getTemplateSrv,
|
||||||
} from '@grafana/runtime';
|
} from '@grafana/runtime';
|
||||||
// Types
|
// Types
|
||||||
import {
|
import {
|
||||||
@@ -17,8 +16,6 @@ import {
|
|||||||
DataSourceSelectItem,
|
DataSourceSelectItem,
|
||||||
ScopedVars,
|
ScopedVars,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { auto } from 'angular';
|
|
||||||
import { GrafanaRootScope } from 'app/routes/GrafanaCtrl';
|
|
||||||
// Pretend Datasource
|
// Pretend Datasource
|
||||||
import {
|
import {
|
||||||
dataSource as expressionDatasource,
|
dataSource as expressionDatasource,
|
||||||
@@ -27,6 +24,8 @@ import {
|
|||||||
} from 'app/features/expressions/ExpressionDatasource';
|
} from 'app/features/expressions/ExpressionDatasource';
|
||||||
import { DataSourceVariableModel } from '../variables/types';
|
import { DataSourceVariableModel } from '../variables/types';
|
||||||
import { ExpressionDatasourceRef } from '@grafana/runtime/src/utils/DataSourceWithBackend';
|
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 {
|
export class DatasourceSrv implements DataSourceService {
|
||||||
private datasources: Record<string, DataSourceApi> = {}; // UID
|
private datasources: Record<string, DataSourceApi> = {}; // UID
|
||||||
@@ -35,12 +34,7 @@ export class DatasourceSrv implements DataSourceService {
|
|||||||
private settingsMapById: Record<string, DataSourceInstanceSettings> = {};
|
private settingsMapById: Record<string, DataSourceInstanceSettings> = {};
|
||||||
private defaultName = ''; // actually UID
|
private defaultName = ''; // actually UID
|
||||||
|
|
||||||
/** @ngInject */
|
constructor(private templateSrv: TemplateSrv = getTemplateSrv()) {}
|
||||||
constructor(
|
|
||||||
private $injector: auto.IInjectorService,
|
|
||||||
private $rootScope: GrafanaRootScope,
|
|
||||||
private templateSrv: TemplateSrv
|
|
||||||
) {}
|
|
||||||
|
|
||||||
init(settingsMapByName: Record<string, DataSourceInstanceSettings>, defaultName: string) {
|
init(settingsMapByName: Record<string, DataSourceInstanceSettings>, defaultName: string) {
|
||||||
this.datasources = {};
|
this.datasources = {};
|
||||||
@@ -164,11 +158,15 @@ export class DatasourceSrv implements DataSourceService {
|
|||||||
|
|
||||||
// If there is only one constructor argument it is instanceSettings
|
// If there is only one constructor argument it is instanceSettings
|
||||||
const useAngular = dsPlugin.DataSourceClass.length !== 1;
|
const useAngular = dsPlugin.DataSourceClass.length !== 1;
|
||||||
const instance: DataSourceApi = useAngular
|
let instance: DataSourceApi<any, any>;
|
||||||
? this.$injector.instantiate(dsPlugin.DataSourceClass, {
|
|
||||||
instanceSettings: dsConfig,
|
if (useAngular) {
|
||||||
})
|
instance = (await getAngularInjector()).instantiate(dsPlugin.DataSourceClass, {
|
||||||
: new dsPlugin.DataSourceClass(dsConfig);
|
instanceSettings: dsConfig,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
instance = new dsPlugin.DataSourceClass(dsConfig);
|
||||||
|
}
|
||||||
|
|
||||||
instance.components = dsPlugin.components;
|
instance.components = dsPlugin.components;
|
||||||
instance.meta = dsConfig.meta;
|
instance.meta = dsConfig.meta;
|
||||||
@@ -178,9 +176,7 @@ export class DatasourceSrv implements DataSourceService {
|
|||||||
this.datasources[instance.uid] = instance;
|
this.datasources[instance.uid] = instance;
|
||||||
return instance;
|
return instance;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (this.$rootScope) {
|
appEvents.emit(AppEvents.alertError, [dsConfig.name + ' plugin failed', err.toString()]);
|
||||||
this.$rootScope.appEvent(AppEvents.alertError, [dsConfig.name + ' plugin failed', err.toString()]);
|
|
||||||
}
|
|
||||||
return Promise.reject({ message: `Datasource: ${key} was not found` });
|
return Promise.reject({ message: `Datasource: ${key} was not found` });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -321,5 +317,4 @@ export const getDatasourceSrv = (): DatasourceSrv => {
|
|||||||
return getDataSourceService() as DatasourceSrv;
|
return getDataSourceService() as DatasourceSrv;
|
||||||
};
|
};
|
||||||
|
|
||||||
coreModule.service('datasourceSrv', DatasourceSrv);
|
|
||||||
export default DatasourceSrv;
|
export default DatasourceSrv;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { DataSourceApi, PanelEvents } from '@grafana/data';
|
|||||||
import { importDataSourcePlugin, importAppPlugin } from './plugin_loader';
|
import { importDataSourcePlugin, importAppPlugin } from './plugin_loader';
|
||||||
import { importPanelPlugin } from './importPanelPlugin';
|
import { importPanelPlugin } from './importPanelPlugin';
|
||||||
import DatasourceSrv from './datasource_srv';
|
import DatasourceSrv from './datasource_srv';
|
||||||
import { GrafanaRootScope } from 'app/routes/GrafanaCtrl';
|
import { GrafanaRootScope } from 'app/angular/GrafanaCtrl';
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
function pluginDirectiveLoader(
|
function pluginDirectiveLoader(
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { find } from 'lodash';
|
|||||||
|
|
||||||
import { getPluginSettings } from './PluginSettingsCache';
|
import { getPluginSettings } from './PluginSettingsCache';
|
||||||
import { PluginMeta, AppEvents } from '@grafana/data';
|
import { PluginMeta, AppEvents } from '@grafana/data';
|
||||||
import { GrafanaRootScope } from 'app/routes/GrafanaCtrl';
|
import { GrafanaRootScope } from 'app/angular/GrafanaCtrl';
|
||||||
import { promiseToDigest } from '../../angular/promiseToDigest';
|
import { promiseToDigest } from '../../angular/promiseToDigest';
|
||||||
import { NavModelSrv } from 'app/angular/services/nav_model_srv';
|
import { NavModelSrv } from 'app/angular/services/nav_model_srv';
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ jest.mock('../plugin_loader', () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
describe('datasource_srv', () => {
|
describe('datasource_srv', () => {
|
||||||
const dataSourceSrv = new DatasourceSrv({} as any, {} as any, templateSrv);
|
const dataSourceSrv = new DatasourceSrv(templateSrv);
|
||||||
const dataSourceInit = {
|
const dataSourceInit = {
|
||||||
mmm: {
|
mmm: {
|
||||||
type: 'test-db',
|
type: 'test-db',
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { AnnotationsQueryRunner } from './AnnotationsQueryRunner';
|
|||||||
import { AnnotationQueryRunnerOptions } from './types';
|
import { AnnotationQueryRunnerOptions } from './types';
|
||||||
import { silenceConsoleOutput } from '../../../../../test/core/utils/silenceConsoleOutput';
|
import { silenceConsoleOutput } from '../../../../../test/core/utils/silenceConsoleOutput';
|
||||||
import * as store from '../../../../store/store';
|
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 { Observable, of, throwError } from 'rxjs';
|
||||||
import { toAsyncOfResult } from './testHelpers';
|
import { toAsyncOfResult } from './testHelpers';
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { AnnotationEvent, DataSourceApi } from '@grafana/data';
|
|||||||
|
|
||||||
import { AnnotationQueryRunner, AnnotationQueryRunnerOptions } from './types';
|
import { AnnotationQueryRunner, AnnotationQueryRunnerOptions } from './types';
|
||||||
import { PanelModel } from '../../../dashboard/state';
|
import { PanelModel } from '../../../dashboard/state';
|
||||||
import { executeAnnotationQuery } from '../../../annotations/annotations_srv';
|
import { executeAnnotationQuery } from '../../../annotations/executeAnnotationQuery';
|
||||||
import { handleAnnotationQueryRunnerError } from './utils';
|
import { handleAnnotationQueryRunnerError } from './utils';
|
||||||
|
|
||||||
export class AnnotationsQueryRunner implements AnnotationQueryRunner {
|
export class AnnotationsQueryRunner implements AnnotationQueryRunner {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Subject, throwError } from 'rxjs';
|
|||||||
import { setDataSourceSrv } from '@grafana/runtime';
|
import { setDataSourceSrv } from '@grafana/runtime';
|
||||||
|
|
||||||
import { AnnotationsWorker } from './AnnotationsWorker';
|
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 { getDefaultOptions, LEGACY_DS_NAME, NEXT_GEN_DS_NAME, toAsyncOfResult } from './testHelpers';
|
||||||
import { silenceConsoleOutput } from '../../../../../test/core/utils/silenceConsoleOutput';
|
import { silenceConsoleOutput } from '../../../../../test/core/utils/silenceConsoleOutput';
|
||||||
import { createDashboardQueryRunner, setDashboardQueryRunnerFactory } from './DashboardQueryRunner';
|
import { createDashboardQueryRunner, setDashboardQueryRunnerFactory } from './DashboardQueryRunner';
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { delay } from 'rxjs/operators';
|
|||||||
import { setDataSourceSrv } from '@grafana/runtime';
|
import { setDataSourceSrv } from '@grafana/runtime';
|
||||||
import { AlertState, AlertStateInfo } from '@grafana/data';
|
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 { getDefaultOptions, LEGACY_DS_NAME, NEXT_GEN_DS_NAME, toAsyncOfResult } from './testHelpers';
|
||||||
import { backendSrv } from '../../../../core/services/backend_srv';
|
import { backendSrv } from '../../../../core/services/backend_srv';
|
||||||
import { DashboardQueryRunner, DashboardQueryRunnerResult } from './types';
|
import { DashboardQueryRunner, DashboardQueryRunnerResult } from './types';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { DebugSection } from './DebugSection';
|
import { DebugSection } from './DebugSection';
|
||||||
import { mount } from 'enzyme';
|
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';
|
import { dateTime } from '@grafana/data';
|
||||||
|
|
||||||
// We do not need more here and TimeSrv is hard to setup fully.
|
// We do not need more here and TimeSrv is hard to setup fully.
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { isString, escape } from 'lodash';
|
import { isString, escape } from 'lodash';
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import coreModule from 'app/angular/core_module';
|
import coreModule from 'app/angular/core_module';
|
||||||
import alertDef from '../alerting/state/alertDef';
|
import alertDef from 'app/features/alerting/state/alertDef';
|
||||||
import { DashboardSrv } from '../dashboard/services/DashboardSrv';
|
import { DashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
||||||
import { ContextSrv } from 'app/core/services/context_srv';
|
import { ContextSrv } from 'app/core/services/context_srv';
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
@@ -2,8 +2,8 @@ import { cloneDeep, isNumber } from 'lodash';
|
|||||||
import { coreModule } from 'app/angular/core_module';
|
import { coreModule } from 'app/angular/core_module';
|
||||||
import { AnnotationEvent, dateTime } from '@grafana/data';
|
import { AnnotationEvent, dateTime } from '@grafana/data';
|
||||||
import { MetricsPanelCtrl } from 'app/angular/panel/metrics_panel_ctrl';
|
import { MetricsPanelCtrl } from 'app/angular/panel/metrics_panel_ctrl';
|
||||||
import { deleteAnnotation, saveAnnotation, updateAnnotation } from './api';
|
import { deleteAnnotation, saveAnnotation, updateAnnotation } from '../../../features/annotations/api';
|
||||||
import { getDashboardQueryRunner } from '../query/state/DashboardQueryRunner/DashboardQueryRunner';
|
import { getDashboardQueryRunner } from '../../../features/query/state/DashboardQueryRunner/DashboardQueryRunner';
|
||||||
|
|
||||||
export class EventEditorCtrl {
|
export class EventEditorCtrl {
|
||||||
// @ts-ignore initialized through Angular not constructor
|
// @ts-ignore initialized through Angular not constructor
|
||||||
@@ -16,7 +16,7 @@ import { coreModule } from 'app/angular/core_module';
|
|||||||
import GraphTooltip from './graph_tooltip';
|
import GraphTooltip from './graph_tooltip';
|
||||||
import { ThresholdManager } from './threshold_manager';
|
import { ThresholdManager } from './threshold_manager';
|
||||||
import { TimeRegionManager } from './time_region_manager';
|
import { TimeRegionManager } from './time_region_manager';
|
||||||
import { EventManager } from 'app/features/annotations/all';
|
import { EventManager } from './event_manager';
|
||||||
import { convertToHistogramData } from './histogram';
|
import { convertToHistogramData } from './histogram';
|
||||||
import { alignYLevel } from './align_yaxes';
|
import { alignYLevel } from './align_yaxes';
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
@@ -52,7 +52,7 @@ import {
|
|||||||
import { GraphContextMenuCtrl } from './GraphContextMenuCtrl';
|
import { GraphContextMenuCtrl } from './GraphContextMenuCtrl';
|
||||||
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
|
||||||
import { ContextSrv } from 'app/core/services/context_srv';
|
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 { DashboardModel } from '../../../features/dashboard/state';
|
||||||
import { isLegacyGraphHoverEvent } from './utils';
|
import { isLegacyGraphHoverEvent } from './utils';
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import './graph';
|
|||||||
import './series_overrides_ctrl';
|
import './series_overrides_ctrl';
|
||||||
import './thresholds_form';
|
import './thresholds_form';
|
||||||
import './time_regions_form';
|
import './time_regions_form';
|
||||||
|
import './annotation_tooltip';
|
||||||
|
import './event_editor';
|
||||||
|
|
||||||
import template from './template';
|
import template from './template';
|
||||||
import { defaults, find, without } from 'lodash';
|
import { defaults, find, without } from 'lodash';
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { graphDirective, GraphElement } from '../graph';
|
|||||||
import { dateTime, EventBusSrv } from '@grafana/data';
|
import { dateTime, EventBusSrv } from '@grafana/data';
|
||||||
import { DashboardModel } from '../../../../features/dashboard/state';
|
import { DashboardModel } from '../../../../features/dashboard/state';
|
||||||
|
|
||||||
jest.mock('app/features/annotations/all', () => ({
|
jest.mock('../event_manager', () => ({
|
||||||
EventManager: () => {
|
EventManager: () => {
|
||||||
return {
|
return {
|
||||||
on: () => {},
|
on: () => {},
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import config from 'app/core/config';
|
|||||||
import { angularMocks, sinon } from '../lib/common';
|
import { angularMocks, sinon } from '../lib/common';
|
||||||
import { PanelModel } from 'app/features/dashboard/state/PanelModel';
|
import { PanelModel } from 'app/features/dashboard/state/PanelModel';
|
||||||
import { RawTimeRange, PanelPluginMeta, dateMath } from '@grafana/data';
|
import { RawTimeRange, PanelPluginMeta, dateMath } from '@grafana/data';
|
||||||
import { GrafanaRootScope } from 'app/routes/GrafanaCtrl';
|
import { GrafanaRootScope } from 'app/angular/GrafanaCtrl';
|
||||||
|
|
||||||
export function ControllerTestContext(this: any) {
|
export function ControllerTestContext(this: any) {
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|||||||
Reference in New Issue
Block a user