Dashboards: Panels react to timeFrom and timeShift changes using variables (#98510)

This commit is contained in:
Sergej-Vlasov 2025-01-08 08:35:08 +00:00 committed by GitHub
parent e786292673
commit 8f6220707b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 50 additions and 5 deletions

View File

@ -1,7 +1,14 @@
import { advanceTo, clear } from 'jest-date-mock';
import { dateTime } from '@grafana/data';
import { SceneCanvasText, SceneFlexItem, SceneFlexLayout, SceneTimeRange } from '@grafana/scenes';
import {
SceneCanvasText,
SceneFlexItem,
SceneFlexLayout,
SceneTimeRange,
SceneVariableSet,
TestVariable,
} from '@grafana/scenes';
import { activateFullSceneTree } from '../utils/test-utils';
@ -47,6 +54,36 @@ describe('PanelTimeRange', () => {
expect(panelTime.state.value.from.toISOString()).toBe('2019-02-11T15:00:00.000Z');
expect(panelTime.state.timeInfo).toBe('Last 2 hours timeshift -2h');
});
it('should update timeInfo when timeShift and timeFrom are variable expressions', async () => {
const customTimeFrom = new TestVariable({
name: 'testFrom',
value: '10s',
});
const customTimeShift = new TestVariable({
name: 'testShift',
value: '20s',
});
const panelTime = new PanelTimeRange({ timeFrom: '$testFrom', timeShift: '$testShift' });
const panel = new SceneCanvasText({ text: 'Hello', $timeRange: panelTime });
const scene = new SceneFlexLayout({
$variables: new SceneVariableSet({
variables: [customTimeFrom, customTimeShift],
}),
$timeRange: new SceneTimeRange({ from: 'now-6h', to: 'now' }),
children: [new SceneFlexItem({ body: panel })],
});
activateFullSceneTree(scene);
expect(panelTime.state.timeInfo).toBe('Last 10 seconds timeshift -20s');
customTimeFrom.setState({ value: '15s' });
customTimeShift.setState({ value: '25s' });
panelTime.forceRender();
expect(panelTime.state.timeInfo).toBe('Last 15 seconds timeshift -25s');
});
});
function buildAndActivateSceneFor(panelTime: PanelTimeRange) {

View File

@ -7,6 +7,7 @@ import {
SceneTimeRangeLike,
SceneTimeRangeState,
SceneTimeRangeTransformerBase,
VariableDependencyConfig,
} from '@grafana/scenes';
import { Icon, PanelChrome, TimePickerTooltip, Tooltip, useStyles2 } from '@grafana/ui';
import { TimeOverrideResult } from 'app/features/dashboard/utils/panel';
@ -33,12 +34,19 @@ export class PanelTimeRange extends SceneTimeRangeTransformerBase<PanelTimeRange
this.addActivationHandler(() => this._onActivate());
}
protected _variableDependency: VariableDependencyConfig<PanelTimeRangeState> = new VariableDependencyConfig(this, {
statePaths: ['timeFrom', 'timeShift'],
});
private _onActivate() {
this._subs.add(
this.subscribeToState((n, p) => {
// Listen to own changes and update time info when required
if (n.timeFrom !== p.timeFrom || n.timeShift !== p.timeShift) {
const { timeInfo, timeRange } = this.getTimeOverride(this.getAncestorTimeRange().state.value);
this.subscribeToState((n) => {
const { timeInfo, timeRange } = this.getTimeOverride(this.getAncestorTimeRange().state.value);
// When timeFrom or timeShift is a variable we cannot compare to previous interpolated value
// therefore we need to compare timeInfo directly and update when required
// Note: compare to newState.timeInfo because it is always one behind
if (n.timeInfo !== timeInfo) {
this.setState({ timeInfo, value: timeRange });
}
})