grafana/public/app/features/scenes/variables/interpolation/ScopedVarsVariable.ts
Dominik Prokop 1758ddd457
Scenes: Add query variable support (#59553)
* WIP first attempt to query variable

* regex issue repro demo

* Refresh variable on time range change if refresh specified

* Instantiate variable runner when updating query variable options

* Simplify runners getTarget interface

* Fix issue with variable ot being updated correctly after other variable changed

* Add templateSrv.replace compatibility with query variable

* QueryVariable: use datasource variable as source

* use proper format

* Make sure variables set is correctly updated when query variable errors

* Do not destruct scopedVars when using sceneGraph.interpolate in templateSrv

* Add support for Legacy variables (metricFindQuery)

* Review

* Fix lint

* Test: Add unit for datasource by variable

* test: Add unit for datasource as var

* query: delegate interpolation to datasourceSrv

* Cleanup

Co-authored-by: Ivan Ortega <ivanortegaalba@gmail.com>
2022-12-12 04:01:27 -08:00

74 lines
1.8 KiB
TypeScript

import { property } from 'lodash';
import { ScopedVar } from '@grafana/data';
import { VariableValue } from '../types';
import { FormatVariable } from './formatRegistry';
export class ScopedVarsVariable implements FormatVariable {
private static fieldAccessorCache: FieldAccessorCache = {};
public state: { name: string; value: ScopedVar; type: string };
public constructor(name: string, value: ScopedVar) {
this.state = { name, value, type: 'scopedvar' };
}
public getValue(fieldPath: string): VariableValue {
let { value } = this.state;
let realValue = value.value;
if (fieldPath) {
realValue = this.getFieldAccessor(fieldPath)(value.value);
} else {
realValue = value.value;
}
if (realValue === 'string' || realValue === 'number' || realValue === 'boolean') {
return realValue;
}
return String(realValue);
}
public getValueText(): string {
const { value } = this.state;
if (value.text != null) {
return String(value.text);
}
return String(value);
}
private getFieldAccessor(fieldPath: string) {
const accessor = ScopedVarsVariable.fieldAccessorCache[fieldPath];
if (accessor) {
return accessor;
}
return (ScopedVarsVariable.fieldAccessorCache[fieldPath] = property(fieldPath));
}
}
interface FieldAccessorCache {
[key: string]: (obj: unknown) => unknown;
}
let scopedVarsVariable: ScopedVarsVariable | undefined;
/**
* Reuses a single instance to avoid unnecessary memory allocations
*/
export function getSceneVariableForScopedVar(name: string, value: ScopedVar) {
if (!scopedVarsVariable) {
scopedVarsVariable = new ScopedVarsVariable(name, value);
} else {
scopedVarsVariable.state.name = name;
scopedVarsVariable.state.value = value;
}
return scopedVarsVariable;
}