Typescript index pattern field editor (#63495) (#64609)

* Typescript index pattern field editor
This commit is contained in:
Matthew Kime 2020-04-27 21:03:43 -05:00 committed by GitHub
parent 5817db864c
commit 1d9eab9aa6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
123 changed files with 1706 additions and 705 deletions

View file

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [Field](./kibana-plugin-plugins-data-public.field.md) &gt; [conflictDescriptions](./kibana-plugin-plugins-data-public.field.conflictdescriptions.md)
## Field.conflictDescriptions property
<b>Signature:</b>
```typescript
conflictDescriptions?: Record<string, string[]>;
```

View file

@ -22,6 +22,7 @@ export declare class Field implements IFieldType
| --- | --- | --- | --- |
| [$$spec](./kibana-plugin-plugins-data-public.field.__spec.md) | | <code>FieldSpec</code> | |
| [aggregatable](./kibana-plugin-plugins-data-public.field.aggregatable.md) | | <code>boolean</code> | |
| [conflictDescriptions](./kibana-plugin-plugins-data-public.field.conflictdescriptions.md) | | <code>Record&lt;string, string[]&gt;</code> | |
| [count](./kibana-plugin-plugins-data-public.field.count.md) | | <code>number</code> | |
| [displayName](./kibana-plugin-plugins-data-public.field.displayname.md) | | <code>string</code> | |
| [esTypes](./kibana-plugin-plugins-data-public.field.estypes.md) | | <code>string[]</code> | |

View file

@ -0,0 +1,21 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [FieldFormat](./kibana-plugin-plugins-data-public.fieldformat.md) &gt; [(constructor)](./kibana-plugin-plugins-data-public.fieldformat._constructor_.md)
## FieldFormat.(constructor)
Constructs a new instance of the `FieldFormat` class
<b>Signature:</b>
```typescript
constructor(_params?: IFieldFormatMetaParams, getConfig?: FieldFormatsGetConfigFn);
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| \_params | <code>IFieldFormatMetaParams</code> | |
| getConfig | <code>FieldFormatsGetConfigFn</code> | |

View file

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [FieldFormat](./kibana-plugin-plugins-data-public.fieldformat.md) &gt; [\_params](./kibana-plugin-plugins-data-public.fieldformat._params.md)
## FieldFormat.\_params property
<b>Signature:</b>
```typescript
protected readonly _params: any;
```

View file

@ -0,0 +1,26 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [FieldFormat](./kibana-plugin-plugins-data-public.fieldformat.md) &gt; [convert](./kibana-plugin-plugins-data-public.fieldformat.convert.md)
## FieldFormat.convert() method
Convert a raw value to a formatted string
<b>Signature:</b>
```typescript
convert(value: any, contentType?: FieldFormatsContentType, options?: HtmlContextTypeOptions | TextContextTypeOptions): string;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| value | <code>any</code> | |
| contentType | <code>FieldFormatsContentType</code> | |
| options | <code>HtmlContextTypeOptions &#124; TextContextTypeOptions</code> | |
<b>Returns:</b>
`string`

View file

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [FieldFormat](./kibana-plugin-plugins-data-public.fieldformat.md) &gt; [convertObject](./kibana-plugin-plugins-data-public.fieldformat.convertobject.md)
## FieldFormat.convertObject property
{<!-- -->FieldFormatConvert<!-- -->} have to remove the private because of https://github.com/Microsoft/TypeScript/issues/17293
<b>Signature:</b>
```typescript
convertObject: FieldFormatConvert | undefined;
```

View file

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [FieldFormat](./kibana-plugin-plugins-data-public.fieldformat.md) &gt; [fieldType](./kibana-plugin-plugins-data-public.fieldformat.fieldtype.md)
## FieldFormat.fieldType property
{<!-- -->string<!-- -->} - Field Format Type
<b>Signature:</b>
```typescript
static fieldType: string | string[];
```

View file

@ -0,0 +1,22 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [FieldFormat](./kibana-plugin-plugins-data-public.fieldformat.md) &gt; [from](./kibana-plugin-plugins-data-public.fieldformat.from.md)
## FieldFormat.from() method
<b>Signature:</b>
```typescript
static from(convertFn: FieldFormatConvertFunction): FieldFormatInstanceType;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| convertFn | <code>FieldFormatConvertFunction</code> | |
<b>Returns:</b>
`FieldFormatInstanceType`

View file

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [FieldFormat](./kibana-plugin-plugins-data-public.fieldformat.md) &gt; [getConfig](./kibana-plugin-plugins-data-public.fieldformat.getconfig.md)
## FieldFormat.getConfig property
<b>Signature:</b>
```typescript
protected getConfig: FieldFormatsGetConfigFn | undefined;
```

View file

@ -0,0 +1,24 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [FieldFormat](./kibana-plugin-plugins-data-public.fieldformat.md) &gt; [getConverterFor](./kibana-plugin-plugins-data-public.fieldformat.getconverterfor.md)
## FieldFormat.getConverterFor() method
Get a convert function that is bound to a specific contentType
<b>Signature:</b>
```typescript
getConverterFor(contentType?: FieldFormatsContentType): FieldFormatConvertFunction;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| contentType | <code>FieldFormatsContentType</code> | |
<b>Returns:</b>
`FieldFormatConvertFunction`

View file

@ -0,0 +1,17 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [FieldFormat](./kibana-plugin-plugins-data-public.fieldformat.md) &gt; [getParamDefaults](./kibana-plugin-plugins-data-public.fieldformat.getparamdefaults.md)
## FieldFormat.getParamDefaults() method
Get parameter defaults {<!-- -->object<!-- -->} - parameter defaults
<b>Signature:</b>
```typescript
getParamDefaults(): Record<string, any>;
```
<b>Returns:</b>
`Record<string, any>`

View file

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [FieldFormat](./kibana-plugin-plugins-data-public.fieldformat.md) &gt; [htmlConvert](./kibana-plugin-plugins-data-public.fieldformat.htmlconvert.md)
## FieldFormat.htmlConvert property
{<!-- -->htmlConvert<!-- -->} have to remove the protected because of https://github.com/Microsoft/TypeScript/issues/17293
<b>Signature:</b>
```typescript
htmlConvert: HtmlContextTypeConvert | undefined;
```

View file

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [FieldFormat](./kibana-plugin-plugins-data-public.fieldformat.md) &gt; [id](./kibana-plugin-plugins-data-public.fieldformat.id.md)
## FieldFormat.id property
{<!-- -->string<!-- -->} - Field Format Id
<b>Signature:</b>
```typescript
static id: string;
```

View file

@ -0,0 +1,22 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [FieldFormat](./kibana-plugin-plugins-data-public.fieldformat.md) &gt; [isInstanceOfFieldFormat](./kibana-plugin-plugins-data-public.fieldformat.isinstanceoffieldformat.md)
## FieldFormat.isInstanceOfFieldFormat() method
<b>Signature:</b>
```typescript
static isInstanceOfFieldFormat(fieldFormat: any): fieldFormat is FieldFormat;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| fieldFormat | <code>any</code> | |
<b>Returns:</b>
`fieldFormat is FieldFormat`

View file

@ -0,0 +1,46 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [FieldFormat](./kibana-plugin-plugins-data-public.fieldformat.md)
## FieldFormat class
<b>Signature:</b>
```typescript
export declare abstract class FieldFormat
```
## Constructors
| Constructor | Modifiers | Description |
| --- | --- | --- |
| [(constructor)(\_params, getConfig)](./kibana-plugin-plugins-data-public.fieldformat._constructor_.md) | | Constructs a new instance of the <code>FieldFormat</code> class |
## Properties
| Property | Modifiers | Type | Description |
| --- | --- | --- | --- |
| [\_params](./kibana-plugin-plugins-data-public.fieldformat._params.md) | | <code>any</code> | |
| [convertObject](./kibana-plugin-plugins-data-public.fieldformat.convertobject.md) | | <code>FieldFormatConvert &#124; undefined</code> | {<!-- -->FieldFormatConvert<!-- -->} have to remove the private because of https://github.com/Microsoft/TypeScript/issues/17293 |
| [fieldType](./kibana-plugin-plugins-data-public.fieldformat.fieldtype.md) | <code>static</code> | <code>string &#124; string[]</code> | {<!-- -->string<!-- -->} - Field Format Type |
| [getConfig](./kibana-plugin-plugins-data-public.fieldformat.getconfig.md) | | <code>FieldFormatsGetConfigFn &#124; undefined</code> | |
| [htmlConvert](./kibana-plugin-plugins-data-public.fieldformat.htmlconvert.md) | | <code>HtmlContextTypeConvert &#124; undefined</code> | {<!-- -->htmlConvert<!-- -->} have to remove the protected because of https://github.com/Microsoft/TypeScript/issues/17293 |
| [id](./kibana-plugin-plugins-data-public.fieldformat.id.md) | <code>static</code> | <code>string</code> | {<!-- -->string<!-- -->} - Field Format Id |
| [textConvert](./kibana-plugin-plugins-data-public.fieldformat.textconvert.md) | | <code>TextContextTypeConvert &#124; undefined</code> | {<!-- -->textConvert<!-- -->} have to remove the protected because of https://github.com/Microsoft/TypeScript/issues/17293 |
| [title](./kibana-plugin-plugins-data-public.fieldformat.title.md) | <code>static</code> | <code>string</code> | {<!-- -->string<!-- -->} - Field Format Title |
| [type](./kibana-plugin-plugins-data-public.fieldformat.type.md) | | <code>any</code> | {<!-- -->Function<!-- -->} - ref to child class |
## Methods
| Method | Modifiers | Description |
| --- | --- | --- |
| [convert(value, contentType, options)](./kibana-plugin-plugins-data-public.fieldformat.convert.md) | | Convert a raw value to a formatted string |
| [from(convertFn)](./kibana-plugin-plugins-data-public.fieldformat.from.md) | <code>static</code> | |
| [getConverterFor(contentType)](./kibana-plugin-plugins-data-public.fieldformat.getconverterfor.md) | | Get a convert function that is bound to a specific contentType |
| [getParamDefaults()](./kibana-plugin-plugins-data-public.fieldformat.getparamdefaults.md) | | Get parameter defaults {<!-- -->object<!-- -->} - parameter defaults |
| [isInstanceOfFieldFormat(fieldFormat)](./kibana-plugin-plugins-data-public.fieldformat.isinstanceoffieldformat.md) | <code>static</code> | |
| [param(name)](./kibana-plugin-plugins-data-public.fieldformat.param.md) | | Get the value of a param. This value may be a default value. |
| [params()](./kibana-plugin-plugins-data-public.fieldformat.params.md) | | Get all of the params in a single object {<!-- -->object<!-- -->} |
| [setupContentType()](./kibana-plugin-plugins-data-public.fieldformat.setupcontenttype.md) | | |
| [toJSON()](./kibana-plugin-plugins-data-public.fieldformat.tojson.md) | | Serialize this format to a simple POJO, with only the params that are not default {<!-- -->object<!-- -->} |

View file

@ -0,0 +1,24 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [FieldFormat](./kibana-plugin-plugins-data-public.fieldformat.md) &gt; [param](./kibana-plugin-plugins-data-public.fieldformat.param.md)
## FieldFormat.param() method
Get the value of a param. This value may be a default value.
<b>Signature:</b>
```typescript
param(name: string): any;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| name | <code>string</code> | |
<b>Returns:</b>
`any`

View file

@ -0,0 +1,17 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [FieldFormat](./kibana-plugin-plugins-data-public.fieldformat.md) &gt; [params](./kibana-plugin-plugins-data-public.fieldformat.params.md)
## FieldFormat.params() method
Get all of the params in a single object {<!-- -->object<!-- -->}
<b>Signature:</b>
```typescript
params(): Record<string, any>;
```
<b>Returns:</b>
`Record<string, any>`

View file

@ -0,0 +1,15 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [FieldFormat](./kibana-plugin-plugins-data-public.fieldformat.md) &gt; [setupContentType](./kibana-plugin-plugins-data-public.fieldformat.setupcontenttype.md)
## FieldFormat.setupContentType() method
<b>Signature:</b>
```typescript
setupContentType(): FieldFormatConvert;
```
<b>Returns:</b>
`FieldFormatConvert`

View file

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [FieldFormat](./kibana-plugin-plugins-data-public.fieldformat.md) &gt; [textConvert](./kibana-plugin-plugins-data-public.fieldformat.textconvert.md)
## FieldFormat.textConvert property
{<!-- -->textConvert<!-- -->} have to remove the protected because of https://github.com/Microsoft/TypeScript/issues/17293
<b>Signature:</b>
```typescript
textConvert: TextContextTypeConvert | undefined;
```

View file

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [FieldFormat](./kibana-plugin-plugins-data-public.fieldformat.md) &gt; [title](./kibana-plugin-plugins-data-public.fieldformat.title.md)
## FieldFormat.title property
{<!-- -->string<!-- -->} - Field Format Title
<b>Signature:</b>
```typescript
static title: string;
```

View file

@ -0,0 +1,25 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [FieldFormat](./kibana-plugin-plugins-data-public.fieldformat.md) &gt; [toJSON](./kibana-plugin-plugins-data-public.fieldformat.tojson.md)
## FieldFormat.toJSON() method
Serialize this format to a simple POJO, with only the params that are not default
{<!-- -->object<!-- -->}
<b>Signature:</b>
```typescript
toJSON(): {
id: unknown;
params: _.Dictionary<unknown> | undefined;
};
```
<b>Returns:</b>
`{
id: unknown;
params: _.Dictionary<unknown> | undefined;
}`

View file

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [FieldFormat](./kibana-plugin-plugins-data-public.fieldformat.md) &gt; [type](./kibana-plugin-plugins-data-public.fieldformat.type.md)
## FieldFormat.type property
{<!-- -->Function<!-- -->} - ref to child class
<b>Signature:</b>
```typescript
type: any;
```

View file

@ -12,6 +12,7 @@
| [AggTypeFieldFilters](./kibana-plugin-plugins-data-public.aggtypefieldfilters.md) | A registry to store which are used to filter down available fields for a specific visualization and . |
| [AggTypeFilters](./kibana-plugin-plugins-data-public.aggtypefilters.md) | A registry to store which are used to filter down available aggregations for a specific visualization and . |
| [Field](./kibana-plugin-plugins-data-public.field.md) | |
| [FieldFormat](./kibana-plugin-plugins-data-public.fieldformat.md) | |
| [FilterManager](./kibana-plugin-plugins-data-public.filtermanager.md) | |
| [IndexPattern](./kibana-plugin-plugins-data-public.indexpattern.md) | |
| [IndexPatternFieldList](./kibana-plugin-plugins-data-public.indexpatternfieldlist.md) | |

View file

@ -9,7 +9,7 @@
```typescript
setup(core: CoreSetup, { usageCollection }: DataPluginSetupDependencies): {
fieldFormats: {
register: (customFieldFormat: import("../common").FieldFormatInstanceType) => number;
register: (customFieldFormat: import("../public").FieldFormatInstanceType) => number;
};
search: ISearchSetup;
};
@ -26,7 +26,7 @@ setup(core: CoreSetup, { usageCollection }: DataPluginSetupDependencies): {
`{
fieldFormats: {
register: (customFieldFormat: import("../common").FieldFormatInstanceType) => number;
register: (customFieldFormat: import("../public").FieldFormatInstanceType) => number;
};
search: ISearchSetup;
}`

View file

@ -23,6 +23,7 @@ import { FieldEditor } from 'ui/field_editor';
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { HttpStart, DocLinksStart } from 'src/core/public';
import { IndexHeader } from '../index_header';
import { IndexPattern, IndexPatternField } from '../../../../../../../../../plugins/data/public';
import { ChromeDocTitle, NotificationsStart } from '../../../../../../../../../core/public';
@ -37,7 +38,8 @@ interface CreateEditFieldProps extends RouteComponentProps {
services: {
notifications: NotificationsStart;
docTitle: ChromeDocTitle;
http: Function;
getHttpStart: () => HttpStart;
docLinksScriptedFields: DocLinksStart['links']['scriptedFields'];
};
}
@ -68,16 +70,14 @@ export const CreateEditField = withRouter(
const url = `/management/kibana/index_patterns/${indexPattern.id}`;
if (mode === 'edit') {
if (!field) {
const message = i18n.translate('kbn.management.editIndexPattern.scripted.noFieldLabel', {
defaultMessage:
"'{indexPatternTitle}' index pattern doesn't have a scripted field called '{fieldName}'",
values: { indexPatternTitle: indexPattern.title, fieldName },
});
services.notifications.toasts.addWarning(message);
history.push(url);
}
if (mode === 'edit' && !field) {
const message = i18n.translate('kbn.management.editIndexPattern.scripted.noFieldLabel', {
defaultMessage:
"'{indexPatternTitle}' index pattern doesn't have a scripted field called '{fieldName}'",
values: { indexPatternTitle: indexPattern.title, fieldName },
});
services.notifications.toasts.addWarning(message);
history.push(url);
}
const docFieldName = field?.name || newFieldPlaceholder;
@ -88,24 +88,29 @@ export const CreateEditField = withRouter(
history.push(`${url}?_a=(tab:${field?.scripted ? TAB_SCRIPTED_FIELDS : TAB_INDEXED_FIELDS})`);
};
return (
<EuiFlexGroup direction="column">
<EuiFlexItem>
<IndexHeader indexPattern={indexPattern} defaultIndex={getConfig('defaultIndex')} />
</EuiFlexItem>
<EuiFlexItem>
<FieldEditor
indexPattern={indexPattern}
field={field}
helpers={{
getConfig,
$http: services.http,
fieldFormatEditors,
redirectAway,
}}
/>
</EuiFlexItem>
</EuiFlexGroup>
);
if (field) {
return (
<EuiFlexGroup direction="column">
<EuiFlexItem>
<IndexHeader indexPattern={indexPattern} defaultIndex={getConfig('defaultIndex')} />
</EuiFlexItem>
<EuiFlexItem>
<FieldEditor
indexPattern={indexPattern}
field={field}
helpers={{
getConfig,
getHttpStart: services.getHttpStart,
fieldFormatEditors,
redirectAway,
docLinksScriptedFields: services.docLinksScriptedFields,
}}
/>
</EuiFlexItem>
</EuiFlexGroup>
);
} else {
return <></>;
}
}
);

View file

@ -95,7 +95,7 @@ uiModules
// routes for create edit field. Will be removed after migartion all component to react.
const REACT_FIELD_EDITOR_ID = 'reactFieldEditor';
const renderCreateEditField = ($scope, $route, getConfig, $http, fieldFormatEditors) => {
const renderCreateEditField = ($scope, $route, getConfig, fieldFormatEditors) => {
$scope.$$postDigest(() => {
const node = document.getElementById(REACT_FIELD_EDITOR_ID);
if (!node) {
@ -112,9 +112,10 @@ const renderCreateEditField = ($scope, $route, getConfig, $http, fieldFormatEdit
fieldFormatEditors={fieldFormatEditors}
getConfig={getConfig}
services={{
http: $http,
getHttpStart: () => npStart.core.http,
notifications: npStart.core.notifications,
docTitle: npStart.core.chrome.docTitle,
docLinksScriptedFields: npStart.core.docLinks.links.scriptedFields,
}}
/>
</I18nContext>
@ -162,11 +163,11 @@ uiRoutes
},
},
controllerAs: 'fieldSettings',
controller: function FieldEditorPageController($scope, $route, $http, Private, config) {
controller: function FieldEditorPageController($scope, $route, Private, config) {
const getConfig = (...args) => config.get(...args);
const fieldFormatEditors = Private(RegistryFieldFormatEditorsProvider);
renderCreateEditField($scope, $route, getConfig, $http, fieldFormatEditors);
renderCreateEditField($scope, $route, getConfig, fieldFormatEditors);
$scope.$on('$destroy', () => {
destroyCreateEditField();

View file

@ -19,10 +19,31 @@ exports[`FieldEditor should render create new scripted field correctly 1`] = `
isVisible={false}
/>
<scripting-warning-callOut
docLinksScriptedFields={
Object {
"luceneExpressions": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-expression.html",
"painless": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-painless.html",
"painlessApi": "https://www.elastic.co/guide/en/elasticsearch/painless/mocked-test-branch/painless-api-reference.html",
"painlessSyntax": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-painless-syntax.html",
"scriptAggs": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/search-aggregations.html#_values_source",
"scriptFields": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/search-request-script-fields.html",
}
}
isVisible={true}
/>
<ScriptingHelpFlyout
docLinksScriptedFields={
Object {
"luceneExpressions": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-expression.html",
"painless": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-painless.html",
"painlessApi": "https://www.elastic.co/guide/en/elasticsearch/painless/mocked-test-branch/painless-api-reference.html",
"painlessSyntax": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-painless-syntax.html",
"scriptAggs": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/search-aggregations.html#_values_source",
"scriptFields": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/search-request-script-fields.html",
}
}
executeScript={[Function]}
getHttpStart={[Function]}
indexPattern={
Object {
"fields": Array [
@ -112,15 +133,9 @@ exports[`FieldEditor should render create new scripted field correctly 1`] = `
}
label={
<FormattedMessage
defaultMessage="Format (Default: {defaultFormat})"
id="common.ui.fieldEditor.defaultFormatHeader"
values={
Object {
"defaultFormat": <eui-code>
Test format
</eui-code>,
}
}
defaultMessage="Format"
id="common.ui.fieldEditor.formatHeader"
values={Object {}}
/>
}
>
@ -134,8 +149,8 @@ exports[`FieldEditor should render create new scripted field correctly 1`] = `
"value": "",
},
Object {
"text": "Test format",
"value": "test_format",
"text": undefined,
"value": "",
},
]
}
@ -260,10 +275,31 @@ exports[`FieldEditor should render edit scripted field correctly 1`] = `
isVisible={false}
/>
<scripting-warning-callOut
docLinksScriptedFields={
Object {
"luceneExpressions": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-expression.html",
"painless": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-painless.html",
"painlessApi": "https://www.elastic.co/guide/en/elasticsearch/painless/mocked-test-branch/painless-api-reference.html",
"painlessSyntax": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-painless-syntax.html",
"scriptAggs": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/search-aggregations.html#_values_source",
"scriptFields": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/search-request-script-fields.html",
}
}
isVisible={true}
/>
<ScriptingHelpFlyout
docLinksScriptedFields={
Object {
"luceneExpressions": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-expression.html",
"painless": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-painless.html",
"painlessApi": "https://www.elastic.co/guide/en/elasticsearch/painless/mocked-test-branch/painless-api-reference.html",
"painlessSyntax": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-painless-syntax.html",
"scriptAggs": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/search-aggregations.html#_values_source",
"scriptFields": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/search-request-script-fields.html",
}
}
executeScript={[Function]}
getHttpStart={[Function]}
indexPattern={
Object {
"fields": Array [
@ -349,15 +385,9 @@ exports[`FieldEditor should render edit scripted field correctly 1`] = `
}
label={
<FormattedMessage
defaultMessage="Format (Default: {defaultFormat})"
id="common.ui.fieldEditor.defaultFormatHeader"
values={
Object {
"defaultFormat": <eui-code>
Test format
</eui-code>,
}
}
defaultMessage="Format"
id="common.ui.fieldEditor.formatHeader"
values={Object {}}
/>
}
>
@ -371,8 +401,8 @@ exports[`FieldEditor should render edit scripted field correctly 1`] = `
"value": "",
},
Object {
"text": "Test format",
"value": "test_format",
"text": undefined,
"value": "",
},
]
}
@ -508,10 +538,31 @@ exports[`FieldEditor should show conflict field warning 1`] = `
isVisible={false}
/>
<scripting-warning-callOut
docLinksScriptedFields={
Object {
"luceneExpressions": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-expression.html",
"painless": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-painless.html",
"painlessApi": "https://www.elastic.co/guide/en/elasticsearch/painless/mocked-test-branch/painless-api-reference.html",
"painlessSyntax": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-painless-syntax.html",
"scriptAggs": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/search-aggregations.html#_values_source",
"scriptFields": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/search-request-script-fields.html",
}
}
isVisible={true}
/>
<ScriptingHelpFlyout
docLinksScriptedFields={
Object {
"luceneExpressions": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-expression.html",
"painless": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-painless.html",
"painlessApi": "https://www.elastic.co/guide/en/elasticsearch/painless/mocked-test-branch/painless-api-reference.html",
"painlessSyntax": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-painless-syntax.html",
"scriptAggs": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/search-aggregations.html#_values_source",
"scriptFields": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/search-request-script-fields.html",
}
}
executeScript={[Function]}
getHttpStart={[Function]}
indexPattern={
Object {
"fields": Array [
@ -645,15 +696,9 @@ exports[`FieldEditor should show conflict field warning 1`] = `
}
label={
<FormattedMessage
defaultMessage="Format (Default: {defaultFormat})"
id="common.ui.fieldEditor.defaultFormatHeader"
values={
Object {
"defaultFormat": <eui-code>
Test format
</eui-code>,
}
}
defaultMessage="Format"
id="common.ui.fieldEditor.formatHeader"
values={Object {}}
/>
}
>
@ -667,8 +712,8 @@ exports[`FieldEditor should show conflict field warning 1`] = `
"value": "",
},
Object {
"text": "Test format",
"value": "test_format",
"text": undefined,
"value": "",
},
]
}
@ -793,10 +838,31 @@ exports[`FieldEditor should show deprecated lang warning 1`] = `
isVisible={false}
/>
<scripting-warning-callOut
docLinksScriptedFields={
Object {
"luceneExpressions": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-expression.html",
"painless": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-painless.html",
"painlessApi": "https://www.elastic.co/guide/en/elasticsearch/painless/mocked-test-branch/painless-api-reference.html",
"painlessSyntax": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-painless-syntax.html",
"scriptAggs": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/search-aggregations.html#_values_source",
"scriptFields": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/search-request-script-fields.html",
}
}
isVisible={true}
/>
<ScriptingHelpFlyout
docLinksScriptedFields={
Object {
"luceneExpressions": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-expression.html",
"painless": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-painless.html",
"painlessApi": "https://www.elastic.co/guide/en/elasticsearch/painless/mocked-test-branch/painless-api-reference.html",
"painlessSyntax": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-painless-syntax.html",
"scriptAggs": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/search-aggregations.html#_values_source",
"scriptFields": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/search-request-script-fields.html",
}
}
executeScript={[Function]}
getHttpStart={[Function]}
indexPattern={
Object {
"fields": Array [
@ -854,7 +920,7 @@ exports[`FieldEditor should show deprecated lang warning 1`] = `
testlang
</eui-code>,
"painlessLink": <eui-link
href="(docLink for scriptedFields.painless)"
href="https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-painless.html"
target="_blank"
>
<FormattedMessage
@ -972,15 +1038,9 @@ exports[`FieldEditor should show deprecated lang warning 1`] = `
}
label={
<FormattedMessage
defaultMessage="Format (Default: {defaultFormat})"
id="common.ui.fieldEditor.defaultFormatHeader"
values={
Object {
"defaultFormat": <eui-code>
Test format
</eui-code>,
}
}
defaultMessage="Format"
id="common.ui.fieldEditor.formatHeader"
values={Object {}}
/>
}
>
@ -994,8 +1054,8 @@ exports[`FieldEditor should show deprecated lang warning 1`] = `
"value": "",
},
Object {
"text": "Test format",
"value": "test_format",
"text": undefined,
"value": "",
},
]
}
@ -1131,10 +1191,31 @@ exports[`FieldEditor should show multiple type field warning with a table contai
isVisible={false}
/>
<scripting-warning-callOut
docLinksScriptedFields={
Object {
"luceneExpressions": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-expression.html",
"painless": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-painless.html",
"painlessApi": "https://www.elastic.co/guide/en/elasticsearch/painless/mocked-test-branch/painless-api-reference.html",
"painlessSyntax": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-painless-syntax.html",
"scriptAggs": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/search-aggregations.html#_values_source",
"scriptFields": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/search-request-script-fields.html",
}
}
isVisible={true}
/>
<ScriptingHelpFlyout
docLinksScriptedFields={
Object {
"luceneExpressions": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-expression.html",
"painless": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-painless.html",
"painlessApi": "https://www.elastic.co/guide/en/elasticsearch/painless/mocked-test-branch/painless-api-reference.html",
"painlessSyntax": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/modules-scripting-painless-syntax.html",
"scriptAggs": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/search-aggregations.html#_values_source",
"scriptFields": "https://www.elastic.co/guide/en/elasticsearch/reference/mocked-test-branch/search-request-script-fields.html",
}
}
executeScript={[Function]}
getHttpStart={[Function]}
indexPattern={
Object {
"fields": Array [
@ -1324,15 +1405,9 @@ exports[`FieldEditor should show multiple type field warning with a table contai
}
label={
<FormattedMessage
defaultMessage="Format (Default: {defaultFormat})"
id="common.ui.fieldEditor.defaultFormatHeader"
values={
Object {
"defaultFormat": <eui-code>
Test format
</eui-code>,
}
}
defaultMessage="Format"
id="common.ui.fieldEditor.formatHeader"
values={Object {}}
/>
}
>
@ -1346,8 +1421,8 @@ exports[`FieldEditor should show multiple type field warning with a table contai
"value": "",
},
Object {
"text": "Test format",
"value": "test_format",
"text": undefined,
"value": "",
},
]
}

View file

@ -12,4 +12,14 @@ exports[`FieldFormatEditor should render normally 1`] = `
</Fragment>
`;
exports[`FieldFormatEditor should render nothing if there is no editor for the format 1`] = `<Fragment />`;
exports[`FieldFormatEditor should render nothing if there is no editor for the format 1`] = `
<Fragment>
<TestEditor
fieldType="number"
format={Object {}}
formatParams={Object {}}
onChange={[Function]}
onError={[Function]}
/>
</Fragment>
`;

View file

@ -5,7 +5,6 @@ exports[`BytesFormatEditor should render normally 1`] = `
<EuiFormRow
describedByIds={Array []}
display="row"
error={null}
fullWidth={false}
hasChildLabel={true}
hasEmptyLabelSpace={false}
@ -47,6 +46,7 @@ exports[`BytesFormatEditor should render normally 1`] = `
isInvalid={false}
onChange={[Function]}
placeholder="0,0.[000]b"
value=""
/>
</EuiFormRow>
<FormatEditorSamples

View file

@ -21,15 +21,18 @@ import React from 'react';
import { shallow } from 'enzyme';
import { BytesFormatEditor } from './bytes';
import { FieldFormat } from 'src/plugins/data/public';
const fieldType = 'number';
const format = {
getConverterFor: jest.fn().mockImplementation(() => input => input * 2),
getConverterFor: jest.fn().mockImplementation(() => (input: number) => input * 2),
getParamDefaults: jest.fn().mockImplementation(() => {
return { pattern: '0,0.[000]b' };
}),
};
const formatParams = {};
const formatParams = {
pattern: '',
};
const onChange = jest.fn();
const onError = jest.fn();
@ -41,8 +44,9 @@ describe('BytesFormatEditor', () => {
it('should render normally', async () => {
const component = shallow(
<BytesFormatEditor
basePath={''}
fieldType={fieldType}
format={format}
format={(format as unknown) as FieldFormat}
formatParams={formatParams}
onChange={onChange}
onError={onError}

View file

@ -18,16 +18,12 @@
*/
import { NumberFormatEditor } from '../number';
import { defaultState } from '../default';
export class BytesFormatEditor extends NumberFormatEditor {
static formatId = 'bytes';
constructor(props) {
super(props);
this.state = {
...this.state,
sampleInputs: [256, 1024, 5150000, 1990000000],
};
}
state = {
...defaultState,
sampleInputs: [256, 1024, 5150000, 1990000000],
};
}

View file

@ -52,6 +52,8 @@ exports[`ColorFormatEditor should render multiple colors 1`] = `
"type": "icon",
},
],
"field": "actions",
"name": "Actions",
},
]
}
@ -149,6 +151,8 @@ exports[`ColorFormatEditor should render other type normally (range field) 1`] =
"type": "icon",
},
],
"field": "actions",
"name": "Actions",
},
]
}
@ -239,6 +243,8 @@ exports[`ColorFormatEditor should render string type normally (regex field) 1`]
"type": "icon",
},
],
"field": "actions",
"name": "Actions",
},
]
}

View file

@ -19,6 +19,7 @@
import React from 'react';
import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers';
import { FieldFormat } from 'src/plugins/data/public';
import { ColorFormatEditor } from './color';
import { fieldFormats } from '../../../../../../../../plugins/data/public';
@ -41,8 +42,9 @@ describe('ColorFormatEditor', () => {
it('should render string type normally (regex field)', async () => {
const component = shallowWithI18nProvider(
<ColorFormatEditor
basePath={''}
fieldType={fieldType}
format={format}
format={(format as unknown) as FieldFormat}
formatParams={formatParams}
onChange={onChange}
onError={onError}
@ -55,8 +57,9 @@ describe('ColorFormatEditor', () => {
it('should render other type normally (range field)', async () => {
const component = shallowWithI18nProvider(
<ColorFormatEditor
basePath={''}
fieldType={'number'}
format={format}
format={(format as unknown) as FieldFormat}
formatParams={formatParams}
onChange={onChange}
onError={onError}
@ -69,8 +72,9 @@ describe('ColorFormatEditor', () => {
it('should render multiple colors', async () => {
const component = shallowWithI18nProvider(
<ColorFormatEditor
basePath={''}
fieldType={fieldType}
format={format}
format={(format as unknown) as FieldFormat}
formatParams={{ colors: [...formatParams.colors, ...formatParams.colors] }}
onChange={onChange}
onError={onError}

View file

@ -21,22 +21,37 @@ import React, { Fragment } from 'react';
import { EuiBasicTable, EuiButton, EuiColorPicker, EuiFieldText, EuiSpacer } from '@elastic/eui';
import { DefaultFormatEditor } from '../default';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { DefaultFormatEditor, FormatEditorProps } from '../default';
import { fieldFormats } from '../../../../../../../../plugins/data/public';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
interface Color {
range?: string;
regex?: string;
text: string;
background: string;
}
export class ColorFormatEditor extends DefaultFormatEditor {
constructor(props) {
interface IndexedColor extends Color {
index: number;
}
interface ColorFormatEditorFormatParams {
colors: Color[];
}
export class ColorFormatEditor extends DefaultFormatEditor<ColorFormatEditorFormatParams> {
static formatId = 'color';
constructor(props: FormatEditorProps<ColorFormatEditorFormatParams>) {
super(props);
this.onChange({
fieldType: props.fieldType,
});
}
onColorChange = (newColorParams, index) => {
onColorChange = (newColorParams: Partial<Color>, index: number) => {
const colors = [...this.props.formatParams.colors];
colors[index] = {
...colors[index],
@ -54,7 +69,7 @@ export class ColorFormatEditor extends DefaultFormatEditor {
});
};
removeColor = index => {
removeColor = (index: number) => {
const colors = [...this.props.formatParams.colors];
colors.splice(index, 1);
this.onChange({
@ -86,7 +101,7 @@ export class ColorFormatEditor extends DefaultFormatEditor {
defaultMessage="Pattern (regular expression)"
/>
),
render: (value, item) => {
render: (value: string, item: IndexedColor) => {
return (
<EuiFieldText
value={value}
@ -110,7 +125,7 @@ export class ColorFormatEditor extends DefaultFormatEditor {
defaultMessage="Range (min:max)"
/>
),
render: (value, item) => {
render: (value: string, item: IndexedColor) => {
return (
<EuiFieldText
value={value}
@ -134,7 +149,7 @@ export class ColorFormatEditor extends DefaultFormatEditor {
defaultMessage="Text color"
/>
),
render: (color, item) => {
render: (color: string, item: IndexedColor) => {
return (
<EuiColorPicker
color={color}
@ -158,7 +173,7 @@ export class ColorFormatEditor extends DefaultFormatEditor {
defaultMessage="Background color"
/>
),
render: (color, item) => {
render: (color: string, item: IndexedColor) => {
return (
<EuiColorPicker
color={color}
@ -181,7 +196,7 @@ export class ColorFormatEditor extends DefaultFormatEditor {
defaultMessage="Example"
/>
),
render: item => {
render: (item: IndexedColor) => {
return (
<div
style={{
@ -195,6 +210,10 @@ export class ColorFormatEditor extends DefaultFormatEditor {
},
},
{
field: 'actions',
name: i18n.translate('common.ui.fieldEditor.color.actions', {
defaultMessage: 'Actions',
}),
actions: [
{
name: i18n.translate('common.ui.fieldEditor.color.deleteAria', {
@ -203,7 +222,7 @@ export class ColorFormatEditor extends DefaultFormatEditor {
description: i18n.translate('common.ui.fieldEditor.color.deleteTitle', {
defaultMessage: 'Delete color format',
}),
onClick: item => {
onClick: (item: IndexedColor) => {
this.removeColor(item.index);
},
type: 'icon',
@ -230,5 +249,3 @@ export class ColorFormatEditor extends DefaultFormatEditor {
);
}
}
ColorFormatEditor.formatId = 'color';

View file

@ -5,7 +5,6 @@ exports[`DateFormatEditor should render normally 1`] = `
<EuiFormRow
describedByIds={Array []}
display="row"
error={null}
fullWidth={false}
hasChildLabel={true}
hasEmptyLabelSpace={false}
@ -48,6 +47,7 @@ exports[`DateFormatEditor should render normally 1`] = `
isInvalid={false}
onChange={[Function]}
placeholder="MMMM Do YYYY, HH:mm:ss.SSS"
value=""
/>
</EuiFormRow>
<FormatEditorSamples

View file

@ -19,17 +19,20 @@
import React from 'react';
import { shallow } from 'enzyme';
import { FieldFormat } from 'src/plugins/data/public';
import { DateFormatEditor } from './date';
const fieldType = 'date';
const format = {
getConverterFor: jest.fn().mockImplementation(() => input => `converted date for ${input}`),
getConverterFor: jest
.fn()
.mockImplementation(() => (input: string) => `converted date for ${input}`),
getParamDefaults: jest.fn().mockImplementation(() => {
return { pattern: 'MMMM Do YYYY, HH:mm:ss.SSS' };
}),
};
const formatParams = {};
const formatParams = { pattern: '' };
const onChange = jest.fn();
const onError = jest.fn();
@ -41,8 +44,9 @@ describe('DateFormatEditor', () => {
it('should render normally', async () => {
const component = shallow(
<DateFormatEditor
basePath={''}
fieldType={fieldType}
format={format}
format={(format as unknown) as FieldFormat}
formatParams={formatParams}
onChange={onChange}
onError={onError}

View file

@ -22,18 +22,20 @@ import moment from 'moment';
import { EuiCode, EuiFieldText, EuiFormRow, EuiIcon, EuiLink } from '@elastic/eui';
import { DefaultFormatEditor } from '../default';
import { FormattedMessage } from '@kbn/i18n/react';
import { DefaultFormatEditor, defaultState } from '../default';
import { FormatEditorSamples } from '../../samples';
import { FormattedMessage } from '@kbn/i18n/react';
interface DateFormatEditorFormatParams {
pattern: string;
}
export class DateFormatEditor extends DefaultFormatEditor {
export class DateFormatEditor extends DefaultFormatEditor<DateFormatEditorFormatParams> {
static formatId = 'date';
constructor(props) {
super(props);
this.state.sampleInputs = [
state = {
...defaultState,
sampleInputs: [
Date.now(),
moment()
.startOf('year')
@ -41,8 +43,8 @@ export class DateFormatEditor extends DefaultFormatEditor {
moment()
.endOf('year')
.valueOf(),
];
}
],
};
render() {
const { format, formatParams } = this.props;

View file

@ -5,7 +5,6 @@ exports[`DateFormatEditor should render normally 1`] = `
<EuiFormRow
describedByIds={Array []}
display="row"
error={null}
fullWidth={false}
hasChildLabel={true}
hasEmptyLabelSpace={false}
@ -48,6 +47,7 @@ exports[`DateFormatEditor should render normally 1`] = `
isInvalid={false}
onChange={[Function]}
placeholder="MMM D, YYYY @ HH:mm:ss.SSSSSSSSS"
value=""
/>
</EuiFormRow>
<FormatEditorSamples

View file

@ -19,17 +19,22 @@
import React from 'react';
import { shallow } from 'enzyme';
import { FieldFormat } from '../../../../../../../../plugins/data/public';
import { DateNanosFormatEditor } from './date_nanos';
const fieldType = 'date_nanos';
const format = {
getConverterFor: jest.fn().mockImplementation(() => input => `converted date for ${input}`),
getConverterFor: jest
.fn()
.mockImplementation(() => (input: string) => `converted date for ${input}`),
getParamDefaults: jest.fn().mockImplementation(() => {
return { pattern: 'MMM D, YYYY @ HH:mm:ss.SSSSSSSSS' };
}),
};
const formatParams = {};
const formatParams = {
pattern: '',
};
const onChange = jest.fn();
const onError = jest.fn();
@ -41,8 +46,9 @@ describe('DateFormatEditor', () => {
it('should render normally', async () => {
const component = shallow(
<DateNanosFormatEditor
basePath={''}
fieldType={fieldType}
format={format}
format={(format as unknown) as FieldFormat}
formatParams={formatParams}
onChange={onChange}
onError={onError}

View file

@ -21,23 +21,25 @@ import React, { Fragment } from 'react';
import { EuiCode, EuiFieldText, EuiFormRow, EuiIcon, EuiLink } from '@elastic/eui';
import { DefaultFormatEditor } from '../default';
import { FormattedMessage } from '@kbn/i18n/react';
import { DefaultFormatEditor, defaultState } from '../default';
import { FormatEditorSamples } from '../../samples';
import { FormattedMessage } from '@kbn/i18n/react';
interface DateNanosFormatEditorFormatParams {
pattern: string;
}
export class DateNanosFormatEditor extends DefaultFormatEditor {
export class DateNanosFormatEditor extends DefaultFormatEditor<DateNanosFormatEditorFormatParams> {
static formatId = 'date_nanos';
constructor(props) {
super(props);
this.state.sampleInputs = [
state = {
...defaultState,
sampleInputs: [
'2015-01-01T12:10:30.123456789Z',
'2019-05-08T06:55:21.567891234Z',
'2019-08-06T17:22:30.987654321Z',
];
}
],
};
render() {
const { format, formatParams } = this.props;

View file

@ -1,3 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`DefaultFormatEditor should render nothing 1`] = `""`;

View file

@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`DefaultFormatEditor should render nothing 1`] = `<Fragment />`;

View file

@ -19,8 +19,9 @@
import React from 'react';
import { shallow } from 'enzyme';
import { FieldFormat } from 'src/plugins/data/public';
import { DefaultFormatEditor, convertSampleInput } from './default';
import { DefaultFormatEditor, convertSampleInput, ConverterParams } from './default';
const fieldType = 'number';
const format = {
@ -32,13 +33,11 @@ const onError = jest.fn();
describe('DefaultFormatEditor', () => {
describe('convertSampleInput', () => {
const converter = input => {
if (isNaN(input)) {
throw {
message: 'Input is not a number',
};
const converter = (input: ConverterParams) => {
if (typeof input !== 'number') {
throw new Error('Input is not a number');
} else {
return input * 2;
return (input * 2).toString();
}
};
@ -46,12 +45,12 @@ describe('DefaultFormatEditor', () => {
const inputs = [1, 10, 15];
const output = convertSampleInput(converter, inputs);
expect(output.error).toEqual(null);
expect(output.error).toBeUndefined();
expect(JSON.stringify(output.samples)).toEqual(
JSON.stringify([
{ input: 1, output: 2 },
{ input: 10, output: 20 },
{ input: 15, output: 30 },
{ input: 1, output: '2' },
{ input: 10, output: '20' },
{ input: 15, output: '30' },
])
);
});
@ -70,8 +69,9 @@ describe('DefaultFormatEditor', () => {
it('should render nothing', async () => {
const component = shallow(
<DefaultFormatEditor
basePath={''}
fieldType={fieldType}
format={format}
format={(format as unknown) as FieldFormat}
formatParams={formatParams}
onChange={onChange}
onError={onError}
@ -86,29 +86,31 @@ describe('DefaultFormatEditor', () => {
it('should call prop onChange()', async () => {
const component = shallow(
<DefaultFormatEditor
basePath={''}
fieldType={fieldType}
format={format}
format={(format as unknown) as FieldFormat}
formatParams={formatParams}
onChange={onChange}
onError={onError}
/>
);
component.instance().onChange();
(component.instance() as DefaultFormatEditor).onChange();
expect(onChange).toBeCalled();
});
it('should call prop onError() if converter throws an error', async () => {
const newFormat = {
getConverterFor: jest.fn().mockImplementation(() => () => {
throw { message: 'Test error message' };
throw new Error('Test error message');
}),
};
shallow(
<DefaultFormatEditor
basePath={''}
fieldType={fieldType}
format={newFormat}
format={(newFormat as unknown) as FieldFormat}
formatParams={formatParams}
onChange={onChange}
onError={onError}

View file

@ -17,13 +17,21 @@
* under the License.
*/
import { PureComponent } from 'react';
import PropTypes from 'prop-types';
import React, { PureComponent, ReactText } from 'react';
import { i18n } from '@kbn/i18n';
export const convertSampleInput = (converter, inputs) => {
let error = null;
let samples = [];
import { FieldFormat, FieldFormatsContentType } from 'src/plugins/data/public';
import { Sample } from '../../../../types';
import { FieldFormatEditorProps } from '../../field_format_editor';
export type ConverterParams = string | number | Array<string | number>;
export const convertSampleInput = (
converter: (input: ConverterParams) => string,
inputs: ConverterParams[]
) => {
let error;
let samples: Sample[] = [];
try {
samples = inputs.map(input => {
@ -45,32 +53,48 @@ export const convertSampleInput = (converter, inputs) => {
};
};
export class DefaultFormatEditor extends PureComponent {
static propTypes = {
fieldType: PropTypes.string.isRequired,
format: PropTypes.object.isRequired,
formatParams: PropTypes.object.isRequired,
onChange: PropTypes.func.isRequired,
onError: PropTypes.func.isRequired,
};
interface SampleInputs {
[key: string]: Array<ReactText[] | ReactText>;
}
constructor(props) {
super(props);
this.state = {
sampleInputs: [],
sampleConverterType: 'text',
error: null,
samples: [],
};
}
export interface FormatEditorProps<P> {
fieldType: string;
format: FieldFormat;
formatParams: { type?: string } & P;
onChange: (newParams: Record<string, any>) => void;
onError: FieldFormatEditorProps['onError'];
basePath: string;
}
static getDerivedStateFromProps(nextProps, state) {
export interface FormatEditorState {
sampleInputs: ReactText[];
sampleConverterType: FieldFormatsContentType;
error?: string;
samples: Sample[];
sampleInputsByType: SampleInputs;
}
export const defaultState = {
sampleInputs: [] as ReactText[],
sampleConverterType: 'text' as FieldFormatsContentType,
error: undefined,
samples: [] as Sample[],
sampleInputsByType: {},
};
export class DefaultFormatEditor<P = {}, S = {}> extends PureComponent<
FormatEditorProps<P>,
FormatEditorState & S
> {
state = defaultState as FormatEditorState & S;
static getDerivedStateFromProps(nextProps: FormatEditorProps<{}>, state: FormatEditorState) {
const { format, formatParams, onError } = nextProps;
const { sampleInputsByType, sampleInputs, sampleConverterType } = state;
const converter = format.getConverterFor(sampleConverterType);
const type = typeof sampleInputsByType === 'object' && formatParams.type;
const inputs = type ? sampleInputsByType[formatParams.type] || [] : sampleInputs;
const inputs = type ? sampleInputsByType[formatParams.type as string] || [] : sampleInputs;
const output = convertSampleInput(converter, inputs);
onError(output.error);
return output;
@ -78,6 +102,7 @@ export class DefaultFormatEditor extends PureComponent {
onChange = (newParams = {}) => {
const { onChange, formatParams } = this.props;
onChange({
...formatParams,
...newParams,
@ -85,6 +110,6 @@ export class DefaultFormatEditor extends PureComponent {
};
render() {
return null;
return <></>;
}
}

View file

@ -17,4 +17,4 @@
* under the License.
*/
export { DefaultFormatEditor } from './default';
export { DefaultFormatEditor, defaultState, FormatEditorProps, FormatEditorState } from './default';

View file

@ -5,7 +5,6 @@ exports[`DurationFormatEditor should render human readable output normally 1`] =
<EuiFormRow
describedByIds={Array []}
display="row"
error={null}
fullWidth={false}
hasChildLabel={true}
hasEmptyLabelSpace={false}
@ -30,6 +29,7 @@ exports[`DurationFormatEditor should render human readable output normally 1`] =
},
]
}
value=""
/>
</EuiFormRow>
<EuiFormRow
@ -63,6 +63,7 @@ exports[`DurationFormatEditor should render human readable output normally 1`] =
},
]
}
value=""
/>
</EuiFormRow>
<FormatEditorSamples
@ -116,7 +117,6 @@ exports[`DurationFormatEditor should render non-human readable output normally 1
<EuiFormRow
describedByIds={Array []}
display="row"
error={null}
fullWidth={false}
hasChildLabel={true}
hasEmptyLabelSpace={false}
@ -141,6 +141,7 @@ exports[`DurationFormatEditor should render non-human readable output normally 1
},
]
}
value=""
/>
</EuiFormRow>
<EuiFormRow
@ -174,6 +175,7 @@ exports[`DurationFormatEditor should render non-human readable output normally 1
},
]
}
value=""
/>
</EuiFormRow>
<EuiFormRow
@ -198,6 +200,7 @@ exports[`DurationFormatEditor should render non-human readable output normally 1
max={20}
min={0}
onChange={[Function]}
value={2}
/>
</EuiFormRow>
<FormatEditorSamples

View file

@ -21,10 +21,13 @@ import React from 'react';
import { shallow } from 'enzyme';
import { DurationFormatEditor } from './duration';
import { FieldFormat } from 'src/plugins/data/public';
const fieldType = 'number';
const format = {
getConverterFor: jest.fn().mockImplementation(() => input => `converted duration for ${input}`),
getConverterFor: jest
.fn()
.mockImplementation(() => (input: string) => `converted duration for ${input}`),
getParamDefaults: jest.fn().mockImplementation(() => {
return {
inputFormat: 'seconds',
@ -52,7 +55,11 @@ const format = {
],
},
};
const formatParams = {};
const formatParams = {
outputPrecision: 2,
inputFormat: '',
outputFormat: '',
};
const onChange = jest.fn();
const onError = jest.fn();
@ -64,8 +71,9 @@ describe('DurationFormatEditor', () => {
it('should render human readable output normally', async () => {
const component = shallow(
<DurationFormatEditor
basePath={''}
fieldType={fieldType}
format={format}
format={(format as unknown) as FieldFormat}
formatParams={formatParams}
onChange={onChange}
onError={onError}
@ -88,8 +96,9 @@ describe('DurationFormatEditor', () => {
};
const component = shallow(
<DurationFormatEditor
basePath={''}
fieldType={fieldType}
format={newFormat}
format={(newFormat as unknown) as FieldFormat}
formatParams={formatParams}
onChange={onChange}
onError={onError}

View file

@ -18,30 +18,63 @@
*/
import React, { Fragment } from 'react';
import { DurationFormat } from 'src/plugins/data/common';
import { EuiFieldNumber, EuiFormRow, EuiSelect } from '@elastic/eui';
import { DefaultFormatEditor } from '../default';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import {
DefaultFormatEditor,
defaultState,
FormatEditorProps,
FormatEditorState,
} from '../default';
import { FormatEditorSamples } from '../../samples';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
interface DurationFormatEditorState {
hasDecimalError: boolean;
}
export class DurationFormatEditor extends DefaultFormatEditor {
interface InputFormat {
kind: string;
text: string;
}
interface OutputFormat {
method: string;
text: string;
}
interface DurationFormatEditorFormatParams {
outputPrecision: number;
inputFormat: string;
outputFormat: string;
}
export class DurationFormatEditor extends DefaultFormatEditor<
DurationFormatEditorFormatParams,
DurationFormatEditorState
> {
static formatId = 'duration';
state = {
...defaultState,
sampleInputs: [-123, 1, 12, 123, 658, 1988, 3857, 123292, 923528271],
hasDecimalError: false,
};
constructor(props) {
super(props);
this.state.sampleInputs = [-123, 1, 12, 123, 658, 1988, 3857, 123292, 923528271];
this.state.hasDecimalError = false;
}
static getDerivedStateFromProps(nextProps, state) {
static getDerivedStateFromProps(
nextProps: FormatEditorProps<DurationFormatEditorFormatParams>,
state: FormatEditorState & DurationFormatEditorState
) {
const output = super.getDerivedStateFromProps(nextProps, state);
let error = null;
if (!nextProps.format.isHuman() && nextProps.formatParams.outputPrecision > 20) {
if (
!(nextProps.format as DurationFormat).isHuman() &&
nextProps.formatParams.outputPrecision > 20
) {
error = i18n.translate('common.ui.fieldEditor.durationErrorMessage', {
defaultMessage: 'Decimal places must be between 0 and 20',
});
@ -77,10 +110,10 @@ export class DurationFormatEditor extends DefaultFormatEditor {
>
<EuiSelect
value={formatParams.inputFormat}
options={format.type.inputFormats.map(format => {
options={format.type.inputFormats.map((fmt: InputFormat) => {
return {
value: format.kind,
text: format.text,
value: fmt.kind,
text: fmt.text,
};
})}
onChange={e => {
@ -100,10 +133,10 @@ export class DurationFormatEditor extends DefaultFormatEditor {
>
<EuiSelect
value={formatParams.outputFormat}
options={format.type.outputFormats.map(format => {
options={format.type.outputFormats.map((fmt: OutputFormat) => {
return {
value: format.method,
text: format.text,
value: fmt.method,
text: fmt.text,
};
})}
onChange={e => {
@ -112,7 +145,7 @@ export class DurationFormatEditor extends DefaultFormatEditor {
isInvalid={!!error}
/>
</EuiFormRow>
{!format.isHuman() ? (
{!(format as DurationFormat).isHuman() ? (
<EuiFormRow
label={
<FormattedMessage

View file

@ -5,7 +5,6 @@ exports[`NumberFormatEditor should render normally 1`] = `
<EuiFormRow
describedByIds={Array []}
display="row"
error={null}
fullWidth={false}
hasChildLabel={true}
hasEmptyLabelSpace={false}
@ -47,6 +46,7 @@ exports[`NumberFormatEditor should render normally 1`] = `
isInvalid={false}
onChange={[Function]}
placeholder="0,0.[000]"
value=""
/>
</EuiFormRow>
<FormatEditorSamples

View file

@ -19,17 +19,20 @@
import React from 'react';
import { shallow } from 'enzyme';
import { FieldFormat } from 'src/plugins/data/public';
import { NumberFormatEditor } from './number';
const fieldType = 'number';
const format = {
getConverterFor: jest.fn().mockImplementation(() => input => input * 2),
getConverterFor: jest.fn().mockImplementation(() => (input: number) => input * 2),
getParamDefaults: jest.fn().mockImplementation(() => {
return { pattern: '0,0.[000]' };
}),
};
const formatParams = {};
const formatParams = {
pattern: '',
};
const onChange = jest.fn();
const onError = jest.fn();
@ -41,8 +44,9 @@ describe('NumberFormatEditor', () => {
it('should render normally', async () => {
const component = shallow(
<NumberFormatEditor
basePath={''}
fieldType={fieldType}
format={format}
format={(format as unknown) as FieldFormat}
formatParams={formatParams}
onChange={onChange}
onError={onError}

View file

@ -21,19 +21,21 @@ import React, { Fragment } from 'react';
import { EuiCode, EuiFieldText, EuiFormRow, EuiIcon, EuiLink } from '@elastic/eui';
import { DefaultFormatEditor } from '../default';
import { FormattedMessage } from '@kbn/i18n/react';
import { DefaultFormatEditor, defaultState } from '../default';
import { FormatEditorSamples } from '../../samples';
import { FormattedMessage } from '@kbn/i18n/react';
export interface NumberFormatEditorParams {
pattern: string;
}
export class NumberFormatEditor extends DefaultFormatEditor {
export class NumberFormatEditor extends DefaultFormatEditor<NumberFormatEditorParams> {
static formatId = 'number';
constructor(props) {
super(props);
this.state.sampleInputs = [10000, 12.345678, -1, -999, 0.52];
}
state = {
...defaultState,
sampleInputs: [10000, 12.345678, -1, -999, 0.52],
};
render() {
const { format, formatParams } = this.props;

View file

@ -5,7 +5,6 @@ exports[`PercentFormatEditor should render normally 1`] = `
<EuiFormRow
describedByIds={Array []}
display="row"
error={null}
fullWidth={false}
hasChildLabel={true}
hasEmptyLabelSpace={false}
@ -47,6 +46,7 @@ exports[`PercentFormatEditor should render normally 1`] = `
isInvalid={false}
onChange={[Function]}
placeholder="0,0.[000]%"
value=""
/>
</EuiFormRow>
<FormatEditorSamples

View file

@ -19,17 +19,20 @@
import React from 'react';
import { shallow } from 'enzyme';
import { FieldFormat } from '../../../../../../../../plugins/data/public';
import { PercentFormatEditor } from './percent';
const fieldType = 'number';
const format = {
getConverterFor: jest.fn().mockImplementation(() => input => input * 2),
getConverterFor: jest.fn().mockImplementation(() => (input: number) => input * 2),
getParamDefaults: jest.fn().mockImplementation(() => {
return { pattern: '0,0.[000]%' };
}),
};
const formatParams = {};
const formatParams = {
pattern: '',
};
const onChange = jest.fn();
const onError = jest.fn();
@ -41,8 +44,9 @@ describe('PercentFormatEditor', () => {
it('should render normally', async () => {
const component = shallow(
<PercentFormatEditor
basePath={''}
fieldType={fieldType}
format={format}
format={(format as unknown) as FieldFormat}
formatParams={formatParams}
onChange={onChange}
onError={onError}

View file

@ -18,16 +18,12 @@
*/
import { NumberFormatEditor } from '../number';
import { defaultState } from '../default';
export class PercentFormatEditor extends NumberFormatEditor {
static formatId = 'percent';
constructor(props) {
super(props);
this.state = {
...this.state,
sampleInputs: [0.1, 0.99999, 1, 100, 1000],
};
}
state = {
...defaultState,
sampleInputs: [0.1, 0.99999, 1, 100, 1000],
};
}

View file

@ -35,6 +35,8 @@ exports[`StaticLookupFormatEditor should render multiple lookup entries and unkn
"type": "icon",
},
],
"field": "actions",
"name": "actions",
"width": "30px",
},
]
@ -140,6 +142,8 @@ exports[`StaticLookupFormatEditor should render normally 1`] = `
"type": "icon",
},
],
"field": "actions",
"name": "actions",
"width": "30px",
},
]

View file

@ -18,7 +18,9 @@
*/
import React from 'react';
import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers';
import { shallowWithI18nProvider } from '../../../../../../../../test_utils/public/enzyme_helpers';
import { StaticLookupFormatEditorFormatParams } from './static_lookup';
import { FieldFormat } from '../../../../../../../../plugins/data/public';
import { StaticLookupFormatEditor } from './static_lookup';
@ -27,8 +29,8 @@ const format = {
getConverterFor: jest.fn(),
};
const formatParams = {
lookupEntries: [{}],
unknownKeyValue: null,
lookupEntries: [{}] as StaticLookupFormatEditorFormatParams['lookupEntries'],
unknownKeyValue: '',
};
const onChange = jest.fn();
const onError = jest.fn();
@ -41,8 +43,9 @@ describe('StaticLookupFormatEditor', () => {
it('should render normally', async () => {
const component = shallowWithI18nProvider(
<StaticLookupFormatEditor
basePath={''}
fieldType={fieldType}
format={format}
format={(format as unknown) as FieldFormat}
formatParams={formatParams}
onChange={onChange}
onError={onError}
@ -55,9 +58,13 @@ describe('StaticLookupFormatEditor', () => {
it('should render multiple lookup entries and unknown key value', async () => {
const component = shallowWithI18nProvider(
<StaticLookupFormatEditor
basePath={''}
fieldType={fieldType}
format={format}
formatParams={{ lookupEntries: [{}, {}, {}], unknownKeyValue: 'test value' }}
format={(format as unknown) as FieldFormat}
formatParams={{
lookupEntries: [{}, {}, {}] as StaticLookupFormatEditorFormatParams['lookupEntries'],
unknownKeyValue: 'test value',
}}
onChange={onChange}
onError={onError}
/>

View file

@ -21,13 +21,26 @@ import React, { Fragment } from 'react';
import { EuiBasicTable, EuiButton, EuiFieldText, EuiFormRow, EuiSpacer } from '@elastic/eui';
import { DefaultFormatEditor } from '../default';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { DefaultFormatEditor } from '../default';
export class StaticLookupFormatEditor extends DefaultFormatEditor {
onLookupChange = (newLookupParams, index) => {
export interface StaticLookupFormatEditorFormatParams {
lookupEntries: Array<{ key: string; value: string }>;
unknownKeyValue: string;
}
interface StaticLookupItem {
key: string;
value: string;
index: number;
}
export class StaticLookupFormatEditor extends DefaultFormatEditor<
StaticLookupFormatEditorFormatParams
> {
static formatId = 'static_lookup';
onLookupChange = (newLookupParams: { value?: string; key?: string }, index: number) => {
const lookupEntries = [...this.props.formatParams.lookupEntries];
lookupEntries[index] = {
...lookupEntries[index],
@ -45,7 +58,7 @@ export class StaticLookupFormatEditor extends DefaultFormatEditor {
});
};
removeLookup = index => {
removeLookup = (index: number) => {
const lookupEntries = [...this.props.formatParams.lookupEntries];
lookupEntries.splice(index, 1);
this.onChange({
@ -73,7 +86,7 @@ export class StaticLookupFormatEditor extends DefaultFormatEditor {
name: (
<FormattedMessage id="common.ui.fieldEditor.staticLookup.keyLabel" defaultMessage="Key" />
),
render: (value, item) => {
render: (value: number, item: StaticLookupItem) => {
return (
<EuiFieldText
value={value || ''}
@ -97,7 +110,7 @@ export class StaticLookupFormatEditor extends DefaultFormatEditor {
defaultMessage="Value"
/>
),
render: (value, item) => {
render: (value: number, item: StaticLookupItem) => {
return (
<EuiFieldText
value={value || ''}
@ -114,6 +127,10 @@ export class StaticLookupFormatEditor extends DefaultFormatEditor {
},
},
{
field: 'actions',
name: i18n.translate('common.ui.fieldEditor.staticLookup.actions', {
defaultMessage: 'actions',
}),
actions: [
{
name: i18n.translate('common.ui.fieldEditor.staticLookup.deleteAria', {
@ -122,7 +139,7 @@ export class StaticLookupFormatEditor extends DefaultFormatEditor {
description: i18n.translate('common.ui.fieldEditor.staticLookup.deleteTitle', {
defaultMessage: 'Delete entry',
}),
onClick: item => {
onClick: (item: StaticLookupItem) => {
this.removeLookup(item.index);
},
type: 'icon',
@ -172,5 +189,3 @@ export class StaticLookupFormatEditor extends DefaultFormatEditor {
);
}
}
StaticLookupFormatEditor.formatId = 'static_lookup';

View file

@ -5,7 +5,6 @@ exports[`StringFormatEditor should render normally 1`] = `
<EuiFormRow
describedByIds={Array []}
display="row"
error={null}
fullWidth={false}
hasChildLabel={true}
hasEmptyLabelSpace={false}
@ -21,6 +20,7 @@ exports[`StringFormatEditor should render normally 1`] = `
>
<EuiSelect
data-test-subj="stringEditorTransform"
defaultValue=""
isInvalid={false}
onChange={[Function]}
options={

View file

@ -19,12 +19,13 @@
import React from 'react';
import { shallow } from 'enzyme';
import { FieldFormat } from 'src/plugins/data/public';
import { StringFormatEditor } from './string';
const fieldType = 'string';
const format = {
getConverterFor: jest.fn().mockImplementation(() => input => input.toUpperCase()),
getConverterFor: jest.fn().mockImplementation(() => (input: string) => input.toUpperCase()),
getParamDefaults: jest.fn().mockImplementation(() => {
return { transform: 'upper' };
}),
@ -37,7 +38,9 @@ const format = {
],
},
};
const formatParams = {};
const formatParams = {
transform: '',
};
const onChange = jest.fn();
const onError = jest.fn();
@ -49,8 +52,9 @@ describe('StringFormatEditor', () => {
it('should render normally', async () => {
const component = shallow(
<StringFormatEditor
basePath={''}
fieldType={fieldType}
format={format}
format={(format as unknown) as FieldFormat}
formatParams={formatParams}
onChange={onChange}
onError={onError}

View file

@ -21,26 +21,33 @@ import React, { Fragment } from 'react';
import { EuiFormRow, EuiSelect } from '@elastic/eui';
import { DefaultFormatEditor } from '../default';
import { FormattedMessage } from '@kbn/i18n/react';
import { DefaultFormatEditor, defaultState } from '../default';
import { FormatEditorSamples } from '../../samples';
import { FormattedMessage } from '@kbn/i18n/react';
interface StringFormatEditorFormatParams {
transform: string;
}
export class StringFormatEditor extends DefaultFormatEditor {
interface TransformOptions {
kind: string;
text: string;
}
export class StringFormatEditor extends DefaultFormatEditor<StringFormatEditorFormatParams> {
static formatId = 'string';
constructor(props) {
super(props);
this.state.sampleInputs = [
state = {
...defaultState,
sampleInputs: [
'A Quick Brown Fox.',
'STAY CALM!',
'com.organizations.project.ClassName',
'hostname.net',
'SGVsbG8gd29ybGQ=',
'%EC%95%88%EB%85%95%20%ED%82%A4%EB%B0%94%EB%82%98',
];
}
],
};
render() {
const { format, formatParams } = this.props;
@ -61,7 +68,7 @@ export class StringFormatEditor extends DefaultFormatEditor {
<EuiSelect
data-test-subj="stringEditorTransform"
defaultValue={formatParams.transform}
options={format.type.transformOptions.map(option => {
options={format.type.transformOptions.map((option: TransformOptions) => {
return {
value: option.kind,
text: option.text,

View file

@ -5,7 +5,6 @@ exports[`TruncateFormatEditor should render normally 1`] = `
<EuiFormRow
describedByIds={Array []}
display="row"
error={null}
fullWidth={false}
hasChildLabel={true}
hasEmptyLabelSpace={false}
@ -20,6 +19,7 @@ exports[`TruncateFormatEditor should render normally 1`] = `
labelType="label"
>
<EuiFieldNumber
defaultValue={5}
isInvalid={false}
min={1}
onChange={[Function]}

View file

@ -1 +0,0 @@
export const sample = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris vitae sem consequat, sollicitudin enim a, feugiat mi. Curabitur congue laoreet elit, eu dictum nisi commodo ut. Nullam congue sem a blandit commodo. Suspendisse eleifend sodales leo ac hendrerit. Nam fringilla tempor fermentum. Ut tristique pharetra sapien sit amet pharetra. Ut turpis massa, viverra id erat quis, fringilla vehicula risus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Phasellus tincidunt gravida gravida. Praesent et ligula viverra, semper lacus in, tristique elit. Cras ac eleifend diam. Nulla facilisi. Morbi id sagittis magna. Sed fringilla, magna in suscipit aliquet."; // eslint-disable-line

View file

@ -0,0 +1,20 @@
/*
* 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.
*/
export const sample = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris vitae sem consequat, sollicitudin enim a, feugiat mi. Curabitur congue laoreet elit, eu dictum nisi commodo ut. Nullam congue sem a blandit commodo. Suspendisse eleifend sodales leo ac hendrerit. Nam fringilla tempor fermentum. Ut tristique pharetra sapien sit amet pharetra. Ut turpis massa, viverra id erat quis, fringilla vehicula risus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Phasellus tincidunt gravida gravida. Praesent et ligula viverra, semper lacus in, tristique elit. Cras ac eleifend diam. Nulla facilisi. Morbi id sagittis magna. Sed fringilla, magna in suscipit aliquet."; // eslint-disable-line

View file

@ -17,20 +17,23 @@
* under the License.
*/
import React from 'react';
import React, { ChangeEvent } from 'react';
import { shallow } from 'enzyme';
import { EuiFieldNumber } from '@elastic/eui';
import { FieldFormat } from 'src/plugins/data/public';
import { TruncateFormatEditor } from './truncate';
const fieldType = 'string';
const format = {
getConverterFor: jest.fn().mockImplementation(() => input => input.substring(0, 10)),
getConverterFor: jest.fn().mockImplementation(() => (input: string) => input.substring(0, 10)),
getParamDefaults: jest.fn().mockImplementation(() => {
return { fieldLength: 10 };
}),
};
const formatParams = {};
const formatParams = {
fieldLength: 5,
};
const onChange = jest.fn();
const onError = jest.fn();
@ -47,8 +50,9 @@ describe('TruncateFormatEditor', () => {
it('should render normally', async () => {
const component = shallow(
<TruncateFormatEditor
basePath={''}
fieldType={fieldType}
format={format}
format={(format as unknown) as FieldFormat}
formatParams={formatParams}
onChange={onChange}
onError={onError}
@ -60,8 +64,9 @@ describe('TruncateFormatEditor', () => {
it('should fire error, when input is invalid', async () => {
const component = shallow(
<TruncateFormatEditor
basePath={''}
fieldType={fieldType}
format={format}
format={(format as unknown) as FieldFormat}
formatParams={formatParams}
onChange={onChange}
onError={onError}
@ -76,7 +81,8 @@ describe('TruncateFormatEditor', () => {
validationMessage: 'Error!',
},
};
await input.invoke('onChange')(changeEvent);
await input!.invoke('onChange')!((changeEvent as unknown) as ChangeEvent<HTMLInputElement>);
expect(onError).toBeCalledWith(changeEvent.target.validationMessage);
expect(onChange).not.toBeCalled();
@ -85,8 +91,9 @@ describe('TruncateFormatEditor', () => {
it('should fire change, when input changed and is valid', async () => {
const component = shallow(
<TruncateFormatEditor
basePath={''}
fieldType={fieldType}
format={format}
format={(format as unknown) as FieldFormat}
formatParams={formatParams}
onChange={onChange}
onError={onError}
@ -102,7 +109,7 @@ describe('TruncateFormatEditor', () => {
},
};
onError.mockClear();
await input.invoke('onChange')(changeEvent);
await input!.invoke('onChange')!((changeEvent as unknown) as ChangeEvent<HTMLInputElement>);
expect(onError).not.toBeCalled();
expect(onChange).toBeCalledWith({ fieldLength: 123 });
});

View file

@ -21,21 +21,23 @@ import React, { Fragment } from 'react';
import { EuiFieldNumber, EuiFormRow } from '@elastic/eui';
import { DefaultFormatEditor } from '../default';
import { FormattedMessage } from '@kbn/i18n/react';
import { DefaultFormatEditor, defaultState } from '../default';
import { FormatEditorSamples } from '../../samples';
import { sample } from './sample';
import { FormattedMessage } from '@kbn/i18n/react';
interface TruncateFormatEditorFormatParams {
fieldLength: number;
}
export class TruncateFormatEditor extends DefaultFormatEditor {
export class TruncateFormatEditor extends DefaultFormatEditor<TruncateFormatEditorFormatParams> {
static formatId = 'truncate';
constructor(props) {
super(props);
this.state.sampleInputs = [sample];
}
state = {
...defaultState,
sampleInputs: [sample],
};
render() {
const { formatParams, onError } = this.props;

View file

@ -49,7 +49,6 @@ exports[`UrlFormatEditor should render label template help 1`] = `
<EuiFormRow
describedByIds={Array []}
display="row"
error={null}
fullWidth={false}
hasChildLabel={true}
hasEmptyLabelSpace={false}
@ -83,7 +82,6 @@ exports[`UrlFormatEditor should render label template help 1`] = `
<EuiFormRow
describedByIds={Array []}
display="row"
error={null}
fullWidth={false}
hasChildLabel={true}
hasEmptyLabelSpace={false}
@ -170,7 +168,6 @@ exports[`UrlFormatEditor should render normally 1`] = `
<EuiFormRow
describedByIds={Array []}
display="row"
error={null}
fullWidth={false}
hasChildLabel={true}
hasEmptyLabelSpace={false}
@ -204,7 +201,6 @@ exports[`UrlFormatEditor should render normally 1`] = `
<EuiFormRow
describedByIds={Array []}
display="row"
error={null}
fullWidth={false}
hasChildLabel={true}
hasEmptyLabelSpace={false}
@ -291,7 +287,6 @@ exports[`UrlFormatEditor should render url template help 1`] = `
<EuiFormRow
describedByIds={Array []}
display="row"
error={null}
fullWidth={false}
hasChildLabel={true}
hasEmptyLabelSpace={false}
@ -325,7 +320,6 @@ exports[`UrlFormatEditor should render url template help 1`] = `
<EuiFormRow
describedByIds={Array []}
display="row"
error={null}
fullWidth={false}
hasChildLabel={true}
hasEmptyLabelSpace={false}
@ -413,7 +407,6 @@ exports[`UrlFormatEditor should render width and height fields if image 1`] = `
<EuiFormRow
describedByIds={Array []}
display="row"
error={null}
fullWidth={false}
hasChildLabel={true}
hasEmptyLabelSpace={false}
@ -447,7 +440,6 @@ exports[`UrlFormatEditor should render width and height fields if image 1`] = `
<EuiFormRow
describedByIds={Array []}
display="row"
error={null}
fullWidth={false}
hasChildLabel={true}
hasEmptyLabelSpace={false}

View file

@ -24,6 +24,43 @@ import { EuiBasicTable, EuiCode, EuiFlyout, EuiFlyoutBody, EuiText } from '@elas
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
interface LabelTemplateExampleItem {
input: string | number;
urlTemplate: string;
labelTemplate: string;
output: string;
}
const items: LabelTemplateExampleItem[] = [
{
input: 1234,
urlTemplate: 'http://company.net/profiles?user_id={{value}}',
labelTemplate: i18n.translate('common.ui.fieldEditor.labelTemplate.example.idLabel', {
defaultMessage: 'User #{value}',
values: { value: '{{value}}' },
}),
output:
'<a href="http://company.net/profiles?user_id=1234">' +
i18n.translate('common.ui.fieldEditor.labelTemplate.example.output.idLabel', {
defaultMessage: 'User',
}) +
' #1234</a>',
},
{
input: '/assets/main.css',
urlTemplate: 'http://site.com{{rawValue}}',
labelTemplate: i18n.translate('common.ui.fieldEditor.labelTemplate.example.pathLabel', {
defaultMessage: 'View Asset',
}),
output:
'<a href="http://site.com/assets/main.css">' +
i18n.translate('common.ui.fieldEditor.labelTemplate.example.output.pathLabel', {
defaultMessage: 'View Asset',
}) +
'</a>',
},
];
export const LabelTemplateFlyout = ({ isVisible = false, onClose = () => {} }) => {
return isVisible ? (
<EuiFlyout onClose={onClose}>
@ -66,40 +103,8 @@ export const LabelTemplateFlyout = ({ isVisible = false, onClose = () => {} }) =
defaultMessage="Examples"
/>
</h4>
<EuiBasicTable
items={[
{
input: 1234,
urlTemplate: 'http://company.net/profiles?user_id={{value}}',
labelTemplate: i18n.translate(
'common.ui.fieldEditor.labelTemplate.example.idLabel',
{
defaultMessage: 'User #{value}',
values: { value: '{{value}}' },
}
),
output:
'<a href="http://company.net/profiles?user_id=1234">' +
i18n.translate('common.ui.fieldEditor.labelTemplate.example.output.idLabel', {
defaultMessage: 'User',
}) +
' #1234</a>',
},
{
input: '/assets/main.css',
urlTemplate: 'http://site.com{{rawValue}}',
labelTemplate: i18n.translate(
'common.ui.fieldEditor.labelTemplate.example.pathLabel',
{ defaultMessage: 'View Asset' }
),
output:
'<a href="http://site.com/assets/main.css">' +
i18n.translate('common.ui.fieldEditor.labelTemplate.example.output.pathLabel', {
defaultMessage: 'View Asset',
}) +
'</a>',
},
]}
<EuiBasicTable<LabelTemplateExampleItem>
items={items}
columns={[
{
field: 'input',
@ -125,14 +130,14 @@ export const LabelTemplateFlyout = ({ isVisible = false, onClose = () => {} }) =
name: i18n.translate('common.ui.fieldEditor.labelTemplate.outputHeader', {
defaultMessage: 'Output',
}),
render: value => {
render: (value: LabelTemplateExampleItem['output']) => {
return (
<span
/*
* Justification for dangerouslySetInnerHTML:
* Example output produces anchor link.
*/
dangerouslySetInnerHTML={{ __html: value }} //eslint-disable-line react/no-danger
dangerouslySetInnerHTML={{ __html: value }} // eslint-disable-line react/no-danger
/>
);
},

View file

@ -19,12 +19,15 @@
import React from 'react';
import { shallow } from 'enzyme';
import { FieldFormat } from 'src/plugins/data/public';
import { UrlFormatEditor } from './url';
const fieldType = 'string';
const format = {
getConverterFor: jest.fn().mockImplementation(() => input => `converted url for ${input}`),
getConverterFor: jest
.fn()
.mockImplementation(() => (input: string) => `converted url for ${input}`),
type: {
urlTypes: [
{ kind: 'a', text: 'Link' },
@ -33,7 +36,13 @@ const format = {
],
},
};
const formatParams = {};
const formatParams = {
openLinkInCurrentTab: true,
urlTemplate: '',
labelTemplate: '',
width: '',
height: '',
};
const onChange = jest.fn();
const onError = jest.fn();
@ -49,8 +58,9 @@ describe('UrlFormatEditor', () => {
it('should render normally', async () => {
const component = shallow(
<UrlFormatEditor
basePath={''}
fieldType={fieldType}
format={format}
format={(format as unknown) as FieldFormat}
formatParams={formatParams}
onChange={onChange}
onError={onError}
@ -63,15 +73,16 @@ describe('UrlFormatEditor', () => {
it('should render url template help', async () => {
const component = shallow(
<UrlFormatEditor
basePath={''}
fieldType={fieldType}
format={format}
format={(format as unknown) as FieldFormat}
formatParams={formatParams}
onChange={onChange}
onError={onError}
/>
);
component.instance().showUrlTemplateHelp();
(component.instance() as UrlFormatEditor).showUrlTemplateHelp();
component.update();
expect(component).toMatchSnapshot();
});
@ -79,15 +90,16 @@ describe('UrlFormatEditor', () => {
it('should render label template help', async () => {
const component = shallow(
<UrlFormatEditor
basePath={''}
fieldType={fieldType}
format={format}
format={(format as unknown) as FieldFormat}
formatParams={formatParams}
onChange={onChange}
onError={onError}
/>
);
component.instance().showLabelTemplateHelp();
(component.instance() as UrlFormatEditor).showLabelTemplateHelp();
component.update();
expect(component).toMatchSnapshot();
});
@ -95,8 +107,9 @@ describe('UrlFormatEditor', () => {
it('should render width and height fields if image', async () => {
const component = shallow(
<UrlFormatEditor
basePath={''}
fieldType={fieldType}
format={format}
format={(format as unknown) as FieldFormat}
formatParams={{ ...formatParams, type: 'img' }}
onChange={onChange}
onError={onError}

View file

@ -28,7 +28,8 @@ import {
EuiFieldNumber,
} from '@elastic/eui';
import { DefaultFormatEditor } from '../default';
import { FormattedMessage } from '@kbn/i18n/react';
import { DefaultFormatEditor, FormatEditorProps } from '../default';
import { FormatEditorSamples } from '../../samples';
@ -36,18 +37,44 @@ import { LabelTemplateFlyout } from './label_template_flyout';
import { UrlTemplateFlyout } from './url_template_flyout';
import chrome from 'ui/chrome';
import './icons';
import { FormattedMessage } from '@kbn/i18n/react';
interface OnChangeParam {
type: string;
width?: string;
height?: string;
urlTemplate?: string;
}
export class UrlFormatEditor extends DefaultFormatEditor {
interface UrlFormatEditorFormatParams {
openLinkInCurrentTab: boolean;
urlTemplate: string;
labelTemplate: string;
width: string;
height: string;
}
interface UrlFormatEditorFormatState {
showLabelTemplateHelp: boolean;
showUrlTemplateHelp: boolean;
}
interface UrlType {
kind: string;
text: string;
}
export class UrlFormatEditor extends DefaultFormatEditor<
UrlFormatEditorFormatParams,
UrlFormatEditorFormatState
> {
static formatId = 'url';
iconPattern: string;
constructor(props) {
constructor(props: FormatEditorProps<UrlFormatEditorFormatParams>) {
super(props);
const bp = chrome.getBasePath();
this.iconPattern = `${bp}/bundles/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/icons/{{value}}.png`;
this.iconPattern = `${props.basePath}/bundles/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/icons/{{value}}.png`;
this.state = {
...this.state,
sampleInputsByType: {
@ -61,17 +88,17 @@ export class UrlFormatEditor extends DefaultFormatEditor {
};
}
sanitizeNumericValue = val => {
const sanitizedValue = parseInt(val);
sanitizeNumericValue = (val: string) => {
const sanitizedValue = parseInt(val, 10);
if (isNaN(sanitizedValue)) {
return '';
}
return sanitizedValue;
};
onTypeChange = newType => {
onTypeChange = (newType: string) => {
const { urlTemplate, width, height } = this.props.formatParams;
const params = {
const params: OnChangeParam = {
type: newType,
};
if (newType === 'img') {
@ -81,7 +108,7 @@ export class UrlFormatEditor extends DefaultFormatEditor {
params.urlTemplate = this.iconPattern;
}
} else if (newType !== 'img' && urlTemplate === this.iconPattern) {
params.urlTemplate = null;
params.urlTemplate = undefined;
}
this.onChange(params);
};
@ -169,7 +196,7 @@ export class UrlFormatEditor extends DefaultFormatEditor {
<EuiSelect
data-test-subj="urlEditorType"
value={formatParams.type}
options={format.type.urlTypes.map(type => {
options={format.type.urlTypes.map((type: UrlType) => {
return {
value: type.kind,
text: type.text,

View file

@ -21,6 +21,7 @@ import React, { PureComponent } from 'react';
import { shallow } from 'enzyme';
import { FieldFormatEditor } from './field_format_editor';
import { DefaultFormatEditor } from './editors/default';
class TestEditor extends PureComponent {
render() {
@ -31,19 +32,22 @@ class TestEditor extends PureComponent {
}
}
const formatEditors = {
byFormatId: {
ip: TestEditor,
number: TestEditor,
},
};
describe('FieldFormatEditor', () => {
it('should render normally', async () => {
const component = shallow(
<FieldFormatEditor
fieldType="number"
fieldFormat={{}}
fieldFormat={{} as DefaultFormatEditor}
fieldFormatId="number"
fieldFormatParams={{}}
fieldFormatEditors={{
getEditor: () => {
return TestEditor;
},
}}
fieldFormatEditors={formatEditors}
onChange={() => {}}
onError={() => {}}
/>
@ -56,14 +60,10 @@ describe('FieldFormatEditor', () => {
const component = shallow(
<FieldFormatEditor
fieldType="number"
fieldFormat={{}}
fieldFormat={{} as DefaultFormatEditor}
fieldFormatId="ip"
fieldFormatParams={{}}
fieldFormatEditors={{
getEditor: () => {
return null;
},
}}
fieldFormatEditors={formatEditors}
onChange={() => {}}
onError={() => {}}
/>

View file

@ -18,29 +18,44 @@
*/
import React, { PureComponent, Fragment } from 'react';
import PropTypes from 'prop-types';
import { DefaultFormatEditor } from '../../components/field_format_editor/editors/default';
export class FieldFormatEditor extends PureComponent {
static propTypes = {
fieldType: PropTypes.string.isRequired,
fieldFormat: PropTypes.object.isRequired,
fieldFormatId: PropTypes.string.isRequired,
fieldFormatParams: PropTypes.object.isRequired,
fieldFormatEditors: PropTypes.object.isRequired,
onChange: PropTypes.func.isRequired,
onError: PropTypes.func.isRequired,
};
export interface FieldFormatEditorProps {
fieldType: string;
fieldFormat: DefaultFormatEditor;
fieldFormatId: string;
fieldFormatParams: { [key: string]: unknown };
fieldFormatEditors: any;
onChange: (change: { fieldType: string; [key: string]: any }) => void;
onError: (error?: string) => void;
}
constructor(props) {
interface EditorComponentProps {
fieldType: FieldFormatEditorProps['fieldType'];
format: FieldFormatEditorProps['fieldFormat'];
formatParams: FieldFormatEditorProps['fieldFormatParams'];
onChange: FieldFormatEditorProps['onChange'];
onError: FieldFormatEditorProps['onError'];
}
interface FieldFormatEditorState {
EditorComponent: React.FC<EditorComponentProps>;
}
export class FieldFormatEditor extends PureComponent<
FieldFormatEditorProps,
FieldFormatEditorState
> {
constructor(props: FieldFormatEditorProps) {
super(props);
this.state = {
EditorComponent: null,
EditorComponent: props.fieldFormatEditors.byFormatId[props.fieldFormatId],
};
}
static getDerivedStateFromProps(nextProps) {
static getDerivedStateFromProps(nextProps: FieldFormatEditorProps) {
return {
EditorComponent: nextProps.fieldFormatEditors.getEditor(nextProps.fieldFormatId) || null,
EditorComponent: nextProps.fieldFormatEditors.byFormatId[nextProps.fieldFormatId] || null,
};
}

View file

@ -41,7 +41,7 @@ exports[`FormatEditorSamples should render normally 1`] = `
},
Object {
"input": 123,
"output": 456,
"output": "456",
},
Object {
"input": Array [

View file

@ -28,7 +28,7 @@ describe('FormatEditorSamples', () => {
<FormatEditorSamples
samples={[
{ input: 'test', output: 'TEST' },
{ input: 123, output: 456 },
{ input: 123, output: '456' },
{ input: ['foo', 'bar'], output: '<span>foo</span>, <span>bar</span>' },
]}
/>

View file

@ -18,26 +18,22 @@
*/
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { EuiBasicTable, EuiFormRow } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { Sample } from '../../../types';
export class FormatEditorSamples extends PureComponent {
interface FormatEditorSamplesProps {
samples: Sample[];
sampleType: string;
}
export class FormatEditorSamples extends PureComponent<FormatEditorSamplesProps> {
static defaultProps = {
sampleType: 'text',
};
static propTypes = {
samples: PropTypes.arrayOf(
PropTypes.shape({
input: PropTypes.any.isRequired,
output: PropTypes.any.isRequired,
})
).isRequired,
sampleType: PropTypes.oneOf(['html', 'text']),
};
render() {
const { samples, sampleType } = this.props;
@ -48,7 +44,7 @@ export class FormatEditorSamples extends PureComponent {
name: i18n.translate('common.ui.fieldEditor.samples.inputHeader', {
defaultMessage: 'Input',
}),
render: input => {
render: (input: {} | string) => {
return typeof input === 'object' ? JSON.stringify(input) : input;
},
},
@ -57,14 +53,14 @@ export class FormatEditorSamples extends PureComponent {
name: i18n.translate('common.ui.fieldEditor.samples.outputHeader', {
defaultMessage: 'Output',
}),
render: output => {
render: (output: string) => {
return sampleType === 'html' ? (
<div
/*
* Justification for dangerouslySetInnerHTML:
* Sample output may contain HTML tags, like URL image/audio format.
*/
dangerouslySetInnerHTML={{ __html: output }} //eslint-disable-line react/no-danger
dangerouslySetInnerHTML={{ __html: output }} // eslint-disable-line react/no-danger
/>
) : (
<div>{output}</div>
@ -79,7 +75,7 @@ export class FormatEditorSamples extends PureComponent {
<FormattedMessage id="common.ui.fieldEditor.samplesHeader" defaultMessage="Samples" />
}
>
<EuiBasicTable
<EuiBasicTable<Sample>
className="kbnFieldFormatEditor__samples"
compressed={true}
items={samples}

View file

@ -20,7 +20,6 @@ exports[`ScriptingWarningCallOut should render normally 1`] = `
values={
Object {
"scripFields": <ForwardRef
href="(docLink for scriptedFields.scriptFields)"
target="_blank"
>
<FormattedMessage
@ -34,7 +33,6 @@ exports[`ScriptingWarningCallOut should render normally 1`] = `
/>
</ForwardRef>,
"scriptsInAggregation": <ForwardRef
href="(docLink for scriptedFields.scriptAggs)"
target="_blank"
>
<FormattedMessage

View file

@ -20,28 +20,17 @@
import React from 'react';
import { shallow } from 'enzyme';
import { ScriptingHelpFlyout } from './help_flyout';
import { ScriptingWarningCallOut } from './warning_call_out';
// eslint-disable-next-line
import { docLinksServiceMock } from '../../../../../../core/public/doc_links/doc_links_service.mock';
jest.mock('ui/documentation_links', () => ({
getDocLink: doc => `(docLink for ${doc})`,
}));
jest.mock('./test_script', () => ({
TestScript: () => {
return `<div>mockTestScript</div>`;
},
}));
const indexPatternMock = {};
describe('ScriptingHelpFlyout', () => {
describe('ScriptingWarningCallOut', () => {
const docLinksScriptedFields = docLinksServiceMock.createStartContract().links.scriptedFields;
it('should render normally', async () => {
const component = shallow(
<ScriptingHelpFlyout
<ScriptingWarningCallOut
isVisible={true}
indexPattern={indexPatternMock}
lang="painless"
executeScript={() => {}}
docLinksScriptedFields={{} as typeof docLinksScriptedFields}
/>
);
@ -50,10 +39,9 @@ describe('ScriptingHelpFlyout', () => {
it('should render nothing if not visible', async () => {
const component = shallow(
<ScriptingHelpFlyout
indexPattern={indexPatternMock}
lang="painless"
executeScript={() => {}}
<ScriptingWarningCallOut
isVisible={false}
docLinksScriptedFields={{} as typeof docLinksScriptedFields}
/>
);

View file

@ -18,13 +18,21 @@
*/
import React, { Fragment } from 'react';
import { getDocLink } from 'ui/documentation_links';
import { DocLinksStart } from 'src/core/public';
import { EuiCallOut, EuiIcon, EuiLink, EuiSpacer } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
export const ScriptingWarningCallOut = ({ isVisible = false }) => {
export interface ScriptingWarningCallOutProps {
isVisible: boolean;
docLinksScriptedFields: DocLinksStart['links']['scriptedFields'];
}
export const ScriptingWarningCallOut = ({
isVisible = false,
docLinksScriptedFields,
}: ScriptingWarningCallOutProps) => {
return isVisible ? (
<Fragment>
<EuiCallOut
@ -43,7 +51,7 @@ export const ScriptingWarningCallOut = ({ isVisible = false }) => {
defaultMessage="Please familiarize yourself with {scripFields} and with {scriptsInAggregation} before using scripted fields."
values={{
scripFields: (
<EuiLink target="_blank" href={getDocLink('scriptedFields.scriptFields')}>
<EuiLink target="_blank" href={docLinksScriptedFields.scriptFields}>
<FormattedMessage
id="common.ui.fieldEditor.warningCallOutLabel.scripFieldsLink"
defaultMessage="script fields"
@ -53,7 +61,7 @@ export const ScriptingWarningCallOut = ({ isVisible = false }) => {
</EuiLink>
),
scriptsInAggregation: (
<EuiLink target="_blank" href={getDocLink('scriptedFields.scriptAggs')}>
<EuiLink target="_blank" href={docLinksScriptedFields.scriptAggs}>
<FormattedMessage
id="common.ui.fieldEditor.warningCallOutLabel.scriptsInAggregationLink"
defaultMessage="scripts in aggregations"

Some files were not shown because too many files have changed in this diff Show more