mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Chore: Convert Wrapper to function component (#56172)
* WIP * remove comment
This commit is contained in:
parent
cb99b94b01
commit
3381629d3d
@ -4416,8 +4416,7 @@ exports[`better eslint`] = {
|
||||
"public/app/features/explore/state/main.ts:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "1"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "2"],
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "3"]
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
|
||||
],
|
||||
"public/app/features/explore/state/query.test.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
|
||||
|
@ -26,7 +26,7 @@ import { getFiscalYearStartMonth, getTimeZone } from '../profile/state/selectors
|
||||
|
||||
import Explore from './Explore';
|
||||
import { initializeExplore, refreshExplore } from './state/explorePane';
|
||||
import { lastSavedUrl, cleanupPaneAction, stateSave } from './state/main';
|
||||
import { lastSavedUrl, stateSave } from './state/main';
|
||||
import { importQueries } from './state/query';
|
||||
import { loadAndInitDatasource } from './state/utils';
|
||||
|
||||
@ -178,7 +178,6 @@ function mapStateToProps(state: StoreState, props: OwnProps) {
|
||||
const mapDispatchToProps = {
|
||||
initializeExplore,
|
||||
refreshExplore,
|
||||
cleanupPaneAction,
|
||||
importQueries,
|
||||
stateSave,
|
||||
};
|
||||
|
@ -1,28 +1,23 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { useResizeObserver } from '@react-aria/utils';
|
||||
import { debounce, inRange } from 'lodash';
|
||||
import React, { PureComponent } from 'react';
|
||||
import { connect, ConnectedProps } from 'react-redux';
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
import { locationService } from '@grafana/runtime';
|
||||
import { ErrorBoundaryAlert } from '@grafana/ui';
|
||||
import { SplitView } from 'app/core/components/SplitPaneWrapper/SplitView';
|
||||
import { GrafanaContext } from 'app/core/context/GrafanaContext';
|
||||
import { useGrafana } from 'app/core/context/GrafanaContext';
|
||||
import { useNavModel } from 'app/core/hooks/useNavModel';
|
||||
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
|
||||
import { StoreState } from 'app/types';
|
||||
import { isTruthy } from 'app/core/utils/types';
|
||||
import { useSelector, useDispatch } from 'app/types';
|
||||
import { ExploreId, ExploreQueryParams } from 'app/types/explore';
|
||||
|
||||
import { Branding } from '../../core/components/Branding/Branding';
|
||||
import { getNavModel } from '../../core/selectors/navModel';
|
||||
|
||||
import { ExploreActions } from './ExploreActions';
|
||||
import { ExplorePaneContainer } from './ExplorePaneContainer';
|
||||
import {
|
||||
lastSavedUrl,
|
||||
resetExploreAction,
|
||||
richHistoryUpdatedAction,
|
||||
cleanupPaneAction,
|
||||
splitSizeUpdateAction,
|
||||
} from './state/main';
|
||||
import { lastSavedUrl, resetExploreAction, splitSizeUpdateAction } from './state/main';
|
||||
|
||||
const styles = {
|
||||
pageScrollbarWrapper: css`
|
||||
@ -36,64 +31,29 @@ const styles = {
|
||||
`,
|
||||
};
|
||||
|
||||
interface RouteProps extends GrafanaRouteComponentProps<{}, ExploreQueryParams> {}
|
||||
interface OwnProps {}
|
||||
const MIN_PANE_WIDTH = 200;
|
||||
function Wrapper(props: GrafanaRouteComponentProps<{}, ExploreQueryParams>) {
|
||||
useExplorePageTitle();
|
||||
const { maxedExploreId, evenSplitPanes } = useSelector((state) => state.explore);
|
||||
const [rightPaneWidth, setRightPaneWidth] = useState<number>();
|
||||
const [prevWindowWidth, setWindowWidth] = useState<number>();
|
||||
const dispatch = useDispatch();
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const queryParams = props.queryParams;
|
||||
const { keybindings, chrome } = useGrafana();
|
||||
const navModel = useNavModel('explore');
|
||||
|
||||
interface WrapperState {
|
||||
rightPaneWidth?: number;
|
||||
windowWidth?: number;
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: StoreState) => {
|
||||
return {
|
||||
navModel: getNavModel(state.navIndex, 'explore'),
|
||||
exploreState: state.explore,
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = {
|
||||
resetExploreAction,
|
||||
richHistoryUpdatedAction,
|
||||
cleanupPaneAction,
|
||||
splitSizeUpdateAction,
|
||||
};
|
||||
|
||||
const connector = connect(mapStateToProps, mapDispatchToProps);
|
||||
|
||||
type Props = OwnProps & RouteProps & ConnectedProps<typeof connector>;
|
||||
class WrapperUnconnected extends PureComponent<Props, WrapperState> {
|
||||
minWidth = 200;
|
||||
static contextType = GrafanaContext;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
rightPaneWidth: undefined,
|
||||
windowWidth: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const { left, right } = this.props.queryParams;
|
||||
this.props.resetExploreAction({});
|
||||
|
||||
if (Boolean(left)) {
|
||||
this.props.cleanupPaneAction({ exploreId: ExploreId.left });
|
||||
}
|
||||
|
||||
if (Boolean(right)) {
|
||||
this.props.cleanupPaneAction({ exploreId: ExploreId.right });
|
||||
}
|
||||
|
||||
window.removeEventListener('resize', this.windowResizeListener);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
useEffect(() => {
|
||||
//This is needed for breadcrumbs and topnav.
|
||||
//We should probably abstract this out at some point
|
||||
this.context.chrome.update({ sectionNav: this.props.navModel.node });
|
||||
this.context.keybindings.setupTimeRangeBindings(false);
|
||||
chrome.update({ sectionNav: navModel.node });
|
||||
}, [chrome, navModel]);
|
||||
|
||||
useEffect(() => {
|
||||
keybindings.setupTimeRangeBindings(false);
|
||||
}, [keybindings]);
|
||||
|
||||
useEffect(() => {
|
||||
lastSavedUrl.left = undefined;
|
||||
lastSavedUrl.right = undefined;
|
||||
|
||||
@ -111,90 +71,101 @@ class WrapperUnconnected extends PureComponent<Props, WrapperState> {
|
||||
locationService.partial({ from: undefined, to: undefined }, true);
|
||||
}
|
||||
|
||||
window.addEventListener('resize', this.windowResizeListener);
|
||||
}
|
||||
return () => {
|
||||
// Cleaning up Explore state so that when navigating back to Explore it starts from a blank state
|
||||
dispatch(resetExploreAction());
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps -- dispatch is stable, doesn't need to be in the deps array
|
||||
}, []);
|
||||
|
||||
componentDidUpdate() {
|
||||
const { left, right } = this.props.queryParams;
|
||||
const hasSplit = Boolean(left) && Boolean(right);
|
||||
const datasourceTitle = hasSplit
|
||||
? `${this.props.exploreState.left.datasourceInstance?.name} | ${this.props.exploreState.right?.datasourceInstance?.name}`
|
||||
: `${this.props.exploreState.left.datasourceInstance?.name}`;
|
||||
const documentTitle = `${this.props.navModel.main.text} - ${datasourceTitle} - ${Branding.AppTitle}`;
|
||||
document.title = documentTitle;
|
||||
}
|
||||
|
||||
windowResizeListener = debounce(() => {
|
||||
const debouncedFunctionRef = useRef((prevWindowWidth?: number, rightPaneWidth?: number) => {
|
||||
let rightPaneRatio = 0.5;
|
||||
const windowWidth = window.innerWidth;
|
||||
if (!containerRef.current) {
|
||||
return;
|
||||
}
|
||||
const windowWidth = containerRef.current.clientWidth;
|
||||
// get the ratio of the previous rightPane to the window width
|
||||
if (this.state.rightPaneWidth && this.state.windowWidth) {
|
||||
rightPaneRatio = this.state.rightPaneWidth / this.state.windowWidth;
|
||||
if (rightPaneWidth && prevWindowWidth) {
|
||||
rightPaneRatio = rightPaneWidth / prevWindowWidth;
|
||||
}
|
||||
let newRightPaneWidth = Math.floor(windowWidth * rightPaneRatio);
|
||||
if (newRightPaneWidth < this.minWidth) {
|
||||
if (newRightPaneWidth < MIN_PANE_WIDTH) {
|
||||
// if right pane is too narrow, make min width
|
||||
newRightPaneWidth = this.minWidth;
|
||||
} else if (windowWidth - newRightPaneWidth < this.minWidth) {
|
||||
newRightPaneWidth = MIN_PANE_WIDTH;
|
||||
} else if (windowWidth - newRightPaneWidth < MIN_PANE_WIDTH) {
|
||||
// if left pane is too narrow, make right pane = window - minWidth
|
||||
newRightPaneWidth = windowWidth - this.minWidth;
|
||||
newRightPaneWidth = windowWidth - MIN_PANE_WIDTH;
|
||||
}
|
||||
|
||||
this.setState({ windowWidth, rightPaneWidth: newRightPaneWidth });
|
||||
}, 500);
|
||||
setRightPaneWidth(newRightPaneWidth);
|
||||
setWindowWidth(windowWidth);
|
||||
});
|
||||
|
||||
updateSplitSize = (rightPaneWidth: number) => {
|
||||
// eslint needs the callback to be inline to analyze the dependencies, but we need to use debounce from lodash
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
const onResize = useCallback(
|
||||
debounce(() => debouncedFunctionRef.current(prevWindowWidth, rightPaneWidth), 500),
|
||||
[prevWindowWidth, rightPaneWidth]
|
||||
);
|
||||
|
||||
const updateSplitSize = (rightPaneWidth: number) => {
|
||||
const evenSplitWidth = window.innerWidth / 2;
|
||||
const areBothSimilar = inRange(rightPaneWidth, evenSplitWidth - 100, evenSplitWidth + 100);
|
||||
if (areBothSimilar) {
|
||||
this.props.splitSizeUpdateAction({ largerExploreId: undefined });
|
||||
dispatch(splitSizeUpdateAction({ largerExploreId: undefined }));
|
||||
} else {
|
||||
this.props.splitSizeUpdateAction({
|
||||
largerExploreId: rightPaneWidth > evenSplitWidth ? ExploreId.right : ExploreId.left,
|
||||
});
|
||||
dispatch(
|
||||
splitSizeUpdateAction({
|
||||
largerExploreId: rightPaneWidth > evenSplitWidth ? ExploreId.right : ExploreId.left,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
this.setState({ ...this.state, rightPaneWidth });
|
||||
setRightPaneWidth(rightPaneWidth);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { left, right } = this.props.queryParams;
|
||||
const { maxedExploreId, evenSplitPanes } = this.props.exploreState;
|
||||
const hasSplit = Boolean(left) && Boolean(right);
|
||||
let widthCalc = 0;
|
||||
useResizeObserver({ onResize, ref: containerRef });
|
||||
const hasSplit = Boolean(queryParams.left) && Boolean(queryParams.right);
|
||||
let widthCalc = 0;
|
||||
|
||||
if (hasSplit) {
|
||||
if (!evenSplitPanes && maxedExploreId) {
|
||||
widthCalc = maxedExploreId === ExploreId.right ? window.innerWidth - this.minWidth : this.minWidth;
|
||||
} else if (evenSplitPanes) {
|
||||
widthCalc = Math.floor(window.innerWidth / 2);
|
||||
} else if (this.state.rightPaneWidth !== undefined) {
|
||||
widthCalc = this.state.rightPaneWidth;
|
||||
}
|
||||
if (hasSplit) {
|
||||
if (!evenSplitPanes && maxedExploreId) {
|
||||
widthCalc = maxedExploreId === ExploreId.right ? window.innerWidth - MIN_PANE_WIDTH : MIN_PANE_WIDTH;
|
||||
} else if (evenSplitPanes) {
|
||||
widthCalc = Math.floor(window.innerWidth / 2);
|
||||
} else if (rightPaneWidth !== undefined) {
|
||||
widthCalc = rightPaneWidth;
|
||||
}
|
||||
|
||||
const splitSizeObj = { rightPaneSize: widthCalc };
|
||||
|
||||
return (
|
||||
<div className={styles.pageScrollbarWrapper}>
|
||||
<ExploreActions exploreIdLeft={ExploreId.left} exploreIdRight={ExploreId.right} />
|
||||
<div className={styles.exploreWrapper}>
|
||||
<SplitView uiState={splitSizeObj} minSize={this.minWidth} onResize={this.updateSplitSize}>
|
||||
<ErrorBoundaryAlert style="page" key="LeftPane">
|
||||
<ExplorePaneContainer split={hasSplit} exploreId={ExploreId.left} urlQuery={left} />
|
||||
</ErrorBoundaryAlert>
|
||||
{hasSplit && (
|
||||
<ErrorBoundaryAlert style="page" key="RightPane">
|
||||
<ExplorePaneContainer split={hasSplit} exploreId={ExploreId.right} urlQuery={right} />
|
||||
</ErrorBoundaryAlert>
|
||||
)}
|
||||
</SplitView>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const splitSizeObj = { rightPaneSize: widthCalc };
|
||||
return (
|
||||
<div className={styles.pageScrollbarWrapper} ref={containerRef}>
|
||||
<ExploreActions exploreIdLeft={ExploreId.left} exploreIdRight={ExploreId.right} />
|
||||
<div className={styles.exploreWrapper}>
|
||||
<SplitView uiState={splitSizeObj} minSize={MIN_PANE_WIDTH} onResize={updateSplitSize}>
|
||||
<ErrorBoundaryAlert style="page" key="LeftPane">
|
||||
<ExplorePaneContainer split={hasSplit} exploreId={ExploreId.left} urlQuery={queryParams.left} />
|
||||
</ErrorBoundaryAlert>
|
||||
{hasSplit && (
|
||||
<ErrorBoundaryAlert style="page" key="RightPane">
|
||||
<ExplorePaneContainer split={hasSplit} exploreId={ExploreId.right} urlQuery={queryParams.right} />
|
||||
</ErrorBoundaryAlert>
|
||||
)}
|
||||
</SplitView>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const Wrapper = connector(WrapperUnconnected);
|
||||
const useExplorePageTitle = () => {
|
||||
const navModel = useNavModel('explore');
|
||||
const datasources = useSelector((state) =>
|
||||
[state.explore.left.datasourceInstance?.name, state.explore.right?.datasourceInstance?.name].filter(isTruthy)
|
||||
);
|
||||
|
||||
const documentTitle = `${navModel.main.text} - ${datasources.join(' | ')} - ${Branding.AppTitle}`;
|
||||
document.title = documentTitle;
|
||||
};
|
||||
|
||||
export default Wrapper;
|
||||
|
@ -192,8 +192,8 @@ export function initializeExplore(
|
||||
*/
|
||||
export function refreshExplore(exploreId: ExploreId, newUrlQuery: string): ThunkResult<void> {
|
||||
return async (dispatch, getState) => {
|
||||
const itemState = getState().explore[exploreId]!;
|
||||
if (!itemState.initialized) {
|
||||
const itemState = getState().explore[exploreId];
|
||||
if (!itemState?.initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -50,10 +50,7 @@ export const evenPaneResizeAction = createAction('explore/evenPaneResizeAction')
|
||||
/**
|
||||
* Resets state for explore.
|
||||
*/
|
||||
export interface ResetExplorePayload {
|
||||
force?: boolean;
|
||||
}
|
||||
export const resetExploreAction = createAction<ResetExplorePayload>('explore/resetExplore');
|
||||
export const resetExploreAction = createAction('explore/resetExplore');
|
||||
|
||||
/**
|
||||
* Close the split view and save URL state.
|
||||
@ -63,17 +60,6 @@ export interface SplitCloseActionPayload {
|
||||
}
|
||||
export const splitCloseAction = createAction<SplitCloseActionPayload>('explore/splitClose');
|
||||
|
||||
/**
|
||||
* Cleans up a pane state. Could seem like this should be in explorePane.ts actions but in case we area closing
|
||||
* left pane we need to move right state to the left.
|
||||
* Also this may seem redundant as we have splitClose actions which clears up state but that action is not called on
|
||||
* URL change.
|
||||
*/
|
||||
export interface CleanupPanePayload {
|
||||
exploreId: ExploreId;
|
||||
}
|
||||
export const cleanupPaneAction = createAction<CleanupPanePayload>('explore/cleanupPane');
|
||||
|
||||
//
|
||||
// Action creators
|
||||
//
|
||||
@ -237,30 +223,6 @@ export const exploreReducer = (state = initialExploreState, action: AnyAction):
|
||||
};
|
||||
}
|
||||
|
||||
if (cleanupPaneAction.match(action)) {
|
||||
const { exploreId } = action.payload as CleanupPanePayload;
|
||||
|
||||
// We want to do this only when we remove single pane not when we are unmounting whole explore.
|
||||
// It needs to be checked like this because in component we don't get new path (which would tell us if we are
|
||||
// navigating out of explore) before the unmount.
|
||||
if (!state[exploreId]?.initialized) {
|
||||
return state;
|
||||
}
|
||||
|
||||
if (exploreId === ExploreId.left) {
|
||||
return {
|
||||
...state,
|
||||
[ExploreId.left]: state[ExploreId.right]!,
|
||||
[ExploreId.right]: undefined,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...state,
|
||||
[ExploreId.right]: undefined,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (syncTimesAction.match(action)) {
|
||||
return { ...state, syncedTimes: action.payload.syncedTimes };
|
||||
}
|
||||
@ -287,7 +249,6 @@ export const exploreReducer = (state = initialExploreState, action: AnyAction):
|
||||
}
|
||||
|
||||
if (resetExploreAction.match(action)) {
|
||||
const payload: ResetExplorePayload = action.payload;
|
||||
const leftState = state[ExploreId.left];
|
||||
const rightState = state[ExploreId.right];
|
||||
stopQueryState(leftState.querySubscription);
|
||||
@ -295,10 +256,6 @@ export const exploreReducer = (state = initialExploreState, action: AnyAction):
|
||||
stopQueryState(rightState.querySubscription);
|
||||
}
|
||||
|
||||
if (payload.force) {
|
||||
return initialExploreState;
|
||||
}
|
||||
|
||||
return {
|
||||
...initialExploreState,
|
||||
left: {
|
||||
|
Loading…
Reference in New Issue
Block a user