diff --git a/examples/discover_customization_examples/public/plugin.tsx b/examples/discover_customization_examples/public/plugin.tsx index c13c29782d89b..bdcb0b1fe19a6 100644 --- a/examples/discover_customization_examples/public/plugin.tsx +++ b/examples/discover_customization_examples/public/plugin.tsx @@ -7,7 +7,6 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import type { IconType } from '@elastic/eui'; import { EuiButton, EuiContextMenu, EuiFlexItem, EuiPopover } from '@elastic/eui'; import type { CoreSetup, CoreStart, Plugin } from '@kbn/core/public'; import type { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public'; @@ -74,7 +73,6 @@ export class DiscoverCustomizationExamplesPlugin implements Plugin { }} scopedHistory={appMountParams.history} customizationCallbacks={[this.customizationCallback]} - customizationContext={{ displayMode: 'standalone' }} /> @@ -102,18 +100,8 @@ export class DiscoverCustomizationExamplesPlugin implements Plugin { }); } - start(core: CoreStart, plugins: DiscoverCustomizationExamplesStartPlugins) { + start(_: CoreStart, plugins: DiscoverCustomizationExamplesStartPlugins) { this.customizationCallback = ({ customizations, stateContainer }) => { - customizations.set({ - id: 'top_nav', - defaultMenu: { - newItem: { disabled: true }, - openItem: { disabled: true }, - alertsItem: { disabled: true }, - inspectItem: { disabled: true }, - }, - }); - customizations.set({ id: 'search_bar', CustomDataViewPicker: () => { @@ -280,28 +268,6 @@ export class DiscoverCustomizationExamplesPlugin implements Plugin { }, }); - customizations.set({ - id: 'flyout', - size: 650, - title: 'Example custom flyout', - actions: { - getActionItems: () => - Array.from({ length: 5 }, (_, i) => { - const index = i + 1; - return { - id: `action-item-${index}`, - enabled: true, - label: `Action ${index}`, - iconType: ['faceHappy', 'faceNeutral', 'faceSad', 'infinity', 'bell'].at( - i - ) as IconType, - dataTestSubj: `customActionItem${index}`, - onClick: () => alert(index), - }; - }), - }, - }); - return () => { // eslint-disable-next-line no-console console.log('Cleaning up Logs explorer customizations'); diff --git a/src/platform/plugins/shared/discover/public/application/main/components/layout/discover_documents.test.tsx b/src/platform/plugins/shared/discover/public/application/main/components/layout/discover_documents.test.tsx index d2fb4d5e4e150..7cdea36ac36e2 100644 --- a/src/platform/plugins/shared/discover/public/application/main/components/layout/discover_documents.test.tsx +++ b/src/platform/plugins/shared/discover/public/application/main/components/layout/discover_documents.test.tsx @@ -21,7 +21,6 @@ import { buildDataTableRecord } from '@kbn/discover-utils'; import type { EsHitRecord } from '@kbn/discover-utils/types'; import { getDiscoverStateMock } from '../../../../__mocks__/discover_state.mock'; import type { DiscoverAppState } from '../../state_management/redux'; -import type { DiscoverCustomization } from '../../../../customizations'; import { createCustomizationService } from '../../../../customizations/customization_service'; import { DiscoverGrid } from '../../../../components/discover_grid'; import { createDataViewDataSource } from '../../../../../common/data_sources'; @@ -152,36 +151,13 @@ describe('Discover documents layout', () => { expect(container.getCurrentTab().appState.grid?.columns?.someField.width).toEqual(206); }); - test('should render customisations', async () => { - const customization: DiscoverCustomization = { - id: 'data_table', - logsEnabled: true, - rowAdditionalLeadingControls: [], - }; - - customisationService.set(customization); - const component = await mountComponent(FetchStatus.COMPLETE, esHitsMock); - const discoverGridComponent = component.find(DiscoverGrid); - expect(discoverGridComponent.exists()).toBeTruthy(); - - expect(discoverGridComponent.prop('rowAdditionalLeadingControls')).toBe( - customization.rowAdditionalLeadingControls - ); - expect(discoverGridComponent.prop('externalCustomRenderers')).toBeDefined(); - }); - describe('context awareness', () => { it('should pass cell renderers from profile', async () => { - customisationService.set({ - id: 'data_table', - logsEnabled: true, - }); await discoverServiceMock.profilesManager.resolveRootProfile({ solutionNavId: 'test' }); const component = await mountComponent(FetchStatus.COMPLETE, esHitsMock); const discoverGridComponent = component.find(DiscoverGrid); expect(discoverGridComponent.exists()).toBeTruthy(); expect(Object.keys(discoverGridComponent.prop('externalCustomRenderers')!)).toEqual([ - '_source', 'rootProfile', ]); }); diff --git a/src/platform/plugins/shared/discover/public/application/main/components/layout/discover_documents.tsx b/src/platform/plugins/shared/discover/public/application/main/components/layout/discover_documents.tsx index 1f8d7cdf0ba93..3a30230d74166 100644 --- a/src/platform/plugins/shared/discover/public/application/main/components/layout/discover_documents.tsx +++ b/src/platform/plugins/shared/discover/public/application/main/components/layout/discover_documents.tsx @@ -66,9 +66,7 @@ import { } from '../../../../utils/get_allowed_sample_size'; import { useFetchMoreRecords } from './use_fetch_more_records'; import { SelectedVSAvailableCallout } from './selected_vs_available_callout'; -import { useDiscoverCustomization } from '../../../../customizations'; import { onResizeGridColumn } from '../../../../utils/on_resize_grid_column'; -import { useContextualGridCustomisations } from '../../hooks/grid_customisations'; import { useIsEsqlMode } from '../../hooks/use_is_esql_mode'; import type { CellRenderersExtensionParams, @@ -457,14 +455,11 @@ function DiscoverDocumentsComponent({ [onAddFilter, dataView, cellRendererDensity, cellRendererRowHeight] ); - const { rowAdditionalLeadingControls } = useDiscoverCustomization('data_table') || {}; - const { customCellRenderer } = useContextualGridCustomisations(cellRendererParams) || {}; - const getCellRenderersAccessor = useProfileAccessor('getCellRenderers'); const cellRenderers = useMemo(() => { - const getCellRenderers = getCellRenderersAccessor(() => customCellRenderer ?? {}); + const getCellRenderers = getCellRenderersAccessor(() => ({})); return getCellRenderers(cellRendererParams); - }, [cellRendererParams, customCellRenderer, getCellRenderersAccessor]); + }, [cellRendererParams, getCellRenderersAccessor]); const documents = useObservable(stateContainer.dataState.data$.documents$); @@ -580,7 +575,6 @@ function DiscoverDocumentsComponent({ totalHits={totalHits} onFetchMoreRecords={onFetchMoreRecords} externalCustomRenderers={cellRenderers} - rowAdditionalLeadingControls={rowAdditionalLeadingControls} dataGridDensityState={density} onUpdateDataGridDensity={onUpdateDensity} onUpdateESQLQuery={onUpdateESQLQuery} diff --git a/src/platform/plugins/shared/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx b/src/platform/plugins/shared/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx index 27ee96ab532b2..a7bbe2ef1d64d 100644 --- a/src/platform/plugins/shared/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx +++ b/src/platform/plugins/shared/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx @@ -32,7 +32,7 @@ import type { AggregateQuery, Query } from '@kbn/es-query'; import { buildDataTableRecord } from '@kbn/discover-utils'; import type { DataTableRecord } from '@kbn/discover-utils/types'; import type { DiscoverCustomizationId } from '../../../../customizations/customization_service'; -import type { FieldListCustomization, SearchBarCustomization } from '../../../../customizations'; +import type { SearchBarCustomization } from '../../../../customizations'; import { DiscoverTestProvider } from '../../../../__mocks__/test_provider'; import type { DataView } from '@kbn/data-views-plugin/common'; import type { UnifiedFieldListRestorableState } from '@kbn/unified-field-list'; @@ -47,11 +47,6 @@ const mockSearchBarCustomization: SearchBarCustomization = { .mockName('CustomDataViewPickerMock'), }; -const mockFieldListCustomisation: FieldListCustomization = { - id: 'field_list', - logsFieldsEnabled: true, -}; - let mockUseCustomizations = false; jest.mock('../../../../customizations', () => ({ @@ -64,8 +59,6 @@ jest.mock('../../../../customizations', () => ({ switch (id) { case 'search_bar': return mockSearchBarCustomization; - case 'field_list': - return mockFieldListCustomisation; default: throw new Error(`Unknown customization id: ${id}`); } diff --git a/src/platform/plugins/shared/discover/public/application/main/components/top_nav/discover_topnav.test.tsx b/src/platform/plugins/shared/discover/public/application/main/components/top_nav/discover_topnav.test.tsx index bb29f3cb6df3d..2909e4647edae 100644 --- a/src/platform/plugins/shared/discover/public/application/main/components/top_nav/discover_topnav.test.tsx +++ b/src/platform/plugins/shared/discover/public/application/main/components/top_nav/discover_topnav.test.tsx @@ -14,10 +14,9 @@ import { mountWithIntl } from '@kbn/test-jest-helpers'; import { dataViewMock } from '@kbn/discover-utils/src/__mocks__'; import type { DiscoverTopNavProps } from './discover_topnav'; import { DiscoverTopNav } from './discover_topnav'; -import { sharePluginMock } from '@kbn/share-plugin/public/mocks'; import { discoverServiceMock as mockDiscoverService } from '../../../../__mocks__/services'; import { getDiscoverStateMock } from '../../../../__mocks__/discover_state.mock'; -import type { SearchBarCustomization, TopNavCustomization } from '../../../../customizations'; +import type { SearchBarCustomization } from '../../../../customizations'; import type { DiscoverCustomizationId } from '../../../../customizations/customization_service'; import { useDiscoverCustomization } from '../../../../customizations'; import { useKibana } from '@kbn/kibana-react-plugin/public'; @@ -34,10 +33,6 @@ jest.mock('@kbn/kibana-react-plugin/public', () => ({ const MockCustomSearchBar: typeof mockDiscoverService.navigation.ui.AggregateQueryTopNavMenu = () =>
; -const mockTopNavCustomization: TopNavCustomization = { - id: 'top_nav', -}; - const mockSearchBarCustomization: SearchBarCustomization = { id: 'search_bar', CustomDataViewPicker: jest.fn(() =>
), @@ -113,7 +108,6 @@ const getTestComponent = (props: DiscoverTopNavProps) => describe('Discover topnav component', () => { beforeEach(() => { - mockTopNavCustomization.defaultMenu = undefined; mockUseCustomizations = false; capturedTopNavMenu = undefined; jest.clearAllMocks(); @@ -124,8 +118,6 @@ describe('Discover topnav component', () => { } switch (id) { - case 'top_nav': - return mockTopNavCustomization; case 'search_bar': return mockSearchBarCustomization; default: @@ -160,83 +152,6 @@ describe('Discover topnav component', () => { expect(capturedTopNavMenu?.primaryActionItem).toBeUndefined(); }); - describe('top nav customization', () => { - it('should allow disabling default menu items', async () => { - mockUseCustomizations = true; - mockTopNavCustomization.defaultMenu = { - newItem: { disabled: true }, - openItem: { disabled: true }, - shareItem: { disabled: true }, - alertsItem: { disabled: true }, - inspectItem: { disabled: true }, - saveItem: { disabled: true }, - }; - const props = getProps(); - await act(async () => { - getTestComponent(props); - }); - - const itemIds = capturedTopNavMenu?.items?.map((item) => item.id) || []; - expect(itemIds).toEqual([]); - }); - - describe('share service available', () => { - let availableIntegrationsSpy: jest.SpyInstance; - - beforeAll(() => { - mockDiscoverService.share = sharePluginMock.createStartContract(); - }); - - afterAll(() => { - mockDiscoverService.share = undefined; - }); - - beforeEach(() => { - (availableIntegrationsSpy = jest.spyOn( - mockDiscoverService.share!, - 'availableIntegrations' - )).mockImplementation(() => []); - }); - - it('will include share menu item if the share service is available', async () => { - const props = getProps(); - await act(async () => { - getTestComponent(props); - }); - - const itemIds = capturedTopNavMenu?.items?.map((item) => item.id) || []; - expect(itemIds).toEqual(['inspect', 'new', 'open', 'share']); - expect(capturedTopNavMenu?.primaryActionItem?.id).toBe('save'); - }); - - it('will include export menu item if there are export integrations available', async () => { - availableIntegrationsSpy.mockImplementation((_objectType, groupId) => { - if (groupId === 'export') { - return [ - { - id: 'export', - shareType: 'integration', - groupId: 'export', - config: () => Promise.resolve({}), - }, - ]; - } - - return []; - }); - - const props = getProps(); - await act(async () => { - getTestComponent(props); - }); - - const itemIds = capturedTopNavMenu?.items?.map((item) => item.id) || []; - expect(itemIds).toEqual(['inspect', 'new', 'open', 'export', 'share']); - expect(capturedTopNavMenu?.primaryActionItem?.id).toBe('save'); - }); - }); - }); - describe('search bar customization', () => { it('should render custom Search Bar', async () => { (useDiscoverCustomization as jest.Mock).mockImplementation((id: DiscoverCustomizationId) => { diff --git a/src/platform/plugins/shared/discover/public/application/main/components/top_nav/use_discover_topnav.ts b/src/platform/plugins/shared/discover/public/application/main/components/top_nav/use_discover_topnav.ts index f43ed87feb7bf..4bd967a14b3af 100644 --- a/src/platform/plugins/shared/discover/public/application/main/components/top_nav/use_discover_topnav.ts +++ b/src/platform/plugins/shared/discover/public/application/main/components/top_nav/use_discover_topnav.ts @@ -10,7 +10,6 @@ import { useMemo } from 'react'; import type { DiscoverSession } from '@kbn/saved-search-plugin/common'; import { useIsWithinBreakpoints } from '@elastic/eui'; -import { useDiscoverCustomization } from '../../../../customizations'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { useInspector } from '../../hooks/use_inspector'; import { useIsEsqlMode } from '../../hooks/use_is_esql_mode'; @@ -32,7 +31,6 @@ export const useDiscoverTopNav = ({ persistedDiscoverSession: DiscoverSession | undefined; }) => { const services = useDiscoverServices(); - const topNavCustomization = useDiscoverCustomization('top_nav'); const hasUnsavedChanges = useInternalStateSelector((state) => state.hasUnsavedChanges); const isMobile = useIsWithinBreakpoints(['xs']); @@ -63,7 +61,6 @@ export const useDiscoverTopNav = ({ hasUnsavedChanges, isEsqlMode, adHocDataViews, - topNavCustomization, hasShareIntegration, persistedDiscoverSession, }); diff --git a/src/platform/plugins/shared/discover/public/application/main/components/top_nav/use_top_nav_links.test.tsx b/src/platform/plugins/shared/discover/public/application/main/components/top_nav/use_top_nav_links.test.tsx index 4a533aa0e3153..f319a850f39d8 100644 --- a/src/platform/plugins/shared/discover/public/application/main/components/top_nav/use_top_nav_links.test.tsx +++ b/src/platform/plugins/shared/discover/public/application/main/components/top_nav/use_top_nav_links.test.tsx @@ -74,7 +74,6 @@ describe('useTopNavLinks', () => { hasUnsavedChanges: false, isEsqlMode: false, adHocDataViews: [], - topNavCustomization: undefined, hasShareIntegration, persistedDiscoverSession: undefined, ...hookAttrs, @@ -173,7 +172,6 @@ describe('useTopNavLinks', () => { hasUnsavedChanges: false, isEsqlMode: false, adHocDataViews: [], - topNavCustomization: undefined, hasShareIntegration: true, persistedDiscoverSession: undefined, }), diff --git a/src/platform/plugins/shared/discover/public/application/main/components/top_nav/use_top_nav_links.tsx b/src/platform/plugins/shared/discover/public/application/main/components/top_nav/use_top_nav_links.tsx index 7119d2fa07172..dc74310bfdc63 100644 --- a/src/platform/plugins/shared/discover/public/application/main/components/top_nav/use_top_nav_links.tsx +++ b/src/platform/plugins/shared/discover/public/application/main/components/top_nav/use_top_nav_links.tsx @@ -36,7 +36,6 @@ import { getBackgroundSearchFlyout, enhanceAppMenuItemWithRunAction, } from './app_menu_actions'; -import type { TopNavCustomization } from '../../../../customizations'; import { useProfileAccessor } from '../../../../context_awareness'; import { internalStateActions, @@ -60,7 +59,6 @@ export const useTopNavLinks = ({ hasUnsavedChanges, isEsqlMode, adHocDataViews, - topNavCustomization, hasShareIntegration, persistedDiscoverSession, }: { @@ -71,7 +69,6 @@ export const useTopNavLinks = ({ hasUnsavedChanges: boolean; isEsqlMode: boolean; adHocDataViews: DataView[]; - topNavCustomization: TopNavCustomization | undefined; hasShareIntegration: boolean; persistedDiscoverSession: DiscoverSession | undefined; }): AppMenuConfig => { @@ -111,20 +108,13 @@ export const useTopNavLinks = ({ [isEsqlMode, dataView, adHocDataViews, dispatch, authorizedRuleTypes] ); - const defaultMenu = topNavCustomization?.defaultMenu; - const appMenuItems: DiscoverAppMenuItemType[] = useMemo(() => { const items: DiscoverAppMenuItemType[] = []; - if (!defaultMenu?.inspectItem?.disabled) { - const inspectAppMenuItem = getInspectAppMenuItem({ onOpenInspector }); - items.push(inspectAppMenuItem); - } - if ( - services.triggersActionsUi && - !defaultMenu?.alertsItem?.disabled && - discoverParams.authorizedRuleTypeIds.length - ) { + const inspectAppMenuItem = getInspectAppMenuItem({ onOpenInspector }); + items.push(inspectAppMenuItem); + + if (services.triggersActionsUi && discoverParams.authorizedRuleTypeIds.length) { const alertsAppMenuItem = getAlertsAppMenuItem({ discoverParams, services, @@ -153,7 +143,7 @@ export const useTopNavLinks = ({ items.push(backgroundSearchFlyoutMenuItem); } - if (!services.embeddableEditor.isEmbeddedEditor() && !defaultMenu?.newItem?.disabled) { + if (!services.embeddableEditor.isEmbeddedEditor()) { const defaultEsqlState: Pick | undefined = isEsqlMode && currentDataView.type === ESQL_TYPE ? { query: { esql: getInitialESQLQuery(currentDataView, true) } } @@ -177,7 +167,7 @@ export const useTopNavLinks = ({ items.push(newSearchMenuItem); } - if (!services.embeddableEditor.isEmbeddedEditor() && !defaultMenu?.openItem?.disabled) { + if (!services.embeddableEditor.isEmbeddedEditor()) { const openSearchMenuItem = getOpenSearchAppMenuItem({ onOpenSavedSearch: (discoverSessionId) => dispatch(internalStateActions.openDiscoverSession({ discoverSessionId })), @@ -185,24 +175,21 @@ export const useTopNavLinks = ({ items.push(openSearchMenuItem); } - if (!defaultMenu?.shareItem?.disabled) { - const shareAppMenuItem = getShareAppMenuItem({ - discoverParams, - services, - stateContainer: state, - hasIntegrations: hasShareIntegration, - hasUnsavedChanges, - currentTab, - persistedDiscoverSession, - totalHitsState, - intl, - }); - items.push(...shareAppMenuItem); - } + const shareAppMenuItem = getShareAppMenuItem({ + discoverParams, + services, + stateContainer: state, + hasIntegrations: hasShareIntegration, + hasUnsavedChanges, + currentTab, + persistedDiscoverSession, + totalHitsState, + intl, + }); + items.push(...shareAppMenuItem); return items; }, [ - defaultMenu, services, discoverParams, appId, @@ -252,7 +239,7 @@ export const useTopNavLinks = ({ }); } - if (services.capabilities.discover_v2.save && !defaultMenu?.saveItem?.disabled) { + if (services.capabilities.discover_v2.save) { const isEmbeddedEditor = services.embeddableEditor.isEmbeddedEditor(); newAppMenuRegistry.setPrimaryActionItem({ @@ -362,7 +349,6 @@ export const useTopNavLinks = ({ dataView, dispatch, state, - defaultMenu?.saveItem?.disabled, hasUnsavedChanges, transitionFromDataViewToESQL, ]); diff --git a/src/platform/plugins/shared/discover/public/application/main/hooks/grid_customisations/index.ts b/src/platform/plugins/shared/discover/public/application/main/hooks/grid_customisations/index.ts deleted file mode 100644 index 97b3f07478423..0000000000000 --- a/src/platform/plugins/shared/discover/public/application/main/hooks/grid_customisations/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { useMemo } from 'react'; -import { useDiscoverCustomization } from '../../../../customizations'; -import type { DataGridColumnsDeps } from './logs'; -import { getDataGridColumnsConfiguration } from './logs'; - -export * from './logs'; - -type ContextualGridCustomizationParams = DataGridColumnsDeps; - -export const useContextualGridCustomisations = (params: ContextualGridCustomizationParams) => { - // TODO / NOTE: This will eventually rely on Discover's context resolution to determine which fields - // are returned based on the data type. - const isLogsContext = useDiscoverCustomization('data_table')?.logsEnabled; - - const virtualColumnsConfiguration = useMemo(() => { - if (!isLogsContext) return null; - - return getDataGridColumnsConfiguration(params); - }, [isLogsContext, params]); - - return virtualColumnsConfiguration; -}; diff --git a/src/platform/plugins/shared/discover/public/application/main/hooks/grid_customisations/logs.tsx b/src/platform/plugins/shared/discover/public/application/main/hooks/grid_customisations/logs.tsx deleted file mode 100644 index c3c28340577f2..0000000000000 --- a/src/platform/plugins/shared/discover/public/application/main/hooks/grid_customisations/logs.tsx +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { SOURCE_COLUMN } from '@kbn/unified-data-table'; -import type { SummaryColumnGetterDeps } from '../../../../components/data_types/logs/summary_column'; -import { getSummaryColumn } from '../../../../components/data_types/logs/summary_column'; - -export type DataGridColumnsDeps = CustomCellRendererDeps; - -export const getDataGridColumnsConfiguration = (params: DataGridColumnsDeps) => { - return { - customCellRenderer: createCustomCellRenderer(params), - }; -}; - -type CustomCellRendererDeps = SummaryColumnGetterDeps; - -export const createCustomCellRenderer = (params: CustomCellRendererDeps) => { - return { - [SOURCE_COLUMN]: getSummaryColumn(params), - }; -}; diff --git a/src/platform/plugins/shared/discover/public/components/discover_container/discover_container.tsx b/src/platform/plugins/shared/discover/public/components/discover_container/discover_container.tsx index 4005d07f560bc..7e6859c0cacb9 100644 --- a/src/platform/plugins/shared/discover/public/components/discover_container/discover_container.tsx +++ b/src/platform/plugins/shared/discover/public/components/discover_container/discover_container.tsx @@ -30,7 +30,6 @@ export interface DiscoverContainerInternalProps { getDiscoverServices: () => Promise; scopedHistory: ScopedHistory; customizationCallbacks: CustomizationCallback[]; - customizationContext?: DiscoverCustomizationContext; stateStorageContainer?: IKbnUrlStateStorage; isLoading?: boolean; } @@ -46,13 +45,12 @@ const discoverContainerWrapperCss = css` } `; -const defaultCustomizationContext: DiscoverCustomizationContext = { displayMode: 'embedded' }; +const customizationContext: DiscoverCustomizationContext = { displayMode: 'embedded' }; export const DiscoverContainerInternal = ({ overrideServices, scopedHistory, customizationCallbacks, - customizationContext = defaultCustomizationContext, getDiscoverServices, stateStorageContainer, isLoading = false, diff --git a/src/platform/plugins/shared/discover/public/components/discover_grid_flyout/discover_grid_flyout.test.tsx b/src/platform/plugins/shared/discover/public/components/discover_grid_flyout/discover_grid_flyout.test.tsx index 43f766e3e9e02..0074b4f806452 100644 --- a/src/platform/plugins/shared/discover/public/components/discover_grid_flyout/discover_grid_flyout.test.tsx +++ b/src/platform/plugins/shared/discover/public/components/discover_grid_flyout/discover_grid_flyout.test.tsx @@ -7,8 +7,8 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ +import type { ComponentType } from 'react'; import React from 'react'; -import { EuiButtonIcon, EuiContextMenuItem, EuiPopover } from '@elastic/eui'; import { findTestSubject } from '@elastic/eui/lib/test'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import type { Query, AggregateQuery } from '@kbn/es-query'; @@ -24,35 +24,23 @@ import { act } from 'react-dom/test-utils'; import type { ReactWrapper } from 'enzyme'; import { setUnifiedDocViewerServices } from '@kbn/unified-doc-viewer-plugin/public/plugin'; import { mockUnifiedDocViewerServices } from '@kbn/unified-doc-viewer-plugin/public/__mocks__'; -import type { FlyoutCustomization } from '../../customizations'; -import { useDiscoverCustomization } from '../../customizations'; import { discoverServiceMock } from '../../__mocks__/services'; import { DiscoverTestProvider } from '../../__mocks__/test_provider'; +import type { UnifiedDocViewerFlyoutProps } from '@kbn/unified-doc-viewer-plugin/public'; -const mockFlyoutCustomization: FlyoutCustomization = { - id: 'flyout', - actions: {}, -}; - -jest.mock('../../customizations', () => ({ - ...jest.requireActual('../../customizations'), - useDiscoverCustomization: jest.fn(), -})); +let mockFlyoutCustomBody: ComponentType | undefined; -let mockBreakpointSize: string | null = null; - -jest.mock('@elastic/eui', () => { - const original = jest.requireActual('@elastic/eui'); +jest.mock('@kbn/unified-doc-viewer-plugin/public', () => { + const actual = jest.requireActual('@kbn/unified-doc-viewer-plugin/public'); + const OriginalFlyout = actual.UnifiedDocViewerFlyout; return { - ...original, - useIsWithinBreakpoints: jest.fn((breakpoints: string[]) => { - if (mockBreakpointSize && breakpoints.includes(mockBreakpointSize)) { - return true; - } - - return original.useIsWithinBreakpoints(breakpoints); - }), - useResizeObserver: jest.fn(() => ({ width: 1000, height: 1000 })), + ...actual, + UnifiedDocViewerFlyout: (props: UnifiedDocViewerFlyoutProps) => ( + + ), }; }); @@ -125,12 +113,8 @@ describe('Discover flyout', function () { }; beforeEach(() => { - mockFlyoutCustomization.actions.defaultActions = undefined; - mockFlyoutCustomization.Content = undefined; - mockFlyoutCustomization.title = undefined; + mockFlyoutCustomBody = undefined; jest.clearAllMocks(); - - (useDiscoverCustomization as jest.Mock).mockImplementation(() => mockFlyoutCustomization); }); it('should be rendered correctly using an data view without timefield', async () => { @@ -241,10 +225,7 @@ describe('Discover flyout', function () { }); it('should not navigate with arrow keys through documents if an input is in focus', async () => { - mockFlyoutCustomization.Content = () => { - return ; - }; - + mockFlyoutCustomBody = () => ; const { component, props } = await mountComponent({}); findTestSubject(component, 'flyoutCustomInput').simulate('keydown', { key: 'ArrowRight', @@ -275,261 +256,47 @@ describe('Discover flyout', function () { ); }); - describe('with applied customizations', () => { - describe('when title is customized', () => { - it('should pass the custom title to EuiFlyout flyoutMenuProps', async () => { - const customTitle = 'Custom flyout title'; - mockFlyoutCustomization.title = customTitle; - - const { component } = await mountComponent({}); - - // TODO: check title text content directly after migrating the test to RTL https://github.com/elastic/kibana/issues/222939 - const flyout = component.find('EuiFlyout'); - const flyoutMenuProps = flyout.prop('flyoutMenuProps'); - expect(flyoutMenuProps).toEqual( - expect.objectContaining({ - title: customTitle, - hideTitle: false, - }) - ); - }); - }); - - describe('when actions are customized', () => { - it('should display actions added by getActionItems', async () => { - mockBreakpointSize = 'xl'; - mockFlyoutCustomization.actions = { - getActionItems: jest.fn(() => [ - { - id: 'action-item-1', - enabled: true, - label: 'Action 1', - iconType: 'document', - dataTestSubj: 'customActionItem1', - onClick: jest.fn(), - }, - { - id: 'action-item-2', - enabled: true, - label: 'Action 2', - iconType: 'document', - dataTestSubj: 'customActionItem2', - onClick: jest.fn(), - }, - { - id: 'action-item-3', - enabled: false, - label: 'Action 3', - iconType: 'document', - dataTestSubj: 'customActionItem3', - onClick: jest.fn(), - }, - ]), - }; - - const { component } = await mountComponent({}); - - const action1 = findTestSubject(component, 'customActionItem1'); - const action2 = findTestSubject(component, 'customActionItem2'); - - expect(action1.text()).toBe('Action 1'); - expect(action2.text()).toBe('Action 2'); - expect(findTestSubject(component, 'customActionItem3').exists()).toBe(false); - mockBreakpointSize = null; - }); - - it('should display multiple actions added by getActionItems', async () => { - mockFlyoutCustomization.actions = { - getActionItems: jest.fn(() => - Array.from({ length: 5 }, (_, i) => ({ - id: `action-item-${i}`, - enabled: true, - label: `Action ${i}`, - iconType: 'document', - dataTestSubj: `customActionItem${i}`, - onClick: jest.fn(), - })) - ), - }; - - const { component } = await mountComponent({}); - expect( - findTestSubject(component, 'docViewerFlyoutActions') - .find(EuiButtonIcon) - .map((button) => button.prop('data-test-subj')) - ).toEqual([ - 'docTableRowAction', - 'customActionItem0', - 'customActionItem1', - 'docViewerMoreFlyoutActionsButton', - ]); - - act(() => { - findTestSubject(component, 'docViewerMoreFlyoutActionsButton').simulate('click'); - }); - - component.update(); - - expect( - component - .find(EuiPopover) - .find(EuiContextMenuItem) - .map((button) => button.prop('data-test-subj')) - ).toEqual(['customActionItem2', 'customActionItem3', 'customActionItem4']); - }); - - it('should display multiple actions added by getActionItems in mobile view', async () => { - mockBreakpointSize = 's'; - - mockFlyoutCustomization.actions = { - getActionItems: jest.fn(() => - Array.from({ length: 3 }, (_, i) => ({ - id: `action-item-${i}`, - enabled: true, - label: `Action ${i}`, - iconType: 'document', - dataTestSubj: `customActionItem${i}`, - onClick: jest.fn(), - })) - ), - }; - - const { component } = await mountComponent({}); - expect(findTestSubject(component, 'docViewerFlyoutActions').length).toBe(0); - - act(() => { - findTestSubject(component, 'docViewerMobileActionsButton').simulate('click'); - }); - - component.update(); - - expect( - component - .find(EuiPopover) - .find(EuiContextMenuItem) - .map((button) => button.prop('data-test-subj')) - ).toEqual([ - 'docTableRowAction', - 'customActionItem0', - 'customActionItem1', - 'customActionItem2', - ]); - - mockBreakpointSize = null; - }); - - it('should allow disabling default actions', async () => { - mockFlyoutCustomization.actions = { - defaultActions: { - viewSingleDocument: { disabled: true }, - viewSurroundingDocument: { disabled: true }, - }, - }; - - const { component } = await mountComponent({}); - - const singleDocumentView = findTestSubject(component, 'docTableRowAction'); - expect(singleDocumentView.length).toBeFalsy(); - }); - }); - - describe('when content is customized', () => { - it('should display the component passed to the Content customization', async () => { - mockFlyoutCustomization.Content = () => ( - Custom content - ); - - const { component } = await mountComponent({}); - - const customContent = findTestSubject(component, 'flyoutCustomContent'); - - expect(customContent.text()).toBe('Custom content'); - }); - - it('should provide a doc property to display details about the current document overview', async () => { - mockFlyoutCustomization.Content = ({ doc }) => { - return ( - {doc.flattened.message as string} - ); - }; - - const { component } = await mountComponent({}); - - const customContent = findTestSubject(component, 'flyoutCustomContent'); - - expect(customContent.text()).toBe('test1'); + describe('context awareness', () => { + it('should render flyout per the defined document profile', async () => { + const services = getServices(); + const hits = [ + { + _index: 'new', + _id: '1', + _score: 1, + _type: '_doc', + _source: { date: '2020-20-01T12:12:12.123', message: 'test1', bytes: 20 }, + }, + { + _index: 'new', + _id: '2', + _score: 1, + _type: '_doc', + _source: { date: '2020-20-01T12:12:12.124', name: 'test2', extension: 'jpg' }, + }, + ]; + const scopedProfilesManager = services.profilesManager.createScopedProfilesManager({ + scopedEbtManager: services.ebtManager.createScopedEBTManager(), }); - - it('should provide an actions prop collection to optionally update the grid content', async () => { - mockFlyoutCustomization.Content = ({ actions }) => ( - <> -