@grafana/scenes 1.3.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/esm/core/types.js.map +1 -1
  3. package/dist/esm/querying/layers/SceneDataLayerBase.js +21 -0
  4. package/dist/esm/querying/layers/SceneDataLayerBase.js.map +1 -1
  5. package/dist/esm/querying/layers/SceneDataLayerControls.js +32 -13
  6. package/dist/esm/querying/layers/SceneDataLayerControls.js.map +1 -1
  7. package/dist/esm/querying/layers/annotations/AnnotationsDataLayer.js +31 -48
  8. package/dist/esm/querying/layers/annotations/AnnotationsDataLayer.js.map +1 -1
  9. package/dist/esm/querying/layers/annotations/standardAnnotationQuery.js +27 -5
  10. package/dist/esm/querying/layers/annotations/standardAnnotationQuery.js.map +1 -1
  11. package/dist/esm/utils/ControlsLabel.js +35 -9
  12. package/dist/esm/utils/ControlsLabel.js.map +1 -1
  13. package/dist/esm/utils/LoadingIndicator.js +21 -0
  14. package/dist/esm/utils/LoadingIndicator.js.map +1 -0
  15. package/dist/esm/utils/getMessageFromError.js +24 -0
  16. package/dist/esm/utils/getMessageFromError.js.map +1 -0
  17. package/dist/esm/variables/components/VariableValueSelect.js +5 -55
  18. package/dist/esm/variables/components/VariableValueSelect.js.map +1 -1
  19. package/dist/esm/variables/components/VariableValueSelectors.js +11 -6
  20. package/dist/esm/variables/components/VariableValueSelectors.js.map +1 -1
  21. package/dist/esm/variables/types.js.map +1 -1
  22. package/dist/esm/variables/variants/MultiValueVariable.js +1 -1
  23. package/dist/esm/variables/variants/MultiValueVariable.js.map +1 -1
  24. package/dist/index.d.ts +19 -9
  25. package/dist/index.js +357 -302
  26. package/dist/index.js.map +1 -1
  27. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ # v1.3.1 (Mon Sep 18 2023)
2
+
3
+ #### 🐛 Bug Fix
4
+
5
+ - AnnotationsDataLayer: Handle data source error [#342](https://github.com/grafana/scenes/pull/342) ([@dprokop](https://github.com/dprokop))
6
+ - DataLayers: Allow cancelling layers from layer control [#337](https://github.com/grafana/scenes/pull/337) ([@dprokop](https://github.com/dprokop))
7
+
8
+ #### Authors: 1
9
+
10
+ - Dominik Prokop ([@dprokop](https://github.com/dprokop))
11
+
12
+ ---
13
+
1
14
  # v1.3.0 (Mon Sep 18 2023)
2
15
 
3
16
  #### 🚀 Enhancement
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sources":["../../../src/core/types.ts"],"sourcesContent":["import React from 'react';\nimport { MonoTypeOperatorFunction, Observable, Unsubscribable } from 'rxjs';\n\nimport {\n BusEvent,\n BusEventHandler,\n BusEventType,\n DataFrame,\n DataQueryRequest,\n DataTopic,\n DataTransformContext,\n PanelData,\n TimeRange,\n} from '@grafana/data';\nimport { TimeZone } from '@grafana/schema';\n\nimport { SceneVariableDependencyConfigLike, SceneVariables } from '../variables/types';\nimport { SceneObjectRef } from './SceneObjectRef';\n\nexport interface SceneObjectState {\n key?: string;\n $timeRange?: SceneTimeRangeLike;\n $data?: SceneDataProvider;\n $variables?: SceneVariables;\n /**\n * @experimental\n * Can be used to add extra behaviors to a scene object.\n * These are activated when the their parent scene object is activated.\n */\n $behaviors?: Array<SceneObject | SceneStatelessBehavior>;\n}\n\nexport interface SceneLayoutChildOptions {\n width?: number | string;\n height?: number | string;\n xSizing?: 'fill' | 'content';\n ySizing?: 'fill' | 'content';\n x?: number;\n y?: number;\n minWidth?: number | string;\n minHeight?: number | string;\n isDraggable?: boolean;\n isResizable?: boolean;\n}\n\nexport interface SceneComponentProps<T> {\n model: T;\n}\n\nexport type SceneComponent<TModel> = (props: SceneComponentProps<TModel>) => React.ReactElement | null;\n\nexport interface SceneDataState extends SceneObjectState {\n data?: PanelData;\n}\n\nexport interface SceneObject<TState extends SceneObjectState = SceneObjectState> {\n /** The current state */\n readonly state: TState;\n\n /** True when there is a React component mounted for this Object */\n readonly isActive: boolean;\n\n /** SceneObject parent */\n readonly parent?: SceneObject;\n\n /** This abtractions declares what variables the scene object depends on and how to handle when they change value. **/\n readonly variableDependency?: SceneVariableDependencyConfigLike;\n\n /** This abstraction declares URL sync dependencies of a scene object. **/\n readonly urlSync?: SceneObjectUrlSyncHandler;\n\n /** Subscribe to state changes */\n subscribeToState(handler: SceneStateChangedHandler<TState>): Unsubscribable;\n\n /** Subscribe to a scene event */\n subscribeToEvent<T extends BusEvent>(typeFilter: BusEventType<T>, handler: BusEventHandler<T>): Unsubscribable;\n\n /** Publish an event and optionally bubble it up the scene */\n publishEvent(event: BusEvent, bubble?: boolean): void;\n\n /** Utility hook that wraps useObservable. Used by React components to subscribes to state changes */\n useState(): TState;\n\n /** How to modify state */\n setState(state: Partial<TState>): void;\n\n /**\n * Called when the Component is mounted. This will also activate any $data, $variables or $timeRange scene object on this level.\n * Don't override this in your custom SceneObjects, instead use addActivationHandler from the constructor.\n **/\n activate(): CancelActivationHandler;\n\n /** Get the scene root */\n getRoot(): SceneObject;\n\n /** Returns a deep clone this object and all its children */\n clone(state?: Partial<TState>): this;\n\n /** A React component to use for rendering the object */\n Component(props: SceneComponentProps<SceneObject<TState>>): React.ReactElement | null;\n\n /** Force a re-render, should only be needed when variable values change */\n forceRender(): void;\n\n /** Returns a SceneObjectRef that will resolve to this object */\n getRef(): SceneObjectRef<this>;\n\n /**\n * Allows external code to register code that is executed on activate and deactivate. This allow you\n * to wire up scene objects that need to respond to state changes in other objects from the outside.\n **/\n addActivationHandler(handler: SceneActivationHandler): void;\n\n /**\n * Loop through state and call callback for each direct child scene object.\n * Checks 1 level deep properties and arrays. So a scene object hidden in a nested plain object will not be detected.\n */\n forEachChild(callback: (child: SceneObject) => void): void;\n}\n\nexport type SceneActivationHandler = () => SceneDeactivationHandler | void;\nexport type SceneDeactivationHandler = () => void;\n\n/**\n * Function returned by activate() that when called will deactivate the object if it's the last activator\n **/\nexport type CancelActivationHandler = () => void;\n\nexport interface SceneLayoutState extends SceneObjectState {\n children: SceneObject[];\n}\n\nexport interface SceneLayout<T extends SceneLayoutState = SceneLayoutState> extends SceneObject<T> {\n isDraggable(): boolean;\n getDragClass?(): string;\n getDragClassCancel?(): string;\n}\n\nexport interface SceneTimeRangeState extends SceneObjectState {\n from: string;\n to: string;\n fiscalYearStartMonth?: number;\n value: TimeRange;\n timeZone?: TimeZone;\n}\n\nexport interface SceneTimeRangeLike extends SceneObject<SceneTimeRangeState> {\n onTimeZoneChange(timeZone: TimeZone): void;\n onTimeRangeChange(timeRange: TimeRange): void;\n onRefresh(): void;\n getTimeZone(): TimeZone;\n}\n\nexport function isSceneObject(obj: any): obj is SceneObject {\n return obj.useState !== undefined;\n}\n\nexport interface SceneObjectWithUrlSync extends SceneObject {\n getUrlState(): SceneObjectUrlValues;\n updateFromUrl(values: SceneObjectUrlValues): void;\n}\n\nexport interface SceneObjectUrlSyncHandler {\n getKeys(): string[];\n getUrlState(): SceneObjectUrlValues;\n updateFromUrl(values: SceneObjectUrlValues): void;\n}\n\nexport interface DataRequestEnricher {\n // Return partial data query request that will be merged with the original request provided by SceneQueryRunner\n enrichDataRequest(source: SceneObject): Partial<DataQueryRequest> | null;\n}\n\nexport function isDataRequestEnricher(obj: any): obj is DataRequestEnricher {\n return 'enrichDataRequest' in obj;\n}\n\nexport type SceneObjectUrlValue = string | string[] | undefined | null;\nexport type SceneObjectUrlValues = Record<string, SceneObjectUrlValue>;\n\nexport type CustomTransformOperator = (context: DataTransformContext) => MonoTypeOperatorFunction<DataFrame[]>;\nexport type SceneStateChangedHandler<TState> = (newState: TState, prevState: TState) => void;\n\nexport type DeepPartial<T> = {\n [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];\n};\n\nexport interface SceneDataProviderResultLike<O, T> {\n origin: O;\n data: T;\n}\n\nexport type SceneDataProviderResult = SceneDataProviderResultLike<SceneDataProvider, PanelData>;\nexport type SceneDataLayerProviderResult = SceneDataProviderResultLike<SceneDataLayerProvider, PanelData> & {\n topic: DataTopic;\n};\n\nexport interface SceneDataProvider extends SceneObject<SceneDataState> {\n setContainerWidth?: (width: number) => void;\n isDataReadyToDisplay?: () => boolean;\n cancelQuery?: () => void;\n getResultsStream?(): Observable<SceneDataProviderResult>;\n}\n\nexport interface SceneDataLayerProviderState extends SceneObjectState {\n name: string;\n isEnabled?: boolean;\n}\n\nexport interface SceneDataLayerProvider extends SceneObject<SceneDataLayerProviderState> {\n cancelQuery?: () => void;\n getResultsStream(): Observable<SceneDataLayerProviderResult>;\n}\n\nexport interface DataLayerFilter {\n panelId: number;\n}\n\nexport interface SceneStatelessBehavior<T extends SceneObject = any> {\n (sceneObject: T): CancelActivationHandler | void;\n}\n"],"names":[],"mappings":"AAyJO,SAAS,cAAc,GAA8B,EAAA;AAC1D,EAAA,OAAO,IAAI,QAAa,KAAA,KAAA,CAAA,CAAA;AAC1B,CAAA;AAkBO,SAAS,sBAAsB,GAAsC,EAAA;AAC1E,EAAA,OAAO,mBAAuB,IAAA,GAAA,CAAA;AAChC;;;;"}
1
+ {"version":3,"file":"types.js","sources":["../../../src/core/types.ts"],"sourcesContent":["import React from 'react';\nimport { MonoTypeOperatorFunction, Observable, Unsubscribable } from 'rxjs';\n\nimport {\n BusEvent,\n BusEventHandler,\n BusEventType,\n DataFrame,\n DataQueryRequest,\n DataTopic,\n DataTransformContext,\n PanelData,\n TimeRange,\n} from '@grafana/data';\nimport { TimeZone } from '@grafana/schema';\n\nimport { SceneVariableDependencyConfigLike, SceneVariables } from '../variables/types';\nimport { SceneObjectRef } from './SceneObjectRef';\n\nexport interface SceneObjectState {\n key?: string;\n $timeRange?: SceneTimeRangeLike;\n $data?: SceneDataProvider;\n $variables?: SceneVariables;\n /**\n * @experimental\n * Can be used to add extra behaviors to a scene object.\n * These are activated when the their parent scene object is activated.\n */\n $behaviors?: Array<SceneObject | SceneStatelessBehavior>;\n}\n\nexport interface SceneLayoutChildOptions {\n width?: number | string;\n height?: number | string;\n xSizing?: 'fill' | 'content';\n ySizing?: 'fill' | 'content';\n x?: number;\n y?: number;\n minWidth?: number | string;\n minHeight?: number | string;\n isDraggable?: boolean;\n isResizable?: boolean;\n}\n\nexport interface SceneComponentProps<T> {\n model: T;\n}\n\nexport type SceneComponent<TModel> = (props: SceneComponentProps<TModel>) => React.ReactElement | null;\n\nexport interface SceneDataState extends SceneObjectState {\n data?: PanelData;\n}\n\nexport interface SceneObject<TState extends SceneObjectState = SceneObjectState> {\n /** The current state */\n readonly state: TState;\n\n /** True when there is a React component mounted for this Object */\n readonly isActive: boolean;\n\n /** SceneObject parent */\n readonly parent?: SceneObject;\n\n /** This abtractions declares what variables the scene object depends on and how to handle when they change value. **/\n readonly variableDependency?: SceneVariableDependencyConfigLike;\n\n /** This abstraction declares URL sync dependencies of a scene object. **/\n readonly urlSync?: SceneObjectUrlSyncHandler;\n\n /** Subscribe to state changes */\n subscribeToState(handler: SceneStateChangedHandler<TState>): Unsubscribable;\n\n /** Subscribe to a scene event */\n subscribeToEvent<T extends BusEvent>(typeFilter: BusEventType<T>, handler: BusEventHandler<T>): Unsubscribable;\n\n /** Publish an event and optionally bubble it up the scene */\n publishEvent(event: BusEvent, bubble?: boolean): void;\n\n /** Utility hook that wraps useObservable. Used by React components to subscribes to state changes */\n useState(): TState;\n\n /** How to modify state */\n setState(state: Partial<TState>): void;\n\n /**\n * Called when the Component is mounted. This will also activate any $data, $variables or $timeRange scene object on this level.\n * Don't override this in your custom SceneObjects, instead use addActivationHandler from the constructor.\n **/\n activate(): CancelActivationHandler;\n\n /** Get the scene root */\n getRoot(): SceneObject;\n\n /** Returns a deep clone this object and all its children */\n clone(state?: Partial<TState>): this;\n\n /** A React component to use for rendering the object */\n Component(props: SceneComponentProps<SceneObject<TState>>): React.ReactElement | null;\n\n /** Force a re-render, should only be needed when variable values change */\n forceRender(): void;\n\n /** Returns a SceneObjectRef that will resolve to this object */\n getRef(): SceneObjectRef<this>;\n\n /**\n * Allows external code to register code that is executed on activate and deactivate. This allow you\n * to wire up scene objects that need to respond to state changes in other objects from the outside.\n **/\n addActivationHandler(handler: SceneActivationHandler): void;\n\n /**\n * Loop through state and call callback for each direct child scene object.\n * Checks 1 level deep properties and arrays. So a scene object hidden in a nested plain object will not be detected.\n */\n forEachChild(callback: (child: SceneObject) => void): void;\n}\n\nexport type SceneActivationHandler = () => SceneDeactivationHandler | void;\nexport type SceneDeactivationHandler = () => void;\n\n/**\n * Function returned by activate() that when called will deactivate the object if it's the last activator\n **/\nexport type CancelActivationHandler = () => void;\n\nexport interface SceneLayoutState extends SceneObjectState {\n children: SceneObject[];\n}\n\nexport interface SceneLayout<T extends SceneLayoutState = SceneLayoutState> extends SceneObject<T> {\n isDraggable(): boolean;\n getDragClass?(): string;\n getDragClassCancel?(): string;\n}\n\nexport interface SceneTimeRangeState extends SceneObjectState {\n from: string;\n to: string;\n fiscalYearStartMonth?: number;\n value: TimeRange;\n timeZone?: TimeZone;\n}\n\nexport interface SceneTimeRangeLike extends SceneObject<SceneTimeRangeState> {\n onTimeZoneChange(timeZone: TimeZone): void;\n onTimeRangeChange(timeRange: TimeRange): void;\n onRefresh(): void;\n getTimeZone(): TimeZone;\n}\n\nexport function isSceneObject(obj: any): obj is SceneObject {\n return obj.useState !== undefined;\n}\n\nexport interface SceneObjectWithUrlSync extends SceneObject {\n getUrlState(): SceneObjectUrlValues;\n updateFromUrl(values: SceneObjectUrlValues): void;\n}\n\nexport interface SceneObjectUrlSyncHandler {\n getKeys(): string[];\n getUrlState(): SceneObjectUrlValues;\n updateFromUrl(values: SceneObjectUrlValues): void;\n}\n\nexport interface DataRequestEnricher {\n // Return partial data query request that will be merged with the original request provided by SceneQueryRunner\n enrichDataRequest(source: SceneObject): Partial<DataQueryRequest> | null;\n}\n\nexport function isDataRequestEnricher(obj: any): obj is DataRequestEnricher {\n return 'enrichDataRequest' in obj;\n}\n\nexport type SceneObjectUrlValue = string | string[] | undefined | null;\nexport type SceneObjectUrlValues = Record<string, SceneObjectUrlValue>;\n\nexport type CustomTransformOperator = (context: DataTransformContext) => MonoTypeOperatorFunction<DataFrame[]>;\nexport type SceneStateChangedHandler<TState> = (newState: TState, prevState: TState) => void;\n\nexport type DeepPartial<T> = {\n [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];\n};\n\nexport interface SceneDataProviderResultLike<O, T> {\n origin: O;\n data: T;\n}\n\nexport type SceneDataProviderResult = SceneDataProviderResultLike<SceneDataProvider, PanelData>;\nexport type SceneDataLayerProviderResult = SceneDataProviderResultLike<SceneDataLayerProvider, PanelData> & {\n topic: DataTopic;\n};\n\nexport interface SceneDataProvider extends SceneObject<SceneDataState> {\n setContainerWidth?: (width: number) => void;\n isDataReadyToDisplay?: () => boolean;\n cancelQuery?: () => void;\n getResultsStream?(): Observable<SceneDataProviderResult>;\n}\n\nexport interface SceneDataLayerProviderState extends SceneObjectState {\n name: string;\n description?: string;\n isEnabled?: boolean;\n data?: PanelData;\n}\n\nexport interface SceneDataLayerProvider extends SceneObject<SceneDataLayerProviderState> {\n cancelQuery?: () => void;\n getResultsStream(): Observable<SceneDataLayerProviderResult>;\n}\n\nexport interface DataLayerFilter {\n panelId: number;\n}\n\nexport interface SceneStatelessBehavior<T extends SceneObject = any> {\n (sceneObject: T): CancelActivationHandler | void;\n}\n"],"names":[],"mappings":"AAyJO,SAAS,cAAc,GAA8B,EAAA;AAC1D,EAAA,OAAO,IAAI,QAAa,KAAA,KAAA,CAAA,CAAA;AAC1B,CAAA;AAkBO,SAAS,sBAAsB,GAAsC,EAAA;AAC1E,EAAA,OAAO,mBAAuB,IAAA,GAAA,CAAA;AAChC;;;;"}
@@ -1,6 +1,7 @@
1
1
  import { ReplaySubject } from 'rxjs';
2
2
  import { emptyPanelData } from '../../core/SceneDataNode.js';
3
3
  import { SceneObjectBase } from '../../core/SceneObjectBase.js';
4
+ import { setBaseClassState } from '../../utils/utils.js';
4
5
 
5
6
  var __defProp = Object.defineProperty;
6
7
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
@@ -30,6 +31,9 @@ class SceneDataLayerBase extends SceneObjectBase {
30
31
  if (this.state.isEnabled) {
31
32
  this.onEnable();
32
33
  }
34
+ if (this.shouldRunLayerOnActivate()) {
35
+ this.runLayer();
36
+ }
33
37
  this.subscribeToState((n, p) => {
34
38
  if (!n.isEnabled && this.querySub) {
35
39
  this.querySub.unsubscribe();
@@ -40,9 +44,13 @@ class SceneDataLayerBase extends SceneObjectBase {
40
44
  data: emptyPanelData,
41
45
  topic: this.topic
42
46
  });
47
+ this.setStateHelper({
48
+ data: emptyPanelData
49
+ });
43
50
  }
44
51
  if (n.isEnabled && !p.isEnabled) {
45
52
  this.onEnable();
53
+ this.runLayer();
46
54
  }
47
55
  });
48
56
  return () => {
@@ -60,6 +68,7 @@ class SceneDataLayerBase extends SceneObjectBase {
60
68
  if (this.querySub) {
61
69
  this.querySub.unsubscribe();
62
70
  this.querySub = void 0;
71
+ this.publishResults(emptyPanelData, this.topic);
63
72
  }
64
73
  }
65
74
  publishResults(data, topic) {
@@ -69,11 +78,23 @@ class SceneDataLayerBase extends SceneObjectBase {
69
78
  data,
70
79
  topic
71
80
  });
81
+ this.setStateHelper({
82
+ data
83
+ });
72
84
  }
73
85
  }
74
86
  getResultsStream() {
75
87
  return this._results;
76
88
  }
89
+ shouldRunLayerOnActivate() {
90
+ if (this.state.data) {
91
+ return false;
92
+ }
93
+ return true;
94
+ }
95
+ setStateHelper(state) {
96
+ setBaseClassState(this, state);
97
+ }
77
98
  }
78
99
 
79
100
  export { SceneDataLayerBase };
@@ -1 +1 @@
1
- {"version":3,"file":"SceneDataLayerBase.js","sources":["../../../../src/querying/layers/SceneDataLayerBase.ts"],"sourcesContent":["import { DataTopic, PanelData } from '@grafana/data';\nimport { ReplaySubject, Unsubscribable } from 'rxjs';\nimport { emptyPanelData } from '../../core/SceneDataNode';\nimport { SceneObjectBase } from '../../core/SceneObjectBase';\nimport {\n CancelActivationHandler,\n SceneDataLayerProvider,\n SceneDataLayerProviderResult,\n SceneDataLayerProviderState,\n} from '../../core/types';\n\ntype SceneDataLayerBaseState<T extends {} = {}> = SceneDataLayerProviderState & T;\n\n/**\n * Base class for data layer. Handles common implementation including enabling/disabling layer and publishing results.\n */\nexport abstract class SceneDataLayerBase<T extends {} = SceneDataLayerProviderState>\n extends SceneObjectBase<SceneDataLayerBaseState<T>>\n implements SceneDataLayerProvider\n{\n /**\n * Subscription to query results. Should be set when layer runs a query.\n */\n protected querySub?: Unsubscribable;\n\n /**\n * Subject to emit results to.\n */\n private _results = new ReplaySubject<SceneDataLayerProviderResult>();\n\n /**\n * Implement logic for enabling the layer. This is called when layer is enabled or when layer is enabled when activated.\n * Use i.e. to setup subscriptions that will trigger layer updates.\n */\n public abstract onEnable(): void;\n\n /**\n * Implement logic for disabling the layer. This is called when layer is disabled.\n * Use i.e. to unsubscribe from subscriptions that trigger layer updates.\n */\n public abstract onDisable(): void;\n\n /**\n * Data topic that a given layer is responsible for.\n */\n public abstract topic: DataTopic;\n\n public constructor(initialState: SceneDataLayerBaseState<T>) {\n super({\n isEnabled: true,\n ...initialState,\n });\n\n this.addActivationHandler(() => this.onActivate());\n }\n\n protected onActivate(): CancelActivationHandler {\n if (this.state.isEnabled) {\n this.onEnable();\n }\n\n // Subscribe to layer state changes and enable/disable layer accordingly.\n this.subscribeToState((n, p) => {\n if (!n.isEnabled && this.querySub) {\n // When layer disabled, cancel query and call onDisable that should publish empty results.\n this.querySub.unsubscribe();\n this.querySub = undefined;\n this.onDisable();\n\n this._results.next({\n origin: this,\n data: emptyPanelData,\n topic: this.topic,\n });\n }\n\n if (n.isEnabled && !p.isEnabled) {\n // When layer enabled, run queries.\n this.onEnable();\n }\n });\n\n return () => {\n this.onDeactivate();\n };\n }\n\n protected onDeactivate(): void {\n if (this.querySub) {\n this.querySub.unsubscribe();\n this.querySub = undefined;\n }\n\n this.onDisable();\n }\n\n public cancelQuery() {\n if (this.querySub) {\n this.querySub.unsubscribe();\n this.querySub = undefined;\n }\n }\n\n protected publishResults(data: PanelData, topic: DataTopic) {\n if (this.state.isEnabled) {\n this._results.next({\n origin: this,\n data,\n topic,\n });\n }\n }\n\n public getResultsStream() {\n return this._results;\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAgBO,MAAe,2BACZ,eAEV,CAAA;AAAA,EA4BS,YAAY,YAA0C,EAAA;AAC3D,IAAM,KAAA,CAAA,cAAA,CAAA;AAAA,MACJ,SAAW,EAAA,IAAA;AAAA,KAAA,EACR,YACJ,CAAA,CAAA,CAAA;AAvBH,IAAQ,IAAA,CAAA,QAAA,GAAW,IAAI,aAA4C,EAAA,CAAA;AAyBjE,IAAA,IAAA,CAAK,oBAAqB,CAAA,MAAM,IAAK,CAAA,UAAA,EAAY,CAAA,CAAA;AAAA,GACnD;AAAA,EAEU,UAAsC,GAAA;AAC9C,IAAI,IAAA,IAAA,CAAK,MAAM,SAAW,EAAA;AACxB,MAAA,IAAA,CAAK,QAAS,EAAA,CAAA;AAAA,KAChB;AAGA,IAAK,IAAA,CAAA,gBAAA,CAAiB,CAAC,CAAA,EAAG,CAAM,KAAA;AAC9B,MAAA,IAAI,CAAC,CAAA,CAAE,SAAa,IAAA,IAAA,CAAK,QAAU,EAAA;AAEjC,QAAA,IAAA,CAAK,SAAS,WAAY,EAAA,CAAA;AAC1B,QAAA,IAAA,CAAK,QAAW,GAAA,KAAA,CAAA,CAAA;AAChB,QAAA,IAAA,CAAK,SAAU,EAAA,CAAA;AAEf,QAAA,IAAA,CAAK,SAAS,IAAK,CAAA;AAAA,UACjB,MAAQ,EAAA,IAAA;AAAA,UACR,IAAM,EAAA,cAAA;AAAA,UACN,OAAO,IAAK,CAAA,KAAA;AAAA,SACb,CAAA,CAAA;AAAA,OACH;AAEA,MAAA,IAAI,CAAE,CAAA,SAAA,IAAa,CAAC,CAAA,CAAE,SAAW,EAAA;AAE/B,QAAA,IAAA,CAAK,QAAS,EAAA,CAAA;AAAA,OAChB;AAAA,KACD,CAAA,CAAA;AAED,IAAA,OAAO,MAAM;AACX,MAAA,IAAA,CAAK,YAAa,EAAA,CAAA;AAAA,KACpB,CAAA;AAAA,GACF;AAAA,EAEU,YAAqB,GAAA;AAC7B,IAAA,IAAI,KAAK,QAAU,EAAA;AACjB,MAAA,IAAA,CAAK,SAAS,WAAY,EAAA,CAAA;AAC1B,MAAA,IAAA,CAAK,QAAW,GAAA,KAAA,CAAA,CAAA;AAAA,KAClB;AAEA,IAAA,IAAA,CAAK,SAAU,EAAA,CAAA;AAAA,GACjB;AAAA,EAEO,WAAc,GAAA;AACnB,IAAA,IAAI,KAAK,QAAU,EAAA;AACjB,MAAA,IAAA,CAAK,SAAS,WAAY,EAAA,CAAA;AAC1B,MAAA,IAAA,CAAK,QAAW,GAAA,KAAA,CAAA,CAAA;AAAA,KAClB;AAAA,GACF;AAAA,EAEU,cAAA,CAAe,MAAiB,KAAkB,EAAA;AAC1D,IAAI,IAAA,IAAA,CAAK,MAAM,SAAW,EAAA;AACxB,MAAA,IAAA,CAAK,SAAS,IAAK,CAAA;AAAA,QACjB,MAAQ,EAAA,IAAA;AAAA,QACR,IAAA;AAAA,QACA,KAAA;AAAA,OACD,CAAA,CAAA;AAAA,KACH;AAAA,GACF;AAAA,EAEO,gBAAmB,GAAA;AACxB,IAAA,OAAO,IAAK,CAAA,QAAA,CAAA;AAAA,GACd;AACF;;;;"}
1
+ {"version":3,"file":"SceneDataLayerBase.js","sources":["../../../../src/querying/layers/SceneDataLayerBase.ts"],"sourcesContent":["import { DataTopic, PanelData } from '@grafana/data';\nimport { ReplaySubject, Unsubscribable } from 'rxjs';\nimport { emptyPanelData } from '../../core/SceneDataNode';\nimport { SceneObjectBase } from '../../core/SceneObjectBase';\nimport {\n CancelActivationHandler,\n SceneDataLayerProvider,\n SceneDataLayerProviderResult,\n SceneDataLayerProviderState,\n} from '../../core/types';\nimport { setBaseClassState } from '../../utils/utils';\n\n/**\n * Base class for data layer. Handles common implementation including enabling/disabling layer and publishing results.\n */\nexport abstract class SceneDataLayerBase<T extends SceneDataLayerProviderState = SceneDataLayerProviderState>\n extends SceneObjectBase<T>\n implements SceneDataLayerProvider\n{\n /**\n * Subscription to query results. Should be set when layer runs a query.\n */\n protected querySub?: Unsubscribable;\n\n /**\n * Subject to emit results to.\n */\n private _results = new ReplaySubject<SceneDataLayerProviderResult>();\n\n /**\n * Implement logic for enabling the layer. This is called when layer is enabled or when layer is enabled when activated.\n * Use i.e. to setup subscriptions that will trigger layer updates.\n */\n public abstract onEnable(): void;\n\n /**\n * Implement logic for disabling the layer. This is called when layer is disabled.\n * Use i.e. to unsubscribe from subscriptions that trigger layer updates.\n */\n public abstract onDisable(): void;\n\n /**\n * Implement logic running the layer and setting up the querySub subscription.\n */\n protected abstract runLayer(): void;\n\n /**\n * Data topic that a given layer is responsible for.\n */\n public abstract topic: DataTopic;\n\n public constructor(initialState: T) {\n super({\n isEnabled: true,\n ...initialState,\n });\n\n this.addActivationHandler(() => this.onActivate());\n }\n\n protected onActivate(): CancelActivationHandler {\n if (this.state.isEnabled) {\n this.onEnable();\n }\n\n if (this.shouldRunLayerOnActivate()) {\n this.runLayer();\n }\n\n // Subscribe to layer state changes and enable/disable layer accordingly.\n this.subscribeToState((n, p) => {\n if (!n.isEnabled && this.querySub) {\n // When layer disabled, cancel query and call onDisable that should publish empty results.\n this.querySub.unsubscribe();\n this.querySub = undefined;\n this.onDisable();\n\n // Manually publishing the results to state and results stream as publishPublish results has a guard for the layer to be enabled.\n this._results.next({\n origin: this,\n data: emptyPanelData,\n topic: this.topic,\n });\n this.setStateHelper({\n data: emptyPanelData,\n });\n }\n\n if (n.isEnabled && !p.isEnabled) {\n // When layer enabled, run queries.\n this.onEnable();\n this.runLayer();\n }\n });\n\n return () => {\n this.onDeactivate();\n };\n }\n\n protected onDeactivate(): void {\n if (this.querySub) {\n this.querySub.unsubscribe();\n this.querySub = undefined;\n }\n\n this.onDisable();\n }\n\n public cancelQuery() {\n if (this.querySub) {\n this.querySub.unsubscribe();\n this.querySub = undefined;\n\n this.publishResults(emptyPanelData, this.topic);\n }\n }\n\n protected publishResults(data: PanelData, topic: DataTopic) {\n if (this.state.isEnabled) {\n this._results.next({\n origin: this,\n data,\n topic,\n });\n\n this.setStateHelper({\n data,\n });\n }\n }\n\n public getResultsStream() {\n return this._results;\n }\n\n private shouldRunLayerOnActivate() {\n if (this.state.data) {\n return false;\n }\n\n return true;\n }\n\n /**\n * This helper function is to counter the contravariance of setState\n */\n private setStateHelper(state: Partial<SceneDataLayerProviderState>) {\n setBaseClassState<SceneDataLayerProviderState>(this, state);\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1,3 +1,5 @@
1
+ import { css } from '@emotion/css';
2
+ import { LoadingState } from '@grafana/schema';
1
3
  import { InlineSwitch } from '@grafana/ui';
2
4
  import React from 'react';
3
5
  import { sceneGraph } from '../../core/sceneGraph/index.js';
@@ -46,21 +48,38 @@ function SceneDataLayerControlsRenderer({ model }) {
46
48
  }
47
49
  return /* @__PURE__ */ React.createElement(React.Fragment, null, layers.map((l) => {
48
50
  const elementId = `data-layer-${l.state.key}`;
49
- return /* @__PURE__ */ React.createElement("div", {
51
+ return /* @__PURE__ */ React.createElement(SceneDataLayerControl, {
50
52
  key: elementId,
51
- style: {
52
- display: "flex"
53
- }
54
- }, /* @__PURE__ */ React.createElement(ControlsLabel, {
55
- htmlFor: elementId,
56
- label: l.state.name
57
- }), /* @__PURE__ */ React.createElement(InlineSwitch, {
58
- id: elementId,
59
- value: layersMap[l.state.key],
60
- onChange: () => model.toggleLayer(l)
61
- }));
53
+ layer: l,
54
+ onToggleLayer: () => model.toggleLayer(l),
55
+ isEnabled: layersMap[l.state.key]
56
+ });
62
57
  }));
63
58
  }
59
+ function SceneDataLayerControl({ layer, isEnabled, onToggleLayer }) {
60
+ var _a, _b;
61
+ const elementId = `data-layer-${layer.state.key}`;
62
+ const { data } = layer.useState();
63
+ const showLoading = Boolean(data && data.state === LoadingState.Loading);
64
+ return /* @__PURE__ */ React.createElement("div", {
65
+ className: containerStyle
66
+ }, /* @__PURE__ */ React.createElement(ControlsLabel, {
67
+ htmlFor: elementId,
68
+ isLoading: showLoading,
69
+ onCancel: () => {
70
+ var _a2;
71
+ return (_a2 = layer.cancelQuery) == null ? void 0 : _a2.call(layer);
72
+ },
73
+ label: layer.state.name,
74
+ description: layer.state.description,
75
+ error: (_b = (_a = layer.state.data) == null ? void 0 : _a.errors) == null ? void 0 : _b[0].message
76
+ }), /* @__PURE__ */ React.createElement(InlineSwitch, {
77
+ id: elementId,
78
+ value: isEnabled,
79
+ onChange: onToggleLayer
80
+ }));
81
+ }
82
+ const containerStyle = css({ display: "flex" });
64
83
 
65
- export { SceneDataLayerControls };
84
+ export { SceneDataLayerControl, SceneDataLayerControls };
66
85
  //# sourceMappingURL=SceneDataLayerControls.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SceneDataLayerControls.js","sources":["../../../../src/querying/layers/SceneDataLayerControls.tsx"],"sourcesContent":["import { InlineSwitch } from '@grafana/ui';\nimport React from 'react';\nimport { sceneGraph } from '../../core/sceneGraph';\nimport { SceneObjectBase } from '../../core/SceneObjectBase';\nimport { SceneComponentProps, SceneDataLayerProvider, SceneObjectState } from '../../core/types';\nimport { ControlsLabel } from '../../utils/ControlsLabel';\n\ninterface SceneDataLayerControlsState extends SceneObjectState {\n layersMap: Record<string, boolean>;\n}\n\nexport class SceneDataLayerControls extends SceneObjectBase<SceneDataLayerControlsState> {\n public static Component = SceneDataLayerControlsRenderer;\n\n public constructor() {\n // Holds the state of the layers, to avoid force re-rendering\n super({ layersMap: {} });\n\n this.addActivationHandler(() => this._onActivate());\n }\n\n private _onActivate() {\n const layers = sceneGraph.getDataLayers(this, true);\n this.setState({ layersMap: layers.reduce((acc, l) => ({ ...acc, [l.state.key!]: l.state.isEnabled }), {}) });\n }\n\n public toggleLayer(l: SceneDataLayerProvider) {\n this.setState({ layersMap: { ...this.state.layersMap, [l.state.key!]: !l.state.isEnabled } });\n l.setState({ isEnabled: !l.state.isEnabled });\n }\n}\n\nfunction SceneDataLayerControlsRenderer({ model }: SceneComponentProps<SceneDataLayerControls>) {\n const { layersMap } = model.useState();\n // Get only layers closest to the controls\n const layers = sceneGraph.getDataLayers(model, true);\n\n if (layers.length === 0) {\n return null;\n }\n\n return (\n <>\n {layers.map((l) => {\n const elementId = `data-layer-${l.state.key}`;\n return (\n <div\n key={elementId}\n style={{\n display: 'flex',\n }}\n >\n <ControlsLabel htmlFor={elementId} label={l.state.name} />\n <InlineSwitch id={elementId} value={layersMap[l.state.key!]} onChange={() => model.toggleLayer(l)} />\n </div>\n );\n })}\n </>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAWO,MAAM,+BAA+B,eAA6C,CAAA;AAAA,EAGhF,WAAc,GAAA;AAEnB,IAAA,KAAA,CAAM,EAAE,SAAA,EAAW,EAAC,EAAG,CAAA,CAAA;AAEvB,IAAA,IAAA,CAAK,oBAAqB,CAAA,MAAM,IAAK,CAAA,WAAA,EAAa,CAAA,CAAA;AAAA,GACpD;AAAA,EAEQ,WAAc,GAAA;AACpB,IAAA,MAAM,MAAS,GAAA,UAAA,CAAW,aAAc,CAAA,IAAA,EAAM,IAAI,CAAA,CAAA;AAClD,IAAK,IAAA,CAAA,QAAA,CAAS,EAAE,SAAW,EAAA,MAAA,CAAO,OAAO,CAAC,GAAA,EAAK,CAAO,KAAA,aAAA,CAAA,cAAA,CAAA,EAAA,EAAK,GAAL,CAAA,EAAA,EAAU,CAAC,CAAE,CAAA,KAAA,CAAM,MAAO,CAAE,CAAA,KAAA,CAAM,WAAc,CAAA,EAAA,EAAE,CAAA,EAAG,CAAA,CAAA;AAAA,GAC7G;AAAA,EAEO,YAAY,CAA2B,EAAA;AAC5C,IAAA,IAAA,CAAK,SAAS,EAAE,SAAA,EAAW,aAAK,CAAA,cAAA,CAAA,EAAA,EAAA,IAAA,CAAK,MAAM,SAAhB,CAAA,EAAA,EAA2B,CAAC,CAAA,CAAE,MAAM,GAAO,GAAA,CAAC,EAAE,KAAM,CAAA,SAAA,KAAa,CAAA,CAAA;AAC5F,IAAA,CAAA,CAAE,SAAS,EAAE,SAAA,EAAW,CAAC,CAAE,CAAA,KAAA,CAAM,WAAW,CAAA,CAAA;AAAA,GAC9C;AACF,CAAA;AAnBa,sBAAA,CACG,SAAY,GAAA,8BAAA,CAAA;AAoB5B,SAAS,8BAAA,CAA+B,EAAE,KAAA,EAAsD,EAAA;AAC9F,EAAA,MAAM,EAAE,SAAA,EAAc,GAAA,KAAA,CAAM,QAAS,EAAA,CAAA;AAErC,EAAA,MAAM,MAAS,GAAA,UAAA,CAAW,aAAc,CAAA,KAAA,EAAO,IAAI,CAAA,CAAA;AAEnD,EAAI,IAAA,MAAA,CAAO,WAAW,CAAG,EAAA;AACvB,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAEA,EAAA,uBAEK,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,EAAA,MAAA,CAAO,GAAI,CAAA,CAAC,CAAM,KAAA;AACjB,IAAM,MAAA,SAAA,GAAY,CAAc,WAAA,EAAA,CAAA,CAAE,KAAM,CAAA,GAAA,CAAA,CAAA,CAAA;AACxC,IAAA,uBACG,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA;AAAA,MACC,GAAK,EAAA,SAAA;AAAA,MACL,KAAO,EAAA;AAAA,QACL,OAAS,EAAA,MAAA;AAAA,OACX;AAAA,KAAA,kBAEC,KAAA,CAAA,aAAA,CAAA,aAAA,EAAA;AAAA,MAAc,OAAS,EAAA,SAAA;AAAA,MAAW,KAAA,EAAO,EAAE,KAAM,CAAA,IAAA;AAAA,KAAM,mBACvD,KAAA,CAAA,aAAA,CAAA,YAAA,EAAA;AAAA,MAAa,EAAI,EAAA,SAAA;AAAA,MAAW,KAAA,EAAO,SAAU,CAAA,CAAA,CAAE,KAAM,CAAA,GAAA,CAAA;AAAA,MAAO,QAAU,EAAA,MAAM,KAAM,CAAA,WAAA,CAAY,CAAC,CAAA;AAAA,KAAG,CACrG,CAAA,CAAA;AAAA,GAEH,CACH,CAAA,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"SceneDataLayerControls.js","sources":["../../../../src/querying/layers/SceneDataLayerControls.tsx"],"sourcesContent":["import { css } from '@emotion/css';\nimport { LoadingState } from '@grafana/schema';\nimport { InlineSwitch } from '@grafana/ui';\nimport React from 'react';\nimport { sceneGraph } from '../../core/sceneGraph';\nimport { SceneObjectBase } from '../../core/SceneObjectBase';\nimport { SceneComponentProps, SceneDataLayerProvider, SceneObjectState } from '../../core/types';\nimport { ControlsLabel } from '../../utils/ControlsLabel';\n\ninterface SceneDataLayerControlsState extends SceneObjectState {\n layersMap: Record<string, boolean>;\n}\n\nexport class SceneDataLayerControls extends SceneObjectBase<SceneDataLayerControlsState> {\n public static Component = SceneDataLayerControlsRenderer;\n\n public constructor() {\n // Holds the state of the layers, to avoid force re-rendering\n super({ layersMap: {} });\n\n this.addActivationHandler(() => this._onActivate());\n }\n\n private _onActivate() {\n const layers = sceneGraph.getDataLayers(this, true);\n this.setState({ layersMap: layers.reduce((acc, l) => ({ ...acc, [l.state.key!]: l.state.isEnabled }), {}) });\n }\n\n public toggleLayer(l: SceneDataLayerProvider) {\n this.setState({ layersMap: { ...this.state.layersMap, [l.state.key!]: !l.state.isEnabled } });\n l.setState({ isEnabled: !l.state.isEnabled });\n }\n}\n\nfunction SceneDataLayerControlsRenderer({ model }: SceneComponentProps<SceneDataLayerControls>) {\n const { layersMap } = model.useState();\n // Get only layers closest to the controls\n const layers = sceneGraph.getDataLayers(model, true);\n\n if (layers.length === 0) {\n return null;\n }\n\n return (\n <>\n {layers.map((l) => {\n const elementId = `data-layer-${l.state.key}`;\n return (\n <SceneDataLayerControl\n key={elementId}\n layer={l}\n onToggleLayer={() => model.toggleLayer(l)}\n isEnabled={layersMap[l.state.key!]}\n />\n );\n })}\n </>\n );\n}\n\ninterface SceneDataLayerControlProps {\n isEnabled: boolean;\n layer: SceneDataLayerProvider;\n onToggleLayer: () => void;\n}\n\nexport function SceneDataLayerControl({ layer, isEnabled, onToggleLayer }: SceneDataLayerControlProps) {\n const elementId = `data-layer-${layer.state.key}`;\n const { data } = layer.useState();\n const showLoading = Boolean(data && data.state === LoadingState.Loading);\n\n return (\n <div className={containerStyle}>\n <ControlsLabel\n htmlFor={elementId}\n isLoading={showLoading}\n onCancel={() => layer.cancelQuery?.()}\n label={layer.state.name}\n description={layer.state.description}\n error={layer.state.data?.errors?.[0].message}\n />\n <InlineSwitch id={elementId} value={isEnabled} onChange={onToggleLayer} />\n </div>\n );\n}\n\nconst containerStyle = css({ display: 'flex' });\n"],"names":["_a"],"mappings":"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"}
@@ -1,8 +1,10 @@
1
1
  import { DataTopic, arrayToDataFrame } from '@grafana/data';
2
- import { from, mergeMap, map, merge, mergeAll, reduce } from 'rxjs';
2
+ import { LoadingState } from '@grafana/schema';
3
+ import { map } from 'rxjs';
3
4
  import { emptyPanelData } from '../../../core/SceneDataNode.js';
4
5
  import { sceneGraph } from '../../../core/sceneGraph/index.js';
5
6
  import { getDataSource } from '../../../utils/getDataSource.js';
7
+ import { getMessageFromError } from '../../../utils/getMessageFromError.js';
6
8
  import { SceneDataLayerBase } from '../SceneDataLayerBase.js';
7
9
  import { executeAnnotationQuery } from './standardAnnotationQuery.js';
8
10
  import { postProcessQueryResult } from './utils.js';
@@ -38,70 +40,51 @@ class AnnotationsDataLayer extends SceneDataLayerBase {
38
40
  this._timeRangeSub = timeRange.subscribeToState(() => {
39
41
  this.runWithTimeRange(timeRange);
40
42
  });
41
- this.runLayer();
42
43
  }
43
44
  onDisable() {
44
45
  var _a;
45
46
  (_a = this._timeRangeSub) == null ? void 0 : _a.unsubscribe();
46
47
  }
47
- onActivate() {
48
- const deactivationHandle = super.onActivate();
49
- if (this.shouldRunQueriesOnActivate()) {
50
- this.runLayer();
51
- }
52
- return () => {
53
- deactivationHandle();
54
- };
55
- }
56
48
  runLayer() {
57
49
  const timeRange = sceneGraph.getTimeRange(this);
58
50
  this.runWithTimeRange(timeRange);
59
51
  }
60
52
  async runWithTimeRange(timeRange) {
61
- const { queries } = this.state;
53
+ const { query } = this.state;
62
54
  if (this.querySub) {
63
55
  this.querySub.unsubscribe();
64
56
  }
65
- if (!(queries == null ? void 0 : queries.length)) {
66
- this.onDataReceived([]);
67
- }
68
- const observables = queries.filter((q) => q.enable).map((query) => {
69
- return from(getDataSource(query.datasource || void 0, {})).pipe(
70
- mergeMap((ds) => {
71
- return executeAnnotationQuery(ds, timeRange, query);
72
- }),
57
+ try {
58
+ const ds = await getDataSource(query.datasource || void 0, {});
59
+ const queryExecution = executeAnnotationQuery(ds, timeRange, query).pipe(
73
60
  map((events) => {
74
- return postProcessQueryResult(query, events || []);
61
+ const processedEvents = postProcessQueryResult(query, events.events || []);
62
+ const stateUpdate = __spreadProps(__spreadValues({}, emptyPanelData), { state: events.state });
63
+ const df = arrayToDataFrame(processedEvents);
64
+ df.meta = __spreadProps(__spreadValues({}, df.meta), {
65
+ dataTopic: DataTopic.Annotations
66
+ });
67
+ stateUpdate.annotations = [df];
68
+ return stateUpdate;
75
69
  })
76
70
  );
77
- });
78
- this.querySub = merge(observables).pipe(
79
- mergeAll(),
80
- reduce((acc, value) => {
81
- acc = acc.concat(value);
82
- return acc;
83
- })
84
- ).subscribe((result) => {
85
- this.onDataReceived(result);
86
- });
87
- }
88
- onDataReceived(result) {
89
- const stateUpdate = __spreadValues({}, emptyPanelData);
90
- const df = arrayToDataFrame(result);
91
- df.meta = __spreadProps(__spreadValues({}, df.meta), {
92
- dataTopic: DataTopic.Annotations
93
- });
94
- stateUpdate.annotations = [df];
95
- this.publishResults(stateUpdate, DataTopic.Annotations);
96
- this.setState({
97
- data: stateUpdate
98
- });
99
- }
100
- shouldRunQueriesOnActivate() {
101
- if (this.state.data) {
102
- return false;
71
+ this.querySub = queryExecution.subscribe((stateUpdate) => {
72
+ this.publishResults(stateUpdate, DataTopic.Annotations);
73
+ });
74
+ } catch (e) {
75
+ this.publishResults(
76
+ __spreadProps(__spreadValues({}, emptyPanelData), {
77
+ state: LoadingState.Error,
78
+ errors: [
79
+ {
80
+ message: getMessageFromError(e)
81
+ }
82
+ ]
83
+ }),
84
+ DataTopic.Annotations
85
+ );
86
+ console.error("AnnotationsDataLayer error", e);
103
87
  }
104
- return true;
105
88
  }
106
89
  }
107
90
 
@@ -1 +1 @@
1
- {"version":3,"file":"AnnotationsDataLayer.js","sources":["../../../../../src/querying/layers/annotations/AnnotationsDataLayer.ts"],"sourcesContent":["import { AnnotationEvent, arrayToDataFrame, DataTopic, PanelData, AnnotationQuery } from '@grafana/data';\nimport { from, map, merge, mergeAll, mergeMap, reduce, Unsubscribable } from 'rxjs';\nimport { emptyPanelData } from '../../../core/SceneDataNode';\nimport { sceneGraph } from '../../../core/sceneGraph';\nimport { SceneDataLayerProvider, SceneTimeRangeLike, SceneDataLayerProviderState } from '../../../core/types';\nimport { getDataSource } from '../../../utils/getDataSource';\nimport { SceneDataLayerBase } from '../SceneDataLayerBase';\nimport { executeAnnotationQuery } from './standardAnnotationQuery';\nimport { postProcessQueryResult } from './utils';\n\ninterface AnnotationsDataLayerState extends SceneDataLayerProviderState {\n data?: PanelData;\n queries: AnnotationQuery[];\n}\n\nexport class AnnotationsDataLayer\n extends SceneDataLayerBase<AnnotationsDataLayerState>\n implements SceneDataLayerProvider\n{\n private _timeRangeSub: Unsubscribable | undefined;\n public topic = DataTopic.Annotations;\n\n public constructor(initialState: AnnotationsDataLayerState) {\n super({\n isEnabled: true,\n ...initialState,\n });\n }\n\n public onEnable(): void {\n const timeRange = sceneGraph.getTimeRange(this);\n\n this._timeRangeSub = timeRange.subscribeToState(() => {\n this.runWithTimeRange(timeRange);\n });\n\n this.runLayer();\n }\n\n public onDisable(): void {\n this._timeRangeSub?.unsubscribe();\n }\n\n protected onActivate() {\n const deactivationHandle = super.onActivate();\n\n if (this.shouldRunQueriesOnActivate()) {\n this.runLayer();\n }\n\n return () => {\n deactivationHandle();\n };\n }\n\n public runLayer() {\n const timeRange = sceneGraph.getTimeRange(this);\n this.runWithTimeRange(timeRange);\n }\n\n private async runWithTimeRange(timeRange: SceneTimeRangeLike) {\n const { queries } = this.state;\n\n if (this.querySub) {\n this.querySub.unsubscribe();\n }\n\n // Simple path when no queries exist\n if (!queries?.length) {\n this.onDataReceived([]);\n }\n\n const observables = queries\n // get enabled queries\n .filter((q) => q.enable)\n // execute queries & collect results\n .map((query) => {\n // TODO pass scopedVars\n return from(getDataSource(query.datasource || undefined, {})).pipe(\n mergeMap((ds) => {\n // TODO: There is a lot of AnnotationEvents[] -> DataFrame -> AnnotationEvents[] conversion going on here\n // This needs to be refactored an possibly optimized to use DataFrame only.\n // Seems like this is done to allow mappings to be applied by the data source using processEvents method.\n return executeAnnotationQuery(ds, timeRange, query);\n }),\n\n map((events) => {\n // Feels like this should be done in annotation processing, not as a separate step.\n return postProcessQueryResult(query, events || []);\n })\n );\n });\n\n this.querySub = merge(observables)\n .pipe(\n mergeAll(),\n // Combine all annotation results into a single array\n reduce((acc: AnnotationEvent[], value: AnnotationEvent[]) => {\n acc = acc.concat(value);\n return acc;\n })\n )\n .subscribe((result) => {\n this.onDataReceived(result);\n });\n }\n\n private onDataReceived(result: AnnotationEvent[]) {\n // This is only faking panel data\n const stateUpdate = { ...emptyPanelData };\n const df = arrayToDataFrame(result);\n df.meta = {\n ...df.meta,\n dataTopic: DataTopic.Annotations,\n };\n\n stateUpdate.annotations = [df];\n\n this.publishResults(stateUpdate, DataTopic.Annotations);\n\n this.setState({\n data: stateUpdate,\n });\n }\n\n private shouldRunQueriesOnActivate() {\n if (this.state.data) {\n return false;\n }\n\n return true;\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AnnotationsDataLayer.js","sources":["../../../../../src/querying/layers/annotations/AnnotationsDataLayer.ts"],"sourcesContent":["import { arrayToDataFrame, DataTopic, AnnotationQuery } from '@grafana/data';\nimport { LoadingState } from '@grafana/schema';\nimport { map, Unsubscribable } from 'rxjs';\nimport { emptyPanelData } from '../../../core/SceneDataNode';\nimport { sceneGraph } from '../../../core/sceneGraph';\nimport { SceneDataLayerProvider, SceneTimeRangeLike, SceneDataLayerProviderState } from '../../../core/types';\nimport { getDataSource } from '../../../utils/getDataSource';\nimport { getMessageFromError } from '../../../utils/getMessageFromError';\nimport { SceneDataLayerBase } from '../SceneDataLayerBase';\nimport { executeAnnotationQuery } from './standardAnnotationQuery';\nimport { postProcessQueryResult } from './utils';\n\ninterface AnnotationsDataLayerState extends SceneDataLayerProviderState {\n query: AnnotationQuery;\n}\n\nexport class AnnotationsDataLayer\n extends SceneDataLayerBase<AnnotationsDataLayerState>\n implements SceneDataLayerProvider\n{\n private _timeRangeSub: Unsubscribable | undefined;\n public topic = DataTopic.Annotations;\n\n public constructor(initialState: AnnotationsDataLayerState) {\n super({\n isEnabled: true,\n ...initialState,\n });\n }\n\n public onEnable(): void {\n const timeRange = sceneGraph.getTimeRange(this);\n\n this._timeRangeSub = timeRange.subscribeToState(() => {\n this.runWithTimeRange(timeRange);\n });\n }\n\n public onDisable(): void {\n this._timeRangeSub?.unsubscribe();\n }\n\n public runLayer() {\n const timeRange = sceneGraph.getTimeRange(this);\n this.runWithTimeRange(timeRange);\n }\n\n private async runWithTimeRange(timeRange: SceneTimeRangeLike) {\n const { query } = this.state;\n\n if (this.querySub) {\n this.querySub.unsubscribe();\n }\n\n try {\n const ds = await getDataSource(query.datasource || undefined, {});\n\n const queryExecution = executeAnnotationQuery(ds, timeRange, query).pipe(\n map((events) => {\n // Feels like this should be done in annotation processing, not as a separate step.\n const processedEvents = postProcessQueryResult(query, events.events || []);\n const stateUpdate = { ...emptyPanelData, state: events.state };\n const df = arrayToDataFrame(processedEvents);\n df.meta = {\n ...df.meta,\n dataTopic: DataTopic.Annotations,\n };\n\n stateUpdate.annotations = [df];\n return stateUpdate;\n })\n );\n\n this.querySub = queryExecution.subscribe((stateUpdate) => {\n this.publishResults(stateUpdate, DataTopic.Annotations);\n });\n } catch (e) {\n this.publishResults(\n {\n ...emptyPanelData,\n state: LoadingState.Error,\n errors: [\n {\n message: getMessageFromError(e),\n },\n ],\n },\n DataTopic.Annotations\n );\n console.error('AnnotationsDataLayer error', e);\n }\n }\n}\n"],"names":[],"mappings":"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"}
@@ -3,6 +3,7 @@ import { map, mergeMap } from 'rxjs/operators';
3
3
  import { rangeUtil, CoreApp, DataTopic } from '@grafana/data';
4
4
  import { getRunRequest } from '@grafana/runtime';
5
5
  import { shouldUseLegacyRunner, standardAnnotationSupport } from './standardAnnotationsSupport.js';
6
+ import { LoadingState } from '@grafana/schema';
6
7
 
7
8
  var __defProp = Object.defineProperty;
8
9
  var __defProps = Object.defineProperties;
@@ -38,17 +39,28 @@ function executeAnnotationQuery(datasource, timeRange, query) {
38
39
  annotation: query,
39
40
  dashboard: {}
40
41
  })
41
- ).pipe(map((events) => events));
42
+ ).pipe(
43
+ map((events) => ({
44
+ state: LoadingState.Done,
45
+ events
46
+ }))
47
+ );
42
48
  }
43
49
  const processor = __spreadValues(__spreadValues({}, standardAnnotationSupport), datasource.annotations);
44
50
  const annotationWithDefaults = __spreadValues(__spreadValues({}, (_a = processor.getDefaultQuery) == null ? void 0 : _a.call(processor)), query);
45
51
  const annotation = processor.prepareAnnotation(annotationWithDefaults);
46
52
  if (!annotation) {
47
- return of([]);
53
+ return of({
54
+ state: LoadingState.Done,
55
+ events: []
56
+ });
48
57
  }
49
58
  const processedQuery = processor.prepareQuery(annotation);
50
59
  if (!processedQuery) {
51
- return of([]);
60
+ return of({
61
+ state: LoadingState.Done,
62
+ events: []
63
+ });
52
64
  }
53
65
  const maxDataPoints = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
54
66
  const interval = rangeUtil.calculateInterval(timeRange.state.value, maxDataPoints, datasource.interval);
@@ -77,7 +89,10 @@ function executeAnnotationQuery(datasource, timeRange, query) {
77
89
  mergeMap((panelData) => {
78
90
  const data = (panelData == null ? void 0 : panelData.series.length) ? panelData.series : panelData.annotations;
79
91
  if (!(data == null ? void 0 : data.length)) {
80
- return of([]);
92
+ return of({
93
+ state: panelData.state,
94
+ events: []
95
+ });
81
96
  }
82
97
  data.forEach((frame) => {
83
98
  var _a2;
@@ -85,7 +100,14 @@ function executeAnnotationQuery(datasource, timeRange, query) {
85
100
  frame.meta = __spreadProps(__spreadValues({}, frame.meta || {}), { dataTopic: DataTopic.Annotations });
86
101
  }
87
102
  });
88
- return processor.processEvents(annotation, data).pipe(map((events) => events != null ? events : []));
103
+ return processor.processEvents(annotation, data).pipe(
104
+ map((events) => {
105
+ return {
106
+ state: panelData.state,
107
+ events: events || []
108
+ };
109
+ })
110
+ );
89
111
  })
90
112
  );
91
113
  }
@@ -1 +1 @@
1
- {"version":3,"file":"standardAnnotationQuery.js","sources":["../../../../../src/querying/layers/annotations/standardAnnotationQuery.ts"],"sourcesContent":["import { from, Observable, of } from 'rxjs';\nimport { map, mergeMap } from 'rxjs/operators';\n\nimport {\n AnnotationEvent,\n AnnotationQuery,\n CoreApp,\n DataQueryRequest,\n DataSourceApi,\n DataTopic,\n PanelModel,\n rangeUtil,\n ScopedVars,\n} from '@grafana/data';\n\nimport { getRunRequest } from '@grafana/runtime';\nimport { shouldUseLegacyRunner, standardAnnotationSupport } from './standardAnnotationsSupport';\nimport { Dashboard } from '@grafana/schema';\nimport { SceneTimeRangeLike } from '../../../core/types';\nlet counter = 100;\nfunction getNextRequestId() {\n return 'AQ' + counter++;\n}\n\nexport interface AnnotationQueryOptions {\n dashboard: Dashboard;\n panel: PanelModel;\n}\n\nexport function executeAnnotationQuery(\n datasource: DataSourceApi,\n timeRange: SceneTimeRangeLike,\n query: AnnotationQuery\n): Observable<AnnotationEvent[]> {\n // Check if we should use the old annotationQuery method\n if (datasource.annotationQuery && shouldUseLegacyRunner(datasource)) {\n console.warn('Using deprecated annotationQuery method, please upgrade your datasource');\n return from(\n datasource.annotationQuery({\n range: timeRange.state.value,\n rangeRaw: timeRange.state.value.raw,\n annotation: query,\n dashboard: {},\n })\n ).pipe(map((events) => events));\n }\n\n // Standard API for annotations support. Spread in datasource annotations support overrides\n const processor = {\n ...standardAnnotationSupport,\n ...datasource.annotations,\n };\n\n const annotationWithDefaults = {\n // Default query provided by a data source\n ...processor.getDefaultQuery?.(),\n ...query,\n };\n\n // Data source query migrations\n const annotation = processor.prepareAnnotation!(annotationWithDefaults);\n if (!annotation) {\n return of([]);\n }\n\n const processedQuery = processor.prepareQuery!(annotation);\n if (!processedQuery) {\n return of([]);\n }\n\n // No more points than pixels\n const maxDataPoints = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;\n\n // Add interval to annotation queries\n const interval = rangeUtil.calculateInterval(timeRange.state.value, maxDataPoints, datasource.interval);\n\n const scopedVars: ScopedVars = {\n __interval: { text: interval.interval, value: interval.interval },\n __interval_ms: { text: interval.intervalMs.toString(), value: interval.intervalMs },\n __annotation: { text: annotation.name, value: annotation },\n };\n\n const queryRequest: DataQueryRequest = {\n startTime: Date.now(),\n requestId: getNextRequestId(),\n range: timeRange.state.value,\n maxDataPoints,\n scopedVars,\n ...interval,\n app: CoreApp.Dashboard,\n timezone: timeRange.getTimeZone(),\n targets: [\n {\n ...processedQuery,\n refId: 'Anno',\n },\n ],\n // TODO\n //publicDashboardAccessToken: options.dashboard.meta.publicDashboardAccessToken,\n };\n\n const runRequest = getRunRequest();\n\n return runRequest(datasource, queryRequest).pipe(\n mergeMap((panelData) => {\n // Some annotations set the topic already\n const data = panelData?.series.length ? panelData.series : panelData.annotations;\n if (!data?.length) {\n return of([]);\n }\n\n // Add data topic to each frame\n data.forEach((frame) => {\n // If data topic has not been provided by the data source, make sure it's set correctly\n if (!frame.meta?.dataTopic) {\n frame.meta = { ...(frame.meta || {}), dataTopic: DataTopic.Annotations };\n }\n });\n\n return processor.processEvents!(annotation, data).pipe(map((events) => events ?? []));\n })\n );\n}\n"],"names":["_a"],"mappings":"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"}
1
+ {"version":3,"file":"standardAnnotationQuery.js","sources":["../../../../../src/querying/layers/annotations/standardAnnotationQuery.ts"],"sourcesContent":["import { from, Observable, of } from 'rxjs';\nimport { map, mergeMap } from 'rxjs/operators';\n\nimport {\n AnnotationEvent,\n AnnotationQuery,\n CoreApp,\n DataQueryRequest,\n DataSourceApi,\n DataTopic,\n PanelModel,\n rangeUtil,\n ScopedVars,\n} from '@grafana/data';\n\nimport { getRunRequest } from '@grafana/runtime';\nimport { shouldUseLegacyRunner, standardAnnotationSupport } from './standardAnnotationsSupport';\nimport { Dashboard, LoadingState } from '@grafana/schema';\nimport { SceneTimeRangeLike } from '../../../core/types';\nlet counter = 100;\nfunction getNextRequestId() {\n return 'AQ' + counter++;\n}\n\nexport interface AnnotationQueryOptions {\n dashboard: Dashboard;\n panel: PanelModel;\n}\n\nexport function executeAnnotationQuery(\n datasource: DataSourceApi,\n timeRange: SceneTimeRangeLike,\n query: AnnotationQuery\n): Observable<{ state: LoadingState; events: AnnotationEvent[] }> {\n // Check if we should use the old annotationQuery method\n if (datasource.annotationQuery && shouldUseLegacyRunner(datasource)) {\n console.warn('Using deprecated annotationQuery method, please upgrade your datasource');\n return from(\n datasource.annotationQuery({\n range: timeRange.state.value,\n rangeRaw: timeRange.state.value.raw,\n annotation: query,\n dashboard: {},\n })\n ).pipe(\n map((events) => ({\n state: LoadingState.Done,\n events,\n }))\n );\n }\n\n // Standard API for annotations support. Spread in datasource annotations support overrides\n const processor = {\n ...standardAnnotationSupport,\n ...datasource.annotations,\n };\n\n const annotationWithDefaults = {\n // Default query provided by a data source\n ...processor.getDefaultQuery?.(),\n ...query,\n };\n\n // Data source query migrations\n const annotation = processor.prepareAnnotation!(annotationWithDefaults);\n if (!annotation) {\n return of({\n state: LoadingState.Done,\n events: [],\n });\n }\n\n const processedQuery = processor.prepareQuery!(annotation);\n if (!processedQuery) {\n return of({\n state: LoadingState.Done,\n events: [],\n });\n }\n\n // No more points than pixels\n const maxDataPoints = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;\n\n // Add interval to annotation queries\n const interval = rangeUtil.calculateInterval(timeRange.state.value, maxDataPoints, datasource.interval);\n\n const scopedVars: ScopedVars = {\n __interval: { text: interval.interval, value: interval.interval },\n __interval_ms: { text: interval.intervalMs.toString(), value: interval.intervalMs },\n __annotation: { text: annotation.name, value: annotation },\n };\n\n const queryRequest: DataQueryRequest = {\n startTime: Date.now(),\n requestId: getNextRequestId(),\n range: timeRange.state.value,\n maxDataPoints,\n scopedVars,\n ...interval,\n app: CoreApp.Dashboard,\n timezone: timeRange.getTimeZone(),\n targets: [\n {\n ...processedQuery,\n refId: 'Anno',\n },\n ],\n // TODO\n //publicDashboardAccessToken: options.dashboard.meta.publicDashboardAccessToken,\n };\n\n const runRequest = getRunRequest();\n\n return runRequest(datasource, queryRequest).pipe(\n mergeMap((panelData) => {\n // Some annotations set the topic already\n const data = panelData?.series.length ? panelData.series : panelData.annotations;\n\n if (!data?.length) {\n return of({\n state: panelData.state,\n events: [],\n });\n }\n\n // Add data topic to each frame\n data.forEach((frame) => {\n // If data topic has not been provided by the data source, make sure it's set correctly\n if (!frame.meta?.dataTopic) {\n frame.meta = { ...(frame.meta || {}), dataTopic: DataTopic.Annotations };\n }\n });\n\n return processor.processEvents!(annotation, data).pipe(\n map((events) => {\n return {\n state: panelData.state,\n events: events || [],\n };\n })\n );\n })\n );\n}\n"],"names":["_a"],"mappings":"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"}
@@ -1,25 +1,47 @@
1
1
  import React from 'react';
2
- import { useStyles2, Tooltip } from '@grafana/ui';
2
+ import { useStyles2, useTheme2, Tooltip, Icon } from '@grafana/ui';
3
3
  import { selectors } from '@grafana/e2e-selectors';
4
4
  import { css } from '@emotion/css';
5
+ import { LoadingIndicator } from './LoadingIndicator.js';
5
6
 
6
7
  function ControlsLabel(props) {
7
8
  const styles = useStyles2(getStyles);
9
+ const theme = useTheme2();
10
+ const loadingIndicator = Boolean(props.isLoading) ? /* @__PURE__ */ React.createElement("div", {
11
+ style: { marginLeft: theme.spacing(1), marginTop: "-1px" }
12
+ }, /* @__PURE__ */ React.createElement(LoadingIndicator, {
13
+ onCancel: (e) => {
14
+ var _a;
15
+ e.preventDefault();
16
+ e.stopPropagation();
17
+ (_a = props.onCancel) == null ? void 0 : _a.call(props);
18
+ }
19
+ })) : null;
8
20
  if (props.description) {
9
- return /* @__PURE__ */ React.createElement(Tooltip, {
10
- content: props.description,
11
- placement: "bottom"
12
- }, /* @__PURE__ */ React.createElement("label", {
21
+ return /* @__PURE__ */ React.createElement("label", {
13
22
  className: styles.label,
14
- "data-testid": selectors.pages.Dashboard.SubMenu.submenuItemLabels(props.label),
23
+ "data-testid": typeof props.label === "string" ? selectors.pages.Dashboard.SubMenu.submenuItemLabels(props.label) : "",
15
24
  htmlFor: props.htmlFor
16
- }, props.label));
25
+ }, /* @__PURE__ */ React.createElement(Tooltip, {
26
+ content: props.description,
27
+ placement: "bottom"
28
+ }, /* @__PURE__ */ React.createElement("span", null, props.label)), loadingIndicator);
29
+ }
30
+ let errorIndicator = null;
31
+ if (props.error) {
32
+ errorIndicator = /* @__PURE__ */ React.createElement(Tooltip, {
33
+ content: props.error,
34
+ placement: "bottom"
35
+ }, /* @__PURE__ */ React.createElement(Icon, {
36
+ className: styles.errorIcon,
37
+ name: "exclamation-triangle"
38
+ }));
17
39
  }
18
40
  return /* @__PURE__ */ React.createElement("label", {
19
41
  className: styles.label,
20
- "data-testid": selectors.pages.Dashboard.SubMenu.submenuItemLabels(props.label),
42
+ "data-testid": typeof props.label === "string" ? selectors.pages.Dashboard.SubMenu.submenuItemLabels(props.label) : "",
21
43
  htmlFor: props.htmlFor
22
- }, props.label);
44
+ }, errorIndicator, props.label, loadingIndicator);
23
45
  }
24
46
  const getStyles = (theme) => ({
25
47
  label: css({
@@ -36,6 +58,10 @@ const getStyles = (theme) => ({
36
58
  position: "relative",
37
59
  right: -1,
38
60
  whiteSpace: "nowrap"
61
+ }),
62
+ errorIcon: css({
63
+ color: theme.colors.error.text,
64
+ marginRight: theme.spacing(1)
39
65
  })
40
66
  });
41
67
 
@@ -1 +1 @@
1
- {"version":3,"file":"ControlsLabel.js","sources":["../../../src/utils/ControlsLabel.tsx"],"sourcesContent":["import React from 'react';\nimport { Tooltip, useStyles2 } from '@grafana/ui';\nimport { selectors } from '@grafana/e2e-selectors';\nimport { GrafanaTheme2 } from '@grafana/data';\nimport { css } from '@emotion/css';\n\ninterface ControlsLabelProps {\n label: string;\n htmlFor: string;\n description?: string;\n}\n\nexport function ControlsLabel(props: ControlsLabelProps) {\n const styles = useStyles2(getStyles);\n\n if (props.description) {\n return (\n <Tooltip content={props.description} placement={'bottom'}>\n <label\n className={styles.label}\n data-testid={selectors.pages.Dashboard.SubMenu.submenuItemLabels(props.label)}\n htmlFor={props.htmlFor}\n >\n {props.label}\n </label>\n </Tooltip>\n );\n }\n\n return (\n <label\n className={styles.label}\n data-testid={selectors.pages.Dashboard.SubMenu.submenuItemLabels(props.label)}\n htmlFor={props.htmlFor}\n >\n {props.label}\n </label>\n );\n}\n\nconst getStyles = (theme: GrafanaTheme2) => ({\n label: css({\n background: theme.isDark ? theme.colors.background.primary : theme.colors.background.secondary,\n display: `flex`,\n alignItems: 'center',\n padding: theme.spacing(0, 1),\n fontWeight: theme.typography.fontWeightMedium,\n fontSize: theme.typography.bodySmall.fontSize,\n height: theme.spacing(theme.components.height.md),\n lineHeight: theme.spacing(theme.components.height.md),\n borderRadius: theme.shape.borderRadius(1),\n border: `1px solid ${theme.components.input.borderColor}`,\n position: 'relative',\n // To make the border line up with the input border\n right: -1,\n whiteSpace: 'nowrap',\n }),\n});\n"],"names":[],"mappings":";;;;;AAYO,SAAS,cAAc,KAA2B,EAAA;AACvD,EAAM,MAAA,MAAA,GAAS,WAAW,SAAS,CAAA,CAAA;AAEnC,EAAA,IAAI,MAAM,WAAa,EAAA;AACrB,IAAA,uBACG,KAAA,CAAA,aAAA,CAAA,OAAA,EAAA;AAAA,MAAQ,SAAS,KAAM,CAAA,WAAA;AAAA,MAAa,SAAW,EAAA,QAAA;AAAA,KAAA,kBAC7C,KAAA,CAAA,aAAA,CAAA,OAAA,EAAA;AAAA,MACC,WAAW,MAAO,CAAA,KAAA;AAAA,MAClB,eAAa,SAAU,CAAA,KAAA,CAAM,UAAU,OAAQ,CAAA,iBAAA,CAAkB,MAAM,KAAK,CAAA;AAAA,MAC5E,SAAS,KAAM,CAAA,OAAA;AAAA,KAEd,EAAA,KAAA,CAAM,KACT,CACF,CAAA,CAAA;AAAA,GAEJ;AAEA,EAAA,uBACG,KAAA,CAAA,aAAA,CAAA,OAAA,EAAA;AAAA,IACC,WAAW,MAAO,CAAA,KAAA;AAAA,IAClB,eAAa,SAAU,CAAA,KAAA,CAAM,UAAU,OAAQ,CAAA,iBAAA,CAAkB,MAAM,KAAK,CAAA;AAAA,IAC5E,SAAS,KAAM,CAAA,OAAA;AAAA,GAAA,EAEd,MAAM,KACT,CAAA,CAAA;AAEJ,CAAA;AAEA,MAAM,SAAA,GAAY,CAAC,KAA0B,MAAA;AAAA,EAC3C,OAAO,GAAI,CAAA;AAAA,IACT,UAAA,EAAY,MAAM,MAAS,GAAA,KAAA,CAAM,OAAO,UAAW,CAAA,OAAA,GAAU,KAAM,CAAA,MAAA,CAAO,UAAW,CAAA,SAAA;AAAA,IACrF,OAAS,EAAA,CAAA,IAAA,CAAA;AAAA,IACT,UAAY,EAAA,QAAA;AAAA,IACZ,OAAS,EAAA,KAAA,CAAM,OAAQ,CAAA,CAAA,EAAG,CAAC,CAAA;AAAA,IAC3B,UAAA,EAAY,MAAM,UAAW,CAAA,gBAAA;AAAA,IAC7B,QAAA,EAAU,KAAM,CAAA,UAAA,CAAW,SAAU,CAAA,QAAA;AAAA,IACrC,QAAQ,KAAM,CAAA,OAAA,CAAQ,KAAM,CAAA,UAAA,CAAW,OAAO,EAAE,CAAA;AAAA,IAChD,YAAY,KAAM,CAAA,OAAA,CAAQ,KAAM,CAAA,UAAA,CAAW,OAAO,EAAE,CAAA;AAAA,IACpD,YAAc,EAAA,KAAA,CAAM,KAAM,CAAA,YAAA,CAAa,CAAC,CAAA;AAAA,IACxC,MAAQ,EAAA,CAAA,UAAA,EAAa,KAAM,CAAA,UAAA,CAAW,KAAM,CAAA,WAAA,CAAA,CAAA;AAAA,IAC5C,QAAU,EAAA,UAAA;AAAA,IAEV,KAAO,EAAA,CAAA,CAAA;AAAA,IACP,UAAY,EAAA,QAAA;AAAA,GACb,CAAA;AACH,CAAA,CAAA;;;;"}
1
+ {"version":3,"file":"ControlsLabel.js","sources":["../../../src/utils/ControlsLabel.tsx"],"sourcesContent":["import React from 'react';\nimport { Icon, Tooltip, useStyles2, useTheme2 } from '@grafana/ui';\nimport { selectors } from '@grafana/e2e-selectors';\nimport { GrafanaTheme2 } from '@grafana/data';\nimport { css } from '@emotion/css';\nimport { LoadingIndicator } from './LoadingIndicator';\n\ninterface ControlsLabelProps {\n label: string;\n htmlFor: string;\n description?: string;\n isLoading?: boolean;\n error?: string;\n onCancel?: () => void;\n}\n\nexport function ControlsLabel(props: ControlsLabelProps) {\n const styles = useStyles2(getStyles);\n const theme = useTheme2();\n\n const loadingIndicator = Boolean(props.isLoading) ? (\n <div style={{ marginLeft: theme.spacing(1), marginTop: '-1px' }}>\n <LoadingIndicator\n onCancel={(e) => {\n e.preventDefault();\n e.stopPropagation();\n props.onCancel?.();\n }}\n />\n </div>\n ) : null;\n\n if (props.description) {\n return (\n <label\n className={styles.label}\n data-testid={\n typeof props.label === 'string' ? selectors.pages.Dashboard.SubMenu.submenuItemLabels(props.label) : ''\n }\n htmlFor={props.htmlFor}\n >\n <Tooltip content={props.description} placement={'bottom'}>\n <span>{props.label}</span>\n </Tooltip>\n {loadingIndicator}\n </label>\n );\n }\n\n let errorIndicator = null;\n if (props.error) {\n errorIndicator = (\n <Tooltip content={props.error} placement={'bottom'}>\n <Icon className={styles.errorIcon} name=\"exclamation-triangle\" />\n </Tooltip>\n );\n }\n\n return (\n <label\n className={styles.label}\n data-testid={\n typeof props.label === 'string' ? selectors.pages.Dashboard.SubMenu.submenuItemLabels(props.label) : ''\n }\n htmlFor={props.htmlFor}\n >\n {errorIndicator}\n {props.label}\n {loadingIndicator}\n </label>\n );\n}\n\nconst getStyles = (theme: GrafanaTheme2) => ({\n label: css({\n background: theme.isDark ? theme.colors.background.primary : theme.colors.background.secondary,\n display: `flex`,\n alignItems: 'center',\n padding: theme.spacing(0, 1),\n fontWeight: theme.typography.fontWeightMedium,\n fontSize: theme.typography.bodySmall.fontSize,\n height: theme.spacing(theme.components.height.md),\n lineHeight: theme.spacing(theme.components.height.md),\n borderRadius: theme.shape.borderRadius(1),\n border: `1px solid ${theme.components.input.borderColor}`,\n position: 'relative',\n // To make the border line up with the input border\n right: -1,\n whiteSpace: 'nowrap',\n }),\n\n errorIcon: css({\n color: theme.colors.error.text,\n marginRight: theme.spacing(1),\n }),\n});\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { selectors } from '@grafana/e2e-selectors';
2
+ import { Tooltip, Icon } from '@grafana/ui';
3
+ import React from 'react';
4
+
5
+ function LoadingIndicator(props) {
6
+ return /* @__PURE__ */ React.createElement(Tooltip, {
7
+ content: "Cancel query"
8
+ }, /* @__PURE__ */ React.createElement(Icon, {
9
+ className: "spin-clockwise",
10
+ name: "sync",
11
+ size: "xs",
12
+ "aria-label": selectors.components.LoadingIndicator.icon,
13
+ role: "button",
14
+ onMouseDown: (e) => {
15
+ props.onCancel(e);
16
+ }
17
+ }));
18
+ }
19
+
20
+ export { LoadingIndicator };
21
+ //# sourceMappingURL=LoadingIndicator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoadingIndicator.js","sources":["../../../src/utils/LoadingIndicator.tsx"],"sourcesContent":["import { selectors } from '@grafana/e2e-selectors';\nimport { Icon, Tooltip } from '@grafana/ui';\nimport React, { useCallback } from 'react';\nimport { LoadingIndicatorProps as SelectLoadingIndicatorProps } from 'react-select';\n\nexport const SelectLoadingIndicator = ({\n innerProps,\n ...props\n}: SelectLoadingIndicatorProps & { selectProps: { onCancel: () => void } }) => {\n const { onCancel } = props.selectProps;\n const onMouseDown = useCallback(\n (event: React.MouseEvent) => {\n event.preventDefault();\n event.stopPropagation();\n onCancel();\n },\n [onCancel]\n );\n\n return <LoadingIndicator onCancel={onMouseDown} />;\n};\n\ninterface LoadingIndicatorProps {\n onCancel: (event: React.MouseEvent) => void;\n}\n\nexport function LoadingIndicator(props: LoadingIndicatorProps) {\n return (\n <Tooltip content=\"Cancel query\">\n <Icon\n className=\"spin-clockwise\"\n name=\"sync\"\n size=\"xs\"\n aria-label={selectors.components.LoadingIndicator.icon}\n role=\"button\"\n onMouseDown={(e) => {\n props.onCancel(e);\n }}\n />\n </Tooltip>\n );\n}\n"],"names":[],"mappings":";;;;AA0BO,SAAS,iBAAiB,KAA8B,EAAA;AAC7D,EAAA,uBACG,KAAA,CAAA,aAAA,CAAA,OAAA,EAAA;AAAA,IAAQ,OAAQ,EAAA,cAAA;AAAA,GAAA,kBACd,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA;AAAA,IACC,SAAU,EAAA,gBAAA;AAAA,IACV,IAAK,EAAA,MAAA;AAAA,IACL,IAAK,EAAA,IAAA;AAAA,IACL,YAAA,EAAY,SAAU,CAAA,UAAA,CAAW,gBAAiB,CAAA,IAAA;AAAA,IAClD,IAAK,EAAA,QAAA;AAAA,IACL,WAAA,EAAa,CAAC,CAAM,KAAA;AAClB,MAAA,KAAA,CAAM,SAAS,CAAC,CAAA,CAAA;AAAA,KAClB;AAAA,GACF,CACF,CAAA,CAAA;AAEJ;;;;"}