diff --git a/public/app/plugins/datasource/grafana/components/AnnotationQueryEditor.test.tsx b/public/app/plugins/datasource/grafana/components/AnnotationQueryEditor.test.tsx index 6adca6ef35a..9402498a435 100644 --- a/public/app/plugins/datasource/grafana/components/AnnotationQueryEditor.test.tsx +++ b/public/app/plugins/datasource/grafana/components/AnnotationQueryEditor.test.tsx @@ -1,6 +1,7 @@ -import { render, screen } from '@testing-library/react'; import React from 'react'; -import { GrafanaAnnotationType, GrafanaAnnotationQuery } from '../types'; +import { render, screen } from '@testing-library/react'; + +import { GrafanaAnnotationQuery, GrafanaAnnotationType } from '../types'; import AnnotationQueryEditor from './AnnotationQueryEditor'; describe('AnnotationQueryEditor', () => { @@ -12,6 +13,9 @@ describe('AnnotationQueryEditor', () => { refId: 'Anno', type: GrafanaAnnotationType.Tags, limit: 100, + enable: true, + name: 'a name', + iconColor: 'a color', }; }); diff --git a/public/app/plugins/datasource/grafana/components/AnnotationQueryEditor.tsx b/public/app/plugins/datasource/grafana/components/AnnotationQueryEditor.tsx index 6075d15cb77..ea51fa7af7c 100644 --- a/public/app/plugins/datasource/grafana/components/AnnotationQueryEditor.tsx +++ b/public/app/plugins/datasource/grafana/components/AnnotationQueryEditor.tsx @@ -1,7 +1,8 @@ import React from 'react'; -import { FieldSet, InlineField, InlineFieldRow, InlineSwitch, Select } from '@grafana/ui'; -import { TagFilter } from 'app/core/components/TagFilter/TagFilter'; import { SelectableValue } from '@grafana/data'; +import { FieldSet, InlineField, InlineFieldRow, InlineSwitch, Select } from '@grafana/ui'; + +import { TagFilter } from 'app/core/components/TagFilter/TagFilter'; import { GrafanaAnnotationQuery, GrafanaAnnotationType } from '../types'; import { getAnnotationTags } from 'app/features/annotations/api'; @@ -48,7 +49,7 @@ interface Props { } export default function AnnotationQueryEditor({ query, onChange }: Props) { - const { limit = 100, matchAny = false, tags = [], type = GrafanaAnnotationType.Tags } = query; + const { limit = 100, matchAny = false, tags = [], type = GrafanaAnnotationType.Dashboard } = query; const onFilterByChange = (newValue: SelectableValue) => onChange({ diff --git a/public/app/plugins/datasource/grafana/datasource.test.ts b/public/app/plugins/datasource/grafana/datasource.test.ts index c107003dd37..d4d83b832ec 100644 --- a/public/app/plugins/datasource/grafana/datasource.test.ts +++ b/public/app/plugins/datasource/grafana/datasource.test.ts @@ -1,8 +1,8 @@ -import { DataSourceInstanceSettings, dateTime, AnnotationQueryRequest } from '@grafana/data'; +import { AnnotationQueryRequest, DataSourceInstanceSettings, dateTime } from '@grafana/data'; import { backendSrv } from 'app/core/services/backend_srv'; // will use the version in __mocks__ import { GrafanaDatasource } from './datasource'; -import { GrafanaQuery, GrafanaAnnotationQuery, GrafanaAnnotationType } from './types'; +import { GrafanaAnnotationQuery, GrafanaAnnotationType, GrafanaQuery } from './types'; jest.mock('@grafana/runtime', () => ({ ...((jest.requireActual('@grafana/runtime') as unknown) as object), @@ -37,7 +37,7 @@ describe('grafana data source', () => { const options = setupAnnotationQueryOptions({ tags: ['tag1:$var'] }); beforeEach(() => { - return ds.annotationQuery(options); + return ds.getAnnotations(options); }); it('should interpolate template variables in tags in query options', () => { @@ -49,7 +49,7 @@ describe('grafana data source', () => { const options = setupAnnotationQueryOptions({ tags: ['$var2'] }); beforeEach(() => { - return ds.annotationQuery(options); + return ds.getAnnotations(options); }); it('should interpolate template variables in tags in query options', () => { @@ -68,7 +68,7 @@ describe('grafana data source', () => { ); beforeEach(() => { - return ds.annotationQuery(options); + return ds.getAnnotations(options); }); it('should remove tags from query options', () => { diff --git a/public/app/plugins/datasource/grafana/datasource.ts b/public/app/plugins/datasource/grafana/datasource.ts index 755462aaccf..530f915e813 100644 --- a/public/app/plugins/datasource/grafana/datasource.ts +++ b/public/app/plugins/datasource/grafana/datasource.ts @@ -1,5 +1,7 @@ +import { from, merge, Observable, of } from 'rxjs'; +import { catchError, map } from 'rxjs/operators'; +import { getBackendSrv, getGrafanaLiveSrv, getTemplateSrv, toDataQueryResponse } from '@grafana/runtime'; import { - AnnotationEvent, AnnotationQueryRequest, DataQueryRequest, DataQueryResponse, @@ -8,13 +10,12 @@ import { isValidLiveChannelAddress, parseLiveChannelAddress, StreamingFrameOptions, + toDataFrame, } from '@grafana/data'; -import { GrafanaQuery, GrafanaAnnotationQuery, GrafanaAnnotationType, GrafanaQueryType } from './types'; -import { getBackendSrv, getGrafanaLiveSrv, getTemplateSrv, toDataQueryResponse } from '@grafana/runtime'; -import { Observable, of, merge } from 'rxjs'; -import { map, catchError } from 'rxjs/operators'; +import { GrafanaAnnotationQuery, GrafanaAnnotationType, GrafanaQuery, GrafanaQueryType } from './types'; import AnnotationQueryEditor from './components/AnnotationQueryEditor'; +import { getDashboardSrv } from '../../../features/dashboard/services/DashboardSrv'; let counter = 100; @@ -23,6 +24,18 @@ export class GrafanaDatasource extends DataSourceApi { super(instanceSettings); this.annotations = { QueryEditor: AnnotationQueryEditor, + prepareAnnotation(json: any): GrafanaAnnotationQuery { + json.target = json.target ?? { + type: json.type, + limit: json.limit, + tags: json.tags, + matchAny: json.matchAny, + }; // using spread syntax caused an infinite loop in StandardAnnotationQueryEditor + return json; + }, + prepareQuery(anno: GrafanaAnnotationQuery): GrafanaQuery { + return { ...anno, refId: anno.name, queryType: GrafanaQueryType.Annotations }; + }, }; } @@ -33,6 +46,16 @@ export class GrafanaDatasource extends DataSourceApi { if (target.hide) { continue; } + if (target.queryType === GrafanaQueryType.Annotations) { + return from( + this.getAnnotations({ + range: request.range, + rangeRaw: request.rangeRaw!, + annotation: target as any, + dashboard: getDashboardSrv().getCurrent(), + }) + ); + } if (target.queryType === GrafanaQueryType.LiveMeasurements) { let channel = templateSrv.replace(target.channel, request.scopedVars); const { filter } = target; @@ -84,7 +107,7 @@ export class GrafanaDatasource extends DataSourceApi { return Promise.resolve([]); } - annotationQuery(options: AnnotationQueryRequest): Promise { + async getAnnotations(options: AnnotationQueryRequest): Promise { const templateSrv = getTemplateSrv(); const annotation = (options.annotation as unknown) as GrafanaAnnotationQuery; const params: any = { @@ -98,7 +121,7 @@ export class GrafanaDatasource extends DataSourceApi { if (annotation.type === GrafanaAnnotationType.Dashboard) { // if no dashboard id yet return if (!options.dashboard.id) { - return Promise.resolve([]); + return Promise.resolve({ data: [] }); } // filter by dashboard id params.dashboardId = options.dashboard.id; @@ -107,7 +130,7 @@ export class GrafanaDatasource extends DataSourceApi { } else { // require at least one tag if (!Array.isArray(annotation.tags) || annotation.tags.length === 0) { - return Promise.resolve([]); + return Promise.resolve({ data: [] }); } const delimiter = '__delimiter__'; const tags = []; @@ -126,11 +149,12 @@ export class GrafanaDatasource extends DataSourceApi { params.tags = tags; } - return getBackendSrv().get( + const annotations = await getBackendSrv().get( '/api/annotations', params, `grafana-data-source-annotations-${annotation.name}-${options.dashboard?.id}` ); + return { data: [toDataFrame(annotations)] }; } testDatasource() { diff --git a/public/app/plugins/datasource/grafana/types.ts b/public/app/plugins/datasource/grafana/types.ts index ccace7bf98c..c0a152f036e 100644 --- a/public/app/plugins/datasource/grafana/types.ts +++ b/public/app/plugins/datasource/grafana/types.ts @@ -8,6 +8,7 @@ import { LiveDataFilter } from '@grafana/runtime'; export enum GrafanaQueryType { RandomWalk = 'randomWalk', LiveMeasurements = 'measurements', + Annotations = 'annotations', } export interface GrafanaQuery extends DataQuery {