Commit 2f5a60f5 by Ivana Huckova Committed by GitHub

Explore: Remove ui params from url (#27753)

* Remove ui from url

* Update tests

* Update changeDedupStrategy

* Add test coverage
parent bd9add72
...@@ -575,8 +575,7 @@ describe('getLinksSupplier', () => { ...@@ -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> { ...@@ -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;
......
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', () => { ...@@ -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, ...@@ -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 = { ...@@ -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 { ...@@ -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 = { ...@@ -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', () => { ...@@ -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', () => { ...@@ -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 = { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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) => { ...@@ -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 = { ...@@ -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 = { ...@@ -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 { ...@@ -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 ...@@ -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 { ...@@ -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> { ...@@ -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> { ...@@ -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> { ...@@ -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 ...@@ -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 ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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.
*/ */
...@@ -193,6 +193,11 @@ export const changeSizeAction = createAction<ChangeSizePayload>('explore/changeS ...@@ -193,6 +193,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.
*/ */
export const clearQueriesAction = createAction<ClearQueriesPayload>('explore/clearQueries'); export const clearQueriesAction = createAction<ClearQueriesPayload>('explore/clearQueries');
...@@ -283,10 +288,6 @@ export const splitOpenAction = createAction<SplitOpenPayload>('explore/splitOpen ...@@ -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
......
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 { ...@@ -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>) => { ...@@ -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>) => { ...@@ -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>) => { ...@@ -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', () => { ...@@ -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', () => { ...@@ -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 { ...@@ -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 { ...@@ -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';
...@@ -92,16 +92,6 @@ import { getExploreDatasources } from './selectors'; ...@@ -92,16 +92,6 @@ 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.
*/ */
export function addQueryRow(exploreId: ExploreId, index: number): ThunkResult<void> { export function addQueryRow(exploreId: ExploreId, index: number): ThunkResult<void> {
...@@ -225,6 +215,16 @@ export function changeRefreshInterval( ...@@ -225,6 +215,16 @@ export function changeRefreshInterval(
} }
/** /**
* 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.
*/ */
export function clearQueries(exploreId: ExploreId): ThunkResult<void> { export function clearQueries(exploreId: ExploreId): ThunkResult<void> {
...@@ -276,7 +276,6 @@ export function initializeExplore( ...@@ -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( ...@@ -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> => { ...@@ -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> => { ...@@ -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);
...@@ -746,15 +732,6 @@ export function syncTimes(exploreId: ExploreId): ThunkResult<void> { ...@@ -746,15 +732,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.
* @param exploreId * @param exploreId
...@@ -772,7 +749,7 @@ export function refreshExplore(exploreId: ExploreId): ThunkResult<void> { ...@@ -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> { ...@@ -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> { ...@@ -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 { ...@@ -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 { ...@@ -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', () => { ...@@ -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) => { ...@@ -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', () => { ...@@ -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'; ...@@ -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 { ...@@ -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 => ({ ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 = ( ...@@ -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 = ( ...@@ -584,7 +584,6 @@ export const updateChildRefreshState = (
datasource, datasource,
queries, queries,
range, range,
ui,
}, },
}; };
}; };
......
...@@ -49,7 +49,7 @@ describe('getFieldLinksForExplore', () => { ...@@ -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 { ...@@ -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 {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment