Embeddable API cleanup (#60207)

* wip

* Remove test in legacy functional plugin
This commit is contained in:
Stacey Gammon 2020-03-16 15:37:42 -04:00 committed by GitHub
parent 6cbfa274cf
commit dccfa593dc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
92 changed files with 451 additions and 647 deletions

View file

@ -33,7 +33,7 @@ export class HelloWorldEmbeddableFactory extends EmbeddableFactory {
* embeddables should check the UI Capabilities service to be sure of
* the right permissions.
*/
public isEditable() {
public async isEditable() {
return true;
}

View file

@ -21,7 +21,7 @@ import ReactDOM from 'react-dom';
import {
Container,
ContainerInput,
GetEmbeddableFactory,
EmbeddableStart,
} from '../../../../src/plugins/embeddable/public';
import { ListContainerComponent } from './list_container_component';
@ -31,7 +31,10 @@ export class ListContainer extends Container<{}, ContainerInput> {
public readonly type = LIST_CONTAINER;
private node?: HTMLElement;
constructor(input: ContainerInput, getEmbeddableFactory: GetEmbeddableFactory) {
constructor(
input: ContainerInput,
getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory']
) {
super(input, { embeddableLoaded: {} }, getEmbeddableFactory);
}

View file

@ -20,25 +20,30 @@
import { i18n } from '@kbn/i18n';
import {
EmbeddableFactory,
GetEmbeddableFactory,
ContainerInput,
EmbeddableStart,
} from '../../../../src/plugins/embeddable/public';
import { LIST_CONTAINER, ListContainer } from './list_container';
interface StartServices {
getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
}
export class ListContainerFactory extends EmbeddableFactory {
public readonly type = LIST_CONTAINER;
public readonly isContainerType = true;
constructor(private getEmbeddableFactory: GetEmbeddableFactory) {
constructor(private getStartServices: () => Promise<StartServices>) {
super();
}
public isEditable() {
public async isEditable() {
return true;
}
public async create(initialInput: ContainerInput) {
return new ListContainer(initialInput, this.getEmbeddableFactory);
const { getEmbeddableFactory } = await this.getStartServices();
return new ListContainer(initialInput, getEmbeddableFactory);
}
public getDisplayName() {

View file

@ -32,7 +32,7 @@ export class MultiTaskTodoEmbeddableFactory extends EmbeddableFactory<
> {
public readonly type = MULTI_TASK_TODO_EMBEDDABLE;
public isEditable() {
public async isEditable() {
return true;
}

View file

@ -17,20 +17,11 @@
* under the License.
*/
import {
IEmbeddableSetup,
IEmbeddableStart,
EmbeddableFactory,
} from '../../../src/plugins/embeddable/public';
import { EmbeddableSetup, EmbeddableStart } from '../../../src/plugins/embeddable/public';
import { Plugin, CoreSetup, CoreStart } from '../../../src/core/public';
import { HelloWorldEmbeddableFactory, HELLO_WORLD_EMBEDDABLE } from './hello_world';
import { TODO_EMBEDDABLE, TodoEmbeddableFactory, TodoInput, TodoOutput } from './todo';
import {
MULTI_TASK_TODO_EMBEDDABLE,
MultiTaskTodoEmbeddableFactory,
MultiTaskTodoOutput,
MultiTaskTodoInput,
} from './multi_task_todo';
import { MULTI_TASK_TODO_EMBEDDABLE, MultiTaskTodoEmbeddableFactory } from './multi_task_todo';
import {
SEARCHABLE_LIST_CONTAINER,
SearchableListContainerFactory,
@ -38,46 +29,56 @@ import {
import { LIST_CONTAINER, ListContainerFactory } from './list_container';
interface EmbeddableExamplesSetupDependencies {
embeddable: IEmbeddableSetup;
embeddable: EmbeddableSetup;
}
interface EmbeddableExamplesStartDependencies {
embeddable: IEmbeddableStart;
embeddable: EmbeddableStart;
}
export class EmbeddableExamplesPlugin
implements
Plugin<void, void, EmbeddableExamplesSetupDependencies, EmbeddableExamplesStartDependencies> {
public setup(core: CoreSetup, deps: EmbeddableExamplesSetupDependencies) {
public setup(
core: CoreSetup<EmbeddableExamplesStartDependencies>,
deps: EmbeddableExamplesSetupDependencies
) {
deps.embeddable.registerEmbeddableFactory(
HELLO_WORLD_EMBEDDABLE,
new HelloWorldEmbeddableFactory()
);
deps.embeddable.registerEmbeddableFactory<
EmbeddableFactory<MultiTaskTodoInput, MultiTaskTodoOutput>
>(MULTI_TASK_TODO_EMBEDDABLE, new MultiTaskTodoEmbeddableFactory());
}
deps.embeddable.registerEmbeddableFactory(
MULTI_TASK_TODO_EMBEDDABLE,
new MultiTaskTodoEmbeddableFactory()
);
public start(core: CoreStart, deps: EmbeddableExamplesStartDependencies) {
// These are registered in the start method because `getEmbeddableFactory `
// is only available in start. We could reconsider this I think and make it
// available in both.
deps.embeddable.registerEmbeddableFactory(
SEARCHABLE_LIST_CONTAINER,
new SearchableListContainerFactory(deps.embeddable.getEmbeddableFactory)
new SearchableListContainerFactory(async () => ({
getEmbeddableFactory: (await core.getStartServices())[1].embeddable.getEmbeddableFactory,
}))
);
deps.embeddable.registerEmbeddableFactory(
LIST_CONTAINER,
new ListContainerFactory(deps.embeddable.getEmbeddableFactory)
new ListContainerFactory(async () => ({
getEmbeddableFactory: (await core.getStartServices())[1].embeddable.getEmbeddableFactory,
}))
);
deps.embeddable.registerEmbeddableFactory<EmbeddableFactory<TodoInput, TodoOutput>>(
deps.embeddable.registerEmbeddableFactory<TodoInput, TodoOutput>(
TODO_EMBEDDABLE,
new TodoEmbeddableFactory(core.overlays.openModal)
new TodoEmbeddableFactory(async () => ({
openModal: (await core.getStartServices())[0].overlays.openModal,
}))
);
}
public start(core: CoreStart, deps: EmbeddableExamplesStartDependencies) {}
public stop() {}
}

View file

@ -21,7 +21,7 @@ import ReactDOM from 'react-dom';
import {
Container,
ContainerInput,
GetEmbeddableFactory,
EmbeddableStart,
EmbeddableInput,
} from '../../../../src/plugins/embeddable/public';
import { SearchableListContainerComponent } from './searchable_list_container_component';
@ -40,7 +40,10 @@ export class SearchableListContainer extends Container<ChildInput, SearchableCon
public readonly type = SEARCHABLE_LIST_CONTAINER;
private node?: HTMLElement;
constructor(input: SearchableContainerInput, getEmbeddableFactory: GetEmbeddableFactory) {
constructor(
input: SearchableContainerInput,
getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory']
) {
super(input, { embeddableLoaded: {} }, getEmbeddableFactory);
}

View file

@ -18,27 +18,32 @@
*/
import { i18n } from '@kbn/i18n';
import { EmbeddableFactory, GetEmbeddableFactory } from '../../../../src/plugins/embeddable/public';
import { EmbeddableFactory, EmbeddableStart } from '../../../../src/plugins/embeddable/public';
import {
SEARCHABLE_LIST_CONTAINER,
SearchableListContainer,
SearchableContainerInput,
} from './searchable_list_container';
interface StartServices {
getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
}
export class SearchableListContainerFactory extends EmbeddableFactory {
public readonly type = SEARCHABLE_LIST_CONTAINER;
public readonly isContainerType = true;
constructor(private getEmbeddableFactory: GetEmbeddableFactory) {
constructor(private getStartServices: () => Promise<StartServices>) {
super();
}
public isEditable() {
public async isEditable() {
return true;
}
public async create(initialInput: SearchableContainerInput) {
return new SearchableListContainer(initialInput, this.getEmbeddableFactory);
const { getEmbeddableFactory } = await this.getStartServices();
return new SearchableListContainer(initialInput, getEmbeddableFactory);
}
public getDisplayName() {

View file

@ -43,6 +43,10 @@ function TaskInput({ onSave }: { onSave: (task: string) => void }) {
);
}
interface StartServices {
openModal: OverlayStart['openModal'];
}
export class TodoEmbeddableFactory extends EmbeddableFactory<
TodoInput,
TodoOutput,
@ -50,11 +54,11 @@ export class TodoEmbeddableFactory extends EmbeddableFactory<
> {
public readonly type = TODO_EMBEDDABLE;
constructor(private openModal: OverlayStart['openModal']) {
constructor(private getStartServices: () => Promise<StartServices>) {
super();
}
public isEditable() {
public async isEditable() {
return true;
}
@ -69,9 +73,10 @@ export class TodoEmbeddableFactory extends EmbeddableFactory<
* in this case, the task string.
*/
public async getExplicitInput() {
const { openModal } = await this.getStartServices();
return new Promise<{ task: string }>(resolve => {
const onSave = (task: string) => resolve({ task });
const overlay = this.openModal(
const overlay = openModal(
toMountPoint(
<TaskInput
onSave={(task: string) => {

View file

@ -23,7 +23,7 @@ import { BrowserRouter as Router, Route, withRouter, RouteComponentProps } from
import { EuiPage, EuiPageSideBar, EuiSideNav } from '@elastic/eui';
import { IEmbeddableStart } from '../../../src/plugins/embeddable/public';
import { EmbeddableStart } from '../../../src/plugins/embeddable/public';
import { UiActionsStart } from '../../../src/plugins/ui_actions/public';
import { Start as InspectorStartContract } from '../../../src/plugins/inspector/public';
import {
@ -74,7 +74,7 @@ const Nav = withRouter(({ history, navigateToApp, pages }: NavProps) => {
interface Props {
basename: string;
navigateToApp: CoreStart['application']['navigateToApp'];
embeddableApi: IEmbeddableStart;
embeddableApi: EmbeddableStart;
uiActionsApi: UiActionsStart;
overlays: OverlayStart;
notifications: CoreStart['notifications'];

View file

@ -31,9 +31,8 @@ import {
import { EuiSpacer } from '@elastic/eui';
import { OverlayStart, CoreStart, SavedObjectsStart, IUiSettingsClient } from 'kibana/public';
import {
GetEmbeddableFactory,
EmbeddablePanel,
IEmbeddableStart,
EmbeddableStart,
IEmbeddable,
} from '../../../src/plugins/embeddable/public';
import {
@ -47,8 +46,8 @@ import { Start as InspectorStartContract } from '../../../src/plugins/inspector/
import { getSavedObjectFinder } from '../../../src/plugins/saved_objects/public';
interface Props {
getAllEmbeddableFactories: IEmbeddableStart['getEmbeddableFactories'];
getEmbeddableFactory: GetEmbeddableFactory;
getAllEmbeddableFactories: EmbeddableStart['getEmbeddableFactories'];
getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
uiActionsApi: UiActionsStart;
overlays: OverlayStart;
notifications: CoreStart['notifications'];

View file

@ -29,14 +29,14 @@ import {
EuiText,
} from '@elastic/eui';
import {
GetEmbeddableFactory,
EmbeddableStart,
EmbeddableFactoryRenderer,
EmbeddableRoot,
} from '../../../src/plugins/embeddable/public';
import { HelloWorldEmbeddable, HELLO_WORLD_EMBEDDABLE } from '../../embeddable_examples/public';
interface Props {
getEmbeddableFactory: GetEmbeddableFactory;
getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
}
export function HelloWorldEmbeddableExample({ getEmbeddableFactory }: Props) {

View file

@ -29,10 +29,7 @@ import {
EuiText,
} from '@elastic/eui';
import { EuiSpacer } from '@elastic/eui';
import {
GetEmbeddableFactory,
EmbeddableFactoryRenderer,
} from '../../../src/plugins/embeddable/public';
import { EmbeddableFactoryRenderer, EmbeddableStart } from '../../../src/plugins/embeddable/public';
import {
HELLO_WORLD_EMBEDDABLE,
TODO_EMBEDDABLE,
@ -42,7 +39,7 @@ import {
} from '../../embeddable_examples/public';
interface Props {
getEmbeddableFactory: GetEmbeddableFactory;
getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
}
export function ListContainerExample({ getEmbeddableFactory }: Props) {

View file

@ -19,12 +19,12 @@
import { Plugin, CoreSetup, AppMountParameters } from 'kibana/public';
import { UiActionsService } from '../../../src/plugins/ui_actions/public';
import { IEmbeddableStart } from '../../../src/plugins/embeddable/public';
import { EmbeddableStart } from '../../../src/plugins/embeddable/public';
import { Start as InspectorStart } from '../../../src/plugins/inspector/public';
interface StartDeps {
uiActions: UiActionsService;
embeddable: IEmbeddableStart;
embeddable: EmbeddableStart;
inspector: InspectorStart;
}

View file

@ -39,10 +39,10 @@ import {
TODO_EMBEDDABLE,
TodoEmbeddableFactory,
} from '../../../examples/embeddable_examples/public/todo';
import { GetEmbeddableFactory, EmbeddableRoot } from '../../../src/plugins/embeddable/public';
import { EmbeddableStart, EmbeddableRoot } from '../../../src/plugins/embeddable/public';
interface Props {
getEmbeddableFactory: GetEmbeddableFactory;
getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
}
interface State {

View file

@ -39,7 +39,7 @@ import {
} from '../legacy_imports';
// @ts-ignore
import { initDashboardApp } from './legacy_app';
import { IEmbeddableStart } from '../../../../../../plugins/embeddable/public';
import { EmbeddableStart } from '../../../../../../plugins/embeddable/public';
import { NavigationPublicPluginStart as NavigationStart } from '../../../../../../plugins/navigation/public';
import { DataPublicPluginStart } from '../../../../../../plugins/data/public';
import { SharePluginStart } from '../../../../../../plugins/share/public';
@ -67,7 +67,7 @@ export interface RenderDeps {
chrome: ChromeStart;
addBasePath: (path: string) => string;
savedQueryService: DataPublicPluginStart['query']['savedQueries'];
embeddable: IEmbeddableStart;
embeddable: EmbeddableStart;
localStorage: Storage;
share: SharePluginStart;
config: KibanaLegacyStart['config'];

View file

@ -35,7 +35,7 @@ import {
DataPublicPluginSetup,
esFilters,
} from '../../../../../plugins/data/public';
import { IEmbeddableStart } from '../../../../../plugins/embeddable/public';
import { EmbeddableStart } from '../../../../../plugins/embeddable/public';
import { Storage } from '../../../../../plugins/kibana_utils/public';
import { NavigationPublicPluginStart as NavigationStart } from '../../../../../plugins/navigation/public';
import { DashboardConstants } from './np_ready/dashboard_constants';
@ -54,7 +54,7 @@ import { createKbnUrlTracker } from '../../../../../plugins/kibana_utils/public'
export interface DashboardPluginStartDependencies {
data: DataPublicPluginStart;
embeddable: IEmbeddableStart;
embeddable: EmbeddableStart;
navigation: NavigationStart;
share: SharePluginStart;
kibanaLegacy: KibanaLegacyStart;
@ -70,7 +70,7 @@ export class DashboardPlugin implements Plugin {
private startDependencies: {
data: DataPublicPluginStart;
savedObjectsClient: SavedObjectsClientContract;
embeddable: IEmbeddableStart;
embeddable: EmbeddableStart;
navigation: NavigationStart;
share: SharePluginStart;
dashboardConfig: KibanaLegacyStart['dashboardConfig'];

View file

@ -32,6 +32,11 @@ import { SearchEmbeddable } from './search_embeddable';
import { SearchInput, SearchOutput } from './types';
import { SEARCH_EMBEDDABLE_TYPE } from './constants';
interface StartServices {
executeTriggerActions: UiActionsStart['executeTriggerActions'];
isEditable: () => boolean;
}
export class SearchEmbeddableFactory extends EmbeddableFactory<
SearchInput,
SearchOutput,
@ -40,12 +45,10 @@ export class SearchEmbeddableFactory extends EmbeddableFactory<
public readonly type = SEARCH_EMBEDDABLE_TYPE;
private $injector: auto.IInjectorService | null;
private getInjector: () => Promise<auto.IInjectorService> | null;
public isEditable: () => boolean;
constructor(
private readonly executeTriggerActions: UiActionsStart['executeTriggerActions'],
getInjector: () => Promise<auto.IInjectorService>,
isEditable: () => boolean
private getStartServices: () => Promise<StartServices>,
getInjector: () => Promise<auto.IInjectorService>
) {
super({
savedObjectMetaData: {
@ -58,13 +61,16 @@ export class SearchEmbeddableFactory extends EmbeddableFactory<
});
this.$injector = null;
this.getInjector = getInjector;
this.isEditable = isEditable;
}
public canCreateNew() {
return false;
}
public async isEditable() {
return (await this.getStartServices()).isEditable();
}
public getDisplayName() {
return i18n.translate('kbn.embeddable.search.displayName', {
defaultMessage: 'search',
@ -90,6 +96,7 @@ export class SearchEmbeddableFactory extends EmbeddableFactory<
try {
const savedObject = await getServices().getSavedSearchById(savedObjectId);
const indexPattern = savedObject.searchSource.getField('index');
const { executeTriggerActions } = await this.getStartServices();
return new SearchEmbeddable(
{
savedSearch: savedObject,
@ -101,7 +108,7 @@ export class SearchEmbeddableFactory extends EmbeddableFactory<
indexPatterns: indexPattern ? [indexPattern] : [],
},
input,
this.executeTriggerActions,
executeTriggerActions,
parent
);
} catch (e) {

View file

@ -30,7 +30,7 @@ import {
} from '../../../../../plugins/data/public';
import { registerFeature } from './np_ready/register_feature';
import './kibana_services';
import { IEmbeddableStart, IEmbeddableSetup } from '../../../../../plugins/embeddable/public';
import { EmbeddableStart, EmbeddableSetup } from '../../../../../plugins/embeddable/public';
import { getInnerAngularModule, getInnerAngularModuleEmbeddable } from './get_inner_angular';
import { setAngularModule, setServices } from './kibana_services';
import { NavigationPublicPluginStart as NavigationStart } from '../../../../../plugins/navigation/public';
@ -63,7 +63,7 @@ export interface DiscoverSetup {
export type DiscoverStart = void;
export interface DiscoverSetupPlugins {
uiActions: UiActionsSetup;
embeddable: IEmbeddableSetup;
embeddable: EmbeddableSetup;
kibanaLegacy: KibanaLegacySetup;
home: HomePublicPluginSetup;
visualizations: VisualizationsSetup;
@ -71,7 +71,7 @@ export interface DiscoverSetupPlugins {
}
export interface DiscoverStartPlugins {
uiActions: UiActionsStart;
embeddable: IEmbeddableStart;
embeddable: EmbeddableStart;
navigation: NavigationStart;
charts: ChartsPluginStart;
data: DataPublicPluginStart;
@ -103,7 +103,7 @@ export class DiscoverPlugin implements Plugin<DiscoverSetup, DiscoverStart> {
public initializeInnerAngular?: () => void;
public initializeServices?: () => Promise<{ core: CoreStart; plugins: DiscoverStartPlugins }>;
setup(core: CoreSetup, plugins: DiscoverSetupPlugins): DiscoverSetup {
setup(core: CoreSetup<DiscoverStartPlugins>, plugins: DiscoverSetupPlugins): DiscoverSetup {
const { appMounted, appUnMounted, stop: stopUrlTracker } = createKbnUrlTracker({
baseUrl: core.http.basePath.prepend('/app/kibana'),
defaultSubUrl: '#/discover',
@ -173,6 +173,7 @@ export class DiscoverPlugin implements Plugin<DiscoverSetup, DiscoverStart> {
});
registerFeature(plugins.home);
this.registerEmbeddable(core, plugins);
return {
addDocView: this.docViewsRegistry.addDocView.bind(this.docViewsRegistry),
};
@ -203,8 +204,6 @@ export class DiscoverPlugin implements Plugin<DiscoverSetup, DiscoverStart> {
return { core, plugins };
};
this.registerEmbeddable(core, plugins);
}
stop() {
@ -216,19 +215,25 @@ export class DiscoverPlugin implements Plugin<DiscoverSetup, DiscoverStart> {
/**
* register embeddable with a slimmer embeddable version of inner angular
*/
private async registerEmbeddable(core: CoreStart, plugins: DiscoverStartPlugins) {
private async registerEmbeddable(
core: CoreSetup<DiscoverStartPlugins>,
plugins: DiscoverSetupPlugins
) {
const { SearchEmbeddableFactory } = await import('./np_ready/embeddable');
const isEditable = () => core.application.capabilities.discover.save as boolean;
if (!this.getEmbeddableInjector) {
throw Error('Discover plugin method getEmbeddableInjector is undefined');
}
const factory = new SearchEmbeddableFactory(
plugins.uiActions.executeTriggerActions,
this.getEmbeddableInjector,
isEditable
);
const getStartServices = async () => {
const [coreStart, deps] = await core.getStartServices();
return {
executeTriggerActions: deps.uiActions.executeTriggerActions,
isEditable: () => coreStart.application.capabilities.discover.save as boolean,
};
};
const factory = new SearchEmbeddableFactory(getStartServices, this.getEmbeddableInjector);
plugins.embeddable.registerEmbeddableFactory(factory.type, factory);
}

View file

@ -29,7 +29,7 @@ import {
import { NavigationPublicPluginStart as NavigationStart } from '../../../../../plugins/navigation/public';
import { Storage } from '../../../../../plugins/kibana_utils/public';
import { IEmbeddableStart } from '../../../../../plugins/embeddable/public';
import { EmbeddableStart } from '../../../../../plugins/embeddable/public';
import { SharePluginStart } from '../../../../../plugins/share/public';
import { DataPublicPluginStart, IndexPatternsContract } from '../../../../../plugins/data/public';
import { VisualizationsStart } from '../../../visualizations/public';
@ -44,7 +44,7 @@ export interface VisualizeKibanaServices {
chrome: ChromeStart;
core: CoreStart;
data: DataPublicPluginStart;
embeddable: IEmbeddableStart;
embeddable: EmbeddableStart;
getBasePath: () => string;
indexPatterns: IndexPatternsContract;
localStorage: Storage;

View file

@ -24,7 +24,7 @@ import {
DataPublicPluginStart,
SavedQuery,
} from 'src/plugins/data/public';
import { IEmbeddableStart } from 'src/plugins/embeddable/public';
import { EmbeddableStart } from 'src/plugins/embeddable/public';
import { PersistedState } from 'src/plugins/visualizations/public';
import { LegacyCoreStart } from 'kibana/public';
import { Vis } from 'src/legacy/core_plugins/visualizations/public';
@ -61,7 +61,7 @@ export interface EditorRenderProps {
appState: { save(): void };
core: LegacyCoreStart;
data: DataPublicPluginStart;
embeddable: IEmbeddableStart;
embeddable: EmbeddableStart;
filters: Filter[];
uiState: PersistedState;
timeRange: TimeRange;

View file

@ -36,7 +36,7 @@ import {
DataPublicPluginSetup,
esFilters,
} from '../../../../../plugins/data/public';
import { IEmbeddableStart } from '../../../../../plugins/embeddable/public';
import { EmbeddableStart } from '../../../../../plugins/embeddable/public';
import { NavigationPublicPluginStart as NavigationStart } from '../../../../../plugins/navigation/public';
import { SharePluginStart } from '../../../../../plugins/share/public';
import {
@ -55,7 +55,7 @@ import { DefaultEditorController } from '../../../vis_default_editor/public';
export interface VisualizePluginStartDependencies {
data: DataPublicPluginStart;
embeddable: IEmbeddableStart;
embeddable: EmbeddableStart;
navigation: NavigationStart;
share: SharePluginStart;
visualizations: VisualizationsStart;
@ -71,7 +71,7 @@ export interface VisualizePluginSetupDependencies {
export class VisualizePlugin implements Plugin {
private startDependencies: {
data: DataPublicPluginStart;
embeddable: IEmbeddableStart;
embeddable: EmbeddableStart;
navigation: NavigationStart;
savedObjectsClient: SavedObjectsClientContract;
share: SharePluginStart;

View file

@ -83,7 +83,7 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory<
});
}
public isEditable() {
public async isEditable() {
return getCapabilities().visualize.save as boolean;
}
@ -114,13 +114,14 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory<
const indexPattern = await getIndexPattern(savedObject);
const indexPatterns = indexPattern ? [indexPattern] : [];
const editable = await this.isEditable();
return new VisualizeEmbeddable(
getTimeFilter(),
{
savedVisualization: savedObject,
indexPatterns,
editUrl,
editable: this.isEditable(),
editable,
appState: input.appState,
uiState: input.uiState,
},

View file

@ -49,7 +49,7 @@ const createInstance = async () => {
const setup = plugin.setup(coreMock.createSetup(), {
data: dataPluginMock.createSetupContract(),
expressions: expressionsPluginMock.createSetupContract(),
embeddable: embeddablePluginMock.createStartContract(),
embeddable: embeddablePluginMock.createSetupContract(),
usageCollection: usageCollectionPluginMock.createSetupContract(),
});
const doStart = () =>

View file

@ -42,7 +42,7 @@ import {
} from './services';
import { VISUALIZE_EMBEDDABLE_TYPE, VisualizeEmbeddableFactory } from './embeddable';
import { ExpressionsSetup, ExpressionsStart } from '../../../../../../plugins/expressions/public';
import { IEmbeddableSetup } from '../../../../../../plugins/embeddable/public';
import { EmbeddableSetup } from '../../../../../../plugins/embeddable/public';
import { visualization as visualizationFunction } from './expressions/visualization_function';
import { visualization as visualizationRenderer } from './expressions/visualization_renderer';
import {
@ -73,7 +73,7 @@ export interface VisualizationsStart extends TypesStart {
export interface VisualizationsSetupDeps {
expressions: ExpressionsSetup;
embeddable: IEmbeddableSetup;
embeddable: EmbeddableSetup;
usageCollection: UsageCollectionSetup;
data: DataPublicPluginSetup;
}

View file

@ -20,7 +20,7 @@
import { IScope } from 'angular';
import { UiActionsStart, UiActionsSetup } from 'src/plugins/ui_actions/public';
import { IEmbeddableStart, IEmbeddableSetup } from 'src/plugins/embeddable/public';
import { EmbeddableStart, EmbeddableSetup } from 'src/plugins/embeddable/public';
import { createBrowserHistory } from 'history';
import {
LegacyCoreSetup,
@ -68,7 +68,7 @@ export interface PluginsSetup {
bfetch: BfetchPublicSetup;
charts: ChartsPluginSetup;
data: ReturnType<DataPlugin['setup']>;
embeddable: IEmbeddableSetup;
embeddable: EmbeddableSetup;
expressions: ReturnType<ExpressionsPlugin['setup']>;
home: HomePublicPluginSetup;
inspector: InspectorSetup;
@ -88,7 +88,7 @@ export interface PluginsStart {
bfetch: BfetchPublicStart;
charts: ChartsPluginStart;
data: ReturnType<DataPlugin['start']>;
embeddable: IEmbeddableStart;
embeddable: EmbeddableStart;
expressions: ReturnType<ExpressionsPlugin['start']>;
inspector: InspectorStart;
uiActions: UiActionsStart;

View file

@ -28,7 +28,6 @@ import {
ContactCardEmbeddableInput,
ContactCardEmbeddableOutput,
} from '../embeddable_plugin_test_samples';
import { DashboardOptions } from '../embeddable/dashboard_container_factory';
const embeddableFactories = new Map<string, EmbeddableFactory>();
embeddableFactories.set(
@ -40,7 +39,7 @@ let container: DashboardContainer;
let embeddable: ContactCardEmbeddable;
beforeEach(async () => {
const options: DashboardOptions = {
const options = {
ExitFullScreenButton: () => null,
SavedObjectFinder: () => null,
application: {} as any,

View file

@ -24,7 +24,7 @@ import {
IEmbeddable,
EmbeddableInput,
EmbeddableOutput,
IEmbeddableStart,
EmbeddableStart,
IContainer,
} from '../embeddable_plugin';
@ -34,7 +34,7 @@ export async function openReplacePanelFlyout(options: {
savedObjectFinder: React.ComponentType<any>;
notifications: CoreStart['notifications'];
panelToRemove: IEmbeddable<EmbeddableInput, EmbeddableOutput>;
getEmbeddableFactories: IEmbeddableStart['getEmbeddableFactories'];
getEmbeddableFactories: EmbeddableStart['getEmbeddableFactories'];
}) {
const {
embeddable,

View file

@ -27,7 +27,6 @@ import {
ContactCardEmbeddableInput,
ContactCardEmbeddableOutput,
} from '../embeddable_plugin_test_samples';
import { DashboardOptions } from '../embeddable/dashboard_container_factory';
import { coreMock } from '../../../../core/public/mocks';
import { CoreStart } from 'kibana/public';
@ -43,7 +42,7 @@ let embeddable: ContactCardEmbeddable;
let coreStart: CoreStart;
beforeEach(async () => {
coreStart = coreMock.createStart();
const options: DashboardOptions = {
const options = {
ExitFullScreenButton: () => null,
SavedObjectFinder: () => null,
application: {} as any,

View file

@ -19,7 +19,7 @@
import { i18n } from '@kbn/i18n';
import { CoreStart } from '../../../../core/public';
import { IEmbeddable, ViewMode, IEmbeddableStart } from '../embeddable_plugin';
import { IEmbeddable, ViewMode, EmbeddableStart } from '../embeddable_plugin';
import { DASHBOARD_CONTAINER_TYPE, DashboardContainer } from '../embeddable';
import { ActionByType, IncompatibleActionError } from '../ui_actions_plugin';
import { openReplacePanelFlyout } from './open_replace_panel_flyout';
@ -43,7 +43,7 @@ export class ReplacePanelAction implements ActionByType<typeof ACTION_REPLACE_PA
private core: CoreStart,
private savedobjectfinder: React.ComponentType<any>,
private notifications: CoreStart['notifications'],
private getEmbeddableFactories: IEmbeddableStart['getEmbeddableFactories']
private getEmbeddableFactories: EmbeddableStart['getEmbeddableFactories']
) {}
public getDisplayName({ embeddable }: ReplacePanelActionContext) {

View file

@ -20,7 +20,7 @@
import { i18n } from '@kbn/i18n';
import React from 'react';
import { EuiFlyout, EuiFlyoutBody, EuiFlyoutHeader, EuiTitle } from '@elastic/eui';
import { GetEmbeddableFactories } from 'src/plugins/embeddable/public';
import { EmbeddableStart } from '../../../../../src/plugins/embeddable/public';
import { DashboardPanelState } from '../embeddable';
import { NotificationsStart, Toast } from '../../../../core/public';
import { IContainer, IEmbeddable, EmbeddableInput, EmbeddableOutput } from '../embeddable_plugin';
@ -31,7 +31,7 @@ interface Props {
onClose: () => void;
notifications: NotificationsStart;
panelToRemove: IEmbeddable<EmbeddableInput, EmbeddableOutput>;
getEmbeddableFactories: GetEmbeddableFactories;
getEmbeddableFactories: EmbeddableStart['getEmbeddableFactories'];
}
export class ReplacePanelFlyout extends React.Component<Props> {

View file

@ -30,7 +30,7 @@ import {
ViewMode,
EmbeddableFactory,
IEmbeddable,
IEmbeddableStart,
EmbeddableStart,
} from '../embeddable_plugin';
import { DASHBOARD_CONTAINER_TYPE } from './dashboard_constants';
import { createPanelState } from './panel';
@ -77,7 +77,7 @@ export interface DashboardContainerOptions {
application: CoreStart['application'];
overlays: CoreStart['overlays'];
notifications: CoreStart['notifications'];
embeddable: IEmbeddableStart;
embeddable: EmbeddableStart;
inspector: InspectorStartContract;
SavedObjectFinder: React.ComponentType<any>;
ExitFullScreenButton: React.ComponentType<any>;

View file

@ -18,24 +18,29 @@
*/
import { i18n } from '@kbn/i18n';
import { SavedObjectMetaData } from '../../../saved_objects/public';
import { SavedObjectAttributes } from '../../../../core/public';
import { UiActionsStart } from '../../../../../src/plugins/ui_actions/public';
import { EmbeddableStart } from '../../../../../src/plugins/embeddable/public';
import { CoreStart } from '../../../../core/public';
import {
ContainerOutput,
EmbeddableFactory,
ErrorEmbeddable,
Container,
} from '../embeddable_plugin';
import {
DashboardContainer,
DashboardContainerInput,
DashboardContainerOptions,
} from './dashboard_container';
import { DashboardCapabilities } from '../types';
import { DashboardContainer, DashboardContainerInput } from './dashboard_container';
import { DASHBOARD_CONTAINER_TYPE } from './dashboard_constants';
import { Start as InspectorStartContract } from '../../../inspector/public';
export interface DashboardOptions extends DashboardContainerOptions {
savedObjectMetaData?: SavedObjectMetaData<SavedObjectAttributes>;
interface StartServices {
capabilities: CoreStart['application']['capabilities'];
application: CoreStart['application'];
overlays: CoreStart['overlays'];
notifications: CoreStart['notifications'];
embeddable: EmbeddableStart;
inspector: InspectorStartContract;
SavedObjectFinder: React.ComponentType<any>;
ExitFullScreenButton: React.ComponentType<any>;
uiActions: UiActionsStart;
}
export class DashboardContainerFactory extends EmbeddableFactory<
@ -45,23 +50,13 @@ export class DashboardContainerFactory extends EmbeddableFactory<
public readonly isContainerType = true;
public readonly type = DASHBOARD_CONTAINER_TYPE;
private readonly allowEditing: boolean;
constructor(private readonly options: DashboardOptions) {
super({ savedObjectMetaData: options.savedObjectMetaData });
const capabilities = (options.application.capabilities
.dashboard as unknown) as DashboardCapabilities;
if (!capabilities || typeof capabilities !== 'object') {
throw new TypeError('Dashboard capabilities not found.');
}
this.allowEditing = !!capabilities.createNew && !!capabilities.showWriteControls;
constructor(private readonly getStartServices: () => Promise<StartServices>) {
super();
}
public isEditable() {
return this.allowEditing;
public async isEditable() {
const { capabilities } = await this.getStartServices();
return !!capabilities.createNew && !!capabilities.showWriteControls;
}
public getDisplayName() {
@ -82,6 +77,7 @@ export class DashboardContainerFactory extends EmbeddableFactory<
initialInput: DashboardContainerInput,
parent?: Container
): Promise<DashboardContainer | ErrorEmbeddable> {
return new DashboardContainer(initialInput, this.options, parent);
const services = await this.getStartServices();
return new DashboardContainer(initialInput, services, parent);
}
}

View file

@ -23,7 +23,7 @@ import sizeMe from 'react-sizeme';
import React from 'react';
import { mountWithIntl } from 'test_utils/enzyme_helpers';
import { skip } from 'rxjs/operators';
import { EmbeddableFactory, GetEmbeddableFactory } from '../../embeddable_plugin';
import { EmbeddableFactory } from '../../embeddable_plugin';
import { DashboardGrid, DashboardGridProps } from './dashboard_grid';
import { DashboardContainer, DashboardContainerOptions } from '../dashboard_container';
import { getSampleDashboardInput } from '../../test_helpers';
@ -41,7 +41,7 @@ function prepare(props?: Partial<DashboardGridProps>) {
CONTACT_CARD_EMBEDDABLE,
new ContactCardEmbeddableFactory({} as any, (() => {}) as any, {} as any)
);
const getEmbeddableFactory: GetEmbeddableFactory = (id: string) => embeddableFactories.get(id);
const getEmbeddableFactory = (id: string) => embeddableFactories.get(id);
const initialInput = getSampleDashboardInput({
panels: {
'1': {

View file

@ -23,7 +23,7 @@ import * as React from 'react';
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from 'src/core/public';
import { SharePluginSetup } from 'src/plugins/share/public';
import { UiActionsSetup, UiActionsStart } from '../../../plugins/ui_actions/public';
import { CONTEXT_MENU_TRIGGER, IEmbeddableSetup, IEmbeddableStart } from './embeddable_plugin';
import { CONTEXT_MENU_TRIGGER, EmbeddableSetup, EmbeddableStart } from './embeddable_plugin';
import { ExpandPanelAction, ReplacePanelAction } from '.';
import { DashboardContainerFactory } from './embeddable/dashboard_container_factory';
import { Start as InspectorStartContract } from '../../../plugins/inspector/public';
@ -47,13 +47,13 @@ declare module '../../share/public' {
}
interface SetupDependencies {
embeddable: IEmbeddableSetup;
embeddable: EmbeddableSetup;
uiActions: UiActionsSetup;
share?: SharePluginSetup;
}
interface StartDependencies {
embeddable: IEmbeddableStart;
embeddable: EmbeddableStart;
inspector: InspectorStartContract;
uiActions: UiActionsStart;
}
@ -72,7 +72,10 @@ export class DashboardEmbeddableContainerPublicPlugin
implements Plugin<Setup, Start, SetupDependencies, StartDependencies> {
constructor(initializerContext: PluginInitializerContext) {}
public setup(core: CoreSetup, { share, uiActions }: SetupDependencies): Setup {
public setup(
core: CoreSetup<StartDependencies>,
{ share, uiActions, embeddable }: SetupDependencies
): Setup {
const expandPanelAction = new ExpandPanelAction();
uiActions.registerAction(expandPanelAction);
uiActions.attachAction(CONTEXT_MENU_TRIGGER, expandPanelAction);
@ -86,26 +89,44 @@ export class DashboardEmbeddableContainerPublicPlugin
}))
);
}
const getStartServices = async () => {
const [coreStart, deps] = await core.getStartServices();
const useHideChrome = () => {
React.useEffect(() => {
coreStart.chrome.setIsVisible(false);
return () => coreStart.chrome.setIsVisible(true);
}, []);
};
const ExitFullScreenButton: React.FC<ExitFullScreenButtonProps> = props => {
useHideChrome();
return <ExitFullScreenButtonUi {...props} />;
};
return {
capabilities: coreStart.application.capabilities,
application: coreStart.application,
notifications: coreStart.notifications,
overlays: coreStart.overlays,
embeddable: deps.embeddable,
inspector: deps.inspector,
SavedObjectFinder: getSavedObjectFinder(coreStart.savedObjects, coreStart.uiSettings),
ExitFullScreenButton,
uiActions: deps.uiActions,
};
};
const factory = new DashboardContainerFactory(getStartServices);
embeddable.registerEmbeddableFactory(factory.type, factory);
}
public start(core: CoreStart, plugins: StartDependencies): Start {
const { application, notifications, overlays } = core;
const { embeddable, inspector, uiActions } = plugins;
const { notifications } = core;
const { uiActions } = plugins;
const SavedObjectFinder = getSavedObjectFinder(core.savedObjects, core.uiSettings);
const useHideChrome = () => {
React.useEffect(() => {
core.chrome.setIsVisible(false);
return () => core.chrome.setIsVisible(true);
}, []);
};
const ExitFullScreenButton: React.FC<ExitFullScreenButtonProps> = props => {
useHideChrome();
return <ExitFullScreenButtonUi {...props} />;
};
const changeViewAction = new ReplacePanelAction(
core,
SavedObjectFinder,
@ -114,19 +135,6 @@ export class DashboardEmbeddableContainerPublicPlugin
);
uiActions.registerAction(changeViewAction);
uiActions.attachAction(CONTEXT_MENU_TRIGGER, changeViewAction);
const factory = new DashboardContainerFactory({
application,
notifications,
overlays,
embeddable,
inspector,
SavedObjectFinder,
ExitFullScreenButton,
uiActions,
});
embeddable.registerEmbeddableFactory(factory.type, factory);
}
public stop() {}

View file

@ -1,26 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { EmbeddableApiPure } from './types';
export const getEmbeddableFactories: EmbeddableApiPure['getEmbeddableFactories'] = ({
embeddableFactories,
}) => () => {
return embeddableFactories.values();
};

View file

@ -1,34 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { EmbeddableApiPure } from './types';
export const getEmbeddableFactory: EmbeddableApiPure['getEmbeddableFactory'] = ({
embeddableFactories,
}) => embeddableFactoryId => {
const factory = embeddableFactories.get(embeddableFactoryId);
if (!factory) {
throw new Error(
`Embeddable factory [embeddableFactoryId = ${embeddableFactoryId}] does not exist.`
);
}
return factory;
};

View file

@ -1,47 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import {
EmbeddableApiPure,
EmbeddableDependencies,
EmbeddableApi,
EmbeddableDependenciesInternal,
} from './types';
import { getEmbeddableFactories } from './get_embeddable_factories';
import { getEmbeddableFactory } from './get_embeddable_factory';
import { registerEmbeddableFactory } from './register_embeddable_factory';
export * from './types';
export const pureApi: EmbeddableApiPure = {
getEmbeddableFactories,
getEmbeddableFactory,
registerEmbeddableFactory,
};
export const createApi = (deps: EmbeddableDependencies) => {
const partialApi: Partial<EmbeddableApi> = {};
const depsInternal: EmbeddableDependenciesInternal = { ...deps, api: partialApi };
for (const [key, fn] of Object.entries(pureApi)) {
(partialApi as any)[key] = fn(depsInternal);
}
Object.freeze(partialApi);
const api = partialApi as EmbeddableApi;
return { api, depsInternal };
};

View file

@ -1,32 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { EmbeddableApiPure } from './types';
export const registerEmbeddableFactory: EmbeddableApiPure['registerEmbeddableFactory'] = ({
embeddableFactories,
}) => (embeddableFactoryId, factory) => {
if (embeddableFactories.has(embeddableFactoryId)) {
throw new Error(
`Embeddable factory [embeddableFactoryId = ${embeddableFactoryId}] already registered in Embeddables API.`
);
}
embeddableFactories.set(embeddableFactoryId, factory);
};

View file

@ -1,27 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { EmbeddableDependencies } from '../types';
export const createDeps = (): EmbeddableDependencies => {
const deps: EmbeddableDependencies = {
embeddableFactories: new Map<any, any>(),
};
return deps;
};

View file

@ -1,43 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { EmbeddableFactoryRegistry } from '../types';
import { EmbeddableFactory, GetEmbeddableFactories } from '../lib';
export interface EmbeddableApi {
getEmbeddableFactory: (embeddableFactoryId: string) => EmbeddableFactory;
getEmbeddableFactories: GetEmbeddableFactories;
// TODO: Make `registerEmbeddableFactory` receive only `factory` argument.
registerEmbeddableFactory: <TEmbeddableFactory extends EmbeddableFactory>(
id: string,
factory: TEmbeddableFactory
) => void;
}
export interface EmbeddableDependencies {
embeddableFactories: EmbeddableFactoryRegistry;
}
export interface EmbeddableDependenciesInternal extends EmbeddableDependencies {
api: Readonly<Partial<EmbeddableApi>>;
}
export type EmbeddableApiPure = {
[K in keyof EmbeddableApi]: (deps: EmbeddableDependenciesInternal) => EmbeddableApi[K];
};

View file

@ -48,8 +48,6 @@ export {
EmbeddableRoot,
EmbeddableVisTriggerContext,
ErrorEmbeddable,
GetEmbeddableFactories,
GetEmbeddableFactory,
IContainer,
IEmbeddable,
isErrorEmbeddable,
@ -68,4 +66,4 @@ export function plugin(initializerContext: PluginInitializerContext) {
return new EmbeddablePublicPlugin(initializerContext);
}
export { IEmbeddableSetup, IEmbeddableStart } from './plugin';
export { EmbeddableSetup, EmbeddableStart } from './plugin';

View file

@ -19,11 +19,13 @@
import { EditPanelAction } from './edit_panel_action';
import { EmbeddableFactory, Embeddable, EmbeddableInput } from '../embeddables';
import { GetEmbeddableFactory, ViewMode } from '../types';
import { ViewMode } from '../types';
import { ContactCardEmbeddable } from '../test_samples';
import { EmbeddableStart } from '../../plugin';
const embeddableFactories = new Map<string, EmbeddableFactory>();
const getFactory: GetEmbeddableFactory = (id: string) => embeddableFactories.get(id);
const getFactory = ((id: string) =>
embeddableFactories.get(id)) as EmbeddableStart['getEmbeddableFactory'];
class EditableEmbeddable extends Embeddable {
public readonly type = 'EDITABLE_EMBEDDABLE';
@ -82,7 +84,8 @@ test('is not compatible when edit url is not available', async () => {
test('is not visible when edit url is available but in view mode', async () => {
embeddableFactories.clear();
const action = new EditPanelAction(type => embeddableFactories.get(type));
const action = new EditPanelAction((type =>
embeddableFactories.get(type)) as EmbeddableStart['getEmbeddableFactory']);
expect(
await action.isCompatible({
embeddable: new EditableEmbeddable(
@ -98,7 +101,8 @@ test('is not visible when edit url is available but in view mode', async () => {
test('is not compatible when edit url is available, in edit mode, but not editable', async () => {
embeddableFactories.clear();
const action = new EditPanelAction(type => embeddableFactories.get(type));
const action = new EditPanelAction((type =>
embeddableFactories.get(type)) as EmbeddableStart['getEmbeddableFactory']);
expect(
await action.isCompatible({
embeddable: new EditableEmbeddable(

View file

@ -19,9 +19,10 @@
import { i18n } from '@kbn/i18n';
import { Action } from 'src/plugins/ui_actions/public';
import { GetEmbeddableFactory, ViewMode } from '../types';
import { ViewMode } from '../types';
import { EmbeddableFactoryNotFoundError } from '../errors';
import { IEmbeddable } from '../embeddables';
import { EmbeddableStart } from '../../plugin';
export const ACTION_EDIT_PANEL = 'editPanel';
@ -34,7 +35,7 @@ export class EditPanelAction implements Action<ActionContext> {
public readonly id = ACTION_EDIT_PANEL;
public order = 15;
constructor(private readonly getEmbeddableFactory: GetEmbeddableFactory) {}
constructor(private readonly getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory']) {}
public getDisplayName({ embeddable }: ActionContext) {
const factory = this.getEmbeddableFactory(embeddable.type);

View file

@ -29,7 +29,7 @@ import {
} from '../embeddables';
import { IContainer, ContainerInput, ContainerOutput, PanelState } from './i_container';
import { PanelNotFoundError, EmbeddableFactoryNotFoundError } from '../errors';
import { GetEmbeddableFactory } from '../types';
import { EmbeddableStart } from '../../plugin';
const getKeys = <T extends {}>(o: T): Array<keyof T> => Object.keys(o) as Array<keyof T>;
@ -49,7 +49,7 @@ export abstract class Container<
constructor(
input: TContainerInput,
output: TContainerOutput,
protected readonly getFactory: GetEmbeddableFactory,
protected readonly getFactory: EmbeddableStart['getEmbeddableFactory'],
parent?: Container
) {
super(input, output, parent);

View file

@ -20,7 +20,6 @@
import React from 'react';
import { nextTick } from 'test_utils/enzyme_helpers';
import { EmbeddableChildPanel } from './embeddable_child_panel';
import { GetEmbeddableFactory } from '../types';
import { EmbeddableFactory } from '../embeddables';
import { CONTACT_CARD_EMBEDDABLE } from '../test_samples/embeddables/contact_card/contact_card_embeddable_factory';
import { SlowContactCardEmbeddableFactory } from '../test_samples/embeddables/contact_card/slow_contact_card_embeddable_factory';
@ -42,7 +41,7 @@ test('EmbeddableChildPanel renders an embeddable when it is done loading', async
CONTACT_CARD_EMBEDDABLE,
new SlowContactCardEmbeddableFactory({ execAction: (() => null) as any })
);
const getEmbeddableFactory: GetEmbeddableFactory = (id: string) => embeddableFactories.get(id);
const getEmbeddableFactory = (id: string) => embeddableFactories.get(id);
const container = new HelloWorldContainer({ id: 'hello', panels: {} }, {
getEmbeddableFactory,
@ -88,7 +87,7 @@ test('EmbeddableChildPanel renders an embeddable when it is done loading', async
test(`EmbeddableChildPanel renders an error message if the factory doesn't exist`, async () => {
const inspector = inspectorPluginMock.createStartContract();
const getEmbeddableFactory: GetEmbeddableFactory = () => undefined;
const getEmbeddableFactory = () => undefined;
const container = new HelloWorldContainer(
{
id: 'hello',

View file

@ -29,15 +29,15 @@ import { Start as InspectorStartContract } from 'src/plugins/inspector/public';
import { ErrorEmbeddable, IEmbeddable } from '../embeddables';
import { EmbeddablePanel } from '../panel';
import { IContainer } from './i_container';
import { GetEmbeddableFactory, GetEmbeddableFactories } from '../types';
import { EmbeddableStart } from '../../plugin';
export interface EmbeddableChildPanelProps {
embeddableId: string;
className?: string;
container: IContainer;
getActions: UiActionsService['getTriggerCompatibleActions'];
getEmbeddableFactory: GetEmbeddableFactory;
getAllEmbeddableFactories: GetEmbeddableFactories;
getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
getAllEmbeddableFactories: EmbeddableStart['getEmbeddableFactories'];
overlays: CoreStart['overlays'];
notifications: CoreStart['notifications'];
inspector: InspectorStartContract;

View file

@ -74,13 +74,11 @@ export abstract class EmbeddableFactory<
this.savedObjectMetaData = savedObjectMetaData;
}
// TODO: Can this be a property? If this "...should be based of capabilities service...",
// TODO: maybe then it should be *async*?
/**
* Returns whether the current user should be allowed to edit this type of
* embeddable. Most of the time this should be based off the capabilities service.
* embeddable. Most of the time this should be based off the capabilities service, hence it's async.
*/
public abstract isEditable(): boolean;
public abstract async isEditable(): Promise<boolean>;
/**
* Returns a display name for this type of embeddable. Used in "Create new... " options

View file

@ -22,21 +22,21 @@ import {
HelloWorldEmbeddableFactory,
} from '../../../../../../examples/embeddable_examples/public';
import { EmbeddableFactory } from './embeddable_factory';
import { GetEmbeddableFactory } from '../types';
import { EmbeddableFactoryRenderer } from './embeddable_factory_renderer';
import { mount } from 'enzyme';
import { nextTick } from 'test_utils/enzyme_helpers';
// @ts-ignore
import { findTestSubject } from '@elastic/eui/lib/test';
import { EmbeddableStart } from '../../plugin';
test('EmbeddableFactoryRenderer renders an embeddable', async () => {
const embeddableFactories = new Map<string, EmbeddableFactory>();
embeddableFactories.set(HELLO_WORLD_EMBEDDABLE, new HelloWorldEmbeddableFactory());
const getEmbeddableFactory: GetEmbeddableFactory = (id: string) => embeddableFactories.get(id);
const getEmbeddableFactory = (id: string) => embeddableFactories.get(id);
const component = mount(
<EmbeddableFactoryRenderer
getEmbeddableFactory={getEmbeddableFactory}
getEmbeddableFactory={getEmbeddableFactory as EmbeddableStart['getEmbeddableFactory']}
type={HELLO_WORLD_EMBEDDABLE}
input={{ id: '123' }}
/>
@ -54,7 +54,7 @@ test('EmbeddableFactoryRenderer renders an embeddable', async () => {
});
test('EmbeddableRoot renders an error if the type does not exist', async () => {
const getEmbeddableFactory: GetEmbeddableFactory = (id: string) => undefined;
const getEmbeddableFactory = (id: string) => undefined;
const component = mount(
<EmbeddableFactoryRenderer

View file

@ -21,11 +21,11 @@ import React from 'react';
import { i18n } from '@kbn/i18n';
import { IEmbeddable, EmbeddableInput } from './i_embeddable';
import { EmbeddableRoot } from './embeddable_root';
import { GetEmbeddableFactory } from '../types';
import { EmbeddableStart } from '../../plugin';
interface Props {
type: string;
getEmbeddableFactory: GetEmbeddableFactory;
getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
input: EmbeddableInput;
}

View file

@ -26,7 +26,7 @@ import { findTestSubject } from '@elastic/eui/lib/test';
import { I18nProvider } from '@kbn/i18n/react';
import { CONTEXT_MENU_TRIGGER } from '../triggers';
import { Action, UiActionsStart, ActionType } from 'src/plugins/ui_actions/public';
import { Trigger, GetEmbeddableFactory, ViewMode } from '../types';
import { Trigger, ViewMode } from '../types';
import { EmbeddableFactory, isErrorEmbeddable } from '../embeddables';
import { EmbeddablePanel } from './embeddable_panel';
import { createEditModeAction } from '../test_samples/actions';
@ -47,7 +47,7 @@ import { EuiBadge } from '@elastic/eui';
const actionRegistry = new Map<string, Action<object | undefined | string | number>>();
const triggerRegistry = new Map<string, Trigger>();
const embeddableFactories = new Map<string, EmbeddableFactory>();
const getEmbeddableFactory: GetEmbeddableFactory = (id: string) => embeddableFactories.get(id);
const getEmbeddableFactory = (id: string) => embeddableFactories.get(id);
const editModeAction = createEditModeAction();
const trigger: Trigger = {

View file

@ -27,7 +27,7 @@ import { toMountPoint } from '../../../../kibana_react/public';
import { Start as InspectorStartContract } from '../inspector';
import { CONTEXT_MENU_TRIGGER, PANEL_BADGE_TRIGGER, EmbeddableContext } from '../triggers';
import { IEmbeddable } from '../embeddables/i_embeddable';
import { ViewMode, GetEmbeddableFactory, GetEmbeddableFactories } from '../types';
import { ViewMode } from '../types';
import { RemovePanelAction } from './panel_header/panel_actions';
import { AddPanelAction } from './panel_header/panel_actions/add_panel/add_panel_action';
@ -36,12 +36,13 @@ import { PanelHeader } from './panel_header/panel_header';
import { InspectPanelAction } from './panel_header/panel_actions/inspect_panel_action';
import { EditPanelAction } from '../actions';
import { CustomizePanelModal } from './panel_header/panel_actions/customize_title/customize_panel_modal';
import { EmbeddableStart } from '../../plugin';
interface Props {
embeddable: IEmbeddable<any, any>;
getActions: UiActionsService['getTriggerCompatibleActions'];
getEmbeddableFactory: GetEmbeddableFactory;
getAllEmbeddableFactories: GetEmbeddableFactories;
getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
getAllEmbeddableFactories: EmbeddableStart['getEmbeddableFactories'];
overlays: CoreStart['overlays'];
notifications: CoreStart['notifications'];
inspector: InspectorStartContract;

View file

@ -27,15 +27,15 @@ import {
} from '../../../../test_samples/embeddables/filterable_embeddable';
import { FilterableEmbeddableFactory } from '../../../../test_samples/embeddables/filterable_embeddable_factory';
import { FilterableContainer } from '../../../../test_samples/embeddables/filterable_container';
import { GetEmbeddableFactory } from '../../../../types';
// eslint-disable-next-line
import { coreMock } from '../../../../../../../../core/public/mocks';
import { ContactCardEmbeddable } from '../../../../test_samples';
import { esFilters, Filter } from '../../../../../../../../plugins/data/public';
import { EmbeddableStart } from 'src/plugins/embeddable/public/plugin';
const embeddableFactories = new Map<string, EmbeddableFactory>();
embeddableFactories.set(FILTERABLE_EMBEDDABLE, new FilterableEmbeddableFactory());
const getFactory: GetEmbeddableFactory = (id: string) => embeddableFactories.get(id);
const getFactory = (id: string) => embeddableFactories.get(id);
let container: FilterableContainer;
let embeddable: FilterableEmbeddable;
@ -58,7 +58,7 @@ beforeEach(async () => {
};
container = new FilterableContainer(
{ id: 'hello', panels: {}, filters: [derivedFilter] },
getFactory
getFactory as EmbeddableStart['getEmbeddableFactory']
);
const filterableEmbeddable = await container.addNewEmbeddable<

View file

@ -19,7 +19,8 @@
import { i18n } from '@kbn/i18n';
import { Action } from 'src/plugins/ui_actions/public';
import { NotificationsStart, OverlayStart } from 'src/core/public';
import { ViewMode, GetEmbeddableFactory, GetEmbeddableFactories } from '../../../../types';
import { EmbeddableStart } from 'src/plugins/embeddable/public/plugin';
import { ViewMode } from '../../../../types';
import { openAddPanelFlyout } from './open_add_panel_flyout';
import { IContainer } from '../../../../containers';
@ -34,8 +35,8 @@ export class AddPanelAction implements Action<ActionContext> {
public readonly id = ACTION_ADD_PANEL;
constructor(
private readonly getFactory: GetEmbeddableFactory,
private readonly getAllFactories: GetEmbeddableFactories,
private readonly getFactory: EmbeddableStart['getEmbeddableFactory'],
private readonly getAllFactories: EmbeddableStart['getEmbeddableFactories'],
private readonly overlays: OverlayStart,
private readonly notifications: NotificationsStart,
private readonly SavedObjectFinder: React.ComponentType<any>

View file

@ -19,7 +19,6 @@
import * as React from 'react';
import { AddPanelFlyout } from './add_panel_flyout';
import { GetEmbeddableFactory } from '../../../../types';
import {
ContactCardEmbeddableFactory,
CONTACT_CARD_EMBEDDABLE,
@ -32,6 +31,7 @@ import { ReactWrapper } from 'enzyme';
import { coreMock } from '../../../../../../../../core/public/mocks';
// @ts-ignore
import { findTestSubject } from '@elastic/eui/lib/test';
import { EmbeddableStart } from 'src/plugins/embeddable/public/plugin';
function DummySavedObjectFinder(props: { children: React.ReactNode }) {
return (
@ -55,7 +55,7 @@ test('createNewEmbeddable() add embeddable to container', async () => {
firstName: 'foo',
lastName: 'bar',
} as any);
const getEmbeddableFactory: GetEmbeddableFactory = (id: string) => contactCardEmbeddableFactory;
const getEmbeddableFactory = (id: string) => contactCardEmbeddableFactory;
const input: ContainerInput<{ firstName: string; lastName: string }> = {
id: '1',
panels: {},
@ -66,7 +66,7 @@ test('createNewEmbeddable() add embeddable to container', async () => {
<AddPanelFlyout
container={container}
onClose={onClose}
getFactory={getEmbeddableFactory}
getFactory={getEmbeddableFactory as EmbeddableStart['getEmbeddableFactory']}
getAllFactories={() => new Set<any>([contactCardEmbeddableFactory]).values()}
notifications={core.notifications}
SavedObjectFinder={() => null}
@ -100,7 +100,8 @@ test('selecting embeddable in "Create new ..." list calls createNewEmbeddable()'
firstName: 'foo',
lastName: 'bar',
} as any);
const getEmbeddableFactory: GetEmbeddableFactory = (id: string) => contactCardEmbeddableFactory;
const getEmbeddableFactory = ((id: string) =>
contactCardEmbeddableFactory) as EmbeddableStart['getEmbeddableFactory'];
const input: ContainerInput<{ firstName: string; lastName: string }> = {
id: '1',
panels: {},

View file

@ -29,16 +29,16 @@ import {
EuiTitle,
} from '@elastic/eui';
import { EmbeddableStart } from 'src/plugins/embeddable/public/plugin';
import { IContainer } from '../../../../containers';
import { EmbeddableFactoryNotFoundError } from '../../../../errors';
import { GetEmbeddableFactories, GetEmbeddableFactory } from '../../../../types';
import { SavedObjectFinderCreateNew } from './saved_object_finder_create_new';
interface Props {
onClose: () => void;
container: IContainer;
getFactory: GetEmbeddableFactory;
getAllFactories: GetEmbeddableFactories;
getFactory: EmbeddableStart['getEmbeddableFactory'];
getAllFactories: EmbeddableStart['getEmbeddableFactories'];
notifications: CoreSetup['notifications'];
SavedObjectFinder: React.ComponentType<any>;
}

View file

@ -18,15 +18,15 @@
*/
import React from 'react';
import { NotificationsStart, OverlayStart } from 'src/core/public';
import { EmbeddableStart } from '../../../../../plugin';
import { toMountPoint } from '../../../../../../../kibana_react/public';
import { IContainer } from '../../../../containers';
import { AddPanelFlyout } from './add_panel_flyout';
import { GetEmbeddableFactory, GetEmbeddableFactories } from '../../../../types';
export async function openAddPanelFlyout(options: {
embeddable: IContainer;
getFactory: GetEmbeddableFactory;
getAllFactories: GetEmbeddableFactories;
getFactory: EmbeddableStart['getEmbeddableFactory'];
getAllFactories: EmbeddableStart['getEmbeddableFactories'];
overlays: OverlayStart;
notifications: NotificationsStart;
SavedObjectFinder: React.ComponentType<any>;

View file

@ -32,7 +32,6 @@ import {
ContactCardEmbeddableFactory,
} from '../../../../test_samples/embeddables/contact_card/contact_card_embeddable_factory';
import { HelloWorldContainer } from '../../../../test_samples/embeddables/hello_world_container';
import { GetEmbeddableFactory } from '../../../../types';
import { EmbeddableFactory } from '../../../../embeddables';
let container: Container;
@ -40,7 +39,7 @@ let embeddable: ContactCardEmbeddable;
function createHelloWorldContainer(input = { id: '123', panels: {} }) {
const embeddableFactories = new Map<string, EmbeddableFactory>();
const getEmbeddableFactory: GetEmbeddableFactory = (id: string) => embeddableFactories.get(id);
const getEmbeddableFactory = (id: string) => embeddableFactories.get(id);
embeddableFactories.set(
CONTACT_CARD_EMBEDDABLE,
new ContactCardEmbeddableFactory({}, (() => {}) as any, {} as any)

View file

@ -34,14 +34,14 @@ import {
isErrorEmbeddable,
ErrorEmbeddable,
} from '../../../embeddables';
import { GetEmbeddableFactory } from '../../../types';
import { of } from '../../../../tests/helpers';
import { esFilters } from '../../../../../../../plugins/data/public';
import { EmbeddableStart } from 'src/plugins/embeddable/public/plugin';
const setup = async () => {
const embeddableFactories = new Map<string, EmbeddableFactory>();
embeddableFactories.set(FILTERABLE_EMBEDDABLE, new FilterableEmbeddableFactory());
const getFactory: GetEmbeddableFactory = (id: string) => embeddableFactories.get(id);
const getFactory = (id: string) => embeddableFactories.get(id);
const container = new FilterableContainer(
{
id: 'hello',
@ -54,7 +54,7 @@ const setup = async () => {
},
],
},
getFactory
getFactory as EmbeddableStart['getEmbeddableFactory']
);
const embeddable: FilterableEmbeddable | ErrorEmbeddable = await container.addNewEmbeddable<

View file

@ -20,6 +20,7 @@
import { EmbeddableOutput, isErrorEmbeddable } from '../../../';
import { RemovePanelAction } from './remove_panel_action';
import { EmbeddableFactory } from '../../../embeddables';
import { EmbeddableStart } from '../../../../plugin';
import {
FILTERABLE_EMBEDDABLE,
FilterableEmbeddable,
@ -27,13 +28,13 @@ import {
} from '../../../test_samples/embeddables/filterable_embeddable';
import { FilterableEmbeddableFactory } from '../../../test_samples/embeddables/filterable_embeddable_factory';
import { FilterableContainer } from '../../../test_samples/embeddables/filterable_container';
import { GetEmbeddableFactory, ViewMode } from '../../../types';
import { ViewMode } from '../../../types';
import { ContactCardEmbeddable } from '../../../test_samples/embeddables/contact_card/contact_card_embeddable';
import { esFilters, Filter } from '../../../../../../../plugins/data/public';
const embeddableFactories = new Map<string, EmbeddableFactory>();
embeddableFactories.set(FILTERABLE_EMBEDDABLE, new FilterableEmbeddableFactory());
const getFactory: GetEmbeddableFactory = (id: string) => embeddableFactories.get(id);
const getFactory = (id: string) => embeddableFactories.get(id);
let container: FilterableContainer;
let embeddable: FilterableEmbeddable;
@ -46,7 +47,7 @@ beforeEach(async () => {
};
container = new FilterableContainer(
{ id: 'hello', panels: {}, filters: [derivedFilter], viewMode: ViewMode.EDIT },
getFactory
getFactory as EmbeddableStart['getEmbeddableFactory']
);
const filterableEmbeddable = await container.addNewEmbeddable<

View file

@ -42,7 +42,7 @@ export class ContactCardEmbeddableFactory extends EmbeddableFactory<ContactCardE
super(options);
}
public isEditable() {
public async isEditable() {
return true;
}

View file

@ -40,7 +40,7 @@ export class SlowContactCardEmbeddableFactory extends EmbeddableFactory<
}
}
public isEditable() {
public async isEditable() {
return true;
}

View file

@ -18,8 +18,8 @@
*/
import { Container, ContainerInput } from '../../containers';
import { GetEmbeddableFactory } from '../../types';
import { Filter } from '../../../../../data/public';
import { EmbeddableStart } from '../../../plugin';
export const FILTERABLE_CONTAINER = 'FILTERABLE_CONTAINER';
@ -46,7 +46,7 @@ export class FilterableContainer extends Container<
constructor(
initialInput: FilterableContainerInput,
getFactory: GetEmbeddableFactory,
getFactory: EmbeddableStart['getEmbeddableFactory'],
parent?: Container
) {
super(initialInput, { embeddableLoaded: {} }, getFactory, parent);

View file

@ -24,14 +24,14 @@ import {
FilterableContainerInput,
FILTERABLE_CONTAINER,
} from './filterable_container';
import { GetEmbeddableFactory } from '../../types';
import { EmbeddableFactoryOptions } from '../../embeddables/embeddable_factory';
import { EmbeddableStart } from '../../../plugin';
export class FilterableContainerFactory extends EmbeddableFactory<FilterableContainerInput> {
public readonly type = FILTERABLE_CONTAINER;
constructor(
private readonly getFactory: GetEmbeddableFactory,
private readonly getFactory: EmbeddableStart['getEmbeddableFactory'],
options: EmbeddableFactoryOptions<any> = {}
) {
super(options);
@ -43,7 +43,7 @@ export class FilterableContainerFactory extends EmbeddableFactory<FilterableCont
});
}
public isEditable() {
public async isEditable() {
return true;
}

View file

@ -29,7 +29,7 @@ import { IContainer } from '../../containers';
export class FilterableEmbeddableFactory extends EmbeddableFactory<FilterableEmbeddableInput> {
public readonly type = FILTERABLE_EMBEDDABLE;
public isEditable() {
public async isEditable() {
return true;
}

View file

@ -24,7 +24,7 @@ import { UiActionsService } from 'src/plugins/ui_actions/public';
import { Start as InspectorStartContract } from 'src/plugins/inspector/public';
import { Container, ViewMode, ContainerInput } from '../..';
import { HelloWorldContainerComponent } from './hello_world_container_component';
import { GetEmbeddableFactory, GetEmbeddableFactories } from '../../types';
import { EmbeddableStart } from '../../../plugin';
export const HELLO_WORLD_CONTAINER = 'HELLO_WORLD_CONTAINER';
@ -46,8 +46,8 @@ interface HelloWorldContainerInput extends ContainerInput {
interface HelloWorldContainerOptions {
getActions: UiActionsService['getTriggerCompatibleActions'];
getEmbeddableFactory: GetEmbeddableFactory;
getAllEmbeddableFactories: GetEmbeddableFactories;
getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
getAllEmbeddableFactories: EmbeddableStart['getEmbeddableFactories'];
overlays: CoreStart['overlays'];
notifications: CoreStart['notifications'];
inspector: InspectorStartContract;

View file

@ -24,13 +24,13 @@ import { CoreStart } from 'src/core/public';
import { UiActionsService } from 'src/plugins/ui_actions/public';
import { Start as InspectorStartContract } from 'src/plugins/inspector/public';
import { IContainer, PanelState, EmbeddableChildPanel } from '../..';
import { GetEmbeddableFactory, GetEmbeddableFactories } from '../../types';
import { EmbeddableStart } from '../../../plugin';
interface Props {
container: IContainer;
getActions: UiActionsService['getTriggerCompatibleActions'];
getEmbeddableFactory: GetEmbeddableFactory;
getAllEmbeddableFactories: GetEmbeddableFactories;
getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
getAllEmbeddableFactories: EmbeddableStart['getEmbeddableFactories'];
overlays: CoreStart['overlays'];
notifications: CoreStart['notifications'];
inspector: InspectorStartContract;

View file

@ -18,7 +18,6 @@
*/
import { Adapters } from './inspector';
import { EmbeddableFactory } from './embeddables/embeddable_factory';
export interface Trigger {
id: string;
@ -40,6 +39,3 @@ export enum ViewMode {
}
export { Adapters };
export type GetEmbeddableFactory = (id: string) => EmbeddableFactory | undefined;
export type GetEmbeddableFactories = () => IterableIterator<EmbeddableFactory>;

View file

@ -17,15 +17,15 @@
* under the License.
*/
import { IEmbeddableStart, IEmbeddableSetup } from '.';
import { EmbeddableStart, EmbeddableSetup } from '.';
import { EmbeddablePublicPlugin } from './plugin';
import { coreMock } from '../../../core/public/mocks';
// eslint-disable-next-line
import { uiActionsPluginMock } from '../../ui_actions/public/mocks';
export type Setup = jest.Mocked<IEmbeddableSetup>;
export type Start = jest.Mocked<IEmbeddableStart>;
export type Setup = jest.Mocked<EmbeddableSetup>;
export type Start = jest.Mocked<EmbeddableStart>;
const createSetupContract = (): Setup => {
const setupContract: Setup = {
@ -36,7 +36,6 @@ const createSetupContract = (): Setup => {
const createStartContract = (): Start => {
const startContract: Start = {
registerEmbeddableFactory: jest.fn(),
getEmbeddableFactories: jest.fn(),
getEmbeddableFactory: jest.fn(),
};

View file

@ -16,18 +16,20 @@
* specific language governing permissions and limitations
* under the License.
*/
import { createApi } from '..';
import { createDeps } from './helpers';
import { coreMock } from '../../../core/public/mocks';
import { testPlugin } from './tests/test_plugin';
test('cannot register embeddable factory with the same ID', async () => {
const deps = createDeps();
const { api } = createApi(deps);
const coreSetup = coreMock.createSetup();
const coreStart = coreMock.createStart();
const { setup } = testPlugin(coreSetup, coreStart);
const embeddableFactoryId = 'ID';
const embeddableFactory = {} as any;
api.registerEmbeddableFactory(embeddableFactoryId, embeddableFactory);
expect(() => api.registerEmbeddableFactory(embeddableFactoryId, embeddableFactory)).toThrowError(
setup.registerEmbeddableFactory(embeddableFactoryId, embeddableFactory);
expect(() =>
setup.registerEmbeddableFactory(embeddableFactoryId, embeddableFactory)
).toThrowError(
'Embeddable factory [embeddableFactoryId = ID] already registered in Embeddables API.'
);
});

View file

@ -16,45 +16,78 @@
* specific language governing permissions and limitations
* under the License.
*/
import { UiActionsSetup } from 'src/plugins/ui_actions/public';
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../core/public';
import { EmbeddableFactoryRegistry } from './types';
import { createApi, EmbeddableApi } from './api';
import { bootstrap } from './bootstrap';
import { EmbeddableFactory, EmbeddableInput, EmbeddableOutput } from './lib';
export interface IEmbeddableSetupDependencies {
export interface EmbeddableSetupDependencies {
uiActions: UiActionsSetup;
}
export interface IEmbeddableSetup {
registerEmbeddableFactory: EmbeddableApi['registerEmbeddableFactory'];
export interface EmbeddableSetup {
registerEmbeddableFactory: <I extends EmbeddableInput, O extends EmbeddableOutput>(
id: string,
factory: EmbeddableFactory<I, O>
) => void;
}
export interface EmbeddableStart {
getEmbeddableFactory: <
I extends EmbeddableInput = EmbeddableInput,
O extends EmbeddableOutput = EmbeddableOutput
>(
embeddableFactoryId: string
) => EmbeddableFactory<I, O> | undefined;
getEmbeddableFactories: () => IterableIterator<EmbeddableFactory>;
}
export type IEmbeddableStart = EmbeddableApi;
export class EmbeddablePublicPlugin implements Plugin<IEmbeddableSetup, IEmbeddableStart> {
export class EmbeddablePublicPlugin implements Plugin<EmbeddableSetup, EmbeddableStart> {
private readonly embeddableFactories: EmbeddableFactoryRegistry = new Map();
private api!: EmbeddableApi;
constructor(initializerContext: PluginInitializerContext) {}
public setup(core: CoreSetup, { uiActions }: IEmbeddableSetupDependencies) {
({ api: this.api } = createApi({
embeddableFactories: this.embeddableFactories,
}));
public setup(core: CoreSetup, { uiActions }: EmbeddableSetupDependencies) {
bootstrap(uiActions);
const { registerEmbeddableFactory } = this.api;
return {
registerEmbeddableFactory,
registerEmbeddableFactory: this.registerEmbeddableFactory,
};
}
public start(core: CoreStart) {
return this.api;
return {
getEmbeddableFactory: this.getEmbeddableFactory,
getEmbeddableFactories: () => this.embeddableFactories.values(),
};
}
public stop() {}
private registerEmbeddableFactory = (embeddableFactoryId: string, factory: EmbeddableFactory) => {
if (this.embeddableFactories.has(embeddableFactoryId)) {
throw new Error(
`Embeddable factory [embeddableFactoryId = ${embeddableFactoryId}] already registered in Embeddables API.`
);
}
this.embeddableFactories.set(embeddableFactoryId, factory);
};
private getEmbeddableFactory = <
I extends EmbeddableInput = EmbeddableInput,
O extends EmbeddableOutput = EmbeddableOutput
>(
embeddableFactoryId: string
) => {
const factory = this.embeddableFactories.get(embeddableFactoryId);
if (!factory) {
throw new Error(
`Embeddable factory [embeddableFactoryId = ${embeddableFactoryId}] does not exist.`
);
}
return factory as EmbeddableFactory<I, O>;
};
}

View file

@ -35,14 +35,14 @@ import { inspectorPluginMock } from 'src/plugins/inspector/public/mocks';
import { esFilters } from '../../../../plugins/data/public';
test('ApplyFilterAction applies the filter to the root of the container tree', async () => {
const { doStart } = testPlugin();
const { doStart, setup } = testPlugin();
const api = doStart();
const factory1 = new FilterableContainerFactory(api.getEmbeddableFactory);
const factory2 = new FilterableEmbeddableFactory();
api.registerEmbeddableFactory(factory1.type, factory1);
api.registerEmbeddableFactory(factory2.type, factory2);
setup.registerEmbeddableFactory(factory1.type, factory1);
setup.registerEmbeddableFactory(factory2.type, factory2);
const applyFilterAction = createFilterAction();
@ -93,7 +93,7 @@ test('ApplyFilterAction applies the filter to the root of the container tree', a
});
test('ApplyFilterAction is incompatible if the root container does not accept a filter as input', async () => {
const { doStart, coreStart } = testPlugin();
const { doStart, coreStart, setup } = testPlugin();
const api = doStart();
const inspector = inspectorPluginMock.createStartContract();
@ -112,7 +112,7 @@ test('ApplyFilterAction is incompatible if the root container does not accept a
);
const factory = new FilterableEmbeddableFactory();
api.registerEmbeddableFactory(factory.type, factory);
setup.registerEmbeddableFactory(factory.type, factory);
const embeddable = await parent.addNewEmbeddable<
FilterableContainerInput,
@ -129,12 +129,12 @@ test('ApplyFilterAction is incompatible if the root container does not accept a
});
test('trying to execute on incompatible context throws an error ', async () => {
const { doStart, coreStart } = testPlugin();
const { doStart, coreStart, setup } = testPlugin();
const api = doStart();
const inspector = inspectorPluginMock.createStartContract();
const factory = new FilterableEmbeddableFactory();
api.registerEmbeddableFactory(factory.type, factory);
setup.registerEmbeddableFactory(factory.type, factory);
const applyFilterAction = createFilterAction();
const parent = new HelloWorldContainer(

View file

@ -562,7 +562,7 @@ test('Panel added to input state', async () => {
test('Container changes made directly after adding a new embeddable are propagated', async done => {
const coreSetup = coreMock.createSetup();
const coreStart = coreMock.createStart();
const { doStart, uiActions } = testPlugin(coreSetup, coreStart);
const { setup, doStart, uiActions } = testPlugin(coreSetup, coreStart);
const start = doStart();
const container = new HelloWorldContainer(
@ -586,7 +586,7 @@ test('Container changes made directly after adding a new embeddable are propagat
loadTickCount: 3,
execAction: uiActions.executeTriggerActions,
});
start.registerEmbeddableFactory(factory.type, factory);
setup.registerEmbeddableFactory(factory.type, factory);
const subscription = Rx.merge(container.getOutput$(), container.getInput$())
.pipe(skip(2))
@ -755,7 +755,7 @@ test('untilEmbeddableLoaded() resolves if child is loaded in the container', asy
});
test('untilEmbeddableLoaded resolves with undefined if child is subsequently removed', async done => {
const { doStart, coreStart, uiActions } = testPlugin(
const { doStart, setup, coreStart, uiActions } = testPlugin(
coreMock.createSetup(),
coreMock.createStart()
);
@ -764,7 +764,7 @@ test('untilEmbeddableLoaded resolves with undefined if child is subsequently rem
loadTickCount: 3,
execAction: uiActions.executeTriggerActions,
});
start.registerEmbeddableFactory(factory.type, factory);
setup.registerEmbeddableFactory(factory.type, factory);
const container = new HelloWorldContainer(
{
id: 'hello',
@ -795,7 +795,7 @@ test('untilEmbeddableLoaded resolves with undefined if child is subsequently rem
});
test('adding a panel then subsequently removing it before its loaded removes the panel', async done => {
const { doStart, coreStart, uiActions } = testPlugin(
const { doStart, coreStart, uiActions, setup } = testPlugin(
coreMock.createSetup(),
coreMock.createStart()
);
@ -804,7 +804,7 @@ test('adding a panel then subsequently removing it before its loaded removes the
loadTickCount: 1,
execAction: uiActions.executeTriggerActions,
});
start.registerEmbeddableFactory(factory.type, factory);
setup.registerEmbeddableFactory(factory.type, factory);
const container = new HelloWorldContainer(
{
id: 'hello',

View file

@ -34,16 +34,16 @@ import { HelloWorldContainer } from '../lib/test_samples/embeddables/hello_world
// eslint-disable-next-line
import { coreMock } from '../../../../core/public/mocks';
import { testPlugin } from './test_plugin';
import { EmbeddableApi } from '../api';
import { CustomizePanelModal } from '../lib/panel/panel_header/panel_actions/customize_title/customize_panel_modal';
import { mount } from 'enzyme';
import { EmbeddableStart } from '../plugin';
let api: EmbeddableApi;
let api: EmbeddableStart;
let container: Container;
let embeddable: ContactCardEmbeddable;
beforeEach(async () => {
const { doStart, coreStart, uiActions } = testPlugin(
const { doStart, coreStart, uiActions, setup } = testPlugin(
coreMock.createSetup(),
coreMock.createStart()
);
@ -54,7 +54,7 @@ beforeEach(async () => {
uiActions.executeTriggerActions,
{} as any
);
api.registerEmbeddableFactory(contactCardFactory.type, contactCardFactory);
setup.registerEmbeddableFactory(contactCardFactory.type, contactCardFactory);
container = new HelloWorldContainer(
{ id: '123', panels: {} },

View file

@ -22,14 +22,14 @@ import { CoreSetup, CoreStart } from 'src/core/public';
import { uiActionsPluginMock } from 'src/plugins/ui_actions/public/mocks';
import { UiActionsStart } from 'src/plugins/ui_actions/public';
import { coreMock } from '../../../../core/public/mocks';
import { EmbeddablePublicPlugin, IEmbeddableSetup, IEmbeddableStart } from '../plugin';
import { EmbeddablePublicPlugin, EmbeddableSetup, EmbeddableStart } from '../plugin';
export interface TestPluginReturn {
plugin: EmbeddablePublicPlugin;
coreSetup: CoreSetup;
coreStart: CoreStart;
setup: IEmbeddableSetup;
doStart: (anotherCoreStart?: CoreStart) => IEmbeddableStart;
setup: EmbeddableSetup;
doStart: (anotherCoreStart?: CoreStart) => EmbeddableStart;
uiActions: UiActionsStart;
}

View file

@ -19,18 +19,15 @@
import { EuiTab } from '@elastic/eui';
import React, { Component } from 'react';
import { CoreStart } from 'src/core/public';
import {
GetEmbeddableFactory,
GetEmbeddableFactories,
} from 'src/legacy/core_plugins/embeddable_api/public/np_ready/public';
import { EmbeddableStart } from 'src/plugins/embeddable/public';
import { UiActionsService } from '../../../../../../../../src/plugins/ui_actions/public';
import { DashboardContainerExample } from './dashboard_container_example';
import { Start as InspectorStartContract } from '../../../../../../../../src/plugins/inspector/public';
export interface AppProps {
getActions: UiActionsService['getTriggerCompatibleActions'];
getEmbeddableFactory: GetEmbeddableFactory;
getAllEmbeddableFactories: GetEmbeddableFactories;
getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
getAllEmbeddableFactories: EmbeddableStart['getEmbeddableFactories'];
overlays: CoreStart['overlays'];
notifications: CoreStart['notifications'];
inspector: InspectorStartContract;

View file

@ -18,18 +18,19 @@
*/
import React from 'react';
import { EuiButton, EuiLoadingChart } from '@elastic/eui';
import { ContainerOutput } from 'src/plugins/embeddable/public';
import {
ErrorEmbeddable,
ViewMode,
isErrorEmbeddable,
EmbeddablePanel,
GetEmbeddableFactory,
GetEmbeddableFactories,
EmbeddableStart,
} from '../embeddable_api';
import {
DASHBOARD_CONTAINER_TYPE,
DashboardContainer,
DashboardContainerFactory,
DashboardContainerInput,
} from '../../../../../../../../src/plugins/dashboard/public';
import { CoreStart } from '../../../../../../../../src/core/public';
@ -39,8 +40,8 @@ import { UiActionsService } from '../../../../../../../../src/plugins/ui_actions
interface Props {
getActions: UiActionsService['getTriggerCompatibleActions'];
getEmbeddableFactory: GetEmbeddableFactory;
getAllEmbeddableFactories: GetEmbeddableFactories;
getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
getAllEmbeddableFactories: EmbeddableStart['getEmbeddableFactories'];
overlays: CoreStart['overlays'];
notifications: CoreStart['notifications'];
inspector: InspectorStartContract;
@ -67,9 +68,10 @@ export class DashboardContainerExample extends React.Component<Props, State> {
public async componentDidMount() {
this.mounted = true;
const dashboardFactory = this.props.getEmbeddableFactory(
DASHBOARD_CONTAINER_TYPE
) as DashboardContainerFactory;
const dashboardFactory = this.props.getEmbeddableFactory<
DashboardContainerInput,
ContainerOutput
>(DASHBOARD_CONTAINER_TYPE) as DashboardContainerFactory;
if (dashboardFactory) {
this.container = await dashboardFactory.create(dashboardInput);
if (this.mounted) {

View file

@ -1,28 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
// eslint-disable-next-line
import { npSetup } from '../../../../../../../../src/legacy/ui/public/new_platform';
// eslint-disable-next-line
import { HelloWorldEmbeddableFactory, HELLO_WORLD_EMBEDDABLE } from '../../../../../../../../examples/embeddable_examples/public';
npSetup.plugins.embeddable.registerEmbeddableFactory(
HELLO_WORLD_EMBEDDABLE,
new HelloWorldEmbeddableFactory()
);

View file

@ -31,21 +31,16 @@ import { CONTEXT_MENU_TRIGGER } from './embeddable_api';
const REACT_ROOT_ID = 'embeddableExplorerRoot';
import {
SayHelloAction,
createSendMessageAction,
ContactCardEmbeddableFactory,
} from './embeddable_api';
import { SayHelloAction, createSendMessageAction } from './embeddable_api';
import { App } from './app';
import { getSavedObjectFinder } from '../../../../../../../src/plugins/saved_objects/public';
import { HelloWorldEmbeddableFactory } from '../../../../../../../examples/embeddable_examples/public';
import {
IEmbeddableStart,
IEmbeddableSetup,
EmbeddableStart,
EmbeddableSetup,
} from '.../../../../../../../src/plugins/embeddable/public';
export interface SetupDependencies {
embeddable: IEmbeddableSetup;
embeddable: EmbeddableSetup;
inspector: InspectorSetupContract;
__LEGACY: {
ExitFullScreenButton: React.ComponentType<any>;
@ -53,7 +48,7 @@ export interface SetupDependencies {
}
interface StartDependencies {
embeddable: IEmbeddableStart;
embeddable: EmbeddableStart;
uiActions: UiActionsStart;
inspector: InspectorStartContract;
__LEGACY: {
@ -74,12 +69,6 @@ export class EmbeddableExplorerPublicPlugin
const helloWorldAction = createHelloWorldAction(core.overlays);
const sayHelloAction = new SayHelloAction(alert);
const sendMessageAction = createSendMessageAction(core.overlays);
const helloWorldEmbeddableFactory = new HelloWorldEmbeddableFactory();
const contactCardEmbeddableFactory = new ContactCardEmbeddableFactory(
{},
plugins.uiActions.executeTriggerActions,
core.overlays
);
plugins.uiActions.registerAction(helloWorldAction);
plugins.uiActions.registerAction(sayHelloAction);
@ -87,15 +76,6 @@ export class EmbeddableExplorerPublicPlugin
plugins.uiActions.attachAction(CONTEXT_MENU_TRIGGER, helloWorldAction);
plugins.embeddable.registerEmbeddableFactory(
helloWorldEmbeddableFactory.type,
helloWorldEmbeddableFactory
);
plugins.embeddable.registerEmbeddableFactory(
contactCardEmbeddableFactory.type,
contactCardEmbeddableFactory
);
plugins.__LEGACY.onRenderComplete(() => {
const root = document.getElementById(REACT_ROOT_ID);
ReactDOM.render(

View file

@ -17,11 +17,8 @@
* under the License.
*/
import expect from '@kbn/expect';
export default function({ getService }) {
const testSubjects = getService('testSubjects');
const retry = getService('retry');
const pieChart = getService('pieChart');
const dashboardExpect = getService('dashboardExpect');
@ -30,17 +27,6 @@ export default function({ getService }) {
await testSubjects.click('embedExplorerTab-dashboardContainer');
});
it('hello world embeddable renders', async () => {
await retry.try(async () => {
const text = await testSubjects.getVisibleText('helloWorldEmbeddable');
expect(text).to.be('HELLO WORLD!');
});
});
it('contact card embeddable renders', async () => {
await testSubjects.existOrFail('embeddablePanelHeading-HelloSue');
});
it('pie charts', async () => {
await pieChart.expectPieSliceCount(5);
});

View file

@ -27,17 +27,19 @@ import { Embeddable } from './embeddable';
import { SavedObjectIndexStore, DOC_TYPE } from '../../persistence';
import { getEditPath } from '../../../../../../plugins/lens/common';
interface StartServices {
timefilter: TimefilterContract;
coreHttp: HttpSetup;
capabilities: RecursiveReadonly<Capabilities>;
savedObjectsClient: SavedObjectsClientContract;
expressionRenderer: ReactExpressionRendererType;
indexPatternService: IndexPatternsContract;
}
export class EmbeddableFactory extends AbstractEmbeddableFactory {
type = DOC_TYPE;
constructor(
private timefilter: TimefilterContract,
private coreHttp: HttpSetup,
private capabilities: RecursiveReadonly<Capabilities>,
private savedObjectsClient: SavedObjectsClientContract,
private expressionRenderer: ReactExpressionRendererType,
private indexPatternService: IndexPatternsContract
) {
constructor(private getStartServices: () => Promise<StartServices>) {
super({
savedObjectMetaData: {
name: i18n.translate('xpack.lens.lensSavedObjectLabel', {
@ -49,8 +51,9 @@ export class EmbeddableFactory extends AbstractEmbeddableFactory {
});
}
public isEditable() {
return this.capabilities.visualize.save as boolean;
public async isEditable() {
const { capabilities } = await this.getStartServices();
return capabilities.visualize.save as boolean;
}
canCreateNew() {
@ -68,13 +71,20 @@ export class EmbeddableFactory extends AbstractEmbeddableFactory {
input: Partial<EmbeddableInput> & { id: string },
parent?: IContainer
) {
const store = new SavedObjectIndexStore(this.savedObjectsClient);
const {
savedObjectsClient,
coreHttp,
indexPatternService,
timefilter,
expressionRenderer,
} = await this.getStartServices();
const store = new SavedObjectIndexStore(savedObjectsClient);
const savedVis = await store.load(savedObjectId);
const promises = savedVis.state.datasourceMetaData.filterableIndexPatterns.map(
async ({ id }) => {
try {
return await this.indexPatternService.get(id);
return await indexPatternService.get(id);
} catch (error) {
// Unable to load index pattern, ignore error as the index patterns are only used to
// configure the filter and query bar - there is still a good chance to get the visualization
@ -90,12 +100,12 @@ export class EmbeddableFactory extends AbstractEmbeddableFactory {
);
return new Embeddable(
this.timefilter,
this.expressionRenderer,
timefilter,
expressionRenderer,
{
savedVis,
editUrl: this.coreHttp.basePath.prepend(getEditPath(savedObjectId)),
editable: this.isEditable(),
editUrl: coreHttp.basePath.prepend(getEditPath(savedObjectId)),
editable: await this.isEditable(),
indexPatterns,
},
input,

View file

@ -12,6 +12,7 @@ import {
createMockSetupDependencies,
createMockStartDependencies,
} from './mocks';
import { CoreSetup } from 'kibana/public';
jest.mock('ui/new_platform');
@ -41,7 +42,10 @@ describe('editor_frame service', () => {
it('should create an editor frame instance which mounts and unmounts', async () => {
await expect(
(async () => {
pluginInstance.setup(coreMock.createSetup(), pluginSetupDependencies);
pluginInstance.setup(
coreMock.createSetup() as CoreSetup<MockedStartDependencies>,
pluginSetupDependencies
);
const publicAPI = pluginInstance.start(coreMock.createStart(), pluginStartDependencies);
const instance = await publicAPI.createInstance({});
instance.mount(mountpoint, {
@ -57,7 +61,10 @@ describe('editor_frame service', () => {
});
it('should not have child nodes after unmount', async () => {
pluginInstance.setup(coreMock.createSetup(), pluginSetupDependencies);
pluginInstance.setup(
coreMock.createSetup() as CoreSetup<MockedStartDependencies>,
pluginSetupDependencies
);
const publicAPI = pluginInstance.start(coreMock.createStart(), pluginStartDependencies);
const instance = await publicAPI.createInstance({});
instance.mount(mountpoint, {

View file

@ -12,10 +12,7 @@ import {
ExpressionsSetup,
ExpressionsStart,
} from '../../../../../../src/plugins/expressions/public';
import {
IEmbeddableSetup,
IEmbeddableStart,
} from '../../../../../../src/plugins/embeddable/public';
import { EmbeddableSetup, EmbeddableStart } from '../../../../../../src/plugins/embeddable/public';
import {
DataPublicPluginSetup,
DataPublicPluginStart,
@ -35,13 +32,13 @@ import { getActiveDatasourceIdFromDoc } from './editor_frame/state_management';
export interface EditorFrameSetupPlugins {
data: DataPublicPluginSetup;
embeddable: IEmbeddableSetup;
embeddable: EmbeddableSetup;
expressions: ExpressionsSetup;
}
export interface EditorFrameStartPlugins {
data: DataPublicPluginStart;
embeddable: IEmbeddableStart;
embeddable: EmbeddableStart;
expressions: ExpressionsStart;
}
@ -63,10 +60,27 @@ export class EditorFrameService {
private readonly datasources: Array<Datasource | Promise<Datasource>> = [];
private readonly visualizations: Array<Visualization | Promise<Visualization>> = [];
public setup(core: CoreSetup, plugins: EditorFrameSetupPlugins): EditorFrameSetup {
public setup(
core: CoreSetup<EditorFrameStartPlugins>,
plugins: EditorFrameSetupPlugins
): EditorFrameSetup {
plugins.expressions.registerFunction(() => mergeTables);
plugins.expressions.registerFunction(() => formatColumn);
const getStartServices = async () => {
const [coreStart, deps] = await core.getStartServices();
return {
capabilities: coreStart.application.capabilities,
savedObjectsClient: coreStart.savedObjects.client,
coreHttp: coreStart.http,
timefilter: deps.data.query.timefilter.timefilter,
expressionRenderer: deps.expressions.ReactExpressionRenderer,
indexPatternService: deps.data.indexPatterns,
};
};
plugins.embeddable.registerEmbeddableFactory('lens', new EmbeddableFactory(getStartServices));
return {
registerDatasource: datasource => {
this.datasources.push(datasource as Datasource<unknown, unknown>);
@ -78,18 +92,6 @@ export class EditorFrameService {
}
public start(core: CoreStart, plugins: EditorFrameStartPlugins): EditorFrameStart {
plugins.embeddable.registerEmbeddableFactory(
'lens',
new EmbeddableFactory(
plugins.data.query.timefilter.timefilter,
core.http,
core.application.capabilities,
core.savedObjects.client,
plugins.expressions.ReactExpressionRenderer,
plugins.data.indexPatterns
)
);
const createInstance = async (): Promise<EditorFrameInstance> => {
let domElement: Element;
const [resolvedDatasources, resolvedVisualizations] = await Promise.all([

View file

@ -36,7 +36,7 @@ import {
getLensUrlFromDashboardAbsoluteUrl,
} from '../../../../../src/legacy/core_plugins/kibana/public/dashboard/np_ready/url_helper';
import { FormatFactory } from './legacy_imports';
import { IEmbeddableSetup, IEmbeddableStart } from '../../../../../src/plugins/embeddable/public';
import { EmbeddableSetup, EmbeddableStart } from '../../../../../src/plugins/embeddable/public';
import { EditorFrameStart } from './types';
import { getLensAliasConfig } from './vis_type_alias';
import { VisualizationsSetup } from './legacy_imports';
@ -45,7 +45,7 @@ export interface LensPluginSetupDependencies {
kibanaLegacy: KibanaLegacySetup;
expressions: ExpressionsSetup;
data: DataPublicPluginSetup;
embeddable: IEmbeddableSetup;
embeddable: EmbeddableSetup;
__LEGACY: {
formatFactory: FormatFactory;
visualizations: VisualizationsSetup;
@ -54,7 +54,7 @@ export interface LensPluginSetupDependencies {
export interface LensPluginStartDependencies {
data: DataPublicPluginStart;
embeddable: IEmbeddableStart;
embeddable: EmbeddableStart;
expressions: ExpressionsStart;
}

View file

@ -9,18 +9,13 @@ import React from 'react';
import { OutPortal, PortalNode } from 'react-reverse-portal';
import minimatch from 'minimatch';
import { ViewMode } from '../../../../../../../src/legacy/core_plugins/embeddable_api/public/np_ready/public';
import {
IndexPatternMapping,
MapEmbeddable,
RenderTooltipContentParams,
SetQuery,
EmbeddableApi,
} from './types';
import { IndexPatternMapping, MapEmbeddable, RenderTooltipContentParams, SetQuery } from './types';
import { getLayerList } from './map_config';
// @ts-ignore Missing type defs as maps moves to Typescript
import { MAP_SAVED_OBJECT_TYPE } from '../../../../maps/common/constants';
import * as i18n from './translations';
import { Query, Filter } from '../../../../../../../src/plugins/data/public';
import { EmbeddableStart } from '../../../../../../../src/plugins/embeddable/public';
import { IndexPatternSavedObject } from '../../hooks/types';
/**
@ -45,7 +40,7 @@ export const createEmbeddable = async (
endDate: number,
setQuery: SetQuery,
portalNode: PortalNode,
embeddableApi: EmbeddableApi
embeddableApi: EmbeddableStart
): Promise<MapEmbeddable> => {
const factory = embeddableApi.getEmbeddableFactory(MAP_SAVED_OBJECT_TYPE);

View file

@ -9,7 +9,6 @@ import {
EmbeddableInput,
EmbeddableOutput,
IEmbeddable,
EmbeddableFactory,
} from '../../../../../../../src/legacy/core_plugins/embeddable_api/public/np_ready/public';
import { inputsModel } from '../../store/inputs';
import { Query, Filter } from '../../../../../../../src/plugins/data/public';
@ -85,8 +84,3 @@ export interface RenderTooltipContentParams {
}
export type MapToolTipProps = Partial<RenderTooltipContentParams>;
export interface EmbeddableApi {
getEmbeddableFactory: (embeddableFactoryId: string) => EmbeddableFactory;
registerEmbeddableFactory: (id: string, factory: EmbeddableFactory) => void;
}

View file

@ -13,7 +13,7 @@ import {
} from '../../../../../src/core/public';
import { HomePublicPluginSetup } from '../../../../../src/plugins/home/public';
import { DataPublicPluginStart } from '../../../../../src/plugins/data/public';
import { IEmbeddableStart } from '../../../../../src/plugins/embeddable/public';
import { EmbeddableStart } from '../../../../../src/plugins/embeddable/public';
import { Start as NewsfeedStart } from '../../../../../src/plugins/newsfeed/public';
import { Start as InspectorStart } from '../../../../../src/plugins/inspector/public';
import { UiActionsStart } from '../../../../../src/plugins/ui_actions/public';
@ -37,7 +37,7 @@ export interface SetupPlugins {
}
export interface StartPlugins {
data: DataPublicPluginStart;
embeddable: IEmbeddableStart;
embeddable: EmbeddableStart;
inspector: InspectorStart;
newsfeed?: NewsfeedStart;
uiActions: UiActionsStart;

View file

@ -15,8 +15,8 @@ import { UiActionsStart, UiActionsSetup } from '../../../../src/plugins/ui_actio
import {
CONTEXT_MENU_TRIGGER,
PANEL_BADGE_TRIGGER,
IEmbeddableSetup,
IEmbeddableStart,
EmbeddableSetup,
EmbeddableStart,
} from '../../../../src/plugins/embeddable/public';
import {
CustomTimeRangeAction,
@ -32,12 +32,12 @@ import {
import { CommonlyUsedRange } from './types';
interface SetupDependencies {
embeddable: IEmbeddableSetup; // Embeddable are needed because they register basic triggers/actions.
embeddable: EmbeddableSetup; // Embeddable are needed because they register basic triggers/actions.
uiActions: UiActionsSetup;
}
interface StartDependencies {
embeddable: IEmbeddableStart;
embeddable: EmbeddableStart;
uiActions: UiActionsStart;
}

View file

@ -8,7 +8,7 @@ import {
ContainerInput,
Container,
ContainerOutput,
GetEmbeddableFactory,
EmbeddableStart,
} from '../../../../../src/plugins/embeddable/public';
import { TimeRange } from '../../../../../src/plugins/data/public';
@ -37,7 +37,7 @@ export class TimeRangeContainer extends Container<
public readonly type = TIME_RANGE_CONTAINER;
constructor(
initialInput: ContainerTimeRangeInput,
getFactory: GetEmbeddableFactory,
getFactory: EmbeddableStart['getEmbeddableFactory'],
parent?: Container
) {
super(initialInput, { embeddableLoaded: {} }, getFactory, parent);

View file

@ -19,7 +19,7 @@ interface EmbeddableTimeRangeInput extends EmbeddableInput {
export class TimeRangeEmbeddableFactory extends EmbeddableFactory<EmbeddableTimeRangeInput> {
public readonly type = TIME_RANGE_EMBEDDABLE;
public isEditable() {
public async isEditable() {
return true;
}

View file

@ -15,7 +15,7 @@ import { ResolverEmbeddable } from './embeddable';
export class ResolverEmbeddableFactory extends EmbeddableFactory {
public readonly type = 'resolver';
public isEditable() {
public async isEditable() {
return true;
}

View file

@ -5,7 +5,7 @@
*/
import { Plugin, CoreSetup, AppMountParameters, CoreStart } from 'kibana/public';
import { IEmbeddableSetup } from 'src/plugins/embeddable/public';
import { EmbeddableSetup } from 'src/plugins/embeddable/public';
import { DataPublicPluginStart } from 'src/plugins/data/public';
import { i18n } from '@kbn/i18n';
import { ResolverEmbeddableFactory } from './embeddables/resolver';
@ -13,7 +13,7 @@ import { ResolverEmbeddableFactory } from './embeddables/resolver';
export type EndpointPluginStart = void;
export type EndpointPluginSetup = void;
export interface EndpointPluginSetupDependencies {
embeddable: IEmbeddableSetup;
embeddable: EmbeddableSetup;
data: DataPublicPluginStart;
}
export interface EndpointPluginStartDependencies {

View file

@ -6,13 +6,13 @@
import { Plugin, CoreSetup } from 'kibana/public';
import { i18n } from '@kbn/i18n';
import { IEmbeddable, IEmbeddableStart } from '../../../../../../src/plugins/embeddable/public';
import { IEmbeddable, EmbeddableStart } from '../../../../../../src/plugins/embeddable/public';
export type ResolverTestPluginSetup = void;
export type ResolverTestPluginStart = void;
export interface ResolverTestPluginSetupDependencies {} // eslint-disable-line @typescript-eslint/no-empty-interface
export interface ResolverTestPluginStartDependencies {
embeddable: IEmbeddableStart;
embeddable: EmbeddableStart;
}
export class ResolverTestPlugin
@ -41,7 +41,9 @@ export class ResolverTestPlugin
(async () => {
const [, { embeddable }] = await core.getStartServices();
const factory = embeddable.getEmbeddableFactory('resolver');
resolveEmbeddable!(factory.create({ id: 'test basic render' }));
if (factory) {
resolveEmbeddable!(factory.create({ id: 'test basic render' }));
}
})();
const { renderApp } = await import('./applications/resolver_test');