mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 10:40:07 -04:00
## Summary
This PR adds resize support to the Discover field list sidebar, which is
persisted to a user's local storage similar to the resizable chart
height.
Additionally it migrates the resizable layout code from Unified
Histogram to a new package called `kbn-resizable-layout` so it can be
shared between Discover and Unified Histogram, as well as act as a new
platform component that other teams can consume to create their own
resizable layouts.

Resolves #9531.
### Checklist
- [ ] ~Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)~
- [ ]
~[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials~
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [x] Any UI touched in this PR is usable by keyboard only (learn more
about [keyboard accessibility](https://webaim.org/techniques/keyboard/))
- [ ] ~Any UI touched in this PR does not create any new axe failures
(run axe in browser:
[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),
[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))~
- [ ] ~If a plugin configuration key changed, check if it needs to be
allowlisted in the cloud and added to the [docker
list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)~
- [x] This renders correctly on smaller devices using a responsive
layout. (You can test this [in your
browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))
- [x] This was checked for [cross-browser
compatibility](https://www.elastic.co/support/matrix#matrix_browsers)
### For maintainers
- [ ] This was checked for breaking API changes and was [labeled
appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
---------
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
159 lines
4.8 KiB
TypeScript
159 lines
4.8 KiB
TypeScript
/*
|
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
* or more contributor license agreements. Licensed under the Elastic License
|
|
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
|
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
|
* Side Public License, v 1.
|
|
*/
|
|
|
|
import React, { forwardRef, useEffect, useImperativeHandle, useState } from 'react';
|
|
import { Subject } from 'rxjs';
|
|
import { pick } from 'lodash';
|
|
import useMount from 'react-use/lib/useMount';
|
|
import { LensSuggestionsApi } from '@kbn/lens-plugin/public';
|
|
import { UnifiedHistogramLayout, UnifiedHistogramLayoutProps } from '../layout';
|
|
import type { UnifiedHistogramInputMessage, UnifiedHistogramRequestContext } from '../types';
|
|
import {
|
|
createStateService,
|
|
UnifiedHistogramStateOptions,
|
|
UnifiedHistogramStateService,
|
|
} from './services/state_service';
|
|
import { useStateProps } from './hooks/use_state_props';
|
|
import { useStateSelector } from './utils/use_state_selector';
|
|
import { topPanelHeightSelector, currentSuggestionSelector } from './utils/state_selectors';
|
|
|
|
type LayoutProps = Pick<
|
|
UnifiedHistogramLayoutProps,
|
|
'disableAutoFetching' | 'disableTriggers' | 'disabledActions'
|
|
>;
|
|
|
|
/**
|
|
* The options used to initialize the container
|
|
*/
|
|
export type UnifiedHistogramCreationOptions = Omit<UnifiedHistogramStateOptions, 'services'> &
|
|
LayoutProps;
|
|
|
|
/**
|
|
* The props exposed by the container
|
|
*/
|
|
export type UnifiedHistogramContainerProps = {
|
|
getCreationOptions?: () =>
|
|
| UnifiedHistogramCreationOptions
|
|
| Promise<UnifiedHistogramCreationOptions>;
|
|
searchSessionId?: UnifiedHistogramRequestContext['searchSessionId'];
|
|
requestAdapter?: UnifiedHistogramRequestContext['adapter'];
|
|
isChartLoading?: boolean;
|
|
} & Pick<
|
|
UnifiedHistogramLayoutProps,
|
|
| 'services'
|
|
| 'className'
|
|
| 'dataView'
|
|
| 'query'
|
|
| 'filters'
|
|
| 'timeRange'
|
|
| 'relativeTimeRange'
|
|
| 'columns'
|
|
| 'container'
|
|
| 'appendHitsCounter'
|
|
| 'children'
|
|
| 'onBrushEnd'
|
|
| 'onFilter'
|
|
| 'withDefaultActions'
|
|
| 'disabledActions'
|
|
>;
|
|
|
|
/**
|
|
* The API exposed by the container
|
|
*/
|
|
export type UnifiedHistogramApi = {
|
|
/**
|
|
* Manually trigger a refetch of the data
|
|
*/
|
|
refetch: () => void;
|
|
} & Pick<
|
|
UnifiedHistogramStateService,
|
|
| 'state$'
|
|
| 'setChartHidden'
|
|
| 'setTopPanelHeight'
|
|
| 'setBreakdownField'
|
|
| 'setTimeInterval'
|
|
| 'setTotalHits'
|
|
>;
|
|
|
|
export const UnifiedHistogramContainer = forwardRef<
|
|
UnifiedHistogramApi,
|
|
UnifiedHistogramContainerProps
|
|
>((containerProps, ref) => {
|
|
const [layoutProps, setLayoutProps] = useState<LayoutProps>();
|
|
const [stateService, setStateService] = useState<UnifiedHistogramStateService>();
|
|
const [lensSuggestionsApi, setLensSuggestionsApi] = useState<LensSuggestionsApi>();
|
|
const [input$] = useState(() => new Subject<UnifiedHistogramInputMessage>());
|
|
const [api, setApi] = useState<UnifiedHistogramApi>();
|
|
|
|
// Expose the API to the parent component
|
|
useImperativeHandle(ref, () => api!, [api]);
|
|
|
|
// Call for creation options once the container is mounted
|
|
useMount(async () => {
|
|
const { getCreationOptions, services } = containerProps;
|
|
const options = await getCreationOptions?.();
|
|
const apiHelper = await services.lens.stateHelperApi();
|
|
|
|
setLayoutProps(pick(options, 'disableAutoFetching', 'disableTriggers', 'disabledActions'));
|
|
setStateService(createStateService({ services, ...options }));
|
|
setLensSuggestionsApi(() => apiHelper.suggestions);
|
|
});
|
|
|
|
// Initialize the API once the state service is available
|
|
useEffect(() => {
|
|
if (!stateService) {
|
|
return;
|
|
}
|
|
|
|
setApi({
|
|
refetch: () => {
|
|
input$.next({ type: 'refetch' });
|
|
},
|
|
...pick(
|
|
stateService,
|
|
'state$',
|
|
'setChartHidden',
|
|
'setTopPanelHeight',
|
|
'setBreakdownField',
|
|
'setTimeInterval',
|
|
'setTotalHits'
|
|
),
|
|
});
|
|
}, [input$, stateService]);
|
|
const { dataView, query, searchSessionId, requestAdapter, isChartLoading } = containerProps;
|
|
const currentSuggestion = useStateSelector(stateService?.state$, currentSuggestionSelector);
|
|
const topPanelHeight = useStateSelector(stateService?.state$, topPanelHeightSelector);
|
|
const stateProps = useStateProps({
|
|
stateService,
|
|
dataView,
|
|
query,
|
|
searchSessionId,
|
|
requestAdapter,
|
|
});
|
|
|
|
// Don't render anything until the container is initialized
|
|
if (!layoutProps || !lensSuggestionsApi || !api) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<UnifiedHistogramLayout
|
|
{...containerProps}
|
|
{...layoutProps}
|
|
{...stateProps}
|
|
currentSuggestion={currentSuggestion}
|
|
isChartLoading={Boolean(isChartLoading)}
|
|
topPanelHeight={topPanelHeight}
|
|
input$={input$}
|
|
lensSuggestionsApi={lensSuggestionsApi}
|
|
/>
|
|
);
|
|
});
|
|
|
|
// eslint-disable-next-line import/no-default-export
|
|
export default UnifiedHistogramContainer;
|