mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Explore: Remove ui params from url (#27753)
* Remove ui from url * Update tests * Update changeDedupStrategy * Add test coverage
This commit is contained in:
parent
bd9add72de
commit
2f5a60f561
@ -575,8 +575,7 @@ describe('getLinksSupplier', () => {
|
|||||||
expect(links[0]).toEqual(
|
expect(links[0]).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
title: 'testDS',
|
title: 'testDS',
|
||||||
href:
|
href: '/explore?left={"datasource":"testDS","queries":["12345"]}',
|
||||||
'/explore?left={"datasource":"testDS","queries":["12345"],"ui":{"showingGraph":true,"showingTable":true,"showingLogs":true}}',
|
|
||||||
onClick: undefined,
|
onClick: undefined,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -469,7 +469,7 @@ export interface DataQueryRequest<TQuery extends DataQuery = DataQuery> {
|
|||||||
// Explore state used by various datasources
|
// Explore state used by various datasources
|
||||||
liveStreaming?: boolean;
|
liveStreaming?: boolean;
|
||||||
/**
|
/**
|
||||||
* @deprecated showingGraph and showingTable are always set to true and set to true
|
* @deprecated showingGraph and showingTable are always set to true
|
||||||
*/
|
*/
|
||||||
showingGraph?: boolean;
|
showingGraph?: boolean;
|
||||||
showingTable?: boolean;
|
showingTable?: boolean;
|
||||||
|
@ -1,20 +1,10 @@
|
|||||||
import { RawTimeRange } from './time';
|
import { RawTimeRange } from './time';
|
||||||
import { LogsDedupStrategy } from './logs';
|
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
export interface ExploreUrlState {
|
export interface ExploreUrlState {
|
||||||
datasource: string;
|
datasource: string;
|
||||||
queries: any[]; // Should be a DataQuery, but we're going to strip refIds, so typing makes less sense
|
queries: any[]; // Should be a DataQuery, but we're going to strip refIds, so typing makes less sense
|
||||||
range: RawTimeRange;
|
range: RawTimeRange;
|
||||||
ui: ExploreUIState;
|
|
||||||
originPanelId?: number;
|
originPanelId?: number;
|
||||||
context?: string;
|
context?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @internal */
|
|
||||||
export interface ExploreUIState {
|
|
||||||
showingTable: boolean;
|
|
||||||
showingGraph: boolean;
|
|
||||||
showingLogs: boolean;
|
|
||||||
dedupStrategy?: LogsDedupStrategy;
|
|
||||||
}
|
|
||||||
|
@ -30,8 +30,7 @@ describe('mapInternalLinkToExplore', () => {
|
|||||||
expect(link).toEqual(
|
expect(link).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
title: 'testDS',
|
title: 'testDS',
|
||||||
href:
|
href: '/explore?left={"datasource":"testDS","queries":[{"query":"12344"}]}',
|
||||||
'/explore?left={"datasource":"testDS","queries":[{"query":"12344"}],"ui":{"showingGraph":true,"showingTable":true,"showingLogs":true}}',
|
|
||||||
onClick: undefined,
|
onClick: undefined,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -79,13 +79,6 @@ function generateInternalHref<T extends DataQuery = any>(datasourceName: string,
|
|||||||
range: range.raw,
|
range: range.raw,
|
||||||
datasource: datasourceName,
|
datasource: datasourceName,
|
||||||
queries: [query],
|
queries: [query],
|
||||||
// This should get overwritten if datasource does not support that mode and we do not know what mode is
|
|
||||||
// preferred anyway.
|
|
||||||
ui: {
|
|
||||||
showingGraph: true,
|
|
||||||
showingTable: true,
|
|
||||||
showingLogs: true,
|
|
||||||
},
|
|
||||||
})}`
|
})}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -134,20 +134,7 @@ export const urlUtil = {
|
|||||||
|
|
||||||
export function serializeStateToUrlParam(urlState: ExploreUrlState, compact?: boolean): string {
|
export function serializeStateToUrlParam(urlState: ExploreUrlState, compact?: boolean): string {
|
||||||
if (compact) {
|
if (compact) {
|
||||||
return JSON.stringify([
|
return JSON.stringify([urlState.range.from, urlState.range.to, urlState.datasource, ...urlState.queries]);
|
||||||
urlState.range.from,
|
|
||||||
urlState.range.to,
|
|
||||||
urlState.datasource,
|
|
||||||
...urlState.queries,
|
|
||||||
{
|
|
||||||
ui: [
|
|
||||||
!!urlState.ui.showingGraph,
|
|
||||||
!!urlState.ui.showingLogs,
|
|
||||||
!!urlState.ui.showingTable,
|
|
||||||
urlState.ui.dedupStrategy,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
return JSON.stringify(urlState);
|
return JSON.stringify(urlState);
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ import {
|
|||||||
GetExploreUrlArguments,
|
GetExploreUrlArguments,
|
||||||
} from './explore';
|
} from './explore';
|
||||||
import store from 'app/core/store';
|
import store from 'app/core/store';
|
||||||
import { DataQueryError, dateTime, LogsDedupStrategy, ExploreUrlState, LogsSortOrder } from '@grafana/data';
|
import { DataQueryError, dateTime, ExploreUrlState, LogsSortOrder } from '@grafana/data';
|
||||||
import { RefreshPicker } from '@grafana/ui';
|
import { RefreshPicker } from '@grafana/ui';
|
||||||
import { serializeStateToUrlParam } from '@grafana/data/src/utils/url';
|
import { serializeStateToUrlParam } from '@grafana/data/src/utils/url';
|
||||||
|
|
||||||
@ -21,12 +21,6 @@ const DEFAULT_EXPLORE_STATE: ExploreUrlState = {
|
|||||||
datasource: '',
|
datasource: '',
|
||||||
queries: [],
|
queries: [],
|
||||||
range: DEFAULT_RANGE,
|
range: DEFAULT_RANGE,
|
||||||
ui: {
|
|
||||||
showingGraph: true,
|
|
||||||
showingTable: true,
|
|
||||||
showingLogs: true,
|
|
||||||
dedupStrategy: LogsDedupStrategy.none,
|
|
||||||
},
|
|
||||||
originPanelId: undefined,
|
originPanelId: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -103,8 +97,7 @@ describe('state functions', () => {
|
|||||||
|
|
||||||
expect(serializeStateToUrlParam(state)).toBe(
|
expect(serializeStateToUrlParam(state)).toBe(
|
||||||
'{"datasource":"foo","queries":[{"expr":"metric{test=\\"a/b\\"}"},' +
|
'{"datasource":"foo","queries":[{"expr":"metric{test=\\"a/b\\"}"},' +
|
||||||
'{"expr":"super{foo=\\"x/z\\"}"}],"range":{"from":"now-5h","to":"now"},' +
|
'{"expr":"super{foo=\\"x/z\\"}"}],"range":{"from":"now-5h","to":"now"}}'
|
||||||
'"ui":{"showingGraph":true,"showingTable":true,"showingLogs":true,"dedupStrategy":"none"}}'
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -126,7 +119,7 @@ describe('state functions', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
expect(serializeStateToUrlParam(state, true)).toBe(
|
expect(serializeStateToUrlParam(state, true)).toBe(
|
||||||
'["now-5h","now","foo",{"expr":"metric{test=\\"a/b\\"}"},{"expr":"super{foo=\\"x/z\\"}"},{"ui":[true,true,true,"none"]}]'
|
'["now-5h","now","foo",{"expr":"metric{test=\\"a/b\\"}"},{"expr":"super{foo=\\"x/z\\"}"}]'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -41,9 +41,6 @@ export const DEFAULT_RANGE = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const DEFAULT_UI_STATE = {
|
export const DEFAULT_UI_STATE = {
|
||||||
showingTable: true,
|
|
||||||
showingGraph: true,
|
|
||||||
showingLogs: true,
|
|
||||||
dedupStrategy: LogsDedupStrategy.none,
|
dedupStrategy: LogsDedupStrategy.none,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -189,13 +186,6 @@ enum ParseUrlStateIndex {
|
|||||||
SegmentsStart = 3,
|
SegmentsStart = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ParseUiStateIndex {
|
|
||||||
Graph = 0,
|
|
||||||
Logs = 1,
|
|
||||||
Table = 2,
|
|
||||||
Strategy = 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const safeParseJson = (text?: string): any | undefined => {
|
export const safeParseJson = (text?: string): any | undefined => {
|
||||||
if (!text) {
|
if (!text) {
|
||||||
return;
|
return;
|
||||||
@ -228,7 +218,6 @@ export function parseUrlState(initial: string | undefined): ExploreUrlState {
|
|||||||
datasource: null,
|
datasource: null,
|
||||||
queries: [],
|
queries: [],
|
||||||
range: DEFAULT_RANGE,
|
range: DEFAULT_RANGE,
|
||||||
ui: DEFAULT_UI_STATE,
|
|
||||||
mode: null,
|
mode: null,
|
||||||
originPanelId: null,
|
originPanelId: null,
|
||||||
};
|
};
|
||||||
@ -254,18 +243,8 @@ export function parseUrlState(initial: string | undefined): ExploreUrlState {
|
|||||||
const parsedSegments = parsed.slice(ParseUrlStateIndex.SegmentsStart);
|
const parsedSegments = parsed.slice(ParseUrlStateIndex.SegmentsStart);
|
||||||
const queries = parsedSegments.filter(segment => !isSegment(segment, 'ui', 'originPanelId'));
|
const queries = parsedSegments.filter(segment => !isSegment(segment, 'ui', 'originPanelId'));
|
||||||
|
|
||||||
const uiState = parsedSegments.filter(segment => isSegment(segment, 'ui'))[0];
|
|
||||||
const ui = uiState
|
|
||||||
? {
|
|
||||||
showingGraph: uiState.ui[ParseUiStateIndex.Graph],
|
|
||||||
showingLogs: uiState.ui[ParseUiStateIndex.Logs],
|
|
||||||
showingTable: uiState.ui[ParseUiStateIndex.Table],
|
|
||||||
dedupStrategy: uiState.ui[ParseUiStateIndex.Strategy],
|
|
||||||
}
|
|
||||||
: DEFAULT_UI_STATE;
|
|
||||||
|
|
||||||
const originPanelId = parsedSegments.filter(segment => isSegment(segment, 'originPanelId'))[0];
|
const originPanelId = parsedSegments.filter(segment => isSegment(segment, 'originPanelId'))[0];
|
||||||
return { datasource, queries, range, ui, originPanelId };
|
return { datasource, queries, range, originPanelId };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateKey(index = 0): string {
|
export function generateKey(index = 0): string {
|
||||||
|
@ -185,11 +185,6 @@ export const createUrlFromRichHistory = (query: RichHistoryQuery) => {
|
|||||||
range: { from: 'now-1h', to: 'now' },
|
range: { from: 'now-1h', to: 'now' },
|
||||||
datasource: query.datasourceName,
|
datasource: query.datasourceName,
|
||||||
queries: query.queries,
|
queries: query.queries,
|
||||||
ui: {
|
|
||||||
showingGraph: true,
|
|
||||||
showingLogs: true,
|
|
||||||
showingTable: true,
|
|
||||||
},
|
|
||||||
context: 'explore',
|
context: 'explore',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -29,7 +29,6 @@ const dummyProps: ExploreProps = {
|
|||||||
queries: false,
|
queries: false,
|
||||||
range: false,
|
range: false,
|
||||||
mode: false,
|
mode: false,
|
||||||
ui: false,
|
|
||||||
},
|
},
|
||||||
refreshExplore: jest.fn(),
|
refreshExplore: jest.fn(),
|
||||||
scanning: false,
|
scanning: false,
|
||||||
@ -52,11 +51,6 @@ const dummyProps: ExploreProps = {
|
|||||||
to: 'now',
|
to: 'now',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
initialUI: {
|
|
||||||
showingTable: false,
|
|
||||||
showingGraph: false,
|
|
||||||
showingLogs: false,
|
|
||||||
},
|
|
||||||
isLive: false,
|
isLive: false,
|
||||||
syncedTimes: false,
|
syncedTimes: false,
|
||||||
updateTimeRange: jest.fn(),
|
updateTimeRange: jest.fn(),
|
||||||
|
@ -18,7 +18,6 @@ import {
|
|||||||
RawTimeRange,
|
RawTimeRange,
|
||||||
TimeRange,
|
TimeRange,
|
||||||
TimeZone,
|
TimeZone,
|
||||||
ExploreUIState,
|
|
||||||
ExploreUrlState,
|
ExploreUrlState,
|
||||||
LogsModel,
|
LogsModel,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
@ -44,7 +43,6 @@ import { ExploreId, ExploreItemState, ExploreUpdateState } from 'app/types/explo
|
|||||||
import { StoreState } from 'app/types';
|
import { StoreState } from 'app/types';
|
||||||
import {
|
import {
|
||||||
DEFAULT_RANGE,
|
DEFAULT_RANGE,
|
||||||
DEFAULT_UI_STATE,
|
|
||||||
ensureQueries,
|
ensureQueries,
|
||||||
getFirstNonQueryRowSpecificError,
|
getFirstNonQueryRowSpecificError,
|
||||||
getTimeRange,
|
getTimeRange,
|
||||||
@ -105,7 +103,6 @@ export interface ExploreProps {
|
|||||||
initialDatasource: string;
|
initialDatasource: string;
|
||||||
initialQueries: DataQuery[];
|
initialQueries: DataQuery[];
|
||||||
initialRange: TimeRange;
|
initialRange: TimeRange;
|
||||||
initialUI: ExploreUIState;
|
|
||||||
isLive: boolean;
|
isLive: boolean;
|
||||||
syncedTimes: boolean;
|
syncedTimes: boolean;
|
||||||
updateTimeRange: typeof updateTimeRange;
|
updateTimeRange: typeof updateTimeRange;
|
||||||
@ -171,15 +168,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const {
|
const { initialized, exploreId, initialDatasource, initialQueries, initialRange, originPanelId } = this.props;
|
||||||
initialized,
|
|
||||||
exploreId,
|
|
||||||
initialDatasource,
|
|
||||||
initialQueries,
|
|
||||||
initialRange,
|
|
||||||
initialUI,
|
|
||||||
originPanelId,
|
|
||||||
} = this.props;
|
|
||||||
const width = this.el ? this.el.offsetWidth : 0;
|
const width = this.el ? this.el.offsetWidth : 0;
|
||||||
|
|
||||||
// initialize the whole explore first time we mount and if browser history contains a change in datasource
|
// initialize the whole explore first time we mount and if browser history contains a change in datasource
|
||||||
@ -191,7 +180,6 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
|||||||
initialRange,
|
initialRange,
|
||||||
width,
|
width,
|
||||||
this.exploreEvents,
|
this.exploreEvents,
|
||||||
initialUI,
|
|
||||||
originPanelId
|
originPanelId
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -289,7 +277,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
|||||||
refreshExplore = () => {
|
refreshExplore = () => {
|
||||||
const { exploreId, update } = this.props;
|
const { exploreId, update } = this.props;
|
||||||
|
|
||||||
if (update.queries || update.ui || update.range || update.datasource || update.mode) {
|
if (update.queries || update.range || update.datasource || update.mode) {
|
||||||
this.props.refreshExplore(exploreId);
|
this.props.refreshExplore(exploreId);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -474,15 +462,13 @@ function mapStateToProps(state: StoreState, { exploreId }: ExploreProps): Partia
|
|||||||
queryResponse,
|
queryResponse,
|
||||||
} = item;
|
} = item;
|
||||||
|
|
||||||
const { datasource, queries, range: urlRange, ui, originPanelId } = (urlState || {}) as ExploreUrlState;
|
const { datasource, queries, range: urlRange, originPanelId } = (urlState || {}) as ExploreUrlState;
|
||||||
const initialDatasource = datasource || store.get(lastUsedDatasourceKeyForOrgId(state.user.orgId));
|
const initialDatasource = datasource || store.get(lastUsedDatasourceKeyForOrgId(state.user.orgId));
|
||||||
const initialQueries: DataQuery[] = ensureQueriesMemoized(queries);
|
const initialQueries: DataQuery[] = ensureQueriesMemoized(queries);
|
||||||
const initialRange = urlRange
|
const initialRange = urlRange
|
||||||
? getTimeRangeFromUrlMemoized(urlRange, timeZone)
|
? getTimeRangeFromUrlMemoized(urlRange, timeZone)
|
||||||
: getTimeRange(timeZone, DEFAULT_RANGE);
|
: getTimeRange(timeZone, DEFAULT_RANGE);
|
||||||
|
|
||||||
const initialUI = ui || DEFAULT_UI_STATE;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
datasourceInstance,
|
datasourceInstance,
|
||||||
datasourceMissing,
|
datasourceMissing,
|
||||||
@ -493,7 +479,6 @@ function mapStateToProps(state: StoreState, { exploreId }: ExploreProps): Partia
|
|||||||
initialDatasource,
|
initialDatasource,
|
||||||
initialQueries,
|
initialQueries,
|
||||||
initialRange,
|
initialRange,
|
||||||
initialUI,
|
|
||||||
isLive,
|
isLive,
|
||||||
graphResult: graphResult ?? undefined,
|
graphResult: graphResult ?? undefined,
|
||||||
logsResult: logsResult ?? undefined,
|
logsResult: logsResult ?? undefined,
|
||||||
|
@ -13,7 +13,7 @@ import {
|
|||||||
PanelData,
|
PanelData,
|
||||||
QueryFixAction,
|
QueryFixAction,
|
||||||
TimeRange,
|
TimeRange,
|
||||||
ExploreUIState,
|
LogsDedupStrategy,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { ExploreId, ExploreItemState } from 'app/types/explore';
|
import { ExploreId, ExploreItemState } from 'app/types/explore';
|
||||||
|
|
||||||
@ -56,7 +56,6 @@ export interface InitializeExplorePayload {
|
|||||||
eventBridge: Emitter;
|
eventBridge: Emitter;
|
||||||
queries: DataQuery[];
|
queries: DataQuery[];
|
||||||
range: TimeRange;
|
range: TimeRange;
|
||||||
ui: ExploreUIState;
|
|
||||||
originPanelId?: number | null;
|
originPanelId?: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,10 +125,6 @@ export interface SyncTimesPayload {
|
|||||||
syncedTimes: boolean;
|
syncedTimes: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdateUIStatePayload extends Partial<ExploreUIState> {
|
|
||||||
exploreId: ExploreId;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UpdateDatasourceInstancePayload {
|
export interface UpdateDatasourceInstancePayload {
|
||||||
exploreId: ExploreId;
|
exploreId: ExploreId;
|
||||||
datasourceInstance: DataSourceApi;
|
datasourceInstance: DataSourceApi;
|
||||||
@ -170,6 +165,11 @@ export interface ResetExplorePayload {
|
|||||||
force?: boolean;
|
force?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ChangeDedupStrategyPayload {
|
||||||
|
exploreId: ExploreId;
|
||||||
|
dedupStrategy: LogsDedupStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a query row after the row with the given index.
|
* Adds a query row after the row with the given index.
|
||||||
*/
|
*/
|
||||||
@ -192,6 +192,11 @@ export const changeSizeAction = createAction<ChangeSizePayload>('explore/changeS
|
|||||||
*/
|
*/
|
||||||
export const changeRefreshIntervalAction = createAction<ChangeRefreshIntervalPayload>('explore/changeRefreshInterval');
|
export const changeRefreshIntervalAction = createAction<ChangeRefreshIntervalPayload>('explore/changeRefreshInterval');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change deduplication strategy for logs.
|
||||||
|
*/
|
||||||
|
export const changeDedupStrategyAction = createAction<ChangeDedupStrategyPayload>('explore/changeDedupStrategyAction');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear all queries and results.
|
* Clear all queries and results.
|
||||||
*/
|
*/
|
||||||
@ -283,10 +288,6 @@ export const splitOpenAction = createAction<SplitOpenPayload>('explore/splitOpen
|
|||||||
export const syncTimesAction = createAction<SyncTimesPayload>('explore/syncTimes');
|
export const syncTimesAction = createAction<SyncTimesPayload>('explore/syncTimes');
|
||||||
|
|
||||||
export const richHistoryUpdatedAction = createAction<any>('explore/richHistoryUpdated');
|
export const richHistoryUpdatedAction = createAction<any>('explore/richHistoryUpdated');
|
||||||
/**
|
|
||||||
* Update state of Explores UI elements (panels visiblity and deduplication strategy)
|
|
||||||
*/
|
|
||||||
export const updateUIStateAction = createAction<UpdateUIStatePayload>('explore/updateUIState');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates datasource instance before datasouce loading has started
|
* Updates datasource instance before datasouce loading has started
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { PayloadAction } from '@reduxjs/toolkit';
|
import { PayloadAction } from '@reduxjs/toolkit';
|
||||||
import { DataQuery, DefaultTimeZone, LogsDedupStrategy, toUtc, ExploreUrlState } from '@grafana/data';
|
import { DataQuery, DefaultTimeZone, toUtc, ExploreUrlState } from '@grafana/data';
|
||||||
|
|
||||||
import { cancelQueries, loadDatasource, navigateToExplore, refreshExplore } from './actions';
|
import { cancelQueries, loadDatasource, navigateToExplore, refreshExplore } from './actions';
|
||||||
import { ExploreId, ExploreUpdateState } from 'app/types';
|
import { ExploreId, ExploreUpdateState } from 'app/types';
|
||||||
@ -12,7 +12,6 @@ import {
|
|||||||
loadDatasourceReadyAction,
|
loadDatasourceReadyAction,
|
||||||
scanStopAction,
|
scanStopAction,
|
||||||
setQueriesAction,
|
setQueriesAction,
|
||||||
updateUIStateAction,
|
|
||||||
} from './actionTypes';
|
} from './actionTypes';
|
||||||
import { Emitter } from 'app/core/core';
|
import { Emitter } from 'app/core/core';
|
||||||
import { makeInitialUpdateState } from './reducers';
|
import { makeInitialUpdateState } from './reducers';
|
||||||
@ -63,14 +62,12 @@ const setup = (updateOverides?: Partial<ExploreUpdateState>) => {
|
|||||||
const exploreId = ExploreId.left;
|
const exploreId = ExploreId.left;
|
||||||
const containerWidth = 1920;
|
const containerWidth = 1920;
|
||||||
const eventBridge = {} as Emitter;
|
const eventBridge = {} as Emitter;
|
||||||
const ui = { dedupStrategy: LogsDedupStrategy.none, showingGraph: false, showingLogs: false, showingTable: false };
|
|
||||||
const timeZone = DefaultTimeZone;
|
const timeZone = DefaultTimeZone;
|
||||||
const range = testRange;
|
const range = testRange;
|
||||||
const urlState: ExploreUrlState = {
|
const urlState: ExploreUrlState = {
|
||||||
datasource: 'some-datasource',
|
datasource: 'some-datasource',
|
||||||
queries: [],
|
queries: [],
|
||||||
range: range.raw,
|
range: range.raw,
|
||||||
ui,
|
|
||||||
};
|
};
|
||||||
const updateDefaults = makeInitialUpdateState();
|
const updateDefaults = makeInitialUpdateState();
|
||||||
const update = { ...updateDefaults, ...updateOverides };
|
const update = { ...updateDefaults, ...updateOverides };
|
||||||
@ -89,7 +86,6 @@ const setup = (updateOverides?: Partial<ExploreUpdateState>) => {
|
|||||||
datasourceInstance: { name: 'some-datasource' },
|
datasourceInstance: { name: 'some-datasource' },
|
||||||
queries: [] as DataQuery[],
|
queries: [] as DataQuery[],
|
||||||
range,
|
range,
|
||||||
ui,
|
|
||||||
refreshInterval: {
|
refreshInterval: {
|
||||||
label: 'Off',
|
label: 'Off',
|
||||||
value: 0,
|
value: 0,
|
||||||
@ -102,7 +98,6 @@ const setup = (updateOverides?: Partial<ExploreUpdateState>) => {
|
|||||||
initialState,
|
initialState,
|
||||||
exploreId,
|
exploreId,
|
||||||
range,
|
range,
|
||||||
ui,
|
|
||||||
containerWidth,
|
containerWidth,
|
||||||
eventBridge,
|
eventBridge,
|
||||||
};
|
};
|
||||||
@ -112,7 +107,7 @@ describe('refreshExplore', () => {
|
|||||||
describe('when explore is initialized', () => {
|
describe('when explore is initialized', () => {
|
||||||
describe('and update datasource is set', () => {
|
describe('and update datasource is set', () => {
|
||||||
it('then it should dispatch initializeExplore', async () => {
|
it('then it should dispatch initializeExplore', async () => {
|
||||||
const { exploreId, ui, initialState, containerWidth, eventBridge } = setup({ datasource: true });
|
const { exploreId, initialState, containerWidth, eventBridge } = setup({ datasource: true });
|
||||||
|
|
||||||
const dispatchedActions = await thunkTester(initialState)
|
const dispatchedActions = await thunkTester(initialState)
|
||||||
.givenThunk(refreshExplore)
|
.givenThunk(refreshExplore)
|
||||||
@ -129,20 +124,6 @@ describe('refreshExplore', () => {
|
|||||||
expect(payload.range.to).toEqual(testRange.to);
|
expect(payload.range.to).toEqual(testRange.to);
|
||||||
expect(payload.range.raw.from).toEqual(testRange.raw.from);
|
expect(payload.range.raw.from).toEqual(testRange.raw.from);
|
||||||
expect(payload.range.raw.to).toEqual(testRange.raw.to);
|
expect(payload.range.raw.to).toEqual(testRange.raw.to);
|
||||||
expect(payload.ui).toEqual(ui);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('and update ui is set', () => {
|
|
||||||
it('then it should dispatch updateUIStateAction', async () => {
|
|
||||||
const { exploreId, initialState, ui } = setup({ ui: true });
|
|
||||||
|
|
||||||
const dispatchedActions = await thunkTester(initialState)
|
|
||||||
.givenThunk(refreshExplore)
|
|
||||||
.whenThunkIsDispatched(exploreId);
|
|
||||||
|
|
||||||
expect(dispatchedActions[0].type).toEqual(updateUIStateAction.type);
|
|
||||||
expect(dispatchedActions[0].payload).toEqual({ ...ui, exploreId });
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -11,13 +11,12 @@ import {
|
|||||||
dateTimeForTimeZone,
|
dateTimeForTimeZone,
|
||||||
isDateTime,
|
isDateTime,
|
||||||
LoadingState,
|
LoadingState,
|
||||||
LogsDedupStrategy,
|
|
||||||
PanelData,
|
PanelData,
|
||||||
QueryFixAction,
|
QueryFixAction,
|
||||||
RawTimeRange,
|
RawTimeRange,
|
||||||
TimeRange,
|
TimeRange,
|
||||||
ExploreUrlState,
|
ExploreUrlState,
|
||||||
ExploreUIState,
|
LogsDedupStrategy,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
// Services & Utils
|
// Services & Utils
|
||||||
import store from 'app/core/store';
|
import store from 'app/core/store';
|
||||||
@ -78,9 +77,10 @@ import {
|
|||||||
splitOpenAction,
|
splitOpenAction,
|
||||||
syncTimesAction,
|
syncTimesAction,
|
||||||
updateDatasourceInstanceAction,
|
updateDatasourceInstanceAction,
|
||||||
updateUIStateAction,
|
|
||||||
changeLoadingStateAction,
|
changeLoadingStateAction,
|
||||||
cancelQueriesAction,
|
cancelQueriesAction,
|
||||||
|
changeDedupStrategyAction,
|
||||||
|
ChangeDedupStrategyPayload,
|
||||||
} from './actionTypes';
|
} from './actionTypes';
|
||||||
import { getTimeZone } from 'app/features/profile/state/selectors';
|
import { getTimeZone } from 'app/features/profile/state/selectors';
|
||||||
import { getShiftedTimeRange } from 'app/core/utils/timePicker';
|
import { getShiftedTimeRange } from 'app/core/utils/timePicker';
|
||||||
@ -91,16 +91,6 @@ import { PanelModel, DashboardModel } from 'app/features/dashboard/state';
|
|||||||
import { getExploreDatasources } from './selectors';
|
import { getExploreDatasources } from './selectors';
|
||||||
import { serializeStateToUrlParam } from '@grafana/data/src/utils/url';
|
import { serializeStateToUrlParam } from '@grafana/data/src/utils/url';
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates UI state and save it to the URL
|
|
||||||
*/
|
|
||||||
const updateExploreUIState = (exploreId: ExploreId, uiStateFragment: Partial<ExploreUIState>): ThunkResult<void> => {
|
|
||||||
return dispatch => {
|
|
||||||
dispatch(updateUIStateAction({ exploreId, ...uiStateFragment }));
|
|
||||||
dispatch(stateSave());
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a query row after the row with the given index.
|
* Adds a query row after the row with the given index.
|
||||||
*/
|
*/
|
||||||
@ -224,6 +214,16 @@ export function changeRefreshInterval(
|
|||||||
return changeRefreshIntervalAction({ exploreId, refreshInterval });
|
return changeRefreshIntervalAction({ exploreId, refreshInterval });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change logs deduplication strategy.
|
||||||
|
*/
|
||||||
|
export const changeDedupStrategy = (
|
||||||
|
exploreId: ExploreId,
|
||||||
|
dedupStrategy: LogsDedupStrategy
|
||||||
|
): PayloadAction<ChangeDedupStrategyPayload> => {
|
||||||
|
return changeDedupStrategyAction({ exploreId, dedupStrategy });
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear all queries and results.
|
* Clear all queries and results.
|
||||||
*/
|
*/
|
||||||
@ -276,7 +276,6 @@ export function initializeExplore(
|
|||||||
range: TimeRange,
|
range: TimeRange,
|
||||||
containerWidth: number,
|
containerWidth: number,
|
||||||
eventBridge: Emitter,
|
eventBridge: Emitter,
|
||||||
ui: ExploreUIState,
|
|
||||||
originPanelId?: number | null
|
originPanelId?: number | null
|
||||||
): ThunkResult<void> {
|
): ThunkResult<void> {
|
||||||
return async (dispatch, getState) => {
|
return async (dispatch, getState) => {
|
||||||
@ -288,7 +287,6 @@ export function initializeExplore(
|
|||||||
eventBridge,
|
eventBridge,
|
||||||
queries,
|
queries,
|
||||||
range,
|
range,
|
||||||
ui,
|
|
||||||
originPanelId,
|
originPanelId,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@ -568,12 +566,6 @@ export const stateSave = (): ThunkResult<void> => {
|
|||||||
datasource: left.datasourceInstance!.name,
|
datasource: left.datasourceInstance!.name,
|
||||||
queries: left.queries.map(clearQueryKeys),
|
queries: left.queries.map(clearQueryKeys),
|
||||||
range: toRawTimeRange(left.range),
|
range: toRawTimeRange(left.range),
|
||||||
ui: {
|
|
||||||
showingGraph: true,
|
|
||||||
showingLogs: true,
|
|
||||||
showingTable: true,
|
|
||||||
dedupStrategy: left.dedupStrategy,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
urlStates.left = serializeStateToUrlParam(leftUrlState, true);
|
urlStates.left = serializeStateToUrlParam(leftUrlState, true);
|
||||||
if (split) {
|
if (split) {
|
||||||
@ -581,12 +573,6 @@ export const stateSave = (): ThunkResult<void> => {
|
|||||||
datasource: right.datasourceInstance!.name,
|
datasource: right.datasourceInstance!.name,
|
||||||
queries: right.queries.map(clearQueryKeys),
|
queries: right.queries.map(clearQueryKeys),
|
||||||
range: toRawTimeRange(right.range),
|
range: toRawTimeRange(right.range),
|
||||||
ui: {
|
|
||||||
showingGraph: true,
|
|
||||||
showingLogs: true,
|
|
||||||
showingTable: true,
|
|
||||||
dedupStrategy: right.dedupStrategy,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
urlStates.right = serializeStateToUrlParam(rightUrlState, true);
|
urlStates.right = serializeStateToUrlParam(rightUrlState, true);
|
||||||
@ -745,15 +731,6 @@ export function syncTimes(exploreId: ExploreId): ThunkResult<void> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Change logs deduplication strategy and update URL.
|
|
||||||
*/
|
|
||||||
export const changeDedupStrategy = (exploreId: ExploreId, dedupStrategy: LogsDedupStrategy): ThunkResult<void> => {
|
|
||||||
return dispatch => {
|
|
||||||
dispatch(updateExploreUIState(exploreId, { dedupStrategy }));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reacts to changes in URL state that we need to sync back to our redux state. Checks the internal update variable
|
* Reacts to changes in URL state that we need to sync back to our redux state. Checks the internal update variable
|
||||||
* to see which parts change and need to be synced.
|
* to see which parts change and need to be synced.
|
||||||
@ -772,7 +749,7 @@ export function refreshExplore(exploreId: ExploreId): ThunkResult<void> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { datasource, queries, range: urlRange, ui, originPanelId } = urlState;
|
const { datasource, queries, range: urlRange, originPanelId } = urlState;
|
||||||
const refreshQueries: DataQuery[] = [];
|
const refreshQueries: DataQuery[] = [];
|
||||||
|
|
||||||
for (let index = 0; index < queries.length; index++) {
|
for (let index = 0; index < queries.length; index++) {
|
||||||
@ -787,7 +764,7 @@ export function refreshExplore(exploreId: ExploreId): ThunkResult<void> {
|
|||||||
if (update.datasource) {
|
if (update.datasource) {
|
||||||
const initialQueries = ensureQueries(queries);
|
const initialQueries = ensureQueries(queries);
|
||||||
dispatch(
|
dispatch(
|
||||||
initializeExplore(exploreId, datasource, initialQueries, range, containerWidth, eventBridge, ui, originPanelId)
|
initializeExplore(exploreId, datasource, initialQueries, range, containerWidth, eventBridge, originPanelId)
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -796,18 +773,13 @@ export function refreshExplore(exploreId: ExploreId): ThunkResult<void> {
|
|||||||
dispatch(updateTime({ exploreId, rawRange: range.raw }));
|
dispatch(updateTime({ exploreId, rawRange: range.raw }));
|
||||||
}
|
}
|
||||||
|
|
||||||
// need to refresh ui state
|
|
||||||
if (update.ui) {
|
|
||||||
dispatch(updateUIStateAction({ ...ui, exploreId }));
|
|
||||||
}
|
|
||||||
|
|
||||||
// need to refresh queries
|
// need to refresh queries
|
||||||
if (update.queries) {
|
if (update.queries) {
|
||||||
dispatch(setQueriesAction({ exploreId, queries: refreshQueries }));
|
dispatch(setQueriesAction({ exploreId, queries: refreshQueries }));
|
||||||
}
|
}
|
||||||
|
|
||||||
// always run queries when refresh is needed
|
// always run queries when refresh is needed
|
||||||
if (update.queries || update.ui || update.range) {
|
if (update.queries || update.range) {
|
||||||
dispatch(runQueries(exploreId));
|
dispatch(runQueries(exploreId));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -4,10 +4,10 @@ import {
|
|||||||
dateTime,
|
dateTime,
|
||||||
ExploreMode,
|
ExploreMode,
|
||||||
LoadingState,
|
LoadingState,
|
||||||
LogsDedupStrategy,
|
|
||||||
RawTimeRange,
|
RawTimeRange,
|
||||||
UrlQueryMap,
|
UrlQueryMap,
|
||||||
ExploreUrlState,
|
ExploreUrlState,
|
||||||
|
LogsDedupStrategy,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -30,6 +30,7 @@ import {
|
|||||||
updateDatasourceInstanceAction,
|
updateDatasourceInstanceAction,
|
||||||
addQueryRowAction,
|
addQueryRowAction,
|
||||||
removeQueryRowAction,
|
removeQueryRowAction,
|
||||||
|
changeDedupStrategyAction,
|
||||||
} from './actionTypes';
|
} from './actionTypes';
|
||||||
import { updateLocation } from '../../../core/actions';
|
import { updateLocation } from '../../../core/actions';
|
||||||
import { serializeStateToUrlParam } from '@grafana/data/src/utils/url';
|
import { serializeStateToUrlParam } from '@grafana/data/src/utils/url';
|
||||||
@ -182,6 +183,24 @@ describe('Explore item reducer', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('changing dedup strategy', () => {
|
||||||
|
describe('when changeDedupStrategyAction is dispatched', () => {
|
||||||
|
it('then it should set correct dedup strategy in state', () => {
|
||||||
|
const initialState = makeExploreItemState();
|
||||||
|
|
||||||
|
reducerTester<ExploreItemState>()
|
||||||
|
.givenReducer(itemReducer, initialState)
|
||||||
|
.whenActionIsDispatched(
|
||||||
|
changeDedupStrategyAction({ exploreId: ExploreId.left, dedupStrategy: LogsDedupStrategy.exact })
|
||||||
|
)
|
||||||
|
.thenStateShouldEqual({
|
||||||
|
...makeExploreItemState(),
|
||||||
|
dedupStrategy: LogsDedupStrategy.exact,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('query rows', () => {
|
describe('query rows', () => {
|
||||||
it('adds a new query row', () => {
|
it('adds a new query row', () => {
|
||||||
reducerTester<ExploreItemState>()
|
reducerTester<ExploreItemState>()
|
||||||
@ -261,12 +280,6 @@ export const setup = (urlStateOverrides?: any) => {
|
|||||||
from: '',
|
from: '',
|
||||||
to: '',
|
to: '',
|
||||||
},
|
},
|
||||||
ui: {
|
|
||||||
dedupStrategy: LogsDedupStrategy.none,
|
|
||||||
showingGraph: false,
|
|
||||||
showingTable: false,
|
|
||||||
showingLogs: false,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
const urlState: ExploreUrlState = { ...urlStateDefaults, ...urlStateOverrides };
|
const urlState: ExploreUrlState = { ...urlStateDefaults, ...urlStateOverrides };
|
||||||
const serializedUrlState = serializeStateToUrlParam(urlState);
|
const serializedUrlState = serializeStateToUrlParam(urlState);
|
||||||
@ -557,47 +570,6 @@ describe('Explore reducer', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('and ui differs', () => {
|
|
||||||
it('then it should return update ui', () => {
|
|
||||||
const { initialState, serializedUrlState } = setup();
|
|
||||||
const expectedState = {
|
|
||||||
...initialState,
|
|
||||||
left: {
|
|
||||||
...initialState.left,
|
|
||||||
update: {
|
|
||||||
...initialState.left.update,
|
|
||||||
ui: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const stateWithDifferentDataSource: any = {
|
|
||||||
...initialState,
|
|
||||||
left: {
|
|
||||||
...initialState.left,
|
|
||||||
urlState: {
|
|
||||||
...initialState.left.urlState,
|
|
||||||
ui: {
|
|
||||||
...initialState.left.urlState!.ui,
|
|
||||||
showingGraph: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
reducerTester<ExploreState>()
|
|
||||||
.givenReducer(exploreReducer, stateWithDifferentDataSource)
|
|
||||||
.whenActionIsDispatched(
|
|
||||||
updateLocation({
|
|
||||||
query: {
|
|
||||||
left: serializedUrlState,
|
|
||||||
},
|
|
||||||
path: '/explore',
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.thenStateShouldEqual(expectedState);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('and nothing differs', () => {
|
describe('and nothing differs', () => {
|
||||||
it('then it should return update ui', () => {
|
it('then it should return update ui', () => {
|
||||||
const { initialState, serializedUrlState } = setup();
|
const { initialState, serializedUrlState } = setup();
|
||||||
|
@ -19,7 +19,6 @@ import { RefreshPicker } from '@grafana/ui';
|
|||||||
import { LocationUpdate } from '@grafana/runtime';
|
import { LocationUpdate } from '@grafana/runtime';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DEFAULT_UI_STATE,
|
|
||||||
ensureQueries,
|
ensureQueries,
|
||||||
generateNewKeyAndAddRefIdIfMissing,
|
generateNewKeyAndAddRefIdIfMissing,
|
||||||
getQueryKeys,
|
getQueryKeys,
|
||||||
@ -62,8 +61,8 @@ import {
|
|||||||
syncTimesAction,
|
syncTimesAction,
|
||||||
toggleLogLevelAction,
|
toggleLogLevelAction,
|
||||||
updateDatasourceInstanceAction,
|
updateDatasourceInstanceAction,
|
||||||
updateUIStateAction,
|
|
||||||
cancelQueriesAction,
|
cancelQueriesAction,
|
||||||
|
changeDedupStrategyAction,
|
||||||
} from './actionTypes';
|
} from './actionTypes';
|
||||||
import { ResultProcessor } from '../utils/ResultProcessor';
|
import { ResultProcessor } from '../utils/ResultProcessor';
|
||||||
import { updateLocation } from '../../../core/actions';
|
import { updateLocation } from '../../../core/actions';
|
||||||
@ -79,7 +78,6 @@ export const makeInitialUpdateState = (): ExploreUpdateState => ({
|
|||||||
queries: false,
|
queries: false,
|
||||||
range: false,
|
range: false,
|
||||||
mode: false,
|
mode: false,
|
||||||
ui: false,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -237,8 +235,16 @@ export const itemReducer = (state: ExploreItemState = makeExploreItemState(), ac
|
|||||||
return { ...state, logsHighlighterExpressions: expressions };
|
return { ...state, logsHighlighterExpressions: expressions };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (changeDedupStrategyAction.match(action)) {
|
||||||
|
const { dedupStrategy } = action.payload;
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
dedupStrategy,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (initializeExploreAction.match(action)) {
|
if (initializeExploreAction.match(action)) {
|
||||||
const { containerWidth, eventBridge, queries, range, ui, originPanelId } = action.payload;
|
const { containerWidth, eventBridge, queries, range, originPanelId } = action.payload;
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
containerWidth,
|
containerWidth,
|
||||||
@ -247,7 +253,6 @@ export const itemReducer = (state: ExploreItemState = makeExploreItemState(), ac
|
|||||||
queries,
|
queries,
|
||||||
initialized: true,
|
initialized: true,
|
||||||
queryKeys: getQueryKeys(queries, state.datasourceInstance),
|
queryKeys: getQueryKeys(queries, state.datasourceInstance),
|
||||||
...ui,
|
|
||||||
originPanelId,
|
originPanelId,
|
||||||
update: makeInitialUpdateState(),
|
update: makeInitialUpdateState(),
|
||||||
};
|
};
|
||||||
@ -401,10 +406,6 @@ export const itemReducer = (state: ExploreItemState = makeExploreItemState(), ac
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updateUIStateAction.match(action)) {
|
|
||||||
return { ...state, ...action.payload };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (queriesImportedAction.match(action)) {
|
if (queriesImportedAction.match(action)) {
|
||||||
const { queries } = action.payload;
|
const { queries } = action.payload;
|
||||||
return {
|
return {
|
||||||
@ -567,14 +568,13 @@ export const updateChildRefreshState = (
|
|||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
urlState,
|
urlState,
|
||||||
update: { datasource: false, queries: false, range: false, mode: false, ui: false },
|
update: { datasource: false, queries: false, range: false, mode: false },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const datasource = _.isEqual(urlState ? urlState.datasource : '', state.urlState.datasource) === false;
|
const datasource = _.isEqual(urlState ? urlState.datasource : '', state.urlState.datasource) === false;
|
||||||
const queries = _.isEqual(urlState ? urlState.queries : [], state.urlState.queries) === false;
|
const queries = _.isEqual(urlState ? urlState.queries : [], state.urlState.queries) === false;
|
||||||
const range = _.isEqual(urlState ? urlState.range : DEFAULT_RANGE, state.urlState.range) === false;
|
const range = _.isEqual(urlState ? urlState.range : DEFAULT_RANGE, state.urlState.range) === false;
|
||||||
const ui = _.isEqual(urlState ? urlState.ui : DEFAULT_UI_STATE, state.urlState.ui) === false;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
@ -584,7 +584,6 @@ export const updateChildRefreshState = (
|
|||||||
datasource,
|
datasource,
|
||||||
queries,
|
queries,
|
||||||
range,
|
range,
|
||||||
ui,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -49,7 +49,7 @@ describe('getFieldLinksForExplore', () => {
|
|||||||
const links = getFieldLinksForExplore(field, 0, splitfn, range);
|
const links = getFieldLinksForExplore(field, 0, splitfn, range);
|
||||||
|
|
||||||
expect(links[0].href).toBe(
|
expect(links[0].href).toBe(
|
||||||
'/explore?left={"range":{"from":"now-1h","to":"now"},"datasource":"test_ds","queries":[{"query":"query_1"}],"ui":{"showingGraph":true,"showingTable":true,"showingLogs":true}}'
|
'/explore?left={"range":{"from":"now-1h","to":"now"},"datasource":"test_ds","queries":[{"query":"query_1"}]}'
|
||||||
);
|
);
|
||||||
expect(links[0].title).toBe('test_ds');
|
expect(links[0].title).toBe('test_ds');
|
||||||
|
|
||||||
|
@ -191,7 +191,6 @@ export interface ExploreUpdateState {
|
|||||||
queries: boolean;
|
queries: boolean;
|
||||||
range: boolean;
|
range: boolean;
|
||||||
mode: boolean;
|
mode: boolean;
|
||||||
ui: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface QueryOptions {
|
export interface QueryOptions {
|
||||||
|
Loading…
Reference in New Issue
Block a user