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.objectContaining({
|
||||
title: 'testDS',
|
||||
href:
|
||||
'/explore?left={"datasource":"testDS","queries":["12345"],"ui":{"showingGraph":true,"showingTable":true,"showingLogs":true}}',
|
||||
href: '/explore?left={"datasource":"testDS","queries":["12345"]}',
|
||||
onClick: undefined,
|
||||
})
|
||||
);
|
||||
|
@ -469,7 +469,7 @@ export interface DataQueryRequest<TQuery extends DataQuery = DataQuery> {
|
||||
// Explore state used by various datasources
|
||||
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;
|
||||
showingTable?: boolean;
|
||||
|
@ -1,20 +1,10 @@
|
||||
import { RawTimeRange } from './time';
|
||||
import { LogsDedupStrategy } from './logs';
|
||||
|
||||
/** @internal */
|
||||
export interface ExploreUrlState {
|
||||
datasource: string;
|
||||
queries: any[]; // Should be a DataQuery, but we're going to strip refIds, so typing makes less sense
|
||||
range: RawTimeRange;
|
||||
ui: ExploreUIState;
|
||||
originPanelId?: number;
|
||||
context?: string;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface ExploreUIState {
|
||||
showingTable: boolean;
|
||||
showingGraph: boolean;
|
||||
showingLogs: boolean;
|
||||
dedupStrategy?: LogsDedupStrategy;
|
||||
}
|
||||
|
@ -30,8 +30,7 @@ describe('mapInternalLinkToExplore', () => {
|
||||
expect(link).toEqual(
|
||||
expect.objectContaining({
|
||||
title: 'testDS',
|
||||
href:
|
||||
'/explore?left={"datasource":"testDS","queries":[{"query":"12344"}],"ui":{"showingGraph":true,"showingTable":true,"showingLogs":true}}',
|
||||
href: '/explore?left={"datasource":"testDS","queries":[{"query":"12344"}]}',
|
||||
onClick: undefined,
|
||||
})
|
||||
);
|
||||
|
@ -79,13 +79,6 @@ function generateInternalHref<T extends DataQuery = any>(datasourceName: string,
|
||||
range: range.raw,
|
||||
datasource: datasourceName,
|
||||
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 {
|
||||
if (compact) {
|
||||
return JSON.stringify([
|
||||
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.range.from, urlState.range.to, urlState.datasource, ...urlState.queries]);
|
||||
}
|
||||
return JSON.stringify(urlState);
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import {
|
||||
GetExploreUrlArguments,
|
||||
} from './explore';
|
||||
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 { serializeStateToUrlParam } from '@grafana/data/src/utils/url';
|
||||
|
||||
@ -21,12 +21,6 @@ const DEFAULT_EXPLORE_STATE: ExploreUrlState = {
|
||||
datasource: '',
|
||||
queries: [],
|
||||
range: DEFAULT_RANGE,
|
||||
ui: {
|
||||
showingGraph: true,
|
||||
showingTable: true,
|
||||
showingLogs: true,
|
||||
dedupStrategy: LogsDedupStrategy.none,
|
||||
},
|
||||
originPanelId: undefined,
|
||||
};
|
||||
|
||||
@ -103,8 +97,7 @@ describe('state functions', () => {
|
||||
|
||||
expect(serializeStateToUrlParam(state)).toBe(
|
||||
'{"datasource":"foo","queries":[{"expr":"metric{test=\\"a/b\\"}"},' +
|
||||
'{"expr":"super{foo=\\"x/z\\"}"}],"range":{"from":"now-5h","to":"now"},' +
|
||||
'"ui":{"showingGraph":true,"showingTable":true,"showingLogs":true,"dedupStrategy":"none"}}'
|
||||
'{"expr":"super{foo=\\"x/z\\"}"}],"range":{"from":"now-5h","to":"now"}}'
|
||||
);
|
||||
});
|
||||
|
||||
@ -126,7 +119,7 @@ describe('state functions', () => {
|
||||
},
|
||||
};
|
||||
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 = {
|
||||
showingTable: true,
|
||||
showingGraph: true,
|
||||
showingLogs: true,
|
||||
dedupStrategy: LogsDedupStrategy.none,
|
||||
};
|
||||
|
||||
@ -189,13 +186,6 @@ enum ParseUrlStateIndex {
|
||||
SegmentsStart = 3,
|
||||
}
|
||||
|
||||
enum ParseUiStateIndex {
|
||||
Graph = 0,
|
||||
Logs = 1,
|
||||
Table = 2,
|
||||
Strategy = 3,
|
||||
}
|
||||
|
||||
export const safeParseJson = (text?: string): any | undefined => {
|
||||
if (!text) {
|
||||
return;
|
||||
@ -228,7 +218,6 @@ export function parseUrlState(initial: string | undefined): ExploreUrlState {
|
||||
datasource: null,
|
||||
queries: [],
|
||||
range: DEFAULT_RANGE,
|
||||
ui: DEFAULT_UI_STATE,
|
||||
mode: null,
|
||||
originPanelId: null,
|
||||
};
|
||||
@ -254,18 +243,8 @@ export function parseUrlState(initial: string | undefined): ExploreUrlState {
|
||||
const parsedSegments = parsed.slice(ParseUrlStateIndex.SegmentsStart);
|
||||
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];
|
||||
return { datasource, queries, range, ui, originPanelId };
|
||||
return { datasource, queries, range, originPanelId };
|
||||
}
|
||||
|
||||
export function generateKey(index = 0): string {
|
||||
|
@ -185,11 +185,6 @@ export const createUrlFromRichHistory = (query: RichHistoryQuery) => {
|
||||
range: { from: 'now-1h', to: 'now' },
|
||||
datasource: query.datasourceName,
|
||||
queries: query.queries,
|
||||
ui: {
|
||||
showingGraph: true,
|
||||
showingLogs: true,
|
||||
showingTable: true,
|
||||
},
|
||||
context: 'explore',
|
||||
};
|
||||
|
||||
|
@ -29,7 +29,6 @@ const dummyProps: ExploreProps = {
|
||||
queries: false,
|
||||
range: false,
|
||||
mode: false,
|
||||
ui: false,
|
||||
},
|
||||
refreshExplore: jest.fn(),
|
||||
scanning: false,
|
||||
@ -52,11 +51,6 @@ const dummyProps: ExploreProps = {
|
||||
to: 'now',
|
||||
},
|
||||
},
|
||||
initialUI: {
|
||||
showingTable: false,
|
||||
showingGraph: false,
|
||||
showingLogs: false,
|
||||
},
|
||||
isLive: false,
|
||||
syncedTimes: false,
|
||||
updateTimeRange: jest.fn(),
|
||||
|
@ -18,7 +18,6 @@ import {
|
||||
RawTimeRange,
|
||||
TimeRange,
|
||||
TimeZone,
|
||||
ExploreUIState,
|
||||
ExploreUrlState,
|
||||
LogsModel,
|
||||
} from '@grafana/data';
|
||||
@ -44,7 +43,6 @@ import { ExploreId, ExploreItemState, ExploreUpdateState } from 'app/types/explo
|
||||
import { StoreState } from 'app/types';
|
||||
import {
|
||||
DEFAULT_RANGE,
|
||||
DEFAULT_UI_STATE,
|
||||
ensureQueries,
|
||||
getFirstNonQueryRowSpecificError,
|
||||
getTimeRange,
|
||||
@ -105,7 +103,6 @@ export interface ExploreProps {
|
||||
initialDatasource: string;
|
||||
initialQueries: DataQuery[];
|
||||
initialRange: TimeRange;
|
||||
initialUI: ExploreUIState;
|
||||
isLive: boolean;
|
||||
syncedTimes: boolean;
|
||||
updateTimeRange: typeof updateTimeRange;
|
||||
@ -171,15 +168,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const {
|
||||
initialized,
|
||||
exploreId,
|
||||
initialDatasource,
|
||||
initialQueries,
|
||||
initialRange,
|
||||
initialUI,
|
||||
originPanelId,
|
||||
} = this.props;
|
||||
const { initialized, exploreId, initialDatasource, initialQueries, initialRange, originPanelId } = this.props;
|
||||
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
|
||||
@ -191,7 +180,6 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
||||
initialRange,
|
||||
width,
|
||||
this.exploreEvents,
|
||||
initialUI,
|
||||
originPanelId
|
||||
);
|
||||
}
|
||||
@ -289,7 +277,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
||||
refreshExplore = () => {
|
||||
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);
|
||||
}
|
||||
};
|
||||
@ -474,15 +462,13 @@ function mapStateToProps(state: StoreState, { exploreId }: ExploreProps): Partia
|
||||
queryResponse,
|
||||
} = 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 initialQueries: DataQuery[] = ensureQueriesMemoized(queries);
|
||||
const initialRange = urlRange
|
||||
? getTimeRangeFromUrlMemoized(urlRange, timeZone)
|
||||
: getTimeRange(timeZone, DEFAULT_RANGE);
|
||||
|
||||
const initialUI = ui || DEFAULT_UI_STATE;
|
||||
|
||||
return {
|
||||
datasourceInstance,
|
||||
datasourceMissing,
|
||||
@ -493,7 +479,6 @@ function mapStateToProps(state: StoreState, { exploreId }: ExploreProps): Partia
|
||||
initialDatasource,
|
||||
initialQueries,
|
||||
initialRange,
|
||||
initialUI,
|
||||
isLive,
|
||||
graphResult: graphResult ?? undefined,
|
||||
logsResult: logsResult ?? undefined,
|
||||
|
@ -13,7 +13,7 @@ import {
|
||||
PanelData,
|
||||
QueryFixAction,
|
||||
TimeRange,
|
||||
ExploreUIState,
|
||||
LogsDedupStrategy,
|
||||
} from '@grafana/data';
|
||||
import { ExploreId, ExploreItemState } from 'app/types/explore';
|
||||
|
||||
@ -56,7 +56,6 @@ export interface InitializeExplorePayload {
|
||||
eventBridge: Emitter;
|
||||
queries: DataQuery[];
|
||||
range: TimeRange;
|
||||
ui: ExploreUIState;
|
||||
originPanelId?: number | null;
|
||||
}
|
||||
|
||||
@ -126,10 +125,6 @@ export interface SyncTimesPayload {
|
||||
syncedTimes: boolean;
|
||||
}
|
||||
|
||||
export interface UpdateUIStatePayload extends Partial<ExploreUIState> {
|
||||
exploreId: ExploreId;
|
||||
}
|
||||
|
||||
export interface UpdateDatasourceInstancePayload {
|
||||
exploreId: ExploreId;
|
||||
datasourceInstance: DataSourceApi;
|
||||
@ -170,6 +165,11 @@ export interface ResetExplorePayload {
|
||||
force?: boolean;
|
||||
}
|
||||
|
||||
export interface ChangeDedupStrategyPayload {
|
||||
exploreId: ExploreId;
|
||||
dedupStrategy: LogsDedupStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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');
|
||||
|
||||
/**
|
||||
* Change deduplication strategy for logs.
|
||||
*/
|
||||
export const changeDedupStrategyAction = createAction<ChangeDedupStrategyPayload>('explore/changeDedupStrategyAction');
|
||||
|
||||
/**
|
||||
* 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 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 { ExploreId, ExploreUpdateState } from 'app/types';
|
||||
@ -12,7 +12,6 @@ import {
|
||||
loadDatasourceReadyAction,
|
||||
scanStopAction,
|
||||
setQueriesAction,
|
||||
updateUIStateAction,
|
||||
} from './actionTypes';
|
||||
import { Emitter } from 'app/core/core';
|
||||
import { makeInitialUpdateState } from './reducers';
|
||||
@ -63,14 +62,12 @@ const setup = (updateOverides?: Partial<ExploreUpdateState>) => {
|
||||
const exploreId = ExploreId.left;
|
||||
const containerWidth = 1920;
|
||||
const eventBridge = {} as Emitter;
|
||||
const ui = { dedupStrategy: LogsDedupStrategy.none, showingGraph: false, showingLogs: false, showingTable: false };
|
||||
const timeZone = DefaultTimeZone;
|
||||
const range = testRange;
|
||||
const urlState: ExploreUrlState = {
|
||||
datasource: 'some-datasource',
|
||||
queries: [],
|
||||
range: range.raw,
|
||||
ui,
|
||||
};
|
||||
const updateDefaults = makeInitialUpdateState();
|
||||
const update = { ...updateDefaults, ...updateOverides };
|
||||
@ -89,7 +86,6 @@ const setup = (updateOverides?: Partial<ExploreUpdateState>) => {
|
||||
datasourceInstance: { name: 'some-datasource' },
|
||||
queries: [] as DataQuery[],
|
||||
range,
|
||||
ui,
|
||||
refreshInterval: {
|
||||
label: 'Off',
|
||||
value: 0,
|
||||
@ -102,7 +98,6 @@ const setup = (updateOverides?: Partial<ExploreUpdateState>) => {
|
||||
initialState,
|
||||
exploreId,
|
||||
range,
|
||||
ui,
|
||||
containerWidth,
|
||||
eventBridge,
|
||||
};
|
||||
@ -112,7 +107,7 @@ describe('refreshExplore', () => {
|
||||
describe('when explore is initialized', () => {
|
||||
describe('and update datasource is set', () => {
|
||||
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)
|
||||
.givenThunk(refreshExplore)
|
||||
@ -129,20 +124,6 @@ describe('refreshExplore', () => {
|
||||
expect(payload.range.to).toEqual(testRange.to);
|
||||
expect(payload.range.raw.from).toEqual(testRange.raw.from);
|
||||
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,
|
||||
isDateTime,
|
||||
LoadingState,
|
||||
LogsDedupStrategy,
|
||||
PanelData,
|
||||
QueryFixAction,
|
||||
RawTimeRange,
|
||||
TimeRange,
|
||||
ExploreUrlState,
|
||||
ExploreUIState,
|
||||
LogsDedupStrategy,
|
||||
} from '@grafana/data';
|
||||
// Services & Utils
|
||||
import store from 'app/core/store';
|
||||
@ -78,9 +77,10 @@ import {
|
||||
splitOpenAction,
|
||||
syncTimesAction,
|
||||
updateDatasourceInstanceAction,
|
||||
updateUIStateAction,
|
||||
changeLoadingStateAction,
|
||||
cancelQueriesAction,
|
||||
changeDedupStrategyAction,
|
||||
ChangeDedupStrategyPayload,
|
||||
} from './actionTypes';
|
||||
import { getTimeZone } from 'app/features/profile/state/selectors';
|
||||
import { getShiftedTimeRange } from 'app/core/utils/timePicker';
|
||||
@ -91,16 +91,6 @@ import { PanelModel, DashboardModel } from 'app/features/dashboard/state';
|
||||
import { getExploreDatasources } from './selectors';
|
||||
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.
|
||||
*/
|
||||
@ -224,6 +214,16 @@ export function changeRefreshInterval(
|
||||
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.
|
||||
*/
|
||||
@ -276,7 +276,6 @@ export function initializeExplore(
|
||||
range: TimeRange,
|
||||
containerWidth: number,
|
||||
eventBridge: Emitter,
|
||||
ui: ExploreUIState,
|
||||
originPanelId?: number | null
|
||||
): ThunkResult<void> {
|
||||
return async (dispatch, getState) => {
|
||||
@ -288,7 +287,6 @@ export function initializeExplore(
|
||||
eventBridge,
|
||||
queries,
|
||||
range,
|
||||
ui,
|
||||
originPanelId,
|
||||
})
|
||||
);
|
||||
@ -568,12 +566,6 @@ export const stateSave = (): ThunkResult<void> => {
|
||||
datasource: left.datasourceInstance!.name,
|
||||
queries: left.queries.map(clearQueryKeys),
|
||||
range: toRawTimeRange(left.range),
|
||||
ui: {
|
||||
showingGraph: true,
|
||||
showingLogs: true,
|
||||
showingTable: true,
|
||||
dedupStrategy: left.dedupStrategy,
|
||||
},
|
||||
};
|
||||
urlStates.left = serializeStateToUrlParam(leftUrlState, true);
|
||||
if (split) {
|
||||
@ -581,12 +573,6 @@ export const stateSave = (): ThunkResult<void> => {
|
||||
datasource: right.datasourceInstance!.name,
|
||||
queries: right.queries.map(clearQueryKeys),
|
||||
range: toRawTimeRange(right.range),
|
||||
ui: {
|
||||
showingGraph: true,
|
||||
showingLogs: true,
|
||||
showingTable: true,
|
||||
dedupStrategy: right.dedupStrategy,
|
||||
},
|
||||
};
|
||||
|
||||
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
|
||||
* to see which parts change and need to be synced.
|
||||
@ -772,7 +749,7 @@ export function refreshExplore(exploreId: ExploreId): ThunkResult<void> {
|
||||
return;
|
||||
}
|
||||
|
||||
const { datasource, queries, range: urlRange, ui, originPanelId } = urlState;
|
||||
const { datasource, queries, range: urlRange, originPanelId } = urlState;
|
||||
const refreshQueries: DataQuery[] = [];
|
||||
|
||||
for (let index = 0; index < queries.length; index++) {
|
||||
@ -787,7 +764,7 @@ export function refreshExplore(exploreId: ExploreId): ThunkResult<void> {
|
||||
if (update.datasource) {
|
||||
const initialQueries = ensureQueries(queries);
|
||||
dispatch(
|
||||
initializeExplore(exploreId, datasource, initialQueries, range, containerWidth, eventBridge, ui, originPanelId)
|
||||
initializeExplore(exploreId, datasource, initialQueries, range, containerWidth, eventBridge, originPanelId)
|
||||
);
|
||||
return;
|
||||
}
|
||||
@ -796,18 +773,13 @@ export function refreshExplore(exploreId: ExploreId): ThunkResult<void> {
|
||||
dispatch(updateTime({ exploreId, rawRange: range.raw }));
|
||||
}
|
||||
|
||||
// need to refresh ui state
|
||||
if (update.ui) {
|
||||
dispatch(updateUIStateAction({ ...ui, exploreId }));
|
||||
}
|
||||
|
||||
// need to refresh queries
|
||||
if (update.queries) {
|
||||
dispatch(setQueriesAction({ exploreId, queries: refreshQueries }));
|
||||
}
|
||||
|
||||
// always run queries when refresh is needed
|
||||
if (update.queries || update.ui || update.range) {
|
||||
if (update.queries || update.range) {
|
||||
dispatch(runQueries(exploreId));
|
||||
}
|
||||
};
|
||||
|
@ -4,10 +4,10 @@ import {
|
||||
dateTime,
|
||||
ExploreMode,
|
||||
LoadingState,
|
||||
LogsDedupStrategy,
|
||||
RawTimeRange,
|
||||
UrlQueryMap,
|
||||
ExploreUrlState,
|
||||
LogsDedupStrategy,
|
||||
} from '@grafana/data';
|
||||
|
||||
import {
|
||||
@ -30,6 +30,7 @@ import {
|
||||
updateDatasourceInstanceAction,
|
||||
addQueryRowAction,
|
||||
removeQueryRowAction,
|
||||
changeDedupStrategyAction,
|
||||
} from './actionTypes';
|
||||
import { updateLocation } from '../../../core/actions';
|
||||
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', () => {
|
||||
it('adds a new query row', () => {
|
||||
reducerTester<ExploreItemState>()
|
||||
@ -261,12 +280,6 @@ export const setup = (urlStateOverrides?: any) => {
|
||||
from: '',
|
||||
to: '',
|
||||
},
|
||||
ui: {
|
||||
dedupStrategy: LogsDedupStrategy.none,
|
||||
showingGraph: false,
|
||||
showingTable: false,
|
||||
showingLogs: false,
|
||||
},
|
||||
};
|
||||
const urlState: ExploreUrlState = { ...urlStateDefaults, ...urlStateOverrides };
|
||||
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', () => {
|
||||
it('then it should return update ui', () => {
|
||||
const { initialState, serializedUrlState } = setup();
|
||||
|
@ -19,7 +19,6 @@ import { RefreshPicker } from '@grafana/ui';
|
||||
import { LocationUpdate } from '@grafana/runtime';
|
||||
|
||||
import {
|
||||
DEFAULT_UI_STATE,
|
||||
ensureQueries,
|
||||
generateNewKeyAndAddRefIdIfMissing,
|
||||
getQueryKeys,
|
||||
@ -62,8 +61,8 @@ import {
|
||||
syncTimesAction,
|
||||
toggleLogLevelAction,
|
||||
updateDatasourceInstanceAction,
|
||||
updateUIStateAction,
|
||||
cancelQueriesAction,
|
||||
changeDedupStrategyAction,
|
||||
} from './actionTypes';
|
||||
import { ResultProcessor } from '../utils/ResultProcessor';
|
||||
import { updateLocation } from '../../../core/actions';
|
||||
@ -79,7 +78,6 @@ export const makeInitialUpdateState = (): ExploreUpdateState => ({
|
||||
queries: false,
|
||||
range: false,
|
||||
mode: false,
|
||||
ui: false,
|
||||
});
|
||||
|
||||
/**
|
||||
@ -237,8 +235,16 @@ export const itemReducer = (state: ExploreItemState = makeExploreItemState(), ac
|
||||
return { ...state, logsHighlighterExpressions: expressions };
|
||||
}
|
||||
|
||||
if (changeDedupStrategyAction.match(action)) {
|
||||
const { dedupStrategy } = action.payload;
|
||||
return {
|
||||
...state,
|
||||
dedupStrategy,
|
||||
};
|
||||
}
|
||||
|
||||
if (initializeExploreAction.match(action)) {
|
||||
const { containerWidth, eventBridge, queries, range, ui, originPanelId } = action.payload;
|
||||
const { containerWidth, eventBridge, queries, range, originPanelId } = action.payload;
|
||||
return {
|
||||
...state,
|
||||
containerWidth,
|
||||
@ -247,7 +253,6 @@ export const itemReducer = (state: ExploreItemState = makeExploreItemState(), ac
|
||||
queries,
|
||||
initialized: true,
|
||||
queryKeys: getQueryKeys(queries, state.datasourceInstance),
|
||||
...ui,
|
||||
originPanelId,
|
||||
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)) {
|
||||
const { queries } = action.payload;
|
||||
return {
|
||||
@ -567,14 +568,13 @@ export const updateChildRefreshState = (
|
||||
return {
|
||||
...state,
|
||||
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 queries = _.isEqual(urlState ? urlState.queries : [], state.urlState.queries) === 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 {
|
||||
...state,
|
||||
@ -584,7 +584,6 @@ export const updateChildRefreshState = (
|
||||
datasource,
|
||||
queries,
|
||||
range,
|
||||
ui,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
@ -49,7 +49,7 @@ describe('getFieldLinksForExplore', () => {
|
||||
const links = getFieldLinksForExplore(field, 0, splitfn, range);
|
||||
|
||||
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');
|
||||
|
||||
|
@ -191,7 +191,6 @@ export interface ExploreUpdateState {
|
||||
queries: boolean;
|
||||
range: boolean;
|
||||
mode: boolean;
|
||||
ui: boolean;
|
||||
}
|
||||
|
||||
export interface QueryOptions {
|
||||
|
Loading…
Reference in New Issue
Block a user