Explore: avoid locking timepicker when range is inverted (#44790)

* Explore: avoid locking timepicker when range is inverted

* Explore: prevent time picker to lock if from & to search parameters are present
This commit is contained in:
Giordano Ricci 2022-02-03 13:45:29 +00:00 committed by GitHub
parent bb88cf683c
commit 6415b9a54d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 45 additions and 6 deletions

View File

@ -11,6 +11,7 @@ import {
getExploreUrl,
GetExploreUrlArguments,
getTimeRangeFromUrl,
getTimeRange,
} from './explore';
import store from 'app/core/store';
import { dateTime, ExploreUrlState, LogsSortOrder } from '@grafana/data';
@ -361,6 +362,19 @@ describe('getTimeRangeFromUrl', () => {
});
});
describe('getTimeRange', () => {
describe('should flip from and to when from is after to', () => {
const rawRange = {
from: 'now',
to: 'now-6h',
};
const range = getTimeRange('utc', rawRange, 0);
expect(range.from.isBefore(range.to)).toBe(true);
});
});
describe('getRefIds', () => {
describe('when called with a null value', () => {
it('then it should return empty array', () => {

View File

@ -358,11 +358,13 @@ export const getQueryKeys = (queries: DataQuery[], datasourceInstance?: DataSour
};
export const getTimeRange = (timeZone: TimeZone, rawRange: RawTimeRange, fiscalYearStartMonth: number): TimeRange => {
return {
from: dateMath.parse(rawRange.from, false, timeZone as any, fiscalYearStartMonth)!,
to: dateMath.parse(rawRange.to, true, timeZone as any, fiscalYearStartMonth)!,
raw: rawRange,
};
let range = rangeUtil.convertRawToRange(rawRange, timeZone, fiscalYearStartMonth);
if (range.to.isBefore(range.from)) {
range = rangeUtil.convertRawToRange({ from: range.raw.to, to: range.raw.from }, timeZone, fiscalYearStartMonth);
}
return range;
};
const parseRawTime = (value: string | DateTime): TimeFragment | null => {

View File

@ -314,12 +314,20 @@ describe('Wrapper', () => {
store.dispatch(splitOpen<any>({ datasourceUid: 'elastic', query: { expr: 'error' } }) as any);
await waitFor(() => expect(document.title).toEqual('Explore - loki | elastic - Grafana'));
});
it('removes `from` and `to` parameters from url when first mounted', () => {
setup({ searchParams: 'from=1&to=2&orgId=1' });
expect(locationService.getSearchObject()).toEqual(expect.not.objectContaining({ from: '1', to: '2' }));
expect(locationService.getSearchObject()).toEqual(expect.objectContaining({ orgId: '1' }));
});
});
type DatasourceSetup = { settings: DataSourceInstanceSettings; api: DataSourceApi };
type SetupOptions = {
datasources?: DatasourceSetup[];
query?: any;
searchParams?: string;
};
function setup(options?: SetupOptions): { datasources: { [name: string]: DataSourceApi }; store: EnhancedStore } {
@ -368,7 +376,7 @@ function setup(options?: SetupOptions): { datasources: { [name: string]: DataSou
},
};
locationService.push({ pathname: '/explore' });
locationService.push({ pathname: '/explore', search: options?.searchParams });
if (options?.query) {
locationService.partial(options.query);

View File

@ -10,6 +10,7 @@ import { Branding } from '../../core/components/Branding/Branding';
import { getNavModel } from '../../core/selectors/navModel';
import { StoreState } from 'app/types';
import { locationService } from '@grafana/runtime';
interface RouteProps extends GrafanaRouteComponentProps<{}, ExploreQueryParams> {}
interface OwnProps {}
@ -38,6 +39,20 @@ class WrapperUnconnected extends PureComponent<Props> {
lastSavedUrl.left = undefined;
lastSavedUrl.right = undefined;
// timeSrv (which is used internally) on init reads `from` and `to` param from the URL and updates itself
// using those value regardless of what is passed to the init method.
// The updated value is then used by Explore to get the range for each pane.
// This means that if `from` and `to` parameters are present in the URL,
// it would be impossible to change the time range in Explore.
// We are only doing this on mount for 2 reasons:
// 1: Doing it on update means we'll enter a render loop.
// 2: when parsing time in Explore (before feeding it to timeSrv) we make sure `from` is before `to` inside
// each pane state in order to not trigger un URL update from timeSrv.
const searchParams = locationService.getSearchObject();
if (searchParams.from || searchParams.to) {
locationService.partial({ from: undefined, to: undefined }, true);
}
const richHistory = getRichHistory();
this.props.richHistoryUpdatedAction({ richHistory });
}