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:
Vadim Kibana 2021-09-20 14:09:02 +02:00 committed by GitHub
parent 382f27cf62
commit 38f3f3f308
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 63 additions and 66 deletions

View file

@ -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]

View file

@ -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]
--

View file

@ -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);
}

View file

@ -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']);
});

View file

@ -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 = {};

View file

@ -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;

View file

@ -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;
};

View file

@ -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;

View file

@ -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;
}

View file

@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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>>;

View file

@ -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%;
}

View file

@ -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}

View file

@ -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 () => {

View file

@ -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

View file

@ -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';

View file

@ -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,
};

View file

@ -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) => {

View file

@ -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);

View file

@ -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);
}
/**

View file

@ -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) {

View file

@ -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,

View file

@ -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,
};