mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Discover] Persist histogram height to local storage (#140997)
* [Discover] Initial work to persist histogram height * [Discover] Fix issues with persisting histogram height * [Discover] Add tests for histogram height persistence * [Discover] Show reset chart height button only when the layout is resizable * [Discover] Update reset chart height button to read 'Reset to default height'
This commit is contained in:
parent
4c0c0db9c5
commit
0aa74edd2e
10 changed files with 290 additions and 81 deletions
|
@ -114,6 +114,7 @@ async function mountComponent(isTimeBased: boolean = false) {
|
|||
viewMode: VIEW_MODE.DOCUMENT_LEVEL,
|
||||
setDiscoverViewMode: jest.fn(),
|
||||
isTimeBased,
|
||||
onResetChartHeight: jest.fn(),
|
||||
};
|
||||
|
||||
let instance: ReactWrapper = {} as ReactWrapper;
|
||||
|
|
|
@ -44,6 +44,7 @@ export function DiscoverChart({
|
|||
interval,
|
||||
isTimeBased,
|
||||
appendHistogram,
|
||||
onResetChartHeight,
|
||||
}: {
|
||||
className?: string;
|
||||
resetSavedSearch: () => void;
|
||||
|
@ -56,6 +57,7 @@ export function DiscoverChart({
|
|||
hideChart?: boolean;
|
||||
interval?: string;
|
||||
appendHistogram?: ReactElement;
|
||||
onResetChartHeight?: () => void;
|
||||
}) {
|
||||
const { data, storage } = useDiscoverServices();
|
||||
const [showChartOptionsPopover, setShowChartOptionsPopover] = useState(false);
|
||||
|
@ -113,13 +115,14 @@ export function DiscoverChart({
|
|||
},
|
||||
[data]
|
||||
);
|
||||
const panels = useChartPanels(
|
||||
const panels = useChartPanels({
|
||||
toggleHideChart,
|
||||
(newInterval) => stateContainer.setAppState({ interval: newInterval }),
|
||||
() => setShowChartOptionsPopover(false),
|
||||
onChangeInterval: (newInterval) => stateContainer.setAppState({ interval: newInterval }),
|
||||
closePopover: () => setShowChartOptionsPopover(false),
|
||||
onResetChartHeight,
|
||||
hideChart,
|
||||
interval
|
||||
);
|
||||
interval,
|
||||
});
|
||||
|
||||
return (
|
||||
<EuiFlexGroup
|
||||
|
|
|
@ -14,20 +14,68 @@ import { EuiContextMenuPanelDescriptor } from '@elastic/eui';
|
|||
describe('test useChartPanels', () => {
|
||||
test('useChartsPanel when hideChart is true', async () => {
|
||||
const { result } = renderHook(() => {
|
||||
return useChartPanels(jest.fn(), jest.fn(), jest.fn(), true, 'auto');
|
||||
return useChartPanels({
|
||||
toggleHideChart: jest.fn(),
|
||||
onChangeInterval: jest.fn(),
|
||||
closePopover: jest.fn(),
|
||||
onResetChartHeight: jest.fn(),
|
||||
hideChart: true,
|
||||
interval: 'auto',
|
||||
});
|
||||
});
|
||||
const panels: EuiContextMenuPanelDescriptor[] = result.current;
|
||||
const panel0: EuiContextMenuPanelDescriptor = result.current[0];
|
||||
expect(panels.length).toBe(1);
|
||||
expect(panel0!.items).toHaveLength(1);
|
||||
expect(panel0!.items![0].icon).toBe('eye');
|
||||
});
|
||||
test('useChartsPanel when hideChart is false', async () => {
|
||||
const { result } = renderHook(() => {
|
||||
return useChartPanels(jest.fn(), jest.fn(), jest.fn(), false, 'auto');
|
||||
return useChartPanels({
|
||||
toggleHideChart: jest.fn(),
|
||||
onChangeInterval: jest.fn(),
|
||||
closePopover: jest.fn(),
|
||||
onResetChartHeight: jest.fn(),
|
||||
hideChart: false,
|
||||
interval: 'auto',
|
||||
});
|
||||
});
|
||||
const panels: EuiContextMenuPanelDescriptor[] = result.current;
|
||||
const panel0: EuiContextMenuPanelDescriptor = result.current[0];
|
||||
expect(panels.length).toBe(2);
|
||||
expect(panel0!.items).toHaveLength(3);
|
||||
expect(panel0!.items![0].icon).toBe('eyeClosed');
|
||||
expect(panel0!.items![1].icon).toBe('refresh');
|
||||
});
|
||||
test('should not show reset chart height when onResetChartHeight is undefined', async () => {
|
||||
const { result } = renderHook(() => {
|
||||
return useChartPanels({
|
||||
toggleHideChart: jest.fn(),
|
||||
onChangeInterval: jest.fn(),
|
||||
closePopover: jest.fn(),
|
||||
hideChart: false,
|
||||
interval: 'auto',
|
||||
});
|
||||
});
|
||||
const panel0: EuiContextMenuPanelDescriptor = result.current[0];
|
||||
expect(panel0!.items).toHaveLength(2);
|
||||
expect(panel0!.items![0].icon).toBe('eyeClosed');
|
||||
});
|
||||
test('onResetChartHeight is called when the reset chart height button is clicked', async () => {
|
||||
const onResetChartHeight = jest.fn();
|
||||
const { result } = renderHook(() => {
|
||||
return useChartPanels({
|
||||
toggleHideChart: jest.fn(),
|
||||
onChangeInterval: jest.fn(),
|
||||
closePopover: jest.fn(),
|
||||
onResetChartHeight,
|
||||
hideChart: false,
|
||||
interval: 'auto',
|
||||
});
|
||||
});
|
||||
const panel0: EuiContextMenuPanelDescriptor = result.current[0];
|
||||
const resetChartHeightButton = panel0!.items![1];
|
||||
(resetChartHeightButton.onClick as Function)();
|
||||
expect(onResetChartHeight).toBeCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -12,13 +12,21 @@ import type {
|
|||
} from '@elastic/eui';
|
||||
import { search } from '@kbn/data-plugin/public';
|
||||
|
||||
export function useChartPanels(
|
||||
toggleHideChart: () => void,
|
||||
onChangeInterval: (value: string) => void,
|
||||
closePopover: () => void,
|
||||
hideChart?: boolean,
|
||||
interval?: string
|
||||
) {
|
||||
export function useChartPanels({
|
||||
toggleHideChart,
|
||||
onChangeInterval,
|
||||
closePopover,
|
||||
onResetChartHeight,
|
||||
hideChart,
|
||||
interval,
|
||||
}: {
|
||||
toggleHideChart: () => void;
|
||||
onChangeInterval: (value: string) => void;
|
||||
closePopover: () => void;
|
||||
onResetChartHeight?: () => void;
|
||||
hideChart?: boolean;
|
||||
interval?: string;
|
||||
}) {
|
||||
const selectedOptionIdx = search.aggs.intervalOptions.findIndex((opt) => opt.val === interval);
|
||||
const intervalDisplay =
|
||||
selectedOptionIdx > -1
|
||||
|
@ -43,6 +51,20 @@ export function useChartPanels(
|
|||
},
|
||||
];
|
||||
if (!hideChart) {
|
||||
if (onResetChartHeight) {
|
||||
mainPanelItems.push({
|
||||
name: i18n.translate('discover.resetChartHeight', {
|
||||
defaultMessage: 'Reset to default height',
|
||||
}),
|
||||
icon: 'refresh',
|
||||
onClick: () => {
|
||||
onResetChartHeight();
|
||||
closePopover();
|
||||
},
|
||||
'data-test-subj': 'discoverChartResetHeight',
|
||||
});
|
||||
}
|
||||
|
||||
mainPanelItems.push({
|
||||
name: i18n.translate('discover.timeIntervalWithValue', {
|
||||
defaultMessage: 'Time interval: {timeInterval}',
|
||||
|
|
|
@ -26,7 +26,11 @@ import { FetchStatus } from '../../../types';
|
|||
import { Chart } from '../chart/point_series';
|
||||
import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { buildDataTableRecord } from '../../../../utils/build_data_record';
|
||||
import { DiscoverMainContent, DiscoverMainContentProps } from './discover_main_content';
|
||||
import {
|
||||
DiscoverMainContent,
|
||||
DiscoverMainContentProps,
|
||||
HISTOGRAM_HEIGHT_KEY,
|
||||
} from './discover_main_content';
|
||||
import { VIEW_MODE } from '@kbn/saved-search-plugin/public';
|
||||
import { DiscoverPanels, DISCOVER_PANELS_MODE } from './discover_panels';
|
||||
import { euiThemeVars } from '@kbn/ui-theme';
|
||||
|
@ -36,21 +40,29 @@ import { setTimeout } from 'timers/promises';
|
|||
import { DiscoverChart } from '../chart';
|
||||
import { ReactWrapper } from 'enzyme';
|
||||
import { DocumentViewModeToggle } from '../../../../components/view_mode_toggle';
|
||||
import { Storage } from '@kbn/kibana-utils-plugin/public';
|
||||
import { LocalStorageMock } from '../../../../__mocks__/local_storage_mock';
|
||||
|
||||
const mountComponent = async ({
|
||||
isPlainRecord = false,
|
||||
hideChart = false,
|
||||
isTimeBased = true,
|
||||
storage,
|
||||
}: {
|
||||
isPlainRecord?: boolean;
|
||||
hideChart?: boolean;
|
||||
isTimeBased?: boolean;
|
||||
storage?: Storage;
|
||||
} = {}) => {
|
||||
const services = discoverServiceMock;
|
||||
let services = discoverServiceMock;
|
||||
services.data.query.timefilter.timefilter.getAbsoluteTime = () => {
|
||||
return { from: '2020-05-14T11:05:13.590', to: '2020-05-14T11:20:13.590' };
|
||||
};
|
||||
|
||||
if (storage) {
|
||||
services = { ...services, storage };
|
||||
}
|
||||
|
||||
const main$ = new BehaviorSubject({
|
||||
fetchStatus: FetchStatus.COMPLETE,
|
||||
recordRawType: isPlainRecord ? RecordRawType.PLAIN : RecordRawType.DOCUMENT,
|
||||
|
@ -188,67 +200,145 @@ describe('Discover main content component', () => {
|
|||
window.innerWidth = windowWidth;
|
||||
});
|
||||
|
||||
it('should set the panels mode to DISCOVER_PANELS_MODE.RESIZABLE when viewing on medium screens and above', async () => {
|
||||
const component = await mountComponent();
|
||||
setWindowWidth(component, euiThemeVars.euiBreakpoints.m);
|
||||
expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.RESIZABLE);
|
||||
});
|
||||
describe('DISCOVER_PANELS_MODE', () => {
|
||||
it('should set the panels mode to DISCOVER_PANELS_MODE.RESIZABLE when viewing on medium screens and above', async () => {
|
||||
const component = await mountComponent();
|
||||
setWindowWidth(component, euiThemeVars.euiBreakpoints.m);
|
||||
expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.RESIZABLE);
|
||||
});
|
||||
|
||||
it('should set the panels mode to DISCOVER_PANELS_MODE.FIXED when viewing on small screens and below', async () => {
|
||||
const component = await mountComponent();
|
||||
setWindowWidth(component, euiThemeVars.euiBreakpoints.s);
|
||||
expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.FIXED);
|
||||
});
|
||||
it('should set the panels mode to DISCOVER_PANELS_MODE.FIXED when viewing on small screens and below', async () => {
|
||||
const component = await mountComponent();
|
||||
setWindowWidth(component, euiThemeVars.euiBreakpoints.s);
|
||||
expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.FIXED);
|
||||
});
|
||||
|
||||
it('should set the panels mode to DISCOVER_PANELS_MODE.FIXED if hideChart is true', async () => {
|
||||
const component = await mountComponent({ hideChart: true });
|
||||
expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.FIXED);
|
||||
});
|
||||
it('should set the panels mode to DISCOVER_PANELS_MODE.FIXED if hideChart is true', async () => {
|
||||
const component = await mountComponent({ hideChart: true });
|
||||
expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.FIXED);
|
||||
});
|
||||
|
||||
it('should set the panels mode to DISCOVER_PANELS_MODE.FIXED if isTimeBased is false', async () => {
|
||||
const component = await mountComponent({ isTimeBased: false });
|
||||
expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.FIXED);
|
||||
});
|
||||
it('should set the panels mode to DISCOVER_PANELS_MODE.FIXED if isTimeBased is false', async () => {
|
||||
const component = await mountComponent({ isTimeBased: false });
|
||||
expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.FIXED);
|
||||
});
|
||||
|
||||
it('should set the panels mode to DISCOVER_PANELS_MODE.SINGLE if isPlainRecord is true', async () => {
|
||||
const component = await mountComponent({ isPlainRecord: true });
|
||||
expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.SINGLE);
|
||||
});
|
||||
it('should set the panels mode to DISCOVER_PANELS_MODE.SINGLE if isPlainRecord is true', async () => {
|
||||
const component = await mountComponent({ isPlainRecord: true });
|
||||
expect(component.find(DiscoverPanels).prop('mode')).toBe(DISCOVER_PANELS_MODE.SINGLE);
|
||||
});
|
||||
|
||||
it('should set a fixed height for DiscoverChart when panels mode is DISCOVER_PANELS_MODE.FIXED and hideChart is false', async () => {
|
||||
const component = await mountComponent();
|
||||
setWindowWidth(component, euiThemeVars.euiBreakpoints.s);
|
||||
const expectedHeight = component.find(DiscoverPanels).prop('initialTopPanelHeight');
|
||||
expect(component.find(DiscoverChart).childAt(0).getDOMNode()).toHaveStyle({
|
||||
height: `${expectedHeight}px`,
|
||||
it('should set a fixed height for DiscoverChart when panels mode is DISCOVER_PANELS_MODE.FIXED and hideChart is false', async () => {
|
||||
const component = await mountComponent();
|
||||
setWindowWidth(component, euiThemeVars.euiBreakpoints.s);
|
||||
const expectedHeight = component.find(DiscoverPanels).prop('topPanelHeight');
|
||||
expect(component.find(DiscoverChart).childAt(0).getDOMNode()).toHaveStyle({
|
||||
height: `${expectedHeight}px`,
|
||||
});
|
||||
});
|
||||
|
||||
it('should not set a fixed height for DiscoverChart when panels mode is DISCOVER_PANELS_MODE.FIXED and hideChart is true', async () => {
|
||||
const component = await mountComponent({ hideChart: true });
|
||||
setWindowWidth(component, euiThemeVars.euiBreakpoints.s);
|
||||
const expectedHeight = component.find(DiscoverPanels).prop('topPanelHeight');
|
||||
expect(component.find(DiscoverChart).childAt(0).getDOMNode()).not.toHaveStyle({
|
||||
height: `${expectedHeight}px`,
|
||||
});
|
||||
});
|
||||
|
||||
it('should not set a fixed height for DiscoverChart when panels mode is DISCOVER_PANELS_MODE.FIXED and isTimeBased is false', async () => {
|
||||
const component = await mountComponent({ isTimeBased: false });
|
||||
setWindowWidth(component, euiThemeVars.euiBreakpoints.s);
|
||||
const expectedHeight = component.find(DiscoverPanels).prop('topPanelHeight');
|
||||
expect(component.find(DiscoverChart).childAt(0).getDOMNode()).not.toHaveStyle({
|
||||
height: `${expectedHeight}px`,
|
||||
});
|
||||
});
|
||||
|
||||
it('should pass undefined for onResetChartHeight to DiscoverChart when panels mode is DISCOVER_PANELS_MODE.FIXED', async () => {
|
||||
const component = await mountComponent();
|
||||
expect(component.find(DiscoverChart).prop('onResetChartHeight')).toBeDefined();
|
||||
setWindowWidth(component, euiThemeVars.euiBreakpoints.s);
|
||||
expect(component.find(DiscoverChart).prop('onResetChartHeight')).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not set a fixed height for DiscoverChart when panels mode is DISCOVER_PANELS_MODE.FIXED and hideChart is true', async () => {
|
||||
const component = await mountComponent({ hideChart: true });
|
||||
setWindowWidth(component, euiThemeVars.euiBreakpoints.s);
|
||||
const expectedHeight = component.find(DiscoverPanels).prop('initialTopPanelHeight');
|
||||
expect(component.find(DiscoverChart).childAt(0).getDOMNode()).not.toHaveStyle({
|
||||
height: `${expectedHeight}px`,
|
||||
describe('DocumentViewModeToggle', () => {
|
||||
it('should show DocumentViewModeToggle when isPlainRecord is false', async () => {
|
||||
const component = await mountComponent();
|
||||
expect(component.find(DocumentViewModeToggle).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('should not show DocumentViewModeToggle when isPlainRecord is true', async () => {
|
||||
const component = await mountComponent({ isPlainRecord: true });
|
||||
expect(component.find(DocumentViewModeToggle).exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
it('should not set a fixed height for DiscoverChart when panels mode is DISCOVER_PANELS_MODE.FIXED and isTimeBased is false', async () => {
|
||||
const component = await mountComponent({ isTimeBased: false });
|
||||
setWindowWidth(component, euiThemeVars.euiBreakpoints.s);
|
||||
const expectedHeight = component.find(DiscoverPanels).prop('initialTopPanelHeight');
|
||||
expect(component.find(DiscoverChart).childAt(0).getDOMNode()).not.toHaveStyle({
|
||||
height: `${expectedHeight}px`,
|
||||
describe('topPanelHeight persistence', () => {
|
||||
it('should try to get the initial topPanelHeight for DiscoverPanels from storage', async () => {
|
||||
const storage = new LocalStorageMock({}) as unknown as Storage;
|
||||
const originalGet = storage.get;
|
||||
storage.get = jest.fn().mockImplementation(originalGet);
|
||||
await mountComponent({ storage });
|
||||
expect(storage.get).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY);
|
||||
});
|
||||
});
|
||||
|
||||
it('should show DocumentViewModeToggle when isPlainRecord is false', async () => {
|
||||
const component = await mountComponent();
|
||||
expect(component.find(DocumentViewModeToggle).exists()).toBe(true);
|
||||
});
|
||||
it('should pass a default topPanelHeight to DiscoverPanels if no value is found in storage', async () => {
|
||||
const storage = new LocalStorageMock({}) as unknown as Storage;
|
||||
const originalGet = storage.get;
|
||||
storage.get = jest.fn().mockImplementation(originalGet);
|
||||
const component = await mountComponent({ storage });
|
||||
expect(storage.get).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY);
|
||||
expect(storage.get).toHaveReturnedWith(null);
|
||||
expect(component.find(DiscoverPanels).prop('topPanelHeight')).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should not show DocumentViewModeToggle when isPlainRecord is true', async () => {
|
||||
const component = await mountComponent({ isPlainRecord: true });
|
||||
expect(component.find(DocumentViewModeToggle).exists()).toBe(false);
|
||||
it('should pass the stored topPanelHeight to DiscoverPanels if a value is found in storage', async () => {
|
||||
const storage = new LocalStorageMock({}) as unknown as Storage;
|
||||
const topPanelHeight = 123;
|
||||
storage.get = jest.fn().mockImplementation(() => topPanelHeight);
|
||||
const component = await mountComponent({ storage });
|
||||
expect(storage.get).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY);
|
||||
expect(storage.get).toHaveReturnedWith(topPanelHeight);
|
||||
expect(component.find(DiscoverPanels).prop('topPanelHeight')).toBe(topPanelHeight);
|
||||
});
|
||||
|
||||
it('should update the topPanelHeight in storage and pass the new value to DiscoverPanels when the topPanelHeight changes', async () => {
|
||||
const storage = new LocalStorageMock({}) as unknown as Storage;
|
||||
const originalSet = storage.set;
|
||||
storage.set = jest.fn().mockImplementation(originalSet);
|
||||
const component = await mountComponent({ storage });
|
||||
const newTopPanelHeight = 123;
|
||||
expect(component.find(DiscoverPanels).prop('topPanelHeight')).not.toBe(newTopPanelHeight);
|
||||
act(() => {
|
||||
component.find(DiscoverPanels).prop('onTopPanelHeightChange')(newTopPanelHeight);
|
||||
});
|
||||
component.update();
|
||||
expect(storage.set).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY, newTopPanelHeight);
|
||||
expect(component.find(DiscoverPanels).prop('topPanelHeight')).toBe(newTopPanelHeight);
|
||||
});
|
||||
|
||||
it('should reset the topPanelHeight to the default when onResetChartHeight is called on DiscoverChart', async () => {
|
||||
const storage = new LocalStorageMock({}) as unknown as Storage;
|
||||
const originalSet = storage.set;
|
||||
storage.set = jest.fn().mockImplementation(originalSet);
|
||||
const component = await mountComponent({ storage });
|
||||
const defaultTopPanelHeight = component.find(DiscoverPanels).prop('topPanelHeight');
|
||||
const newTopPanelHeight = 123;
|
||||
expect(component.find(DiscoverPanels).prop('topPanelHeight')).not.toBe(newTopPanelHeight);
|
||||
act(() => {
|
||||
component.find(DiscoverPanels).prop('onTopPanelHeightChange')(newTopPanelHeight);
|
||||
});
|
||||
component.update();
|
||||
expect(storage.set).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY, newTopPanelHeight);
|
||||
expect(component.find(DiscoverPanels).prop('topPanelHeight')).toBe(newTopPanelHeight);
|
||||
act(() => {
|
||||
component.find(DiscoverChart).prop('onResetChartHeight')!();
|
||||
});
|
||||
component.update();
|
||||
expect(storage.set).toHaveBeenCalledWith(HISTOGRAM_HEIGHT_KEY, defaultTopPanelHeight);
|
||||
expect(component.find(DiscoverPanels).prop('topPanelHeight')).toBe(defaultTopPanelHeight);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -15,7 +15,7 @@ import {
|
|||
useIsWithinBreakpoints,
|
||||
} from '@elastic/eui';
|
||||
import { SavedSearch } from '@kbn/saved-search-plugin/public';
|
||||
import React, { RefObject, useCallback, useMemo } from 'react';
|
||||
import React, { RefObject, useCallback, useMemo, useState } from 'react';
|
||||
import { DataView } from '@kbn/data-views-plugin/common';
|
||||
import { METRIC_TYPE } from '@kbn/analytics';
|
||||
import { createHtmlPortalNode, InPortal, OutPortal } from 'react-reverse-portal';
|
||||
|
@ -35,6 +35,8 @@ import { DiscoverPanels, DISCOVER_PANELS_MODE } from './discover_panels';
|
|||
const DiscoverChartMemoized = React.memo(DiscoverChart);
|
||||
const FieldStatisticsTableMemoized = React.memo(FieldStatisticsTable);
|
||||
|
||||
export const HISTOGRAM_HEIGHT_KEY = 'discover:histogramHeight';
|
||||
|
||||
export interface DiscoverMainContentProps {
|
||||
isPlainRecord: boolean;
|
||||
dataView: DataView;
|
||||
|
@ -74,7 +76,7 @@ export const DiscoverMainContent = ({
|
|||
columns,
|
||||
resizeRef,
|
||||
}: DiscoverMainContentProps) => {
|
||||
const { trackUiMetric } = useDiscoverServices();
|
||||
const { trackUiMetric, storage } = useDiscoverServices();
|
||||
|
||||
const setDiscoverViewMode = useCallback(
|
||||
(mode: VIEW_MODE) => {
|
||||
|
@ -104,14 +106,36 @@ export const DiscoverMainContent = ({
|
|||
const hideChart = state.hideChart || !isTimeBased;
|
||||
const showFixedPanels = useIsWithinBreakpoints(['xs', 's']) || isPlainRecord || hideChart;
|
||||
const { euiTheme } = useEuiTheme();
|
||||
const topPanelHeight = euiTheme.base * 12;
|
||||
const defaultTopPanelHeight = euiTheme.base * 12;
|
||||
const minTopPanelHeight = euiTheme.base * 8;
|
||||
const minMainPanelHeight = euiTheme.base * 10;
|
||||
|
||||
const [topPanelHeight, setTopPanelHeight] = useState(
|
||||
Number(storage.get(HISTOGRAM_HEIGHT_KEY)) || defaultTopPanelHeight
|
||||
);
|
||||
|
||||
const storeTopPanelHeight = useCallback(
|
||||
(newTopPanelHeight: number) => {
|
||||
storage.set(HISTOGRAM_HEIGHT_KEY, newTopPanelHeight);
|
||||
setTopPanelHeight(newTopPanelHeight);
|
||||
},
|
||||
[storage]
|
||||
);
|
||||
|
||||
const resetTopPanelHeight = useCallback(
|
||||
() => storeTopPanelHeight(defaultTopPanelHeight),
|
||||
[storeTopPanelHeight, defaultTopPanelHeight]
|
||||
);
|
||||
|
||||
const onTopPanelHeightChange = useCallback(
|
||||
(newTopPanelHeight: number) => storeTopPanelHeight(newTopPanelHeight),
|
||||
[storeTopPanelHeight]
|
||||
);
|
||||
|
||||
const chartClassName =
|
||||
showFixedPanels && !hideChart
|
||||
? css`
|
||||
height: ${topPanelHeight}px;
|
||||
height: ${defaultTopPanelHeight}px;
|
||||
`
|
||||
: 'eui-fullHeight';
|
||||
|
||||
|
@ -136,6 +160,9 @@ export const DiscoverMainContent = ({
|
|||
interval={state.interval}
|
||||
isTimeBased={isTimeBased}
|
||||
appendHistogram={showFixedPanels ? <EuiSpacer size="s" /> : <EuiSpacer size="m" />}
|
||||
onResetChartHeight={
|
||||
panelsMode === DISCOVER_PANELS_MODE.RESIZABLE ? resetTopPanelHeight : undefined
|
||||
}
|
||||
/>
|
||||
</InPortal>
|
||||
<InPortal node={mainPanelNode}>
|
||||
|
@ -189,11 +216,12 @@ export const DiscoverMainContent = ({
|
|||
className="dscPageContent__inner"
|
||||
mode={panelsMode}
|
||||
resizeRef={resizeRef}
|
||||
initialTopPanelHeight={topPanelHeight}
|
||||
topPanelHeight={topPanelHeight}
|
||||
minTopPanelHeight={minTopPanelHeight}
|
||||
minMainPanelHeight={minMainPanelHeight}
|
||||
topPanel={<OutPortal node={topPanelNode} />}
|
||||
mainPanel={<OutPortal node={mainPanelNode} />}
|
||||
onTopPanelHeightChange={onTopPanelHeightChange}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -34,11 +34,12 @@ describe('Discover panels component', () => {
|
|||
<DiscoverPanels
|
||||
mode={mode}
|
||||
resizeRef={resizeRef}
|
||||
initialTopPanelHeight={initialTopPanelHeight}
|
||||
topPanelHeight={initialTopPanelHeight}
|
||||
minTopPanelHeight={minTopPanelHeight}
|
||||
minMainPanelHeight={minMainPanelHeight}
|
||||
topPanel={topPanel}
|
||||
mainPanel={mainPanel}
|
||||
onTopPanelHeightChange={jest.fn()}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -20,11 +20,12 @@ export interface DiscoverPanelsProps {
|
|||
className?: string;
|
||||
mode: DISCOVER_PANELS_MODE;
|
||||
resizeRef: RefObject<HTMLDivElement>;
|
||||
initialTopPanelHeight: number;
|
||||
topPanelHeight: number;
|
||||
minTopPanelHeight: number;
|
||||
minMainPanelHeight: number;
|
||||
topPanel: ReactElement;
|
||||
mainPanel: ReactElement;
|
||||
onTopPanelHeightChange: (height: number) => void;
|
||||
}
|
||||
|
||||
const fixedModes = [DISCOVER_PANELS_MODE.SINGLE, DISCOVER_PANELS_MODE.FIXED];
|
||||
|
@ -33,11 +34,12 @@ export const DiscoverPanels = ({
|
|||
className,
|
||||
mode,
|
||||
resizeRef,
|
||||
initialTopPanelHeight,
|
||||
topPanelHeight,
|
||||
minTopPanelHeight,
|
||||
minMainPanelHeight,
|
||||
topPanel,
|
||||
mainPanel,
|
||||
onTopPanelHeightChange,
|
||||
}: DiscoverPanelsProps) => {
|
||||
const panelsProps = { className, topPanel, mainPanel };
|
||||
|
||||
|
@ -46,9 +48,10 @@ export const DiscoverPanels = ({
|
|||
) : (
|
||||
<DiscoverPanelsResizable
|
||||
resizeRef={resizeRef}
|
||||
initialTopPanelHeight={initialTopPanelHeight}
|
||||
topPanelHeight={topPanelHeight}
|
||||
minTopPanelHeight={minTopPanelHeight}
|
||||
minMainPanelHeight={minMainPanelHeight}
|
||||
onTopPanelHeightChange={onTopPanelHeightChange}
|
||||
{...panelsProps}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -33,6 +33,7 @@ describe('Discover panels resizable', () => {
|
|||
topPanel = <></>,
|
||||
mainPanel = <></>,
|
||||
attachTo,
|
||||
onTopPanelHeightChange = jest.fn(),
|
||||
}: {
|
||||
className?: string;
|
||||
resizeRef?: RefObject<HTMLDivElement>;
|
||||
|
@ -42,16 +43,18 @@ describe('Discover panels resizable', () => {
|
|||
topPanel?: ReactElement;
|
||||
mainPanel?: ReactElement;
|
||||
attachTo?: HTMLElement;
|
||||
onTopPanelHeightChange?: (height: number) => void;
|
||||
}) => {
|
||||
return mount(
|
||||
<DiscoverPanelsResizable
|
||||
className={className}
|
||||
resizeRef={resizeRef}
|
||||
initialTopPanelHeight={initialTopPanelHeight}
|
||||
topPanelHeight={initialTopPanelHeight}
|
||||
minTopPanelHeight={minTopPanelHeight}
|
||||
minMainPanelHeight={minMainPanelHeight}
|
||||
topPanel={topPanel}
|
||||
mainPanel={mainPanel}
|
||||
onTopPanelHeightChange={onTopPanelHeightChange}
|
||||
/>,
|
||||
attachTo ? { attachTo } : undefined
|
||||
);
|
||||
|
@ -95,7 +98,10 @@ describe('Discover panels resizable', () => {
|
|||
|
||||
it('should set the correct heights of both panels when the panels are resized', () => {
|
||||
const initialTopPanelHeight = 200;
|
||||
const component = mountComponent({ initialTopPanelHeight });
|
||||
const onTopPanelHeightChange = jest.fn((topPanelHeight) => {
|
||||
component.setProps({ topPanelHeight }).update();
|
||||
});
|
||||
const component = mountComponent({ initialTopPanelHeight, onTopPanelHeightChange });
|
||||
expectCorrectPanelSizes(component, containerHeight, initialTopPanelHeight);
|
||||
const newTopPanelSize = 30;
|
||||
const onPanelSizeChange = component
|
||||
|
@ -106,7 +112,9 @@ describe('Discover panels resizable', () => {
|
|||
onPanelSizeChange({ [topPanelId]: newTopPanelSize });
|
||||
});
|
||||
forceRender(component);
|
||||
expectCorrectPanelSizes(component, containerHeight, containerHeight * (newTopPanelSize / 100));
|
||||
const newTopPanelHeight = (newTopPanelSize / 100) * containerHeight;
|
||||
expect(onTopPanelHeightChange).toHaveBeenCalledWith(newTopPanelHeight);
|
||||
expectCorrectPanelSizes(component, containerHeight, newTopPanelHeight);
|
||||
});
|
||||
|
||||
it('should maintain the height of the top panel and resize the main panel when the container height changes', () => {
|
||||
|
|
|
@ -19,23 +19,24 @@ const pixelsToPercent = (containerHeight: number, pixels: number) =>
|
|||
export const DiscoverPanelsResizable = ({
|
||||
className,
|
||||
resizeRef,
|
||||
initialTopPanelHeight,
|
||||
topPanelHeight,
|
||||
minTopPanelHeight,
|
||||
minMainPanelHeight,
|
||||
topPanel,
|
||||
mainPanel,
|
||||
onTopPanelHeightChange,
|
||||
}: {
|
||||
className?: string;
|
||||
resizeRef: RefObject<HTMLDivElement>;
|
||||
initialTopPanelHeight: number;
|
||||
topPanelHeight: number;
|
||||
minTopPanelHeight: number;
|
||||
minMainPanelHeight: number;
|
||||
topPanel: ReactElement;
|
||||
mainPanel: ReactElement;
|
||||
onTopPanelHeightChange: (height: number) => void;
|
||||
}) => {
|
||||
const topPanelId = useGeneratedHtmlId({ prefix: 'topPanel' });
|
||||
const { height: containerHeight } = useResizeObserver(resizeRef.current);
|
||||
const [topPanelHeight, setTopPanelHeight] = useState(initialTopPanelHeight);
|
||||
const [panelSizes, setPanelSizes] = useState({ topPanelSize: 0, mainPanelSize: 0 });
|
||||
|
||||
// EuiResizableContainer doesn't work properly when used with react-reverse-portal and
|
||||
|
@ -69,9 +70,13 @@ export const DiscoverPanelsResizable = ({
|
|||
// the effect below to update the panel sizes.
|
||||
const onPanelSizeChange = useCallback(
|
||||
({ [topPanelId]: topPanelSize }: { [key: string]: number }) => {
|
||||
setTopPanelHeight(percentToPixels(containerHeight, topPanelSize));
|
||||
const newTopPanelHeight = percentToPixels(containerHeight, topPanelSize);
|
||||
|
||||
if (newTopPanelHeight !== topPanelHeight) {
|
||||
onTopPanelHeightChange(newTopPanelHeight);
|
||||
}
|
||||
},
|
||||
[containerHeight, topPanelId]
|
||||
[containerHeight, onTopPanelHeightChange, topPanelHeight, topPanelId]
|
||||
);
|
||||
|
||||
// This effect will update the panel sizes based on the top panel height whenever
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue