mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
Remove UiComponent
and related code (#148037)
## Summary - Removes `UiComponent` and its usages. - Fixes UI Actions TypeScript types. ### Checklist Delete any items that are not applicable to this PR. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Anton Dosov <dosantappdev@gmail.com> Co-authored-by: Dima Arnautov <arnautov.dima@gmail.com>
This commit is contained in:
parent
5921abbf35
commit
039ed991d8
78 changed files with 366 additions and 827 deletions
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { createAction, IncompatibleActionError } from '@kbn/ui-actions-plugin/public';
|
||||
import { IncompatibleActionError } from '@kbn/ui-actions-plugin/public';
|
||||
import { ViewMode, isReferenceOrValueEmbeddable } from '@kbn/embeddable-plugin/public';
|
||||
import { DASHBOARD_CONTAINER_TYPE } from '@kbn/dashboard-plugin/public';
|
||||
import { BookEmbeddable, BOOK_EMBEDDABLE } from './book_embeddable';
|
||||
|
@ -18,31 +18,30 @@ interface ActionContext {
|
|||
|
||||
export const ACTION_ADD_BOOK_TO_LIBRARY = 'ACTION_ADD_BOOK_TO_LIBRARY';
|
||||
|
||||
export const createAddBookToLibraryAction = () =>
|
||||
createAction({
|
||||
getDisplayName: () =>
|
||||
i18n.translate('embeddableExamples.book.addToLibrary', {
|
||||
defaultMessage: 'Add Book To Library',
|
||||
}),
|
||||
id: ACTION_ADD_BOOK_TO_LIBRARY,
|
||||
type: ACTION_ADD_BOOK_TO_LIBRARY,
|
||||
order: 100,
|
||||
getIconType: () => 'folderCheck',
|
||||
isCompatible: async ({ embeddable }: ActionContext) => {
|
||||
return (
|
||||
embeddable.type === BOOK_EMBEDDABLE &&
|
||||
embeddable.getInput().viewMode === ViewMode.EDIT &&
|
||||
embeddable.getRoot().isContainer &&
|
||||
embeddable.getRoot().type !== DASHBOARD_CONTAINER_TYPE &&
|
||||
isReferenceOrValueEmbeddable(embeddable) &&
|
||||
!embeddable.inputIsRefType(embeddable.getInput())
|
||||
);
|
||||
},
|
||||
execute: async ({ embeddable }: ActionContext) => {
|
||||
if (!isReferenceOrValueEmbeddable(embeddable)) {
|
||||
throw new IncompatibleActionError();
|
||||
}
|
||||
const newInput = await embeddable.getInputAsRefType();
|
||||
embeddable.updateInput(newInput);
|
||||
},
|
||||
});
|
||||
export const createAddBookToLibraryActionDefinition = () => ({
|
||||
getDisplayName: () =>
|
||||
i18n.translate('embeddableExamples.book.addToLibrary', {
|
||||
defaultMessage: 'Add Book To Library',
|
||||
}),
|
||||
id: ACTION_ADD_BOOK_TO_LIBRARY,
|
||||
type: ACTION_ADD_BOOK_TO_LIBRARY,
|
||||
order: 100,
|
||||
getIconType: () => 'folderCheck',
|
||||
isCompatible: async ({ embeddable }: ActionContext) => {
|
||||
return (
|
||||
embeddable.type === BOOK_EMBEDDABLE &&
|
||||
embeddable.getInput().viewMode === ViewMode.EDIT &&
|
||||
embeddable.getRoot().isContainer &&
|
||||
embeddable.getRoot().type !== DASHBOARD_CONTAINER_TYPE &&
|
||||
isReferenceOrValueEmbeddable(embeddable) &&
|
||||
!embeddable.inputIsRefType(embeddable.getInput())
|
||||
);
|
||||
},
|
||||
execute: async ({ embeddable }: ActionContext) => {
|
||||
if (!isReferenceOrValueEmbeddable(embeddable)) {
|
||||
throw new IncompatibleActionError();
|
||||
}
|
||||
const newInput = await embeddable.getInputAsRefType();
|
||||
embeddable.updateInput(newInput);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
import React from 'react';
|
||||
import { OverlayStart } from '@kbn/core/public';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { createAction } from '@kbn/ui-actions-plugin/public';
|
||||
import { toMountPoint } from '@kbn/kibana-react-plugin/public';
|
||||
import {
|
||||
ViewMode,
|
||||
|
@ -39,61 +38,58 @@ interface ActionContext {
|
|||
|
||||
export const ACTION_EDIT_BOOK = 'ACTION_EDIT_BOOK';
|
||||
|
||||
export const createEditBookAction = (getStartServices: () => Promise<StartServices>) =>
|
||||
createAction({
|
||||
getDisplayName: () =>
|
||||
i18n.translate('embeddableExamples.book.edit', { defaultMessage: 'Edit Book' }),
|
||||
id: ACTION_EDIT_BOOK,
|
||||
type: ACTION_EDIT_BOOK,
|
||||
order: 100,
|
||||
getIconType: () => 'documents',
|
||||
isCompatible: async ({ embeddable }: ActionContext) => {
|
||||
return (
|
||||
embeddable.type === BOOK_EMBEDDABLE && embeddable.getInput().viewMode === ViewMode.EDIT
|
||||
);
|
||||
},
|
||||
execute: async ({ embeddable }: ActionContext) => {
|
||||
const { openModal, getAttributeService, savedObjectsClient } = await getStartServices();
|
||||
const attributeService = getAttributeService<BookSavedObjectAttributes>(BOOK_SAVED_OBJECT, {
|
||||
saveMethod: async (attributes: BookSavedObjectAttributes, savedObjectId?: string) => {
|
||||
if (savedObjectId) {
|
||||
return savedObjectsClient.update(BOOK_EMBEDDABLE, savedObjectId, attributes);
|
||||
}
|
||||
return savedObjectsClient.create(BOOK_EMBEDDABLE, attributes);
|
||||
},
|
||||
checkForDuplicateTitle: (props: OnSaveProps) => {
|
||||
return new Promise(() => {
|
||||
return true;
|
||||
});
|
||||
},
|
||||
});
|
||||
const onSave = async (attributes: BookSavedObjectAttributes, useRefType: boolean) => {
|
||||
const newInput = await attributeService.wrapAttributes(
|
||||
attributes,
|
||||
useRefType,
|
||||
embeddable.getExplicitInput()
|
||||
);
|
||||
if (!useRefType && (embeddable.getInput() as SavedObjectEmbeddableInput).savedObjectId) {
|
||||
// Set the saved object ID to null so that update input will remove the existing savedObjectId...
|
||||
(newInput as BookByValueInput & { savedObjectId: unknown }).savedObjectId = null;
|
||||
export const createEditBookActionDefinition = (getStartServices: () => Promise<StartServices>) => ({
|
||||
getDisplayName: () =>
|
||||
i18n.translate('embeddableExamples.book.edit', { defaultMessage: 'Edit Book' }),
|
||||
id: ACTION_EDIT_BOOK,
|
||||
type: ACTION_EDIT_BOOK,
|
||||
order: 100,
|
||||
getIconType: () => 'documents',
|
||||
isCompatible: async ({ embeddable }: ActionContext) => {
|
||||
return embeddable.type === BOOK_EMBEDDABLE && embeddable.getInput().viewMode === ViewMode.EDIT;
|
||||
},
|
||||
execute: async ({ embeddable }: ActionContext) => {
|
||||
const { openModal, getAttributeService, savedObjectsClient } = await getStartServices();
|
||||
const attributeService = getAttributeService<BookSavedObjectAttributes>(BOOK_SAVED_OBJECT, {
|
||||
saveMethod: async (attributes: BookSavedObjectAttributes, savedObjectId?: string) => {
|
||||
if (savedObjectId) {
|
||||
return savedObjectsClient.update(BOOK_EMBEDDABLE, savedObjectId, attributes);
|
||||
}
|
||||
embeddable.updateInput(newInput);
|
||||
if (useRefType) {
|
||||
// Ensures that any duplicate embeddables also register the changes. This mirrors the behavior of going back and forth between apps
|
||||
embeddable.getRoot().reload();
|
||||
}
|
||||
};
|
||||
const overlay = openModal(
|
||||
toMountPoint(
|
||||
<CreateEditBookComponent
|
||||
savedObjectId={(embeddable.getInput() as BookByReferenceInput).savedObjectId}
|
||||
attributes={embeddable.getOutput().attributes}
|
||||
onSave={(attributes: BookSavedObjectAttributes, useRefType: boolean) => {
|
||||
overlay.close();
|
||||
onSave(attributes, useRefType);
|
||||
}}
|
||||
/>
|
||||
)
|
||||
return savedObjectsClient.create(BOOK_EMBEDDABLE, attributes);
|
||||
},
|
||||
checkForDuplicateTitle: (props: OnSaveProps) => {
|
||||
return new Promise(() => {
|
||||
return true;
|
||||
});
|
||||
},
|
||||
});
|
||||
const onSave = async (attributes: BookSavedObjectAttributes, useRefType: boolean) => {
|
||||
const newInput = await attributeService.wrapAttributes(
|
||||
attributes,
|
||||
useRefType,
|
||||
embeddable.getExplicitInput()
|
||||
);
|
||||
},
|
||||
});
|
||||
if (!useRefType && (embeddable.getInput() as SavedObjectEmbeddableInput).savedObjectId) {
|
||||
// Set the saved object ID to null so that update input will remove the existing savedObjectId...
|
||||
(newInput as BookByValueInput & { savedObjectId: unknown }).savedObjectId = null;
|
||||
}
|
||||
embeddable.updateInput(newInput);
|
||||
if (useRefType) {
|
||||
// Ensures that any duplicate embeddables also register the changes. This mirrors the behavior of going back and forth between apps
|
||||
embeddable.getRoot().reload();
|
||||
}
|
||||
};
|
||||
const overlay = openModal(
|
||||
toMountPoint(
|
||||
<CreateEditBookComponent
|
||||
savedObjectId={(embeddable.getInput() as BookByReferenceInput).savedObjectId}
|
||||
attributes={embeddable.getOutput().attributes}
|
||||
onSave={(attributes: BookSavedObjectAttributes, useRefType: boolean) => {
|
||||
overlay.close();
|
||||
onSave(attributes, useRefType);
|
||||
}}
|
||||
/>
|
||||
)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { createAction, IncompatibleActionError } from '@kbn/ui-actions-plugin/public';
|
||||
import { IncompatibleActionError } from '@kbn/ui-actions-plugin/public';
|
||||
import { ViewMode, isReferenceOrValueEmbeddable } from '@kbn/embeddable-plugin/public';
|
||||
import { DASHBOARD_CONTAINER_TYPE } from '@kbn/dashboard-plugin/public';
|
||||
import { BookEmbeddable, BOOK_EMBEDDABLE } from './book_embeddable';
|
||||
|
@ -18,31 +18,30 @@ interface ActionContext {
|
|||
|
||||
export const ACTION_UNLINK_BOOK_FROM_LIBRARY = 'ACTION_UNLINK_BOOK_FROM_LIBRARY';
|
||||
|
||||
export const createUnlinkBookFromLibraryAction = () =>
|
||||
createAction({
|
||||
getDisplayName: () =>
|
||||
i18n.translate('embeddableExamples.book.unlinkFromLibrary', {
|
||||
defaultMessage: 'Unlink Book from Library Item',
|
||||
}),
|
||||
id: ACTION_UNLINK_BOOK_FROM_LIBRARY,
|
||||
type: ACTION_UNLINK_BOOK_FROM_LIBRARY,
|
||||
order: 100,
|
||||
getIconType: () => 'folderExclamation',
|
||||
isCompatible: async ({ embeddable }: ActionContext) => {
|
||||
return (
|
||||
embeddable.type === BOOK_EMBEDDABLE &&
|
||||
embeddable.getInput().viewMode === ViewMode.EDIT &&
|
||||
embeddable.getRoot().isContainer &&
|
||||
embeddable.getRoot().type !== DASHBOARD_CONTAINER_TYPE &&
|
||||
isReferenceOrValueEmbeddable(embeddable) &&
|
||||
embeddable.inputIsRefType(embeddable.getInput())
|
||||
);
|
||||
},
|
||||
execute: async ({ embeddable }: ActionContext) => {
|
||||
if (!isReferenceOrValueEmbeddable(embeddable)) {
|
||||
throw new IncompatibleActionError();
|
||||
}
|
||||
const newInput = await embeddable.getInputAsValueType();
|
||||
embeddable.updateInput(newInput);
|
||||
},
|
||||
});
|
||||
export const createUnlinkBookFromLibraryActionDefinition = () => ({
|
||||
getDisplayName: () =>
|
||||
i18n.translate('embeddableExamples.book.unlinkFromLibrary', {
|
||||
defaultMessage: 'Unlink Book from Library Item',
|
||||
}),
|
||||
id: ACTION_UNLINK_BOOK_FROM_LIBRARY,
|
||||
type: ACTION_UNLINK_BOOK_FROM_LIBRARY,
|
||||
order: 100,
|
||||
getIconType: () => 'folderExclamation',
|
||||
isCompatible: async ({ embeddable }: ActionContext) => {
|
||||
return (
|
||||
embeddable.type === BOOK_EMBEDDABLE &&
|
||||
embeddable.getInput().viewMode === ViewMode.EDIT &&
|
||||
embeddable.getRoot().isContainer &&
|
||||
embeddable.getRoot().type !== DASHBOARD_CONTAINER_TYPE &&
|
||||
isReferenceOrValueEmbeddable(embeddable) &&
|
||||
embeddable.inputIsRefType(embeddable.getInput())
|
||||
);
|
||||
},
|
||||
execute: async ({ embeddable }: ActionContext) => {
|
||||
if (!isReferenceOrValueEmbeddable(embeddable)) {
|
||||
throw new IncompatibleActionError();
|
||||
}
|
||||
const newInput = await embeddable.getInputAsValueType();
|
||||
embeddable.updateInput(newInput);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -41,14 +41,14 @@ import {
|
|||
TodoRefEmbeddableFactory,
|
||||
TodoRefEmbeddableFactoryDefinition,
|
||||
} from './todo/todo_ref_embeddable_factory';
|
||||
import { createEditBookAction } from './book/edit_book_action';
|
||||
import { createEditBookActionDefinition } from './book/edit_book_action';
|
||||
import { BOOK_EMBEDDABLE } from './book/book_embeddable';
|
||||
import {
|
||||
BookEmbeddableFactory,
|
||||
BookEmbeddableFactoryDefinition,
|
||||
} from './book/book_embeddable_factory';
|
||||
import { createAddBookToLibraryAction } from './book/add_book_to_library_action';
|
||||
import { createUnlinkBookFromLibraryAction } from './book/unlink_book_from_library_action';
|
||||
import { createAddBookToLibraryActionDefinition } from './book/add_book_to_library_action';
|
||||
import { createUnlinkBookFromLibraryActionDefinition } from './book/unlink_book_from_library_action';
|
||||
import {
|
||||
SIMPLE_EMBEDDABLE,
|
||||
SimpleEmbeddableFactory,
|
||||
|
@ -157,7 +157,7 @@ export class EmbeddableExamplesPlugin
|
|||
}))
|
||||
);
|
||||
|
||||
const editBookAction = createEditBookAction(async () => ({
|
||||
const editBookAction = createEditBookActionDefinition(async () => ({
|
||||
getAttributeService: (await core.getStartServices())[1].embeddable.getAttributeService,
|
||||
openModal: (await core.getStartServices())[0].overlays.openModal,
|
||||
savedObjectsClient: (await core.getStartServices())[0].savedObjects.client,
|
||||
|
@ -165,11 +165,11 @@ export class EmbeddableExamplesPlugin
|
|||
deps.uiActions.registerAction(editBookAction);
|
||||
deps.uiActions.attachAction(CONTEXT_MENU_TRIGGER, editBookAction.id);
|
||||
|
||||
const addBookToLibraryAction = createAddBookToLibraryAction();
|
||||
const addBookToLibraryAction = createAddBookToLibraryActionDefinition();
|
||||
deps.uiActions.registerAction(addBookToLibraryAction);
|
||||
deps.uiActions.attachAction(CONTEXT_MENU_TRIGGER, addBookToLibraryAction.id);
|
||||
|
||||
const unlinkBookFromLibraryAction = createUnlinkBookFromLibraryAction();
|
||||
const unlinkBookFromLibraryAction = createUnlinkBookFromLibraryActionDefinition();
|
||||
deps.uiActions.registerAction(unlinkBookFromLibraryAction);
|
||||
deps.uiActions.attachAction(CONTEXT_MENU_TRIGGER, unlinkBookFromLibraryAction.id);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
import React from 'react';
|
||||
import { EuiText, EuiModalBody, EuiButton } from '@elastic/eui';
|
||||
import { OverlayStart } from '@kbn/core/public';
|
||||
import { createAction } from '@kbn/ui-actions-plugin/public';
|
||||
import { toMountPoint } from '@kbn/kibana-react-plugin/public';
|
||||
|
||||
export const ACTION_HELLO_WORLD = 'ACTION_HELLO_WORLD';
|
||||
|
@ -18,22 +17,23 @@ interface StartServices {
|
|||
openModal: OverlayStart['openModal'];
|
||||
}
|
||||
|
||||
export const createHelloWorldAction = (getStartServices: () => Promise<StartServices>) =>
|
||||
createAction({
|
||||
id: ACTION_HELLO_WORLD,
|
||||
type: ACTION_HELLO_WORLD,
|
||||
getDisplayName: () => 'Hello World!',
|
||||
execute: async () => {
|
||||
const { openModal } = await getStartServices();
|
||||
const overlay = openModal(
|
||||
toMountPoint(
|
||||
<EuiModalBody>
|
||||
<EuiText data-test-subj="helloWorldActionText">Hello world!</EuiText>
|
||||
<EuiButton data-test-subj="closeModal" onClick={() => overlay.close()}>
|
||||
Close
|
||||
</EuiButton>
|
||||
</EuiModalBody>
|
||||
)
|
||||
);
|
||||
},
|
||||
});
|
||||
export const createHelloWorldActionDefinition = (
|
||||
getStartServices: () => Promise<StartServices>
|
||||
) => ({
|
||||
id: ACTION_HELLO_WORLD,
|
||||
type: ACTION_HELLO_WORLD,
|
||||
getDisplayName: () => 'Hello World!',
|
||||
execute: async () => {
|
||||
const { openModal } = await getStartServices();
|
||||
const overlay = openModal(
|
||||
toMountPoint(
|
||||
<EuiModalBody>
|
||||
<EuiText data-test-subj="helloWorldActionText">Hello world!</EuiText>
|
||||
<EuiButton data-test-subj="closeModal" onClick={() => overlay.close()}>
|
||||
Close
|
||||
</EuiButton>
|
||||
</EuiModalBody>
|
||||
)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import { Plugin, CoreSetup, CoreStart } from '@kbn/core/public';
|
||||
import { UiActionsSetup, UiActionsStart } from '@kbn/ui-actions-plugin/public';
|
||||
import { createHelloWorldAction } from './hello_world_action';
|
||||
import { createHelloWorldActionDefinition } from './hello_world_action';
|
||||
import { helloWorldTrigger } from './hello_world_trigger';
|
||||
|
||||
export interface UiActionExamplesSetupDependencies {
|
||||
|
@ -29,7 +29,7 @@ export class UiActionExamplesPlugin
|
|||
) {
|
||||
uiActions.registerTrigger(helloWorldTrigger);
|
||||
|
||||
const helloWorldAction = createHelloWorldAction(async () => ({
|
||||
const helloWorldAction = createHelloWorldActionDefinition(async () => ({
|
||||
openModal: (await core.getStartServices())[0].overlays.openModal,
|
||||
}));
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import React from 'react';
|
|||
|
||||
import { EditPanelAction, isFilterableEmbeddable, ViewMode } from '@kbn/embeddable-plugin/public';
|
||||
import { type IEmbeddable, isErrorEmbeddable } from '@kbn/embeddable-plugin/public';
|
||||
import { KibanaThemeProvider, reactToUiComponent } from '@kbn/kibana-react-plugin/public';
|
||||
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { Action, IncompatibleActionError } from '@kbn/ui-actions-plugin/public';
|
||||
import { createKibanaReactContext } from '@kbn/kibana-react-plugin/public';
|
||||
import type { ApplicationStart } from '@kbn/core/public';
|
||||
|
@ -46,7 +46,7 @@ export class FiltersNotificationAction implements Action<FiltersNotificationActi
|
|||
} = pluginServices.getServices());
|
||||
}
|
||||
|
||||
private FilterIconButton = ({ context }: { context: FiltersNotificationActionContext }) => {
|
||||
public readonly MenuItem = ({ context }: { context: FiltersNotificationActionContext }) => {
|
||||
const { embeddable } = context;
|
||||
|
||||
const editPanelAction = new EditPanelAction(
|
||||
|
@ -76,8 +76,6 @@ export class FiltersNotificationAction implements Action<FiltersNotificationActi
|
|||
);
|
||||
};
|
||||
|
||||
public readonly MenuItem = reactToUiComponent(this.FilterIconButton);
|
||||
|
||||
public getDisplayName({ embeddable }: FiltersNotificationActionContext) {
|
||||
if (!embeddable.getRoot() || !embeddable.getRoot().isContainer) {
|
||||
throw new IncompatibleActionError();
|
||||
|
|
|
@ -15,7 +15,7 @@ import {
|
|||
isReferenceOrValueEmbeddable,
|
||||
} from '@kbn/embeddable-plugin/public';
|
||||
import { Action, IncompatibleActionError } from '@kbn/ui-actions-plugin/public';
|
||||
import { KibanaThemeProvider, reactToUiComponent } from '@kbn/kibana-react-plugin/public';
|
||||
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
|
||||
|
||||
import { pluginServices } from '../services/plugin_services';
|
||||
import { UnlinkFromLibraryAction } from './unlink_from_library_action';
|
||||
|
@ -47,11 +47,7 @@ export class LibraryNotificationAction implements Action<LibraryNotificationActi
|
|||
|
||||
private icon = 'folderCheck';
|
||||
|
||||
private LibraryNotification: React.FC<{ context: LibraryNotificationActionContext }> = ({
|
||||
context,
|
||||
}: {
|
||||
context: LibraryNotificationActionContext;
|
||||
}) => {
|
||||
public readonly MenuItem = ({ context }: { context: LibraryNotificationActionContext }) => {
|
||||
const { embeddable } = context;
|
||||
return (
|
||||
<KibanaThemeProvider theme$={this.theme$}>
|
||||
|
@ -66,8 +62,6 @@ export class LibraryNotificationAction implements Action<LibraryNotificationActi
|
|||
);
|
||||
};
|
||||
|
||||
public readonly MenuItem = reactToUiComponent(this.LibraryNotification);
|
||||
|
||||
public getDisplayName({ embeddable }: LibraryNotificationActionContext) {
|
||||
if (!embeddable.getRoot() || !embeddable.getRoot().isContainer) {
|
||||
throw new IncompatibleActionError();
|
||||
|
|
|
@ -27,7 +27,7 @@ import {
|
|||
} from '@kbn/embeddable-plugin/public/lib/test_samples/embeddables';
|
||||
import { applicationServiceMock, coreMock } from '@kbn/core/public/mocks';
|
||||
import { uiActionsPluginMock } from '@kbn/ui-actions-plugin/public/mocks';
|
||||
import { createEditModeAction } from '@kbn/embeddable-plugin/public/lib/test_samples';
|
||||
import { createEditModeActionDefinition } from '@kbn/embeddable-plugin/public/lib/test_samples';
|
||||
|
||||
import { DashboardContainer } from './dashboard_container';
|
||||
import { getSampleDashboardInput, getSampleDashboardPanel } from '../../mocks';
|
||||
|
@ -201,7 +201,7 @@ test('searchSessionId propagates to children', async () => {
|
|||
test('DashboardContainer in edit mode shows edit mode actions', async () => {
|
||||
const uiActionsSetup = uiActionsPluginMock.createSetupContract();
|
||||
|
||||
const editModeAction = createEditModeAction();
|
||||
const editModeAction = createEditModeActionDefinition();
|
||||
uiActionsSetup.registerAction(editModeAction);
|
||||
uiActionsSetup.addTriggerAction(CONTEXT_MENU_TRIGGER, editModeAction);
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import { Datatable } from '@kbn/expressions-plugin/public';
|
||||
import { Action, createAction, UiActionsStart } from '@kbn/ui-actions-plugin/public';
|
||||
import { UiActionsActionDefinition, UiActionsStart } from '@kbn/ui-actions-plugin/public';
|
||||
import { APPLY_FILTER_TRIGGER } from '../triggers';
|
||||
import { createFiltersFromRangeSelectAction } from './filters/create_filters_from_range_select';
|
||||
|
||||
|
@ -25,10 +25,10 @@ export interface SelectRangeActionContext {
|
|||
|
||||
export const ACTION_SELECT_RANGE = 'ACTION_SELECT_RANGE';
|
||||
|
||||
export function createSelectRangeAction(
|
||||
export function createSelectRangeActionDefinition(
|
||||
getStartServices: () => { uiActions: UiActionsStart }
|
||||
): Action {
|
||||
return createAction({
|
||||
): UiActionsActionDefinition<SelectRangeActionContext> {
|
||||
return {
|
||||
type: ACTION_SELECT_RANGE,
|
||||
id: ACTION_SELECT_RANGE,
|
||||
shouldAutoExecute: async () => true,
|
||||
|
@ -47,5 +47,5 @@ export function createSelectRangeAction(
|
|||
console.warn(`Error [ACTION_SELECT_RANGE]: can\'t extract filters from action context`);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import type { Filter } from '@kbn/es-query';
|
||||
import { Datatable } from '@kbn/expressions-plugin/public';
|
||||
import { Action, createAction, UiActionsStart } from '@kbn/ui-actions-plugin/public';
|
||||
import { UiActionsActionDefinition, UiActionsStart } from '@kbn/ui-actions-plugin/public';
|
||||
import { APPLY_FILTER_TRIGGER } from '../triggers';
|
||||
import { createFiltersFromValueClickAction } from './filters/create_filters_from_value_click';
|
||||
|
||||
|
@ -31,10 +31,10 @@ export interface ValueClickContext {
|
|||
};
|
||||
}
|
||||
|
||||
export function createValueClickAction(
|
||||
export function createValueClickActionDefinition(
|
||||
getStartServices: () => { uiActions: UiActionsStart }
|
||||
): Action {
|
||||
return createAction({
|
||||
): UiActionsActionDefinition<ValueClickContext> {
|
||||
return {
|
||||
type: ACTION_VALUE_CLICK,
|
||||
id: ACTION_VALUE_CLICK,
|
||||
shouldAutoExecute: async () => true,
|
||||
|
@ -59,5 +59,5 @@ export function createValueClickAction(
|
|||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -34,8 +34,8 @@ import {
|
|||
import {
|
||||
createFiltersFromValueClickAction,
|
||||
createFiltersFromRangeSelectAction,
|
||||
createValueClickAction,
|
||||
createSelectRangeAction,
|
||||
createValueClickActionDefinition,
|
||||
createSelectRangeActionDefinition,
|
||||
} from './actions';
|
||||
import { applyFilterTrigger } from './triggers';
|
||||
import { getTableViewDescription } from './utils/table_inspector_view';
|
||||
|
@ -142,14 +142,14 @@ export class DataPublicPlugin
|
|||
|
||||
uiActions.addTriggerAction(
|
||||
'SELECT_RANGE_TRIGGER',
|
||||
createSelectRangeAction(() => ({
|
||||
createSelectRangeActionDefinition(() => ({
|
||||
uiActions,
|
||||
}))
|
||||
);
|
||||
|
||||
uiActions.addTriggerAction(
|
||||
'VALUE_CLICK_TRIGGER',
|
||||
createValueClickAction(() => ({
|
||||
createValueClickActionDefinition(() => ({
|
||||
uiActions,
|
||||
}))
|
||||
);
|
||||
|
|
|
@ -13,12 +13,12 @@ import { mountWithIntl, nextTick } from '@kbn/test-jest-helpers';
|
|||
import { findTestSubject } from '@elastic/eui/lib/test';
|
||||
import { I18nProvider } from '@kbn/i18n-react';
|
||||
import { CONTEXT_MENU_TRIGGER } from '../triggers';
|
||||
import { Action, UiActionsStart } from '@kbn/ui-actions-plugin/public';
|
||||
import { Action, UiActionsStart, ActionInternal } from '@kbn/ui-actions-plugin/public';
|
||||
import { Trigger, ViewMode } from '../types';
|
||||
import { isErrorEmbeddable } from '../embeddables';
|
||||
import { EmbeddablePanel } from './embeddable_panel';
|
||||
import {
|
||||
createEditModeAction,
|
||||
createEditModeActionDefinition,
|
||||
ContactCardEmbeddable,
|
||||
ContactCardEmbeddableInput,
|
||||
ContactCardEmbeddableOutput,
|
||||
|
@ -38,7 +38,7 @@ const triggerRegistry = new Map<string, Trigger>();
|
|||
|
||||
const { setup, doStart } = embeddablePluginMock.createInstance();
|
||||
|
||||
const editModeAction = createEditModeAction();
|
||||
const editModeAction = createEditModeActionDefinition();
|
||||
const trigger: Trigger = {
|
||||
id: CONTEXT_MENU_TRIGGER,
|
||||
};
|
||||
|
@ -50,7 +50,7 @@ const embeddableReactFactory = new ContactCardEmbeddableReactFactory(
|
|||
const applicationMock = applicationServiceMock.createStartContract();
|
||||
const theme = themeServiceMock.createStartContract();
|
||||
|
||||
actionRegistry.set(editModeAction.id, editModeAction);
|
||||
actionRegistry.set(editModeAction.id, new ActionInternal(editModeAction));
|
||||
triggerRegistry.set(trigger.id, trigger);
|
||||
setup.registerEmbeddableFactory(embeddableFactory.type, embeddableFactory);
|
||||
setup.registerEmbeddableFactory(embeddableReactFactory.type, embeddableReactFactory);
|
||||
|
|
|
@ -163,10 +163,15 @@ export class EmbeddablePanel extends React.Component<Props, State> {
|
|||
if (this.props.showBadges === false) {
|
||||
return;
|
||||
}
|
||||
let badges =
|
||||
(await this.props.getActions?.(PANEL_BADGE_TRIGGER, {
|
||||
|
||||
type BadgeAction = Action<
|
||||
EmbeddableContext<IEmbeddable<EmbeddableInput, EmbeddableOutput, any>>
|
||||
>;
|
||||
|
||||
let badges: BadgeAction[] =
|
||||
((await this.props.getActions?.(PANEL_BADGE_TRIGGER, {
|
||||
embeddable: this.props.embeddable,
|
||||
})) ?? [];
|
||||
})) as BadgeAction[]) ?? [];
|
||||
|
||||
const { disabledActions } = this.props.embeddable.getInput();
|
||||
if (disabledActions) {
|
||||
|
@ -187,10 +192,15 @@ export class EmbeddablePanel extends React.Component<Props, State> {
|
|||
if (this.props.showNotifications === false) {
|
||||
return;
|
||||
}
|
||||
let notifications =
|
||||
(await this.props.getActions?.(PANEL_NOTIFICATION_TRIGGER, {
|
||||
|
||||
type NotificationAction = Action<
|
||||
EmbeddableContext<IEmbeddable<EmbeddableInput, EmbeddableOutput, any>>
|
||||
>;
|
||||
|
||||
let notifications: NotificationAction[] =
|
||||
((await this.props.getActions?.(PANEL_NOTIFICATION_TRIGGER, {
|
||||
embeddable: this.props.embeddable,
|
||||
})) ?? [];
|
||||
})) as NotificationAction[]) ?? [];
|
||||
|
||||
const { disabledActions } = this.props.embeddable.getInput();
|
||||
if (disabledActions) {
|
||||
|
|
|
@ -19,7 +19,6 @@ import {
|
|||
import classNames from 'classnames';
|
||||
import React from 'react';
|
||||
import { Action } from '@kbn/ui-actions-plugin/public';
|
||||
import { uiToReactComponent } from '@kbn/kibana-react-plugin/public';
|
||||
import { PanelOptionsMenu } from './panel_options_menu';
|
||||
import { IEmbeddable } from '../../embeddables';
|
||||
import { EmbeddableContext, panelBadgeTrigger, panelNotificationTrigger } from '../../triggers';
|
||||
|
@ -65,7 +64,7 @@ function renderNotifications(
|
|||
const context = { embeddable };
|
||||
|
||||
let badge = notification.MenuItem ? (
|
||||
React.createElement(uiToReactComponent(notification.MenuItem), {
|
||||
React.createElement(notification.MenuItem, {
|
||||
key: notification.id,
|
||||
context: {
|
||||
embeddable,
|
||||
|
|
|
@ -6,19 +6,19 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { createAction } from '../../ui_actions';
|
||||
import { ViewMode } from '../../types';
|
||||
import { IEmbeddable } from '../..';
|
||||
import { UiActionsActionDefinition } from '../../ui_actions';
|
||||
|
||||
export const EDIT_MODE_ACTION = 'EDIT_MODE_ACTION';
|
||||
|
||||
export function createEditModeAction() {
|
||||
return createAction({
|
||||
export function createEditModeActionDefinition(): UiActionsActionDefinition {
|
||||
return {
|
||||
id: EDIT_MODE_ACTION,
|
||||
type: EDIT_MODE_ACTION,
|
||||
getDisplayName: () => 'I only show up in edit mode',
|
||||
isCompatible: async (context: { embeddable: IEmbeddable }) =>
|
||||
context.embeddable.getInput().viewMode === ViewMode.EDIT,
|
||||
execute: async () => {},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export * from './react_to_ui_component';
|
||||
export * from './ui_to_react_component';
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import * as React from 'react';
|
||||
import { reactToUiComponent } from './react_to_ui_component';
|
||||
|
||||
const ReactComp: React.FC<{ cnt?: number }> = ({ cnt = 0 }) => {
|
||||
return <div>cnt: {cnt}</div>;
|
||||
};
|
||||
|
||||
describe('reactToUiComponent', () => {
|
||||
test('can render UI component', () => {
|
||||
const UiComp = reactToUiComponent(ReactComp);
|
||||
const div = document.createElement('div');
|
||||
|
||||
const instance = UiComp();
|
||||
instance.render(div, {});
|
||||
|
||||
expect(div.innerHTML).toBe('<div>cnt: 0</div>');
|
||||
});
|
||||
|
||||
test('can pass in props', async () => {
|
||||
const UiComp = reactToUiComponent(ReactComp);
|
||||
const div = document.createElement('div');
|
||||
|
||||
const instance = UiComp();
|
||||
instance.render(div, { cnt: 5 });
|
||||
|
||||
expect(div.innerHTML).toBe('<div>cnt: 5</div>');
|
||||
});
|
||||
|
||||
test('can re-render multiple times', async () => {
|
||||
const UiComp = reactToUiComponent(ReactComp);
|
||||
const div = document.createElement('div');
|
||||
const instance = UiComp();
|
||||
|
||||
instance.render(div, { cnt: 1 });
|
||||
|
||||
expect(div.innerHTML).toBe('<div>cnt: 1</div>');
|
||||
|
||||
instance.render(div, { cnt: 2 });
|
||||
|
||||
expect(div.innerHTML).toBe('<div>cnt: 2</div>');
|
||||
});
|
||||
|
||||
test('renders React component only when .render() method is called', () => {
|
||||
let renderCnt = 0;
|
||||
const MyReactComp: React.FC<{ cnt?: number }> = ({ cnt = 0 }) => {
|
||||
renderCnt++;
|
||||
return <div>cnt: {cnt}</div>;
|
||||
};
|
||||
const UiComp = reactToUiComponent(MyReactComp);
|
||||
const instance = UiComp();
|
||||
const div = document.createElement('div');
|
||||
|
||||
expect(renderCnt).toBe(0);
|
||||
|
||||
instance.render(div, { cnt: 1 });
|
||||
|
||||
expect(renderCnt).toBe(1);
|
||||
|
||||
instance.render(div, { cnt: 2 });
|
||||
|
||||
expect(renderCnt).toBe(2);
|
||||
|
||||
instance.render(div, { cnt: 3 });
|
||||
|
||||
expect(renderCnt).toBe(3);
|
||||
});
|
||||
});
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { ComponentType, createElement as h } from 'react';
|
||||
import { render as renderReact, unmountComponentAtNode } from 'react-dom';
|
||||
import { UiComponent, UiComponentInstance } from '@kbn/kibana-utils-plugin/public';
|
||||
|
||||
/**
|
||||
* Transform a React component into a `UiComponent`.
|
||||
*
|
||||
* @param ReactComp A React component.
|
||||
*/
|
||||
export const reactToUiComponent =
|
||||
<Props extends object>(ReactComp: ComponentType<Props>): UiComponent<Props> =>
|
||||
() => {
|
||||
let lastEl: HTMLElement | undefined;
|
||||
|
||||
const render: UiComponentInstance<Props>['render'] = (el, props) => {
|
||||
lastEl = el;
|
||||
renderReact(h(ReactComp, props), el);
|
||||
};
|
||||
|
||||
const unmount: UiComponentInstance<Props>['unmount'] = () => {
|
||||
if (lastEl) unmountComponentAtNode(lastEl);
|
||||
};
|
||||
|
||||
const comp: UiComponentInstance<Props> = {
|
||||
render,
|
||||
unmount,
|
||||
};
|
||||
|
||||
return comp;
|
||||
};
|
|
@ -1,142 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import { UiComponent } from '@kbn/kibana-utils-plugin/public';
|
||||
import { uiToReactComponent } from './ui_to_react_component';
|
||||
import { reactToUiComponent } from './react_to_ui_component';
|
||||
|
||||
const UiComp: UiComponent<{ cnt?: number }> = () => ({
|
||||
render: (el, { cnt = 0 }) => {
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
el.innerHTML = `cnt: ${cnt}`;
|
||||
},
|
||||
});
|
||||
|
||||
describe('uiToReactComponent', () => {
|
||||
test('can render React component', () => {
|
||||
const ReactComp = uiToReactComponent(UiComp);
|
||||
const div = document.createElement('div');
|
||||
|
||||
ReactDOM.render(<ReactComp />, div);
|
||||
|
||||
expect(div.innerHTML).toBe('<div>cnt: 0</div>');
|
||||
});
|
||||
|
||||
test('can pass in props', async () => {
|
||||
const ReactComp = uiToReactComponent(UiComp);
|
||||
const div = document.createElement('div');
|
||||
|
||||
ReactDOM.render(<ReactComp cnt={5} />, div);
|
||||
|
||||
expect(div.innerHTML).toBe('<div>cnt: 5</div>');
|
||||
});
|
||||
|
||||
test('re-renders when React component is re-rendered', async () => {
|
||||
const ReactComp = uiToReactComponent(UiComp);
|
||||
const div = document.createElement('div');
|
||||
|
||||
ReactDOM.render(<ReactComp cnt={1} />, div);
|
||||
|
||||
expect(div.innerHTML).toBe('<div>cnt: 1</div>');
|
||||
|
||||
ReactDOM.render(<ReactComp cnt={2} />, div);
|
||||
|
||||
expect(div.innerHTML).toBe('<div>cnt: 2</div>');
|
||||
});
|
||||
|
||||
test('does not crash if .unmount() not provided', () => {
|
||||
const UiComp2: UiComponent<{ cnt?: number }> = () => ({
|
||||
render: (el, { cnt = 0 }) => {
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
el.innerHTML = `cnt: ${cnt}`;
|
||||
},
|
||||
});
|
||||
const ReactComp = uiToReactComponent(UiComp2);
|
||||
const div = document.createElement('div');
|
||||
|
||||
ReactDOM.render(<ReactComp cnt={1} />, div);
|
||||
ReactDOM.unmountComponentAtNode(div);
|
||||
|
||||
expect(div.innerHTML).toBe('');
|
||||
});
|
||||
|
||||
test('calls .unmount() method once when component un-mounts', () => {
|
||||
const unmount = jest.fn();
|
||||
const UiComp2: UiComponent<{ cnt?: number }> = () => ({
|
||||
render: (el, { cnt = 0 }) => {
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
el.innerHTML = `cnt: ${cnt}`;
|
||||
},
|
||||
unmount,
|
||||
});
|
||||
const ReactComp = uiToReactComponent(UiComp2);
|
||||
const div = document.createElement('div');
|
||||
|
||||
expect(unmount).toHaveBeenCalledTimes(0);
|
||||
|
||||
ReactDOM.render(<ReactComp cnt={1} />, div);
|
||||
|
||||
expect(unmount).toHaveBeenCalledTimes(0);
|
||||
|
||||
ReactDOM.unmountComponentAtNode(div);
|
||||
|
||||
expect(unmount).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('calls .render() method only once when components mounts, and once on every re-render', () => {
|
||||
const render = jest.fn((el, { cnt = 0 }) => {
|
||||
// eslint-disable-next-line no-unsanitized/property
|
||||
el.innerHTML = `cnt: ${cnt}`;
|
||||
});
|
||||
const UiComp2: UiComponent<{ cnt?: number }> = () => ({
|
||||
render,
|
||||
});
|
||||
const ReactComp = uiToReactComponent(UiComp2);
|
||||
const div = document.createElement('div');
|
||||
|
||||
expect(render).toHaveBeenCalledTimes(0);
|
||||
|
||||
ReactDOM.render(<ReactComp cnt={1} />, div);
|
||||
|
||||
expect(render).toHaveBeenCalledTimes(1);
|
||||
|
||||
ReactDOM.render(<ReactComp cnt={2} />, div);
|
||||
|
||||
expect(render).toHaveBeenCalledTimes(2);
|
||||
|
||||
ReactDOM.render(<ReactComp cnt={3} />, div);
|
||||
|
||||
expect(render).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
|
||||
test('can specify wrapper element', async () => {
|
||||
const ReactComp = uiToReactComponent(UiComp, 'span');
|
||||
const div = document.createElement('div');
|
||||
|
||||
ReactDOM.render(<ReactComp cnt={5} />, div);
|
||||
|
||||
expect(div.innerHTML).toBe('<span>cnt: 5</span>');
|
||||
});
|
||||
});
|
||||
|
||||
test('can adapt component many times', () => {
|
||||
const ReactComp = uiToReactComponent(
|
||||
reactToUiComponent(uiToReactComponent(reactToUiComponent(uiToReactComponent(UiComp))))
|
||||
);
|
||||
const div = document.createElement('div');
|
||||
|
||||
ReactDOM.render(<ReactComp />, div);
|
||||
|
||||
expect(div.textContent).toBe('cnt: 0');
|
||||
|
||||
ReactDOM.render(<ReactComp cnt={123} />, div);
|
||||
|
||||
expect(div.textContent).toBe('cnt: 123');
|
||||
});
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { FC, createElement as h, useRef, useLayoutEffect, useMemo } from 'react';
|
||||
import { UiComponent, UiComponentInstance } from '@kbn/kibana-utils-plugin/public';
|
||||
|
||||
/**
|
||||
* Transforms `UiComponent` into a React component.
|
||||
*/
|
||||
export const uiToReactComponent =
|
||||
<Props extends object>(Comp: UiComponent<Props>, as: string = 'div'): FC<Props> =>
|
||||
(props) => {
|
||||
const ref = useRef<HTMLDivElement>();
|
||||
const comp = useMemo<UiComponentInstance<Props>>(() => Comp(), [Comp]);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (!ref.current) return;
|
||||
comp.render(ref.current, props);
|
||||
});
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (!comp.unmount) return;
|
||||
return () => {
|
||||
if (comp.unmount) comp.unmount();
|
||||
};
|
||||
}, [comp]);
|
||||
|
||||
return h(as, {
|
||||
ref,
|
||||
});
|
||||
};
|
|
@ -75,8 +75,6 @@ export { createNotifications } from './notifications';
|
|||
/** @deprecated use `Markdown` from `@kbn/shared-ux-markdown` */
|
||||
export { Markdown, MarkdownSimple } from './markdown';
|
||||
|
||||
export { reactToUiComponent, uiToReactComponent } from './adapters';
|
||||
|
||||
export { toMountPoint, MountPointPortal } from './util';
|
||||
export type { ToMountPointOptions } from './util';
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
},
|
||||
"include": [".storybook/**/*", "common/**/*", "public/**/*", "../../../typings/**/*"],
|
||||
"kbn_references": [
|
||||
"@kbn/kibana-utils-plugin",
|
||||
"@kbn/storybook",
|
||||
"@kbn/ui-theme",
|
||||
"@kbn/core",
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
export { Defer, defer } from './defer';
|
||||
export { fieldWildcardMatcher, fieldWildcardFilter } from './field_wildcard';
|
||||
export type { UiComponent, UiComponentInstance } from './ui';
|
||||
export { of } from './of';
|
||||
export type {
|
||||
BaseState,
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export type { UiComponent, UiComponentInstance } from './ui_component';
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface UiComponentInstance<Props extends object = object> {
|
||||
/**
|
||||
* Call this method on initial render and on all subsequent updates.
|
||||
*
|
||||
* @param el DOM element.
|
||||
* @param props Component props, same as props in React.
|
||||
*/
|
||||
render(el: HTMLElement, props: Props): void;
|
||||
|
||||
/**
|
||||
* Un-mount UI component. Call it to remove view from DOM. Implementers of this
|
||||
* interface should clear DOM from this UI component and destroy any internal state.
|
||||
*/
|
||||
unmount?(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* In many places in Kibana we want to be agnostic to frontend view library,
|
||||
* i.e. instead of exposing React-specific APIs we want to expose APIs that
|
||||
* are orthogonal to any rendering library. This interface represents such UI
|
||||
* components. UI component receives a DOM element and `props` through `render()`
|
||||
* method, the `render()` method can be called many times.
|
||||
*
|
||||
* Although Kibana aims to be library agnostic, Kibana itself is written in React,
|
||||
* thus here we define `UiComponent` which is an abstract unit of UI that can be
|
||||
* implemented in any framework, but it maps easily to React components, i.e.
|
||||
* `UiComponent<Props>` is like `React.ComponentType<Props>`.
|
||||
*/
|
||||
export type UiComponent<Props extends object = object> = () => UiComponentInstance<Props>;
|
|
@ -9,7 +9,7 @@
|
|||
import { PluginInitializerContext } from '@kbn/core/public';
|
||||
import { KibanaUtilsPublicPlugin } from './plugin';
|
||||
|
||||
export type { Get, Set, UiComponent, UiComponentInstance } from '../common';
|
||||
export type { Get, Set } from '../common';
|
||||
export {
|
||||
AbortError,
|
||||
abortSignalToPromise,
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import type { SerializableRecord } from '@kbn/utility-types';
|
||||
import { UiComponent } from '../../common/ui/ui_component';
|
||||
import type { FC } from 'react';
|
||||
|
||||
/**
|
||||
* Represents something that can be configured by user using UI.
|
||||
|
@ -27,9 +27,9 @@ export interface Configurable<
|
|||
readonly isConfigValid: (config: Config, context: Context) => boolean;
|
||||
|
||||
/**
|
||||
* `UiComponent` to be rendered when collecting configuration for this item.
|
||||
* Component to be rendered when collecting configuration for this item.
|
||||
*/
|
||||
readonly CollectConfig: UiComponent<CollectConfigProps<Config, Context>>;
|
||||
readonly CollectConfig: FC<CollectConfigProps<Config, Context>>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,9 +6,8 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { UiComponent } from '@kbn/kibana-utils-plugin/public';
|
||||
import { Presentable } from '../util/presentable';
|
||||
import { Trigger } from '../triggers';
|
||||
import type { Presentable } from '../util/presentable';
|
||||
import type { Trigger } from '../triggers';
|
||||
|
||||
/**
|
||||
* During action execution we can provide additional information,
|
||||
|
@ -68,12 +67,6 @@ export interface Action<Context extends object = object>
|
|||
*/
|
||||
getDisplayName(context: ActionExecutionContext<Context>): string;
|
||||
|
||||
/**
|
||||
* `UiComponent` to render when displaying this action as a context menu item.
|
||||
* If not provided, `getDisplayName` will be used instead.
|
||||
*/
|
||||
MenuItem?: UiComponent<ActionMenuItemProps<Context>>;
|
||||
|
||||
/**
|
||||
* Returns a promise that resolves to true if this action is compatible given the context,
|
||||
* otherwise resolves to false.
|
||||
|
|
|
@ -6,69 +6,64 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
// @ts-ignore
|
||||
import React from 'react';
|
||||
import type { UiComponent } from '@kbn/kibana-utils-plugin/public';
|
||||
import { uiToReactComponent } from '@kbn/kibana-react-plugin/public';
|
||||
import { Action, ActionContext as Context, ActionDefinition, ActionMenuItemProps } from './action';
|
||||
import * as React from 'react';
|
||||
import { Action, ActionDefinition, ActionMenuItemProps } from './action';
|
||||
import { Presentable, PresentableGrouping } from '../util/presentable';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export class ActionInternal<A extends ActionDefinition = ActionDefinition>
|
||||
implements Action<Context<A>>, Presentable<Context<A>>
|
||||
export class ActionInternal<Context extends object = object>
|
||||
implements Action<Context>, Presentable<Context>
|
||||
{
|
||||
public readonly id: string;
|
||||
public readonly type: string;
|
||||
public readonly order: number;
|
||||
public readonly MenuItem?: UiComponent<ActionMenuItemProps<Context<A>>>;
|
||||
public readonly ReactMenuItem?: React.FC<ActionMenuItemProps<Context<A>>>;
|
||||
public readonly grouping?: PresentableGrouping<Context<A>>;
|
||||
public readonly MenuItem?: React.FC<ActionMenuItemProps<any>>;
|
||||
public readonly grouping?: PresentableGrouping<Context>;
|
||||
public readonly showNotification?: boolean;
|
||||
public readonly disabled?: boolean;
|
||||
|
||||
constructor(public readonly definition: A) {
|
||||
constructor(public readonly definition: ActionDefinition<Context>) {
|
||||
this.id = this.definition.id;
|
||||
this.type = this.definition.type || '';
|
||||
this.order = this.definition.order || 0;
|
||||
this.MenuItem = this.definition.MenuItem;
|
||||
this.ReactMenuItem = this.MenuItem ? uiToReactComponent(this.MenuItem) : undefined;
|
||||
this.grouping = this.definition.grouping;
|
||||
this.showNotification = this.definition.showNotification;
|
||||
this.disabled = this.definition.disabled;
|
||||
}
|
||||
|
||||
public execute(context: Context<A>) {
|
||||
public execute(context: Context) {
|
||||
return this.definition.execute(context);
|
||||
}
|
||||
|
||||
public getIconType(context: Context<A>): string | undefined {
|
||||
public getIconType(context: Context): string | undefined {
|
||||
if (!this.definition.getIconType) return undefined;
|
||||
return this.definition.getIconType(context);
|
||||
}
|
||||
|
||||
public getDisplayName(context: Context<A>): string {
|
||||
public getDisplayName(context: Context): string {
|
||||
if (!this.definition.getDisplayName) return `Action: ${this.id}`;
|
||||
return this.definition.getDisplayName(context);
|
||||
}
|
||||
|
||||
public getDisplayNameTooltip(context: Context<A>): string {
|
||||
public getDisplayNameTooltip(context: Context): string {
|
||||
if (!this.definition.getDisplayNameTooltip) return '';
|
||||
return this.definition.getDisplayNameTooltip(context);
|
||||
}
|
||||
|
||||
public async isCompatible(context: Context<A>): Promise<boolean> {
|
||||
public async isCompatible(context: Context): Promise<boolean> {
|
||||
if (!this.definition.isCompatible) return true;
|
||||
return await this.definition.isCompatible(context);
|
||||
}
|
||||
|
||||
public async getHref(context: Context<A>): Promise<string | undefined> {
|
||||
public async getHref(context: Context): Promise<string | undefined> {
|
||||
if (!this.definition.getHref) return undefined;
|
||||
return await this.definition.getHref(context);
|
||||
}
|
||||
|
||||
public async shouldAutoExecute(context: Context<A>): Promise<boolean> {
|
||||
public async shouldAutoExecute(context: Context): Promise<boolean> {
|
||||
if (!this.definition.shouldAutoExecute) return false;
|
||||
return this.definition.shouldAutoExecute(context);
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@ import * as React from 'react';
|
|||
import { EuiContextMenuPanelDescriptor, EuiContextMenuPanelItemDescriptor } from '@elastic/eui';
|
||||
import _ from 'lodash';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import type { Trigger } from '../triggers';
|
||||
import type { Action, ActionDefinition, ActionExecutionContext, ActionInternal } from '../actions';
|
||||
import { Trigger } from '../triggers';
|
||||
import type { Action, ActionExecutionContext, ActionInternal } from '../actions';
|
||||
|
||||
export const defaultTitle = i18n.translate('uiActions.actionPanel.title', {
|
||||
defaultMessage: 'Options',
|
||||
|
@ -22,7 +22,7 @@ export const txtMore = i18n.translate('uiActions.actionPanel.more', {
|
|||
});
|
||||
|
||||
interface ActionWithContext<Context extends object = object> {
|
||||
action: Action<Context> | ActionInternal<ActionDefinition<Context>>;
|
||||
action: Action<Context> | ActionInternal<Context>;
|
||||
context: Context;
|
||||
|
||||
/**
|
||||
|
@ -43,11 +43,7 @@ type PanelDescriptor = EuiContextMenuPanelDescriptor & {
|
|||
};
|
||||
|
||||
const onClick =
|
||||
(
|
||||
action: Action | ActionInternal<ActionDefinition>,
|
||||
context: ActionExecutionContext<object>,
|
||||
close: () => void
|
||||
) =>
|
||||
(action: Action | ActionInternal, context: ActionExecutionContext<object>, close: () => void) =>
|
||||
(event: React.MouseEvent) => {
|
||||
if (event.currentTarget instanceof HTMLAnchorElement) {
|
||||
// from react-router's <Link/>
|
||||
|
@ -166,10 +162,8 @@ export async function buildContextMenuForActions({
|
|||
}
|
||||
}
|
||||
panels[parentPanel || 'mainMenu'].items!.push({
|
||||
name: (action as ActionInternal<ActionDefinition>).ReactMenuItem
|
||||
? React.createElement((action as ActionInternal<ActionDefinition>).ReactMenuItem!, {
|
||||
context,
|
||||
})
|
||||
name: action.MenuItem
|
||||
? React.createElement(action.MenuItem, { context })
|
||||
: action.getDisplayName(context),
|
||||
icon: action.getIconType(context),
|
||||
toolTipContent: action.getDisplayNameTooltip ? action.getDisplayNameTooltip(context) : '',
|
||||
|
|
|
@ -17,7 +17,7 @@ export type { UiActionsSetup, UiActionsStart } from './plugin';
|
|||
export type { UiActionsServiceParams } from './service';
|
||||
export { UiActionsService } from './service';
|
||||
export type { Action, ActionDefinition as UiActionsActionDefinition } from './actions';
|
||||
export { createAction, IncompatibleActionError } from './actions';
|
||||
export { ActionInternal, createAction, IncompatibleActionError } from './actions';
|
||||
export { buildContextMenuForActions } from './context_menu';
|
||||
export type {
|
||||
Presentable as UiActionsPresentable,
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import { UiActionsService } from './ui_actions_service';
|
||||
import { Action, ActionDefinition, ActionInternal, createAction } from '../actions';
|
||||
import { ActionDefinition, ActionInternal } from '../actions';
|
||||
import { createHelloWorldAction } from '../tests/test_samples';
|
||||
import { TriggerRegistry, ActionRegistry } from '../types';
|
||||
import { Trigger } from '../triggers';
|
||||
|
@ -17,7 +17,7 @@ const FOO_TRIGGER = 'FOO_TRIGGER';
|
|||
const BAR_TRIGGER = 'BAR_TRIGGER';
|
||||
const MY_TRIGGER = 'MY_TRIGGER';
|
||||
|
||||
const testAction1: Action = {
|
||||
const testAction1: ActionDefinition = {
|
||||
id: 'action1',
|
||||
order: 1,
|
||||
type: 'type1',
|
||||
|
@ -27,7 +27,7 @@ const testAction1: Action = {
|
|||
isCompatible: async () => true,
|
||||
};
|
||||
|
||||
const testAction2: Action = {
|
||||
const testAction2: ActionDefinition = {
|
||||
id: 'action2',
|
||||
order: 2,
|
||||
type: 'type2',
|
||||
|
@ -108,7 +108,7 @@ describe('UiActionsService', () => {
|
|||
});
|
||||
|
||||
describe('.getTriggerActions()', () => {
|
||||
const action1: Action = {
|
||||
const action1: ActionDefinition = {
|
||||
id: 'action1',
|
||||
order: 1,
|
||||
type: 'type1',
|
||||
|
@ -117,7 +117,7 @@ describe('UiActionsService', () => {
|
|||
getIconType: () => '',
|
||||
isCompatible: async () => true,
|
||||
};
|
||||
const action2: Action = {
|
||||
const action2: ActionDefinition = {
|
||||
id: 'action2',
|
||||
order: 2,
|
||||
type: 'type2',
|
||||
|
@ -194,12 +194,12 @@ describe('UiActionsService', () => {
|
|||
|
||||
test('filters out actions not applicable based on the context', async () => {
|
||||
const service = new UiActionsService();
|
||||
const action = createAction({
|
||||
const action = {
|
||||
id: 'test',
|
||||
type: 'test',
|
||||
isCompatible: ({ accept }: { accept: boolean }) => Promise.resolve(accept),
|
||||
execute: () => Promise.resolve(),
|
||||
});
|
||||
};
|
||||
|
||||
service.registerAction(action);
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import { TriggerRegistry, ActionRegistry, TriggerToActionsRegistry } from '../types';
|
||||
import { ActionInternal, Action, ActionDefinition, ActionContext } from '../actions';
|
||||
import { ActionInternal, Action, ActionDefinition } from '../actions';
|
||||
import { Trigger } from '../triggers/trigger';
|
||||
import { TriggerInternal } from '../triggers/trigger_internal';
|
||||
import { TriggerContract } from '../triggers/trigger_contract';
|
||||
|
@ -60,16 +60,16 @@ export class UiActionsService {
|
|||
return trigger.contract;
|
||||
};
|
||||
|
||||
public readonly registerAction = <A extends ActionDefinition>(
|
||||
definition: A
|
||||
): Action<ActionContext<A>> => {
|
||||
public readonly registerAction = <Context extends object>(
|
||||
definition: ActionDefinition<Context>
|
||||
): Action<Context> => {
|
||||
if (this.actions.has(definition.id)) {
|
||||
throw new Error(`Action [action.id = ${definition.id}] already registered.`);
|
||||
}
|
||||
|
||||
const action = new ActionInternal(definition);
|
||||
|
||||
this.actions.set(action.id, action);
|
||||
this.actions.set(action.id, action as unknown as ActionInternal<object>);
|
||||
|
||||
return action;
|
||||
};
|
||||
|
@ -123,22 +123,17 @@ export class UiActionsService {
|
|||
* `addTriggerAction` is similar to `attachAction` as it attaches action to a
|
||||
* trigger, but it also registers the action, if it has not been registered, yet.
|
||||
*/
|
||||
public readonly addTriggerAction = (
|
||||
triggerId: string,
|
||||
action: ActionDefinition // TODO: remove `Action` https://github.com/elastic/kibana/issues/74501
|
||||
): void => {
|
||||
public readonly addTriggerAction = (triggerId: string, action: ActionDefinition<any>): void => {
|
||||
if (!this.actions.has(action.id)) this.registerAction(action);
|
||||
this.attachAction(triggerId, action.id);
|
||||
};
|
||||
|
||||
public readonly getAction = <T extends ActionDefinition>(
|
||||
id: string
|
||||
): Action<ActionContext<T>> => {
|
||||
public readonly getAction = (id: string): Action => {
|
||||
if (!this.actions.has(id)) {
|
||||
throw new Error(`Action [action.id = ${id}] not registered.`);
|
||||
}
|
||||
|
||||
return this.actions.get(id) as ActionInternal<T>;
|
||||
return this.actions.get(id)! as Action;
|
||||
};
|
||||
|
||||
public readonly getTriggerActions = (triggerId: string): Action[] => {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { Action, createAction } from '../actions';
|
||||
import { ActionDefinition } from '../actions';
|
||||
import { openContextMenu } from '../context_menu';
|
||||
import { uiActionsPluginMock } from '../mocks';
|
||||
import { Trigger } from '../triggers';
|
||||
|
@ -23,14 +23,14 @@ function createTestAction<C extends object>(
|
|||
type: string,
|
||||
checkCompatibility: (context: C) => boolean,
|
||||
autoExecutable = false
|
||||
): Action<object> {
|
||||
return createAction({
|
||||
): ActionDefinition {
|
||||
return {
|
||||
type,
|
||||
id: type,
|
||||
isCompatible: (context: C) => Promise.resolve(checkCompatibility(context)),
|
||||
execute: (context) => executeFn(context),
|
||||
shouldAutoExecute: () => Promise.resolve(autoExecutable),
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
let uiActions: ReturnType<typeof uiActionsPluginMock.createPlugin>;
|
||||
|
|
|
@ -6,19 +6,22 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { ActionInternal, Action } from '../actions';
|
||||
import { ActionInternal, ActionDefinition } from '../actions';
|
||||
import { uiActionsPluginMock } from '../mocks';
|
||||
|
||||
const action1: Action = {
|
||||
const action1: ActionDefinition = {
|
||||
id: 'action1',
|
||||
order: 1,
|
||||
type: 'type1',
|
||||
} as unknown as Action;
|
||||
const action2: Action = {
|
||||
execute: async () => {},
|
||||
};
|
||||
|
||||
const action2: ActionDefinition = {
|
||||
id: 'action2',
|
||||
order: 2,
|
||||
type: 'type2',
|
||||
} as unknown as Action;
|
||||
execute: async () => {},
|
||||
};
|
||||
|
||||
test('returns actions set on trigger', () => {
|
||||
const { setup, doStart } = uiActionsPluginMock.createPlugin();
|
||||
|
|
|
@ -8,26 +8,26 @@
|
|||
|
||||
import { uiActionsPluginMock } from '../mocks';
|
||||
import { createHelloWorldAction } from './test_samples';
|
||||
import { Action, createAction } from '../actions';
|
||||
import { ActionDefinition } from '../actions';
|
||||
import { Trigger } from '../triggers';
|
||||
import { OverlayStart } from '@kbn/core/public';
|
||||
|
||||
let action: Action<{ name: string }>;
|
||||
let action: ActionDefinition<{ name: string }>;
|
||||
let uiActions: ReturnType<typeof uiActionsPluginMock.createPlugin>;
|
||||
beforeEach(() => {
|
||||
uiActions = uiActionsPluginMock.createPlugin();
|
||||
action = createAction({
|
||||
action = {
|
||||
id: 'test',
|
||||
type: 'test',
|
||||
execute: () => Promise.resolve(),
|
||||
});
|
||||
};
|
||||
|
||||
uiActions.setup.registerAction(action);
|
||||
uiActions.setup.registerAction(action as ActionDefinition);
|
||||
uiActions.setup.registerTrigger({
|
||||
id: 'trigger',
|
||||
title: 'trigger',
|
||||
});
|
||||
uiActions.setup.addTriggerAction('trigger', action);
|
||||
uiActions.setup.addTriggerAction('trigger', action as ActionDefinition);
|
||||
});
|
||||
|
||||
test('can register action', async () => {
|
||||
|
@ -59,14 +59,14 @@ test('getTriggerCompatibleActions returns attached actions', async () => {
|
|||
|
||||
test('filters out actions not applicable based on the context', async () => {
|
||||
const { setup, doStart } = uiActions;
|
||||
const action1 = createAction({
|
||||
const action1 = {
|
||||
id: 'test1',
|
||||
type: 'test1',
|
||||
isCompatible: async (context: { accept: boolean }) => {
|
||||
return Promise.resolve(context.accept);
|
||||
},
|
||||
execute: () => Promise.resolve(),
|
||||
});
|
||||
};
|
||||
|
||||
const testTrigger: Trigger = {
|
||||
id: 'MY-TRIGGER2',
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
import React from 'react';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiBadge, EuiFlyoutBody } from '@elastic/eui';
|
||||
import { CoreStart } from '@kbn/core/public';
|
||||
import { toMountPoint, reactToUiComponent } from '@kbn/kibana-react-plugin/public';
|
||||
import { createAction, Action } from '../../actions';
|
||||
import { toMountPoint } from '@kbn/kibana-react-plugin/public';
|
||||
import { ActionDefinition } from '../../actions';
|
||||
|
||||
const ReactMenuItem: React.FC = () => {
|
||||
const MenuItem: React.FC = () => {
|
||||
return (
|
||||
<EuiFlexGroup alignItems="center">
|
||||
<EuiFlexItem>Hello world!</EuiFlexItem>
|
||||
|
@ -23,16 +23,14 @@ const ReactMenuItem: React.FC = () => {
|
|||
);
|
||||
};
|
||||
|
||||
const UiMenuItem = reactToUiComponent(ReactMenuItem);
|
||||
|
||||
export const ACTION_HELLO_WORLD = 'ACTION_HELLO_WORLD';
|
||||
|
||||
export function createHelloWorldAction(overlays: CoreStart['overlays']): Action {
|
||||
return createAction({
|
||||
export function createHelloWorldAction(overlays: CoreStart['overlays']): ActionDefinition {
|
||||
return {
|
||||
id: ACTION_HELLO_WORLD,
|
||||
type: ACTION_HELLO_WORLD,
|
||||
getIconType: () => 'lock',
|
||||
MenuItem: UiMenuItem,
|
||||
MenuItem,
|
||||
execute: async () => {
|
||||
overlays.openFlyout(
|
||||
toMountPoint(<EuiFlyoutBody>Hello World, I am a hello world action!</EuiFlyoutBody>),
|
||||
|
@ -42,5 +40,5 @@ export function createHelloWorldAction(overlays: CoreStart['overlays']): Action
|
|||
}
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { UiComponent } from '@kbn/kibana-utils-plugin/public';
|
||||
import type { FC } from 'react';
|
||||
|
||||
/**
|
||||
* Represents something that can be displayed to user in UI.
|
||||
|
@ -24,10 +24,10 @@ export interface Presentable<Context = unknown> {
|
|||
readonly order: number;
|
||||
|
||||
/**
|
||||
* `UiComponent` to render when displaying this entity as a context menu item.
|
||||
* Component to render when displaying this entity as a context menu item.
|
||||
* If not provided, `getDisplayName` will be used instead.
|
||||
*/
|
||||
readonly MenuItem?: UiComponent<{ context: Context }>;
|
||||
readonly MenuItem?: FC<{ context: Context }>;
|
||||
|
||||
/**
|
||||
* Optional EUI icon type that can be displayed along with the title.
|
||||
|
|
|
@ -298,11 +298,7 @@ const SelectedActionFactory: React.FC<SelectedActionFactoryProps> = ({
|
|||
)}
|
||||
<EuiSpacer size="m" />
|
||||
<div>
|
||||
<actionFactory.ReactCollectConfig
|
||||
config={config}
|
||||
onConfig={onConfigChange}
|
||||
context={context}
|
||||
/>
|
||||
<actionFactory.CollectConfig config={config} onConfig={onConfigChange} context={context} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
import React, { useState } from 'react';
|
||||
import { EuiFieldText, EuiFormRow, EuiSelect, EuiSwitch } from '@elastic/eui';
|
||||
import { reactToUiComponent } from '@kbn/kibana-react-plugin/public';
|
||||
import { CollectConfigProps } from '@kbn/kibana-utils-plugin/public';
|
||||
import { licensingMock } from '@kbn/licensing-plugin/public/mocks';
|
||||
import {
|
||||
|
@ -98,7 +97,7 @@ export const dashboardDrilldownActionFactory: ActionFactoryDefinition<
|
|||
if (!config.dashboardId) return false;
|
||||
return true;
|
||||
},
|
||||
CollectConfig: reactToUiComponent(DashboardDrilldownCollectConfig),
|
||||
CollectConfig: DashboardDrilldownCollectConfig,
|
||||
|
||||
isCompatible(context?: object): Promise<boolean> {
|
||||
return Promise.resolve(true);
|
||||
|
@ -164,7 +163,7 @@ export const urlDrilldownActionFactory: ActionFactoryDefinition<UrlDrilldownConf
|
|||
if (!config.url) return false;
|
||||
return true;
|
||||
},
|
||||
CollectConfig: reactToUiComponent(UrlDrilldownCollectConfig),
|
||||
CollectConfig: UrlDrilldownCollectConfig,
|
||||
|
||||
order: 10,
|
||||
isCompatible(context?: object): Promise<boolean> {
|
||||
|
|
|
@ -6,9 +6,10 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { FC } from 'react';
|
||||
import type { LicenseType } from '@kbn/licensing-plugin/public';
|
||||
import type { ActionExecutionContext } from '@kbn/ui-actions-plugin/public';
|
||||
import type { PersistableStateDefinition, UiComponent } from '@kbn/kibana-utils-plugin/common';
|
||||
import type { PersistableStateDefinition } from '@kbn/kibana-utils-plugin/common';
|
||||
import type {
|
||||
ActionFactoryDefinition,
|
||||
BaseActionConfig,
|
||||
|
@ -72,22 +73,17 @@ export interface DrilldownDefinition<
|
|||
createConfig: ActionFactoryDefinition<Config, ExecutionContext, FactoryContext>['createConfig'];
|
||||
|
||||
/**
|
||||
* `UiComponent` that collects config for this drilldown. You can create
|
||||
* a React component and transform it `UiComponent` using `uiToReactComponent`
|
||||
* helper from `kibana_utils` plugin.
|
||||
* Component that collects config for this drilldown.
|
||||
*
|
||||
* ```tsx
|
||||
* import React from 'react';
|
||||
* import { uiToReactComponent } from 'src/plugins/kibana_utils';
|
||||
* import { CollectConfigProps } from 'src/plugins/kibana_utils/public';
|
||||
*
|
||||
* type Props = CollectConfigProps<Config>;
|
||||
*
|
||||
* const ReactCollectConfig: React.FC<Props> = () => {
|
||||
* export const CollectConfig: React.FC<Props> = () => {
|
||||
* return <div>Collecting config...'</div>;
|
||||
* };
|
||||
*
|
||||
* export const CollectConfig = uiToReactComponent(ReactCollectConfig);
|
||||
* ```
|
||||
*/
|
||||
CollectConfig: ActionFactoryDefinition<Config, ExecutionContext, FactoryContext>['CollectConfig'];
|
||||
|
@ -118,7 +114,7 @@ export interface DrilldownDefinition<
|
|||
* Name of the drilldown instance displayed to the user at the moment of
|
||||
* drilldown execution. Should be internationalized.
|
||||
*/
|
||||
readonly actionMenuItem?: UiComponent<{
|
||||
readonly actionMenuItem?: FC<{
|
||||
config: Omit<SerializedAction<Config>, 'factoryId'>;
|
||||
context: ExecutionContext | ActionExecutionContext<ExecutionContext>;
|
||||
}>;
|
||||
|
|
|
@ -42,7 +42,7 @@ export const DrilldownStateForm: React.FC<DrilldownStateFormProps> = ({ state, d
|
|||
triggers={triggerPickerProps}
|
||||
disabled={disabled}
|
||||
>
|
||||
<state.factory.ReactCollectConfig
|
||||
<state.factory.CollectConfig
|
||||
config={config}
|
||||
onConfig={disabled ? () => {} : state.setConfig}
|
||||
context={context}
|
||||
|
|
|
@ -36,11 +36,7 @@ export const CreateDrilldownForm: React.FC<CreateDrilldownFormProps> = ({ state
|
|||
|
||||
return (
|
||||
<DrilldownForm name={name} onNameChange={state.setName} triggers={triggerPickerProps}>
|
||||
<state.factory.ReactCollectConfig
|
||||
config={config}
|
||||
onConfig={state.setConfig}
|
||||
context={context}
|
||||
/>
|
||||
<state.factory.CollectConfig config={config} onConfig={state.setConfig} context={context} />
|
||||
</DrilldownForm>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -46,11 +46,7 @@ export const EditDrilldownForm: React.FC<EditDrilldownFormProps> = ({ state }) =
|
|||
return (
|
||||
<>
|
||||
<DrilldownForm name={name} onNameChange={state.setName} triggers={triggerPickerProps}>
|
||||
<state.factory.ReactCollectConfig
|
||||
config={config}
|
||||
onConfig={state.setConfig}
|
||||
context={context}
|
||||
/>
|
||||
<state.factory.CollectConfig config={config} onConfig={state.setConfig} context={context} />
|
||||
</DrilldownForm>
|
||||
<EuiSpacer size={'xl'} />
|
||||
<EuiButton
|
||||
|
|
|
@ -42,7 +42,7 @@ const createDrilldownManagerState = () => {
|
|||
const factory1 = new ActionFactory(
|
||||
{
|
||||
id: 'FACTORY1',
|
||||
CollectConfig: () => ({ render: () => {} }),
|
||||
CollectConfig: () => null,
|
||||
supportedTriggers: () => ['TRIGGER1', 'TRIGGER2'],
|
||||
isConfigValid: () => true,
|
||||
createConfig: () => ({}),
|
||||
|
@ -56,7 +56,7 @@ const createDrilldownManagerState = () => {
|
|||
const factory2 = new ActionFactory(
|
||||
{
|
||||
id: 'FACTORY2',
|
||||
CollectConfig: () => ({ render: () => {} }),
|
||||
CollectConfig: () => null,
|
||||
supportedTriggers: () => ['TRIGGER2', 'TRIGGER3'],
|
||||
isConfigValid: () => true,
|
||||
createConfig: () => ({}),
|
||||
|
@ -70,7 +70,7 @@ const createDrilldownManagerState = () => {
|
|||
const factory3 = new ActionFactory(
|
||||
{
|
||||
id: 'FACTORY3',
|
||||
CollectConfig: () => ({ render: () => {} }),
|
||||
CollectConfig: () => null,
|
||||
supportedTriggers: () => ['TRIGGER_MISSING'],
|
||||
isConfigValid: () => true,
|
||||
createConfig: () => ({}),
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { UiComponent, CollectConfigProps } from '@kbn/kibana-utils-plugin/public';
|
||||
import type { FC } from 'react';
|
||||
import type { CollectConfigProps } from '@kbn/kibana-utils-plugin/public';
|
||||
import type {
|
||||
MigrateFunctionsObject,
|
||||
GetMigrationFunctionObjectFn,
|
||||
} from '@kbn/kibana-utils-plugin/common';
|
||||
import { uiToReactComponent } from '@kbn/kibana-react-plugin/public';
|
||||
import type {
|
||||
UiActionsPresentable as Presentable,
|
||||
ActionMenuItemProps,
|
||||
|
@ -48,11 +48,9 @@ export class ActionFactory<
|
|||
public readonly minimalLicense?: LicenseType;
|
||||
public readonly licenseFeatureName?: string;
|
||||
public readonly order: number;
|
||||
public readonly MenuItem?: UiComponent<ActionMenuItemProps<FactoryContext>>;
|
||||
public readonly ReactMenuItem?: React.FC<ActionMenuItemProps<FactoryContext>>;
|
||||
public readonly MenuItem?: FC<ActionMenuItemProps<any>>;
|
||||
|
||||
public readonly CollectConfig: UiComponent<CollectConfigProps<Config, FactoryContext>>;
|
||||
public readonly ReactCollectConfig: React.FC<CollectConfigProps<Config, FactoryContext>>;
|
||||
public readonly CollectConfig: FC<CollectConfigProps<Config, FactoryContext>>;
|
||||
public readonly createConfig: (context: FactoryContext) => Config;
|
||||
public readonly isConfigValid: (config: Config, context: FactoryContext) => boolean;
|
||||
public readonly migrations: MigrateFunctionsObject | GetMigrationFunctionObjectFn;
|
||||
|
@ -73,9 +71,7 @@ export class ActionFactory<
|
|||
this.licenseFeatureName = this.def.licenseFeatureName;
|
||||
this.order = this.def.order || 0;
|
||||
this.MenuItem = this.def.MenuItem;
|
||||
this.ReactMenuItem = this.MenuItem ? uiToReactComponent(this.MenuItem) : undefined;
|
||||
this.CollectConfig = this.def.CollectConfig;
|
||||
this.ReactCollectConfig = uiToReactComponent(this.CollectConfig);
|
||||
this.createConfig = this.def.createConfig;
|
||||
this.isConfigValid = this.def.isConfigValid;
|
||||
this.migrations = this.def.migrations || {};
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { createElement } from 'react';
|
||||
import { SerializableRecord } from '@kbn/utility-types';
|
||||
import { ILicense } from '@kbn/licensing-plugin/common/types';
|
||||
import { LicensingPluginSetup, LicensingPluginStart } from '@kbn/licensing-plugin/public';
|
||||
|
@ -67,7 +68,7 @@ export class UiActionsServiceEnhancements
|
|||
actionFactory.id,
|
||||
actionFactory as unknown as ActionFactory<
|
||||
SerializableRecord,
|
||||
ExecutionContext,
|
||||
object,
|
||||
BaseActionFactoryContext
|
||||
>
|
||||
);
|
||||
|
@ -145,15 +146,7 @@ export class UiActionsServiceEnhancements
|
|||
getIconType: () => euiIcon,
|
||||
getDisplayName: () => serializedAction.name,
|
||||
MenuItem: actionMenuItem
|
||||
? () => {
|
||||
const comp = actionMenuItem();
|
||||
return {
|
||||
render: (el, { context }) => {
|
||||
comp.render(el, { context, config: serializedAction });
|
||||
},
|
||||
unmount: comp.unmount,
|
||||
};
|
||||
}
|
||||
? ({ context }) => createElement(actionMenuItem, { context, config: serializedAction })
|
||||
: undefined,
|
||||
execute: async (context) => await execute(serializedAction.config, context),
|
||||
getHref: getHref ? async (context) => getHref(serializedAction.config, context) : undefined,
|
||||
|
|
|
@ -12,13 +12,13 @@ import { ReactWrapper } from 'enzyme';
|
|||
import { EuiButton, EuiPopoverFooter } from '@elastic/eui';
|
||||
import { mountWithIntl } from '@kbn/test-jest-helpers';
|
||||
import { stubLogstashDataView as dataView } from '@kbn/data-views-plugin/common/data_view.stub';
|
||||
import { ActionInternal } from '@kbn/ui-actions-plugin/public';
|
||||
import { uiActionsPluginMock } from '@kbn/ui-actions-plugin/public/mocks';
|
||||
import { FieldVisualizeButton } from './field_visualize_button';
|
||||
import {
|
||||
ACTION_VISUALIZE_LENS_FIELD,
|
||||
VISUALIZE_FIELD_TRIGGER,
|
||||
VISUALIZE_GEO_FIELD_TRIGGER,
|
||||
createAction,
|
||||
VisualizeFieldContext,
|
||||
} from '@kbn/ui-actions-plugin/public';
|
||||
import { TriggerContract } from '@kbn/ui-actions-plugin/public/triggers';
|
||||
|
@ -26,7 +26,7 @@ import { TriggerContract } from '@kbn/ui-actions-plugin/public/triggers';
|
|||
const ORIGINATING_APP = 'test';
|
||||
const mockExecuteAction = jest.fn();
|
||||
const uiActions = uiActionsPluginMock.createStartContract();
|
||||
const visualizeAction = createAction<VisualizeFieldContext>({
|
||||
const visualizeAction = new ActionInternal({
|
||||
type: ACTION_VISUALIZE_LENS_FIELD,
|
||||
id: ACTION_VISUALIZE_LENS_FIELD,
|
||||
getDisplayName: () => 'test',
|
||||
|
@ -37,7 +37,9 @@ const visualizeAction = createAction<VisualizeFieldContext>({
|
|||
getHref: async () => '/app/test',
|
||||
});
|
||||
|
||||
jest.spyOn(uiActions, 'getTriggerCompatibleActions').mockResolvedValue([visualizeAction]);
|
||||
jest
|
||||
.spyOn(uiActions, 'getTriggerCompatibleActions')
|
||||
.mockResolvedValue([visualizeAction as ActionInternal<object>]);
|
||||
jest.spyOn(uiActions, 'getTrigger').mockReturnValue({
|
||||
id: ACTION_VISUALIZE_LENS_FIELD,
|
||||
exec: mockExecuteAction,
|
||||
|
|
|
@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import { ThemeServiceSetup } from '@kbn/core/public';
|
||||
import type { IEmbeddable } from '@kbn/embeddable-plugin/public';
|
||||
import { toMountPoint } from '@kbn/kibana-react-plugin/public';
|
||||
import { Action, createAction, IncompatibleActionError } from '@kbn/ui-actions-plugin/public';
|
||||
import { IncompatibleActionError, UiActionsActionDefinition } from '@kbn/ui-actions-plugin/public';
|
||||
// for cleanup esFilters need to fix the issue https://github.com/elastic/kibana/issues/131292
|
||||
import { FilterManager, TimefilterContract } from '@kbn/data-plugin/public';
|
||||
import type { Filter, RangeFilter } from '@kbn/es-query';
|
||||
|
@ -36,8 +36,8 @@ export function createFilterAction(
|
|||
filterManager: FilterManager,
|
||||
timeFilter: TimefilterContract,
|
||||
theme: ThemeServiceSetup
|
||||
): Action {
|
||||
return createAction({
|
||||
): UiActionsActionDefinition<ApplyGlobalFilterActionContext> {
|
||||
return {
|
||||
type: ACTION_GLOBAL_APPLY_FILTER,
|
||||
id: ACTION_GLOBAL_APPLY_FILTER,
|
||||
order: 100,
|
||||
|
@ -115,7 +115,7 @@ export function createFilterAction(
|
|||
filterManager.addFilters(selectedFilters);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
async function changeTimeFilter(timeFilter: TimefilterContract, filter: RangeFilter) {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { Action, ActionExecutionMeta, createAction } from '@kbn/ui-actions-plugin/public';
|
||||
import { ActionExecutionMeta, UiActionsActionDefinition } from '@kbn/ui-actions-plugin/public';
|
||||
import { FilterManager } from '@kbn/data-plugin/public';
|
||||
|
||||
export const UPDATE_FILTER_REFERENCES_ACTION = 'UPDATE_FILTER_REFERENCES_ACTION';
|
||||
|
@ -24,8 +24,10 @@ export interface UpdateFilterReferencesActionContext extends ActionExecutionMeta
|
|||
defaultDataView?: string;
|
||||
}
|
||||
|
||||
export function createUpdateFilterReferencesAction(filterManager: FilterManager): Action {
|
||||
return createAction<UpdateFilterReferencesActionContext>({
|
||||
export function createUpdateFilterReferencesAction(
|
||||
filterManager: FilterManager
|
||||
): UiActionsActionDefinition<UpdateFilterReferencesActionContext> {
|
||||
return {
|
||||
type: UPDATE_FILTER_REFERENCES_ACTION,
|
||||
id: UPDATE_FILTER_REFERENCES_ACTION,
|
||||
execute: async ({ fromDataView, toDataView, usedDataViews, defaultDataView }) => {
|
||||
|
@ -65,5 +67,5 @@ export function createUpdateFilterReferencesAction(filterManager: FilterManager)
|
|||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -83,15 +83,9 @@ export class UnifiedSearchPublicPlugin
|
|||
},
|
||||
});
|
||||
|
||||
uiActions.addTriggerAction(
|
||||
APPLY_FILTER_TRIGGER,
|
||||
uiActions.getAction(ACTION_GLOBAL_APPLY_FILTER)
|
||||
);
|
||||
uiActions.attachAction(APPLY_FILTER_TRIGGER, ACTION_GLOBAL_APPLY_FILTER);
|
||||
|
||||
uiActions.addTriggerAction(
|
||||
UPDATE_FILTER_REFERENCES_TRIGGER,
|
||||
uiActions.getAction(UPDATE_FILTER_REFERENCES_ACTION)
|
||||
);
|
||||
uiActions.attachAction(UPDATE_FILTER_REFERENCES_TRIGGER, UPDATE_FILTER_REFERENCES_ACTION);
|
||||
|
||||
return {
|
||||
ui: {
|
||||
|
|
|
@ -10,7 +10,6 @@ import React from 'react';
|
|||
import { take } from 'rxjs/operators';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiBadge } from '@elastic/eui';
|
||||
import { METRIC_TYPE } from '@kbn/analytics';
|
||||
import { reactToUiComponent } from '@kbn/kibana-react-plugin/public';
|
||||
import { ActionExecutionContext } from '@kbn/ui-actions-plugin/public';
|
||||
import { TimefilterContract } from '@kbn/data-plugin/public';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
@ -30,7 +29,7 @@ const displayName = i18n.translate('visualizations.actions.editInLens.displayNam
|
|||
defaultMessage: 'Convert to Lens',
|
||||
});
|
||||
|
||||
const ReactMenuItem: React.FC = () => {
|
||||
const MenuItem: React.FC = () => {
|
||||
return (
|
||||
<EuiFlexGroup alignItems="center">
|
||||
<EuiFlexItem>{displayName}</EuiFlexItem>
|
||||
|
@ -45,8 +44,6 @@ const ReactMenuItem: React.FC = () => {
|
|||
);
|
||||
};
|
||||
|
||||
const UiMenuItem = reactToUiComponent(ReactMenuItem);
|
||||
|
||||
const isVisualizeEmbeddable = (embeddable: IEmbeddable): embeddable is VisualizeEmbeddable => {
|
||||
return 'getVis' in embeddable;
|
||||
};
|
||||
|
@ -106,7 +103,7 @@ export class EditInLensAction implements Action<EditInLensContext> {
|
|||
return displayName;
|
||||
}
|
||||
|
||||
MenuItem = UiMenuItem;
|
||||
MenuItem = MenuItem;
|
||||
|
||||
getIconType(context: ActionExecutionContext<EditInLensContext>): string | undefined {
|
||||
return 'merge';
|
||||
|
|
|
@ -39,7 +39,6 @@ jest.mock('@kbn/kibana-react-plugin/public', () => ({
|
|||
},
|
||||
})),
|
||||
withKibana: jest.fn((comp) => comp),
|
||||
reactToUiComponent: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('../../services', () => ({
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
import React from 'react';
|
||||
import { EuiFieldText, EuiFormRow } from '@elastic/eui';
|
||||
import type { SerializableRecord } from '@kbn/utility-types';
|
||||
import { reactToUiComponent } from '@kbn/kibana-react-plugin/public';
|
||||
import { UiActionsEnhancedDrilldownDefinition as Drilldown } from '@kbn/ui-actions-enhanced-plugin/public';
|
||||
import { CollectConfigProps as CollectConfigPropsBase } from '@kbn/kibana-utils-plugin/public';
|
||||
import { SAMPLE_APP1_CLICK_TRIGGER, SampleApp1ClickContext } from '../../triggers';
|
||||
|
@ -20,7 +19,7 @@ export interface Config extends SerializableRecord {
|
|||
type Trigger = typeof SAMPLE_APP1_CLICK_TRIGGER;
|
||||
type Context = SampleApp1ClickContext;
|
||||
|
||||
export type CollectConfigProps = CollectConfigPropsBase<Config, { triggers: Trigger[] }>;
|
||||
export type CollectConfigProps = CollectConfigPropsBase<Config, { triggers: string[] }>;
|
||||
|
||||
export const APP1_HELLO_WORLD_DRILLDOWN = 'APP1_HELLO_WORLD_DRILLDOWN';
|
||||
|
||||
|
@ -37,11 +36,7 @@ export class App1HelloWorldDrilldown implements Drilldown<Config, Context> {
|
|||
return [SAMPLE_APP1_CLICK_TRIGGER];
|
||||
}
|
||||
|
||||
private readonly ReactCollectConfig: React.FC<CollectConfigProps> = ({
|
||||
config,
|
||||
onConfig,
|
||||
context,
|
||||
}) => (
|
||||
public readonly CollectConfig: React.FC<CollectConfigProps> = ({ config, onConfig }) => (
|
||||
<EuiFormRow label="Enter your name" fullWidth>
|
||||
<EuiFieldText
|
||||
fullWidth
|
||||
|
@ -51,8 +46,6 @@ export class App1HelloWorldDrilldown implements Drilldown<Config, Context> {
|
|||
</EuiFormRow>
|
||||
);
|
||||
|
||||
public readonly CollectConfig = reactToUiComponent(this.ReactCollectConfig);
|
||||
|
||||
public readonly createConfig = () => ({
|
||||
name: '',
|
||||
});
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
import React from 'react';
|
||||
import { EuiFormRow, EuiFieldText } from '@elastic/eui';
|
||||
import { reactToUiComponent } from '@kbn/kibana-react-plugin/public';
|
||||
import { UiActionsEnhancedDrilldownDefinition as Drilldown } from '@kbn/ui-actions-enhanced-plugin/public';
|
||||
import {
|
||||
ChartActionContext,
|
||||
|
@ -37,11 +36,7 @@ export class DashboardHelloWorldDrilldown implements Drilldown<Config, ActionCon
|
|||
return [VALUE_CLICK_TRIGGER, SELECT_RANGE_TRIGGER];
|
||||
}
|
||||
|
||||
private readonly ReactCollectConfig: React.FC<CollectConfigProps<Config>> = ({
|
||||
config,
|
||||
onConfig,
|
||||
context,
|
||||
}) => (
|
||||
public readonly CollectConfig = ({ config, onConfig, context }: CollectConfigProps<Config>) => (
|
||||
<EuiFormRow label="Enter your name" fullWidth>
|
||||
<EuiFieldText
|
||||
fullWidth
|
||||
|
@ -51,8 +46,6 @@ export class DashboardHelloWorldDrilldown implements Drilldown<Config, ActionCon
|
|||
</EuiFormRow>
|
||||
);
|
||||
|
||||
public readonly CollectConfig = reactToUiComponent(this.ReactCollectConfig);
|
||||
|
||||
public readonly createConfig = () => ({
|
||||
name: '',
|
||||
});
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
import React from 'react';
|
||||
import { EuiFormRow, EuiFieldText } from '@elastic/eui';
|
||||
import { reactToUiComponent } from '@kbn/kibana-react-plugin/public';
|
||||
import { UiActionsEnhancedDrilldownDefinition as Drilldown } from '@kbn/ui-actions-enhanced-plugin/public';
|
||||
import { RangeSelectContext, SELECT_RANGE_TRIGGER } from '@kbn/embeddable-plugin/public';
|
||||
import { CollectConfigProps } from '@kbn/kibana-utils-plugin/public';
|
||||
|
@ -35,10 +34,7 @@ export class DashboardHelloWorldOnlyRangeSelectDrilldown
|
|||
return [SELECT_RANGE_TRIGGER];
|
||||
}
|
||||
|
||||
private readonly ReactCollectConfig: React.FC<CollectConfigProps<Config>> = ({
|
||||
config,
|
||||
onConfig,
|
||||
}) => (
|
||||
public readonly CollectConfig = ({ config, onConfig }: CollectConfigProps<Config>) => (
|
||||
<EuiFormRow label="Enter your name" fullWidth>
|
||||
<EuiFieldText
|
||||
fullWidth
|
||||
|
@ -48,8 +44,6 @@ export class DashboardHelloWorldOnlyRangeSelectDrilldown
|
|||
</EuiFormRow>
|
||||
);
|
||||
|
||||
public readonly CollectConfig = reactToUiComponent(this.ReactCollectConfig);
|
||||
|
||||
public readonly createConfig = () => ({
|
||||
name: '',
|
||||
});
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { reactToUiComponent } from '@kbn/kibana-react-plugin/public';
|
||||
import { StartServicesGetter } from '@kbn/kibana-utils-plugin/public';
|
||||
import { UiActionsEnhancedDrilldownDefinition as Drilldown } from '@kbn/ui-actions-enhanced-plugin/public';
|
||||
import { APPLY_FILTER_TRIGGER } from '@kbn/data-plugin/public';
|
||||
|
@ -31,9 +30,7 @@ export interface Params {
|
|||
export class DashboardToDiscoverDrilldown
|
||||
implements Drilldown<Config, ApplyGlobalFilterActionContext>
|
||||
{
|
||||
constructor(protected readonly params: Params) {
|
||||
this.ReactCollectConfig = (props) => <CollectConfigContainer {...props} params={this.params} />;
|
||||
}
|
||||
constructor(protected readonly params: Params) {}
|
||||
|
||||
public readonly id = SAMPLE_DASHBOARD_TO_DISCOVER_DRILLDOWN;
|
||||
|
||||
|
@ -47,9 +44,9 @@ export class DashboardToDiscoverDrilldown
|
|||
return [APPLY_FILTER_TRIGGER];
|
||||
}
|
||||
|
||||
private readonly ReactCollectConfig!: React.FC<CollectConfigProps>;
|
||||
|
||||
public readonly CollectConfig = reactToUiComponent(this.ReactCollectConfig);
|
||||
public readonly CollectConfig = (props: CollectConfigProps) => (
|
||||
<CollectConfigContainer {...props} params={this.params} />
|
||||
);
|
||||
|
||||
public readonly createConfig = () => ({
|
||||
customIndexPattern: false,
|
||||
|
|
|
@ -9,17 +9,12 @@ import type { KibanaLocation } from '@kbn/share-plugin/public';
|
|||
import React from 'react';
|
||||
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import { DashboardStart } from '@kbn/dashboard-plugin/public';
|
||||
import { reactToUiComponent } from '@kbn/kibana-react-plugin/public';
|
||||
import {
|
||||
AdvancedUiActionsStart,
|
||||
UiActionsEnhancedBaseActionFactoryContext as BaseActionFactoryContext,
|
||||
UiActionsEnhancedDrilldownDefinition as Drilldown,
|
||||
} from '@kbn/ui-actions-enhanced-plugin/public';
|
||||
import {
|
||||
CollectConfigProps,
|
||||
StartServicesGetter,
|
||||
UiComponent,
|
||||
} from '@kbn/kibana-utils-plugin/public';
|
||||
import { CollectConfigProps, StartServicesGetter } from '@kbn/kibana-utils-plugin/public';
|
||||
import { DrilldownConfig } from '../../../../common/drilldowns/dashboard_drilldown/types';
|
||||
import { CollectConfigContainer } from './components';
|
||||
import { txtGoToDashboard } from './i18n';
|
||||
|
@ -38,7 +33,7 @@ export abstract class AbstractDashboardDrilldown<Context extends object = object
|
|||
{
|
||||
constructor(protected readonly params: Params) {
|
||||
this.ReactCollectConfig = (props) => <CollectConfigContainer {...props} params={this.params} />;
|
||||
this.CollectConfig = reactToUiComponent(this.ReactCollectConfig);
|
||||
this.CollectConfig = this.ReactCollectConfig;
|
||||
}
|
||||
|
||||
public abstract readonly id: string;
|
||||
|
@ -61,7 +56,7 @@ export abstract class AbstractDashboardDrilldown<Context extends object = object
|
|||
CollectConfigProps<Config, BaseActionFactoryContext>
|
||||
>;
|
||||
|
||||
public readonly CollectConfig: UiComponent<
|
||||
public readonly CollectConfig: React.FC<
|
||||
CollectConfigProps<DrilldownConfig, BaseActionFactoryContext>
|
||||
>;
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import React from 'react';
|
|||
import { distinctUntilChanged, filter, map, skip, take, takeUntil } from 'rxjs/operators';
|
||||
import { Subject } from 'rxjs';
|
||||
import { Action } from '@kbn/ui-actions-plugin/public';
|
||||
import { reactToUiComponent, toMountPoint } from '@kbn/kibana-react-plugin/public';
|
||||
import { toMountPoint } from '@kbn/kibana-react-plugin/public';
|
||||
import { EmbeddableContext, ViewMode, CONTEXT_MENU_TRIGGER } from '@kbn/embeddable-plugin/public';
|
||||
import {
|
||||
isEnhancedEmbeddable,
|
||||
|
@ -43,7 +43,7 @@ export class FlyoutEditDrilldownAction implements Action<EmbeddableContext> {
|
|||
return 'list';
|
||||
}
|
||||
|
||||
MenuItem = reactToUiComponent(MenuItem);
|
||||
public readonly MenuItem = MenuItem as any;
|
||||
|
||||
public async isCompatible({ embeddable }: EmbeddableContext) {
|
||||
if (embeddable.getInput().viewMode !== ViewMode.EDIT) return false;
|
||||
|
|
|
@ -14,18 +14,15 @@ import { EnhancedEmbeddable } from '@kbn/embeddable-enhanced-plugin/public';
|
|||
|
||||
test('<MenuItem/>', () => {
|
||||
const state = createStateContainer<{ events: object[] }>({ events: [] });
|
||||
const { getByText, queryByText } = render(
|
||||
<MenuItem
|
||||
context={{
|
||||
embeddable: {
|
||||
enhancements: {
|
||||
dynamicActions: { state } as unknown as DynamicActionManager,
|
||||
},
|
||||
} as unknown as EnhancedEmbeddable,
|
||||
trigger: {} as any,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
const context = {
|
||||
embeddable: {
|
||||
enhancements: {
|
||||
dynamicActions: { state } as unknown as DynamicActionManager,
|
||||
},
|
||||
} as unknown as EnhancedEmbeddable,
|
||||
trigger: {},
|
||||
};
|
||||
const { getByText, queryByText } = render(<MenuItem context={context} />);
|
||||
|
||||
expect(getByText(/manage drilldowns/i)).toBeInTheDocument();
|
||||
expect(queryByText('0')).not.toBeInTheDocument();
|
||||
|
|
|
@ -9,12 +9,9 @@ import React from 'react';
|
|||
import { EuiNotificationBadge, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { useContainerState } from '@kbn/kibana-utils-plugin/public';
|
||||
import { EnhancedEmbeddableContext } from '@kbn/embeddable-enhanced-plugin/public';
|
||||
import { ActionExecutionContext } from '@kbn/ui-actions-plugin/public';
|
||||
import { txtDisplayName } from './i18n';
|
||||
|
||||
export const MenuItem: React.FC<{ context: ActionExecutionContext<EnhancedEmbeddableContext> }> = ({
|
||||
context,
|
||||
}) => {
|
||||
export const MenuItem = ({ context }: { context: EnhancedEmbeddableContext }) => {
|
||||
const { events } = useContainerState(context.embeddable.enhancements.dynamicActions.state);
|
||||
const count = events.length;
|
||||
|
||||
|
|
|
@ -18,15 +18,8 @@ import {
|
|||
import { IMAGE_CLICK_TRIGGER } from '@kbn/image-embeddable-plugin/public';
|
||||
import { ActionExecutionContext, ROW_CLICK_TRIGGER } from '@kbn/ui-actions-plugin/public';
|
||||
import type { Query, Filter, TimeRange } from '@kbn/es-query';
|
||||
import type {
|
||||
CollectConfigProps as CollectConfigPropsBase,
|
||||
UiComponent,
|
||||
} from '@kbn/kibana-utils-plugin/public';
|
||||
import {
|
||||
reactToUiComponent,
|
||||
UrlTemplateEditorVariable,
|
||||
KibanaContextProvider,
|
||||
} from '@kbn/kibana-react-plugin/public';
|
||||
import type { CollectConfigProps as CollectConfigPropsBase } from '@kbn/kibana-utils-plugin/public';
|
||||
import { UrlTemplateEditorVariable, KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import {
|
||||
UiActionsEnhancedDrilldownDefinition as Drilldown,
|
||||
UrlDrilldownGlobalScope,
|
||||
|
@ -88,10 +81,10 @@ export class UrlDrilldown implements Drilldown<Config, ActionContext, ActionFact
|
|||
|
||||
public readonly getDisplayName = () => txtUrlDrilldownDisplayName;
|
||||
|
||||
public readonly actionMenuItem: UiComponent<{
|
||||
public readonly actionMenuItem: React.FC<{
|
||||
config: Omit<SerializedAction<UrlDrilldownConfig>, 'factoryId'>;
|
||||
context: ActionContext | ActionExecutionContext<ActionContext>;
|
||||
}> = reactToUiComponent(({ config, context }) => {
|
||||
}> = ({ config, context }) => {
|
||||
const [title, setTitle] = React.useState(config.name);
|
||||
React.useEffect(() => {
|
||||
let unmounted = false;
|
||||
|
@ -107,7 +100,7 @@ export class UrlDrilldown implements Drilldown<Config, ActionContext, ActionFact
|
|||
};
|
||||
});
|
||||
return <>{title}</>;
|
||||
});
|
||||
};
|
||||
|
||||
public readonly euiIcon = 'link';
|
||||
|
||||
|
@ -120,12 +113,7 @@ export class UrlDrilldown implements Drilldown<Config, ActionContext, ActionFact
|
|||
IMAGE_CLICK_TRIGGER,
|
||||
];
|
||||
}
|
||||
|
||||
private readonly ReactCollectConfig: React.FC<CollectConfigProps> = ({
|
||||
config,
|
||||
onConfig,
|
||||
context,
|
||||
}) => {
|
||||
public readonly CollectConfig: React.FC<CollectConfigProps> = ({ config, onConfig, context }) => {
|
||||
const [variables, exampleUrl] = React.useMemo(
|
||||
() => [this.getVariableList(context), this.getExampleUrl(context)],
|
||||
[context]
|
||||
|
@ -149,8 +137,6 @@ export class UrlDrilldown implements Drilldown<Config, ActionContext, ActionFact
|
|||
);
|
||||
};
|
||||
|
||||
public readonly CollectConfig = reactToUiComponent(this.ReactCollectConfig);
|
||||
|
||||
public readonly createConfig = () => ({
|
||||
url: {
|
||||
template: '',
|
||||
|
|
|
@ -788,10 +788,10 @@ export class Embeddable
|
|||
const { getTriggerCompatibleActions } = this.deps;
|
||||
if (getTriggerCompatibleActions) {
|
||||
const embeddable = this;
|
||||
const actions: Array<Action<CellValueContext>> = await getTriggerCompatibleActions(
|
||||
const actions: Array<Action<CellValueContext>> = (await getTriggerCompatibleActions(
|
||||
CELL_VALUE_TRIGGER,
|
||||
{ data, embeddable }
|
||||
);
|
||||
)) as Array<Action<CellValueContext>>;
|
||||
return actions
|
||||
.sort((a, b) => (a.order ?? Infinity) - (b.order ?? Infinity))
|
||||
.map((action) => ({
|
||||
|
|
|
@ -12,7 +12,6 @@ import { APPLY_FILTER_TRIGGER } from '@kbn/data-plugin/public';
|
|||
import type { ApplicationStart } from '@kbn/core/public';
|
||||
import type { SerializableRecord } from '@kbn/utility-types';
|
||||
import type { CollectConfigProps as CollectConfigPropsBase } from '@kbn/kibana-utils-plugin/public';
|
||||
import { reactToUiComponent } from '@kbn/kibana-react-plugin/public';
|
||||
import type {
|
||||
UiActionsEnhancedDrilldownDefinition as Drilldown,
|
||||
UiActionsEnhancedBaseActionFactoryContext as BaseActionFactoryContext,
|
||||
|
@ -92,7 +91,7 @@ export class OpenInDiscoverDrilldown
|
|||
);
|
||||
};
|
||||
|
||||
public readonly CollectConfig = reactToUiComponent(this.ReactCollectConfig);
|
||||
public readonly CollectConfig = this.ReactCollectConfig;
|
||||
|
||||
public readonly createConfig = () => ({
|
||||
openInNewTab: true,
|
||||
|
|
|
@ -65,7 +65,6 @@ jest.mock('@kbn/kibana-react-plugin/public', () => ({
|
|||
withKibana: (comp) => {
|
||||
return comp;
|
||||
},
|
||||
reactToUiComponent: jest.fn(),
|
||||
}));
|
||||
|
||||
import { shallowWithIntl, mountWithIntl } from '@kbn/test-jest-helpers';
|
||||
|
|
|
@ -54,7 +54,6 @@ jest.mock('@kbn/kibana-react-plugin/public', () => ({
|
|||
withKibana: (node) => {
|
||||
return node;
|
||||
},
|
||||
reactToUiComponent: jest.fn(),
|
||||
}));
|
||||
|
||||
const testingState = {
|
||||
|
|
|
@ -14,7 +14,6 @@ jest.mock('@kbn/kibana-react-plugin/public', () => ({
|
|||
withKibana: (comp) => {
|
||||
return comp;
|
||||
},
|
||||
reactToUiComponent: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('CalendarListsHeader', () => {
|
||||
|
|
|
@ -49,7 +49,6 @@ jest.mock('@kbn/kibana-react-plugin/public', () => ({
|
|||
withKibana: (node) => {
|
||||
return node;
|
||||
},
|
||||
reactToUiComponent: jest.fn(),
|
||||
}));
|
||||
|
||||
import { shallowWithIntl } from '@kbn/test-jest-helpers';
|
||||
|
|
|
@ -30,7 +30,6 @@ jest.mock('@kbn/kibana-react-plugin/public', () => ({
|
|||
withKibana: (node) => {
|
||||
return node;
|
||||
},
|
||||
reactToUiComponent: jest.fn(),
|
||||
}));
|
||||
|
||||
// Mock the call for loading the list of filters.
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import { Filter, FilterStateStore } from '@kbn/es-query';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { createAction } from '@kbn/ui-actions-plugin/public';
|
||||
import type { UiActionsActionDefinition } from '@kbn/ui-actions-plugin/public';
|
||||
import { MlCoreSetup } from '../plugin';
|
||||
import {
|
||||
ANOMALY_EXPLORER_CHARTS_EMBEDDABLE_TYPE,
|
||||
|
@ -20,8 +20,8 @@ export const APPLY_ENTITY_FIELD_FILTERS_ACTION = 'applyEntityFieldFiltersAction'
|
|||
|
||||
export function createApplyEntityFieldFiltersAction(
|
||||
getStartServices: MlCoreSetup['getStartServices']
|
||||
) {
|
||||
return createAction<AnomalyChartsFieldSelectionContext>({
|
||||
): UiActionsActionDefinition<AnomalyChartsFieldSelectionContext> {
|
||||
return {
|
||||
id: 'apply-entity-field-filters',
|
||||
type: APPLY_ENTITY_FIELD_FILTERS_ACTION,
|
||||
getIconType(context: AnomalyChartsFieldSelectionContext): string {
|
||||
|
@ -88,5 +88,5 @@ export function createApplyEntityFieldFiltersAction(
|
|||
async isCompatible({ embeddable, data }) {
|
||||
return embeddable.type === ANOMALY_EXPLORER_CHARTS_EMBEDDABLE_TYPE && data !== undefined;
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import { Filter, FilterStateStore } from '@kbn/es-query';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { createAction } from '@kbn/ui-actions-plugin/public';
|
||||
import type { UiActionsActionDefinition } from '@kbn/ui-actions-plugin/public';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { DASHBOARD_APP_ID } from '@kbn/dashboard-plugin/public';
|
||||
import { MlCoreSetup } from '../plugin';
|
||||
|
@ -21,8 +21,8 @@ const supportedApps = [DASHBOARD_APP_ID];
|
|||
|
||||
export function createApplyInfluencerFiltersAction(
|
||||
getStartServices: MlCoreSetup['getStartServices']
|
||||
) {
|
||||
return createAction<SwimLaneDrilldownContext>({
|
||||
): UiActionsActionDefinition<SwimLaneDrilldownContext> {
|
||||
return {
|
||||
id: 'apply-to-current-view',
|
||||
type: APPLY_INFLUENCER_FILTERS_ACTION,
|
||||
getIconType(context: SwimLaneDrilldownContext): string {
|
||||
|
@ -85,5 +85,5 @@ export function createApplyInfluencerFiltersAction(
|
|||
supportedApps.includes(appId!)
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import moment from 'moment';
|
||||
import { createAction } from '@kbn/ui-actions-plugin/public';
|
||||
import type { UiActionsActionDefinition } from '@kbn/ui-actions-plugin/public';
|
||||
import { DASHBOARD_APP_ID } from '@kbn/dashboard-plugin/public';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { MlCoreSetup } from '../plugin';
|
||||
|
@ -19,8 +19,8 @@ const supportedApps = [DASHBOARD_APP_ID];
|
|||
|
||||
export function createApplyTimeRangeSelectionAction(
|
||||
getStartServices: MlCoreSetup['getStartServices']
|
||||
) {
|
||||
return createAction<SwimLaneDrilldownContext>({
|
||||
): UiActionsActionDefinition<SwimLaneDrilldownContext> {
|
||||
return {
|
||||
id: 'apply-time-range-selection',
|
||||
type: APPLY_TIME_RANGE_SELECTION_ACTION,
|
||||
getIconType(context): string {
|
||||
|
@ -61,5 +61,5 @@ export function createApplyTimeRangeSelectionAction(
|
|||
supportedApps.includes(appId!)
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { createAction } from '@kbn/ui-actions-plugin/public';
|
||||
import type { UiActionsActionDefinition } from '@kbn/ui-actions-plugin/public';
|
||||
import { MlCoreSetup } from '../plugin';
|
||||
|
||||
export const CLEAR_SELECTION_ACTION = 'clearSelectionAction';
|
||||
|
@ -15,8 +15,10 @@ export interface ClearSelectionContext {
|
|||
updateCallback: () => void;
|
||||
}
|
||||
|
||||
export function createClearSelectionAction(getStartServices: MlCoreSetup['getStartServices']) {
|
||||
return createAction<ClearSelectionContext>({
|
||||
export function createClearSelectionAction(
|
||||
getStartServices: MlCoreSetup['getStartServices']
|
||||
): UiActionsActionDefinition<ClearSelectionContext> {
|
||||
return {
|
||||
id: 'clear-selection-action',
|
||||
type: CLEAR_SELECTION_ACTION,
|
||||
getIconType(context): string {
|
||||
|
@ -33,5 +35,5 @@ export function createClearSelectionAction(getStartServices: MlCoreSetup['getSta
|
|||
async isCompatible({ updateCallback }) {
|
||||
return typeof updateCallback === 'function';
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { createAction } from '@kbn/ui-actions-plugin/public';
|
||||
import type { UiActionsActionDefinition } from '@kbn/ui-actions-plugin/public';
|
||||
import { ViewMode } from '@kbn/embeddable-plugin/public';
|
||||
import { MlCoreSetup } from '../plugin';
|
||||
import {
|
||||
|
@ -18,8 +18,8 @@ export const EDIT_ANOMALY_CHARTS_PANEL_ACTION = 'editAnomalyChartsPanelAction';
|
|||
|
||||
export function createEditAnomalyChartsPanelAction(
|
||||
getStartServices: MlCoreSetup['getStartServices']
|
||||
) {
|
||||
return createAction<EditAnomalyChartsPanelContext>({
|
||||
): UiActionsActionDefinition<EditAnomalyChartsPanelContext> {
|
||||
return {
|
||||
id: 'edit-anomaly-charts',
|
||||
type: EDIT_ANOMALY_CHARTS_PANEL_ACTION,
|
||||
getIconType(context): string {
|
||||
|
@ -56,5 +56,5 @@ export function createEditAnomalyChartsPanelAction(
|
|||
embeddable.getInput().viewMode === ViewMode.EDIT
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,15 +6,17 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { createAction } from '@kbn/ui-actions-plugin/public';
|
||||
import type { UiActionsActionDefinition } from '@kbn/ui-actions-plugin/public';
|
||||
import { ViewMode } from '@kbn/embeddable-plugin/public';
|
||||
import { MlCoreSetup } from '../plugin';
|
||||
import { ANOMALY_SWIMLANE_EMBEDDABLE_TYPE, EditSwimlanePanelContext } from '../embeddables';
|
||||
|
||||
export const EDIT_SWIMLANE_PANEL_ACTION = 'editSwimlanePanelAction';
|
||||
|
||||
export function createEditSwimlanePanelAction(getStartServices: MlCoreSetup['getStartServices']) {
|
||||
return createAction<EditSwimlanePanelContext>({
|
||||
export function createEditSwimlanePanelAction(
|
||||
getStartServices: MlCoreSetup['getStartServices']
|
||||
): UiActionsActionDefinition<EditSwimlanePanelContext> {
|
||||
return {
|
||||
id: 'edit-anomaly-swimlane',
|
||||
type: EDIT_SWIMLANE_PANEL_ACTION,
|
||||
getIconType(context): string {
|
||||
|
@ -48,5 +50,5 @@ export function createEditSwimlanePanelAction(getStartServices: MlCoreSetup['get
|
|||
embeddable.getInput().viewMode === ViewMode.EDIT
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { SerializableRecord } from '@kbn/utility-types';
|
||||
import { createAction } from '@kbn/ui-actions-plugin/public';
|
||||
import type { UiActionsActionDefinition } from '@kbn/ui-actions-plugin/public';
|
||||
import { MlCoreSetup } from '../plugin';
|
||||
import { ML_APP_LOCATOR } from '../../common/constants/locator';
|
||||
import {
|
||||
|
@ -23,8 +23,10 @@ import { ExplorerAppState } from '../../common/types/locator';
|
|||
|
||||
export const OPEN_IN_ANOMALY_EXPLORER_ACTION = 'openInAnomalyExplorerAction';
|
||||
|
||||
export function createOpenInExplorerAction(getStartServices: MlCoreSetup['getStartServices']) {
|
||||
return createAction<SwimLaneDrilldownContext | AnomalyChartsFieldSelectionContext>({
|
||||
export function createOpenInExplorerAction(
|
||||
getStartServices: MlCoreSetup['getStartServices']
|
||||
): UiActionsActionDefinition<SwimLaneDrilldownContext | AnomalyChartsFieldSelectionContext> {
|
||||
return {
|
||||
id: 'open-in-anomaly-explorer',
|
||||
type: OPEN_IN_ANOMALY_EXPLORER_ACTION,
|
||||
getIconType(context): string {
|
||||
|
@ -129,5 +131,5 @@ export function createOpenInExplorerAction(getStartServices: MlCoreSetup['getSta
|
|||
embeddable.type === ANOMALY_EXPLORER_CHARTS_EMBEDDABLE_TYPE
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,13 +7,15 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import type { Embeddable } from '@kbn/lens-plugin/public';
|
||||
import { createAction } from '@kbn/ui-actions-plugin/public';
|
||||
import type { UiActionsActionDefinition } from '@kbn/ui-actions-plugin/public';
|
||||
import { MlCoreSetup } from '../plugin';
|
||||
|
||||
export const CREATE_LENS_VIS_TO_ML_AD_JOB_ACTION = 'createMLADJobAction';
|
||||
|
||||
export function createLensVisToADJobAction(getStartServices: MlCoreSetup['getStartServices']) {
|
||||
return createAction<{ embeddable: Embeddable }>({
|
||||
export function createLensVisToADJobAction(
|
||||
getStartServices: MlCoreSetup['getStartServices']
|
||||
): UiActionsActionDefinition<{ embeddable: Embeddable }> {
|
||||
return {
|
||||
id: 'create-ml-ad-job-action',
|
||||
type: CREATE_LENS_VIS_TO_ML_AD_JOB_ACTION,
|
||||
getIconType(context): string {
|
||||
|
@ -66,5 +68,5 @@ export function createLensVisToADJobAction(getStartServices: MlCoreSetup['getSta
|
|||
return false;
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue