@grafana/scenes 4.18.0 → 4.20.0--canary.705.9031064372.0

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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ # v4.19.0 (Fri May 10 2024)
2
+
3
+ #### 🚀 Enhancement
4
+
5
+ - SceneDataTransformer: Performance optimizations [#725](https://github.com/grafana/scenes/pull/725) ([@torkelo](https://github.com/torkelo))
6
+ - Variables: Do not update value when value and text are the same [#726](https://github.com/grafana/scenes/pull/726) ([@torkelo](https://github.com/torkelo))
7
+
8
+ #### Authors: 1
9
+
10
+ - Torkel Ödegaard ([@torkelo](https://github.com/torkelo))
11
+
12
+ ---
13
+
1
14
  # v4.18.0 (Fri May 10 2024)
2
15
 
3
16
  #### 🚀 Enhancement
@@ -75,7 +75,7 @@ class SceneDataTransformer extends SceneObjectBase {
75
75
  return true;
76
76
  }
77
77
  reprocessTransformations() {
78
- this.transform(this.getSourceData().state.data);
78
+ this.transform(this.getSourceData().state.data, true);
79
79
  }
80
80
  cancelQuery() {
81
81
  var _a, _b;
@@ -84,8 +84,42 @@ class SceneDataTransformer extends SceneObjectBase {
84
84
  getResultsStream() {
85
85
  return this._results;
86
86
  }
87
- transform(data) {
87
+ clone(withState) {
88
+ const clone = super.clone(withState);
89
+ if (this._prevDataFromSource) {
90
+ clone["_prevDataFromSource"] = this._prevDataFromSource;
91
+ }
92
+ return clone;
93
+ }
94
+ haveAlreadyTransformedData(data) {
95
+ if (!this._prevDataFromSource) {
96
+ return false;
97
+ }
98
+ if (data === this._prevDataFromSource) {
99
+ return true;
100
+ }
101
+ const { series, annotations } = this._prevDataFromSource;
102
+ if (data.series === series && data.annotations === annotations) {
103
+ if (this.state.data && data.state !== this.state.data.state) {
104
+ this.setState({ data: __spreadProps(__spreadValues({}, this.state.data), { state: data.state }) });
105
+ }
106
+ return true;
107
+ }
108
+ return false;
109
+ }
110
+ transform(data, force = false) {
88
111
  var _a;
112
+ if (this.state.transformations.length === 0 || !data) {
113
+ this._prevDataFromSource = data;
114
+ this.setState({ data });
115
+ if (data) {
116
+ this._results.next({ origin: this, data });
117
+ }
118
+ return;
119
+ }
120
+ if (!force && this.haveAlreadyTransformedData(data)) {
121
+ return;
122
+ }
89
123
  const seriesTransformations = this.state.transformations.filter((transformation) => {
90
124
  if ("options" in transformation || "topic" in transformation) {
91
125
  return transformation.topic == null || transformation.topic === DataTopic.Series;
@@ -98,13 +132,6 @@ class SceneDataTransformer extends SceneObjectBase {
98
132
  }
99
133
  return false;
100
134
  }).map((transformation) => "operator" in transformation ? transformation.operator : transformation);
101
- if (this.state.transformations.length === 0 || !data) {
102
- this.setState({ data });
103
- if (data) {
104
- this._results.next({ origin: this, data });
105
- }
106
- return;
107
- }
108
135
  if (this._transformSub) {
109
136
  this._transformSub.unsubscribe();
110
137
  }
@@ -139,9 +166,10 @@ class SceneDataTransformer extends SceneObjectBase {
139
166
  });
140
167
  return of(result);
141
168
  })
142
- ).subscribe((data2) => {
143
- this.setState({ data: data2 });
144
- this._results.next({ origin: this, data: data2 });
169
+ ).subscribe((transformedData) => {
170
+ this.setState({ data: transformedData });
171
+ this._results.next({ origin: this, data: transformedData });
172
+ this._prevDataFromSource = data;
145
173
  });
146
174
  }
147
175
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SceneDataTransformer.js","sources":["../../../src/querying/SceneDataTransformer.ts"],"sourcesContent":["import { DataTopic, DataTransformerConfig, LoadingState, PanelData, transformDataFrame } from '@grafana/data';\nimport { toDataQueryError } from '@grafana/runtime';\nimport { catchError, forkJoin, map, of, ReplaySubject, Unsubscribable } from 'rxjs';\nimport { sceneGraph } from '../core/sceneGraph';\nimport { SceneObjectBase } from '../core/SceneObjectBase';\nimport { CustomTransformerDefinition, SceneDataProvider, SceneDataProviderResult, SceneDataState } from '../core/types';\nimport { VariableDependencyConfig } from '../variables/VariableDependencyConfig';\nimport { SceneDataLayerSet } from './SceneDataLayerSet';\n\nexport interface SceneDataTransformerState extends SceneDataState {\n /**\n * Array of standard transformation configs and custom transform operators\n */\n transformations: Array<DataTransformerConfig | CustomTransformerDefinition>;\n}\n\n/**\n * You can use this as a $data object. It can either transform an inner $data DataProvider or if that is not set it will\n * subscribe to a DataProvider higher up in the scene graph and transform its data.\n *\n * The transformations array supports custom (runtime defined) transformation as well as declarative core transformations.\n * You can manually re-process the transformations by calling reprocessTransformations(). This is useful if you have\n * transformations that depend on other scene object states.\n */\nexport class SceneDataTransformer extends SceneObjectBase<SceneDataTransformerState> implements SceneDataProvider {\n private _transformSub?: Unsubscribable;\n private _results = new ReplaySubject<SceneDataProviderResult>(1);\n\n /**\n * Scan transformations for variable usage and re-process transforms when a variable values change\n */\n protected _variableDependency: VariableDependencyConfig<SceneDataTransformerState> = new VariableDependencyConfig(\n this,\n {\n statePaths: ['transformations'],\n onReferencedVariableValueChanged: () => this.reprocessTransformations(),\n }\n );\n\n public constructor(state: SceneDataTransformerState) {\n super(state);\n\n this.addActivationHandler(() => this.activationHandler());\n }\n\n private activationHandler() {\n const sourceData = this.getSourceData();\n\n this._subs.add(sourceData.subscribeToState((state) => this.transform(state.data)));\n\n if (sourceData.state.data) {\n this.transform(sourceData.state.data);\n }\n\n return () => {\n if (this._transformSub) {\n this._transformSub.unsubscribe();\n }\n };\n }\n\n private getSourceData(): SceneDataProvider {\n if (this.state.$data) {\n if (this.state.$data instanceof SceneDataLayerSet) {\n throw new Error('SceneDataLayerSet can not be used as data provider for SceneDataTransformer.');\n }\n return this.state.$data;\n }\n\n if (!this.parent || !this.parent.parent) {\n throw new Error('SceneDataTransformer must either have $data set on it or have a parent.parent with $data');\n }\n\n return sceneGraph.getData(this.parent.parent);\n }\n\n public setContainerWidth(width: number) {\n if (this.state.$data && this.state.$data.setContainerWidth) {\n this.state.$data.setContainerWidth(width);\n }\n }\n\n public isDataReadyToDisplay() {\n const dataObject = this.getSourceData();\n if (dataObject.isDataReadyToDisplay) {\n return dataObject.isDataReadyToDisplay();\n }\n\n return true;\n }\n\n public reprocessTransformations() {\n this.transform(this.getSourceData().state.data);\n }\n\n public cancelQuery() {\n this.getSourceData().cancelQuery?.();\n }\n\n public getResultsStream() {\n return this._results;\n }\n\n private transform(data: PanelData | undefined) {\n const seriesTransformations = this.state.transformations\n .filter((transformation) => {\n if ('options' in transformation || 'topic' in transformation) {\n return transformation.topic == null || transformation.topic === DataTopic.Series;\n }\n\n return true;\n })\n .map((transformation) => ('operator' in transformation ? transformation.operator : transformation));\n\n const annotationsTransformations = this.state.transformations\n .filter((transformation) => {\n if ('options' in transformation || 'topic' in transformation) {\n return transformation.topic === DataTopic.Annotations;\n }\n\n return false;\n })\n .map((transformation) => ('operator' in transformation ? transformation.operator : transformation));\n\n if (this.state.transformations.length === 0 || !data) {\n this.setState({ data });\n\n if (data) {\n this._results.next({ origin: this, data });\n }\n return;\n }\n\n if (this._transformSub) {\n this._transformSub.unsubscribe();\n }\n\n const ctx = {\n interpolate: (value: string) => {\n return sceneGraph.interpolate(this, value, data.request?.scopedVars);\n },\n };\n\n let streams = [transformDataFrame(seriesTransformations, data.series, ctx)];\n\n if (data.annotations && data.annotations.length > 0 && annotationsTransformations.length > 0) {\n streams.push(transformDataFrame(annotationsTransformations, data.annotations ?? []));\n }\n\n this._transformSub = forkJoin(streams)\n .pipe(\n map((values) => {\n const transformedSeries = values[0];\n const transformedAnnotations = values[1];\n\n return {\n ...data,\n series: transformedSeries,\n annotations: transformedAnnotations ?? data.annotations,\n };\n }),\n catchError((err) => {\n console.error('Error transforming data: ', err);\n const sourceErr = this.getSourceData().state.data?.errors || [];\n\n const transformationError = toDataQueryError(err);\n transformationError.message = `Error transforming data: ${transformationError.message}`;\n\n const result: PanelData = {\n ...data,\n state: LoadingState.Error,\n // Combine transformation error with upstream errors\n errors: [...sourceErr, transformationError],\n };\n\n return of(result);\n })\n )\n .subscribe((data) => {\n this.setState({ data });\n this._results.next({ origin: this, data });\n });\n }\n}\n"],"names":["_a","data"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAwBO,MAAM,6BAA6B,eAAwE,CAAA;AAAA,EAezG,YAAY,KAAkC,EAAA;AACnD,IAAA,KAAA,CAAM,KAAK,CAAA,CAAA;AAdb,IAAQ,IAAA,CAAA,QAAA,GAAW,IAAI,aAAA,CAAuC,CAAC,CAAA,CAAA;AAK/D,IAAA,IAAA,CAAU,sBAA2E,IAAI,wBAAA;AAAA,MACvF,IAAA;AAAA,MACA;AAAA,QACE,UAAA,EAAY,CAAC,iBAAiB,CAAA;AAAA,QAC9B,gCAAA,EAAkC,MAAM,IAAA,CAAK,wBAAyB,EAAA;AAAA,OACxE;AAAA,KACF,CAAA;AAKE,IAAA,IAAA,CAAK,oBAAqB,CAAA,MAAM,IAAK,CAAA,iBAAA,EAAmB,CAAA,CAAA;AAAA,GAC1D;AAAA,EAEQ,iBAAoB,GAAA;AAC1B,IAAM,MAAA,UAAA,GAAa,KAAK,aAAc,EAAA,CAAA;AAEtC,IAAK,IAAA,CAAA,KAAA,CAAM,GAAI,CAAA,UAAA,CAAW,gBAAiB,CAAA,CAAC,KAAU,KAAA,IAAA,CAAK,SAAU,CAAA,KAAA,CAAM,IAAI,CAAC,CAAC,CAAA,CAAA;AAEjF,IAAI,IAAA,UAAA,CAAW,MAAM,IAAM,EAAA;AACzB,MAAK,IAAA,CAAA,SAAA,CAAU,UAAW,CAAA,KAAA,CAAM,IAAI,CAAA,CAAA;AAAA,KACtC;AAEA,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,KAAK,aAAe,EAAA;AACtB,QAAA,IAAA,CAAK,cAAc,WAAY,EAAA,CAAA;AAAA,OACjC;AAAA,KACF,CAAA;AAAA,GACF;AAAA,EAEQ,aAAmC,GAAA;AACzC,IAAI,IAAA,IAAA,CAAK,MAAM,KAAO,EAAA;AACpB,MAAI,IAAA,IAAA,CAAK,KAAM,CAAA,KAAA,YAAiB,iBAAmB,EAAA;AACjD,QAAM,MAAA,IAAI,MAAM,8EAA8E,CAAA,CAAA;AAAA,OAChG;AACA,MAAA,OAAO,KAAK,KAAM,CAAA,KAAA,CAAA;AAAA,KACpB;AAEA,IAAA,IAAI,CAAC,IAAK,CAAA,MAAA,IAAU,CAAC,IAAA,CAAK,OAAO,MAAQ,EAAA;AACvC,MAAM,MAAA,IAAI,MAAM,0FAA0F,CAAA,CAAA;AAAA,KAC5G;AAEA,IAAA,OAAO,UAAW,CAAA,OAAA,CAAQ,IAAK,CAAA,MAAA,CAAO,MAAM,CAAA,CAAA;AAAA,GAC9C;AAAA,EAEO,kBAAkB,KAAe,EAAA;AACtC,IAAA,IAAI,KAAK,KAAM,CAAA,KAAA,IAAS,IAAK,CAAA,KAAA,CAAM,MAAM,iBAAmB,EAAA;AAC1D,MAAK,IAAA,CAAA,KAAA,CAAM,KAAM,CAAA,iBAAA,CAAkB,KAAK,CAAA,CAAA;AAAA,KAC1C;AAAA,GACF;AAAA,EAEO,oBAAuB,GAAA;AAC5B,IAAM,MAAA,UAAA,GAAa,KAAK,aAAc,EAAA,CAAA;AACtC,IAAA,IAAI,WAAW,oBAAsB,EAAA;AACnC,MAAA,OAAO,WAAW,oBAAqB,EAAA,CAAA;AAAA,KACzC;AAEA,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAAA,EAEO,wBAA2B,GAAA;AAChC,IAAA,IAAA,CAAK,SAAU,CAAA,IAAA,CAAK,aAAc,EAAA,CAAE,MAAM,IAAI,CAAA,CAAA;AAAA,GAChD;AAAA,EAEO,WAAc,GAAA;AA/FvB,IAAA,IAAA,EAAA,EAAA,EAAA,CAAA;AAgGI,IAAK,CAAA,EAAA,GAAA,CAAA,EAAA,GAAA,IAAA,CAAA,aAAA,IAAgB,WAArB,KAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,IAAA,CAAA,EAAA,CAAA,CAAA;AAAA,GACF;AAAA,EAEO,gBAAmB,GAAA;AACxB,IAAA,OAAO,IAAK,CAAA,QAAA,CAAA;AAAA,GACd;AAAA,EAEQ,UAAU,IAA6B,EAAA;AAvGjD,IAAA,IAAA,EAAA,CAAA;AAwGI,IAAA,MAAM,wBAAwB,IAAK,CAAA,KAAA,CAAM,eACtC,CAAA,MAAA,CAAO,CAAC,cAAmB,KAAA;AAC1B,MAAI,IAAA,SAAA,IAAa,cAAkB,IAAA,OAAA,IAAW,cAAgB,EAAA;AAC5D,QAAA,OAAO,cAAe,CAAA,KAAA,IAAS,IAAQ,IAAA,cAAA,CAAe,UAAU,SAAU,CAAA,MAAA,CAAA;AAAA,OAC5E;AAEA,MAAO,OAAA,IAAA,CAAA;AAAA,KACR,EACA,GAAI,CAAA,CAAC,mBAAoB,UAAc,IAAA,cAAA,GAAiB,cAAe,CAAA,QAAA,GAAW,cAAe,CAAA,CAAA;AAEpG,IAAA,MAAM,6BAA6B,IAAK,CAAA,KAAA,CAAM,eAC3C,CAAA,MAAA,CAAO,CAAC,cAAmB,KAAA;AAC1B,MAAI,IAAA,SAAA,IAAa,cAAkB,IAAA,OAAA,IAAW,cAAgB,EAAA;AAC5D,QAAO,OAAA,cAAA,CAAe,UAAU,SAAU,CAAA,WAAA,CAAA;AAAA,OAC5C;AAEA,MAAO,OAAA,KAAA,CAAA;AAAA,KACR,EACA,GAAI,CAAA,CAAC,mBAAoB,UAAc,IAAA,cAAA,GAAiB,cAAe,CAAA,QAAA,GAAW,cAAe,CAAA,CAAA;AAEpG,IAAA,IAAI,KAAK,KAAM,CAAA,eAAA,CAAgB,MAAW,KAAA,CAAA,IAAK,CAAC,IAAM,EAAA;AACpD,MAAK,IAAA,CAAA,QAAA,CAAS,EAAE,IAAA,EAAM,CAAA,CAAA;AAEtB,MAAA,IAAI,IAAM,EAAA;AACR,QAAA,IAAA,CAAK,SAAS,IAAK,CAAA,EAAE,MAAQ,EAAA,IAAA,EAAM,MAAM,CAAA,CAAA;AAAA,OAC3C;AACA,MAAA,OAAA;AAAA,KACF;AAEA,IAAA,IAAI,KAAK,aAAe,EAAA;AACtB,MAAA,IAAA,CAAK,cAAc,WAAY,EAAA,CAAA;AAAA,KACjC;AAEA,IAAA,MAAM,GAAM,GAAA;AAAA,MACV,WAAA,EAAa,CAAC,KAAkB,KAAA;AA1ItC,QAAAA,IAAAA,GAAAA,CAAAA;AA2IQ,QAAO,OAAA,UAAA,CAAW,YAAY,IAAM,EAAA,KAAA,EAAA,CAAOA,MAAA,IAAK,CAAA,OAAA,KAAL,IAAAA,GAAAA,KAAAA,CAAAA,GAAAA,GAAAA,CAAc,UAAU,CAAA,CAAA;AAAA,OACrE;AAAA,KACF,CAAA;AAEA,IAAA,IAAI,UAAU,CAAC,kBAAA,CAAmB,uBAAuB,IAAK,CAAA,MAAA,EAAQ,GAAG,CAAC,CAAA,CAAA;AAE1E,IAAI,IAAA,IAAA,CAAK,eAAe,IAAK,CAAA,WAAA,CAAY,SAAS,CAAK,IAAA,0BAAA,CAA2B,SAAS,CAAG,EAAA;AAC5F,MAAQ,OAAA,CAAA,IAAA,CAAK,mBAAmB,0BAA4B,EAAA,CAAA,EAAA,GAAA,IAAA,CAAK,gBAAL,IAAoB,GAAA,EAAA,GAAA,EAAE,CAAC,CAAA,CAAA;AAAA,KACrF;AAEA,IAAK,IAAA,CAAA,aAAA,GAAgB,QAAS,CAAA,OAAO,CAClC,CAAA,IAAA;AAAA,MACC,GAAA,CAAI,CAAC,MAAW,KAAA;AACd,QAAA,MAAM,oBAAoB,MAAO,CAAA,CAAA,CAAA,CAAA;AACjC,QAAA,MAAM,yBAAyB,MAAO,CAAA,CAAA,CAAA,CAAA;AAEtC,QAAA,OAAO,iCACF,IADE,CAAA,EAAA;AAAA,UAEL,MAAQ,EAAA,iBAAA;AAAA,UACR,WAAA,EAAa,0DAA0B,IAAK,CAAA,WAAA;AAAA,SAC9C,CAAA,CAAA;AAAA,OACD,CAAA;AAAA,MACD,UAAA,CAAW,CAAC,GAAQ,KAAA;AAjK5B,QAAAA,IAAAA,GAAAA,CAAAA;AAkKU,QAAQ,OAAA,CAAA,KAAA,CAAM,6BAA6B,GAAG,CAAA,CAAA;AAC9C,QAAM,MAAA,SAAA,GAAA,CAAA,CAAYA,GAAA,GAAA,IAAA,CAAK,aAAc,EAAA,CAAE,MAAM,IAA3B,KAAA,IAAA,GAAA,KAAA,CAAA,GAAAA,GAAiC,CAAA,MAAA,KAAU,EAAC,CAAA;AAE9D,QAAM,MAAA,mBAAA,GAAsB,iBAAiB,GAAG,CAAA,CAAA;AAChD,QAAoB,mBAAA,CAAA,OAAA,GAAU,4BAA4B,mBAAoB,CAAA,OAAA,CAAA,CAAA,CAAA;AAE9E,QAAM,MAAA,MAAA,GAAoB,iCACrB,IADqB,CAAA,EAAA;AAAA,UAExB,OAAO,YAAa,CAAA,KAAA;AAAA,UAEpB,MAAQ,EAAA,CAAC,GAAG,SAAA,EAAW,mBAAmB,CAAA;AAAA,SAC5C,CAAA,CAAA;AAEA,QAAA,OAAO,GAAG,MAAM,CAAA,CAAA;AAAA,OACjB,CAAA;AAAA,KACH,CACC,SAAU,CAAA,CAACC,KAAS,KAAA;AACnB,MAAA,IAAA,CAAK,QAAS,CAAA,EAAE,IAAAA,EAAAA,KAAAA,EAAM,CAAA,CAAA;AACtB,MAAA,IAAA,CAAK,SAAS,IAAK,CAAA,EAAE,QAAQ,IAAM,EAAA,IAAA,EAAAA,OAAM,CAAA,CAAA;AAAA,KAC1C,CAAA,CAAA;AAAA,GACL;AACF;;;;"}
1
+ {"version":3,"file":"SceneDataTransformer.js","sources":["../../../src/querying/SceneDataTransformer.ts"],"sourcesContent":["import { DataTopic, DataTransformerConfig, LoadingState, PanelData, transformDataFrame } from '@grafana/data';\nimport { toDataQueryError } from '@grafana/runtime';\nimport { catchError, forkJoin, map, of, ReplaySubject, Unsubscribable } from 'rxjs';\nimport { sceneGraph } from '../core/sceneGraph';\nimport { SceneObjectBase } from '../core/SceneObjectBase';\nimport { CustomTransformerDefinition, SceneDataProvider, SceneDataProviderResult, SceneDataState } from '../core/types';\nimport { VariableDependencyConfig } from '../variables/VariableDependencyConfig';\nimport { SceneDataLayerSet } from './SceneDataLayerSet';\n\nexport interface SceneDataTransformerState extends SceneDataState {\n /**\n * Array of standard transformation configs and custom transform operators\n */\n transformations: Array<DataTransformerConfig | CustomTransformerDefinition>;\n}\n\n/**\n * You can use this as a $data object. It can either transform an inner $data DataProvider or if that is not set it will\n * subscribe to a DataProvider higher up in the scene graph and transform its data.\n *\n * The transformations array supports custom (runtime defined) transformation as well as declarative core transformations.\n * You can manually re-process the transformations by calling reprocessTransformations(). This is useful if you have\n * transformations that depend on other scene object states.\n */\nexport class SceneDataTransformer extends SceneObjectBase<SceneDataTransformerState> implements SceneDataProvider {\n private _transformSub?: Unsubscribable;\n private _results = new ReplaySubject<SceneDataProviderResult>(1);\n private _prevDataFromSource?: PanelData;\n\n /**\n * Scan transformations for variable usage and re-process transforms when a variable values change\n */\n protected _variableDependency: VariableDependencyConfig<SceneDataTransformerState> = new VariableDependencyConfig(\n this,\n {\n statePaths: ['transformations'],\n onReferencedVariableValueChanged: () => this.reprocessTransformations(),\n }\n );\n\n public constructor(state: SceneDataTransformerState) {\n super(state);\n\n this.addActivationHandler(() => this.activationHandler());\n }\n\n private activationHandler() {\n const sourceData = this.getSourceData();\n\n this._subs.add(sourceData.subscribeToState((state) => this.transform(state.data)));\n\n if (sourceData.state.data) {\n this.transform(sourceData.state.data);\n }\n\n return () => {\n if (this._transformSub) {\n this._transformSub.unsubscribe();\n }\n };\n }\n\n private getSourceData(): SceneDataProvider {\n if (this.state.$data) {\n if (this.state.$data instanceof SceneDataLayerSet) {\n throw new Error('SceneDataLayerSet can not be used as data provider for SceneDataTransformer.');\n }\n return this.state.$data;\n }\n\n if (!this.parent || !this.parent.parent) {\n throw new Error('SceneDataTransformer must either have $data set on it or have a parent.parent with $data');\n }\n\n return sceneGraph.getData(this.parent.parent);\n }\n\n public setContainerWidth(width: number) {\n if (this.state.$data && this.state.$data.setContainerWidth) {\n this.state.$data.setContainerWidth(width);\n }\n }\n\n public isDataReadyToDisplay() {\n const dataObject = this.getSourceData();\n if (dataObject.isDataReadyToDisplay) {\n return dataObject.isDataReadyToDisplay();\n }\n\n return true;\n }\n\n public reprocessTransformations() {\n this.transform(this.getSourceData().state.data, true);\n }\n\n public cancelQuery() {\n this.getSourceData().cancelQuery?.();\n }\n\n public getResultsStream() {\n return this._results;\n }\n\n public clone(withState?: Partial<SceneDataTransformerState>) {\n const clone = super.clone(withState);\n\n if (this._prevDataFromSource) {\n clone['_prevDataFromSource'] = this._prevDataFromSource;\n }\n\n return clone;\n }\n\n private haveAlreadyTransformedData(data: PanelData) {\n if (!this._prevDataFromSource) {\n return false;\n }\n\n if (data === this._prevDataFromSource) {\n return true;\n }\n\n const { series, annotations } = this._prevDataFromSource;\n\n if (data.series === series && data.annotations === annotations) {\n if (this.state.data && data.state !== this.state.data.state) {\n this.setState({ data: { ...this.state.data, state: data.state } });\n }\n return true;\n }\n\n return false;\n }\n\n private transform(data: PanelData | undefined, force = false) {\n if (this.state.transformations.length === 0 || !data) {\n this._prevDataFromSource = data;\n this.setState({ data });\n\n if (data) {\n this._results.next({ origin: this, data });\n }\n return;\n }\n\n // Skip transform step if we have already transformed this data\n if (!force && this.haveAlreadyTransformedData(data)) {\n return;\n }\n\n const seriesTransformations = this.state.transformations\n .filter((transformation) => {\n if ('options' in transformation || 'topic' in transformation) {\n return transformation.topic == null || transformation.topic === DataTopic.Series;\n }\n\n return true;\n })\n .map((transformation) => ('operator' in transformation ? transformation.operator : transformation));\n\n const annotationsTransformations = this.state.transformations\n .filter((transformation) => {\n if ('options' in transformation || 'topic' in transformation) {\n return transformation.topic === DataTopic.Annotations;\n }\n\n return false;\n })\n .map((transformation) => ('operator' in transformation ? transformation.operator : transformation));\n\n if (this._transformSub) {\n this._transformSub.unsubscribe();\n }\n\n const ctx = {\n interpolate: (value: string) => {\n return sceneGraph.interpolate(this, value, data.request?.scopedVars);\n },\n };\n\n let streams = [transformDataFrame(seriesTransformations, data.series, ctx)];\n\n if (data.annotations && data.annotations.length > 0 && annotationsTransformations.length > 0) {\n streams.push(transformDataFrame(annotationsTransformations, data.annotations ?? []));\n }\n\n this._transformSub = forkJoin(streams)\n .pipe(\n map((values) => {\n const transformedSeries = values[0];\n const transformedAnnotations = values[1];\n\n return {\n ...data,\n series: transformedSeries,\n annotations: transformedAnnotations ?? data.annotations,\n };\n }),\n catchError((err) => {\n console.error('Error transforming data: ', err);\n const sourceErr = this.getSourceData().state.data?.errors || [];\n\n const transformationError = toDataQueryError(err);\n transformationError.message = `Error transforming data: ${transformationError.message}`;\n\n const result: PanelData = {\n ...data,\n state: LoadingState.Error,\n // Combine transformation error with upstream errors\n errors: [...sourceErr, transformationError],\n };\n\n return of(result);\n })\n )\n .subscribe((transformedData) => {\n this.setState({ data: transformedData });\n this._results.next({ origin: this, data: transformedData });\n this._prevDataFromSource = data;\n });\n }\n}\n"],"names":["_a"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { isFilterComplete } from './AdHocFiltersVariable.js';
2
+ import { escapeUrlPipeDelimiters, toUrlCommaDelimitedString, unescapeUrlDelimiters } from '../utils.js';
2
3
 
3
4
  class AdHocFiltersVariableUrlSyncHandler {
4
5
  constructor(_variable) {
@@ -15,7 +16,7 @@ class AdHocFiltersVariableUrlSyncHandler {
15
16
  if (filters.length === 0) {
16
17
  return { [this.getKey()]: [""] };
17
18
  }
18
- const value = filters.filter(isFilterComplete).map((filter) => toArray(filter).map(escapePipeDelimiters).join("|"));
19
+ const value = filters.filter(isFilterComplete).map((filter) => toArray(filter).map(escapeUrlPipeDelimiters).join("|"));
19
20
  return { [this.getKey()]: value };
20
21
  }
21
22
  updateFromUrl(values) {
@@ -35,39 +36,13 @@ function deserializeUrlToFilters(value) {
35
36
  const filter = toFilter(value);
36
37
  return filter === null ? [] : [filter];
37
38
  }
38
- function escapePipeDelimiters(value) {
39
- if (value === null || value === void 0) {
40
- return "";
41
- }
42
- return value = /\|/g[Symbol.replace](value, "__gfp__");
43
- }
44
- function escapeCommaDelimiters(value) {
45
- if (value === null || value === void 0) {
46
- return "";
47
- }
48
- return /,/g[Symbol.replace](value, "__gfc__");
49
- }
50
- function unescapeDelimiters(value) {
51
- if (value === null || value === void 0) {
52
- return "";
53
- }
54
- value = /__gfp__/g[Symbol.replace](value, "|");
55
- value = /__gfc__/g[Symbol.replace](value, ",");
56
- return value;
57
- }
58
39
  function toArray(filter) {
59
40
  return [
60
- toCommaDelimitedString(filter.key, filter.keyLabel),
41
+ toUrlCommaDelimitedString(filter.key, filter.keyLabel),
61
42
  filter.operator,
62
- toCommaDelimitedString(filter.value, filter.valueLabel)
43
+ toUrlCommaDelimitedString(filter.value, filter.valueLabel)
63
44
  ];
64
45
  }
65
- function toCommaDelimitedString(key, label) {
66
- if (!label || key === label) {
67
- return escapeCommaDelimiters(key);
68
- }
69
- return [key, label].map(escapeCommaDelimiters).join(",");
70
- }
71
46
  function toFilter(urlValue) {
72
47
  if (typeof urlValue !== "string" || urlValue.length === 0) {
73
48
  return null;
@@ -76,7 +51,7 @@ function toFilter(urlValue) {
76
51
  const [key2, label] = v.split(",");
77
52
  acc.push(key2, label != null ? label : key2);
78
53
  return acc;
79
- }, []).map(unescapeDelimiters);
54
+ }, []).map(unescapeUrlDelimiters);
80
55
  return {
81
56
  key,
82
57
  keyLabel,
@@ -1 +1 @@
1
- {"version":3,"file":"AdHocFiltersVariableUrlSyncHandler.js","sources":["../../../../src/variables/adhoc/AdHocFiltersVariableUrlSyncHandler.ts"],"sourcesContent":["import { SceneObjectUrlSyncHandler, SceneObjectUrlValue, SceneObjectUrlValues } from '../../core/types';\nimport { AdHocFiltersVariable, AdHocFilterWithLabels, isFilterComplete } from './AdHocFiltersVariable';\n\nexport class AdHocFiltersVariableUrlSyncHandler implements SceneObjectUrlSyncHandler {\n public constructor(private _variable: AdHocFiltersVariable) {}\n\n private getKey(): string {\n return `var-${this._variable.state.name}`;\n }\n\n public getKeys(): string[] {\n return [this.getKey()];\n }\n\n public getUrlState(): SceneObjectUrlValues {\n const filters = this._variable.state.filters;\n\n if (filters.length === 0) {\n return { [this.getKey()]: [''] };\n }\n\n const value = filters.filter(isFilterComplete).map((filter) => toArray(filter).map(escapePipeDelimiters).join('|'));\n return { [this.getKey()]: value };\n }\n\n public updateFromUrl(values: SceneObjectUrlValues): void {\n const urlValue = values[this.getKey()];\n\n if (urlValue == null) {\n return;\n }\n\n const filters = deserializeUrlToFilters(urlValue);\n this._variable.setState({ filters });\n }\n}\n\nfunction deserializeUrlToFilters(value: SceneObjectUrlValue): AdHocFilterWithLabels[] {\n if (Array.isArray(value)) {\n const values = value;\n return values.map(toFilter).filter(isFilter);\n }\n\n const filter = toFilter(value);\n return filter === null ? [] : [filter];\n}\n\nfunction escapePipeDelimiters(value: string | undefined): string {\n if (value === null || value === undefined) {\n return '';\n }\n\n // Replace the pipe due to using it as a filter separator\n return (value = /\\|/g[Symbol.replace](value, '__gfp__'));\n}\n\nfunction escapeCommaDelimiters(value: string | undefined): string {\n if (value === null || value === undefined) {\n return '';\n }\n\n // Replace the comma due to using it as a value/label separator\n return /,/g[Symbol.replace](value, '__gfc__');\n}\n\nfunction unescapeDelimiters(value: string | undefined): string {\n if (value === null || value === undefined) {\n return '';\n }\n\n value = /__gfp__/g[Symbol.replace](value, '|');\n value = /__gfc__/g[Symbol.replace](value, ',');\n\n return value;\n}\n\nfunction toArray(filter: AdHocFilterWithLabels): string[] {\n return [\n toCommaDelimitedString(filter.key, filter.keyLabel),\n filter.operator,\n toCommaDelimitedString(filter.value, filter.valueLabel),\n ];\n}\n\nfunction toCommaDelimitedString(key: string, label?: string): string {\n // Omit for identical key/label or when label is not set at all\n if (!label || key === label) {\n return escapeCommaDelimiters(key);\n }\n\n return [key, label].map(escapeCommaDelimiters).join(',');\n}\n\nfunction toFilter(urlValue: string | number | boolean | undefined | null): AdHocFilterWithLabels | null {\n if (typeof urlValue !== 'string' || urlValue.length === 0) {\n return null;\n }\n\n const [key, keyLabel, operator, _operatorLabel, value, valueLabel] = urlValue\n .split('|')\n .reduce<string[]>((acc, v) => {\n const [key, label] = v.split(',');\n\n acc.push(key, label ?? key);\n\n return acc;\n }, [])\n .map(unescapeDelimiters);\n\n return {\n key,\n keyLabel,\n operator,\n value,\n valueLabel,\n condition: '',\n };\n}\n\nfunction isFilter(filter: AdHocFilterWithLabels | null): filter is AdHocFilterWithLabels {\n return filter !== null && typeof filter.key === 'string' && typeof filter.value === 'string';\n}\n"],"names":["key"],"mappings":"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"}
1
+ {"version":3,"file":"AdHocFiltersVariableUrlSyncHandler.js","sources":["../../../../src/variables/adhoc/AdHocFiltersVariableUrlSyncHandler.ts"],"sourcesContent":["import { SceneObjectUrlSyncHandler, SceneObjectUrlValue, SceneObjectUrlValues } from '../../core/types';\nimport { AdHocFiltersVariable, AdHocFilterWithLabels, isFilterComplete } from './AdHocFiltersVariable';\nimport { escapeUrlPipeDelimiters, toUrlCommaDelimitedString, unescapeUrlDelimiters } from '../utils';\n\nexport class AdHocFiltersVariableUrlSyncHandler implements SceneObjectUrlSyncHandler {\n public constructor(private _variable: AdHocFiltersVariable) {}\n\n private getKey(): string {\n return `var-${this._variable.state.name}`;\n }\n\n public getKeys(): string[] {\n return [this.getKey()];\n }\n\n public getUrlState(): SceneObjectUrlValues {\n const filters = this._variable.state.filters;\n\n if (filters.length === 0) {\n return { [this.getKey()]: [''] };\n }\n\n const value = filters.filter(isFilterComplete).map((filter) => toArray(filter).map(escapeUrlPipeDelimiters).join('|'));\n return { [this.getKey()]: value };\n }\n\n public updateFromUrl(values: SceneObjectUrlValues): void {\n const urlValue = values[this.getKey()];\n\n if (urlValue == null) {\n return;\n }\n\n const filters = deserializeUrlToFilters(urlValue);\n this._variable.setState({ filters });\n }\n}\n\nfunction deserializeUrlToFilters(value: SceneObjectUrlValue): AdHocFilterWithLabels[] {\n if (Array.isArray(value)) {\n const values = value;\n return values.map(toFilter).filter(isFilter);\n }\n\n const filter = toFilter(value);\n return filter === null ? [] : [filter];\n}\n\nfunction toArray(filter: AdHocFilterWithLabels): string[] {\n return [\n toUrlCommaDelimitedString(filter.key, filter.keyLabel),\n filter.operator,\n toUrlCommaDelimitedString(filter.value, filter.valueLabel),\n ];\n}\n\nfunction toFilter(urlValue: string | number | boolean | undefined | null): AdHocFilterWithLabels | null {\n if (typeof urlValue !== 'string' || urlValue.length === 0) {\n return null;\n }\n\n const [key, keyLabel, operator, _operatorLabel, value, valueLabel] = urlValue\n .split('|')\n .reduce<string[]>((acc, v) => {\n const [key, label] = v.split(',');\n\n acc.push(key, label ?? key);\n\n return acc;\n }, [])\n .map(unescapeUrlDelimiters);\n\n return {\n key,\n keyLabel,\n operator,\n value,\n valueLabel,\n condition: '',\n };\n}\n\nfunction isFilter(filter: AdHocFilterWithLabels | null): filter is AdHocFilterWithLabels {\n return filter !== null && typeof filter.key === 'string' && typeof filter.value === 'string';\n}\n"],"names":["key"],"mappings":"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"}
@@ -8,6 +8,7 @@ import { MultiSelect } from '@grafana/ui';
8
8
  import { isArray } from 'lodash';
9
9
  import { getQueriesForVariables } from '../utils.js';
10
10
  import { OptionWithCheckbox } from '../components/VariableValueSelect.js';
11
+ import { GroupByVariableUrlSyncHandler } from './GroupByVariableUrlSyncHandler.js';
11
12
 
12
13
  var __defProp = Object.defineProperty;
13
14
  var __defProps = Object.defineProperties;
@@ -45,6 +46,7 @@ class GroupByVariable extends MultiValueVariable {
45
46
  noValueOnClear: true
46
47
  }));
47
48
  this.isLazy = true;
49
+ this._urlSync = new GroupByVariableUrlSyncHandler(this);
48
50
  this._getKeys = async (ds) => {
49
51
  var _a, _b, _c;
50
52
  const override = await ((_b = (_a = this.state).getTagKeysProvider) == null ? void 0 : _b.call(_a, this, null));
@@ -130,15 +132,25 @@ class GroupByVariable extends MultiValueVariable {
130
132
  }
131
133
  GroupByVariable.Component = GroupByVariableRenderer;
132
134
  function GroupByVariableRenderer({ model }) {
133
- const { value, key, maxVisibleValues, noValueOnClear } = model.useState();
134
- const arrayValue = useMemo(() => isArray(value) ? value : [value], [value]);
135
+ const { value, text, key, maxVisibleValues, noValueOnClear } = model.useState();
136
+ const values = useMemo(() => {
137
+ const arrayValue = isArray(value) ? value : [value];
138
+ const arrayText = isArray(text) ? text : [text];
139
+ return arrayValue.map((value2, idx) => {
140
+ var _a;
141
+ return {
142
+ value: value2,
143
+ label: String((_a = arrayText[idx]) != null ? _a : value2)
144
+ };
145
+ });
146
+ }, [value, text]);
135
147
  const [isFetchingOptions, setIsFetchingOptions] = useState(false);
136
148
  const [isOptionsOpen, setIsOptionsOpen] = useState(false);
137
149
  const [inputValue, setInputValue] = useState("");
138
- const [uncommittedValue, setUncommittedValue] = useState(arrayValue);
150
+ const [uncommittedValue, setUncommittedValue] = useState(values);
139
151
  useEffect(() => {
140
- setUncommittedValue(arrayValue);
141
- }, [arrayValue]);
152
+ setUncommittedValue(values);
153
+ }, [values]);
142
154
  const onInputChange = (value2, { action }) => {
143
155
  if (action === "input-change") {
144
156
  setInputValue(value2);
@@ -175,13 +187,16 @@ function GroupByVariableRenderer({ model }) {
175
187
  components: { Option: OptionWithCheckbox },
176
188
  onInputChange,
177
189
  onBlur: () => {
178
- model.changeValueTo(uncommittedValue);
190
+ model.changeValueTo(
191
+ uncommittedValue.map((x) => x.value),
192
+ uncommittedValue.map((x) => x.label)
193
+ );
179
194
  },
180
195
  onChange: (newValue, action) => {
181
196
  if (action.action === "clear" && noValueOnClear) {
182
197
  model.changeValueTo([]);
183
198
  }
184
- setUncommittedValue(newValue.map((x) => x.value));
199
+ setUncommittedValue(newValue);
185
200
  },
186
201
  onOpenMenu: async () => {
187
202
  setIsFetchingOptions(true);
@@ -1 +1 @@
1
- {"version":3,"file":"GroupByVariable.js","sources":["../../../../src/variables/groupby/GroupByVariable.tsx"],"sourcesContent":["import React, { useEffect, useMemo, useState } from 'react';\nimport { AdHocVariableFilter, DataSourceApi, MetricFindValue } from '@grafana/data';\nimport { allActiveGroupByVariables } from './findActiveGroupByVariablesByUid';\nimport { DataSourceRef, VariableType } from '@grafana/schema';\nimport { SceneComponentProps, ControlsLayout } from '../../core/types';\nimport { sceneGraph } from '../../core/sceneGraph';\nimport { ValidateAndUpdateResult, VariableValueOption, VariableValueSingle } from '../types';\nimport { MultiValueVariable, MultiValueVariableState, VariableGetOptionsArgs } from '../variants/MultiValueVariable';\nimport { from, lastValueFrom, map, mergeMap, Observable, of, take } from 'rxjs';\nimport { getDataSource } from '../../utils/getDataSource';\nimport { InputActionMeta, MultiSelect } from '@grafana/ui';\nimport { isArray } from 'lodash';\nimport { getQueriesForVariables } from '../utils';\nimport { OptionWithCheckbox } from '../components/VariableValueSelect';\n\nexport interface GroupByVariableState extends MultiValueVariableState {\n /** Defaults to \"Group\" */\n name: string;\n /** The visible keys to group on */\n // TODO review this type and name (naming is hard)\n defaultOptions?: MetricFindValue[];\n /** Base filters to always apply when looking up keys */\n baseFilters?: AdHocVariableFilter[];\n /** Datasource to use for getTagKeys and also controls which scene queries the group by should apply to */\n datasource: DataSourceRef | null;\n /** Controls if the group by can be changed */\n readOnly?: boolean;\n /**\n * @experimental\n * Controls the layout and design of the label.\n * Vertical layout does not yet support operator selector.\n */\n layout?: ControlsLayout;\n /**\n * Defaults to same-datasource which means group by will automatically be applied to all queries with the same data source as this GroupBySet.\n * In manual mode no queries are re-run on changes, and you have to manually apply the filter to whatever queries you want.\n */\n applyMode?: 'auto' | 'manual';\n /**\n * Filter out the keys that do not match the regex.\n */\n tagKeyRegexFilter?: RegExp;\n /**\n * Extension hook for customizing the key lookup.\n * Return replace: true if you want to override the default lookup\n * Return replace: false if you want to combine the results with the default lookup\n */\n getTagKeysProvider?: getTagKeysProvider;\n}\n\nexport type getTagKeysProvider = (\n set: GroupByVariable,\n currentKey: string | null\n) => Promise<{ replace?: boolean; values: MetricFindValue[] }>;\n\nexport class GroupByVariable extends MultiValueVariable<GroupByVariableState> {\n static Component = GroupByVariableRenderer;\n isLazy = true;\n\n public validateAndUpdate(): Observable<ValidateAndUpdateResult> {\n return this.getValueOptions({}).pipe(\n map((options) => {\n this._updateValueGivenNewOptions(options);\n return {};\n })\n );\n }\n\n private _updateValueGivenNewOptions(options: VariableValueOption[]) {\n const { value: currentValue, text: currentText } = this.state;\n\n const stateUpdate: Partial<MultiValueVariableState> = {\n options,\n loading: false,\n value: currentValue ?? [],\n text: currentText ?? [],\n };\n\n this.setState(stateUpdate);\n }\n\n public getValueOptions(args: VariableGetOptionsArgs): Observable<VariableValueOption[]> {\n // When default dimensions are provided, return the static list\n if (this.state.defaultOptions) {\n return of(\n this.state.defaultOptions.map((o) => ({\n label: o.text,\n value: String(o.value),\n }))\n );\n }\n\n this.setState({ loading: true, error: null });\n\n return from(\n getDataSource(this.state.datasource, {\n __sceneObject: { text: '__sceneObject', value: this },\n })\n ).pipe(\n mergeMap((ds) => {\n return from(this._getKeys(ds)).pipe(\n take(1),\n mergeMap((data: MetricFindValue[]) => {\n const a: VariableValueOption[] = data.map((i) => {\n return {\n label: i.text,\n value: i.value ? String(i.value) : i.text,\n };\n });\n return of(a);\n })\n );\n })\n );\n }\n\n public constructor(initialState: Partial<GroupByVariableState>) {\n super({\n isMulti: true,\n name: '',\n value: [],\n text: [],\n options: [],\n datasource: null,\n baseFilters: [],\n applyMode: 'auto',\n layout: 'horizontal',\n type: 'groupby' as VariableType,\n ...initialState,\n noValueOnClear: true,\n });\n\n this.addActivationHandler(() => {\n allActiveGroupByVariables.add(this);\n\n return () => allActiveGroupByVariables.delete(this);\n });\n }\n\n /**\n * Get possible keys given current filters. Do not call from plugins directly\n */\n public _getKeys = async (ds: DataSourceApi) => {\n // TODO: provide current dimensions?\n const override = await this.state.getTagKeysProvider?.(this, null);\n\n if (override && override.replace) {\n return override.values;\n }\n\n if (this.state.defaultOptions) {\n return this.state.defaultOptions.concat(override?.values ?? []);\n }\n\n if (!ds.getTagKeys) {\n return [];\n }\n\n const queries = getQueriesForVariables(this);\n\n const otherFilters = this.state.baseFilters || [];\n const timeRange = sceneGraph.getTimeRange(this).state.value;\n let keys = await ds.getTagKeys({ filters: otherFilters, queries, timeRange });\n\n if (override) {\n keys = keys.concat(override.values);\n }\n\n const tagKeyRegexFilter = this.state.tagKeyRegexFilter;\n if (tagKeyRegexFilter) {\n keys = keys.filter((f) => f.text.match(tagKeyRegexFilter));\n }\n\n return keys;\n };\n\n /**\n * Allows clearing the value of the variable to an empty value. Overrides default behavior of a MultiValueVariable\n */\n public getDefaultMultiState(options: VariableValueOption[]): { value: VariableValueSingle[]; text: string[] } {\n return { value: [], text: [] };\n }\n}\nexport function GroupByVariableRenderer({ model }: SceneComponentProps<MultiValueVariable>) {\n const { value, key, maxVisibleValues, noValueOnClear } = model.useState();\n const arrayValue = useMemo(() => (isArray(value) ? value : [value]), [value]);\n const [isFetchingOptions, setIsFetchingOptions] = useState(false);\n const [isOptionsOpen, setIsOptionsOpen] = useState(false);\n const [inputValue, setInputValue] = useState('');\n\n // To not trigger queries on every selection we store this state locally here and only update the variable onBlur\n const [uncommittedValue, setUncommittedValue] = useState(arrayValue);\n\n // Detect value changes outside\n useEffect(() => {\n setUncommittedValue(arrayValue);\n }, [arrayValue]);\n\n const onInputChange = (value: string, { action }: InputActionMeta) => {\n if (action === 'input-change') {\n setInputValue(value);\n if (model.onSearchChange) {\n model.onSearchChange!(value);\n }\n return value;\n }\n\n if (action === 'input-blur') {\n setInputValue('');\n return '';\n }\n\n return inputValue;\n };\n\n const placeholder = 'Select value';\n\n return (\n <MultiSelect<VariableValueSingle>\n data-testid={`GroupBySelect-${key}`}\n id={key}\n placeholder={placeholder}\n width=\"auto\"\n inputValue={inputValue}\n value={uncommittedValue}\n noMultiValueWrap={true}\n maxVisibleValues={maxVisibleValues ?? 5}\n tabSelectsValue={false}\n virtualized\n allowCustomValue\n options={model.getOptionsForSelect()}\n closeMenuOnSelect={false}\n isOpen={isOptionsOpen}\n isClearable={true}\n hideSelectedOptions={false}\n isLoading={isFetchingOptions}\n components={{ Option: OptionWithCheckbox }}\n onInputChange={onInputChange}\n onBlur={() => {\n model.changeValueTo(uncommittedValue);\n }}\n onChange={(newValue, action) => {\n if (action.action === 'clear' && noValueOnClear) {\n model.changeValueTo([]);\n }\n setUncommittedValue(newValue.map((x) => x.value!));\n }}\n onOpenMenu={async () => {\n setIsFetchingOptions(true);\n await lastValueFrom(model.validateAndUpdate());\n setIsFetchingOptions(false);\n setIsOptionsOpen(true);\n }}\n onCloseMenu={() => {\n setIsOptionsOpen(false);\n }}\n />\n );\n}\n"],"names":["value"],"mappings":"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"}
1
+ {"version":3,"file":"GroupByVariable.js","sources":["../../../../src/variables/groupby/GroupByVariable.tsx"],"sourcesContent":["import React, { useEffect, useMemo, useState } from 'react';\nimport { AdHocVariableFilter, DataSourceApi, MetricFindValue, SelectableValue } from '@grafana/data';\nimport { allActiveGroupByVariables } from './findActiveGroupByVariablesByUid';\nimport { DataSourceRef, VariableType } from '@grafana/schema';\nimport { SceneComponentProps, ControlsLayout, SceneObjectUrlSyncHandler } from '../../core/types';\nimport { sceneGraph } from '../../core/sceneGraph';\nimport { ValidateAndUpdateResult, VariableValueOption, VariableValueSingle } from '../types';\nimport { MultiValueVariable, MultiValueVariableState, VariableGetOptionsArgs } from '../variants/MultiValueVariable';\nimport { from, lastValueFrom, map, mergeMap, Observable, of, take } from 'rxjs';\nimport { getDataSource } from '../../utils/getDataSource';\nimport { InputActionMeta, MultiSelect } from '@grafana/ui';\nimport { isArray } from 'lodash';\nimport { getQueriesForVariables } from '../utils';\nimport { OptionWithCheckbox } from '../components/VariableValueSelect';\nimport { GroupByVariableUrlSyncHandler } from './GroupByVariableUrlSyncHandler';\n\nexport interface GroupByVariableState extends MultiValueVariableState {\n /** Defaults to \"Group\" */\n name: string;\n /** The visible keys to group on */\n // TODO review this type and name (naming is hard)\n defaultOptions?: MetricFindValue[];\n /** Base filters to always apply when looking up keys */\n baseFilters?: AdHocVariableFilter[];\n /** Datasource to use for getTagKeys and also controls which scene queries the group by should apply to */\n datasource: DataSourceRef | null;\n /** Controls if the group by can be changed */\n readOnly?: boolean;\n /**\n * @experimental\n * Controls the layout and design of the label.\n * Vertical layout does not yet support operator selector.\n */\n layout?: ControlsLayout;\n /**\n * Defaults to same-datasource which means group by will automatically be applied to all queries with the same data source as this GroupBySet.\n * In manual mode no queries are re-run on changes, and you have to manually apply the filter to whatever queries you want.\n */\n applyMode?: 'auto' | 'manual';\n /**\n * Filter out the keys that do not match the regex.\n */\n tagKeyRegexFilter?: RegExp;\n /**\n * Extension hook for customizing the key lookup.\n * Return replace: true if you want to override the default lookup\n * Return replace: false if you want to combine the results with the default lookup\n */\n getTagKeysProvider?: getTagKeysProvider;\n}\n\nexport type getTagKeysProvider = (\n set: GroupByVariable,\n currentKey: string | null\n) => Promise<{ replace?: boolean; values: MetricFindValue[] }>;\n\nexport class GroupByVariable extends MultiValueVariable<GroupByVariableState> {\n static Component = GroupByVariableRenderer;\n isLazy = true;\n\n protected _urlSync: SceneObjectUrlSyncHandler = new GroupByVariableUrlSyncHandler(this);\n\n public validateAndUpdate(): Observable<ValidateAndUpdateResult> {\n return this.getValueOptions({}).pipe(\n map((options) => {\n this._updateValueGivenNewOptions(options);\n return {};\n })\n );\n }\n\n private _updateValueGivenNewOptions(options: VariableValueOption[]) {\n const { value: currentValue, text: currentText } = this.state;\n\n const stateUpdate: Partial<MultiValueVariableState> = {\n options,\n loading: false,\n value: currentValue ?? [],\n text: currentText ?? [],\n };\n\n this.setState(stateUpdate);\n }\n\n public getValueOptions(args: VariableGetOptionsArgs): Observable<VariableValueOption[]> {\n // When default dimensions are provided, return the static list\n if (this.state.defaultOptions) {\n return of(\n this.state.defaultOptions.map((o) => ({\n label: o.text,\n value: String(o.value),\n }))\n );\n }\n\n this.setState({ loading: true, error: null });\n\n return from(\n getDataSource(this.state.datasource, {\n __sceneObject: { text: '__sceneObject', value: this },\n })\n ).pipe(\n mergeMap((ds) => {\n return from(this._getKeys(ds)).pipe(\n take(1),\n mergeMap((data: MetricFindValue[]) => {\n const a: VariableValueOption[] = data.map((i) => {\n return {\n label: i.text,\n value: i.value ? String(i.value) : i.text,\n };\n });\n return of(a);\n })\n );\n })\n );\n }\n\n public constructor(initialState: Partial<GroupByVariableState>) {\n super({\n isMulti: true,\n name: '',\n value: [],\n text: [],\n options: [],\n datasource: null,\n baseFilters: [],\n applyMode: 'auto',\n layout: 'horizontal',\n type: 'groupby' as VariableType,\n ...initialState,\n noValueOnClear: true,\n });\n\n this.addActivationHandler(() => {\n allActiveGroupByVariables.add(this);\n\n return () => allActiveGroupByVariables.delete(this);\n });\n }\n\n /**\n * Get possible keys given current filters. Do not call from plugins directly\n */\n public _getKeys = async (ds: DataSourceApi) => {\n // TODO: provide current dimensions?\n const override = await this.state.getTagKeysProvider?.(this, null);\n\n if (override && override.replace) {\n return override.values;\n }\n\n if (this.state.defaultOptions) {\n return this.state.defaultOptions.concat(override?.values ?? []);\n }\n\n if (!ds.getTagKeys) {\n return [];\n }\n\n const queries = getQueriesForVariables(this);\n\n const otherFilters = this.state.baseFilters || [];\n const timeRange = sceneGraph.getTimeRange(this).state.value;\n let keys = await ds.getTagKeys({ filters: otherFilters, queries, timeRange });\n\n if (override) {\n keys = keys.concat(override.values);\n }\n\n const tagKeyRegexFilter = this.state.tagKeyRegexFilter;\n if (tagKeyRegexFilter) {\n keys = keys.filter((f) => f.text.match(tagKeyRegexFilter));\n }\n\n return keys;\n };\n\n /**\n * Allows clearing the value of the variable to an empty value. Overrides default behavior of a MultiValueVariable\n */\n public getDefaultMultiState(options: VariableValueOption[]): { value: VariableValueSingle[]; text: string[] } {\n return { value: [], text: [] };\n }\n}\nexport function GroupByVariableRenderer({ model }: SceneComponentProps<MultiValueVariable>) {\n const { value, text, key, maxVisibleValues, noValueOnClear } = model.useState();\n const values = useMemo<Array<SelectableValue<VariableValueSingle>>>(() => {\n const arrayValue = isArray(value) ? value : [value];\n const arrayText = isArray(text) ? text : [text];\n\n return arrayValue.map((value, idx) => ({\n value,\n label: String(arrayText[idx] ?? value),\n }));\n }, [value, text]);\n const [isFetchingOptions, setIsFetchingOptions] = useState(false);\n const [isOptionsOpen, setIsOptionsOpen] = useState(false);\n const [inputValue, setInputValue] = useState('');\n\n // To not trigger queries on every selection we store this state locally here and only update the variable onBlur\n const [uncommittedValue, setUncommittedValue] = useState(values);\n\n // Detect value changes outside\n useEffect(() => {\n setUncommittedValue(values);\n }, [values]);\n\n const onInputChange = (value: string, { action }: InputActionMeta) => {\n if (action === 'input-change') {\n setInputValue(value);\n if (model.onSearchChange) {\n model.onSearchChange!(value);\n }\n return value;\n }\n\n if (action === 'input-blur') {\n setInputValue('');\n return '';\n }\n\n return inputValue;\n };\n\n const placeholder = 'Select value';\n\n return (\n <MultiSelect<VariableValueSingle>\n data-testid={`GroupBySelect-${key}`}\n id={key}\n placeholder={placeholder}\n width=\"auto\"\n inputValue={inputValue}\n value={uncommittedValue}\n noMultiValueWrap={true}\n maxVisibleValues={maxVisibleValues ?? 5}\n tabSelectsValue={false}\n virtualized\n allowCustomValue\n options={model.getOptionsForSelect()}\n closeMenuOnSelect={false}\n isOpen={isOptionsOpen}\n isClearable={true}\n hideSelectedOptions={false}\n isLoading={isFetchingOptions}\n components={{ Option: OptionWithCheckbox }}\n onInputChange={onInputChange}\n onBlur={() => {\n model.changeValueTo(\n uncommittedValue.map((x) => x.value!),\n uncommittedValue.map((x) => x.label!)\n );\n }}\n onChange={(newValue, action) => {\n if (action.action === 'clear' && noValueOnClear) {\n model.changeValueTo([]);\n }\n setUncommittedValue(newValue);\n }}\n onOpenMenu={async () => {\n setIsFetchingOptions(true);\n await lastValueFrom(model.validateAndUpdate());\n setIsFetchingOptions(false);\n setIsOptionsOpen(true);\n }}\n onCloseMenu={() => {\n setIsOptionsOpen(false);\n }}\n />\n );\n}\n"],"names":["value"],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ import { toUrlCommaDelimitedString, unescapeUrlDelimiters } from '../utils.js';
2
+
3
+ class GroupByVariableUrlSyncHandler {
4
+ constructor(_sceneObject) {
5
+ this._sceneObject = _sceneObject;
6
+ }
7
+ getKey() {
8
+ return `var-${this._sceneObject.state.name}`;
9
+ }
10
+ getKeys() {
11
+ if (this._sceneObject.state.skipUrlSync) {
12
+ return [];
13
+ }
14
+ return [this.getKey()];
15
+ }
16
+ getUrlState() {
17
+ if (this._sceneObject.state.skipUrlSync) {
18
+ return {};
19
+ }
20
+ return { [this.getKey()]: toUrlValues(this._sceneObject.state.value, this._sceneObject.state.text) };
21
+ }
22
+ updateFromUrl(values) {
23
+ let urlValue = values[this.getKey()];
24
+ if (urlValue != null) {
25
+ if (!this._sceneObject.isActive) {
26
+ this._sceneObject.skipNextValidation = true;
27
+ }
28
+ const { values: values2, texts } = fromUrlValues(urlValue);
29
+ this._sceneObject.changeValueTo(values2, texts);
30
+ }
31
+ }
32
+ }
33
+ function toUrlValues(values, texts) {
34
+ values = Array.isArray(values) ? values : [values];
35
+ texts = Array.isArray(texts) ? texts : [texts];
36
+ return values.map((value, idx) => {
37
+ if (value === void 0 || value === null) {
38
+ return "";
39
+ }
40
+ value = String(value);
41
+ let text = texts[idx];
42
+ text = text === void 0 || text === null ? value : String(text);
43
+ return toUrlCommaDelimitedString(value, text);
44
+ });
45
+ }
46
+ function fromUrlValues(urlValues) {
47
+ urlValues = Array.isArray(urlValues) ? urlValues : [urlValues];
48
+ return urlValues.reduce(
49
+ (acc, urlValue) => {
50
+ const [value, label] = (urlValue != null ? urlValue : "").split(",");
51
+ acc.values.push(unescapeUrlDelimiters(value));
52
+ acc.texts.push(unescapeUrlDelimiters(label != null ? label : value));
53
+ return acc;
54
+ },
55
+ {
56
+ values: [],
57
+ texts: []
58
+ }
59
+ );
60
+ }
61
+
62
+ export { GroupByVariableUrlSyncHandler };
63
+ //# sourceMappingURL=GroupByVariableUrlSyncHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GroupByVariableUrlSyncHandler.js","sources":["../../../../src/variables/groupby/GroupByVariableUrlSyncHandler.ts"],"sourcesContent":["import { SceneObjectUrlSyncHandler, SceneObjectUrlValues } from '../../core/types';\nimport { GroupByVariable } from './GroupByVariable';\nimport { toUrlCommaDelimitedString, unescapeUrlDelimiters } from '../utils';\nimport { VariableValue } from '../types';\n\nexport class GroupByVariableUrlSyncHandler implements SceneObjectUrlSyncHandler {\n public constructor(private _sceneObject: GroupByVariable) {}\n\n private getKey(): string {\n return `var-${this._sceneObject.state.name}`;\n }\n\n public getKeys(): string[] {\n if (this._sceneObject.state.skipUrlSync) {\n return [];\n }\n\n return [this.getKey()];\n }\n\n public getUrlState(): SceneObjectUrlValues {\n if (this._sceneObject.state.skipUrlSync) {\n return {};\n }\n\n return { [this.getKey()]: toUrlValues(this._sceneObject.state.value, this._sceneObject.state.text) };\n }\n\n public updateFromUrl(values: SceneObjectUrlValues): void {\n let urlValue = values[this.getKey()];\n\n if (urlValue != null) {\n /**\n * Initial URL Sync happens before scene objects are activated.\n * We need to skip validation in this case to make sure values set via URL are maintained.\n */\n if (!this._sceneObject.isActive) {\n this._sceneObject.skipNextValidation = true;\n }\n\n const { values, texts } = fromUrlValues(urlValue);\n\n this._sceneObject.changeValueTo(values, texts);\n }\n }\n}\n\nfunction toUrlValues(values: VariableValue, texts: VariableValue): string[] {\n values = Array.isArray(values) ? values : [values];\n texts = Array.isArray(texts) ? texts : [texts];\n\n return values.map((value, idx) => {\n if (value === undefined || value === null) {\n return '';\n }\n\n value = String(value);\n\n let text = texts[idx];\n text = text === undefined || text === null ? value : String(text);\n\n return toUrlCommaDelimitedString(value, text);\n });\n}\n\nfunction fromUrlValues(urlValues: string | string[]): { values: string[]; texts: string[] } {\n urlValues = Array.isArray(urlValues) ? urlValues : [urlValues];\n\n return urlValues.reduce<{ values: string[]; texts: string[] }>(\n (acc, urlValue) => {\n const [value, label] = (urlValue ?? '').split(',');\n\n acc.values.push(unescapeUrlDelimiters(value));\n acc.texts.push(unescapeUrlDelimiters(label ?? value));\n\n return acc;\n },\n {\n values: [],\n texts: [],\n }\n );\n}\n"],"names":["values"],"mappings":"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"}
@@ -86,6 +86,32 @@ function filterOutInactiveRunnerDuplicates(runners) {
86
86
  return activeItems;
87
87
  });
88
88
  }
89
+ function escapeUrlPipeDelimiters(value) {
90
+ if (value === null || value === void 0) {
91
+ return "";
92
+ }
93
+ return value = /\|/g[Symbol.replace](value, "__gfp__");
94
+ }
95
+ function escapeUrlCommaDelimiters(value) {
96
+ if (value === null || value === void 0) {
97
+ return "";
98
+ }
99
+ return /,/g[Symbol.replace](value, "__gfc__");
100
+ }
101
+ function unescapeUrlDelimiters(value) {
102
+ if (value === null || value === void 0) {
103
+ return "";
104
+ }
105
+ value = /__gfp__/g[Symbol.replace](value, "|");
106
+ value = /__gfc__/g[Symbol.replace](value, ",");
107
+ return value;
108
+ }
109
+ function toUrlCommaDelimitedString(key, label) {
110
+ if (!label || key === label) {
111
+ return escapeUrlCommaDelimiters(key);
112
+ }
113
+ return [key, label].map(escapeUrlCommaDelimiters).join(",");
114
+ }
89
115
 
90
- export { escapeLabelValueInExactSelector, escapeLabelValueInRegexSelector, getQueriesForVariables, isVariableValueEqual, renderPrometheusLabelFilters, safeStringifyValue };
116
+ export { escapeLabelValueInExactSelector, escapeLabelValueInRegexSelector, escapeUrlCommaDelimiters, escapeUrlPipeDelimiters, getQueriesForVariables, isVariableValueEqual, renderPrometheusLabelFilters, safeStringifyValue, toUrlCommaDelimitedString, unescapeUrlDelimiters };
91
117
  //# sourceMappingURL=utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../../../src/variables/utils.ts"],"sourcesContent":["import { isEqual } from 'lodash';\nimport { VariableValue } from './types';\nimport { AdHocVariableFilter } from '@grafana/data';\nimport { sceneGraph } from '../core/sceneGraph';\nimport { SceneObject, SceneObjectState } from '../core/types';\nimport { DataQueryExtended, SceneQueryRunner } from '../querying/SceneQueryRunner';\nimport { DataSourceRef } from '@grafana/schema';\n\nexport function isVariableValueEqual(a: VariableValue | null | undefined, b: VariableValue | null | undefined) {\n if (a === b) {\n return true;\n }\n\n return isEqual(a, b);\n}\n\nexport function safeStringifyValue(value: unknown) {\n // Avoid circular references ignoring those references\n const getCircularReplacer = () => {\n const seen = new WeakSet();\n return (_: string, value: object | null) => {\n if (typeof value === 'object' && value !== null) {\n if (seen.has(value)) {\n return;\n }\n seen.add(value);\n }\n return value;\n };\n };\n\n try {\n return JSON.stringify(value, getCircularReplacer());\n } catch (error) {\n console.error(error);\n }\n\n return '';\n}\n\nexport function renderPrometheusLabelFilters(filters: AdHocVariableFilter[]) {\n return filters.map((filter) => renderFilter(filter)).join(',');\n}\n\nfunction renderFilter(filter: AdHocVariableFilter) {\n let value = '';\n\n if (filter.operator === '=~' || filter.operator === '!~¨') {\n value = escapeLabelValueInRegexSelector(filter.value);\n } else {\n value = escapeLabelValueInExactSelector(filter.value);\n }\n\n return `${filter.key}${filter.operator}\"${value}\"`;\n}\n\n// based on the openmetrics-documentation, the 3 symbols we have to handle are:\n// - \\n ... the newline character\n// - \\ ... the backslash character\n// - \" ... the double-quote character\nexport function escapeLabelValueInExactSelector(labelValue: string): string {\n return labelValue.replace(/\\\\/g, '\\\\\\\\').replace(/\\n/g, '\\\\n').replace(/\"/g, '\\\\\"');\n}\n\nexport function escapeLabelValueInRegexSelector(labelValue: string): string {\n return escapeLabelValueInExactSelector(escapeLokiRegexp(labelValue));\n}\n\nexport function isRegexSelector(selector?: string) {\n if (selector && (selector.includes('=~') || selector.includes('!~'))) {\n return true;\n }\n return false;\n}\n\n// Loki regular-expressions use the RE2 syntax (https://github.com/google/re2/wiki/Syntax),\n// so every character that matches something in that list has to be escaped.\n// the list of meta characters is: *+?()|\\.[]{}^$\n// we make a javascript regular expression that matches those characters:\nconst RE2_METACHARACTERS = /[*+?()|\\\\.\\[\\]{}^$]/g;\nfunction escapeLokiRegexp(value: string): string {\n return value.replace(RE2_METACHARACTERS, '\\\\$&');\n}\n\n/**\n * Get all queries in the scene that have the same datasource as provided source object\n */\nexport function getQueriesForVariables(\n sourceObject: SceneObject<SceneObjectState & { datasource: DataSourceRef | null }>\n) {\n const runners = sceneGraph.findAllObjects(\n sourceObject.getRoot(),\n (o) => o instanceof SceneQueryRunner\n ) as SceneQueryRunner[];\n\n const applicableRunners = filterOutInactiveRunnerDuplicates(runners).filter((r) => {\n return r.state.datasource?.uid === sourceObject.state.datasource?.uid;\n });\n\n if (applicableRunners.length === 0) {\n return [];\n }\n\n const result: DataQueryExtended[] = [];\n applicableRunners.forEach((r) => {\n result.push(...r.state.queries);\n });\n\n return result;\n}\n\n// Filters out inactive runner duplicates, keeping only the ones that are currently active.\n// This is needed for scnearios whan a query runner is cloned and the original is not removed but de-activated.\n// Can happen i.e. when editing a panel in Grafana Core dashboards.\nfunction filterOutInactiveRunnerDuplicates(runners: SceneQueryRunner[]) {\n // Group items by key\n const groupedItems: { [key: string]: SceneQueryRunner[] } = {};\n\n for (const item of runners) {\n if (item.state.key) {\n if (!(item.state.key in groupedItems)) {\n groupedItems[item.state.key] = [];\n }\n groupedItems[item.state.key].push(item);\n }\n }\n\n // Filter out inactive items and concatenate active items\n return Object.values(groupedItems).flatMap((group) => {\n const activeItems = group.filter((item) => item.isActive);\n // Keep inactive items if there's only one item with the key\n if (activeItems.length === 0 && group.length === 1) {\n return group;\n }\n return activeItems;\n });\n}\n"],"names":["value"],"mappings":";;;;AAQgB,SAAA,oBAAA,CAAqB,GAAqC,CAAqC,EAAA;AAC7G,EAAA,IAAI,MAAM,CAAG,EAAA;AACX,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAEA,EAAO,OAAA,OAAA,CAAQ,GAAG,CAAC,CAAA,CAAA;AACrB,CAAA;AAEO,SAAS,mBAAmB,KAAgB,EAAA;AAEjD,EAAA,MAAM,sBAAsB,MAAM;AAChC,IAAM,MAAA,IAAA,uBAAW,OAAQ,EAAA,CAAA;AACzB,IAAO,OAAA,CAAC,GAAWA,MAAyB,KAAA;AAC1C,MAAA,IAAI,OAAOA,MAAAA,KAAU,QAAYA,IAAAA,MAAAA,KAAU,IAAM,EAAA;AAC/C,QAAI,IAAA,IAAA,CAAK,GAAIA,CAAAA,MAAK,CAAG,EAAA;AACnB,UAAA,OAAA;AAAA,SACF;AACA,QAAA,IAAA,CAAK,IAAIA,MAAK,CAAA,CAAA;AAAA,OAChB;AACA,MAAOA,OAAAA,MAAAA,CAAAA;AAAA,KACT,CAAA;AAAA,GACF,CAAA;AAEA,EAAI,IAAA;AACF,IAAA,OAAO,IAAK,CAAA,SAAA,CAAU,KAAO,EAAA,mBAAA,EAAqB,CAAA,CAAA;AAAA,WAC3C,KAAP,EAAA;AACA,IAAA,OAAA,CAAQ,MAAM,KAAK,CAAA,CAAA;AAAA,GACrB;AAEA,EAAO,OAAA,EAAA,CAAA;AACT,CAAA;AAEO,SAAS,6BAA6B,OAAgC,EAAA;AAC3E,EAAO,OAAA,OAAA,CAAQ,IAAI,CAAC,MAAA,KAAW,aAAa,MAAM,CAAC,CAAE,CAAA,IAAA,CAAK,GAAG,CAAA,CAAA;AAC/D,CAAA;AAEA,SAAS,aAAa,MAA6B,EAAA;AACjD,EAAA,IAAI,KAAQ,GAAA,EAAA,CAAA;AAEZ,EAAA,IAAI,MAAO,CAAA,QAAA,KAAa,IAAQ,IAAA,MAAA,CAAO,aAAa,QAAO,EAAA;AACzD,IAAQ,KAAA,GAAA,+BAAA,CAAgC,OAAO,KAAK,CAAA,CAAA;AAAA,GAC/C,MAAA;AACL,IAAQ,KAAA,GAAA,+BAAA,CAAgC,OAAO,KAAK,CAAA,CAAA;AAAA,GACtD;AAEA,EAAA,OAAO,CAAG,EAAA,MAAA,CAAO,GAAM,CAAA,EAAA,MAAA,CAAO,QAAY,CAAA,CAAA,EAAA,KAAA,CAAA,CAAA,CAAA,CAAA;AAC5C,CAAA;AAMO,SAAS,gCAAgC,UAA4B,EAAA;AAC1E,EAAO,OAAA,UAAA,CAAW,OAAQ,CAAA,KAAA,EAAO,MAAM,CAAA,CAAE,OAAQ,CAAA,KAAA,EAAO,KAAK,CAAA,CAAE,OAAQ,CAAA,IAAA,EAAM,KAAK,CAAA,CAAA;AACpF,CAAA;AAEO,SAAS,gCAAgC,UAA4B,EAAA;AAC1E,EAAO,OAAA,+BAAA,CAAgC,gBAAiB,CAAA,UAAU,CAAC,CAAA,CAAA;AACrE,CAAA;AAaA,MAAM,kBAAqB,GAAA,sBAAA,CAAA;AAC3B,SAAS,iBAAiB,KAAuB,EAAA;AAC/C,EAAO,OAAA,KAAA,CAAM,OAAQ,CAAA,kBAAA,EAAoB,MAAM,CAAA,CAAA;AACjD,CAAA;AAKO,SAAS,uBACd,YACA,EAAA;AACA,EAAA,MAAM,UAAU,UAAW,CAAA,cAAA;AAAA,IACzB,aAAa,OAAQ,EAAA;AAAA,IACrB,CAAC,MAAM,CAAa,YAAA,gBAAA;AAAA,GACtB,CAAA;AAEA,EAAA,MAAM,oBAAoB,iCAAkC,CAAA,OAAO,CAAE,CAAA,MAAA,CAAO,CAAC,CAAM,KAAA;AA/FrF,IAAA,IAAA,EAAA,EAAA,EAAA,CAAA;AAgGI,IAAO,OAAA,CAAA,CAAA,EAAA,GAAA,CAAA,CAAE,MAAM,UAAR,KAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAoB,WAAQ,EAAa,GAAA,YAAA,CAAA,KAAA,CAAM,eAAnB,IAA+B,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,GAAA,CAAA,CAAA;AAAA,GACnE,CAAA,CAAA;AAED,EAAI,IAAA,iBAAA,CAAkB,WAAW,CAAG,EAAA;AAClC,IAAA,OAAO,EAAC,CAAA;AAAA,GACV;AAEA,EAAA,MAAM,SAA8B,EAAC,CAAA;AACrC,EAAkB,iBAAA,CAAA,OAAA,CAAQ,CAAC,CAAM,KAAA;AAC/B,IAAA,MAAA,CAAO,IAAK,CAAA,GAAG,CAAE,CAAA,KAAA,CAAM,OAAO,CAAA,CAAA;AAAA,GAC/B,CAAA,CAAA;AAED,EAAO,OAAA,MAAA,CAAA;AACT,CAAA;AAKA,SAAS,kCAAkC,OAA6B,EAAA;AAEtE,EAAA,MAAM,eAAsD,EAAC,CAAA;AAE7D,EAAA,KAAA,MAAW,QAAQ,OAAS,EAAA;AAC1B,IAAI,IAAA,IAAA,CAAK,MAAM,GAAK,EAAA;AAClB,MAAA,IAAI,EAAE,IAAA,CAAK,KAAM,CAAA,GAAA,IAAO,YAAe,CAAA,EAAA;AACrC,QAAa,YAAA,CAAA,IAAA,CAAK,KAAM,CAAA,GAAA,CAAA,GAAO,EAAC,CAAA;AAAA,OAClC;AACA,MAAA,YAAA,CAAa,IAAK,CAAA,KAAA,CAAM,GAAK,CAAA,CAAA,IAAA,CAAK,IAAI,CAAA,CAAA;AAAA,KACxC;AAAA,GACF;AAGA,EAAA,OAAO,OAAO,MAAO,CAAA,YAAY,CAAE,CAAA,OAAA,CAAQ,CAAC,KAAU,KAAA;AACpD,IAAA,MAAM,cAAc,KAAM,CAAA,MAAA,CAAO,CAAC,IAAA,KAAS,KAAK,QAAQ,CAAA,CAAA;AAExD,IAAA,IAAI,WAAY,CAAA,MAAA,KAAW,CAAK,IAAA,KAAA,CAAM,WAAW,CAAG,EAAA;AAClD,MAAO,OAAA,KAAA,CAAA;AAAA,KACT;AACA,IAAO,OAAA,WAAA,CAAA;AAAA,GACR,CAAA,CAAA;AACH;;;;"}
1
+ {"version":3,"file":"utils.js","sources":["../../../src/variables/utils.ts"],"sourcesContent":["import { isEqual } from 'lodash';\nimport { VariableValue } from './types';\nimport { AdHocVariableFilter } from '@grafana/data';\nimport { sceneGraph } from '../core/sceneGraph';\nimport { SceneObject, SceneObjectState } from '../core/types';\nimport { DataQueryExtended, SceneQueryRunner } from '../querying/SceneQueryRunner';\nimport { DataSourceRef } from '@grafana/schema';\n\nexport function isVariableValueEqual(a: VariableValue | null | undefined, b: VariableValue | null | undefined) {\n if (a === b) {\n return true;\n }\n\n return isEqual(a, b);\n}\n\nexport function safeStringifyValue(value: unknown) {\n // Avoid circular references ignoring those references\n const getCircularReplacer = () => {\n const seen = new WeakSet();\n return (_: string, value: object | null) => {\n if (typeof value === 'object' && value !== null) {\n if (seen.has(value)) {\n return;\n }\n seen.add(value);\n }\n return value;\n };\n };\n\n try {\n return JSON.stringify(value, getCircularReplacer());\n } catch (error) {\n console.error(error);\n }\n\n return '';\n}\n\nexport function renderPrometheusLabelFilters(filters: AdHocVariableFilter[]) {\n return filters.map((filter) => renderFilter(filter)).join(',');\n}\n\nfunction renderFilter(filter: AdHocVariableFilter) {\n let value = '';\n\n if (filter.operator === '=~' || filter.operator === '!~¨') {\n value = escapeLabelValueInRegexSelector(filter.value);\n } else {\n value = escapeLabelValueInExactSelector(filter.value);\n }\n\n return `${filter.key}${filter.operator}\"${value}\"`;\n}\n\n// based on the openmetrics-documentation, the 3 symbols we have to handle are:\n// - \\n ... the newline character\n// - \\ ... the backslash character\n// - \" ... the double-quote character\nexport function escapeLabelValueInExactSelector(labelValue: string): string {\n return labelValue.replace(/\\\\/g, '\\\\\\\\').replace(/\\n/g, '\\\\n').replace(/\"/g, '\\\\\"');\n}\n\nexport function escapeLabelValueInRegexSelector(labelValue: string): string {\n return escapeLabelValueInExactSelector(escapeLokiRegexp(labelValue));\n}\n\nexport function isRegexSelector(selector?: string) {\n if (selector && (selector.includes('=~') || selector.includes('!~'))) {\n return true;\n }\n return false;\n}\n\n// Loki regular-expressions use the RE2 syntax (https://github.com/google/re2/wiki/Syntax),\n// so every character that matches something in that list has to be escaped.\n// the list of meta characters is: *+?()|\\.[]{}^$\n// we make a javascript regular expression that matches those characters:\nconst RE2_METACHARACTERS = /[*+?()|\\\\.\\[\\]{}^$]/g;\nfunction escapeLokiRegexp(value: string): string {\n return value.replace(RE2_METACHARACTERS, '\\\\$&');\n}\n\n/**\n * Get all queries in the scene that have the same datasource as provided source object\n */\nexport function getQueriesForVariables(\n sourceObject: SceneObject<SceneObjectState & { datasource: DataSourceRef | null }>\n) {\n const runners = sceneGraph.findAllObjects(\n sourceObject.getRoot(),\n (o) => o instanceof SceneQueryRunner\n ) as SceneQueryRunner[];\n\n const applicableRunners = filterOutInactiveRunnerDuplicates(runners).filter((r) => {\n return r.state.datasource?.uid === sourceObject.state.datasource?.uid;\n });\n\n if (applicableRunners.length === 0) {\n return [];\n }\n\n const result: DataQueryExtended[] = [];\n applicableRunners.forEach((r) => {\n result.push(...r.state.queries);\n });\n\n return result;\n}\n\n// Filters out inactive runner duplicates, keeping only the ones that are currently active.\n// This is needed for scnearios whan a query runner is cloned and the original is not removed but de-activated.\n// Can happen i.e. when editing a panel in Grafana Core dashboards.\nfunction filterOutInactiveRunnerDuplicates(runners: SceneQueryRunner[]) {\n // Group items by key\n const groupedItems: { [key: string]: SceneQueryRunner[] } = {};\n\n for (const item of runners) {\n if (item.state.key) {\n if (!(item.state.key in groupedItems)) {\n groupedItems[item.state.key] = [];\n }\n groupedItems[item.state.key].push(item);\n }\n }\n\n // Filter out inactive items and concatenate active items\n return Object.values(groupedItems).flatMap((group) => {\n const activeItems = group.filter((item) => item.isActive);\n // Keep inactive items if there's only one item with the key\n if (activeItems.length === 0 && group.length === 1) {\n return group;\n }\n return activeItems;\n });\n}\n\nexport function escapeUrlPipeDelimiters(value: string | undefined): string {\n if (value === null || value === undefined) {\n return '';\n }\n\n // Replace the pipe due to using it as a filter separator\n return (value = /\\|/g[Symbol.replace](value, '__gfp__'));\n}\n\nexport function escapeUrlCommaDelimiters(value: string | undefined): string {\n if (value === null || value === undefined) {\n return '';\n }\n\n // Replace the comma due to using it as a value/label separator\n return /,/g[Symbol.replace](value, '__gfc__');\n}\n\nexport function unescapeUrlDelimiters(value: string | undefined): string {\n if (value === null || value === undefined) {\n return '';\n }\n\n value = /__gfp__/g[Symbol.replace](value, '|');\n value = /__gfc__/g[Symbol.replace](value, ',');\n\n return value;\n}\n\nexport function toUrlCommaDelimitedString(key: string, label?: string): string {\n // Omit for identical key/label or when label is not set at all\n if (!label || key === label) {\n return escapeUrlCommaDelimiters(key);\n }\n\n return [key, label].map(escapeUrlCommaDelimiters).join(',');\n}\n"],"names":["value"],"mappings":";;;;AAQgB,SAAA,oBAAA,CAAqB,GAAqC,CAAqC,EAAA;AAC7G,EAAA,IAAI,MAAM,CAAG,EAAA;AACX,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAEA,EAAO,OAAA,OAAA,CAAQ,GAAG,CAAC,CAAA,CAAA;AACrB,CAAA;AAEO,SAAS,mBAAmB,KAAgB,EAAA;AAEjD,EAAA,MAAM,sBAAsB,MAAM;AAChC,IAAM,MAAA,IAAA,uBAAW,OAAQ,EAAA,CAAA;AACzB,IAAO,OAAA,CAAC,GAAWA,MAAyB,KAAA;AAC1C,MAAA,IAAI,OAAOA,MAAAA,KAAU,QAAYA,IAAAA,MAAAA,KAAU,IAAM,EAAA;AAC/C,QAAI,IAAA,IAAA,CAAK,GAAIA,CAAAA,MAAK,CAAG,EAAA;AACnB,UAAA,OAAA;AAAA,SACF;AACA,QAAA,IAAA,CAAK,IAAIA,MAAK,CAAA,CAAA;AAAA,OAChB;AACA,MAAOA,OAAAA,MAAAA,CAAAA;AAAA,KACT,CAAA;AAAA,GACF,CAAA;AAEA,EAAI,IAAA;AACF,IAAA,OAAO,IAAK,CAAA,SAAA,CAAU,KAAO,EAAA,mBAAA,EAAqB,CAAA,CAAA;AAAA,WAC3C,KAAP,EAAA;AACA,IAAA,OAAA,CAAQ,MAAM,KAAK,CAAA,CAAA;AAAA,GACrB;AAEA,EAAO,OAAA,EAAA,CAAA;AACT,CAAA;AAEO,SAAS,6BAA6B,OAAgC,EAAA;AAC3E,EAAO,OAAA,OAAA,CAAQ,IAAI,CAAC,MAAA,KAAW,aAAa,MAAM,CAAC,CAAE,CAAA,IAAA,CAAK,GAAG,CAAA,CAAA;AAC/D,CAAA;AAEA,SAAS,aAAa,MAA6B,EAAA;AACjD,EAAA,IAAI,KAAQ,GAAA,EAAA,CAAA;AAEZ,EAAA,IAAI,MAAO,CAAA,QAAA,KAAa,IAAQ,IAAA,MAAA,CAAO,aAAa,QAAO,EAAA;AACzD,IAAQ,KAAA,GAAA,+BAAA,CAAgC,OAAO,KAAK,CAAA,CAAA;AAAA,GAC/C,MAAA;AACL,IAAQ,KAAA,GAAA,+BAAA,CAAgC,OAAO,KAAK,CAAA,CAAA;AAAA,GACtD;AAEA,EAAA,OAAO,CAAG,EAAA,MAAA,CAAO,GAAM,CAAA,EAAA,MAAA,CAAO,QAAY,CAAA,CAAA,EAAA,KAAA,CAAA,CAAA,CAAA,CAAA;AAC5C,CAAA;AAMO,SAAS,gCAAgC,UAA4B,EAAA;AAC1E,EAAO,OAAA,UAAA,CAAW,OAAQ,CAAA,KAAA,EAAO,MAAM,CAAA,CAAE,OAAQ,CAAA,KAAA,EAAO,KAAK,CAAA,CAAE,OAAQ,CAAA,IAAA,EAAM,KAAK,CAAA,CAAA;AACpF,CAAA;AAEO,SAAS,gCAAgC,UAA4B,EAAA;AAC1E,EAAO,OAAA,+BAAA,CAAgC,gBAAiB,CAAA,UAAU,CAAC,CAAA,CAAA;AACrE,CAAA;AAaA,MAAM,kBAAqB,GAAA,sBAAA,CAAA;AAC3B,SAAS,iBAAiB,KAAuB,EAAA;AAC/C,EAAO,OAAA,KAAA,CAAM,OAAQ,CAAA,kBAAA,EAAoB,MAAM,CAAA,CAAA;AACjD,CAAA;AAKO,SAAS,uBACd,YACA,EAAA;AACA,EAAA,MAAM,UAAU,UAAW,CAAA,cAAA;AAAA,IACzB,aAAa,OAAQ,EAAA;AAAA,IACrB,CAAC,MAAM,CAAa,YAAA,gBAAA;AAAA,GACtB,CAAA;AAEA,EAAA,MAAM,oBAAoB,iCAAkC,CAAA,OAAO,CAAE,CAAA,MAAA,CAAO,CAAC,CAAM,KAAA;AA/FrF,IAAA,IAAA,EAAA,EAAA,EAAA,CAAA;AAgGI,IAAO,OAAA,CAAA,CAAA,EAAA,GAAA,CAAA,CAAE,MAAM,UAAR,KAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAoB,WAAQ,EAAa,GAAA,YAAA,CAAA,KAAA,CAAM,eAAnB,IAA+B,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,GAAA,CAAA,CAAA;AAAA,GACnE,CAAA,CAAA;AAED,EAAI,IAAA,iBAAA,CAAkB,WAAW,CAAG,EAAA;AAClC,IAAA,OAAO,EAAC,CAAA;AAAA,GACV;AAEA,EAAA,MAAM,SAA8B,EAAC,CAAA;AACrC,EAAkB,iBAAA,CAAA,OAAA,CAAQ,CAAC,CAAM,KAAA;AAC/B,IAAA,MAAA,CAAO,IAAK,CAAA,GAAG,CAAE,CAAA,KAAA,CAAM,OAAO,CAAA,CAAA;AAAA,GAC/B,CAAA,CAAA;AAED,EAAO,OAAA,MAAA,CAAA;AACT,CAAA;AAKA,SAAS,kCAAkC,OAA6B,EAAA;AAEtE,EAAA,MAAM,eAAsD,EAAC,CAAA;AAE7D,EAAA,KAAA,MAAW,QAAQ,OAAS,EAAA;AAC1B,IAAI,IAAA,IAAA,CAAK,MAAM,GAAK,EAAA;AAClB,MAAA,IAAI,EAAE,IAAA,CAAK,KAAM,CAAA,GAAA,IAAO,YAAe,CAAA,EAAA;AACrC,QAAa,YAAA,CAAA,IAAA,CAAK,KAAM,CAAA,GAAA,CAAA,GAAO,EAAC,CAAA;AAAA,OAClC;AACA,MAAA,YAAA,CAAa,IAAK,CAAA,KAAA,CAAM,GAAK,CAAA,CAAA,IAAA,CAAK,IAAI,CAAA,CAAA;AAAA,KACxC;AAAA,GACF;AAGA,EAAA,OAAO,OAAO,MAAO,CAAA,YAAY,CAAE,CAAA,OAAA,CAAQ,CAAC,KAAU,KAAA;AACpD,IAAA,MAAM,cAAc,KAAM,CAAA,MAAA,CAAO,CAAC,IAAA,KAAS,KAAK,QAAQ,CAAA,CAAA;AAExD,IAAA,IAAI,WAAY,CAAA,MAAA,KAAW,CAAK,IAAA,KAAA,CAAM,WAAW,CAAG,EAAA;AAClD,MAAO,OAAA,KAAA,CAAA;AAAA,KACT;AACA,IAAO,OAAA,WAAA,CAAA;AAAA,GACR,CAAA,CAAA;AACH,CAAA;AAEO,SAAS,wBAAwB,KAAmC,EAAA;AACzE,EAAI,IAAA,KAAA,KAAU,IAAQ,IAAA,KAAA,KAAU,KAAW,CAAA,EAAA;AACzC,IAAO,OAAA,EAAA,CAAA;AAAA,GACT;AAGA,EAAA,OAAQ,KAAQ,GAAA,KAAA,CAAM,MAAO,CAAA,OAAA,CAAA,CAAS,OAAO,SAAS,CAAA,CAAA;AACxD,CAAA;AAEO,SAAS,yBAAyB,KAAmC,EAAA;AAC1E,EAAI,IAAA,KAAA,KAAU,IAAQ,IAAA,KAAA,KAAU,KAAW,CAAA,EAAA;AACzC,IAAO,OAAA,EAAA,CAAA;AAAA,GACT;AAGA,EAAA,OAAO,IAAK,CAAA,MAAA,CAAO,OAAS,CAAA,CAAA,KAAA,EAAO,SAAS,CAAA,CAAA;AAC9C,CAAA;AAEO,SAAS,sBAAsB,KAAmC,EAAA;AACvE,EAAI,IAAA,KAAA,KAAU,IAAQ,IAAA,KAAA,KAAU,KAAW,CAAA,EAAA;AACzC,IAAO,OAAA,EAAA,CAAA;AAAA,GACT;AAEA,EAAA,KAAA,GAAQ,UAAW,CAAA,MAAA,CAAO,OAAS,CAAA,CAAA,KAAA,EAAO,GAAG,CAAA,CAAA;AAC7C,EAAA,KAAA,GAAQ,UAAW,CAAA,MAAA,CAAO,OAAS,CAAA,CAAA,KAAA,EAAO,GAAG,CAAA,CAAA;AAE7C,EAAO,OAAA,KAAA,CAAA;AACT,CAAA;AAEgB,SAAA,yBAAA,CAA0B,KAAa,KAAwB,EAAA;AAE7E,EAAI,IAAA,CAAC,KAAS,IAAA,GAAA,KAAQ,KAAO,EAAA;AAC3B,IAAA,OAAO,yBAAyB,GAAG,CAAA,CAAA;AAAA,GACrC;AAEA,EAAO,OAAA,CAAC,KAAK,KAAK,CAAA,CAAE,IAAI,wBAAwB,CAAA,CAAE,KAAK,GAAG,CAAA,CAAA;AAC5D;;;;"}
@@ -147,6 +147,9 @@ class MultiValueVariable extends SceneObjectBase {
147
147
  }
148
148
  }
149
149
  }
150
+ if (isEqual(value, this.state.value) && isEqual(text, this.state.text)) {
151
+ return;
152
+ }
150
153
  this.setStateHelper({ value, text, loading: false });
151
154
  this.publishEvent(new SceneVariableValueChangedEvent(this), true);
152
155
  }