From 86b11a11eeab341e8e589eab2e9ee3275092990e Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Tue, 20 Apr 2021 17:02:26 +0100 Subject: [PATCH] [Discover] Support for runtime fields editor in mobile view (#97416) * [Discover] Add runtime fields editor to mobile view * Add a unit test * Fix typescript issues * Fixing layout on mobile Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- ...ver_index_pattern_management.test.tsx.snap | 661 ++++++++++++++++++ ...discover_index_pattern_management.test.tsx | 73 ++ .../discover_index_pattern_management.tsx | 107 +++ .../sidebar/discover_sidebar.test.tsx | 1 + .../components/sidebar/discover_sidebar.tsx | 131 +--- .../sidebar/discover_sidebar_responsive.tsx | 64 +- 6 files changed, 929 insertions(+), 108 deletions(-) create mode 100644 src/plugins/discover/public/application/components/sidebar/__snapshots__/discover_index_pattern_management.test.tsx.snap create mode 100644 src/plugins/discover/public/application/components/sidebar/discover_index_pattern_management.test.tsx create mode 100644 src/plugins/discover/public/application/components/sidebar/discover_index_pattern_management.tsx diff --git a/src/plugins/discover/public/application/components/sidebar/__snapshots__/discover_index_pattern_management.test.tsx.snap b/src/plugins/discover/public/application/components/sidebar/__snapshots__/discover_index_pattern_management.test.tsx.snap new file mode 100644 index 0000000000000..44b8cbb8b839a --- /dev/null +++ b/src/plugins/discover/public/application/components/sidebar/__snapshots__/discover_index_pattern_management.test.tsx.snap @@ -0,0 +1,661 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Discover IndexPattern Management renders correctly 1`] = ` + +`; diff --git a/src/plugins/discover/public/application/components/sidebar/discover_index_pattern_management.test.tsx b/src/plugins/discover/public/application/components/sidebar/discover_index_pattern_management.test.tsx new file mode 100644 index 0000000000000..88644dc213fd6 --- /dev/null +++ b/src/plugins/discover/public/application/components/sidebar/discover_index_pattern_management.test.tsx @@ -0,0 +1,73 @@ +/* + * 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 { getStubIndexPattern } from '../../../../../data/public/index_patterns/index_pattern.stub'; +import { coreMock } from '../../../../../../core/public/mocks'; +import { DiscoverServices } from '../../../build_services'; +// @ts-ignore +import stubbedLogstashFields from '../../../__fixtures__/logstash_fields'; +import { mountWithIntl } from '@kbn/test/jest'; +import React from 'react'; +import { DiscoverIndexPatternManagement } from './discover_index_pattern_management'; + +const mockServices = ({ + history: () => ({ + location: { + search: '', + }, + }), + capabilities: { + visualize: { + show: true, + }, + discover: { + save: false, + }, + }, + uiSettings: { + get: (key: string) => { + if (key === 'fields:popularLimit') { + return 5; + } + }, + }, + indexPatternFieldEditor: { + openEditor: jest.fn(), + userPermissions: { + editIndexPattern: jest.fn(), + }, + }, +} as unknown) as DiscoverServices; + +jest.mock('../../../kibana_services', () => ({ + getServices: () => mockServices, +})); + +describe('Discover IndexPattern Management', () => { + const indexPattern = getStubIndexPattern( + 'logstash-*', + (cfg: any) => cfg, + 'time', + stubbedLogstashFields(), + coreMock.createSetup() + ); + + const editField = jest.fn(); + + test('renders correctly', () => { + const component = mountWithIntl( + + ); + expect(component).toMatchSnapshot(); + }); +}); diff --git a/src/plugins/discover/public/application/components/sidebar/discover_index_pattern_management.tsx b/src/plugins/discover/public/application/components/sidebar/discover_index_pattern_management.tsx new file mode 100644 index 0000000000000..38681d75a4e1d --- /dev/null +++ b/src/plugins/discover/public/application/components/sidebar/discover_index_pattern_management.tsx @@ -0,0 +1,107 @@ +/* + * 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, { useState } from 'react'; +import { EuiButtonIcon, EuiContextMenuItem, EuiContextMenuPanel, EuiPopover } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { DiscoverServices } from '../../../build_services'; +import { IndexPattern } from '../../../../../data/common/index_patterns/index_patterns'; + +export interface DiscoverIndexPatternManagementProps { + /** + * Currently selected index pattern + */ + selectedIndexPattern?: IndexPattern; + /** + * Discover plugin services; + */ + services: DiscoverServices; + /** + * Read from the Fields API + */ + useNewFieldsApi?: boolean; + /** + * Callback to execute on edit field action + * @param fieldName + */ + editField: (fieldName?: string) => void; +} + +export function DiscoverIndexPatternManagement(props: DiscoverIndexPatternManagementProps) { + const { indexPatternFieldEditor, core } = props.services; + const { useNewFieldsApi, selectedIndexPattern, editField } = props; + const indexPatternFieldEditPermission = indexPatternFieldEditor?.userPermissions.editIndexPattern(); + const canEditIndexPatternField = !!indexPatternFieldEditPermission && useNewFieldsApi; + const [isAddIndexPatternFieldPopoverOpen, setIsAddIndexPatternFieldPopoverOpen] = useState(false); + + if (!useNewFieldsApi || !selectedIndexPattern || !canEditIndexPatternField) { + return null; + } + + const addField = () => { + editField(undefined); + }; + + return ( + { + setIsAddIndexPatternFieldPopoverOpen(false); + }} + ownFocus + data-test-subj="discover-addRuntimeField-popover" + button={ + { + setIsAddIndexPatternFieldPopoverOpen(!isAddIndexPatternFieldPopoverOpen); + }} + /> + } + > + { + setIsAddIndexPatternFieldPopoverOpen(false); + addField(); + }} + > + {i18n.translate('discover.fieldChooser.indexPatterns.addFieldButton', { + defaultMessage: 'Add field to index pattern', + })} + , + { + setIsAddIndexPatternFieldPopoverOpen(false); + core.application.navigateToApp('management', { + path: `/kibana/indexPatterns/patterns/${props.selectedIndexPattern?.id}`, + }); + }} + > + {i18n.translate('discover.fieldChooser.indexPatterns.manageFieldButton', { + defaultMessage: 'Manage index pattern fields', + })} + , + ]} + /> + + ); +} diff --git a/src/plugins/discover/public/application/components/sidebar/discover_sidebar.test.tsx b/src/plugins/discover/public/application/components/sidebar/discover_sidebar.test.tsx index 0b3f55b5630cc..01541344be7e1 100644 --- a/src/plugins/discover/public/application/components/sidebar/discover_sidebar.test.tsx +++ b/src/plugins/discover/public/application/components/sidebar/discover_sidebar.test.tsx @@ -109,6 +109,7 @@ function getCompProps(): DiscoverSidebarProps { setFieldFilter: jest.fn(), setAppState: jest.fn(), onEditRuntimeField: jest.fn(), + editField: jest.fn(), }; } diff --git a/src/plugins/discover/public/application/components/sidebar/discover_sidebar.tsx b/src/plugins/discover/public/application/components/sidebar/discover_sidebar.tsx index d97f98b9e054f..aaaf72f770630 100644 --- a/src/plugins/discover/public/application/components/sidebar/discover_sidebar.tsx +++ b/src/plugins/discover/public/application/components/sidebar/discover_sidebar.tsx @@ -19,10 +19,6 @@ import { EuiSpacer, EuiNotificationBadge, EuiPageSideBar, - EuiContextMenuPanel, - EuiContextMenuItem, - EuiPopover, - EuiButtonIcon, useResizeObserver, } from '@elastic/eui'; @@ -38,6 +34,7 @@ import { getDetails } from './lib/get_details'; import { FieldFilterState, getDefaultFieldFilter, setFieldFilterProp } from './lib/field_filter'; import { getIndexPatternFieldList } from './lib/get_index_pattern_field_list'; import { DiscoverSidebarResponsiveProps } from './discover_sidebar_responsive'; +import { DiscoverIndexPatternManagement } from './discover_index_pattern_management'; /** * Default number of available fields displayed and added on scroll @@ -64,6 +61,8 @@ export interface DiscoverSidebarProps extends DiscoverSidebarResponsiveProps { * @param ref reference to the field editor component */ setFieldEditorRef?: (ref: () => void | undefined) => void; + + editField: (fieldName?: string) => void; } export function DiscoverSidebar({ @@ -90,10 +89,10 @@ export function DiscoverSidebar({ onEditRuntimeField, setFieldEditorRef, closeFlyout, + editField, }: DiscoverSidebarProps) { const [fields, setFields] = useState(null); - const [isAddIndexPatternFieldPopoverOpen, setIsAddIndexPatternFieldPopoverOpen] = useState(false); - const { indexPatternFieldEditor, core } = services; + const { indexPatternFieldEditor } = services; const indexPatternFieldEditPermission = indexPatternFieldEditor?.userPermissions.editIndexPattern(); const canEditIndexPatternField = !!indexPatternFieldEditPermission && useNewFieldsApi; const [scrollContainer, setScrollContainer] = useState(null); @@ -273,31 +272,6 @@ export function DiscoverSidebar({ return null; } - const editField = (fieldName?: string) => { - if (!canEditIndexPatternField) { - return; - } - const ref = indexPatternFieldEditor.openEditor({ - ctx: { - indexPattern: selectedIndexPattern, - }, - fieldName, - onSave: async () => { - onEditRuntimeField(); - }, - }); - if (setFieldEditorRef) { - setFieldEditorRef(ref); - } - if (closeFlyout) { - closeFlyout(); - } - }; - - const addField = () => { - editField(undefined); - }; - if (useFlyout) { return (
- o.attributes.title)} - indexPatterns={indexPatterns} - state={state} - setAppState={setAppState} - /> + + + o.attributes.title)} + indexPatterns={indexPatterns} + state={state} + setAppState={setAppState} + /> + + + + +
); } - const indexPatternActions = ( - { - setIsAddIndexPatternFieldPopoverOpen(false); - }} - ownFocus - data-test-subj="discover-addRuntimeField-popover" - button={ - { - setIsAddIndexPatternFieldPopoverOpen(!isAddIndexPatternFieldPopoverOpen); - }} - /> - } - > - { - setIsAddIndexPatternFieldPopoverOpen(false); - addField(); - }} - > - {i18n.translate('discover.fieldChooser.indexPatterns.addFieldButton', { - defaultMessage: 'Add field to index pattern', - })} - , - { - setIsAddIndexPatternFieldPopoverOpen(false); - core.application.navigateToApp('management', { - path: `/kibana/indexPatterns/patterns/${selectedIndexPattern.id}`, - }); - }} - > - {i18n.translate('discover.fieldChooser.indexPatterns.manageFieldButton', { - defaultMessage: 'Manage index pattern fields', - })} - , - ]} - /> - - ); - return ( - {useNewFieldsApi && {indexPatternActions}} + + + diff --git a/src/plugins/discover/public/application/components/sidebar/discover_sidebar_responsive.tsx b/src/plugins/discover/public/application/components/sidebar/discover_sidebar_responsive.tsx index 6a16399f0e2e1..6b8918e2d9965 100644 --- a/src/plugins/discover/public/application/components/sidebar/discover_sidebar_responsive.tsx +++ b/src/plugins/discover/public/application/components/sidebar/discover_sidebar_responsive.tsx @@ -24,6 +24,8 @@ import { EuiIcon, EuiLink, EuiPortal, + EuiFlexGroup, + EuiFlexItem, } from '@elastic/eui'; import { DiscoverIndexPattern } from './discover_index_pattern'; import { IndexPatternAttributes, IndexPatternsContract } from '../../../../../data/common'; @@ -34,6 +36,7 @@ import { DiscoverSidebar } from './discover_sidebar'; import { DiscoverServices } from '../../../build_services'; import { ElasticSearchHit } from '../../doc_views/doc_views_types'; import { AppState } from '../../angular/discover_state'; +import { DiscoverIndexPatternManagement } from './discover_index_pattern_management'; export interface DiscoverSidebarResponsiveProps { /** @@ -121,7 +124,9 @@ export interface DiscoverSidebarResponsiveProps { */ showUnmappedFields: boolean; }; - + /** + * callback to execute on edit runtime field + */ onEditRuntimeField: () => void; } @@ -160,6 +165,31 @@ export function DiscoverSidebarResponsive(props: DiscoverSidebarResponsiveProps) setIsFlyoutVisible(false); }; + const { indexPatternFieldEditor } = props.services; + const indexPatternFieldEditPermission = indexPatternFieldEditor?.userPermissions.editIndexPattern(); + const canEditIndexPatternField = !!indexPatternFieldEditPermission && props.useNewFieldsApi; + + const editField = (fieldName?: string) => { + if (!canEditIndexPatternField || !props.selectedIndexPattern) { + return; + } + const ref = indexPatternFieldEditor.openEditor({ + ctx: { + indexPattern: props.selectedIndexPattern, + }, + fieldName, + onSave: async () => { + props.onEditRuntimeField(); + }, + }); + if (setFieldEditorRef) { + setFieldEditorRef(ref); + } + if (closeFlyout) { + closeFlyout(); + } + }; + return ( <> {props.isClosed ? null : ( @@ -168,7 +198,7 @@ export function DiscoverSidebarResponsive(props: DiscoverSidebarResponsiveProps) {...props} fieldFilter={fieldFilter} setFieldFilter={setFieldFilter} - setFieldEditorRef={setFieldEditorRef} + editField={editField} /> )} @@ -182,15 +212,28 @@ export function DiscoverSidebarResponsive(props: DiscoverSidebarResponsiveProps) } )} > - o.attributes.title)} - indexPatterns={props.indexPatterns} - state={props.state} - setAppState={props.setAppState} - /> + + + o.attributes.title)} + indexPatterns={props.indexPatterns} + state={props.state} + setAppState={props.setAppState} + /> + + + + + +