mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
Embeddable telemetry and reference extraction/injection (#74352)
This commit is contained in:
parent
ef55756b8c
commit
e361035650
91 changed files with 1314 additions and 505 deletions
|
@ -35,7 +35,7 @@ esFilters: {
|
|||
type?: string | undefined;
|
||||
key?: string | undefined;
|
||||
params?: any;
|
||||
value?: string | ((formatter?: import("../common").FilterValueFormatter | undefined) => string) | undefined;
|
||||
value?: string | undefined;
|
||||
};
|
||||
$state?: import("../common").FilterState | undefined;
|
||||
query?: any;
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [Filter](./kibana-plugin-plugins-data-public.filter.md) > [$state](./kibana-plugin-plugins-data-public.filter._state.md)
|
||||
|
||||
## Filter.$state property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
$state?: FilterState;
|
||||
```
|
|
@ -2,19 +2,14 @@
|
|||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [Filter](./kibana-plugin-plugins-data-public.filter.md)
|
||||
|
||||
## Filter interface
|
||||
## Filter type
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface Filter
|
||||
export declare type Filter = {
|
||||
$state?: FilterState;
|
||||
meta: FilterMeta;
|
||||
query?: any;
|
||||
};
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [$state](./kibana-plugin-plugins-data-public.filter._state.md) | <code>FilterState</code> | |
|
||||
| [meta](./kibana-plugin-plugins-data-public.filter.meta.md) | <code>FilterMeta</code> | |
|
||||
| [query](./kibana-plugin-plugins-data-public.filter.query.md) | <code>any</code> | |
|
||||
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [Filter](./kibana-plugin-plugins-data-public.filter.md) > [meta](./kibana-plugin-plugins-data-public.filter.meta.md)
|
||||
|
||||
## Filter.meta property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
meta: FilterMeta;
|
||||
```
|
|
@ -1,11 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [Filter](./kibana-plugin-plugins-data-public.filter.md) > [query](./kibana-plugin-plugins-data-public.filter.query.md)
|
||||
|
||||
## Filter.query property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
query?: any;
|
||||
```
|
|
@ -1,11 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [Query](./kibana-plugin-plugins-data-public.query.md) > [language](./kibana-plugin-plugins-data-public.query.language.md)
|
||||
|
||||
## Query.language property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
language: string;
|
||||
```
|
|
@ -2,18 +2,15 @@
|
|||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [Query](./kibana-plugin-plugins-data-public.query.md)
|
||||
|
||||
## Query interface
|
||||
## Query type
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface Query
|
||||
export declare type Query = {
|
||||
query: string | {
|
||||
[key: string]: any;
|
||||
};
|
||||
language: string;
|
||||
};
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [language](./kibana-plugin-plugins-data-public.query.language.md) | <code>string</code> | |
|
||||
| [query](./kibana-plugin-plugins-data-public.query.query.md) | <code>string | {</code><br/><code> [key: string]: any;</code><br/><code> }</code> | |
|
||||
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [Query](./kibana-plugin-plugins-data-public.query.md) > [query](./kibana-plugin-plugins-data-public.query.query.md)
|
||||
|
||||
## Query.query property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
query: string | {
|
||||
[key: string]: any;
|
||||
};
|
||||
```
|
|
@ -1,11 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [TimeRange](./kibana-plugin-plugins-data-public.timerange.md) > [from](./kibana-plugin-plugins-data-public.timerange.from.md)
|
||||
|
||||
## TimeRange.from property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
from: string;
|
||||
```
|
|
@ -2,19 +2,14 @@
|
|||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [TimeRange](./kibana-plugin-plugins-data-public.timerange.md)
|
||||
|
||||
## TimeRange interface
|
||||
## TimeRange type
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface TimeRange
|
||||
export declare type TimeRange = {
|
||||
from: string;
|
||||
to: string;
|
||||
mode?: 'absolute' | 'relative';
|
||||
};
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [from](./kibana-plugin-plugins-data-public.timerange.from.md) | <code>string</code> | |
|
||||
| [mode](./kibana-plugin-plugins-data-public.timerange.mode.md) | <code>'absolute' | 'relative'</code> | |
|
||||
| [to](./kibana-plugin-plugins-data-public.timerange.to.md) | <code>string</code> | |
|
||||
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [TimeRange](./kibana-plugin-plugins-data-public.timerange.md) > [mode](./kibana-plugin-plugins-data-public.timerange.mode.md)
|
||||
|
||||
## TimeRange.mode property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
mode?: 'absolute' | 'relative';
|
||||
```
|
|
@ -1,11 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [TimeRange](./kibana-plugin-plugins-data-public.timerange.md) > [to](./kibana-plugin-plugins-data-public.timerange.to.md)
|
||||
|
||||
## TimeRange.to property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
to: string;
|
||||
```
|
|
@ -1,11 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [Filter](./kibana-plugin-plugins-data-server.filter.md) > [$state](./kibana-plugin-plugins-data-server.filter._state.md)
|
||||
|
||||
## Filter.$state property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
$state?: FilterState;
|
||||
```
|
|
@ -2,19 +2,14 @@
|
|||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [Filter](./kibana-plugin-plugins-data-server.filter.md)
|
||||
|
||||
## Filter interface
|
||||
## Filter type
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface Filter
|
||||
export declare type Filter = {
|
||||
$state?: FilterState;
|
||||
meta: FilterMeta;
|
||||
query?: any;
|
||||
};
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [$state](./kibana-plugin-plugins-data-server.filter._state.md) | <code>FilterState</code> | |
|
||||
| [meta](./kibana-plugin-plugins-data-server.filter.meta.md) | <code>FilterMeta</code> | |
|
||||
| [query](./kibana-plugin-plugins-data-server.filter.query.md) | <code>any</code> | |
|
||||
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [Filter](./kibana-plugin-plugins-data-server.filter.md) > [meta](./kibana-plugin-plugins-data-server.filter.meta.md)
|
||||
|
||||
## Filter.meta property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
meta: FilterMeta;
|
||||
```
|
|
@ -1,11 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [Filter](./kibana-plugin-plugins-data-server.filter.md) > [query](./kibana-plugin-plugins-data-server.filter.query.md)
|
||||
|
||||
## Filter.query property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
query?: any;
|
||||
```
|
|
@ -42,7 +42,6 @@
|
|||
| [AggParamOption](./kibana-plugin-plugins-data-server.aggparamoption.md) | |
|
||||
| [EsQueryConfig](./kibana-plugin-plugins-data-server.esqueryconfig.md) | |
|
||||
| [FieldFormatConfig](./kibana-plugin-plugins-data-server.fieldformatconfig.md) | |
|
||||
| [Filter](./kibana-plugin-plugins-data-server.filter.md) | |
|
||||
| [IEsSearchRequest](./kibana-plugin-plugins-data-server.iessearchrequest.md) | |
|
||||
| [IEsSearchResponse](./kibana-plugin-plugins-data-server.iessearchresponse.md) | |
|
||||
| [IFieldSubType](./kibana-plugin-plugins-data-server.ifieldsubtype.md) | |
|
||||
|
@ -58,12 +57,10 @@
|
|||
| [OptionedValueProp](./kibana-plugin-plugins-data-server.optionedvalueprop.md) | |
|
||||
| [PluginSetup](./kibana-plugin-plugins-data-server.pluginsetup.md) | |
|
||||
| [PluginStart](./kibana-plugin-plugins-data-server.pluginstart.md) | |
|
||||
| [Query](./kibana-plugin-plugins-data-server.query.md) | |
|
||||
| [RefreshInterval](./kibana-plugin-plugins-data-server.refreshinterval.md) | |
|
||||
| [SearchUsage](./kibana-plugin-plugins-data-server.searchusage.md) | |
|
||||
| [TabbedAggColumn](./kibana-plugin-plugins-data-server.tabbedaggcolumn.md) | \* |
|
||||
| [TabbedTable](./kibana-plugin-plugins-data-server.tabbedtable.md) | \* |
|
||||
| [TimeRange](./kibana-plugin-plugins-data-server.timerange.md) | |
|
||||
|
||||
## Variables
|
||||
|
||||
|
@ -91,11 +88,14 @@
|
|||
| [AggParam](./kibana-plugin-plugins-data-server.aggparam.md) | |
|
||||
| [EsaggsExpressionFunctionDefinition](./kibana-plugin-plugins-data-server.esaggsexpressionfunctiondefinition.md) | |
|
||||
| [FieldFormatsGetConfigFn](./kibana-plugin-plugins-data-server.fieldformatsgetconfigfn.md) | |
|
||||
| [Filter](./kibana-plugin-plugins-data-server.filter.md) | |
|
||||
| [IAggConfig](./kibana-plugin-plugins-data-server.iaggconfig.md) | AggConfig This class represents an aggregation, which is displayed in the left-hand nav of the Visualize app. |
|
||||
| [IAggType](./kibana-plugin-plugins-data-server.iaggtype.md) | |
|
||||
| [IFieldFormatsRegistry](./kibana-plugin-plugins-data-server.ifieldformatsregistry.md) | |
|
||||
| [IFieldParamType](./kibana-plugin-plugins-data-server.ifieldparamtype.md) | |
|
||||
| [IMetricAggType](./kibana-plugin-plugins-data-server.imetricaggtype.md) | |
|
||||
| [ParsedInterval](./kibana-plugin-plugins-data-server.parsedinterval.md) | |
|
||||
| [Query](./kibana-plugin-plugins-data-server.query.md) | |
|
||||
| [TabbedAggRow](./kibana-plugin-plugins-data-server.tabbedaggrow.md) | \* |
|
||||
| [TimeRange](./kibana-plugin-plugins-data-server.timerange.md) | |
|
||||
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [Query](./kibana-plugin-plugins-data-server.query.md) > [language](./kibana-plugin-plugins-data-server.query.language.md)
|
||||
|
||||
## Query.language property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
language: string;
|
||||
```
|
|
@ -2,18 +2,15 @@
|
|||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [Query](./kibana-plugin-plugins-data-server.query.md)
|
||||
|
||||
## Query interface
|
||||
## Query type
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface Query
|
||||
export declare type Query = {
|
||||
query: string | {
|
||||
[key: string]: any;
|
||||
};
|
||||
language: string;
|
||||
};
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [language](./kibana-plugin-plugins-data-server.query.language.md) | <code>string</code> | |
|
||||
| [query](./kibana-plugin-plugins-data-server.query.query.md) | <code>string | {</code><br/><code> [key: string]: any;</code><br/><code> }</code> | |
|
||||
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [Query](./kibana-plugin-plugins-data-server.query.md) > [query](./kibana-plugin-plugins-data-server.query.query.md)
|
||||
|
||||
## Query.query property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
query: string | {
|
||||
[key: string]: any;
|
||||
};
|
||||
```
|
|
@ -1,11 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [TimeRange](./kibana-plugin-plugins-data-server.timerange.md) > [from](./kibana-plugin-plugins-data-server.timerange.from.md)
|
||||
|
||||
## TimeRange.from property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
from: string;
|
||||
```
|
|
@ -2,19 +2,14 @@
|
|||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [TimeRange](./kibana-plugin-plugins-data-server.timerange.md)
|
||||
|
||||
## TimeRange interface
|
||||
## TimeRange type
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
export interface TimeRange
|
||||
export declare type TimeRange = {
|
||||
from: string;
|
||||
to: string;
|
||||
mode?: 'absolute' | 'relative';
|
||||
};
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [from](./kibana-plugin-plugins-data-server.timerange.from.md) | <code>string</code> | |
|
||||
| [mode](./kibana-plugin-plugins-data-server.timerange.mode.md) | <code>'absolute' | 'relative'</code> | |
|
||||
| [to](./kibana-plugin-plugins-data-server.timerange.to.md) | <code>string</code> | |
|
||||
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [TimeRange](./kibana-plugin-plugins-data-server.timerange.md) > [mode](./kibana-plugin-plugins-data-server.timerange.mode.md)
|
||||
|
||||
## TimeRange.mode property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
mode?: 'absolute' | 'relative';
|
||||
```
|
|
@ -1,11 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [TimeRange](./kibana-plugin-plugins-data-server.timerange.md) > [to](./kibana-plugin-plugins-data-server.timerange.to.md)
|
||||
|
||||
## TimeRange.to property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
to: string;
|
||||
```
|
|
@ -43,7 +43,7 @@ export function getDisplayValueFromFilter(filter: Filter, indexPatterns: IIndexP
|
|||
if (typeof filter.meta.value === 'function') {
|
||||
const indexPattern = getIndexPatternFromFilter(filter, indexPatterns);
|
||||
const valueFormatter: any = getValueFormatter(indexPattern, filter.meta.key);
|
||||
return filter.meta.value(valueFormatter);
|
||||
return (filter.meta.value as any)(valueFormatter);
|
||||
} else {
|
||||
return filter.meta.value || '';
|
||||
}
|
||||
|
|
|
@ -22,9 +22,10 @@ export enum FilterStateStore {
|
|||
GLOBAL_STATE = 'globalState',
|
||||
}
|
||||
|
||||
export interface FilterState {
|
||||
// eslint-disable-next-line
|
||||
export type FilterState = {
|
||||
store: FilterStateStore;
|
||||
}
|
||||
};
|
||||
|
||||
type FilterFormatterFunction = (value: any) => string;
|
||||
export interface FilterValueFormatter {
|
||||
|
@ -32,7 +33,8 @@ export interface FilterValueFormatter {
|
|||
getConverterFor: (type: string) => FilterFormatterFunction;
|
||||
}
|
||||
|
||||
export interface FilterMeta {
|
||||
// eslint-disable-next-line
|
||||
export type FilterMeta = {
|
||||
alias: string | null;
|
||||
disabled: boolean;
|
||||
negate: boolean;
|
||||
|
@ -43,14 +45,15 @@ export interface FilterMeta {
|
|||
type?: string;
|
||||
key?: string;
|
||||
params?: any;
|
||||
value?: string | ((formatter?: FilterValueFormatter) => string);
|
||||
}
|
||||
value?: string;
|
||||
};
|
||||
|
||||
export interface Filter {
|
||||
// eslint-disable-next-line
|
||||
export type Filter = {
|
||||
$state?: FilterState;
|
||||
meta: FilterMeta;
|
||||
query?: any;
|
||||
}
|
||||
};
|
||||
|
||||
export interface LatLon {
|
||||
lat: number;
|
||||
|
|
|
@ -24,11 +24,12 @@ export interface RefreshInterval {
|
|||
value: number;
|
||||
}
|
||||
|
||||
export interface TimeRange {
|
||||
// eslint-disable-next-line
|
||||
export type TimeRange = {
|
||||
from: string;
|
||||
to: string;
|
||||
mode?: 'absolute' | 'relative';
|
||||
}
|
||||
};
|
||||
|
||||
export interface TimeRangeBounds {
|
||||
min: Moment | undefined;
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
|
||||
export * from './timefilter/types';
|
||||
|
||||
export interface Query {
|
||||
// eslint-disable-next-line
|
||||
export type Query = {
|
||||
query: string | { [key: string]: any };
|
||||
language: string;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -565,7 +565,7 @@ export const esFilters: {
|
|||
type?: string | undefined;
|
||||
key?: string | undefined;
|
||||
params?: any;
|
||||
value?: string | ((formatter?: import("../common").FilterValueFormatter | undefined) => string) | undefined;
|
||||
value?: string | undefined;
|
||||
};
|
||||
$state?: import("../common").FilterState | undefined;
|
||||
query?: any;
|
||||
|
@ -791,18 +791,11 @@ export interface FieldMappingSpec {
|
|||
// Warning: (ae-missing-release-tag) "Filter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export interface Filter {
|
||||
// Warning: (ae-forgotten-export) The symbol "FilterState" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// (undocumented)
|
||||
export type Filter = {
|
||||
$state?: FilterState;
|
||||
// Warning: (ae-forgotten-export) The symbol "FilterMeta" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// (undocumented)
|
||||
meta: FilterMeta;
|
||||
// (undocumented)
|
||||
query?: any;
|
||||
}
|
||||
};
|
||||
|
||||
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
|
||||
// Warning: (ae-missing-release-tag) "FilterBar" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
|
@ -1645,14 +1638,12 @@ export function plugin(initializerContext: PluginInitializerContext<ConfigSchema
|
|||
// Warning: (ae-missing-release-tag) "Query" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export interface Query {
|
||||
// (undocumented)
|
||||
language: string;
|
||||
// (undocumented)
|
||||
export type Query = {
|
||||
query: string | {
|
||||
[key: string]: any;
|
||||
};
|
||||
}
|
||||
language: string;
|
||||
};
|
||||
|
||||
// Warning: (ae-forgotten-export) The symbol "QueryService" needs to be exported by the entry point index.d.ts
|
||||
// Warning: (ae-missing-release-tag) "QueryStart" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
|
@ -2147,14 +2138,11 @@ export type TimeHistoryContract = PublicMethodsOf<TimeHistory>;
|
|||
// Warning: (ae-missing-release-tag) "TimeRange" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export interface TimeRange {
|
||||
// (undocumented)
|
||||
export type TimeRange = {
|
||||
from: string;
|
||||
// (undocumented)
|
||||
mode?: 'absolute' | 'relative';
|
||||
// (undocumented)
|
||||
to: string;
|
||||
}
|
||||
mode?: 'absolute' | 'relative';
|
||||
};
|
||||
|
||||
// Warning: (ae-missing-release-tag) "UI_SETTINGS" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
|
@ -2197,6 +2185,8 @@ export const UI_SETTINGS: {
|
|||
// src/plugins/data/common/es_query/filters/exists_filter.ts:30:3 - (ae-forgotten-export) The symbol "ExistsFilterMeta" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/common/es_query/filters/exists_filter.ts:31:3 - (ae-forgotten-export) The symbol "FilterExistsProperty" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/common/es_query/filters/match_all_filter.ts:28:3 - (ae-forgotten-export) The symbol "MatchAllFilterMeta" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/common/es_query/filters/meta_filter.ts:53:3 - (ae-forgotten-export) The symbol "FilterState" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/common/es_query/filters/meta_filter.ts:54:3 - (ae-forgotten-export) The symbol "FilterMeta" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/common/es_query/filters/phrase_filter.ts:33:3 - (ae-forgotten-export) The symbol "PhraseFilterMeta" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/common/es_query/filters/phrases_filter.ts:31:3 - (ae-forgotten-export) The symbol "PhrasesFilterMeta" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/common/search/aggs/types.ts:98:51 - (ae-forgotten-export) The symbol "AggTypesRegistryStart" needs to be exported by the entry point index.d.ts
|
||||
|
|
|
@ -25,7 +25,9 @@ describe('filter manager utilities', () => {
|
|||
let filters: unknown;
|
||||
|
||||
function getDisplayName(filter: Filter) {
|
||||
return typeof filter.meta.value === 'function' ? filter.meta.value() : filter.meta.value;
|
||||
return typeof filter.meta.value === 'function'
|
||||
? (filter.meta.value as any)()
|
||||
: filter.meta.value;
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
|
@ -22,7 +22,9 @@ import { Filter } from '../../../../common';
|
|||
|
||||
describe('filter manager utilities', () => {
|
||||
function getDisplayName(filter: Filter) {
|
||||
return typeof filter.meta.value === 'function' ? filter.meta.value() : filter.meta.value;
|
||||
return typeof filter.meta.value === 'function'
|
||||
? (filter.meta.value as any)()
|
||||
: filter.meta.value;
|
||||
}
|
||||
|
||||
describe('mapFilter()', () => {
|
||||
|
|
|
@ -440,18 +440,11 @@ export type FieldFormatsGetConfigFn = GetConfigFn;
|
|||
// Warning: (ae-missing-release-tag) "Filter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export interface Filter {
|
||||
// Warning: (ae-forgotten-export) The symbol "FilterState" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// (undocumented)
|
||||
export type Filter = {
|
||||
$state?: FilterState;
|
||||
// Warning: (ae-forgotten-export) The symbol "FilterMeta" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// (undocumented)
|
||||
meta: FilterMeta;
|
||||
// (undocumented)
|
||||
query?: any;
|
||||
}
|
||||
};
|
||||
|
||||
// Warning: (ae-forgotten-export) The symbol "IUiSettingsClient" needs to be exported by the entry point index.d.ts
|
||||
// Warning: (ae-missing-release-tag) "getDefaultSearchParams" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
|
@ -941,14 +934,12 @@ export interface PluginStart {
|
|||
// Warning: (ae-missing-release-tag) "Query" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export interface Query {
|
||||
// (undocumented)
|
||||
language: string;
|
||||
// (undocumented)
|
||||
export type Query = {
|
||||
query: string | {
|
||||
[key: string]: any;
|
||||
};
|
||||
}
|
||||
language: string;
|
||||
};
|
||||
|
||||
// Warning: (ae-missing-release-tag) "RefreshInterval" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
|
@ -1063,14 +1054,11 @@ export interface TabbedTable {
|
|||
// Warning: (ae-missing-release-tag) "TimeRange" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export interface TimeRange {
|
||||
// (undocumented)
|
||||
export type TimeRange = {
|
||||
from: string;
|
||||
// (undocumented)
|
||||
mode?: 'absolute' | 'relative';
|
||||
// (undocumented)
|
||||
to: string;
|
||||
}
|
||||
mode?: 'absolute' | 'relative';
|
||||
};
|
||||
|
||||
// Warning: (ae-missing-release-tag) "toSnakeCase" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
|
@ -1120,6 +1108,8 @@ export function usageProvider(core: CoreSetup_2): SearchUsage;
|
|||
|
||||
// Warnings were encountered during analysis:
|
||||
//
|
||||
// src/plugins/data/common/es_query/filters/meta_filter.ts:53:3 - (ae-forgotten-export) The symbol "FilterState" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/common/es_query/filters/meta_filter.ts:54:3 - (ae-forgotten-export) The symbol "FilterMeta" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/common/index_patterns/fields/types.ts:41:25 - (ae-forgotten-export) The symbol "IndexPattern" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:40:23 - (ae-forgotten-export) The symbol "buildCustomFilter" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:40:23 - (ae-forgotten-export) The symbol "buildFilter" needs to be exported by the entry point index.d.ts
|
||||
|
|
5
src/plugins/embeddable/.eslintrc.json
Normal file
5
src/plugins/embeddable/.eslintrc.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"rules": {
|
||||
"@typescript-eslint/consistent-type-definitions": 0
|
||||
}
|
||||
}
|
39
src/plugins/embeddable/common/lib/migrate_base_input.ts
Normal file
39
src/plugins/embeddable/common/lib/migrate_base_input.ts
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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';
|
||||
import { EmbeddableInput } from '../types';
|
||||
|
||||
export const telemetryBaseEmbeddableInput = (
|
||||
state: EmbeddableInput,
|
||||
telemetryData: Record<string, any>
|
||||
) => {
|
||||
return telemetryData;
|
||||
};
|
||||
|
||||
export const extractBaseEmbeddableInput = (state: EmbeddableInput) => {
|
||||
return { state, references: [] as SavedObjectReference[] };
|
||||
};
|
||||
|
||||
export const injectBaseEmbeddableInput = (
|
||||
state: EmbeddableInput,
|
||||
references: SavedObjectReference[]
|
||||
) => {
|
||||
return state;
|
||||
};
|
70
src/plugins/embeddable/common/types.ts
Normal file
70
src/plugins/embeddable/common/types.ts
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* 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 { SerializableState } from '../../kibana_utils/common';
|
||||
import { Query, TimeRange } from '../../data/common/query';
|
||||
import { Filter } from '../../data/common/es_query/filters';
|
||||
|
||||
export enum ViewMode {
|
||||
EDIT = 'edit',
|
||||
VIEW = 'view',
|
||||
}
|
||||
|
||||
export type EmbeddableInput = {
|
||||
viewMode?: ViewMode;
|
||||
title?: string;
|
||||
/**
|
||||
* Note this is not a saved object id. It is used to uniquely identify this
|
||||
* Embeddable instance from others (e.g. inside a container). It's possible to
|
||||
* have two Embeddables where everything else is the same but the id.
|
||||
*/
|
||||
id: string;
|
||||
lastReloadRequestTime?: number;
|
||||
hidePanelTitles?: boolean;
|
||||
|
||||
/**
|
||||
* Reserved key for enhancements added by other plugins.
|
||||
*/
|
||||
enhancements?: SerializableState;
|
||||
|
||||
/**
|
||||
* List of action IDs that this embeddable should not render.
|
||||
*/
|
||||
disabledActions?: string[];
|
||||
|
||||
/**
|
||||
* Whether this embeddable should not execute triggers.
|
||||
*/
|
||||
disableTriggers?: boolean;
|
||||
|
||||
/**
|
||||
* Time range of the chart.
|
||||
*/
|
||||
timeRange?: TimeRange;
|
||||
|
||||
/**
|
||||
* Visualization query string used to narrow down results.
|
||||
*/
|
||||
query?: Query;
|
||||
|
||||
/**
|
||||
* Visualization filters used to narrow down results.
|
||||
*/
|
||||
filters?: Filter[];
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "embeddable",
|
||||
"version": "kibana",
|
||||
"server": false,
|
||||
"server": true,
|
||||
"ui": true,
|
||||
"requiredPlugins": [
|
||||
"inspector",
|
||||
|
|
|
@ -78,6 +78,8 @@ export {
|
|||
EmbeddableRendererProps,
|
||||
} from './lib';
|
||||
|
||||
export { EnhancementRegistryDefinition } from './types';
|
||||
|
||||
export function plugin(initializerContext: PluginInitializerContext) {
|
||||
return new EmbeddablePublicPlugin(initializerContext);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { SavedObjectAttributes } from 'kibana/public';
|
||||
import { EmbeddableFactoryDefinition } from './embeddable_factory_definition';
|
||||
import { EmbeddableInput, EmbeddableOutput, IEmbeddable } from './i_embeddable';
|
||||
|
@ -47,6 +48,9 @@ export const defaultEmbeddableFactoryProvider = <
|
|||
isEditable: def.isEditable.bind(def),
|
||||
getDisplayName: def.getDisplayName.bind(def),
|
||||
savedObjectMetaData: def.savedObjectMetaData,
|
||||
telemetry: def.telemetry || (() => ({})),
|
||||
inject: def.inject || ((state: EmbeddableInput) => state),
|
||||
extract: def.extract || ((state: EmbeddableInput) => ({ state, references: [] })),
|
||||
};
|
||||
return factory;
|
||||
};
|
||||
|
|
|
@ -21,10 +21,11 @@ import { cloneDeep, isEqual } from 'lodash';
|
|||
import * as Rx from 'rxjs';
|
||||
import { distinctUntilChanged, map } from 'rxjs/operators';
|
||||
import { RenderCompleteDispatcher } from '../../../../kibana_utils/public';
|
||||
import { Adapters, ViewMode } from '../types';
|
||||
import { Adapters } from '../types';
|
||||
import { IContainer } from '../containers';
|
||||
import { EmbeddableInput, EmbeddableOutput, IEmbeddable } from './i_embeddable';
|
||||
import { EmbeddableOutput, IEmbeddable } from './i_embeddable';
|
||||
import { TriggerContextMapping } from '../ui_actions';
|
||||
import { EmbeddableInput, ViewMode } from '../../../common/types';
|
||||
|
||||
function getPanelTitle(input: EmbeddableInput, output: EmbeddableOutput) {
|
||||
return input.hidePanelTitles ? '' : input.title === undefined ? output.defaultTitle : input.title;
|
||||
|
|
|
@ -23,6 +23,7 @@ import { EmbeddableInput, EmbeddableOutput, IEmbeddable } from './i_embeddable';
|
|||
import { ErrorEmbeddable } from './error_embeddable';
|
||||
import { IContainer } from '../containers/i_container';
|
||||
import { PropertySpec } from '../types';
|
||||
import { PersistableState } from '../../../../kibana_utils/common';
|
||||
|
||||
export interface EmbeddableInstanceConfiguration {
|
||||
id: string;
|
||||
|
@ -44,7 +45,7 @@ export interface EmbeddableFactory<
|
|||
TEmbeddableOutput
|
||||
>,
|
||||
TSavedObjectAttributes extends SavedObjectAttributes = SavedObjectAttributes
|
||||
> {
|
||||
> extends PersistableState<EmbeddableInput> {
|
||||
// A unique identified for this factory, which will be used to map an embeddable spec to
|
||||
// a factory that can generate an instance of it.
|
||||
readonly type: string;
|
||||
|
|
|
@ -40,5 +40,8 @@ export type EmbeddableFactoryDefinition<
|
|||
| 'savedObjectMetaData'
|
||||
| 'canCreateNew'
|
||||
| 'getDefaultInput'
|
||||
| 'telemetry'
|
||||
| 'extract'
|
||||
| 'inject'
|
||||
>
|
||||
>;
|
||||
|
|
|
@ -20,57 +20,15 @@
|
|||
import { Observable } from 'rxjs';
|
||||
import { Adapters } from '../types';
|
||||
import { IContainer } from '../containers/i_container';
|
||||
import { ViewMode } from '../types';
|
||||
import { TriggerContextMapping } from '../../../../ui_actions/public';
|
||||
import type { TimeRange, Query, Filter } from '../../../../data/common';
|
||||
import { EmbeddableInput } from '../../../common/types';
|
||||
|
||||
export interface EmbeddableError {
|
||||
name: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface EmbeddableInput {
|
||||
viewMode?: ViewMode;
|
||||
title?: string;
|
||||
/**
|
||||
* Note this is not a saved object id. It is used to uniquely identify this
|
||||
* Embeddable instance from others (e.g. inside a container). It's possible to
|
||||
* have two Embeddables where everything else is the same but the id.
|
||||
*/
|
||||
id: string;
|
||||
lastReloadRequestTime?: number;
|
||||
hidePanelTitles?: boolean;
|
||||
|
||||
/**
|
||||
* Reserved key for enhancements added by other plugins.
|
||||
*/
|
||||
enhancements?: unknown;
|
||||
|
||||
/**
|
||||
* List of action IDs that this embeddable should not render.
|
||||
*/
|
||||
disabledActions?: string[];
|
||||
|
||||
/**
|
||||
* Whether this embeddable should not execute triggers.
|
||||
*/
|
||||
disableTriggers?: boolean;
|
||||
|
||||
/**
|
||||
* Time range of the chart.
|
||||
*/
|
||||
timeRange?: TimeRange;
|
||||
|
||||
/**
|
||||
* Visualization query string used to narrow down results.
|
||||
*/
|
||||
query?: Query;
|
||||
|
||||
/**
|
||||
* Visualization filters used to narrow down results.
|
||||
*/
|
||||
filters?: Filter[];
|
||||
}
|
||||
export { EmbeddableInput };
|
||||
|
||||
export interface EmbeddableOutput {
|
||||
// Whether the embeddable is actively loading.
|
||||
|
|
|
@ -32,7 +32,6 @@ export interface FilterableContainerInput extends ContainerInput {
|
|||
* 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 = {
|
||||
filters: Filter[];
|
||||
id?: string;
|
||||
|
|
|
@ -30,7 +30,6 @@ export const HELLO_WORLD_CONTAINER = 'HELLO_WORLD_CONTAINER';
|
|||
* 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
|
||||
type InheritedInput = {
|
||||
id: string;
|
||||
viewMode: ViewMode;
|
||||
|
|
|
@ -32,10 +32,5 @@ export interface PropertySpec {
|
|||
description: string;
|
||||
value?: string;
|
||||
}
|
||||
|
||||
export enum ViewMode {
|
||||
EDIT = 'edit',
|
||||
VIEW = 'view',
|
||||
}
|
||||
|
||||
export { ViewMode } from '../../common/types';
|
||||
export { Adapters };
|
||||
|
|
|
@ -109,6 +109,7 @@ export const mockRefOrValEmbeddable = <
|
|||
const createSetupContract = (): Setup => {
|
||||
const setupContract: Setup = {
|
||||
registerEmbeddableFactory: jest.fn(),
|
||||
registerEnhancement: jest.fn(),
|
||||
setCustomEmbeddableFactoryProvider: jest.fn(),
|
||||
};
|
||||
return setupContract;
|
||||
|
@ -118,6 +119,9 @@ const createStartContract = (): Start => {
|
|||
const startContract: Start = {
|
||||
getEmbeddableFactories: jest.fn(),
|
||||
getEmbeddableFactory: jest.fn(),
|
||||
telemetry: jest.fn(),
|
||||
extract: jest.fn(),
|
||||
inject: jest.fn(),
|
||||
EmbeddablePanel: jest.fn(),
|
||||
getEmbeddablePanel: jest.fn(),
|
||||
getStateTransfer: jest.fn(() => createEmbeddableStateTransferMock() as EmbeddableStateTransfer),
|
||||
|
|
|
@ -22,21 +22,6 @@ import { EmbeddableFactoryProvider } from './types';
|
|||
import { defaultEmbeddableFactoryProvider } from './lib';
|
||||
import { HelloWorldEmbeddable } from '../../../../examples/embeddable_examples/public';
|
||||
|
||||
test('cannot register embeddable factory with the same ID', async () => {
|
||||
const coreSetup = coreMock.createSetup();
|
||||
const coreStart = coreMock.createStart();
|
||||
const { setup } = testPlugin(coreSetup, coreStart);
|
||||
const embeddableFactoryId = 'ID';
|
||||
const embeddableFactory = {} as any;
|
||||
|
||||
setup.registerEmbeddableFactory(embeddableFactoryId, embeddableFactory);
|
||||
expect(() =>
|
||||
setup.registerEmbeddableFactory(embeddableFactoryId, embeddableFactory)
|
||||
).toThrowError(
|
||||
'Embeddable factory [embeddableFactoryId = ID] already registered in Embeddables API.'
|
||||
);
|
||||
});
|
||||
|
||||
test('can set custom embeddable factory provider', async () => {
|
||||
const coreSetup = coreMock.createSetup();
|
||||
const coreStart = coreMock.createStart();
|
||||
|
@ -108,3 +93,90 @@ test('custom embeddable factory provider test for intercepting embeddable creati
|
|||
await new Promise((resolve) => process.nextTick(resolve));
|
||||
expect(updateCount).toEqual(0);
|
||||
});
|
||||
|
||||
describe('embeddable factory', () => {
|
||||
const coreSetup = coreMock.createSetup();
|
||||
const coreStart = coreMock.createStart();
|
||||
const { setup, doStart } = testPlugin(coreSetup, coreStart);
|
||||
const start = doStart();
|
||||
const embeddableFactoryId = 'ID';
|
||||
const embeddableFactory = {
|
||||
type: embeddableFactoryId,
|
||||
create: jest.fn(),
|
||||
getDisplayName: () => 'Test',
|
||||
isEditable: () => Promise.resolve(true),
|
||||
extract: jest.fn().mockImplementation((state) => ({ state, references: [] })),
|
||||
inject: jest.fn().mockImplementation((state) => state),
|
||||
telemetry: jest.fn().mockResolvedValue({}),
|
||||
} as any;
|
||||
const embeddableState = {
|
||||
id: embeddableFactoryId,
|
||||
my: 'state',
|
||||
} as any;
|
||||
|
||||
test('cannot register embeddable factory with the same ID', async () => {
|
||||
setup.registerEmbeddableFactory(embeddableFactoryId, embeddableFactory);
|
||||
expect(() =>
|
||||
setup.registerEmbeddableFactory(embeddableFactoryId, embeddableFactory)
|
||||
).toThrowError(
|
||||
'Embeddable factory [embeddableFactoryId = ID] already registered in Embeddables API.'
|
||||
);
|
||||
});
|
||||
|
||||
test('embeddableFactory extract function gets called when calling embeddable extract', () => {
|
||||
start.extract(embeddableState);
|
||||
expect(embeddableFactory.extract).toBeCalledWith(embeddableState);
|
||||
});
|
||||
|
||||
test('embeddableFactory inject function gets called when calling embeddable inject', () => {
|
||||
start.inject(embeddableState, []);
|
||||
expect(embeddableFactory.extract).toBeCalledWith(embeddableState);
|
||||
});
|
||||
|
||||
test('embeddableFactory telemetry function gets called when calling embeddable telemetry', () => {
|
||||
start.telemetry(embeddableState, {});
|
||||
expect(embeddableFactory.telemetry).toBeCalledWith(embeddableState, {});
|
||||
});
|
||||
});
|
||||
|
||||
describe('embeddable enhancements', () => {
|
||||
const coreSetup = coreMock.createSetup();
|
||||
const coreStart = coreMock.createStart();
|
||||
const { setup, doStart } = testPlugin(coreSetup, coreStart);
|
||||
const start = doStart();
|
||||
const embeddableEnhancement = {
|
||||
id: 'test',
|
||||
extract: jest.fn().mockImplementation((state) => ({ state, references: [] })),
|
||||
inject: jest.fn().mockImplementation((state) => state),
|
||||
telemetry: jest.fn().mockResolvedValue({}),
|
||||
} as any;
|
||||
const embeddableState = {
|
||||
enhancements: {
|
||||
test: {
|
||||
my: 'state',
|
||||
},
|
||||
},
|
||||
} as any;
|
||||
|
||||
test('cannot register embeddable enhancement with the same ID', async () => {
|
||||
setup.registerEnhancement(embeddableEnhancement);
|
||||
expect(() => setup.registerEnhancement(embeddableEnhancement)).toThrowError(
|
||||
'enhancement with id test already exists in the registry'
|
||||
);
|
||||
});
|
||||
|
||||
test('enhancement extract function gets called when calling embeddable extract', () => {
|
||||
start.extract(embeddableState);
|
||||
expect(embeddableEnhancement.extract).toBeCalledWith(embeddableState.enhancements.test);
|
||||
});
|
||||
|
||||
test('enhancement inject function gets called when calling embeddable inject', () => {
|
||||
start.inject(embeddableState, []);
|
||||
expect(embeddableEnhancement.extract).toBeCalledWith(embeddableState.enhancements.test);
|
||||
});
|
||||
|
||||
test('enhancement telemetry function gets called when calling embeddable telemetry', () => {
|
||||
start.telemetry(embeddableState, {});
|
||||
expect(embeddableEnhancement.telemetry).toBeCalledWith(embeddableState.enhancements.test, {});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { identity } from 'lodash';
|
||||
import { DataPublicPluginSetup, DataPublicPluginStart } from '../../data/public';
|
||||
import { getSavedObjectFinder } from '../../saved_objects/public';
|
||||
import { UiActionsSetup, UiActionsStart } from '../../ui_actions/public';
|
||||
|
@ -29,8 +30,15 @@ import {
|
|||
Plugin,
|
||||
ScopedHistory,
|
||||
PublicAppInfo,
|
||||
SavedObjectReference,
|
||||
} from '../../../core/public';
|
||||
import { EmbeddableFactoryRegistry, EmbeddableFactoryProvider } from './types';
|
||||
import {
|
||||
EmbeddableFactoryRegistry,
|
||||
EmbeddableFactoryProvider,
|
||||
EnhancementsRegistry,
|
||||
EnhancementRegistryDefinition,
|
||||
EnhancementRegistryItem,
|
||||
} from './types';
|
||||
import { bootstrap } from './bootstrap';
|
||||
import {
|
||||
EmbeddableFactory,
|
||||
|
@ -42,6 +50,12 @@ import {
|
|||
} from './lib';
|
||||
import { EmbeddableFactoryDefinition } from './lib/embeddables/embeddable_factory_definition';
|
||||
import { EmbeddableStateTransfer } from './lib/state_transfer';
|
||||
import {
|
||||
extractBaseEmbeddableInput,
|
||||
injectBaseEmbeddableInput,
|
||||
telemetryBaseEmbeddableInput,
|
||||
} from '../common/lib/migrate_base_input';
|
||||
import { PersistableState, SerializableState } from '../../kibana_utils/common';
|
||||
|
||||
export interface EmbeddableSetupDependencies {
|
||||
data: DataPublicPluginSetup;
|
||||
|
@ -63,10 +77,11 @@ export interface EmbeddableSetup {
|
|||
id: string,
|
||||
factory: EmbeddableFactoryDefinition<I, O, E>
|
||||
) => () => EmbeddableFactory<I, O, E>;
|
||||
registerEnhancement: (enhancement: EnhancementRegistryDefinition) => void;
|
||||
setCustomEmbeddableFactoryProvider: (customProvider: EmbeddableFactoryProvider) => void;
|
||||
}
|
||||
|
||||
export interface EmbeddableStart {
|
||||
export interface EmbeddableStart extends PersistableState<EmbeddableInput> {
|
||||
getEmbeddableFactory: <
|
||||
I extends EmbeddableInput = EmbeddableInput,
|
||||
O extends EmbeddableOutput = EmbeddableOutput,
|
||||
|
@ -88,6 +103,7 @@ export class EmbeddablePublicPlugin implements Plugin<EmbeddableSetup, Embeddabl
|
|||
EmbeddableFactoryDefinition
|
||||
> = new Map();
|
||||
private readonly embeddableFactories: EmbeddableFactoryRegistry = new Map();
|
||||
private readonly enhancements: EnhancementsRegistry = new Map();
|
||||
private customEmbeddableFactoryProvider?: EmbeddableFactoryProvider;
|
||||
private outgoingOnlyStateTransfer: EmbeddableStateTransfer = {} as EmbeddableStateTransfer;
|
||||
private isRegistryReady = false;
|
||||
|
@ -101,6 +117,7 @@ export class EmbeddablePublicPlugin implements Plugin<EmbeddableSetup, Embeddabl
|
|||
|
||||
return {
|
||||
registerEmbeddableFactory: this.registerEmbeddableFactory,
|
||||
registerEnhancement: this.registerEnhancement,
|
||||
setCustomEmbeddableFactoryProvider: (provider: EmbeddableFactoryProvider) => {
|
||||
if (this.customEmbeddableFactoryProvider) {
|
||||
throw new Error(
|
||||
|
@ -168,6 +185,9 @@ export class EmbeddablePublicPlugin implements Plugin<EmbeddableSetup, Embeddabl
|
|||
},
|
||||
EmbeddablePanel: getEmbeddablePanelHoc(),
|
||||
getEmbeddablePanel: getEmbeddablePanelHoc,
|
||||
telemetry: this.telemetry,
|
||||
extract: this.extract,
|
||||
inject: this.inject,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -177,6 +197,103 @@ export class EmbeddablePublicPlugin implements Plugin<EmbeddableSetup, Embeddabl
|
|||
}
|
||||
}
|
||||
|
||||
private telemetry = (state: EmbeddableInput, telemetryData: Record<string, any> = {}) => {
|
||||
const enhancements: Record<string, any> = 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 getEmbeddableFactories = () => {
|
||||
this.ensureFactoriesExist();
|
||||
return this.embeddableFactories.values();
|
||||
|
@ -215,12 +332,6 @@ export class EmbeddablePublicPlugin implements Plugin<EmbeddableSetup, Embeddabl
|
|||
this.ensureFactoryExists(embeddableFactoryId);
|
||||
const factory = this.embeddableFactories.get(embeddableFactoryId);
|
||||
|
||||
if (!factory) {
|
||||
throw new Error(
|
||||
`Embeddable factory [embeddableFactoryId = ${embeddableFactoryId}] does not exist.`
|
||||
);
|
||||
}
|
||||
|
||||
return factory as EmbeddableFactory<I, O, E>;
|
||||
};
|
||||
|
||||
|
|
|
@ -25,8 +25,24 @@ import {
|
|||
IEmbeddable,
|
||||
EmbeddableFactoryDefinition,
|
||||
} from './lib/embeddables';
|
||||
import {
|
||||
PersistableState,
|
||||
PersistableStateDefinition,
|
||||
SerializableState,
|
||||
} from '../../kibana_utils/common';
|
||||
|
||||
export type EmbeddableFactoryRegistry = Map<string, EmbeddableFactory>;
|
||||
export type EnhancementsRegistry = Map<string, EnhancementRegistryItem>;
|
||||
|
||||
export interface EnhancementRegistryDefinition<P extends SerializableState = SerializableState>
|
||||
extends PersistableStateDefinition<P> {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface EnhancementRegistryItem<P extends SerializableState = SerializableState>
|
||||
extends PersistableState<P> {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export type EmbeddableFactoryProvider = <
|
||||
I extends EmbeddableInput = EmbeddableInput,
|
||||
|
|
26
src/plugins/embeddable/server/index.ts
Normal file
26
src/plugins/embeddable/server/index.ts
Normal file
|
@ -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();
|
186
src/plugins/embeddable/server/plugin.ts
Normal file
186
src/plugins/embeddable/server/plugin.ts
Normal file
|
@ -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<object, object> {
|
||||
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<string, any> = {}) => {
|
||||
const enhancements: Record<string, any> = 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: [] };
|
||||
},
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
48
src/plugins/embeddable/server/types.ts
Normal file
48
src/plugins/embeddable/server/types.ts
Normal file
|
@ -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<string, EmbeddableRegistryItem>;
|
||||
export type EnhancementsRegistry = Map<string, EnhancementRegistryItem>;
|
||||
|
||||
export interface EnhancementRegistryDefinition<P extends SerializableState = SerializableState>
|
||||
extends PersistableStateDefinition<P> {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface EnhancementRegistryItem<P extends SerializableState = SerializableState>
|
||||
extends PersistableState<P> {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface EmbeddableRegistryDefinition<P extends EmbeddableInput = EmbeddableInput>
|
||||
extends PersistableStateDefinition<P> {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface EmbeddableRegistryItem<P extends EmbeddableInput = EmbeddableInput>
|
||||
extends PersistableState<P> {
|
||||
id: string;
|
||||
}
|
|
@ -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';
|
||||
|
|
54
src/plugins/kibana_utils/common/persistable_state/index.ts
Normal file
54
src/plugins/kibana_utils/common/persistable_state/index.ts
Normal file
|
@ -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<P extends SerializableState = SerializableState> {
|
||||
/**
|
||||
* function to extract telemetry information
|
||||
* @param state
|
||||
* @param collector
|
||||
*/
|
||||
telemetry: (state: P, collector: Record<string, any>) => Record<string, any>;
|
||||
/**
|
||||
* 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<P extends SerializableState = SerializableState> = Partial<
|
||||
PersistableState<P>
|
||||
>;
|
|
@ -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<Config extends object = object, Context = object> {
|
||||
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<Config extends object = object, Context = object>
|
|||
/**
|
||||
* Props provided to `CollectConfig` component on every re-render.
|
||||
*/
|
||||
export interface CollectConfigProps<Config extends object = object, Context = object> {
|
||||
export interface CollectConfigProps<
|
||||
Config extends SerializableState = SerializableState,
|
||||
Context = object
|
||||
> {
|
||||
/**
|
||||
* Current (latest) config of the item.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"rules": {
|
||||
"@typescript-eslint/consistent-type-definitions": 0
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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<Config>;
|
||||
|
|
|
@ -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<typeof APPLY_FILTER_TRIGGER>;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
5
x-pack/plugins/ui_actions_enhanced/.eslintrc.json
Normal file
5
x-pack/plugins/ui_actions_enhanced/.eslintrc.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"rules": {
|
||||
"@typescript-eslint/consistent-type-definitions": 0
|
||||
}
|
||||
}
|
28
x-pack/plugins/ui_actions_enhanced/common/types.ts
Normal file
28
x-pack/plugins/ui_actions_enhanced/common/types.ts
Normal file
|
@ -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<Config extends BaseActionConfig = BaseActionConfig> = {
|
||||
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[];
|
||||
};
|
|
@ -7,7 +7,7 @@
|
|||
"uiActions",
|
||||
"licensing"
|
||||
],
|
||||
"server": false,
|
||||
"server": true,
|
||||
"ui": true,
|
||||
"requiredBundles": [
|
||||
"kibanaUtils",
|
||||
|
|
|
@ -31,7 +31,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<
|
||||
|
@ -57,12 +57,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
|
||||
|
@ -219,9 +219,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[];
|
||||
|
|
|
@ -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<DashboardDrilldownConfig>) {
|
||||
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<UrlDrilldownConfig>) {
|
||||
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<any>
|
||||
>) 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<ActionFactory<any>> }) {
|
||||
const [state, setState] = useState<{
|
||||
currentActionFactory?: ActionFactory;
|
||||
config?: ActionBaseConfig;
|
||||
config?: BaseActionConfig;
|
||||
selectedTriggers?: TriggerId[];
|
||||
}>({});
|
||||
|
||||
|
|
|
@ -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[]) => {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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[],
|
||||
};
|
||||
|
|
|
@ -60,7 +60,7 @@ class MockDynamicActionManager implements PublicMethodsOf<DynamicActionManager>
|
|||
|
||||
async updateEvent(
|
||||
eventId: string,
|
||||
action: UiActionsEnhancedSerializedAction<unknown>,
|
||||
action: UiActionsEnhancedSerializedAction,
|
||||
triggers: Array<keyof TriggerContextMapping>
|
||||
) {
|
||||
const state = this.state.get();
|
||||
|
|
|
@ -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 (
|
||||
<FlyoutDrilldownWizard
|
||||
drilldownActionFactories={[urlFactory as ActionFactory, dashboardFactory as ActionFactory]}
|
||||
{...otherProps}
|
||||
/>
|
||||
);
|
||||
return <FlyoutDrilldownWizard drilldownActionFactories={mockActionFactories} {...otherProps} />;
|
||||
})
|
||||
.add('open in flyout - create', () => {
|
||||
return (
|
||||
<EuiFlyout onClose={() => {}}>
|
||||
<FlyoutDrilldownWizard
|
||||
drilldownActionFactories={[
|
||||
urlFactory as ActionFactory,
|
||||
dashboardFactory as ActionFactory,
|
||||
]}
|
||||
{...otherProps}
|
||||
/>
|
||||
<FlyoutDrilldownWizard drilldownActionFactories={mockActionFactories} {...otherProps} />
|
||||
</EuiFlyout>
|
||||
);
|
||||
})
|
||||
|
@ -48,13 +36,10 @@ storiesOf('components/FlyoutDrilldownWizard', module)
|
|||
return (
|
||||
<EuiFlyout onClose={() => {}}>
|
||||
<FlyoutDrilldownWizard
|
||||
drilldownActionFactories={[
|
||||
urlFactory as ActionFactory,
|
||||
dashboardFactory as ActionFactory,
|
||||
]}
|
||||
drilldownActionFactories={mockActionFactories}
|
||||
initialDrilldownWizardConfig={{
|
||||
name: 'My fancy drilldown',
|
||||
actionFactory: urlFactory as any,
|
||||
actionFactory: mockActionFactories[1],
|
||||
actionConfig: {
|
||||
url: 'https://elastic.co',
|
||||
openInNewTab: true,
|
||||
|
@ -70,10 +55,10 @@ storiesOf('components/FlyoutDrilldownWizard', module)
|
|||
return (
|
||||
<EuiFlyout onClose={() => {}}>
|
||||
<FlyoutDrilldownWizard
|
||||
drilldownActionFactories={[dashboardFactory as ActionFactory]}
|
||||
drilldownActionFactories={[mockActionFactories[1]]}
|
||||
initialDrilldownWizardConfig={{
|
||||
name: 'My fancy drilldown',
|
||||
actionFactory: urlFactory as any,
|
||||
actionFactory: mockActionFactories[1],
|
||||
actionConfig: {
|
||||
url: 'https://elastic.co',
|
||||
openInNewTab: true,
|
||||
|
|
|
@ -16,11 +16,15 @@ import {
|
|||
txtEditDrilldownTitle,
|
||||
} from './i18n';
|
||||
import { DrilldownHelloBar } from '../drilldown_hello_bar';
|
||||
import { ActionFactory, BaseActionFactoryContext } from '../../../dynamic_actions';
|
||||
import {
|
||||
ActionFactory,
|
||||
BaseActionConfig,
|
||||
BaseActionFactoryContext,
|
||||
} from '../../../dynamic_actions';
|
||||
import { Trigger, TriggerId } from '../../../../../../../src/plugins/ui_actions/public';
|
||||
import { ActionFactoryPlaceContext } from '../types';
|
||||
|
||||
export interface DrilldownWizardConfig<ActionConfig extends object = object> {
|
||||
export interface DrilldownWizardConfig<ActionConfig extends BaseActionConfig = BaseActionConfig> {
|
||||
name: string;
|
||||
actionFactory?: ActionFactory;
|
||||
actionConfig?: ActionConfig;
|
||||
|
@ -28,7 +32,7 @@ export interface DrilldownWizardConfig<ActionConfig extends object = object> {
|
|||
}
|
||||
|
||||
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<CurrentActionConfig extends object = object>({
|
||||
export function FlyoutDrilldownWizard<
|
||||
CurrentActionConfig extends BaseActionConfig = BaseActionConfig
|
||||
>({
|
||||
onClose,
|
||||
onBack,
|
||||
onSubmit = () => {},
|
||||
|
|
|
@ -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[];
|
||||
|
||||
|
|
|
@ -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<SupportedTriggers> = {
|
||||
triggers: SupportedTriggers[];
|
||||
},
|
||||
ExecutionContext extends TriggerContextMapping[SupportedTriggers] = TriggerContextMapping[SupportedTriggers]
|
||||
> {
|
||||
> extends PersistableStateDefinition<SerializedEvent> {
|
||||
/**
|
||||
* Globally unique identifier for this drilldown.
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<SupportedTriggers> = {
|
||||
triggers: SupportedTriggers[];
|
||||
},
|
||||
ActionContext extends TriggerContextMapping[SupportedTriggers] = TriggerContextMapping[SupportedTriggers]
|
||||
> implements Omit<Presentable<FactoryContext>, 'getHref'>, Configurable<Config, FactoryContext> {
|
||||
> implements
|
||||
Omit<Presentable<FactoryContext>, 'getHref'>,
|
||||
Configurable<Config, FactoryContext>,
|
||||
PersistableState<SerializedEvent> {
|
||||
constructor(
|
||||
protected readonly def: ActionFactoryDefinition<
|
||||
Config,
|
||||
|
@ -121,4 +131,16 @@ export class ActionFactory<
|
|||
);
|
||||
});
|
||||
}
|
||||
|
||||
public telemetry(state: SerializedEvent, telemetryData: Record<string, any>) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<SupportedTriggers> = {
|
||||
triggers: SupportedTriggers[];
|
||||
},
|
||||
ActionContext extends TriggerContextMapping[SupportedTriggers] = TriggerContextMapping[SupportedTriggers]
|
||||
> extends Partial<Omit<Presentable<FactoryContext>, 'getHref'>>,
|
||||
Configurable<Config, FactoryContext> {
|
||||
Configurable<Config, FactoryContext>,
|
||||
PersistableStateDefinition<SerializedEvent> {
|
||||
/**
|
||||
* 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
|
||||
|
|
|
@ -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<string, any>) => {
|
||||
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<SerializableState>;
|
||||
};
|
|
@ -250,7 +250,7 @@ describe('DynamicActionManager', () => {
|
|||
uiActions.registerActionFactory(actionFactoryDefinition1);
|
||||
await manager.start();
|
||||
|
||||
const action: SerializedAction<unknown> = {
|
||||
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<unknown> = {
|
||||
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<unknown> = {
|
||||
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<unknown> = {
|
||||
const action: SerializedAction = {
|
||||
factoryId: actionFactoryDefinition1.id,
|
||||
name: 'foo',
|
||||
config: {},
|
||||
|
@ -348,7 +348,7 @@ describe('DynamicActionManager', () => {
|
|||
uiActions.registerActionFactory(actionFactoryDefinition1);
|
||||
await manager.start();
|
||||
|
||||
const action: SerializedAction<unknown> = {
|
||||
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<unknown> = {
|
||||
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<unknown> = {
|
||||
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<unknown> = {
|
||||
const action: SerializedAction = {
|
||||
factoryId: actionFactoryDefinition1.id,
|
||||
name: 'foo',
|
||||
config: {},
|
||||
|
@ -432,7 +432,7 @@ describe('DynamicActionManager', () => {
|
|||
uiActions.registerActionFactory(actionFactoryDefinition1);
|
||||
await manager.start();
|
||||
|
||||
const action: SerializedAction<unknown> = {
|
||||
const action: SerializedAction = {
|
||||
factoryId: actionFactoryDefinition1.id,
|
||||
name: 'foo',
|
||||
config: {},
|
||||
|
@ -457,7 +457,7 @@ describe('DynamicActionManager', () => {
|
|||
|
||||
expect(registeredAction1.getDisplayName()).toBe('Action 3');
|
||||
|
||||
const action: SerializedAction<unknown> = {
|
||||
const action: SerializedAction = {
|
||||
factoryId: actionFactoryDefinition2.id,
|
||||
name: 'foo',
|
||||
config: {},
|
||||
|
@ -479,7 +479,7 @@ describe('DynamicActionManager', () => {
|
|||
uiActions.registerActionFactory(actionFactoryDefinition2);
|
||||
await manager.start();
|
||||
|
||||
const action: SerializedAction<unknown> = {
|
||||
const action: SerializedAction = {
|
||||
factoryId: actionFactoryDefinition2.id,
|
||||
name: 'foo',
|
||||
config: {},
|
||||
|
@ -505,7 +505,7 @@ describe('DynamicActionManager', () => {
|
|||
uiActions.registerActionFactory(actionFactoryDefinition2);
|
||||
await manager.start();
|
||||
|
||||
const action: SerializedAction<unknown> = {
|
||||
const action: SerializedAction = {
|
||||
factoryId: actionFactoryDefinition2.id,
|
||||
name: 'foo',
|
||||
config: {},
|
||||
|
@ -524,7 +524,7 @@ describe('DynamicActionManager', () => {
|
|||
uiActions.registerActionFactory(actionFactoryDefinition2);
|
||||
await manager.start();
|
||||
|
||||
const action: SerializedAction<unknown> = {
|
||||
const action: SerializedAction = {
|
||||
factoryId: actionFactoryDefinition2.id,
|
||||
name: 'foo',
|
||||
config: {},
|
||||
|
@ -552,7 +552,7 @@ describe('DynamicActionManager', () => {
|
|||
uiActions.registerActionFactory(actionFactoryDefinition2);
|
||||
await manager.start();
|
||||
|
||||
const action: SerializedAction<unknown> = {
|
||||
const action: SerializedAction = {
|
||||
factoryId: actionFactoryDefinition2.id,
|
||||
name: 'foo',
|
||||
config: {},
|
||||
|
@ -580,7 +580,7 @@ describe('DynamicActionManager', () => {
|
|||
|
||||
expect(registeredAction1.getDisplayName()).toBe('Action 3');
|
||||
|
||||
const action: SerializedAction<unknown> = {
|
||||
const action: SerializedAction = {
|
||||
factoryId: actionFactoryDefinition2.id,
|
||||
name: 'foo',
|
||||
config: {},
|
||||
|
@ -604,7 +604,7 @@ describe('DynamicActionManager', () => {
|
|||
uiActions.registerActionFactory(actionFactoryDefinition2);
|
||||
await manager.start();
|
||||
|
||||
const action: SerializedAction<unknown> = {
|
||||
const action: SerializedAction = {
|
||||
factoryId: actionFactoryDefinition2.id,
|
||||
name: 'foo',
|
||||
config: {},
|
||||
|
|
|
@ -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<object>);
|
||||
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<unknown>,
|
||||
triggers: Array<keyof TriggerContextMapping>
|
||||
) {
|
||||
public async createEvent(action: SerializedAction, triggers: Array<keyof TriggerContextMapping>) {
|
||||
const event: SerializedEvent = {
|
||||
eventId: uuidv4(),
|
||||
triggers,
|
||||
|
@ -231,7 +228,7 @@ export class DynamicActionManager {
|
|||
*/
|
||||
public async updateEvent(
|
||||
eventId: string,
|
||||
action: SerializedAction<unknown>,
|
||||
action: SerializedAction,
|
||||
triggers: Array<keyof TriggerContextMapping>
|
||||
) {
|
||||
const event: SerializedEvent = {
|
||||
|
|
|
@ -5,21 +5,9 @@
|
|||
*/
|
||||
|
||||
import { TriggerId } from '../../../../../src/plugins/ui_actions/public';
|
||||
import { SerializedAction, SerializedEvent, BaseActionConfig } from '../../common/types';
|
||||
|
||||
export interface SerializedAction<Config = unknown> {
|
||||
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
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<UiActionsServiceEnhancements, 'getActionFactory' | 'getActionFactories'> {
|
||||
Pick<
|
||||
UiActionsServiceEnhancements,
|
||||
'getActionFactory' | 'getActionFactories' | 'telemetry' | 'extract' | 'inject'
|
||||
> {
|
||||
FlyoutManageDrilldowns: ReturnType<typeof createFlyoutManageDrilldowns>;
|
||||
}
|
||||
|
||||
|
@ -87,7 +91,7 @@ export class AdvancedUiActionsPublicPlugin
|
|||
|
||||
public setup(
|
||||
core: CoreSetup<StartDependencies>,
|
||||
{ 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,
|
||||
|
|
|
@ -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(() => {
|
||||
|
|
|
@ -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<DynamicActionsState> {
|
||||
protected readonly actionFactories: ActionFactoryRegistry;
|
||||
protected readonly deps: Omit<UiActionsServiceEnhancementsParams, 'actionFactories'>;
|
||||
|
||||
|
@ -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<SupportedTriggers> = {
|
||||
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<SupportedTriggers> = {
|
||||
triggers: SupportedTriggers[];
|
||||
|
@ -102,6 +111,9 @@ export class UiActionsServiceEnhancements {
|
|||
licenseFeatureName,
|
||||
supportedTriggers,
|
||||
isCompatible,
|
||||
telemetry,
|
||||
extract,
|
||||
inject,
|
||||
}: DrilldownDefinition<Config, SupportedTriggers, FactoryContext, ExecutionContext>): void => {
|
||||
const actionFactory: ActionFactoryDefinition<
|
||||
Config,
|
||||
|
@ -119,6 +131,9 @@ export class UiActionsServiceEnhancements {
|
|||
isConfigValid,
|
||||
getDisplayName,
|
||||
supportedTriggers,
|
||||
telemetry,
|
||||
extract,
|
||||
inject,
|
||||
getIconType: () => euiIcon,
|
||||
isCompatible: async () => true,
|
||||
create: (serializedAction) => ({
|
||||
|
@ -151,4 +166,43 @@ export class UiActionsServiceEnhancements {
|
|||
);
|
||||
});
|
||||
};
|
||||
|
||||
public readonly telemetry = (state: DynamicActionsState, telemetry: Record<string, any> = {}) => {
|
||||
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;
|
||||
}),
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<string, any>) => {
|
||||
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;
|
||||
};
|
29
x-pack/plugins/ui_actions_enhanced/server/index.ts
Normal file
29
x-pack/plugins/ui_actions_enhanced/server/index.ts
Normal file
|
@ -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';
|
107
x-pack/plugins/ui_actions_enhanced/server/plugin.ts
Normal file
107
x-pack/plugins/ui_actions_enhanced/server/plugin.ts
Normal file
|
@ -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<SetupContract, StartContract, SetupDependencies> {
|
||||
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<string, any> = {}) => {
|
||||
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;
|
||||
}),
|
||||
};
|
||||
};
|
||||
}
|
26
x-pack/plugins/ui_actions_enhanced/server/types.ts
Normal file
26
x-pack/plugins/ui_actions_enhanced/server/types.ts
Normal file
|
@ -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<string, ActionFactory>;
|
||||
|
||||
export interface ActionFactoryDefinition<P extends SerializedEvent = SerializedEvent>
|
||||
extends PersistableStateDefinition<P> {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface ActionFactory<P extends SerializedEvent = SerializedEvent>
|
||||
extends PersistableState<P> {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export { SerializedEvent, SerializedAction, DynamicActionsState };
|
Loading…
Add table
Add a link
Reference in a new issue