mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Explore: Ensure old panes are removed before opening split view (#70670)
This commit is contained in:
parent
e3a4d7c099
commit
c9c357fc19
@ -94,7 +94,7 @@ export function changeSize(exploreId: string, { width }: { width: number }): Pay
|
|||||||
return changeSizeAction({ exploreId, width });
|
return changeSizeAction({ exploreId, width });
|
||||||
}
|
}
|
||||||
|
|
||||||
interface InitializeExploreOptions {
|
export interface InitializeExploreOptions {
|
||||||
exploreId: string;
|
exploreId: string;
|
||||||
datasource: DataSourceRef | string | undefined;
|
datasource: DataSourceRef | string | undefined;
|
||||||
queries: DataQuery[];
|
queries: DataQuery[];
|
||||||
|
@ -7,9 +7,10 @@ import { PanelModel } from 'app/features/dashboard/state';
|
|||||||
|
|
||||||
import { reducerTester } from '../../../../test/core/redux/reducerTester';
|
import { reducerTester } from '../../../../test/core/redux/reducerTester';
|
||||||
import { MockDataSourceApi } from '../../../../test/mocks/datasource_srv';
|
import { MockDataSourceApi } from '../../../../test/mocks/datasource_srv';
|
||||||
import { ExploreItemState, ExploreState } from '../../../types';
|
import { configureStore } from '../../../store/configureStore';
|
||||||
|
import { ExploreItemState, ExploreState, StoreState, ThunkDispatch } from '../../../types';
|
||||||
|
|
||||||
import { exploreReducer, navigateToExplore, splitClose } from './main';
|
import { exploreReducer, navigateToExplore, splitClose, splitOpen } from './main';
|
||||||
|
|
||||||
const getNavigateToExploreContext = async (openInNewWindow?: (url: string) => void) => {
|
const getNavigateToExploreContext = async (openInNewWindow?: (url: string) => void) => {
|
||||||
const url = '/explore';
|
const url = '/explore';
|
||||||
@ -116,6 +117,35 @@ describe('navigateToExplore', () => {
|
|||||||
|
|
||||||
describe('Explore reducer', () => {
|
describe('Explore reducer', () => {
|
||||||
describe('split view', () => {
|
describe('split view', () => {
|
||||||
|
describe('split open', () => {
|
||||||
|
it('it should create only ony new pane', async () => {
|
||||||
|
let dispatch: ThunkDispatch, getState: () => StoreState;
|
||||||
|
|
||||||
|
const store: { dispatch: ThunkDispatch; getState: () => StoreState } = configureStore({
|
||||||
|
explore: {
|
||||||
|
panes: {
|
||||||
|
one: { queries: [], range: {} },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as unknown as Partial<StoreState>);
|
||||||
|
|
||||||
|
dispatch = store.dispatch;
|
||||||
|
getState = store.getState;
|
||||||
|
|
||||||
|
await dispatch(splitOpen());
|
||||||
|
let splitPanes = Object.keys(getState().explore.panes);
|
||||||
|
expect(splitPanes).toHaveLength(2);
|
||||||
|
let secondSplitPaneId = splitPanes[1];
|
||||||
|
|
||||||
|
await dispatch(splitOpen());
|
||||||
|
splitPanes = Object.keys(getState().explore.panes);
|
||||||
|
// only 2 panes exist...
|
||||||
|
expect(splitPanes).toHaveLength(2);
|
||||||
|
// ...and the second pane is replaced
|
||||||
|
expect(splitPanes[0]).toBe('one');
|
||||||
|
expect(splitPanes[1]).not.toBe(secondSplitPaneId);
|
||||||
|
});
|
||||||
|
});
|
||||||
describe('split close', () => {
|
describe('split close', () => {
|
||||||
it('should reset right pane when it is closed', () => {
|
it('should reset right pane when it is closed', () => {
|
||||||
const leftItemMock = {
|
const leftItemMock = {
|
||||||
|
@ -14,7 +14,7 @@ import { CorrelationData } from '../../correlations/useCorrelations';
|
|||||||
import { TimeSrv } from '../../dashboard/services/TimeSrv';
|
import { TimeSrv } from '../../dashboard/services/TimeSrv';
|
||||||
import { withUniqueRefIds } from '../utils/queries';
|
import { withUniqueRefIds } from '../utils/queries';
|
||||||
|
|
||||||
import { initializeExplore, paneReducer } from './explorePane';
|
import { initializeExplore, InitializeExploreOptions, paneReducer } from './explorePane';
|
||||||
import { DEFAULT_RANGE, makeExplorePaneState } from './utils';
|
import { DEFAULT_RANGE, makeExplorePaneState } from './utils';
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -63,10 +63,7 @@ export const setPaneState = createAction<SetPaneStateActionPayload>('explore/set
|
|||||||
export const clearPanes = createAction('explore/clearPanes');
|
export const clearPanes = createAction('explore/clearPanes');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens a new split pane. It either copies existing state of an already present pane
|
* Ensure Explore doesn't exceed supported number of panes and initializes the new pane.
|
||||||
* or uses values from options arg.
|
|
||||||
*
|
|
||||||
* TODO: this can be improved by better inferring fallback values.
|
|
||||||
*/
|
*/
|
||||||
export const splitOpen = createAsyncThunk(
|
export const splitOpen = createAsyncThunk(
|
||||||
'explore/splitOpen',
|
'explore/splitOpen',
|
||||||
@ -76,8 +73,15 @@ export const splitOpen = createAsyncThunk(
|
|||||||
|
|
||||||
const queries = options?.queries ?? (options?.query ? [options?.query] : originState?.queries || []);
|
const queries = options?.queries ?? (options?.query ? [options?.query] : originState?.queries || []);
|
||||||
|
|
||||||
|
Object.keys(getState().explore.panes).forEach((paneId, index) => {
|
||||||
|
// Only 2 panes are supported. Remove panes before create a new one.
|
||||||
|
if (index >= 1) {
|
||||||
|
dispatch(splitClose(paneId));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
await dispatch(
|
await dispatch(
|
||||||
initializeExplore({
|
createNewSplitOpenPane({
|
||||||
exploreId: requestId,
|
exploreId: requestId,
|
||||||
datasource: options?.datasourceUid || originState?.datasourceInstance?.getRef(),
|
datasource: options?.datasourceUid || originState?.datasourceInstance?.getRef(),
|
||||||
queries: withUniqueRefIds(queries),
|
queries: withUniqueRefIds(queries),
|
||||||
@ -91,6 +95,19 @@ export const splitOpen = createAsyncThunk(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens a new split pane. It either copies existing state of an already present pane
|
||||||
|
* or uses values from options arg.
|
||||||
|
*
|
||||||
|
* TODO: this can be improved by better inferring fallback values.
|
||||||
|
*/
|
||||||
|
const createNewSplitOpenPane = createAsyncThunk(
|
||||||
|
'explore/createNewSplitOpen',
|
||||||
|
async (options: InitializeExploreOptions, { dispatch }) => {
|
||||||
|
await dispatch(initializeExplore(options));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
export interface NavigateToExploreDependencies {
|
export interface NavigateToExploreDependencies {
|
||||||
getDataSourceSrv: () => DataSourceSrv;
|
getDataSourceSrv: () => DataSourceSrv;
|
||||||
getTimeSrv: () => TimeSrv;
|
getTimeSrv: () => TimeSrv;
|
||||||
@ -215,12 +232,12 @@ export const exploreReducer = (state = initialExploreState, action: AnyAction):
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (splitOpen.pending.match(action)) {
|
if (createNewSplitOpenPane.pending.match(action)) {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
panes: {
|
panes: {
|
||||||
...state.panes,
|
...state.panes,
|
||||||
[action.meta.requestId]: initialExploreItemState,
|
[action.meta.arg.exploreId]: initialExploreItemState,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user