mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Remove any
in embeddables (#110023)
* remove anys in embeddable * fix typescript errors * generate autogenerated docs * Update src/plugins/embeddable/public/lib/reference_or_value_embeddable/types.ts Co-authored-by: Jean-Louis Leysens <jloleysens@gmail.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Jean-Louis Leysens <jloleysens@gmail.com>
This commit is contained in:
parent
382f27cf62
commit
38f3f3f308
25 changed files with 63 additions and 66 deletions
|
@ -65,7 +65,7 @@ This API doesn't support angular, for registering angular dev tools, bootstrap a
|
|||
|
||||
|
||||
|<<embeddable-plugin>>
|
||||
|Embeddables are re-usable widgets that can be rendered in any environment or plugin. Developers can embed them directly in their plugin. End users can dynamically add them to any embeddable _containers_.
|
||||
|Embeddables are re-usable widgets that can be rendered on dashboard, but also in other apps. Developers can embed them directly in their plugin. End users can dynamically add them to embeddable _containers_.
|
||||
|
||||
|
||||
|{kib-repo}blob/{branch}/src/plugins/es_ui_shared/README.md[esUiShared]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[[embeddable-plugin]]
|
||||
== Embeddables plugin
|
||||
|
||||
Embeddables are re-usable widgets that can be rendered in any environment or plugin. Developers can embed them directly in their plugin. End users can dynamically add them to any embeddable _containers_.
|
||||
Embeddables are re-usable widgets that can be rendered on dashboard, but also in other apps. Developers can embed them directly in their plugin. End users can dynamically add them to embeddable _containers_.
|
||||
|
||||
=== Embeddable containers
|
||||
|
||||
|
@ -9,7 +9,7 @@ Containers are a special type of embeddable that can contain nested embeddables.
|
|||
|
||||
=== Examples
|
||||
|
||||
Many example embeddables are implemented and registered https://github.com/elastic/kibana/tree/master/examples/embeddable_examples[here]. They can be played around with and explored https://github.com/elastic/kibana/tree/master/examples/embeddable_explorer[in the Embeddable Explorer example plugin]. Just run kibana with
|
||||
Multiple embeddable examples are implemented and registered https://github.com/elastic/kibana/tree/master/examples/embeddable_examples[here]. They can be played around with and explored https://github.com/elastic/kibana/tree/master/examples/embeddable_explorer[in the Embeddable Explorer example plugin]. Just run kibana with
|
||||
|
||||
[source,sh]
|
||||
--
|
||||
|
|
|
@ -21,7 +21,7 @@ export const getExtractFunction = (embeddables: CommonEmbeddableStartContract) =
|
|||
|
||||
if (factory) {
|
||||
const factoryResponse = factory.extract(state);
|
||||
updatedInput = factoryResponse.state;
|
||||
updatedInput = factoryResponse.state as EmbeddableStateWithType;
|
||||
refs.push(...factoryResponse.references);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
import { getAllMigrations } from './get_all_migrations';
|
||||
|
||||
describe('embeddable getAllMigratons', () => {
|
||||
const factories = [{ migrations: { '7.11.0': (state: any) => state } }];
|
||||
const enhacements = [{ migrations: { '7.12.0': (state: any) => state } }];
|
||||
const factories = [{ migrations: { '7.11.0': (state: unknown) => state } }];
|
||||
const enhacements = [{ migrations: { '7.12.0': (state: unknown) => state } }];
|
||||
const migrateFn = jest.fn();
|
||||
|
||||
test('returns base migrations', () => {
|
||||
|
@ -18,16 +18,16 @@ describe('embeddable getAllMigratons', () => {
|
|||
});
|
||||
|
||||
test('returns embeddable factory migrations', () => {
|
||||
expect(getAllMigrations(factories as any, [], migrateFn)).toHaveProperty(['7.11.0']);
|
||||
expect(getAllMigrations(factories, [], migrateFn)).toHaveProperty(['7.11.0']);
|
||||
});
|
||||
|
||||
test('returns enhancement migrations', () => {
|
||||
const migrations = getAllMigrations([], enhacements as any, migrateFn);
|
||||
const migrations = getAllMigrations([], enhacements, migrateFn);
|
||||
expect(migrations).toHaveProperty(['7.12.0']);
|
||||
});
|
||||
|
||||
test('returns all migrations', () => {
|
||||
const migrations = getAllMigrations(factories as any, enhacements as any, migrateFn);
|
||||
const migrations = getAllMigrations(factories, enhacements, migrateFn);
|
||||
expect(migrations).toHaveProperty(['7.11.0']);
|
||||
expect(migrations).toHaveProperty(['7.12.0']);
|
||||
});
|
||||
|
|
|
@ -19,7 +19,7 @@ export const getInjectFunction = (embeddables: CommonEmbeddableStartContract) =>
|
|||
let updatedInput = injectBaseEmbeddableInput(state, references);
|
||||
|
||||
if (factory) {
|
||||
updatedInput = factory.inject(updatedInput, references);
|
||||
updatedInput = factory.inject(updatedInput, references) as EmbeddableStateWithType;
|
||||
}
|
||||
|
||||
updatedInput.enhancements = {};
|
||||
|
|
|
@ -38,7 +38,7 @@ export const getMigrateFunction = (embeddables: CommonEmbeddableStartContract) =
|
|||
const migratedEnhancement = enhancementDefinition?.migrations?.[version]
|
||||
? enhancementDefinition.migrations[version](enhancements[key] as SerializableRecord)
|
||||
: enhancements[key];
|
||||
(updatedInput.enhancements! as Record<string, any>)[key] = migratedEnhancement;
|
||||
(updatedInput.enhancements! as Record<string, {}>)[key] = migratedEnhancement;
|
||||
});
|
||||
|
||||
return updatedInput;
|
||||
|
|
|
@ -12,7 +12,7 @@ import { MigrateFunctionsObject } from '../../../kibana_utils/common';
|
|||
|
||||
export const telemetryBaseEmbeddableInput = (
|
||||
state: EmbeddableStateWithType,
|
||||
telemetryData: Record<string, any>
|
||||
telemetryData: Record<string, string | number | boolean>
|
||||
) => {
|
||||
return telemetryData;
|
||||
};
|
||||
|
|
|
@ -6,12 +6,16 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { SerializableRecord } from '@kbn/utility-types';
|
||||
import { CommonEmbeddableStartContract, EmbeddableStateWithType } from '../types';
|
||||
import { telemetryBaseEmbeddableInput } from './migrate_base_input';
|
||||
|
||||
export const getTelemetryFunction = (embeddables: CommonEmbeddableStartContract) => {
|
||||
return (state: EmbeddableStateWithType, telemetryData: Record<string, any> = {}) => {
|
||||
const enhancements: Record<string, any> = state.enhancements || {};
|
||||
return (
|
||||
state: EmbeddableStateWithType,
|
||||
telemetryData: Record<string, string | number | boolean> = {}
|
||||
) => {
|
||||
const enhancements = state.enhancements || {};
|
||||
const factory = embeddables.getEmbeddableFactory(state.type);
|
||||
|
||||
let outputTelemetryData = telemetryBaseEmbeddableInput(state, telemetryData);
|
||||
|
@ -22,7 +26,7 @@ export const getTelemetryFunction = (embeddables: CommonEmbeddableStartContract)
|
|||
if (!enhancements[key]) return;
|
||||
outputTelemetryData = embeddables
|
||||
.getEnhancement(key)
|
||||
.telemetry(enhancements[key], outputTelemetryData);
|
||||
.telemetry(enhancements[key] as Record<string, SerializableRecord>, outputTelemetryData);
|
||||
});
|
||||
|
||||
return outputTelemetryData;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import type { SerializableRecord } from '@kbn/utility-types';
|
||||
import type { KibanaExecutionContext } from 'src/core/public';
|
||||
import { PersistableStateService } from '../../kibana_utils/common';
|
||||
import { PersistableStateService, PersistableState } from '../../kibana_utils/common';
|
||||
|
||||
export enum ViewMode {
|
||||
EDIT = 'edit',
|
||||
|
@ -62,8 +62,7 @@ export interface PanelState<E extends EmbeddableInput & { id: string } = { id: s
|
|||
type: string;
|
||||
|
||||
// Stores input for this embeddable that is specific to this embeddable. Other parts of embeddable input
|
||||
// will be derived from the container's input. **Any state in here will override any state derived from
|
||||
// the container.**
|
||||
// will be derived from the container's input. **State in here will override state derived from the container.**
|
||||
explicitInput: Partial<E> & { id: string };
|
||||
}
|
||||
|
||||
|
@ -72,6 +71,8 @@ export type EmbeddableStateWithType = EmbeddableInput & { type: string };
|
|||
export type EmbeddablePersistableStateService = PersistableStateService<EmbeddableStateWithType>;
|
||||
|
||||
export interface CommonEmbeddableStartContract {
|
||||
getEmbeddableFactory: (embeddableFactoryId: string) => any;
|
||||
getEnhancement: (enhancementId: string) => any;
|
||||
getEmbeddableFactory: (
|
||||
embeddableFactoryId: string
|
||||
) => PersistableState & { isContainerType: boolean };
|
||||
getEnhancement: (enhancementId: string) => PersistableState;
|
||||
}
|
||||
|
|
|
@ -230,7 +230,7 @@ export abstract class Container<
|
|||
|
||||
/**
|
||||
* Return state that comes from the container and is passed down to the child. For instance, time range and
|
||||
* filters are common inherited input state. Note that any state stored in `this.input.panels[embeddableId].explicitInput`
|
||||
* filters are common inherited input state. Note that state stored in `this.input.panels[embeddableId].explicitInput`
|
||||
* will override inherited input.
|
||||
*/
|
||||
protected abstract getInheritedInput(id: string): TChildInput;
|
||||
|
@ -309,8 +309,7 @@ export abstract class Container<
|
|||
throw new EmbeddableFactoryNotFoundError(panel.type);
|
||||
}
|
||||
|
||||
// TODO: lets get rid of this distinction with factories, I don't think it will be needed
|
||||
// anymore after this change.
|
||||
// TODO: lets get rid of this distinction with factories, I don't think it will be needed after this change.
|
||||
embeddable = isSavedObjectEmbeddableInput(inputForChild)
|
||||
? await factory.createFromSavedObject(inputForChild.savedObjectId, inputForChild, this)
|
||||
: await factory.create(inputForChild, this);
|
||||
|
|
|
@ -49,7 +49,7 @@ export interface IContainer<
|
|||
getInputForChild<EEI extends EmbeddableInput>(id: string): EEI;
|
||||
|
||||
/**
|
||||
* Changes the input for a given child. Note, this will override any inherited state taken from
|
||||
* Changes the input for a given child. Note, this will override all inherited state taken from
|
||||
* the container itself.
|
||||
* @param id
|
||||
* @param changes
|
||||
|
|
|
@ -111,7 +111,7 @@ export abstract class Embeddable<
|
|||
* Merges input$ and output$ streams and debounces emit till next macro-task.
|
||||
* Could be useful to batch reactions to input$ and output$ updates that happen separately but synchronously.
|
||||
* In case corresponding state change triggered `reload` this stream is guarantied to emit later,
|
||||
* which allows to skip any state handling in case `reload` already handled it.
|
||||
* which allows to skip state handling in case `reload` already handled it.
|
||||
*/
|
||||
public getUpdated$(): Readonly<Rx.Observable<TEmbeddableInput | TEmbeddableOutput>> {
|
||||
return merge(this.getInput$().pipe(skip(1)), this.getOutput$().pipe(skip(1))).pipe(
|
||||
|
@ -184,7 +184,7 @@ export abstract class Embeddable<
|
|||
|
||||
/**
|
||||
* Called when this embeddable is no longer used, this should be the place for
|
||||
* implementors to add any additional clean up tasks, like unmounting and unsubscribing.
|
||||
* implementors to add additional clean up tasks, like un-mounting and unsubscribing.
|
||||
*/
|
||||
public destroy(): void {
|
||||
this.destroyed = true;
|
||||
|
|
|
@ -86,8 +86,8 @@ export interface EmbeddableFactory<
|
|||
canCreateNew(): boolean;
|
||||
|
||||
/**
|
||||
* Can be used to get any default input, to be passed in to during the creation process. Default
|
||||
* input will not be stored in a parent container, so any inherited input from a container will trump
|
||||
* Can be used to get the default input, to be passed in to during the creation process. Default
|
||||
* input will not be stored in a parent container, so all inherited input from a container will trump
|
||||
* default input parameters.
|
||||
* @param partial
|
||||
*/
|
||||
|
@ -95,7 +95,7 @@ export interface EmbeddableFactory<
|
|||
|
||||
/**
|
||||
* Can be used to request explicit input from the user, to be passed in to `EmbeddableFactory:create`.
|
||||
* Explicit input is stored on the parent container for this embeddable. It overrides any inherited
|
||||
* Explicit input is stored on the parent container for this embeddable. It overrides all inherited
|
||||
* input passed down from the parent container.
|
||||
*/
|
||||
getExplicitInput(): Promise<Partial<TEmbeddableInput>>;
|
||||
|
|
|
@ -21,8 +21,7 @@
|
|||
min-height: 0; // Absolute must for Firefox to scroll contents
|
||||
}
|
||||
|
||||
// SASSTODO: Pretty sure this doesn't do anything since the flex-basis 100%,
|
||||
// but it MIGHT be fixing IE
|
||||
// SASSTODO: this MIGHT be fixing IE
|
||||
.embPanel__content--fullWidth {
|
||||
width: 100%;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import React, { ReactElement } from 'react';
|
||||
import { METRIC_TYPE } from '@kbn/analytics';
|
||||
import { CoreSetup, SavedObjectAttributes, SimpleSavedObject } from 'src/core/public';
|
||||
import { CoreSetup, SavedObjectAttributes, SimpleSavedObject, Toast } from 'src/core/public';
|
||||
|
||||
import { EuiContextMenuItem, EuiFlyoutBody, EuiFlyoutHeader, EuiTitle } from '@elastic/eui';
|
||||
|
||||
|
@ -41,7 +41,7 @@ function capitalize([first, ...letters]: string) {
|
|||
}
|
||||
|
||||
export class AddPanelFlyout extends React.Component<Props, State> {
|
||||
private lastToast: any;
|
||||
private lastToast?: string | Toast;
|
||||
|
||||
public state = {
|
||||
isCreateMenuOpen: false,
|
||||
|
@ -151,7 +151,7 @@ export class AddPanelFlyout extends React.Component<Props, State> {
|
|||
(embeddableFactory) =>
|
||||
Boolean(embeddableFactory.savedObjectMetaData) && !embeddableFactory.isContainerType
|
||||
)
|
||||
.map(({ savedObjectMetaData }) => savedObjectMetaData as any);
|
||||
.map(({ savedObjectMetaData }) => savedObjectMetaData);
|
||||
const savedObjectsFinder = (
|
||||
<SavedObjectFinder
|
||||
onChoose={this.onAddPanel}
|
||||
|
|
|
@ -126,7 +126,7 @@ test('Execute throws an error when inspector adapters are not available', async
|
|||
);
|
||||
|
||||
expect(error).toBeInstanceOf(Error);
|
||||
expect(error.message).toMatchInlineSnapshot(`"Action not compatible with context"`);
|
||||
expect((error as Error).message).toMatchInlineSnapshot(`"Action not compatible with context"`);
|
||||
});
|
||||
|
||||
test('Returns title', async () => {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
import { EmbeddableInput, SavedObjectEmbeddableInput } from '..';
|
||||
|
||||
/**
|
||||
* Any embeddable that implements this interface will be able to use input that is
|
||||
* All embeddables that implement this interface will be able to use input that is
|
||||
* either by reference (backed by a saved object) OR by value, (provided
|
||||
* by the container).
|
||||
* @public
|
||||
|
|
|
@ -11,9 +11,9 @@ import { EmbeddableOutput, EmbeddableInput, Embeddable } from '../../embeddables
|
|||
|
||||
/** @internal */
|
||||
export interface MockFilter {
|
||||
$state?: any;
|
||||
meta: any;
|
||||
query?: any;
|
||||
$state?: {};
|
||||
meta: {};
|
||||
query?: {};
|
||||
}
|
||||
|
||||
export const FILTERABLE_EMBEDDABLE = 'FILTERABLE_EMBEDDABLE';
|
||||
|
|
|
@ -43,7 +43,7 @@ import { Storage } from '../../kibana_utils/public';
|
|||
import { migrateToLatest, PersistableStateService } from '../../kibana_utils/common';
|
||||
import { ATTRIBUTE_SERVICE_KEY, AttributeService } from './lib/attribute_service';
|
||||
import { AttributeServiceOptions } from './lib/attribute_service/attribute_service';
|
||||
import { EmbeddableStateWithType } from '../common/types';
|
||||
import { EmbeddableStateWithType, CommonEmbeddableStartContract } from '../common/types';
|
||||
import {
|
||||
getExtractFunction,
|
||||
getInjectFunction,
|
||||
|
@ -172,8 +172,9 @@ export class EmbeddablePublicPlugin implements Plugin<EmbeddableSetup, Embeddabl
|
|||
/>
|
||||
);
|
||||
|
||||
const commonContract = {
|
||||
getEmbeddableFactory: this.getEmbeddableFactory,
|
||||
const commonContract: CommonEmbeddableStartContract = {
|
||||
getEmbeddableFactory: (this
|
||||
.getEmbeddableFactory as unknown) as CommonEmbeddableStartContract['getEmbeddableFactory'],
|
||||
getEnhancement: this.getEnhancement,
|
||||
};
|
||||
|
||||
|
|
|
@ -494,8 +494,7 @@ test('Panel removed from input state', async () => {
|
|||
const { container } = await creatHelloWorldContainerAndEmbeddable({
|
||||
id: 'hello',
|
||||
panels: {},
|
||||
filters: [],
|
||||
} as any);
|
||||
});
|
||||
|
||||
const embeddable = await container.addNewEmbeddable<
|
||||
FilterableEmbeddableInput,
|
||||
|
@ -521,8 +520,7 @@ test('Panel added to input state', async () => {
|
|||
const { container, start } = await creatHelloWorldContainerAndEmbeddable({
|
||||
id: 'hello',
|
||||
panels: {},
|
||||
filters: [],
|
||||
} as any);
|
||||
});
|
||||
|
||||
const embeddable = await container.addNewEmbeddable<
|
||||
FilterableEmbeddableInput,
|
||||
|
@ -712,7 +710,7 @@ test('untilEmbeddableLoaded() throws an error if there is no such child panel in
|
|||
|
||||
const [, error] = await of(container.untilEmbeddableLoaded('123'));
|
||||
expect(error).toBeInstanceOf(Error);
|
||||
expect(error.message).toMatchInlineSnapshot(`"Panel not found"`);
|
||||
expect((error as Error).message).toMatchInlineSnapshot(`"Panel not found"`);
|
||||
});
|
||||
|
||||
test('untilEmbeddableLoaded() resolves if child is loaded in the container', async (done) => {
|
||||
|
|
|
@ -25,6 +25,7 @@ import { CustomizePanelModal } from '../lib/panel/panel_header/panel_actions/cus
|
|||
import { EmbeddableStart } from '../plugin';
|
||||
import { createEmbeddablePanelMock } from '../mocks';
|
||||
import { mountWithIntl } from '@kbn/test/jest';
|
||||
import { OverlayStart } from 'kibana/public';
|
||||
|
||||
let api: EmbeddableStart;
|
||||
let container: Container;
|
||||
|
@ -38,7 +39,7 @@ beforeEach(async () => {
|
|||
|
||||
const contactCardFactory = new ContactCardEmbeddableFactory(
|
||||
uiActions.executeTriggerActions,
|
||||
{} as any
|
||||
({} as unknown) as OverlayStart
|
||||
);
|
||||
setup.registerEmbeddableFactory(contactCardFactory.type, contactCardFactory);
|
||||
|
||||
|
|
|
@ -16,15 +16,7 @@ export class HelloWorldEmbeddable extends Embeddable {
|
|||
public readonly type = HELLO_WORLD_EMBEDDABLE;
|
||||
|
||||
constructor(initialInput: EmbeddableInput, parent?: IContainer) {
|
||||
super(
|
||||
// Input state is irrelevant to this embeddable, just pass it along.
|
||||
initialInput,
|
||||
// Initial output state - this embeddable does not do anything with output, so just
|
||||
// pass along an empty object.
|
||||
{},
|
||||
// Optional parent component, this embeddable can optionally be rendered inside a container.
|
||||
parent
|
||||
);
|
||||
super(initialInput, {}, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,7 +19,7 @@ export const expectErrorAsync = (fn: (...args: unknown[]) => Promise<unknown>):
|
|||
});
|
||||
};
|
||||
|
||||
export const expectError = (fn: (...args: any) => any): Error => {
|
||||
export const expectError = (fn: (...args: unknown[]) => unknown): Error => {
|
||||
try {
|
||||
fn();
|
||||
throw new Error('Expected an error throw.');
|
||||
|
@ -33,7 +33,7 @@ export const expectError = (fn: (...args: any) => any): Error => {
|
|||
|
||||
export const of = async <T, P extends Promise<T>>(
|
||||
promise: P
|
||||
): Promise<[T | undefined, Error | any]> => {
|
||||
): Promise<[T | undefined, Error | unknown]> => {
|
||||
try {
|
||||
return [await promise, undefined];
|
||||
} catch (error) {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { CoreSetup, CoreStart } from 'src/core/public';
|
||||
import { CoreSetup, CoreStart, PluginInitializerContext } from 'src/core/public';
|
||||
import { UiActionsStart } from '../../../ui_actions/public';
|
||||
import { uiActionsPluginMock } from '../../../ui_actions/public/mocks';
|
||||
import { inspectorPluginMock } from '../../../inspector/public/mocks';
|
||||
|
@ -27,7 +27,7 @@ export const testPlugin = (
|
|||
coreStart: CoreStart = coreMock.createStart()
|
||||
): TestPluginReturn => {
|
||||
const uiActions = uiActionsPluginMock.createPlugin(coreSetup, coreStart);
|
||||
const initializerContext = {} as any;
|
||||
const initializerContext = {} as PluginInitializerContext;
|
||||
const plugin = new EmbeddablePublicPlugin(initializerContext);
|
||||
const setup = plugin.setup(coreSetup, {
|
||||
uiActions: uiActions.setup,
|
||||
|
|
|
@ -27,7 +27,7 @@ import {
|
|||
PersistableStateMigrateFn,
|
||||
MigrateFunctionsObject,
|
||||
} from '../../kibana_utils/common';
|
||||
import { EmbeddableStateWithType } from '../common/types';
|
||||
import { EmbeddableStateWithType, CommonEmbeddableStartContract } from '../common/types';
|
||||
import { getAllMigrations } from '../common/lib/get_all_migrations';
|
||||
|
||||
export interface EmbeddableSetup extends PersistableStateService<EmbeddableStateWithType> {
|
||||
|
@ -44,8 +44,9 @@ export class EmbeddableServerPlugin implements Plugin<EmbeddableSetup, Embeddabl
|
|||
private migrateFn: PersistableStateMigrateFn | undefined;
|
||||
|
||||
public setup(core: CoreSetup) {
|
||||
const commonContract = {
|
||||
getEmbeddableFactory: this.getEmbeddableFactory,
|
||||
const commonContract: CommonEmbeddableStartContract = {
|
||||
getEmbeddableFactory: (this
|
||||
.getEmbeddableFactory as unknown) as CommonEmbeddableStartContract['getEmbeddableFactory'],
|
||||
getEnhancement: this.getEnhancement,
|
||||
};
|
||||
|
||||
|
@ -66,8 +67,9 @@ export class EmbeddableServerPlugin implements Plugin<EmbeddableSetup, Embeddabl
|
|||
}
|
||||
|
||||
public start(core: CoreStart) {
|
||||
const commonContract = {
|
||||
getEmbeddableFactory: this.getEmbeddableFactory,
|
||||
const commonContract: CommonEmbeddableStartContract = {
|
||||
getEmbeddableFactory: (this
|
||||
.getEmbeddableFactory as unknown) as CommonEmbeddableStartContract['getEmbeddableFactory'],
|
||||
getEnhancement: this.getEnhancement,
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue