From 00b89b0d29c5616da5ef7e2254371d85277012fe Mon Sep 17 00:00:00 2001 From: Kristina Demeshchik Date: Wed, 7 Jan 2026 14:24:20 -0500 Subject: [PATCH] Dashboards: Fix liveNow not working for panels with time shift (#115902) * relative time for timeshifts * remove extra assertion * absolute time range --- .../src/datetime/datemath.test.ts | 14 +++- .../panel-timerange/PanelTimeRange.test.tsx | 78 ++++++++++++++++++- .../scene/panel-timerange/PanelTimeRange.tsx | 59 ++++++++++---- 3 files changed, 134 insertions(+), 17 deletions(-) diff --git a/packages/grafana-data/src/datetime/datemath.test.ts b/packages/grafana-data/src/datetime/datemath.test.ts index f53bbe8e6e5..3abf59ea43f 100644 --- a/packages/grafana-data/src/datetime/datemath.test.ts +++ b/packages/grafana-data/src/datetime/datemath.test.ts @@ -165,9 +165,17 @@ describe('DateMath', () => { expect(date!.valueOf()).toEqual(dateTime([2014, 1, 3]).valueOf()); }); - it('should handle multiple math expressions', () => { - const date = dateMath.parseDateMath('-2d-6h', dateTime([2014, 1, 5])); - expect(date!.valueOf()).toEqual(dateTime([2014, 1, 2, 18]).valueOf()); + it.each([ + ['-2d-6h', [2014, 1, 5], [2014, 1, 2, 18]], + ['-30m-2d', [2014, 1, 5], [2014, 1, 2, 23, 30]], + ['-2d-1d', [2014, 1, 5], [2014, 1, 2]], + ['-1h-30m', [2014, 1, 5, 12, 0], [2014, 1, 5, 10, 30]], + ['-1d-1h-30m', [2014, 1, 5, 12, 0], [2014, 1, 4, 10, 30]], + ['+1d-6h', [2014, 1, 5], [2014, 1, 5, 18]], + ['-1w-1d', [2014, 1, 14], [2014, 1, 6]], + ])('should handle multiple math expressions: %s', (expression, inputDate, expectedDate) => { + const date = dateMath.parseDateMath(expression, dateTime(inputDate)); + expect(date!.valueOf()).toEqual(dateTime(expectedDate).valueOf()); }); it('should return false when invalid expression', () => { diff --git a/public/app/features/dashboard-scene/scene/panel-timerange/PanelTimeRange.test.tsx b/public/app/features/dashboard-scene/scene/panel-timerange/PanelTimeRange.test.tsx index 8bce6364a34..a31927a3e92 100644 --- a/public/app/features/dashboard-scene/scene/panel-timerange/PanelTimeRange.test.tsx +++ b/public/app/features/dashboard-scene/scene/panel-timerange/PanelTimeRange.test.tsx @@ -128,7 +128,7 @@ describe('PanelTimeRange', () => { expect(panelTime.state.value.to.format('Z')).toBe('+00:00'); // UTC }); - it('should handle invalid time reference in timeShift', () => { + it('should handle invalid time reference in timeShift with relative time range', () => { const panelTime = new PanelTimeRange({ timeShift: 'now-1d' }); buildAndActivateSceneFor(panelTime); @@ -139,6 +139,22 @@ describe('PanelTimeRange', () => { expect(panelTime.state.to).toBe('now'); }); + it('should handle invalid time reference in timeShift with absolute time range', () => { + const panelTime = new PanelTimeRange({ timeShift: 'now-1d' }); + const panel = new SceneCanvasText({ text: 'Hello', $timeRange: panelTime }); + const absoluteFrom = '2019-02-11T10:00:00.000Z'; + const absoluteTo = '2019-02-11T16:00:00.000Z'; + const scene = new SceneFlexLayout({ + $timeRange: new SceneTimeRange({ from: absoluteFrom, to: absoluteTo }), + children: [new SceneFlexItem({ body: panel })], + }); + activateFullSceneTree(scene); + + expect(panelTime.state.timeInfo).toBe('invalid timeshift'); + expect(panelTime.state.from).toBe(absoluteFrom); + expect(panelTime.state.to).toBe(absoluteTo); + }); + it('should handle invalid time reference in timeShift combined with timeFrom', () => { const panelTime = new PanelTimeRange({ timeFrom: 'now-2h', @@ -153,6 +169,66 @@ describe('PanelTimeRange', () => { expect(panelTime.state.to).toBe('now'); }); + describe('from/to state format for liveNow compatibility', () => { + it('should store relative strings in from/to when timeShift is applied to relative time range', () => { + const panelTime = new PanelTimeRange({ timeShift: '2h' }); + + buildAndActivateSceneFor(panelTime); + + expect(panelTime.state.from).toBe('now-6h-2h'); + expect(panelTime.state.to).toBe('now-2h'); + expect(panelTime.state.value.raw.from).toBe('now-6h-2h'); + expect(panelTime.state.value.raw.to).toBe('now-2h'); + }); + + it('should store relative strings when both timeFrom and timeShift are applied', () => { + const panelTime = new PanelTimeRange({ timeFrom: '2h', timeShift: '1h' }); + + buildAndActivateSceneFor(panelTime); + + expect(panelTime.state.from).toBe('now-2h-1h'); + expect(panelTime.state.to).toBe('now-1h'); + }); + + it('should store ISO strings when timeShift is applied to absolute time range', () => { + const panelTime = new PanelTimeRange({ timeShift: '1h' }); + const panel = new SceneCanvasText({ text: 'Hello', $timeRange: panelTime }); + const absoluteFrom = '2019-02-11T10:00:00.000Z'; + const absoluteTo = '2019-02-11T16:00:00.000Z'; + const scene = new SceneFlexLayout({ + $timeRange: new SceneTimeRange({ from: absoluteFrom, to: absoluteTo }), + children: [new SceneFlexItem({ body: panel })], + }); + activateFullSceneTree(scene); + + expect(panelTime.state.from).toBe('2019-02-11T09:00:00.000Z'); + expect(panelTime.state.to).toBe('2019-02-11T15:00:00.000Z'); + }); + + it('should update from/to when ancestor time range changes', () => { + const panelTime = new PanelTimeRange({ timeShift: '1h' }); + const sceneTimeRange = new SceneTimeRange({ from: 'now-6h', to: 'now' }); + const panel = new SceneCanvasText({ text: 'Hello', $timeRange: panelTime }); + const scene = new SceneFlexLayout({ + $timeRange: sceneTimeRange, + children: [new SceneFlexItem({ body: panel })], + }); + activateFullSceneTree(scene); + + expect(panelTime.state.from).toBe('now-6h-1h'); + expect(panelTime.state.to).toBe('now-1h'); + + sceneTimeRange.onTimeRangeChange({ + from: dateTime('2019-02-11T12:00:00.000Z'), + to: dateTime('2019-02-11T18:00:00.000Z'), + raw: { from: 'now-12h', to: 'now' }, + }); + + expect(panelTime.state.from).toBe('now-12h-1h'); + expect(panelTime.state.to).toBe('now-1h'); + }); + }); + describe('onTimeRangeChange', () => { it('should reverse timeShift when updating time range', () => { const oneHourShift = '1h'; diff --git a/public/app/features/dashboard-scene/scene/panel-timerange/PanelTimeRange.tsx b/public/app/features/dashboard-scene/scene/panel-timerange/PanelTimeRange.tsx index 04f3eac85e2..7fe4133a7fa 100644 --- a/public/app/features/dashboard-scene/scene/panel-timerange/PanelTimeRange.tsx +++ b/public/app/features/dashboard-scene/scene/panel-timerange/PanelTimeRange.tsx @@ -81,7 +81,19 @@ export class PanelTimeRange extends SceneTimeRangeTransformerBase