[embeddable] remove EmbeddableInput type (#211949)

EmbeddableInput type is part of the legacy embeddable system. The legacy
embeddable system is being removed and as such, the EmbeddableInput type
is being removed.

---------

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Nathan Reese 2025-03-05 18:41:00 -07:00 committed by GitHub
parent e73fd1fd83
commit 04ee5fc4f3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 117 additions and 221 deletions

View file

@ -7,7 +7,6 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import { SavedObjectEmbeddableInput } from '@kbn/embeddable-plugin/common';
import type { Reference } from '@kbn/content-management-utils';
import type { GridData } from '../../server/content_management';
@ -33,5 +32,3 @@ export interface DashboardPanelState<PanelState = object> {
*/
references?: Reference[];
}
export type DashboardContainerByReferenceInput = SavedObjectEmbeddableInput;

View file

@ -9,11 +9,7 @@
export type { DashboardCapabilities } from './types';
export type {
DashboardPanelMap,
DashboardPanelState,
DashboardContainerByReferenceInput,
} from './dashboard_container/types';
export type { DashboardPanelMap, DashboardPanelState } from './dashboard_container/types';
export {
type InjectExtractDeps,

View file

@ -8,7 +8,6 @@
*/
import type { SavedObjectMigrationFn } from '@kbn/core/server';
import type { EmbeddableInput } from '@kbn/embeddable-plugin/common';
import type { SavedDashboardPanel } from '../schema';
import {
@ -36,14 +35,14 @@ export const migrateExplicitlyHiddenTitles: SavedObjectMigrationFn<any, any> = (
const newPanels: SavedDashboardPanel[] = [];
panels.forEach((panel) => {
// Convert each panel into the dashboard panel state
const originalPanelState = convertSavedDashboardPanelToPanelState<EmbeddableInput>(panel);
const originalPanelState = convertSavedDashboardPanelToPanelState(panel);
newPanels.push(
convertPanelStateToSavedDashboardPanel(panel.panelIndex, {
...originalPanelState,
explicitInput: {
...originalPanelState.explicitInput,
...(originalPanelState.explicitInput.title === '' &&
!originalPanelState.explicitInput.hidePanelTitles
...((originalPanelState.explicitInput as { title?: string }).title === '' &&
!(originalPanelState.explicitInput as { hidePanelTitles?: boolean }).hidePanelTitles
? { hidePanelTitles: true }
: {}),
},

View file

@ -8,11 +8,8 @@
*/
export type {
EmbeddableInput,
CommonEmbeddableStartContract,
EmbeddableStateWithType,
EmbeddablePersistableStateService,
EmbeddableRegistryDefinition,
} from './types';
export type { SavedObjectEmbeddableInput } from './lib';
export { isSavedObjectEmbeddableInput } from './lib';

View file

@ -12,5 +12,3 @@ export { getInjectFunction } from './inject';
export type { MigrateFunction } from './migrate';
export { getMigrateFunction } from './migrate';
export { getTelemetryFunction } from './telemetry';
export type { SavedObjectEmbeddableInput } from './saved_object_embeddable';
export { isSavedObjectEmbeddableInput } from './saved_object_embeddable';

View file

@ -1,20 +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 { EmbeddableInput } from '../types';
export interface SavedObjectEmbeddableInput extends EmbeddableInput {
savedObjectId: string;
}
export function isSavedObjectEmbeddableInput(
input: EmbeddableInput | SavedObjectEmbeddableInput
): input is SavedObjectEmbeddableInput {
return Boolean((input as SavedObjectEmbeddableInput).savedObjectId);
}

View file

@ -8,65 +8,12 @@
*/
import type { SerializableRecord } from '@kbn/utility-types';
import type { KibanaExecutionContext } from '@kbn/core/public';
import type {
PersistableStateService,
PersistableState,
PersistableStateDefinition,
} from '@kbn/kibana-utils-plugin/common';
export type EmbeddableInput = {
version?: string;
viewMode?: 'view' | 'edit' | 'print' | 'preview';
title?: string;
description?: string;
/**
* Note this is not a saved object id. It is used to uniquely identify this
* Embeddable instance from others (e.g. inside a container). It's possible to
* have two Embeddables where everything else is the same but the id.
*/
id: string;
lastReloadRequestTime?: number;
hidePanelTitles?: boolean;
/**
* Reserved key for enhancements added by other plugins.
*/
enhancements?: SerializableRecord;
/**
* List of action IDs that this embeddable should not render.
*/
disabledActions?: string[];
/**
* Whether this embeddable should not execute triggers.
*/
disableTriggers?: boolean;
/**
* Search session id to group searches
*/
searchSessionId?: string;
/**
* Flag whether colors should be synced with other panels
*/
syncColors?: boolean;
/**
* Flag whether cursor should be synced with other panels on hover
*/
syncCursor?: boolean;
/**
* Flag whether tooltips should be synced with other panels on hover
*/
syncTooltips?: boolean;
executionContext?: KibanaExecutionContext;
};
export type EmbeddableStateWithType = {
enhancements?: SerializableRecord;
type: string;

View file

@ -16,12 +16,12 @@ import {
SaveResult,
showSaveModal,
} from '@kbn/saved-objects-plugin/public';
import {
EmbeddableInput,
SavedObjectEmbeddableInput,
isSavedObjectEmbeddableInput,
} from '@kbn/embeddable-plugin/common';
import { getNotifications } from '../../services';
import {
VisualizeByReferenceInput,
VisualizeByValueInput,
VisualizeSavedObjectAttributes,
} from './visualize_embeddable';
/**
* The attribute service is a shared, generic service that embeddables can use to provide the functionality
@ -34,76 +34,57 @@ export const ATTRIBUTE_SERVICE_KEY = 'attributes';
export interface GenericAttributes {
title: string;
}
export interface AttributeServiceUnwrapResult<
SavedObjectAttributes extends GenericAttributes,
MetaInfo extends unknown = unknown
> {
attributes: SavedObjectAttributes;
metaInfo?: MetaInfo;
export interface AttributeServiceUnwrapResult {
attributes: VisualizeSavedObjectAttributes;
metaInfo?: unknown;
}
export interface AttributeServiceOptions<
SavedObjectAttributes extends GenericAttributes,
MetaInfo extends unknown = unknown
> {
export interface AttributeServiceOptions {
saveMethod: (
attributes: SavedObjectAttributes,
attributes: VisualizeSavedObjectAttributes,
savedObjectId?: string
) => Promise<{ id?: string } | { error: Error }>;
checkForDuplicateTitle: (props: OnSaveProps) => Promise<boolean>;
unwrapMethod?: (
savedObjectId: string
) => Promise<AttributeServiceUnwrapResult<SavedObjectAttributes, MetaInfo>>;
unwrapMethod?: (savedObjectId: string) => Promise<AttributeServiceUnwrapResult>;
}
export class AttributeService<
SavedObjectAttributes extends { title: string },
ValType extends EmbeddableInput & {
[ATTRIBUTE_SERVICE_KEY]: SavedObjectAttributes;
} = EmbeddableInput & { [ATTRIBUTE_SERVICE_KEY]: SavedObjectAttributes },
RefType extends SavedObjectEmbeddableInput = SavedObjectEmbeddableInput,
MetaInfo extends unknown = unknown
> {
constructor(
private type: string,
private options: AttributeServiceOptions<SavedObjectAttributes, MetaInfo>
) {}
export class AttributeService {
constructor(private type: string, private options: AttributeServiceOptions) {}
private async defaultUnwrapMethod(
input: RefType
): Promise<AttributeServiceUnwrapResult<SavedObjectAttributes, MetaInfo>> {
return Promise.resolve({ attributes: { ...(input as unknown as SavedObjectAttributes) } });
input: VisualizeByReferenceInput
): Promise<AttributeServiceUnwrapResult> {
return Promise.resolve({
attributes: { ...(input as unknown as VisualizeSavedObjectAttributes) },
});
}
public async unwrapAttributes(
input: RefType | ValType
): Promise<AttributeServiceUnwrapResult<SavedObjectAttributes, MetaInfo>> {
input: VisualizeByReferenceInput | VisualizeByValueInput
): Promise<AttributeServiceUnwrapResult> {
if (this.inputIsRefType(input)) {
return this.options.unwrapMethod
? await this.options.unwrapMethod(input.savedObjectId)
: await this.defaultUnwrapMethod(input);
}
return { attributes: (input as ValType)[ATTRIBUTE_SERVICE_KEY] };
return { attributes: (input as VisualizeByValueInput)[ATTRIBUTE_SERVICE_KEY] };
}
public async wrapAttributes(
newAttributes: SavedObjectAttributes,
newAttributes: VisualizeSavedObjectAttributes,
useRefType: boolean,
input?: ValType | RefType
): Promise<Omit<ValType | RefType, 'id'>> {
input?: VisualizeByValueInput | VisualizeByReferenceInput
): Promise<Omit<VisualizeByValueInput | VisualizeByReferenceInput, 'id'>> {
const originalInput = input ? input : {};
const savedObjectId =
input && this.inputIsRefType(input)
? (input as SavedObjectEmbeddableInput).savedObjectId
: undefined;
const savedObjectId = input && this.inputIsRefType(input) ? input.savedObjectId : undefined;
if (!useRefType) {
return { [ATTRIBUTE_SERVICE_KEY]: newAttributes } as ValType;
return { [ATTRIBUTE_SERVICE_KEY]: newAttributes } as VisualizeByValueInput;
}
try {
const savedItem = await this.options.saveMethod(newAttributes, savedObjectId);
if ('id' in savedItem) {
return { ...originalInput, savedObjectId: savedItem.id } as RefType;
return { ...originalInput, savedObjectId: savedItem.id } as VisualizeByReferenceInput;
}
return { ...originalInput } as RefType;
return { ...originalInput } as VisualizeByReferenceInput;
} catch (error) {
getNotifications().toasts.addDanger({
title: i18n.translate('visualizations.attributeService.saveToLibraryError', {
@ -118,13 +99,17 @@ export class AttributeService<
}
}
inputIsRefType = (input: ValType | RefType): input is RefType => {
return isSavedObjectEmbeddableInput(input);
inputIsRefType = (
input: VisualizeByValueInput | VisualizeByReferenceInput
): input is VisualizeByReferenceInput => {
return Boolean((input as VisualizeByReferenceInput).savedObjectId);
};
getInputAsValueType = async (input: ValType | RefType): Promise<ValType> => {
getInputAsValueType = async (
input: VisualizeByValueInput | VisualizeByReferenceInput
): Promise<VisualizeByValueInput> => {
if (!this.inputIsRefType(input)) {
return input as ValType;
return input as VisualizeByValueInput;
}
const { attributes } = await this.unwrapAttributes(input);
const { savedObjectId, ...originalInputToPropagate } = input;
@ -133,26 +118,26 @@ export class AttributeService<
...originalInputToPropagate,
// by value visualizations should not have default titles and/or descriptions
...{ attributes: omit(attributes, ['title', 'description']) },
} as unknown as ValType;
} as unknown as VisualizeByValueInput;
};
getInputAsRefType = async (
input: ValType | RefType,
input: VisualizeByValueInput | VisualizeByReferenceInput,
saveOptions?: { showSaveModal: boolean; saveModalTitle?: string } | { title: string }
): Promise<RefType> => {
): Promise<VisualizeByReferenceInput> => {
if (this.inputIsRefType(input)) {
return input;
}
return new Promise<RefType>((resolve, reject) => {
return new Promise<VisualizeByReferenceInput>((resolve, reject) => {
const onSave = async (props: OnSaveProps): Promise<SaveResult> => {
await this.options.checkForDuplicateTitle(props);
try {
const newAttributes = { ...(input as ValType)[ATTRIBUTE_SERVICE_KEY] };
const newAttributes = { ...(input as VisualizeByValueInput)[ATTRIBUTE_SERVICE_KEY] };
newAttributes.title = props.newTitle;
const wrappedInput = (await this.wrapAttributes(
newAttributes,
true
)) as unknown as RefType;
)) as unknown as VisualizeByReferenceInput;
// Remove unneeded attributes from the original input. Note that the original panel title
// is removed in favour of the new attributes title
const newInput = omit(input, [ATTRIBUTE_SERVICE_KEY, 'title']);
@ -173,7 +158,7 @@ export class AttributeService<
title={get(
saveOptions,
'saveModalTitle',
(input as ValType)[ATTRIBUTE_SERVICE_KEY].title
(input as VisualizeByValueInput)[ATTRIBUTE_SERVICE_KEY].title
)}
showCopyOnSave={false}
objectType={this.type}

View file

@ -12,9 +12,6 @@ import { Vis } from '../../types';
import type {
VisualizeInput,
VisualizeEmbeddable,
VisualizeByValueInput,
VisualizeByReferenceInput,
VisualizeSavedObjectAttributes,
VisualizeEmbeddableDeps,
} from './visualize_embeddable';
import { getHttp, getTimeFilter, getCapabilities } from '../../services';
@ -32,11 +29,7 @@ export const createVisEmbeddableFromObject =
async (
vis: Vis,
input: Partial<VisualizeInput> & { id: string },
attributeService?: AttributeService<
VisualizeSavedObjectAttributes,
VisualizeByValueInput,
VisualizeByReferenceInput
>
attributeService?: AttributeService
): Promise<VisualizeEmbeddable | ErrorEmbeddable> => {
try {
const visId = vis.id as string;

View file

@ -8,8 +8,8 @@
*/
import { KibanaExecutionContext } from '@kbn/core/types';
import { EmbeddableInput } from '@kbn/embeddable-plugin/common';
import { omitGenericEmbeddableInput, genericEmbeddableInputIsEqual } from './diff_embeddable_input';
import { EmbeddableInput } from './i_embeddable';
const getGenericEmbeddableState = (state?: Partial<EmbeddableInput>): EmbeddableInput => {
const defaultState: EmbeddableInput = {

View file

@ -9,7 +9,7 @@
import fastIsEqual from 'fast-deep-equal';
import { pick, omit } from 'lodash';
import type { EmbeddableInput } from '@kbn/embeddable-plugin/common';
import { EmbeddableInput } from './i_embeddable';
// list out the keys from the EmbeddableInput type to allow lodash to pick them later
const allGenericInputKeys: Readonly<Array<keyof EmbeddableInput>> = [

View file

@ -14,8 +14,7 @@ import { merge } from 'rxjs';
import { debounceTime, distinctUntilChanged, map, skip } from 'rxjs';
import { RenderCompleteDispatcher } from '@kbn/kibana-utils-plugin/public';
import { Adapters } from '@kbn/inspector-plugin/public';
import { EmbeddableInput } from '@kbn/embeddable-plugin/common';
import { EmbeddableError, EmbeddableOutput, IEmbeddable } from './i_embeddable';
import { EmbeddableError, EmbeddableInput, EmbeddableOutput, IEmbeddable } from './i_embeddable';
import { genericEmbeddableInputIsEqual, omitGenericEmbeddableInput } from './diff_embeddable_input';
function getPanelTitle(input: EmbeddableInput, output: EmbeddableOutput) {

View file

@ -7,13 +7,66 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import { ErrorLike } from '@kbn/expressions-plugin/common';
import { Adapters } from '@kbn/inspector-plugin/public';
import { Observable } from 'rxjs';
import type { EmbeddableInput } from '@kbn/embeddable-plugin/common';
import { ErrorLike } from '@kbn/expressions-plugin/common';
import type { KibanaExecutionContext } from '@kbn/core/public';
import { Adapters } from '@kbn/inspector-plugin/public';
import type { SerializableRecord } from '@kbn/utility-types';
import { ViewMode } from '@kbn/presentation-publishing';
export type EmbeddableError = ErrorLike;
export type { EmbeddableInput };
export interface EmbeddableInput {
version?: string;
viewMode?: ViewMode;
title?: string;
description?: string;
/**
* Note this is not a saved object id. It is used to uniquely identify this
* Embeddable instance from others (e.g. inside a container). It's possible to
* have two Embeddables where everything else is the same but the id.
*/
id: string;
lastReloadRequestTime?: number;
hidePanelTitles?: boolean;
/**
* Reserved key for enhancements added by other plugins.
*/
enhancements?: SerializableRecord;
/**
* List of action IDs that this embeddable should not render.
*/
disabledActions?: string[];
/**
* Whether this embeddable should not execute triggers.
*/
disableTriggers?: boolean;
/**
* Search session id to group searches
*/
searchSessionId?: string;
/**
* Flag whether colors should be synced with other panels
*/
syncColors?: boolean;
/**
* Flag whether cursor should be synced with other panels on hover
*/
syncCursor?: boolean;
/**
* Flag whether tooltips should be synced with other panels on hover
*/
syncTooltips?: boolean;
executionContext?: KibanaExecutionContext;
}
export interface EmbeddableOutput {
// Whether the embeddable is actively loading.

View file

@ -22,8 +22,6 @@ import type { DataView } from '@kbn/data-views-plugin/public';
import { Warnings } from '@kbn/charts-plugin/public';
import { hasUnsupportedDownsampledAggregationFailure } from '@kbn/search-response-warnings';
import { Adapters } from '@kbn/inspector-plugin/public';
import { EmbeddableInput } from '@kbn/embeddable-plugin/common';
import { SavedObjectEmbeddableInput } from '@kbn/embeddable-plugin/common';
import {
ExpressionAstExpression,
ExpressionLoader,
@ -48,7 +46,7 @@ import { toExpressionAst } from '../../embeddable/to_ast';
import { AttributeService } from './attribute_service';
import { VisualizationsStartDeps } from '../../plugin';
import { Embeddable } from './embeddable';
import { EmbeddableOutput } from './i_embeddable';
import { EmbeddableInput, EmbeddableOutput } from './i_embeddable';
export interface VisualizeEmbeddableDeps {
start: StartServicesGetter<
@ -95,7 +93,7 @@ export type VisualizeSavedObjectAttributes = SavedObjectAttributes & {
savedVis?: VisSavedObject;
};
export type VisualizeByValueInput = { attributes: VisualizeSavedObjectAttributes } & VisualizeInput;
export type VisualizeByReferenceInput = SavedObjectEmbeddableInput & VisualizeInput;
export type VisualizeByReferenceInput = { savedObjectId: string } & VisualizeInput;
/** @deprecated
* VisualizeEmbeddable is no longer registered with the legacy embeddable system and is only
@ -122,11 +120,7 @@ export class VisualizeEmbeddable extends Embeddable<VisualizeInput, VisualizeOut
private abortController?: AbortController;
private readonly deps: VisualizeEmbeddableDeps;
private readonly inspectorAdapters?: Adapters;
private attributeService?: AttributeService<
VisualizeSavedObjectAttributes,
VisualizeByValueInput,
VisualizeByReferenceInput
>;
private attributeService?: AttributeService;
private expressionVariables: Record<string, unknown> | undefined;
private readonly expressionVariablesSubject = new ReplaySubject<
Record<string, unknown> | undefined
@ -136,11 +130,7 @@ export class VisualizeEmbeddable extends Embeddable<VisualizeInput, VisualizeOut
timefilter: TimefilterContract,
{ vis, editPath, editUrl, indexPatterns, deps, capabilities }: VisualizeEmbeddableConfiguration,
initialInput: VisualizeInput,
attributeService?: AttributeService<
VisualizeSavedObjectAttributes,
VisualizeByValueInput,
VisualizeByReferenceInput
>
attributeService?: AttributeService
) {
super(initialInput, {
defaultTitle: vis.title,

View file

@ -5,49 +5,11 @@
* 2.0.
*/
import useObservable from 'react-use/lib/useObservable';
import { map } from 'rxjs';
import type { KibanaExecutionContext } from '@kbn/core/types';
import { useMemo } from 'react';
import { useExecutionContext } from '@kbn/kibana-react-plugin/public';
import type { Observable } from 'rxjs';
import type { EmbeddableInput } from '@kbn/embeddable-plugin/common';
import type { ExecutionContextStart } from '@kbn/core/public';
/**
* Use execution context for ML embeddables.
* @param executionContext
* @param embeddableInput$
* @param embeddableType
* @param id
*/
export function useEmbeddableExecutionContext<T extends EmbeddableInput>(
executionContext: ExecutionContextStart,
embeddableInput$: Observable<T>,
embeddableType: string,
id: string
) {
const parentExecutionContext = useObservable(
embeddableInput$.pipe(map((v) => v.executionContext))
);
const embeddableExecutionContext: KibanaExecutionContext = useMemo(() => {
const child: KibanaExecutionContext = {
type: 'visualization',
name: embeddableType,
id,
};
return {
...parentExecutionContext,
child,
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [parentExecutionContext, id]);
useExecutionContext(executionContext, embeddableExecutionContext);
}
export const useReactEmbeddableExecutionContext = (
executionContextStart: ExecutionContextStart,
parentExecutionContext: KibanaExecutionContext,

View file

@ -8,7 +8,6 @@
import type { CoreStart } from '@kbn/core/public';
import type { RefreshInterval } from '@kbn/data-plugin/common';
import type { DefaultEmbeddableApi } from '@kbn/embeddable-plugin/public';
import type { EmbeddableInput } from '@kbn/embeddable-plugin/common';
import type { Filter, Query, TimeRange } from '@kbn/es-query';
import type { MlEntityField } from '@kbn/ml-anomaly-utils';
import type {
@ -192,8 +191,9 @@ export interface SingleMetricViewerEmbeddableCustomInput
timeRange: TimeRange | undefined;
}
export type SingleMetricViewerEmbeddableInput = EmbeddableInput &
SingleMetricViewerEmbeddableCustomInput;
export type SingleMetricViewerEmbeddableInput = SingleMetricViewerEmbeddableCustomInput & {
title?: string;
};
/**
* Persisted state for the Single Metric Embeddable.

View file

@ -4,7 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { EmbeddableInput } from '@kbn/embeddable-plugin/common';
import type { CoreStart, CoreSetup } from '@kbn/core/public';
import type { ObservabilityRuleTypeRegistry } from '@kbn/observability-plugin/public';
import type { ApmPluginStartDeps, ApmPluginSetupDeps } from '../plugin';
@ -26,4 +26,4 @@ export interface APMEmbeddableProps {
kuery?: string;
}
export type APMEmbeddableInput = EmbeddableInput & APMEmbeddableProps;
export type APMEmbeddableInput = APMEmbeddableProps;