diff --git a/x-pack/plugins/lens/public/react_embeddable/data_loader.ts b/x-pack/plugins/lens/public/react_embeddable/data_loader.ts index 0aed3edf70b8..64b7ca4501b0 100644 --- a/x-pack/plugins/lens/public/react_embeddable/data_loader.ts +++ b/x-pack/plugins/lens/public/react_embeddable/data_loader.ts @@ -226,7 +226,7 @@ export function loadEmbeddableData( handleEvent, disableTriggers, updateBlockingErrors, - renderCount: internalApi.renderCount$.getValue(), + getDisplayOptions: internalApi.getDisplayOptions, }), getUsedDataViews( currentState.attributes.references, diff --git a/x-pack/plugins/lens/public/react_embeddable/expressions/expression_params.ts b/x-pack/plugins/lens/public/react_embeddable/expressions/expression_params.ts index e10dded4ad8f..ff6206f3f70e 100644 --- a/x-pack/plugins/lens/public/react_embeddable/expressions/expression_params.ts +++ b/x-pack/plugins/lens/public/react_embeddable/expressions/expression_params.ts @@ -24,6 +24,7 @@ import { IndexPatternMap, IndexPatternRef, UserMessage, + VisualizationDisplayOptions, isLensFilterEvent, isLensMultiFilterEvent, isLensTableRowContextMenuClickEvent, @@ -61,7 +62,7 @@ interface GetExpressionRendererPropsParams { api: LensApi; addUserMessages: (messages: UserMessage[]) => void; updateBlockingErrors: (error: Error) => void; - renderCount: number; + getDisplayOptions: () => VisualizationDisplayOptions; } async function getExpressionFromDocument( @@ -146,7 +147,7 @@ export async function getExpressionRendererParams( addUserMessages, updateBlockingErrors, searchContext, - renderCount, + getDisplayOptions, }: GetExpressionRendererPropsParams ): Promise<{ params: ExpressionWrapperProps | null; @@ -215,7 +216,7 @@ export async function getExpressionRendererParams( variables: getVariables(api, state), style: state.style, className: state.className, - noPadding: state.noPadding, + noPadding: getDisplayOptions().noPadding, }; return { indexPatterns, diff --git a/x-pack/plugins/lens/public/react_embeddable/initializers/initialize_dashboard_services.ts b/x-pack/plugins/lens/public/react_embeddable/initializers/initialize_dashboard_services.ts index d030a92a02b5..bf203f5faf32 100644 --- a/x-pack/plugins/lens/public/react_embeddable/initializers/initialize_dashboard_services.ts +++ b/x-pack/plugins/lens/public/react_embeddable/initializers/initialize_dashboard_services.ts @@ -142,7 +142,7 @@ export function initializeDashboardServices( }, }, serialize: () => { - const { style, noPadding, className } = apiHasLensComponentProps(parentApi) + const { style, className } = apiHasLensComponentProps(parentApi) ? parentApi : ({} as LensComponentProps); const settings = apiPublishesSettings(parentApi) @@ -155,7 +155,6 @@ export function initializeDashboardServices( return { ...serializeTitles(), style, - noPadding, className, ...settings, palette: initialState.palette, diff --git a/x-pack/plugins/lens/public/react_embeddable/initializers/initialize_internal_api.ts b/x-pack/plugins/lens/public/react_embeddable/initializers/initialize_internal_api.ts index 2bdc00b3124a..e366c24a6c0e 100644 --- a/x-pack/plugins/lens/public/react_embeddable/initializers/initialize_internal_api.ts +++ b/x-pack/plugins/lens/public/react_embeddable/initializers/initialize_internal_api.ts @@ -6,21 +6,25 @@ */ import { BehaviorSubject } from 'rxjs'; +import { initializeTitles } from '@kbn/presentation-publishing'; import type { DataView } from '@kbn/data-views-plugin/common'; import { buildObservableVariable, createEmptyLensState } from '../helper'; import type { ExpressionWrapperProps, + LensEmbeddableStartServices, LensInternalApi, LensOverrides, LensRuntimeState, } from '../types'; -import { apiHasAbortController } from '../type_guards'; +import { apiHasAbortController, apiHasLensComponentProps } from '../type_guards'; import type { UserMessage } from '../../types'; export function initializeInternalApi( initialState: LensRuntimeState, - parentApi: unknown + parentApi: unknown, + { visualizationMap }: LensEmbeddableStartServices ): LensInternalApi { + const { titlesApi } = initializeTitles(initialState); const [hasRenderCompleted$] = buildObservableVariable(false); const [expressionParams$] = buildObservableVariable(null); const expressionAbortController$ = new BehaviorSubject(undefined); @@ -87,5 +91,30 @@ export function initializeInternalApi( validationMessages$.next([]); }, setAsCreated: () => isNewlyCreated$.next(false), + getDisplayOptions: () => { + const latestAttributes = attributes$.getValue(); + if (!latestAttributes.visualizationType) { + return {}; + } + + let displayOptions = + visualizationMap[latestAttributes.visualizationType]?.getDisplayOptions?.() ?? {}; + + if (apiHasLensComponentProps(parentApi) && parentApi.noPadding != null) { + displayOptions = { + ...displayOptions, + noPadding: parentApi.noPadding, + }; + } + + if (displayOptions.noPanelTitle == null && titlesApi.hidePanelTitle?.getValue()) { + displayOptions = { + ...displayOptions, + noPanelTitle: true, + }; + } + + return displayOptions; + }, }; } diff --git a/x-pack/plugins/lens/public/react_embeddable/lens_embeddable.tsx b/x-pack/plugins/lens/public/react_embeddable/lens_embeddable.tsx index 8c17063f97a2..074ae451115b 100644 --- a/x-pack/plugins/lens/public/react_embeddable/lens_embeddable.tsx +++ b/x-pack/plugins/lens/public/react_embeddable/lens_embeddable.tsx @@ -59,7 +59,7 @@ export const createLensEmbeddableFactory = ( * Observables and functions declared here are used internally to store mutating state values * This is an internal API not exposed outside of the embeddable. */ - const internalApi = initializeInternalApi(initialState, parentApi); + const internalApi = initializeInternalApi(initialState, parentApi, services); const visualizationContextHelper = initializeVisualizationContext(internalApi); diff --git a/x-pack/plugins/lens/public/react_embeddable/mocks/index.tsx b/x-pack/plugins/lens/public/react_embeddable/mocks/index.tsx index 0b64b84f7a74..ddcd5e608959 100644 --- a/x-pack/plugins/lens/public/react_embeddable/mocks/index.tsx +++ b/x-pack/plugins/lens/public/react_embeddable/mocks/index.tsx @@ -309,6 +309,7 @@ const LensInternalApiMock: LensInternalApi = { dispatchError: jest.fn(), updateValidationMessages: jest.fn(), setAsCreated: jest.fn(), + getDisplayOptions: jest.fn(() => ({})), }; export function getLensInternalApiMock(overrides: Partial = {}): LensInternalApi { diff --git a/x-pack/plugins/lens/public/react_embeddable/renderer/lens_embeddable_component.test.tsx b/x-pack/plugins/lens/public/react_embeddable/renderer/lens_embeddable_component.test.tsx index 04c3511ab3d4..f444f429250b 100644 --- a/x-pack/plugins/lens/public/react_embeddable/renderer/lens_embeddable_component.test.tsx +++ b/x-pack/plugins/lens/public/react_embeddable/renderer/lens_embeddable_component.test.tsx @@ -13,6 +13,12 @@ import { PublishingSubject } from '@kbn/presentation-publishing'; import React from 'react'; import { LensEmbeddableComponent } from './lens_embeddable_component'; +jest.mock('../expression_wrapper', () => ({ + ExpressionWrapper: () => ( +
+ ), +})); + type GetValueType = Type extends PublishingSubject ? X : never; function getDefaultProps({ @@ -39,4 +45,17 @@ describe('Lens Embeddable component', () => { render(); expect(screen.queryByTestId('lens-embeddable')).not.toBeInTheDocument(); }); + + it('shoud not render the title if the visualization forces the title to be hidden', () => { + const getDisplayOptions = jest.fn(() => ({ noPanelTitle: true })); + const props = getDefaultProps({ + internalApiOverrides: { + getDisplayOptions, + }, + }); + + render(); + expect(props.internalApi.getDisplayOptions).toHaveBeenCalled(); + expect(screen.getByTestId('lens-embeddable').parentElement).not.toHaveAttribute('data-title'); + }); }); diff --git a/x-pack/plugins/lens/public/react_embeddable/renderer/lens_embeddable_component.tsx b/x-pack/plugins/lens/public/react_embeddable/renderer/lens_embeddable_component.tsx index d4ae4516ee93..122891788a80 100644 --- a/x-pack/plugins/lens/public/react_embeddable/renderer/lens_embeddable_component.tsx +++ b/x-pack/plugins/lens/public/react_embeddable/renderer/lens_embeddable_component.tsx @@ -57,7 +57,7 @@ export function LensEmbeddableComponent({ const rootRef = useDispatcher(hasRendered, api); // Publish the data attributes only if avaialble/visible - const title = api.hidePanelTitle?.getValue() + const title = internalApi.getDisplayOptions()?.noPanelTitle ? undefined : { 'data-title': api.panelTitle?.getValue() ?? api.defaultPanelTitle?.getValue() }; const description = api.panelDescription?.getValue() diff --git a/x-pack/plugins/lens/public/react_embeddable/types.ts b/x-pack/plugins/lens/public/react_embeddable/types.ts index 6f01947d41bf..058affe7f8d2 100644 --- a/x-pack/plugins/lens/public/react_embeddable/types.ts +++ b/x-pack/plugins/lens/public/react_embeddable/types.ts @@ -81,6 +81,7 @@ import type { SharingSavedObjectProps, Simplify, UserMessage, + VisualizationDisplayOptions, VisualizationMap, } from '../types'; import type { LensPluginStartDependencies } from '../plugin'; @@ -276,7 +277,7 @@ export type LensSerializedState = Simplify< LensUnifiedSearchContext & LensPanelProps & SerializedTitles & - LensSharedProps & + Omit & Partial & { isNewPanel?: boolean } >; @@ -414,6 +415,7 @@ export type LensInternalApi = Simplify< validationMessages$: PublishingSubject; updateValidationMessages: (newMessages: UserMessage[]) => void; resetAllMessages: () => void; + getDisplayOptions: () => VisualizationDisplayOptions; } >;