Scene: ObjectVariable for supporting the built in system variables and object scoped variables (__data for example) (#58291)

* Scene: Adds ObjectVariable to support the built-in/system variables

* fixed lint issue
This commit is contained in:
Torkel Ödegaard 2022-11-09 10:27:20 +01:00 committed by GitHub
parent fdeefaee42
commit b5651803e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 72 additions and 0 deletions

View File

@ -4671,6 +4671,10 @@ exports[`better eslint`] = {
"public/app/features/scenes/variables/types.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"public/app/features/scenes/variables/variants/ObjectVariable.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
"public/app/features/search/components/SearchCard.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"],

View File

@ -4,6 +4,7 @@ import { SceneObjectStatePlain } from '../core/types';
import { sceneTemplateInterpolator } from './sceneTemplateInterpolator';
import { SceneVariableSet } from './sets/SceneVariableSet';
import { ConstantVariable } from './variants/ConstantVariable';
import { ObjectVariable } from './variants/ObjectVariable';
interface TestSceneState extends SceneObjectStatePlain {
nested?: TestScene;
@ -42,4 +43,21 @@ describe('sceneTemplateInterpolator', () => {
expect(sceneTemplateInterpolator('${test}', scene.state.nested!)).toBe('nestedValue');
expect(sceneTemplateInterpolator('${atRootOnly}', scene.state.nested!)).toBe('RootValue');
});
describe('Given an expression with fieldPath', () => {
it('Should interpolate correctly', () => {
const scene = new TestScene({
$variables: new SceneVariableSet({
variables: [
new ObjectVariable({
name: 'test',
value: { prop1: 'prop1Value' },
}),
],
}),
});
expect(sceneTemplateInterpolator('${test.prop1}', scene)).toBe('prop1Value');
});
});
});

View File

@ -0,0 +1,18 @@
import { ObjectVariable } from './ObjectVariable';
describe('ObjectVariable', () => {
describe('getValue', () => {
it('it should return value according to fieldPath', () => {
const variable = new ObjectVariable({
name: 'test',
value: {
field1: 'value1',
array: ['value1', 'value2', 'value3'],
},
});
expect(variable.getValue('field1')).toBe('value1');
expect(variable.getValue('array[1]')).toBe('value2');
});
});
});

View File

@ -0,0 +1,32 @@
import { property } from 'lodash';
import { SceneObjectBase } from '../../core/SceneObjectBase';
import { SceneVariable, SceneVariableState, VariableValue } from '../types';
export interface ObjectVariableState<T extends object> extends SceneVariableState {
value: T;
}
export class ObjectVariable<T extends object>
extends SceneObjectBase<ObjectVariableState<T>>
implements SceneVariable<ObjectVariableState<T>>
{
private static fieldAccessorCache: FieldAccessorCache = {};
public getValue(fieldPath: string): VariableValue {
return this.getFieldAccessor(fieldPath)(this.state.value);
}
private getFieldAccessor(fieldPath: string) {
const accessor = ObjectVariable.fieldAccessorCache[fieldPath];
if (accessor) {
return accessor;
}
return (ObjectVariable.fieldAccessorCache[fieldPath] = property(fieldPath));
}
}
interface FieldAccessorCache {
[key: string]: (obj: any) => any;
}