[Discover] Close document flyout when inspect flyout is displayed (#89679)

This commit is contained in:
Matthias Wilhelm 2021-02-05 11:42:59 +01:00 committed by GitHub
parent 3a388c6bf0
commit b058f7852b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 93 additions and 72 deletions

View file

@ -56,7 +56,6 @@ import {
SORT_DEFAULT_ORDER_SETTING,
} from '../../../common';
import { loadIndexPattern, resolveIndexPattern } from '../helpers/resolve_index_pattern';
import { getTopNavLinks } from '../components/top_nav/get_top_nav_links';
import { updateSearchSource } from '../helpers/update_search_source';
import { calcFieldCounts } from '../helpers/calc_field_counts';
import { getDefaultSort } from './doc_table/lib/get_default_sort';
@ -198,7 +197,7 @@ function discoverController($route, $scope, Promise) {
session: data.search.session,
});
const state = getState({
const stateContainer = getState({
getStateDefaults,
storeInSessionStorage: config.get('state:storeInSessionStorage'),
history,
@ -213,7 +212,7 @@ function discoverController($route, $scope, Promise) {
replaceUrlAppState,
kbnUrlStateStorage,
getPreviousAppState,
} = state;
} = stateContainer;
if (appStateContainer.getState().index !== $scope.indexPattern.id) {
//used index pattern is different than the given by url/state which is invalid
@ -323,10 +322,24 @@ function discoverController($route, $scope, Promise) {
)
);
const inspectorAdapters = {
requests: new RequestAdapter(),
$scope.opts = {
// number of records to fetch, then paginate through
sampleSize: config.get(SAMPLE_SIZE_SETTING),
timefield: getTimeField(),
savedSearch: savedSearch,
indexPatternList: $route.current.locals.savedObjects.ip.list,
config: config,
setHeaderActionMenu: getHeaderActionMenuMounter(),
filterManager,
setAppState,
data,
stateContainer,
};
const inspectorAdapters = ($scope.opts.inspectorAdapters = {
requests: new RequestAdapter(),
});
$scope.timefilterUpdateHandler = (ranges) => {
timefilter.setTime({
from: moment(ranges.from).toISOString(),
@ -358,7 +371,7 @@ function discoverController($route, $scope, Promise) {
unlistenHistoryBasePath();
});
const getFieldCounts = async () => {
$scope.opts.getFieldCounts = async () => {
// the field counts aren't set until we have the data back,
// so we wait for the fetch to be done before proceeding
if ($scope.fetchStatus === fetchStatuses.COMPLETE) {
@ -374,20 +387,11 @@ function discoverController($route, $scope, Promise) {
});
});
};
$scope.topNavMenu = getTopNavLinks({
getFieldCounts,
indexPattern: $scope.indexPattern,
inspectorAdapters,
navigateTo: (path) => {
$scope.$evalAsync(() => {
history.push(path);
});
},
savedSearch,
services,
state,
});
$scope.opts.navigateTo = (path) => {
$scope.$evalAsync(() => {
history.push(path);
});
};
$scope.searchSource
.setField('index', $scope.indexPattern)
@ -446,19 +450,6 @@ function discoverController($route, $scope, Promise) {
$scope.state.index = $scope.indexPattern.id;
$scope.state.sort = getSortArray($scope.state.sort, $scope.indexPattern);
$scope.opts = {
// number of records to fetch, then paginate through
sampleSize: config.get(SAMPLE_SIZE_SETTING),
timefield: getTimeField(),
savedSearch: savedSearch,
indexPatternList: $route.current.locals.savedObjects.ip.list,
config: config,
setHeaderActionMenu: getHeaderActionMenuMounter(),
filterManager,
setAppState,
data,
};
const shouldSearchOnPageLoad = () => {
// A saved search is created on every page load, so we check the ID to see if we're loading a
// previously saved search or if it is just transient

View file

@ -9,11 +9,8 @@
import React from 'react';
import { shallowWithIntl } from '@kbn/test/jest';
import { Discover } from './discover';
import { inspectorPluginMock } from '../../../../inspector/public/mocks';
import { esHits } from '../../__mocks__/es_hits';
import { indexPatternMock } from '../../__mocks__/index_pattern';
import { getTopNavLinks } from './top_nav/get_top_nav_links';
import { DiscoverServices } from '../../build_services';
import { GetStateReturn } from '../angular/discover_state';
import { savedSearchMock } from '../../__mocks__/saved_search';
import { createSearchSourceMock } from '../../../../data/common/search/search_source/mocks';
@ -25,6 +22,8 @@ import { SavedObject } from '../../../../../core/types';
import { navigationPluginMock } from '../../../../navigation/public/mocks';
import { indexPatternWithTimefieldMock } from '../../__mocks__/index_pattern_with_timefield';
import { calcFieldCounts } from '../helpers/calc_field_counts';
import { DiscoverProps } from './types';
import { RequestAdapter } from '../../../../inspector/common';
const mockNavigation = navigationPluginMock.createStartContract();
@ -45,17 +44,9 @@ jest.mock('../../kibana_services', () => {
};
});
function getProps(indexPattern: IndexPattern) {
function getProps(indexPattern: IndexPattern): DiscoverProps {
const searchSourceMock = createSearchSourceMock({});
const state = ({} as unknown) as GetStateReturn;
const services = ({
capabilities: {
discover: {
save: true,
},
},
uiSettings: mockUiSettings,
} as unknown) as DiscoverServices;
return {
fetch: jest.fn(),
@ -76,32 +67,25 @@ function getProps(indexPattern: IndexPattern) {
opts: {
config: mockUiSettings,
data: dataPluginMock.createStartContract(),
fixedScroll: jest.fn(),
filterManager: createFilterManagerMock(),
getFieldCounts: jest.fn(),
indexPatternList: (indexPattern as unknown) as Array<SavedObject<IndexPatternAttributes>>,
inspectorAdapters: { requests: {} as RequestAdapter },
navigateTo: jest.fn(),
sampleSize: 10,
savedSearch: savedSearchMock,
setHeaderActionMenu: jest.fn(),
timefield: indexPattern.timeFieldName || '',
setAppState: jest.fn(),
setHeaderActionMenu: jest.fn(),
stateContainer: state,
timefield: indexPattern.timeFieldName || '',
},
resetQuery: jest.fn(),
resultState: 'ready',
rows: esHits,
searchSource: searchSourceMock,
setIndexPattern: jest.fn(),
showSaveQuery: true,
state: { columns: [] },
timefilterUpdateHandler: jest.fn(),
topNavMenu: getTopNavLinks({
getFieldCounts: jest.fn(),
indexPattern,
inspectorAdapters: inspectorPluginMock,
navigateTo: jest.fn(),
savedSearch: savedSearchMock,
services,
state,
}),
updateQuery: jest.fn(),
updateSavedQueryId: jest.fn(),
};

View file

@ -41,6 +41,8 @@ import { getDisplayedColumns } from '../helpers/columns';
import { SortPairArr } from '../angular/doc_table/lib/get_sort';
import { DiscoverGrid, DiscoverGridProps } from './discover_grid/discover_grid';
import { SEARCH_FIELDS_FROM_SOURCE } from '../../../common';
import { ElasticSearchHit } from '../doc_views/doc_views_types';
import { getTopNavLinks } from './top_nav/get_top_nav_links';
const DocTableLegacyMemoized = React.memo((props: DocTableLegacyProps) => (
<DocTableLegacy {...props} />
@ -77,11 +79,11 @@ export function Discover({
state,
timefilterUpdateHandler,
timeRange,
topNavMenu,
updateQuery,
updateSavedQueryId,
unmappedFieldsConfig,
}: DiscoverProps) {
const [expandedDoc, setExpandedDoc] = useState<ElasticSearchHit | undefined>(undefined);
const scrollableDesktop = useRef<HTMLDivElement>(null);
const collapseIcon = useRef<HTMLButtonElement>(null);
const isMobile = () => {
@ -91,7 +93,24 @@ export function Discover({
const [toggleOn, toggleChart] = useState(true);
const [isSidebarClosed, setIsSidebarClosed] = useState(false);
const services = getServices();
const services = useMemo(() => getServices(), []);
const topNavMenu = useMemo(
() =>
getTopNavLinks({
getFieldCounts: opts.getFieldCounts,
indexPattern,
inspectorAdapters: opts.inspectorAdapters,
navigateTo: opts.navigateTo,
savedSearch: opts.savedSearch,
services,
state: opts.stateContainer,
onOpenInspector: () => {
// prevent overlapping
setExpandedDoc(undefined);
},
}),
[indexPattern, opts, services]
);
const { TopNavMenu } = services.navigation.ui;
const { trackUiMetric } = services;
const { savedSearch, indexPatternList, config } = opts;
@ -318,12 +337,14 @@ export function Discover({
<DataGridMemoized
ariaLabelledBy="documentsAriaLabel"
columns={getDisplayedColumns(state.columns, indexPattern)}
expandedDoc={expandedDoc}
indexPattern={indexPattern}
rows={rows}
sort={(state.sort as SortPairArr[]) || []}
sampleSize={opts.sampleSize}
searchDescription={opts.savedSearch.description}
searchTitle={opts.savedSearch.lastSavedTitle}
setExpandedDoc={setExpandedDoc}
showTimeCol={
!config.get('doc_table:hideTimeColumn', false) &&
!!indexPattern.timeFieldName

View file

@ -50,6 +50,10 @@ export interface DiscoverGridProps {
* Determines which columns are displayed
*/
columns: string[];
/**
* If set, the given document is displayed in a flyout
*/
expandedDoc?: ElasticSearchHit;
/**
* The used index pattern
*/
@ -87,6 +91,10 @@ export interface DiscoverGridProps {
* The max size of the documents returned by Elasticsearch
*/
sampleSize: number;
/**
* Function to set the expanded document, which is displayed in a flyout
*/
setExpandedDoc: (doc: ElasticSearchHit | undefined) => void;
/**
* Grid display settings persisted in Elasticsearch (e.g. column width)
*/
@ -121,6 +129,7 @@ export const DiscoverGrid = ({
ariaLabelledBy,
columns,
indexPattern,
expandedDoc,
onAddColumn,
onFilter,
onRemoveColumn,
@ -132,11 +141,11 @@ export const DiscoverGrid = ({
searchDescription,
searchTitle,
services,
setExpandedDoc,
settings,
showTimeCol,
sort,
}: DiscoverGridProps) => {
const [expanded, setExpanded] = useState<ElasticSearchHit | undefined>(undefined);
const defaultColumns = columns.includes('_source');
/**
@ -233,8 +242,8 @@ export const DiscoverGrid = ({
return (
<DiscoverGridContext.Provider
value={{
expanded,
setExpanded,
expanded: expandedDoc,
setExpanded: setExpandedDoc,
rows: rows || [],
onFilter,
indexPattern,
@ -302,15 +311,15 @@ export const DiscoverGrid = ({
</p>
</EuiScreenReaderOnly>
)}
{expanded && (
{expandedDoc && (
<DiscoverGridFlyout
indexPattern={indexPattern}
hit={expanded}
hit={expandedDoc}
columns={columns}
onFilter={onFilter}
onRemoveColumn={onRemoveColumn}
onAddColumn={onAddColumn}
onClose={() => setExpanded(undefined)}
onClose={() => setExpandedDoc(undefined)}
services={services}
/>
)}

View file

@ -29,6 +29,7 @@ test('getTopNavLinks result', () => {
indexPattern: indexPatternMock,
inspectorAdapters: inspectorPluginMock,
navigateTo: jest.fn(),
onOpenInspector: jest.fn(),
savedSearch: savedSearchMock,
services,
state,

View file

@ -28,6 +28,7 @@ export const getTopNavLinks = ({
savedSearch,
services,
state,
onOpenInspector,
}: {
getFieldCounts: () => Promise<Record<string, number>>;
indexPattern: IndexPattern;
@ -36,6 +37,7 @@ export const getTopNavLinks = ({
savedSearch: SavedSearch;
services: DiscoverServices;
state: GetStateReturn;
onOpenInspector: () => void;
}) => {
const newSearch = {
id: 'new',
@ -123,6 +125,7 @@ export const getTopNavLinks = ({
}),
testId: 'openInspectorButton',
run: () => {
onOpenInspector();
services.inspector.open(inspectorAdapters, {
title: savedSearch.title,
});

View file

@ -21,8 +21,8 @@ import {
TimeRange,
} from '../../../../data/public';
import { SavedSearch } from '../../saved_searches';
import { AppState } from '../angular/discover_state';
import { TopNavMenuData } from '../../../../navigation/public';
import { AppState, GetStateReturn } from '../angular/discover_state';
import { RequestAdapter } from '../../../../inspector/common';
export interface DiscoverProps {
/**
@ -100,6 +100,22 @@ export interface DiscoverProps {
* Client of uiSettings
*/
config: IUiSettingsClient;
/**
* returns field statistics based on the loaded data sample
*/
getFieldCounts: () => Promise<Record<string, number>>;
/**
* Use angular router for navigation
*/
navigateTo: () => void;
/**
* Functions to get/mutate state
*/
stateContainer: GetStateReturn;
/**
* Inspect, for analyzing requests and responses
*/
inspectorAdapters: { requests: RequestAdapter };
/**
* Data plugin
*/
@ -165,10 +181,6 @@ export interface DiscoverProps {
* Currently selected time range
*/
timeRange?: { from: string; to: string };
/**
* Menu data of top navigation (New, save ...)
*/
topNavMenu: TopNavMenuData[];
/**
* Function to update the actual query
*/