Commit a8c50ed6 by Dominik Prokop Committed by GitHub

feat(explore): make it possible to close left pane of split view (#16155)

* feat(explore): make it possible to close left pane of split view

* Use action's type prop instead of enum
parent c2e9daad
......@@ -108,11 +108,9 @@ export class UnConnectedExploreToolbar extends PureComponent<Props, {}> {
</span>
)}
</div>
{exploreId === 'right' && (
<a className="explore-toolbar-header-close" onClick={this.props.closeSplit}>
<i className="fa fa-times fa-fw" />
</a>
)}
<a className="explore-toolbar-header-close" onClick={() => this.props.closeSplit(exploreId)}>
<i className="fa fa-times fa-fw" />
</a>
</div>
</div>
<div className="explore-toolbar-item">
......
......@@ -24,16 +24,9 @@ import { LogLevel } from 'app/core/logs_model';
*
*/
export enum ActionTypes {
SplitClose = 'explore/SPLIT_CLOSE',
SplitOpen = 'explore/SPLIT_OPEN',
ResetExplore = 'explore/RESET_EXPLORE',
}
export interface SplitCloseAction {
type: ActionTypes.SplitClose;
payload: {};
}
export interface SplitOpenAction {
type: ActionTypes.SplitOpen;
payload: {
......@@ -167,6 +160,10 @@ export interface SetQueriesPayload {
queries: DataQuery[];
}
export interface SplitCloseActionPayload {
itemId: ExploreId;
}
export interface SplitOpenPayload {
itemState: ExploreItemState;
}
......@@ -350,7 +347,7 @@ export const setQueriesAction = actionCreatorFactory<SetQueriesPayload>('explore
/**
* Close the split view and save URL state.
*/
export const splitCloseAction = noPayloadActionCreatorFactory('explore/SPLIT_CLOSE').create();
export const splitCloseAction = actionCreatorFactory<SplitCloseActionPayload>('explore/SPLIT_CLOSE').create();
/**
* Open the split view and copy the left state to be the right state.
......@@ -395,7 +392,11 @@ export const toggleLogLevelAction = actionCreatorFactory<ToggleLogLevelPayload>(
export const resetExploreAction = noPayloadActionCreatorFactory('explore/RESET_EXPLORE').create();
export const queriesImportedAction = actionCreatorFactory<QueriesImportedPayload>('explore/QueriesImported').create();
export type HigherOrderAction = SplitCloseAction | SplitOpenAction | ResetExploreAction | ActionOf<any>;
export type HigherOrderAction =
| ActionOf<SplitCloseActionPayload>
| SplitOpenAction
| ResetExploreAction
| ActionOf<any>;
export type Action =
| ActionOf<AddQueryRowPayload>
......
// Libraries
import _ from 'lodash';
import { ThunkAction } from 'redux-thunk';
// Services & Utils
import store from 'app/core/store';
......@@ -23,7 +22,6 @@ import {
import { updateLocation } from 'app/core/actions';
// Types
import { StoreState } from 'app/types';
import {
RawTimeRange,
TimeRange,
......@@ -35,7 +33,6 @@ import {
} from '@grafana/ui/src/types';
import { ExploreId, ExploreUrlState, RangeScanner, ResultType, QueryOptions, ExploreUIState } from 'app/types/explore';
import {
Action,
updateDatasourceInstanceAction,
changeQueryAction,
changeSizeAction,
......@@ -71,10 +68,9 @@ import {
} from './actionTypes';
import { ActionOf, ActionCreator } from 'app/core/redux/actionCreatorFactory';
import { LogsDedupStrategy } from 'app/core/logs_model';
import { ThunkResult } from 'app/types';
import { parseTime } from '../TimePicker';
type ThunkResult<R> = ThunkAction<R, StoreState, undefined, Action>;
/**
* Updates UI state and save it to the URL
*/
......@@ -645,9 +641,9 @@ export function setQueries(exploreId: ExploreId, rawQueries: DataQuery[]): Thunk
/**
* Close the split view and save URL state.
*/
export function splitClose(): ThunkResult<void> {
export function splitClose(itemId: ExploreId): ThunkResult<void> {
return dispatch => {
dispatch(splitCloseAction());
dispatch(splitCloseAction({ itemId }));
dispatch(stateSave());
};
}
......
import { itemReducer, makeExploreItemState, exploreReducer, makeInitialUpdateState } from './reducers';
import { ExploreId, ExploreItemState, ExploreUrlState } from 'app/types/explore';
import {
itemReducer,
makeExploreItemState,
exploreReducer,
makeInitialUpdateState,
initialExploreState,
} from './reducers';
import { ExploreId, ExploreItemState, ExploreUrlState, ExploreState } from 'app/types/explore';
import { reducerTester } from 'test/core/redux/reducerTester';
import { scanStartAction, scanStopAction } from './actionTypes';
import { scanStartAction, scanStopAction, splitOpenAction, splitCloseAction } from './actionTypes';
import { Reducer } from 'redux';
import { ActionOf } from 'app/core/redux/actionCreatorFactory';
import { updateLocation } from 'app/core/actions/location';
......@@ -76,6 +82,82 @@ export const setup = (urlStateOverrides?: any) => {
};
describe('Explore reducer', () => {
describe('split view', () => {
it("should make right pane a duplicate of the given item's state on split open", () => {
const leftItemMock = {
containerWidth: 100,
} as ExploreItemState;
const initalState = {
split: null,
left: leftItemMock as ExploreItemState,
right: makeExploreItemState(),
} as ExploreState;
reducerTester()
.givenReducer(exploreReducer as Reducer<ExploreState, ActionOf<any>>, initalState)
.whenActionIsDispatched(splitOpenAction({ itemState: leftItemMock }))
.thenStateShouldEqual({
split: true,
left: leftItemMock,
right: leftItemMock,
});
});
describe('split close', () => {
it('should keep right pane as left when left is closed', () => {
const leftItemMock = {
containerWidth: 100,
} as ExploreItemState;
const rightItemMock = {
containerWidth: 200,
} as ExploreItemState;
const initalState = {
split: null,
left: leftItemMock,
right: rightItemMock,
} as ExploreState;
// closing left item
reducerTester()
.givenReducer(exploreReducer as Reducer<ExploreState, ActionOf<any>>, initalState)
.whenActionIsDispatched(splitCloseAction({ itemId: ExploreId.left }))
.thenStateShouldEqual({
split: false,
left: rightItemMock,
right: initialExploreState.right,
});
});
it('should reset right pane when it is closed ', () => {
const leftItemMock = {
containerWidth: 100,
} as ExploreItemState;
const rightItemMock = {
containerWidth: 200,
} as ExploreItemState;
const initalState = {
split: null,
left: leftItemMock,
right: rightItemMock,
} as ExploreState;
// closing left item
reducerTester()
.givenReducer(exploreReducer as Reducer<ExploreState, ActionOf<any>>, initalState)
.whenActionIsDispatched(splitCloseAction({ itemId: ExploreId.right }))
.thenStateShouldEqual({
split: false,
left: leftItemMock,
right: initialExploreState.right,
});
});
});
});
describe('when updateLocation is dispatched', () => {
describe('and payload does not contain a query', () => {
it('then it should just return state', () => {
......
......@@ -12,7 +12,7 @@ import {
import { ExploreItemState, ExploreState, QueryTransaction, ExploreId, ExploreUpdateState } from 'app/types/explore';
import { DataQuery } from '@grafana/ui/src/types';
import { HigherOrderAction, ActionTypes } from './actionTypes';
import { HigherOrderAction, ActionTypes, SplitCloseActionPayload, splitCloseAction } from './actionTypes';
import { reducerFactory } from 'app/core/redux';
import {
addQueryRowAction,
......@@ -560,8 +560,17 @@ export const updateChildRefreshState = (
*/
export const exploreReducer = (state = initialExploreState, action: HigherOrderAction): ExploreState => {
switch (action.type) {
case ActionTypes.SplitClose: {
return { ...state, split: false };
case splitCloseAction.type: {
const { itemId } = action.payload as SplitCloseActionPayload;
const targetSplit = {
left: itemId === ExploreId.left ? state.right : state.left,
right: initialExploreState.right,
};
return {
...state,
...targetSplit,
split: false,
};
}
case ActionTypes.SplitOpen: {
......
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