[release-11.6.1] Dashboards: Fix time range bug when use_browser_locale is enabled 2 (#103108)

Dashboards: Fix time range bug when use_browser_locale is enabled 2 (#102750)

* revert

* make it work on initial load

* add integration test; cleanup

* fix test

* fix

(cherry picked from commit 39c33d421b)
This commit is contained in:
Haris Rozajac 2025-03-31 08:37:39 -06:00 committed by GitHub
parent 7b6db626ad
commit cbcfe0bcff
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 55 additions and 12 deletions

View File

@ -32,7 +32,7 @@ describe('dateTimeParse', () => {
const date = dateTimeParse('2025-03-12T07:09:37.253Z', { timeZone: 'browser' });
expect(date.isValid()).toBe(true);
expect(date.format()).toEqual('2025-03-12T02:09:37-05:00');
expect(date.format()).toEqual('2025-03-12T07:09:37Z');
});
it('should be able to parse array formats used by calendar', () => {

View File

@ -53,29 +53,31 @@ export const dateTimeParse: DateTimeParser<DateTimeOptionsWhenParsing> = (value,
};
const parseString = (value: string, options?: DateTimeOptionsWhenParsing): DateTime => {
const parsed = parse(value, options?.roundUp, options?.timeZone, options?.fiscalYearStartMonth);
if (value.indexOf('now') !== -1) {
if (!isValid(value)) {
return dateTime();
}
const parsed = parse(value, options?.roundUp, options?.timeZone, options?.fiscalYearStartMonth);
return parsed || dateTime();
}
const timeZone = getTimeZone(options);
let timeZone = getTimeZone(options);
let format = options?.format ?? systemDateFormats.fullDate;
if (value.endsWith('Z')) {
// This is a special case when we have an ISO date string
// In this case we want to force the format to be ISO and the timeZone to be UTC
// This logic is needed for initial load when parsing the URL params
format = 'YYYY-MM-DDTHH:mm:ss.SSSZ';
timeZone = 'utc';
}
const zone = moment.tz.zone(timeZone);
const format = options?.format ?? systemDateFormats.fullDate;
if (zone && zone.name) {
return dateTimeForTimeZone(zone.name, value, format);
}
if (format === systemDateFormats.fullDate) {
// We use parsed here to handle case when `use_browser_locale` is true
// We need to pass the parsed value to handle case when value is an ISO 8601 date string
return dateTime(parsed, format);
}
switch (lowerCase(timeZone)) {
case 'utc':
return toUtc(value, format);

View File

@ -269,7 +269,7 @@ function valueAsString(value: DateTime | string, timeZone?: TimeZone): string {
}
if (value.endsWith('Z')) {
const dt = dateTimeParse(value, { timeZone: 'utc', format: 'YYYY-MM-DDTHH:mm:ss.SSSZ' });
const dt = dateTimeParse(value);
return dateTimeFormat(dt, { timeZone });
}

View File

@ -5,7 +5,7 @@ import { useParams } from 'react-router-dom-v5-compat';
import { TestProvider } from 'test/helpers/TestProvider';
import { getGrafanaContextMock } from 'test/mocks/getGrafanaContextMock';
import { PanelProps } from '@grafana/data';
import { PanelProps, systemDateFormats, SystemDateFormatsState } from '@grafana/data';
import { getPanelPlugin } from '@grafana/data/test/__mocks__/pluginMocks';
import { selectors } from '@grafana/e2e-selectors';
import {
@ -229,6 +229,42 @@ describe('DashboardScenePage', () => {
expect(await screen.findByTitle('Panel B')).toBeInTheDocument();
});
describe('absolute time range', () => {
it('should render with absolute time range when use_browser_locale is true', async () => {
locationService.push('/d/my-dash-uid?from=2025-03-11T07:09:37.253Z&to=2025-03-12T07:09:37.253Z');
systemDateFormats.update({
fullDate: 'YYYY-MM-DD HH:mm:ss.SSS',
interval: {} as SystemDateFormatsState['interval'],
useBrowserLocale: true,
});
setup();
await waitForDashboardToRenderWithTimeRange({
from: '03/11/2025, 02:09:37 AM',
to: '03/12/2025, 02:09:37 AM',
});
});
it('should render correct time range when use_browser_locale is true and time range is other than default system date format', async () => {
locationService.push('/d/my-dash-uid?from=2025-03-11T07:09:37.253Z&to=2025-03-12T07:09:37.253Z');
// mocking navigator.languages to return 'de'
// this property configured in the browser settings
Object.defineProperty(navigator, 'languages', { value: ['de'] });
systemDateFormats.update({
// left fullDate empty to show that this should be overridden by the browser locale
fullDate: '',
interval: {} as SystemDateFormatsState['interval'],
useBrowserLocale: true,
});
setup();
await waitForDashboardToRenderWithTimeRange({
from: '11.03.2025, 02:09:37',
to: '12.03.2025, 02:09:37',
});
});
});
describe('empty state', () => {
it('Shows empty state when dashboard is empty', async () => {
loadDashboardMock.mockResolvedValue({ dashboard: { uid: 'my-dash-uid', panels: [] }, meta: {} });
@ -373,3 +409,8 @@ async function waitForDashboardToRender() {
expect(await screen.findByText('Last 6 hours')).toBeInTheDocument();
expect(await screen.findByTitle('Panel A')).toBeInTheDocument();
}
async function waitForDashboardToRenderWithTimeRange(timeRange: { from: string; to: string }) {
expect(await screen.findByText(`${timeRange.from} to ${timeRange.to}`)).toBeInTheDocument();
expect(await screen.findByTitle('Panel A')).toBeInTheDocument();
}