;
+
+export interface EnhancementRegistryDefinition
+ extends PersistableStateDefinition
{
+ id: string;
+}
+
+export interface EnhancementRegistryItem
+ extends PersistableState
{
+ id: string;
+}
export type EmbeddableFactoryProvider = <
I extends EmbeddableInput = EmbeddableInput,
diff --git a/src/plugins/embeddable/server/index.ts b/src/plugins/embeddable/server/index.ts
new file mode 100644
index 0000000000000..1138478bff4b7
--- /dev/null
+++ b/src/plugins/embeddable/server/index.ts
@@ -0,0 +1,26 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { EmbeddableServerPlugin, EmbeddableSetup } from './plugin';
+
+export { EmbeddableSetup };
+
+export { EnhancementRegistryDefinition, EmbeddableRegistryDefinition } from './types';
+
+export const plugin = () => new EmbeddableServerPlugin();
diff --git a/src/plugins/embeddable/server/plugin.ts b/src/plugins/embeddable/server/plugin.ts
new file mode 100644
index 0000000000000..f79c4b7620110
--- /dev/null
+++ b/src/plugins/embeddable/server/plugin.ts
@@ -0,0 +1,186 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { CoreSetup, CoreStart, Plugin, SavedObjectReference } from 'kibana/server';
+import { identity } from 'lodash';
+import {
+ EmbeddableFactoryRegistry,
+ EnhancementsRegistry,
+ EnhancementRegistryDefinition,
+ EnhancementRegistryItem,
+ EmbeddableRegistryDefinition,
+} from './types';
+import {
+ extractBaseEmbeddableInput,
+ injectBaseEmbeddableInput,
+ telemetryBaseEmbeddableInput,
+} from '../common/lib/migrate_base_input';
+import { SerializableState } from '../../kibana_utils/common';
+import { EmbeddableInput } from '../common/types';
+
+export interface EmbeddableSetup {
+ registerEmbeddableFactory: (factory: EmbeddableRegistryDefinition) => void;
+ registerEnhancement: (enhancement: EnhancementRegistryDefinition) => void;
+}
+
+export class EmbeddableServerPlugin implements Plugin {
+ private readonly embeddableFactories: EmbeddableFactoryRegistry = new Map();
+ private readonly enhancements: EnhancementsRegistry = new Map();
+
+ public setup(core: CoreSetup) {
+ return {
+ registerEmbeddableFactory: this.registerEmbeddableFactory,
+ registerEnhancement: this.registerEnhancement,
+ };
+ }
+
+ public start(core: CoreStart) {
+ return {
+ telemetry: this.telemetry,
+ extract: this.extract,
+ inject: this.inject,
+ };
+ }
+
+ public stop() {}
+
+ private telemetry = (state: EmbeddableInput, telemetryData: Record = {}) => {
+ const enhancements: Record = state.enhancements || {};
+ const factory = this.getEmbeddableFactory(state.id);
+
+ let telemetry = telemetryBaseEmbeddableInput(state, telemetryData);
+ if (factory) {
+ telemetry = factory.telemetry(state, telemetry);
+ }
+ Object.keys(enhancements).map((key) => {
+ if (!enhancements[key]) return;
+ telemetry = this.getEnhancement(key).telemetry(enhancements[key], telemetry);
+ });
+
+ return telemetry;
+ };
+
+ private extract = (state: EmbeddableInput) => {
+ const enhancements = state.enhancements || {};
+ const factory = this.getEmbeddableFactory(state.id);
+
+ const baseResponse = extractBaseEmbeddableInput(state);
+ let updatedInput = baseResponse.state;
+ const refs = baseResponse.references;
+
+ if (factory) {
+ const factoryResponse = factory.extract(state);
+ updatedInput = factoryResponse.state;
+ refs.push(...factoryResponse.references);
+ }
+
+ updatedInput.enhancements = {};
+ Object.keys(enhancements).forEach((key) => {
+ if (!enhancements[key]) return;
+ const enhancementResult = this.getEnhancement(key).extract(
+ enhancements[key] as SerializableState
+ );
+ refs.push(...enhancementResult.references);
+ updatedInput.enhancements![key] = enhancementResult.state;
+ });
+
+ return {
+ state: updatedInput,
+ references: refs,
+ };
+ };
+
+ private inject = (state: EmbeddableInput, references: SavedObjectReference[]) => {
+ const enhancements = state.enhancements || {};
+ const factory = this.getEmbeddableFactory(state.id);
+
+ let updatedInput = injectBaseEmbeddableInput(state, references);
+
+ if (factory) {
+ updatedInput = factory.inject(updatedInput, references);
+ }
+
+ updatedInput.enhancements = {};
+ Object.keys(enhancements).forEach((key) => {
+ if (!enhancements[key]) return;
+ updatedInput.enhancements![key] = this.getEnhancement(key).inject(
+ enhancements[key] as SerializableState,
+ references
+ );
+ });
+
+ return updatedInput;
+ };
+
+ private registerEnhancement = (enhancement: EnhancementRegistryDefinition) => {
+ if (this.enhancements.has(enhancement.id)) {
+ throw new Error(`enhancement with id ${enhancement.id} already exists in the registry`);
+ }
+ this.enhancements.set(enhancement.id, {
+ id: enhancement.id,
+ telemetry: enhancement.telemetry || (() => ({})),
+ inject: enhancement.inject || identity,
+ extract:
+ enhancement.extract ||
+ ((state: SerializableState) => {
+ return { state, references: [] };
+ }),
+ });
+ };
+
+ private getEnhancement = (id: string): EnhancementRegistryItem => {
+ return (
+ this.enhancements.get(id) || {
+ id: 'unknown',
+ telemetry: () => ({}),
+ inject: identity,
+ extract: (state: SerializableState) => {
+ return { state, references: [] };
+ },
+ }
+ );
+ };
+
+ private registerEmbeddableFactory = (factory: EmbeddableRegistryDefinition) => {
+ if (this.embeddableFactories.has(factory.id)) {
+ throw new Error(
+ `Embeddable factory [embeddableFactoryId = ${factory.id}] already registered in Embeddables API.`
+ );
+ }
+ this.embeddableFactories.set(factory.id, {
+ id: factory.id,
+ telemetry: factory.telemetry || (() => ({})),
+ inject: factory.inject || identity,
+ extract: factory.extract || ((state: EmbeddableInput) => ({ state, references: [] })),
+ });
+ };
+
+ private getEmbeddableFactory = (embeddableFactoryId: string) => {
+ return (
+ this.embeddableFactories.get(embeddableFactoryId) || {
+ id: 'unknown',
+ telemetry: () => ({}),
+ inject: (state: EmbeddableInput) => state,
+ extract: (state: EmbeddableInput) => {
+ return { state, references: [] };
+ },
+ }
+ );
+ };
+}
diff --git a/src/plugins/embeddable/server/types.ts b/src/plugins/embeddable/server/types.ts
new file mode 100644
index 0000000000000..64f9325dad3cb
--- /dev/null
+++ b/src/plugins/embeddable/server/types.ts
@@ -0,0 +1,48 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import {
+ PersistableState,
+ PersistableStateDefinition,
+ SerializableState,
+} from '../../kibana_utils/common';
+import { EmbeddableInput } from '../common/types';
+
+export type EmbeddableFactoryRegistry = Map;
+export type EnhancementsRegistry = Map;
+
+export interface EnhancementRegistryDefinition
+ extends PersistableStateDefinition
{
+ id: string;
+}
+
+export interface EnhancementRegistryItem
+ extends PersistableState
{
+ id: string;
+}
+
+export interface EmbeddableRegistryDefinition
+ extends PersistableStateDefinition
{
+ id: string;
+}
+
+export interface EmbeddableRegistryItem
+ extends PersistableState
{
+ id: string;
+}
diff --git a/src/plugins/kibana_utils/common/index.ts b/src/plugins/kibana_utils/common/index.ts
index 1ec5737c5a38b..e09290c811c7b 100644
--- a/src/plugins/kibana_utils/common/index.ts
+++ b/src/plugins/kibana_utils/common/index.ts
@@ -29,3 +29,4 @@ export { distinctUntilChangedWithInitialValue } from './distinct_until_changed_w
export { url } from './url';
export { now } from './now';
export { calculateObjectHash } from './calculate_object_hash';
+export * from './persistable_state';
diff --git a/src/plugins/kibana_utils/common/persistable_state/index.ts b/src/plugins/kibana_utils/common/persistable_state/index.ts
new file mode 100644
index 0000000000000..ae5e3d514554c
--- /dev/null
+++ b/src/plugins/kibana_utils/common/persistable_state/index.ts
@@ -0,0 +1,54 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { SavedObjectReference } from '../../../../core/types';
+
+export type SerializableValue = string | number | boolean | null | undefined | SerializableState;
+export type Serializable = SerializableValue | SerializableValue[];
+
+// eslint-disable-next-line
+export type SerializableState = {
+ [key: string]: Serializable;
+};
+
+export interface PersistableState
{
+ /**
+ * function to extract telemetry information
+ * @param state
+ * @param collector
+ */
+ telemetry: (state: P, collector: Record) => Record;
+ /**
+ * inject function receives state and a list of references and should return state with references injected
+ * default is identity function
+ * @param state
+ * @param references
+ */
+ inject: (state: P, references: SavedObjectReference[]) => P;
+ /**
+ * extract function receives state and should return state with references extracted and array of references
+ * default returns same state with empty reference array
+ * @param state
+ */
+ extract: (state: P) => { state: P; references: SavedObjectReference[] };
+}
+
+export type PersistableStateDefinition = Partial<
+ PersistableState
+>;
diff --git a/src/plugins/kibana_utils/public/ui/configurable.ts b/src/plugins/kibana_utils/public/ui/configurable.ts
index 3fa5cdc8b5e47..89bce5ae423ee 100644
--- a/src/plugins/kibana_utils/public/ui/configurable.ts
+++ b/src/plugins/kibana_utils/public/ui/configurable.ts
@@ -18,11 +18,15 @@
*/
import { UiComponent } from '../../common/ui/ui_component';
+import { SerializableState } from '../../common';
/**
* Represents something that can be configured by user using UI.
*/
-export interface Configurable {
+export interface Configurable<
+ Config extends SerializableState = SerializableState,
+ Context = object
+> {
/**
* Create default config for this item, used when item is created for the first time.
*/
@@ -42,7 +46,10 @@ export interface Configurable
/**
* Props provided to `CollectConfig` component on every re-render.
*/
-export interface CollectConfigProps {
+export interface CollectConfigProps<
+ Config extends SerializableState = SerializableState,
+ Context = object
+> {
/**
* Current (latest) config of the item.
*/
diff --git a/x-pack/examples/ui_actions_enhanced_examples/.eslintrc.json b/x-pack/examples/ui_actions_enhanced_examples/.eslintrc.json
new file mode 100644
index 0000000000000..2aab6c2d9093b
--- /dev/null
+++ b/x-pack/examples/ui_actions_enhanced_examples/.eslintrc.json
@@ -0,0 +1,5 @@
+{
+ "rules": {
+ "@typescript-eslint/consistent-type-definitions": 0
+ }
+}
diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_hello_world_drilldown/index.tsx b/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_hello_world_drilldown/index.tsx
index fd782f5468c85..cac5f0b29dc6e 100644
--- a/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_hello_world_drilldown/index.tsx
+++ b/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_hello_world_drilldown/index.tsx
@@ -17,9 +17,9 @@ import {
export type ActionContext = ChartActionContext;
-export interface Config {
+export type Config = {
name: string;
-}
+};
const SAMPLE_DASHBOARD_HELLO_WORLD_DRILLDOWN = 'SAMPLE_DASHBOARD_HELLO_WORLD_DRILLDOWN';
diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_hello_world_only_range_select_drilldown/index.tsx b/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_hello_world_only_range_select_drilldown/index.tsx
index 7394690a61eae..fa2f0825f9335 100644
--- a/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_hello_world_only_range_select_drilldown/index.tsx
+++ b/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_hello_world_only_range_select_drilldown/index.tsx
@@ -13,9 +13,9 @@ import { CollectConfigProps } from '../../../../../src/plugins/kibana_utils/publ
import { SELECT_RANGE_TRIGGER } from '../../../../../src/plugins/ui_actions/public';
import { BaseActionFactoryContext } from '../../../../plugins/ui_actions_enhanced/public/dynamic_actions';
-export interface Config {
+export type Config = {
name: string;
-}
+};
const SAMPLE_DASHBOARD_HELLO_WORLD_DRILLDOWN_ONLY_RANGE_SELECT =
'SAMPLE_DASHBOARD_HELLO_WORLD_DRILLDOWN_ONLY_RANGE_SELECT';
diff --git a/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_to_discover_drilldown/types.ts b/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_to_discover_drilldown/types.ts
index a10e8ad707e97..692de571e8a00 100644
--- a/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_to_discover_drilldown/types.ts
+++ b/x-pack/examples/ui_actions_enhanced_examples/public/dashboard_to_discover_drilldown/types.ts
@@ -9,7 +9,7 @@ import { ApplyGlobalFilterActionContext } from '../../../../../src/plugins/data/
export type ActionContext = ApplyGlobalFilterActionContext;
-export interface Config {
+export type Config = {
/**
* Whether to use a user selected index pattern, stored in `indexPatternId` field.
*/
@@ -30,6 +30,6 @@ export interface Config {
* Whether to carry over source dashboard time range.
*/
carryTimeRange: boolean;
-}
+};
export type CollectConfigProps = CollectConfigPropsBase;
diff --git a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/types.ts b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/types.ts
index c21109f8a596a..330a501a78d39 100644
--- a/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/types.ts
+++ b/x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/types.ts
@@ -7,10 +7,11 @@
import { UiActionsEnhancedBaseActionFactoryContext } from '../../../../../ui_actions_enhanced/public';
import { APPLY_FILTER_TRIGGER } from '../../../../../../../src/plugins/ui_actions/public';
-export interface Config {
+// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
+export type Config = {
dashboardId?: string;
useCurrentFilters: boolean;
useCurrentDateRange: boolean;
-}
+};
export type FactoryContext = UiActionsEnhancedBaseActionFactoryContext;
diff --git a/x-pack/plugins/embeddable_enhanced/public/embeddables/embeddable_action_storage.ts b/x-pack/plugins/embeddable_enhanced/public/embeddables/embeddable_action_storage.ts
index 8881b2063c8db..e0960b83b23f9 100644
--- a/x-pack/plugins/embeddable_enhanced/public/embeddables/embeddable_action_storage.ts
+++ b/x-pack/plugins/embeddable_enhanced/public/embeddables/embeddable_action_storage.ts
@@ -5,6 +5,7 @@
*/
import {
+ DynamicActionsState,
UiActionsEnhancedAbstractActionStorage as AbstractActionStorage,
UiActionsEnhancedSerializedEvent as SerializedEvent,
} from '../../../ui_actions_enhanced/public';
@@ -13,12 +14,12 @@ import {
EmbeddableOutput,
IEmbeddable,
} from '../../../../../src/plugins/embeddable/public';
+import { SerializableState } from '../../../../../src/plugins/kibana_utils/common';
export interface EmbeddableWithDynamicActionsInput extends EmbeddableInput {
enhancements?: {
- dynamicActions?: {
- events: SerializedEvent[];
- };
+ dynamicActions: DynamicActionsState;
+ [key: string]: SerializableState;
};
}
diff --git a/x-pack/plugins/ui_actions_enhanced/.eslintrc.json b/x-pack/plugins/ui_actions_enhanced/.eslintrc.json
new file mode 100644
index 0000000000000..2aab6c2d9093b
--- /dev/null
+++ b/x-pack/plugins/ui_actions_enhanced/.eslintrc.json
@@ -0,0 +1,5 @@
+{
+ "rules": {
+ "@typescript-eslint/consistent-type-definitions": 0
+ }
+}
diff --git a/x-pack/plugins/ui_actions_enhanced/common/types.ts b/x-pack/plugins/ui_actions_enhanced/common/types.ts
new file mode 100644
index 0000000000000..1150f4f823e8e
--- /dev/null
+++ b/x-pack/plugins/ui_actions_enhanced/common/types.ts
@@ -0,0 +1,28 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { SerializableState } from '../../../../src/plugins/kibana_utils/common';
+
+export type BaseActionConfig = SerializableState;
+
+export type SerializedAction = {
+ readonly factoryId: string;
+ readonly name: string;
+ readonly config: Config;
+};
+
+/**
+ * Serialized representation of a triggers-action pair, used to persist in storage.
+ */
+export type SerializedEvent = {
+ eventId: string;
+ triggers: string[];
+ action: SerializedAction;
+};
+
+export type DynamicActionsState = {
+ events: SerializedEvent[];
+};
diff --git a/x-pack/plugins/ui_actions_enhanced/kibana.json b/x-pack/plugins/ui_actions_enhanced/kibana.json
index 108c66505f25c..5435019f216f2 100644
--- a/x-pack/plugins/ui_actions_enhanced/kibana.json
+++ b/x-pack/plugins/ui_actions_enhanced/kibana.json
@@ -7,7 +7,7 @@
"uiActions",
"licensing"
],
- "server": false,
+ "server": true,
"ui": true,
"requiredBundles": [
"kibanaUtils",
diff --git a/x-pack/plugins/ui_actions_enhanced/public/components/action_wizard/action_wizard.tsx b/x-pack/plugins/ui_actions_enhanced/public/components/action_wizard/action_wizard.tsx
index 16d0250c5721e..2aa80b46129a2 100644
--- a/x-pack/plugins/ui_actions_enhanced/public/components/action_wizard/action_wizard.tsx
+++ b/x-pack/plugins/ui_actions_enhanced/public/components/action_wizard/action_wizard.tsx
@@ -28,7 +28,7 @@ import {
txtTriggerPickerHelpTooltip,
} from './i18n';
import './action_wizard.scss';
-import { ActionFactory, BaseActionFactoryContext } from '../../dynamic_actions';
+import { ActionFactory, BaseActionConfig, BaseActionFactoryContext } from '../../dynamic_actions';
import { Trigger, TriggerId } from '../../../../../../src/plugins/ui_actions/public';
export interface ActionWizardProps<
@@ -54,12 +54,12 @@ export interface ActionWizardProps<
/**
* current config for currently selected action factory
*/
- config?: object;
+ config?: BaseActionConfig;
/**
* config changed
*/
- onConfigChange: (config: object) => void;
+ onConfigChange: (config: BaseActionConfig) => void;
/**
* Context will be passed into ActionFactory's methods
@@ -216,9 +216,9 @@ interface SelectedActionFactoryProps<
ActionFactoryContext extends BaseActionFactoryContext = BaseActionFactoryContext
> {
actionFactory: ActionFactory;
- config: object;
+ config: BaseActionConfig;
context: ActionFactoryContext;
- onConfigChange: (config: object) => void;
+ onConfigChange: (config: BaseActionConfig) => void;
showDeselect: boolean;
onDeselect: () => void;
allTriggers: TriggerId[];
diff --git a/x-pack/plugins/ui_actions_enhanced/public/components/action_wizard/test_data.tsx b/x-pack/plugins/ui_actions_enhanced/public/components/action_wizard/test_data.tsx
index 71286e9a59c06..af930bfba6b8b 100644
--- a/x-pack/plugins/ui_actions_enhanced/public/components/action_wizard/test_data.tsx
+++ b/x-pack/plugins/ui_actions_enhanced/public/components/action_wizard/test_data.tsx
@@ -8,7 +8,7 @@ import React, { useState } from 'react';
import { EuiFieldText, EuiFormRow, EuiSelect, EuiSwitch } from '@elastic/eui';
import { reactToUiComponent } from '../../../../../../src/plugins/kibana_react/public';
import { ActionWizard } from './action_wizard';
-import { ActionFactory, ActionFactoryDefinition } from '../../dynamic_actions';
+import { ActionFactory, ActionFactoryDefinition, BaseActionConfig } from '../../dynamic_actions';
import { CollectConfigProps } from '../../../../../../src/plugins/kibana_utils/public';
import { licensingMock } from '../../../../licensing/public/mocks';
import {
@@ -19,18 +19,16 @@ import {
VALUE_CLICK_TRIGGER,
} from '../../../../../../src/plugins/ui_actions/public';
-type ActionBaseConfig = object;
-
export const dashboards = [
{ id: 'dashboard1', title: 'Dashboard 1' },
{ id: 'dashboard2', title: 'Dashboard 2' },
];
-interface DashboardDrilldownConfig {
+type DashboardDrilldownConfig = {
dashboardId?: string;
useCurrentFilters: boolean;
useCurrentDateRange: boolean;
-}
+};
function DashboardDrilldownCollectConfig(props: CollectConfigProps) {
const config = props.config ?? {
@@ -121,10 +119,11 @@ export const dashboardFactory = new ActionFactory(dashboardDrilldownActionFactor
getFeatureUsageStart: () => licensingMock.createStart().featureUsage,
});
-interface UrlDrilldownConfig {
+type UrlDrilldownConfig = {
url: string;
openInNewTab: boolean;
-}
+};
+
function UrlDrilldownCollectConfig(props: CollectConfigProps) {
const config = props.config ?? {
url: '',
@@ -182,6 +181,10 @@ export const urlFactory = new ActionFactory(urlDrilldownActionFactory, {
getFeatureUsageStart: () => licensingMock.createStart().featureUsage,
});
+export const mockActionFactories: ActionFactory[] = ([dashboardFactory, urlFactory] as Array<
+ ActionFactory
+>) as ActionFactory[];
+
export const mockSupportedTriggers: TriggerId[] = [
VALUE_CLICK_TRIGGER,
SELECT_RANGE_TRIGGER,
@@ -210,7 +213,7 @@ export const mockGetTriggerInfo = (triggerId: TriggerId): Trigger => {
export function Demo({ actionFactories }: { actionFactories: Array> }) {
const [state, setState] = useState<{
currentActionFactory?: ActionFactory;
- config?: ActionBaseConfig;
+ config?: BaseActionConfig;
selectedTriggers?: TriggerId[];
}>({});
diff --git a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.story.tsx b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.story.tsx
index f7284539ab2fe..daa56354289cf 100644
--- a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.story.tsx
+++ b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.story.tsx
@@ -8,14 +8,13 @@ import * as React from 'react';
import { EuiFlyout } from '@elastic/eui';
import { storiesOf } from '@storybook/react';
import { createFlyoutManageDrilldowns } from './connected_flyout_manage_drilldowns';
-import { dashboardFactory, urlFactory } from '../../../components/action_wizard/test_data';
+import { mockActionFactories } from '../../../components/action_wizard/test_data';
import { Storage } from '../../../../../../../src/plugins/kibana_utils/public';
import { StubBrowserStorage } from '../../../../../../../src/test_utils/public/stub_browser_storage';
import { mockDynamicActionManager } from './test_data';
-import { ActionFactory } from '../../../dynamic_actions';
const FlyoutManageDrilldowns = createFlyoutManageDrilldowns({
- actionFactories: [dashboardFactory as ActionFactory, urlFactory as ActionFactory],
+ actionFactories: mockActionFactories,
storage: new Storage(new StubBrowserStorage()),
toastService: {
addError: (...args: any[]) => {
diff --git a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.test.tsx b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.test.tsx
index 2412cdd51748c..c4b07fa05c3c1 100644
--- a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.test.tsx
+++ b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.test.tsx
@@ -8,10 +8,9 @@ import React from 'react';
import { cleanup, fireEvent, render, wait } from '@testing-library/react/pure';
import { createFlyoutManageDrilldowns } from './connected_flyout_manage_drilldowns';
import {
- dashboardFactory,
mockGetTriggerInfo,
mockSupportedTriggers,
- urlFactory,
+ mockActionFactories,
} from '../../../components/action_wizard/test_data';
import { StubBrowserStorage } from '../../../../../../../src/test_utils/public/stub_browser_storage';
import { Storage } from '../../../../../../../src/plugins/kibana_utils/public';
@@ -21,12 +20,11 @@ import { WELCOME_MESSAGE_TEST_SUBJ } from '../drilldown_hello_bar';
import { coreMock } from '../../../../../../../src/core/public/mocks';
import { NotificationsStart } from 'kibana/public';
import { toastDrilldownsCRUDError } from './i18n';
-import { ActionFactory } from '../../../dynamic_actions';
const storage = new Storage(new StubBrowserStorage());
const toasts = coreMock.createStart().notifications.toasts;
const FlyoutManageDrilldowns = createFlyoutManageDrilldowns({
- actionFactories: [dashboardFactory as ActionFactory, urlFactory as ActionFactory],
+ actionFactories: mockActionFactories,
storage: new Storage(new StubBrowserStorage()),
toastService: toasts,
getTrigger: mockGetTriggerInfo,
diff --git a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.tsx b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.tsx
index 6f9eccde8bdb0..28a0990cf7526 100644
--- a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.tsx
+++ b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/connected_flyout_manage_drilldowns.tsx
@@ -25,6 +25,7 @@ import {
} from './i18n';
import {
ActionFactory,
+ BaseActionConfig,
BaseActionFactoryContext,
DynamicActionManager,
SerializedAction,
@@ -127,7 +128,7 @@ export function createFlyoutManageDrilldowns({
return {
actionFactory: allActionFactoriesById[drilldownToEdit.action.factoryId],
- actionConfig: drilldownToEdit.action.config as object,
+ actionConfig: drilldownToEdit.action.config as BaseActionConfig,
name: drilldownToEdit.action.name,
selectedTriggers: (drilldownToEdit.triggers ?? []) as TriggerId[],
};
diff --git a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/test_data.ts b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/test_data.ts
index 58c36e36481b8..78eec05eb2d0b 100644
--- a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/test_data.ts
+++ b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/connected_flyout_manage_drilldowns/test_data.ts
@@ -60,7 +60,7 @@ class MockDynamicActionManager implements PublicMethodsOf
async updateEvent(
eventId: string,
- action: UiActionsEnhancedSerializedAction,
+ action: UiActionsEnhancedSerializedAction,
triggers: Array
) {
const state = this.state.get();
diff --git a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/flyout_drilldown_wizard/flyout_drilldown_wizard.story.tsx b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/flyout_drilldown_wizard/flyout_drilldown_wizard.story.tsx
index 8f73c2b3b3cc9..2f5f7760d40bd 100644
--- a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/flyout_drilldown_wizard/flyout_drilldown_wizard.story.tsx
+++ b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/flyout_drilldown_wizard/flyout_drilldown_wizard.story.tsx
@@ -8,8 +8,7 @@ import * as React from 'react';
import { EuiFlyout } from '@elastic/eui';
import { storiesOf } from '@storybook/react';
import { FlyoutDrilldownWizard } from './index';
-import { dashboardFactory, urlFactory } from '../../../components/action_wizard/test_data';
-import { ActionFactory } from '../../../dynamic_actions';
+import { mockActionFactories } from '../../../components/action_wizard/test_data';
import { Trigger, TriggerId } from '../../../../../../../src/plugins/ui_actions/public';
const otherProps = {
@@ -24,23 +23,12 @@ const otherProps = {
storiesOf('components/FlyoutDrilldownWizard', module)
.add('default', () => {
- return (
-
- );
+ return ;
})
.add('open in flyout - create', () => {
return (
{}}>
-
+
);
})
@@ -48,13 +36,10 @@ storiesOf('components/FlyoutDrilldownWizard', module)
return (
{}}>
{}}>
{
+export interface DrilldownWizardConfig {
name: string;
actionFactory?: ActionFactory;
actionConfig?: ActionConfig;
@@ -28,7 +32,7 @@ export interface DrilldownWizardConfig {
}
export interface FlyoutDrilldownWizardProps<
- CurrentActionConfig extends object = object,
+ CurrentActionConfig extends BaseActionConfig = BaseActionConfig,
ActionFactoryContext extends BaseActionFactoryContext = BaseActionFactoryContext
> {
drilldownActionFactories: ActionFactory[];
@@ -71,7 +75,7 @@ function useWizardConfigState(
DrilldownWizardConfig,
{
setName: (name: string) => void;
- setActionConfig: (actionConfig: object) => void;
+ setActionConfig: (actionConfig: BaseActionConfig) => void;
setActionFactory: (actionFactory?: ActionFactory) => void;
setSelectedTriggers: (triggers?: TriggerId[]) => void;
}
@@ -100,7 +104,7 @@ function useWizardConfigState(
name,
});
},
- setActionConfig: (actionConfig: object) => {
+ setActionConfig: (actionConfig: BaseActionConfig) => {
setWizardConfig({
...wizardConfig,
actionConfig,
@@ -108,12 +112,12 @@ function useWizardConfigState(
},
setActionFactory: (actionFactory?: ActionFactory) => {
if (actionFactory) {
+ const actionConfig = (actionConfigCache[actionFactory.id] ??
+ actionFactory.createConfig(actionFactoryContext)) as BaseActionConfig;
setWizardConfig({
...wizardConfig,
actionFactory,
- actionConfig:
- actionConfigCache[actionFactory.id] ??
- actionFactory.createConfig(actionFactoryContext),
+ actionConfig,
selectedTriggers: [],
});
} else {
@@ -141,7 +145,9 @@ function useWizardConfigState(
];
}
-export function FlyoutDrilldownWizard({
+export function FlyoutDrilldownWizard<
+ CurrentActionConfig extends BaseActionConfig = BaseActionConfig
+>({
onClose,
onBack,
onSubmit = () => {},
diff --git a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/form_drilldown_wizard/form_drilldown_wizard.tsx b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/form_drilldown_wizard/form_drilldown_wizard.tsx
index d7f94a52088b7..45655c2634fe7 100644
--- a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/form_drilldown_wizard/form_drilldown_wizard.tsx
+++ b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/components/form_drilldown_wizard/form_drilldown_wizard.tsx
@@ -8,7 +8,11 @@ import React from 'react';
import { EuiFieldText, EuiForm, EuiFormRow, EuiLink, EuiSpacer, EuiText } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { txtDrilldownAction, txtNameOfDrilldown, txtUntitledDrilldown } from './i18n';
-import { ActionFactory, BaseActionFactoryContext } from '../../../dynamic_actions';
+import {
+ ActionFactory,
+ BaseActionConfig,
+ BaseActionFactoryContext,
+} from '../../../dynamic_actions';
import { ActionWizard } from '../../../components/action_wizard';
import { Trigger, TriggerId } from '../../../../../../../src/plugins/ui_actions/public';
@@ -26,8 +30,8 @@ export interface FormDrilldownWizardProps<
onActionFactoryChange?: (actionFactory?: ActionFactory) => void;
actionFactoryContext: ActionFactoryContext;
- actionConfig?: object;
- onActionConfigChange?: (config: object) => void;
+ actionConfig?: BaseActionConfig;
+ onActionConfigChange?: (config: BaseActionConfig) => void;
actionFactories?: ActionFactory[];
diff --git a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/drilldown_definition.ts b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/drilldown_definition.ts
index 8faccc088a327..85307cd463e63 100644
--- a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/drilldown_definition.ts
+++ b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/drilldown_definition.ts
@@ -4,10 +4,16 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { ActionFactoryDefinition, BaseActionFactoryContext } from '../dynamic_actions';
+import {
+ ActionFactoryDefinition,
+ BaseActionConfig,
+ BaseActionFactoryContext,
+ SerializedEvent,
+} from '../dynamic_actions';
import { LicenseType } from '../../../licensing/public';
import { TriggerContextMapping, TriggerId } from '../../../../../src/plugins/ui_actions/public';
import { ActionExecutionContext } from '../../../../../src/plugins/ui_actions/public';
+import { PersistableStateDefinition } from '../../../../../src/plugins/kibana_utils/common';
/**
* This is a convenience interface to register a drilldown. Drilldown has
@@ -24,13 +30,13 @@ import { ActionExecutionContext } from '../../../../../src/plugins/ui_actions/pu
*/
export interface DrilldownDefinition<
- Config extends object = object,
+ Config extends BaseActionConfig = BaseActionConfig,
SupportedTriggers extends TriggerId = TriggerId,
FactoryContext extends BaseActionFactoryContext = {
triggers: SupportedTriggers[];
},
ExecutionContext extends TriggerContextMapping[SupportedTriggers] = TriggerContextMapping[SupportedTriggers]
-> {
+> extends PersistableStateDefinition {
/**
* Globally unique identifier for this drilldown.
*/
diff --git a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/types.ts b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/types.ts
index 31c7481c9d63e..fb7d96aaf8325 100644
--- a/x-pack/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/types.ts
+++ b/x-pack/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/types.ts
@@ -4,10 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export interface UrlDrilldownConfig {
+export type UrlDrilldownConfig = {
url: { format?: 'handlebars_v1'; template: string };
openInNewTab: boolean;
-}
+};
/**
* URL drilldown has 3 sources for variables: global, context and event variables
diff --git a/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/action_factory.ts b/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/action_factory.ts
index 35a82adf9896d..5df07ca5a508b 100644
--- a/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/action_factory.ts
+++ b/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/action_factory.ts
@@ -12,9 +12,16 @@ import {
} from '../../../../../src/plugins/ui_actions/public';
import { ActionFactoryDefinition } from './action_factory_definition';
import { Configurable } from '../../../../../src/plugins/kibana_utils/public';
-import { BaseActionFactoryContext, SerializedAction } from './types';
+import {
+ BaseActionConfig,
+ BaseActionFactoryContext,
+ SerializedAction,
+ SerializedEvent,
+} from './types';
import { ILicense, LicensingPluginStart } from '../../../licensing/public';
import { UiActionsActionDefinition as ActionDefinition } from '../../../../../src/plugins/ui_actions/public';
+import { SavedObjectReference } from '../../../../../src/core/types';
+import { PersistableState } from '../../../../../src/plugins/kibana_utils/common';
export interface ActionFactoryDeps {
readonly getLicense: () => ILicense;
@@ -22,13 +29,16 @@ export interface ActionFactoryDeps {
}
export class ActionFactory<
- Config extends object = object,
+ Config extends BaseActionConfig = BaseActionConfig,
SupportedTriggers extends TriggerId = TriggerId,
FactoryContext extends BaseActionFactoryContext = {
triggers: SupportedTriggers[];
},
ActionContext extends TriggerContextMapping[SupportedTriggers] = TriggerContextMapping[SupportedTriggers]
-> implements Omit, 'getHref'>, Configurable {
+> implements
+ Omit, 'getHref'>,
+ Configurable,
+ PersistableState {
constructor(
protected readonly def: ActionFactoryDefinition<
Config,
@@ -120,4 +130,16 @@ export class ActionFactory<
);
});
}
+
+ public telemetry(state: SerializedEvent, telemetryData: Record) {
+ return this.def.telemetry ? this.def.telemetry(state, telemetryData) : {};
+ }
+
+ public extract(state: SerializedEvent) {
+ return this.def.extract ? this.def.extract(state) : { state, references: [] };
+ }
+
+ public inject(state: SerializedEvent, references: SavedObjectReference[]) {
+ return this.def.inject ? this.def.inject(state, references) : state;
+ }
}
diff --git a/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/action_factory_definition.ts b/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/action_factory_definition.ts
index 91b8c8ec1e5ef..b5041c99507e6 100644
--- a/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/action_factory_definition.ts
+++ b/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/action_factory_definition.ts
@@ -5,7 +5,12 @@
*/
import { Configurable } from '../../../../../src/plugins/kibana_utils/public';
-import { BaseActionFactoryContext, SerializedAction } from './types';
+import {
+ BaseActionConfig,
+ BaseActionFactoryContext,
+ SerializedAction,
+ SerializedEvent,
+} from './types';
import { LicenseType } from '../../../licensing/public';
import {
TriggerContextMapping,
@@ -13,19 +18,21 @@ import {
UiActionsActionDefinition as ActionDefinition,
UiActionsPresentable as Presentable,
} from '../../../../../src/plugins/ui_actions/public';
+import { PersistableStateDefinition } from '../../../../../src/plugins/kibana_utils/common';
/**
* This is a convenience interface for registering new action factories.
*/
export interface ActionFactoryDefinition<
- Config extends object = object,
+ Config extends BaseActionConfig = BaseActionConfig,
SupportedTriggers extends TriggerId = TriggerId,
FactoryContext extends BaseActionFactoryContext = {
triggers: SupportedTriggers[];
},
ActionContext extends TriggerContextMapping[SupportedTriggers] = TriggerContextMapping[SupportedTriggers]
> extends Partial, 'getHref'>>,
- Configurable {
+ Configurable,
+ PersistableStateDefinition {
/**
* Unique ID of the action factory. This ID is used to identify this action
* factory in the registry as well as to construct actions of this type and
diff --git a/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/dynamic_action_enhancement.ts b/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/dynamic_action_enhancement.ts
new file mode 100644
index 0000000000000..7cac49624bfdd
--- /dev/null
+++ b/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/dynamic_action_enhancement.ts
@@ -0,0 +1,28 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { EnhancementRegistryDefinition } from '../../../../../src/plugins/embeddable/public';
+import { SavedObjectReference } from '../../../../../src/core/types';
+import { SerializableState } from '../../../../../src/plugins/kibana_utils/common';
+import { DynamicActionsState } from '../../../ui_actions_enhanced/public';
+import { UiActionsServiceEnhancements } from '../services';
+
+export const dynamicActionEnhancement = (
+ uiActionsEnhanced: UiActionsServiceEnhancements
+): EnhancementRegistryDefinition => {
+ return {
+ id: 'dynamicActions',
+ telemetry: (state: SerializableState, telemetryData: Record) => {
+ return uiActionsEnhanced.telemetry(state as DynamicActionsState, telemetryData);
+ },
+ extract: (state: SerializableState) => {
+ return uiActionsEnhanced.extract(state as DynamicActionsState);
+ },
+ inject: (state: SerializableState, references: SavedObjectReference[]) => {
+ return uiActionsEnhanced.inject(state as DynamicActionsState, references);
+ },
+ } as EnhancementRegistryDefinition;
+};
diff --git a/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/dynamic_action_manager.test.ts b/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/dynamic_action_manager.test.ts
index 39d9dfeca2fd6..83232bbce1ba7 100644
--- a/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/dynamic_action_manager.test.ts
+++ b/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/dynamic_action_manager.test.ts
@@ -250,7 +250,7 @@ describe('DynamicActionManager', () => {
uiActions.registerActionFactory(actionFactoryDefinition1);
await manager.start();
- const action: SerializedAction = {
+ const action: SerializedAction = {
factoryId: actionFactoryDefinition1.id,
name: 'foo',
config: {},
@@ -277,7 +277,7 @@ describe('DynamicActionManager', () => {
test('adds event to UI state', async () => {
const { manager, uiActions } = setup([]);
- const action: SerializedAction = {
+ const action: SerializedAction = {
factoryId: actionFactoryDefinition1.id,
name: 'foo',
config: {},
@@ -296,7 +296,7 @@ describe('DynamicActionManager', () => {
test('optimistically adds event to UI state', async () => {
const { manager, uiActions } = setup([]);
- const action: SerializedAction = {
+ const action: SerializedAction = {
factoryId: actionFactoryDefinition1.id,
name: 'foo',
config: {},
@@ -319,7 +319,7 @@ describe('DynamicActionManager', () => {
test('instantiates event in actions service', async () => {
const { manager, uiActions, actions } = setup([]);
- const action: SerializedAction = {
+ const action: SerializedAction = {
factoryId: actionFactoryDefinition1.id,
name: 'foo',
config: {},
@@ -348,7 +348,7 @@ describe('DynamicActionManager', () => {
uiActions.registerActionFactory(actionFactoryDefinition1);
await manager.start();
- const action: SerializedAction = {
+ const action: SerializedAction = {
factoryId: actionFactoryDefinition1.id,
name: 'foo',
config: {},
@@ -361,7 +361,7 @@ describe('DynamicActionManager', () => {
test('does not add even to UI state', async () => {
const { manager, storage, uiActions } = setup([]);
- const action: SerializedAction = {
+ const action: SerializedAction = {
factoryId: actionFactoryDefinition1.id,
name: 'foo',
config: {},
@@ -380,7 +380,7 @@ describe('DynamicActionManager', () => {
test('optimistically adds event to UI state and then removes it', async () => {
const { manager, storage, uiActions } = setup([]);
- const action: SerializedAction = {
+ const action: SerializedAction = {
factoryId: actionFactoryDefinition1.id,
name: 'foo',
config: {},
@@ -406,7 +406,7 @@ describe('DynamicActionManager', () => {
test('does not instantiate event in actions service', async () => {
const { manager, storage, uiActions, actions } = setup([]);
- const action: SerializedAction = {
+ const action: SerializedAction = {
factoryId: actionFactoryDefinition1.id,
name: 'foo',
config: {},
@@ -432,7 +432,7 @@ describe('DynamicActionManager', () => {
uiActions.registerActionFactory(actionFactoryDefinition1);
await manager.start();
- const action: SerializedAction = {
+ const action: SerializedAction = {
factoryId: actionFactoryDefinition1.id,
name: 'foo',
config: {},
@@ -457,7 +457,7 @@ describe('DynamicActionManager', () => {
expect(registeredAction1.getDisplayName()).toBe('Action 3');
- const action: SerializedAction = {
+ const action: SerializedAction = {
factoryId: actionFactoryDefinition2.id,
name: 'foo',
config: {},
@@ -479,7 +479,7 @@ describe('DynamicActionManager', () => {
uiActions.registerActionFactory(actionFactoryDefinition2);
await manager.start();
- const action: SerializedAction = {
+ const action: SerializedAction = {
factoryId: actionFactoryDefinition2.id,
name: 'foo',
config: {},
@@ -505,7 +505,7 @@ describe('DynamicActionManager', () => {
uiActions.registerActionFactory(actionFactoryDefinition2);
await manager.start();
- const action: SerializedAction = {
+ const action: SerializedAction = {
factoryId: actionFactoryDefinition2.id,
name: 'foo',
config: {},
@@ -524,7 +524,7 @@ describe('DynamicActionManager', () => {
uiActions.registerActionFactory(actionFactoryDefinition2);
await manager.start();
- const action: SerializedAction = {
+ const action: SerializedAction = {
factoryId: actionFactoryDefinition2.id,
name: 'foo',
config: {},
@@ -552,7 +552,7 @@ describe('DynamicActionManager', () => {
uiActions.registerActionFactory(actionFactoryDefinition2);
await manager.start();
- const action: SerializedAction = {
+ const action: SerializedAction = {
factoryId: actionFactoryDefinition2.id,
name: 'foo',
config: {},
@@ -580,7 +580,7 @@ describe('DynamicActionManager', () => {
expect(registeredAction1.getDisplayName()).toBe('Action 3');
- const action: SerializedAction = {
+ const action: SerializedAction = {
factoryId: actionFactoryDefinition2.id,
name: 'foo',
config: {},
@@ -604,7 +604,7 @@ describe('DynamicActionManager', () => {
uiActions.registerActionFactory(actionFactoryDefinition2);
await manager.start();
- const action: SerializedAction = {
+ const action: SerializedAction = {
factoryId: actionFactoryDefinition2.id,
name: 'foo',
config: {},
diff --git a/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/dynamic_action_manager.ts b/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/dynamic_action_manager.ts
index 6ca388281ad76..471b929fdbc06 100644
--- a/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/dynamic_action_manager.ts
+++ b/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/dynamic_action_manager.ts
@@ -74,7 +74,7 @@ export class DynamicActionManager {
const actionId = this.generateActionId(eventId);
const factory = uiActions.getActionFactory(event.action.factoryId);
- const actionDefinition: ActionDefinition = factory.create(action as SerializedAction);
+ const actionDefinition: ActionDefinition = factory.create(action as SerializedAction);
uiActions.registerAction({
...actionDefinition,
id: actionId,
@@ -195,10 +195,7 @@ export class DynamicActionManager {
* @param action Dynamic action for which to create an event.
* @param triggers List of triggers to which action should react.
*/
- public async createEvent(
- action: SerializedAction,
- triggers: Array
- ) {
+ public async createEvent(action: SerializedAction, triggers: Array) {
const event: SerializedEvent = {
eventId: uuidv4(),
triggers,
@@ -231,7 +228,7 @@ export class DynamicActionManager {
*/
public async updateEvent(
eventId: string,
- action: SerializedAction,
+ action: SerializedAction,
triggers: Array
) {
const event: SerializedEvent = {
diff --git a/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/types.ts b/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/types.ts
index d00db0d9acb7a..28d104093f64f 100644
--- a/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/types.ts
+++ b/x-pack/plugins/ui_actions_enhanced/public/dynamic_actions/types.ts
@@ -5,21 +5,9 @@
*/
import { TriggerId } from '../../../../../src/plugins/ui_actions/public';
+import { SerializedAction, SerializedEvent, BaseActionConfig } from '../../common/types';
-export interface SerializedAction {
- readonly factoryId: string;
- readonly name: string;
- readonly config: Config;
-}
-
-/**
- * Serialized representation of a triggers-action pair, used to persist in storage.
- */
-export interface SerializedEvent {
- eventId: string;
- triggers: string[];
- action: SerializedAction;
-}
+export { SerializedAction, SerializedEvent, BaseActionConfig };
/**
* Action factory context passed into ActionFactories' CollectConfig, getDisplayName, getIconType
diff --git a/x-pack/plugins/ui_actions_enhanced/public/index.ts b/x-pack/plugins/ui_actions_enhanced/public/index.ts
index 4a899b24852a9..ae720598ec759 100644
--- a/x-pack/plugins/ui_actions_enhanced/public/index.ts
+++ b/x-pack/plugins/ui_actions_enhanced/public/index.ts
@@ -29,7 +29,10 @@ export {
DynamicActionManagerState as UiActionsEnhancedDynamicActionManagerState,
MemoryActionStorage as UiActionsEnhancedMemoryActionStorage,
BaseActionFactoryContext as UiActionsEnhancedBaseActionFactoryContext,
+ BaseActionConfig as UiActionsEnhancedBaseActionConfig,
} from './dynamic_actions';
+export { DynamicActionsState } from './services/ui_actions_service_enhancements';
+
export { DrilldownDefinition as UiActionsEnhancedDrilldownDefinition } from './drilldowns';
export * from './drilldowns/url_drilldown';
diff --git a/x-pack/plugins/ui_actions_enhanced/public/mocks.ts b/x-pack/plugins/ui_actions_enhanced/public/mocks.ts
index 17a6fc1b955df..9eb0a06b6dbaf 100644
--- a/x-pack/plugins/ui_actions_enhanced/public/mocks.ts
+++ b/x-pack/plugins/ui_actions_enhanced/public/mocks.ts
@@ -30,6 +30,9 @@ const createStartContract = (): Start => {
getActionFactories: jest.fn(),
getActionFactory: jest.fn(),
FlyoutManageDrilldowns: jest.fn(),
+ telemetry: jest.fn(),
+ extract: jest.fn(),
+ inject: jest.fn(),
};
return startContract;
diff --git a/x-pack/plugins/ui_actions_enhanced/public/plugin.ts b/x-pack/plugins/ui_actions_enhanced/public/plugin.ts
index b38bc44abe2b0..b05c08c4c77d0 100644
--- a/x-pack/plugins/ui_actions_enhanced/public/plugin.ts
+++ b/x-pack/plugins/ui_actions_enhanced/public/plugin.ts
@@ -39,6 +39,7 @@ import { UiActionsServiceEnhancements } from './services';
import { ILicense, LicensingPluginSetup, LicensingPluginStart } from '../../licensing/public';
import { createFlyoutManageDrilldowns } from './drilldowns';
import { createStartServicesGetter, Storage } from '../../../../src/plugins/kibana_utils/public';
+import { dynamicActionEnhancement } from './dynamic_actions/dynamic_action_enhancement';
interface SetupDependencies {
embeddable: EmbeddableSetup; // Embeddable are needed because they register basic triggers/actions.
@@ -58,7 +59,10 @@ export interface SetupContract
export interface StartContract
extends UiActionsStart,
- Pick {
+ Pick<
+ UiActionsServiceEnhancements,
+ 'getActionFactory' | 'getActionFactories' | 'telemetry' | 'extract' | 'inject'
+ > {
FlyoutManageDrilldowns: ReturnType;
}
@@ -87,7 +91,7 @@ export class AdvancedUiActionsPublicPlugin
public setup(
core: CoreSetup,
- { uiActions, licensing }: SetupDependencies
+ { embeddable, uiActions, licensing }: SetupDependencies
): SetupContract {
const startServices = createStartServicesGetter(core.getStartServices);
this.enhancements = new UiActionsServiceEnhancements({
@@ -95,6 +99,7 @@ export class AdvancedUiActionsPublicPlugin
featureUsageSetup: licensing.featureUsage,
getFeatureUsageStart: () => startServices().plugins.licensing.featureUsage,
});
+ embeddable.registerEnhancement(dynamicActionEnhancement(this.enhancements));
return {
...uiActions,
...this.enhancements,
diff --git a/x-pack/plugins/ui_actions_enhanced/public/services/ui_actions_service_enhancements.test.ts b/x-pack/plugins/ui_actions_enhanced/public/services/ui_actions_service_enhancements.test.ts
index 3a0b65d2ed844..6c71868222b24 100644
--- a/x-pack/plugins/ui_actions_enhanced/public/services/ui_actions_service_enhancements.test.ts
+++ b/x-pack/plugins/ui_actions_enhanced/public/services/ui_actions_service_enhancements.test.ts
@@ -96,6 +96,66 @@ describe('UiActionsService', () => {
).resolves.toBe(false);
});
+ test('action factory extract function gets called when calling uiactions extract', () => {
+ const service = new UiActionsServiceEnhancements(deps);
+ const actionState = {
+ events: [
+ {
+ eventId: 'test',
+ triggers: [],
+ action: { factoryId: factoryDefinition1.id, name: 'test', config: {} },
+ },
+ ],
+ };
+ const extract = jest.fn().mockImplementation((state) => ({ state, references: [] }));
+ service.registerActionFactory({
+ ...factoryDefinition1,
+ extract,
+ });
+ service.extract(actionState);
+ expect(extract).toBeCalledWith(actionState.events[0]);
+ });
+
+ test('action factory inject function gets called when calling uiactions inject', () => {
+ const service = new UiActionsServiceEnhancements(deps);
+ const actionState = {
+ events: [
+ {
+ eventId: 'test',
+ triggers: [],
+ action: { factoryId: factoryDefinition1.id, name: 'test', config: {} },
+ },
+ ],
+ };
+ const inject = jest.fn().mockImplementation((state) => state);
+ service.registerActionFactory({
+ ...factoryDefinition1,
+ inject,
+ });
+ service.inject(actionState, []);
+ expect(inject).toBeCalledWith(actionState.events[0], []);
+ });
+
+ test('action factory telemetry function gets called when calling uiactions telemetry', () => {
+ const service = new UiActionsServiceEnhancements(deps);
+ const actionState = {
+ events: [
+ {
+ eventId: 'test',
+ triggers: [],
+ action: { factoryId: factoryDefinition1.id, name: 'test', config: {} },
+ },
+ ],
+ };
+ const telemetry = jest.fn().mockImplementation((state) => ({}));
+ service.registerActionFactory({
+ ...factoryDefinition1,
+ telemetry,
+ });
+ service.telemetry(actionState);
+ expect(telemetry).toBeCalledWith(actionState.events[0], {});
+ });
+
describe('registerFeature for licensing', () => {
const spy = jest.spyOn(deps.featureUsageSetup, 'register');
beforeEach(() => {
diff --git a/x-pack/plugins/ui_actions_enhanced/public/services/ui_actions_service_enhancements.ts b/x-pack/plugins/ui_actions_enhanced/public/services/ui_actions_service_enhancements.ts
index b8086c16f5e71..28ce1b3524b06 100644
--- a/x-pack/plugins/ui_actions_enhanced/public/services/ui_actions_service_enhancements.ts
+++ b/x-pack/plugins/ui_actions_enhanced/public/services/ui_actions_service_enhancements.ts
@@ -8,12 +8,20 @@ import { ActionFactoryRegistry } from '../types';
import {
ActionFactory,
ActionFactoryDefinition,
+ BaseActionConfig,
BaseActionFactoryContext,
+ SerializedEvent,
} from '../dynamic_actions';
import { DrilldownDefinition } from '../drilldowns';
import { ILicense } from '../../../licensing/common/types';
import { TriggerContextMapping, TriggerId } from '../../../../../src/plugins/ui_actions/public';
import { LicensingPluginSetup, LicensingPluginStart } from '../../../licensing/public';
+import { SavedObjectReference } from '../../../../../src/core/types';
+import { PersistableStateDefinition } from '../../../../../src/plugins/kibana_utils/common';
+
+import { DynamicActionsState } from '../../common/types';
+
+export { DynamicActionsState };
export interface UiActionsServiceEnhancementsParams {
readonly actionFactories?: ActionFactoryRegistry;
@@ -22,7 +30,8 @@ export interface UiActionsServiceEnhancementsParams {
readonly getFeatureUsageStart: () => LicensingPluginStart['featureUsage'];
}
-export class UiActionsServiceEnhancements {
+export class UiActionsServiceEnhancements
+ implements PersistableStateDefinition {
protected readonly actionFactories: ActionFactoryRegistry;
protected readonly deps: Omit;
@@ -36,7 +45,7 @@ export class UiActionsServiceEnhancements {
* serialize/deserialize dynamic actions.
*/
public readonly registerActionFactory = <
- Config extends object = object,
+ Config extends BaseActionConfig = BaseActionConfig,
SupportedTriggers extends TriggerId = TriggerId,
FactoryContext extends BaseActionFactoryContext = {
triggers: SupportedTriggers[];
@@ -81,7 +90,7 @@ export class UiActionsServiceEnhancements {
* Convenience method to register a {@link DrilldownDefinition | drilldown}.
*/
public readonly registerDrilldown = <
- Config extends object = object,
+ Config extends BaseActionConfig = BaseActionConfig,
SupportedTriggers extends TriggerId = TriggerId,
FactoryContext extends BaseActionFactoryContext = {
triggers: SupportedTriggers[];
@@ -101,6 +110,9 @@ export class UiActionsServiceEnhancements {
licenseFeatureName,
supportedTriggers,
isCompatible,
+ telemetry,
+ extract,
+ inject,
}: DrilldownDefinition): void => {
const actionFactory: ActionFactoryDefinition<
Config,
@@ -117,6 +129,9 @@ export class UiActionsServiceEnhancements {
isConfigValid,
getDisplayName,
supportedTriggers,
+ telemetry,
+ extract,
+ inject,
getIconType: () => euiIcon,
isCompatible: async () => true,
create: (serializedAction) => ({
@@ -149,4 +164,43 @@ export class UiActionsServiceEnhancements {
);
});
};
+
+ public readonly telemetry = (state: DynamicActionsState, telemetry: Record = {}) => {
+ let telemetryData = telemetry;
+ state.events.forEach((event: SerializedEvent) => {
+ if (this.actionFactories.has(event.action.factoryId)) {
+ telemetryData = this.actionFactories
+ .get(event.action.factoryId)!
+ .telemetry(event, telemetryData);
+ }
+ });
+ return telemetryData;
+ };
+
+ public readonly extract = (state: DynamicActionsState) => {
+ const references: SavedObjectReference[] = [];
+ const newState = {
+ events: state.events.map((event: SerializedEvent) => {
+ const result = this.actionFactories.has(event.action.factoryId)
+ ? this.actionFactories.get(event.action.factoryId)!.extract(event)
+ : {
+ state: event,
+ references: [],
+ };
+ references.push(...result.references);
+ return result.state;
+ }),
+ };
+ return { state: newState, references };
+ };
+
+ public readonly inject = (state: DynamicActionsState, references: SavedObjectReference[]) => {
+ return {
+ events: state.events.map((event: SerializedEvent) => {
+ return this.actionFactories.has(event.action.factoryId)
+ ? this.actionFactories.get(event.action.factoryId)!.inject(event, references)
+ : event;
+ }),
+ };
+ };
}
diff --git a/x-pack/plugins/ui_actions_enhanced/public/test_helpers/time_range_container.ts b/x-pack/plugins/ui_actions_enhanced/public/test_helpers/time_range_container.ts
index 3d143b0cacd06..9a529f192158d 100644
--- a/x-pack/plugins/ui_actions_enhanced/public/test_helpers/time_range_container.ts
+++ b/x-pack/plugins/ui_actions_enhanced/public/test_helpers/time_range_container.ts
@@ -17,7 +17,6 @@ import { TimeRange } from '../../../../../src/plugins/data/public';
* https://github.com/microsoft/TypeScript/issues/15300 is fixed so we use a type
* here instead
*/
-// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
export type InheritedChildrenInput = {
timeRange: TimeRange;
id?: string;
diff --git a/x-pack/plugins/ui_actions_enhanced/server/dynamic_action_enhancement.ts b/x-pack/plugins/ui_actions_enhanced/server/dynamic_action_enhancement.ts
new file mode 100644
index 0000000000000..b366436200914
--- /dev/null
+++ b/x-pack/plugins/ui_actions_enhanced/server/dynamic_action_enhancement.ts
@@ -0,0 +1,55 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { EnhancementRegistryDefinition } from '../../../../src/plugins/embeddable/server';
+import { SavedObjectReference } from '../../../../src/core/types';
+import { DynamicActionsState, SerializedEvent } from './types';
+import { AdvancedUiActionsPublicPlugin } from './plugin';
+import { SerializableState } from '../../../../src/plugins/kibana_utils/common';
+
+export const dynamicActionEnhancement = (
+ uiActionsEnhanced: AdvancedUiActionsPublicPlugin
+): EnhancementRegistryDefinition => {
+ return {
+ id: 'dynamicActions',
+ telemetry: (state: SerializableState, telemetry: Record) => {
+ let telemetryData = telemetry;
+ (state as DynamicActionsState).events.forEach((event: SerializedEvent) => {
+ if (uiActionsEnhanced.getActionFactory(event.action.factoryId)) {
+ telemetryData = uiActionsEnhanced
+ .getActionFactory(event.action.factoryId)!
+ .telemetry(event, telemetryData);
+ }
+ });
+ return telemetryData;
+ },
+ extract: (state: SerializableState) => {
+ const references: SavedObjectReference[] = [];
+ const newState: DynamicActionsState = {
+ events: (state as DynamicActionsState).events.map((event: SerializedEvent) => {
+ const result = uiActionsEnhanced.getActionFactory(event.action.factoryId)
+ ? uiActionsEnhanced.getActionFactory(event.action.factoryId)!.extract(event)
+ : {
+ state: event,
+ references: [],
+ };
+ result.references.forEach((r) => references.push(r));
+ return result.state;
+ }),
+ };
+ return { state: newState, references };
+ },
+ inject: (state: SerializableState, references: SavedObjectReference[]) => {
+ return {
+ events: (state as DynamicActionsState).events.map((event: SerializedEvent) => {
+ return uiActionsEnhanced.getActionFactory(event.action.factoryId)
+ ? uiActionsEnhanced.getActionFactory(event.action.factoryId)!.inject(event, references)
+ : event;
+ }),
+ } as DynamicActionsState;
+ },
+ } as EnhancementRegistryDefinition;
+};
diff --git a/x-pack/plugins/ui_actions_enhanced/server/index.ts b/x-pack/plugins/ui_actions_enhanced/server/index.ts
new file mode 100644
index 0000000000000..5419c4135796d
--- /dev/null
+++ b/x-pack/plugins/ui_actions_enhanced/server/index.ts
@@ -0,0 +1,29 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { AdvancedUiActionsPublicPlugin } from './plugin';
+
+export function plugin() {
+ return new AdvancedUiActionsPublicPlugin();
+}
+
+export { AdvancedUiActionsPublicPlugin as Plugin };
+export {
+ SetupContract as AdvancedUiActionsSetup,
+ StartContract as AdvancedUiActionsStart,
+} from './plugin';
+
+export {
+ ActionFactoryDefinition as UiActionsEnhancedActionFactoryDefinition,
+ ActionFactory as UiActionsEnhancedActionFactory,
+} from './types';
+
+export {
+ DynamicActionsState,
+ BaseActionConfig as UiActionsEnhancedBaseActionConfig,
+ SerializedAction as UiActionsEnhancedSerializedAction,
+ SerializedEvent as UiActionsEnhancedSerializedEvent,
+} from '../common/types';
diff --git a/x-pack/plugins/ui_actions_enhanced/server/plugin.ts b/x-pack/plugins/ui_actions_enhanced/server/plugin.ts
new file mode 100644
index 0000000000000..0a61c917a2c5c
--- /dev/null
+++ b/x-pack/plugins/ui_actions_enhanced/server/plugin.ts
@@ -0,0 +1,107 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { identity } from 'lodash';
+import { CoreSetup, Plugin, SavedObjectReference } from '../../../../src/core/server';
+import { EmbeddableSetup } from '../../../../src/plugins/embeddable/server';
+import { dynamicActionEnhancement } from './dynamic_action_enhancement';
+import {
+ ActionFactoryRegistry,
+ SerializedEvent,
+ ActionFactoryDefinition,
+ DynamicActionsState,
+} from './types';
+
+export interface SetupContract {
+ registerActionFactory: any;
+}
+
+export type StartContract = void;
+
+interface SetupDependencies {
+ embeddable: EmbeddableSetup; // Embeddable are needed because they register basic triggers/actions.
+}
+
+export class AdvancedUiActionsPublicPlugin
+ implements Plugin {
+ protected readonly actionFactories: ActionFactoryRegistry = new Map();
+
+ constructor() {}
+
+ public setup(core: CoreSetup, { embeddable }: SetupDependencies) {
+ embeddable.registerEnhancement(dynamicActionEnhancement(this));
+
+ return {
+ registerActionFactory: this.registerActionFactory,
+ };
+ }
+
+ public start() {}
+
+ public stop() {}
+
+ /**
+ * Register an action factory. Action factories are used to configure and
+ * serialize/deserialize dynamic actions.
+ */
+ public readonly registerActionFactory = (definition: ActionFactoryDefinition) => {
+ if (this.actionFactories.has(definition.id)) {
+ throw new Error(`ActionFactory [actionFactory.id = ${definition.id}] already registered.`);
+ }
+
+ this.actionFactories.set(definition.id, {
+ id: definition.id,
+ telemetry: definition.telemetry || (() => ({})),
+ inject: definition.inject || identity,
+ extract:
+ definition.extract ||
+ ((state: SerializedEvent) => {
+ return { state, references: [] };
+ }),
+ });
+ };
+
+ public readonly getActionFactory = (actionFactoryId: string) => {
+ const actionFactory = this.actionFactories.get(actionFactoryId);
+ return actionFactory;
+ };
+
+ public readonly telemetry = (state: DynamicActionsState, telemetry: Record = {}) => {
+ state.events.forEach((event: SerializedEvent) => {
+ if (this.actionFactories.has(event.action.factoryId)) {
+ this.actionFactories.get(event.action.factoryId)!.telemetry(event, telemetry);
+ }
+ });
+ return telemetry;
+ };
+
+ public readonly extract = (state: DynamicActionsState) => {
+ const references: SavedObjectReference[] = [];
+ const newState = {
+ events: state.events.map((event: SerializedEvent) => {
+ const result = this.actionFactories.has(event.action.factoryId)
+ ? this.actionFactories.get(event.action.factoryId)!.extract(event)
+ : {
+ state: event,
+ references: [],
+ };
+ result.references.forEach((r) => references.push(r));
+ return result.state;
+ }),
+ };
+ return { state: newState, references };
+ };
+
+ public readonly inject = (state: DynamicActionsState, references: SavedObjectReference[]) => {
+ return {
+ events: state.events.map((event: SerializedEvent) => {
+ return this.actionFactories.has(event.action.factoryId)
+ ? this.actionFactories.get(event.action.factoryId)!.inject(event, references)
+ : event;
+ }),
+ };
+ };
+}
diff --git a/x-pack/plugins/ui_actions_enhanced/server/types.ts b/x-pack/plugins/ui_actions_enhanced/server/types.ts
new file mode 100644
index 0000000000000..4859be6728344
--- /dev/null
+++ b/x-pack/plugins/ui_actions_enhanced/server/types.ts
@@ -0,0 +1,26 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import {
+ PersistableState,
+ PersistableStateDefinition,
+} from '../../../../src/plugins/kibana_utils/common';
+
+import { SerializedAction, SerializedEvent, DynamicActionsState } from '../common/types';
+
+export type ActionFactoryRegistry = Map;
+
+export interface ActionFactoryDefinition
+ extends PersistableStateDefinition
{
+ id: string;
+}
+
+export interface ActionFactory
+ extends PersistableState
{
+ id: string;
+}
+
+export { SerializedEvent, SerializedAction, DynamicActionsState };