;
+}
- constructor(props) {
- super(props);
- this.state = {
- sampleInputs: [],
- sampleConverterType: 'text',
- error: null,
- samples: [],
- };
- }
+export interface FormatEditorProps {
+ fieldType: string;
+ format: FieldFormat;
+ formatParams: { type?: string } & P;
+ onChange: (newParams: Record) => 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 extends PureComponent<
+ FormatEditorProps
,
+ 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 <>>;
}
}
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/default/index.ts b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/default/index.ts
new file mode 100644
index 0000000000000..a6575f296864d
--- /dev/null
+++ b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/default/index.ts
@@ -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 { DefaultFormatEditor, defaultState, FormatEditorProps, FormatEditorState } from './default';
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/duration/__snapshots__/duration.test.js.snap b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/duration/__snapshots__/duration.test.tsx.snap
similarity index 98%
rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/duration/__snapshots__/duration.test.js.snap
rename to src/legacy/ui/public/field_editor/components/field_format_editor/editors/duration/__snapshots__/duration.test.tsx.snap
index ef11d70926ad7..dbebd324b16b6 100644
--- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/duration/__snapshots__/duration.test.js.snap
+++ b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/duration/__snapshots__/duration.test.tsx.snap
@@ -5,7 +5,6 @@ exports[`DurationFormatEditor should render human readable output normally 1`] =
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(
{
};
const component = shallow(
{
+ static formatId = 'duration';
+ state = {
+ ...defaultState,
+ sampleInputs: [-123, 1, 12, 123, 658, 1988, 3857, 123292, 923528271],
+ hasDecimalError: false,
+ };
- static getDerivedStateFromProps(nextProps, state) {
+ static getDerivedStateFromProps(
+ nextProps: FormatEditorProps,
+ 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 {
>
{
+ 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 {
>
{
+ 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}
/>
- {!format.isHuman() ? (
+ {!(format as DurationFormat).isHuman() ? (
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(
{
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;
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/percent/__snapshots__/percent.test.js.snap b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/percent/__snapshots__/percent.test.tsx.snap
similarity index 99%
rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/percent/__snapshots__/percent.test.js.snap
rename to src/legacy/ui/public/field_editor/components/field_format_editor/editors/percent/__snapshots__/percent.test.tsx.snap
index 30d1de270522e..0784a3f5e407d 100644
--- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/percent/__snapshots__/percent.test.js.snap
+++ b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/percent/__snapshots__/percent.test.tsx.snap
@@ -5,7 +5,6 @@ exports[`PercentFormatEditor should render normally 1`] = `
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(
{
it('should render normally', async () => {
const component = shallowWithI18nProvider(
{
it('should render multiple lookup entries and unknown key value', async () => {
const component = shallowWithI18nProvider(
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/static_lookup/static_lookup.js b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/static_lookup/static_lookup.tsx
similarity index 86%
rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/static_lookup/static_lookup.js
rename to src/legacy/ui/public/field_editor/components/field_format_editor/editors/static_lookup/static_lookup.tsx
index 31ff99696da01..f998e271b6c99 100644
--- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/static_lookup/static_lookup.js
+++ b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/static_lookup/static_lookup.tsx
@@ -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 interface StaticLookupFormatEditorFormatParams {
+ lookupEntries: Array<{ key: string; value: string }>;
+ unknownKeyValue: string;
+}
+
+interface StaticLookupItem {
+ key: string;
+ value: string;
+ index: number;
+}
-export class StaticLookupFormatEditor extends DefaultFormatEditor {
- onLookupChange = (newLookupParams, index) => {
+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: (
),
- render: (value, item) => {
+ render: (value: number, item: StaticLookupItem) => {
return (
),
- render: (value, item) => {
+ render: (value: number, item: StaticLookupItem) => {
return (
{
+ onClick: (item: StaticLookupItem) => {
this.removeLookup(item.index);
},
type: 'icon',
@@ -172,5 +189,3 @@ export class StaticLookupFormatEditor extends DefaultFormatEditor {
);
}
}
-
-StaticLookupFormatEditor.formatId = 'static_lookup';
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/string/__snapshots__/string.test.js.snap b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/string/__snapshots__/string.test.tsx.snap
similarity index 98%
rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/string/__snapshots__/string.test.js.snap
rename to src/legacy/ui/public/field_editor/components/field_format_editor/editors/string/__snapshots__/string.test.tsx.snap
index 270ff844fd086..cde081ff10d14 100644
--- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/string/__snapshots__/string.test.js.snap
+++ b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/string/__snapshots__/string.test.tsx.snap
@@ -5,7 +5,6 @@ exports[`StringFormatEditor should render normally 1`] = `
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(
{
+ static formatId = 'string';
+ 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 {
{
+ options={format.type.transformOptions.map((option: TransformOptions) => {
return {
value: option.kind,
text: option.text,
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/truncate/__snapshots__/truncate.test.js.snap b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/truncate/__snapshots__/truncate.test.tsx.snap
similarity index 98%
rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/truncate/__snapshots__/truncate.test.js.snap
rename to src/legacy/ui/public/field_editor/components/field_format_editor/editors/truncate/__snapshots__/truncate.test.tsx.snap
index 729487dfae5d7..f646d5b4afca8 100644
--- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/truncate/__snapshots__/truncate.test.js.snap
+++ b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/truncate/__snapshots__/truncate.test.tsx.snap
@@ -5,7 +5,6 @@ exports[`TruncateFormatEditor should render normally 1`] = `
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(
{
it('should fire error, when input is invalid', async () => {
const component = shallow(
{
validationMessage: 'Error!',
},
};
- await input.invoke('onChange')(changeEvent);
+
+ await input!.invoke('onChange')!((changeEvent as unknown) as ChangeEvent);
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(
{
},
};
onError.mockClear();
- await input.invoke('onChange')(changeEvent);
+ await input!.invoke('onChange')!((changeEvent as unknown) as ChangeEvent);
expect(onError).not.toBeCalled();
expect(onChange).toBeCalledWith({ fieldLength: 123 });
});
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/truncate/truncate.js b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/truncate/truncate.tsx
similarity index 87%
rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/truncate/truncate.js
rename to src/legacy/ui/public/field_editor/components/field_format_editor/editors/truncate/truncate.tsx
index 9a9b6c954b78d..9fd44c5f9655d 100644
--- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/truncate/truncate.js
+++ b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/truncate/truncate.tsx
@@ -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 {
static formatId = 'truncate';
-
- constructor(props) {
- super(props);
- this.state.sampleInputs = [sample];
- }
+ state = {
+ ...defaultState,
+ sampleInputs: [sample],
+ };
render() {
const { formatParams, onError } = this.props;
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/label_template_flyout.test.js.snap b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/label_template_flyout.test.tsx.snap
similarity index 100%
rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/label_template_flyout.test.js.snap
rename to src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/label_template_flyout.test.tsx.snap
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/url.test.js.snap b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/url.test.tsx.snap
similarity index 98%
rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/url.test.js.snap
rename to src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/url.test.tsx.snap
index c727f54874db4..a3418077ad258 100644
--- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/url.test.js.snap
+++ b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/url.test.tsx.snap
@@ -49,7 +49,6 @@ exports[`UrlFormatEditor should render label template help 1`] = `
' +
+ i18n.translate('common.ui.fieldEditor.labelTemplate.example.output.idLabel', {
+ defaultMessage: 'User',
+ }) +
+ ' #1234',
+ },
+ {
+ input: '/assets/main.css',
+ urlTemplate: 'http://site.com{{rawValue}}',
+ labelTemplate: i18n.translate('common.ui.fieldEditor.labelTemplate.example.pathLabel', {
+ defaultMessage: 'View Asset',
+ }),
+ output:
+ '' +
+ i18n.translate('common.ui.fieldEditor.labelTemplate.example.output.pathLabel', {
+ defaultMessage: 'View Asset',
+ }) +
+ '',
+ },
+];
+
export const LabelTemplateFlyout = ({ isVisible = false, onClose = () => {} }) => {
return isVisible ? (
@@ -66,40 +103,8 @@ export const LabelTemplateFlyout = ({ isVisible = false, onClose = () => {} }) =
defaultMessage="Examples"
/>
- ' +
- i18n.translate('common.ui.fieldEditor.labelTemplate.example.output.idLabel', {
- defaultMessage: 'User',
- }) +
- ' #1234',
- },
- {
- input: '/assets/main.css',
- urlTemplate: 'http://site.com{{rawValue}}',
- labelTemplate: i18n.translate(
- 'common.ui.fieldEditor.labelTemplate.example.pathLabel',
- { defaultMessage: 'View Asset' }
- ),
- output:
- '' +
- i18n.translate('common.ui.fieldEditor.labelTemplate.example.output.pathLabel', {
- defaultMessage: 'View Asset',
- }) +
- '',
- },
- ]}
+
+ 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 (
);
},
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/url.test.js b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/url.test.tsx
similarity index 78%
rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/url.test.js
rename to src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/url.test.tsx
index 1d732b50db3d0..4d09da84edfb6 100644
--- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/url.test.js
+++ b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/url.test.tsx
@@ -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(
{
it('should render url template help', async () => {
const component = shallow(
);
- 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(
);
- 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(
{
static formatId = 'url';
+ iconPattern: string;
- constructor(props) {
+ constructor(props: FormatEditorProps) {
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 {
{
+ options={format.type.urlTypes.map((type: UrlType) => {
return {
value: type.kind,
text: type.text,
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/url_template_flyout.test.js b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/url_template_flyout.test.tsx
similarity index 100%
rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/url_template_flyout.test.js
rename to src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/url_template_flyout.test.tsx
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/url_template_flyout.js b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/url_template_flyout.tsx
similarity index 100%
rename from src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/url_template_flyout.js
rename to src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/url_template_flyout.tsx
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/field_format_editor.test.js b/src/legacy/ui/public/field_editor/components/field_format_editor/field_format_editor.test.tsx
similarity index 84%
rename from src/legacy/ui/public/field_editor/components/field_format_editor/field_format_editor.test.js
rename to src/legacy/ui/public/field_editor/components/field_format_editor/field_format_editor.test.tsx
index 9e03841397872..f6e631c8b7ac0 100644
--- a/src/legacy/ui/public/field_editor/components/field_format_editor/field_format_editor.test.js
+++ b/src/legacy/ui/public/field_editor/components/field_format_editor/field_format_editor.test.tsx
@@ -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(
{
- return TestEditor;
- },
- }}
+ fieldFormatEditors={formatEditors}
onChange={() => {}}
onError={() => {}}
/>
@@ -56,14 +60,10 @@ describe('FieldFormatEditor', () => {
const component = shallow(
{
- return null;
- },
- }}
+ fieldFormatEditors={formatEditors}
onChange={() => {}}
onError={() => {}}
/>
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/field_format_editor.js b/src/legacy/ui/public/field_editor/components/field_format_editor/field_format_editor.tsx
similarity index 54%
rename from src/legacy/ui/public/field_editor/components/field_format_editor/field_format_editor.js
rename to src/legacy/ui/public/field_editor/components/field_format_editor/field_format_editor.tsx
index 204554ad94644..2de6dff5d251a 100644
--- a/src/legacy/ui/public/field_editor/components/field_format_editor/field_format_editor.js
+++ b/src/legacy/ui/public/field_editor/components/field_format_editor/field_format_editor.tsx
@@ -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;
+}
+
+interface EditorComponentProps {
+ fieldType: FieldFormatEditorProps['fieldType'];
+ format: FieldFormatEditorProps['fieldFormat'];
+ formatParams: FieldFormatEditorProps['fieldFormatParams'];
+ onChange: FieldFormatEditorProps['onChange'];
+ onError: FieldFormatEditorProps['onError'];
+}
+
+interface FieldFormatEditorState {
+ EditorComponent: React.FC;
+}
- constructor(props) {
+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,
};
}
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/index.js b/src/legacy/ui/public/field_editor/components/field_format_editor/index.ts
similarity index 100%
rename from src/legacy/ui/public/field_editor/components/field_format_editor/index.js
rename to src/legacy/ui/public/field_editor/components/field_format_editor/index.ts
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/register.js b/src/legacy/ui/public/field_editor/components/field_format_editor/register.ts
similarity index 100%
rename from src/legacy/ui/public/field_editor/components/field_format_editor/register.js
rename to src/legacy/ui/public/field_editor/components/field_format_editor/register.ts
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/samples/__snapshots__/samples.test.js.snap b/src/legacy/ui/public/field_editor/components/field_format_editor/samples/__snapshots__/samples.test.tsx.snap
similarity index 97%
rename from src/legacy/ui/public/field_editor/components/field_format_editor/samples/__snapshots__/samples.test.js.snap
rename to src/legacy/ui/public/field_editor/components/field_format_editor/samples/__snapshots__/samples.test.tsx.snap
index 73a7c1141c601..2883ffb6bc8a1 100644
--- a/src/legacy/ui/public/field_editor/components/field_format_editor/samples/__snapshots__/samples.test.js.snap
+++ b/src/legacy/ui/public/field_editor/components/field_format_editor/samples/__snapshots__/samples.test.tsx.snap
@@ -41,7 +41,7 @@ exports[`FormatEditorSamples should render normally 1`] = `
},
Object {
"input": 123,
- "output": 456,
+ "output": "456",
},
Object {
"input": Array [
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/samples/index.js b/src/legacy/ui/public/field_editor/components/field_format_editor/samples/index.ts
similarity index 100%
rename from src/legacy/ui/public/field_editor/components/field_format_editor/samples/index.js
rename to src/legacy/ui/public/field_editor/components/field_format_editor/samples/index.ts
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/samples/samples.test.js b/src/legacy/ui/public/field_editor/components/field_format_editor/samples/samples.test.tsx
similarity index 97%
rename from src/legacy/ui/public/field_editor/components/field_format_editor/samples/samples.test.js
rename to src/legacy/ui/public/field_editor/components/field_format_editor/samples/samples.test.tsx
index 8e18f1f5f4de8..01f405e9aff1f 100644
--- a/src/legacy/ui/public/field_editor/components/field_format_editor/samples/samples.test.js
+++ b/src/legacy/ui/public/field_editor/components/field_format_editor/samples/samples.test.tsx
@@ -28,7 +28,7 @@ describe('FormatEditorSamples', () => {
foo, bar' },
]}
/>
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/samples/samples.js b/src/legacy/ui/public/field_editor/components/field_format_editor/samples/samples.tsx
similarity index 81%
rename from src/legacy/ui/public/field_editor/components/field_format_editor/samples/samples.js
rename to src/legacy/ui/public/field_editor/components/field_format_editor/samples/samples.tsx
index b3345f085882c..d63674bf4d205 100644
--- a/src/legacy/ui/public/field_editor/components/field_format_editor/samples/samples.js
+++ b/src/legacy/ui/public/field_editor/components/field_format_editor/samples/samples.tsx
@@ -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 {
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' ? (
) : (
{output}
@@ -79,7 +75,7 @@ export class FormatEditorSamples extends PureComponent {
}
>
-
className="kbnFieldFormatEditor__samples"
compressed={true}
items={samples}
diff --git a/src/legacy/ui/public/field_editor/components/scripting_call_outs/__snapshots__/disabled_call_out.test.js.snap b/src/legacy/ui/public/field_editor/components/scripting_call_outs/__snapshots__/disabled_call_out.test.tsx.snap
similarity index 100%
rename from src/legacy/ui/public/field_editor/components/scripting_call_outs/__snapshots__/disabled_call_out.test.js.snap
rename to src/legacy/ui/public/field_editor/components/scripting_call_outs/__snapshots__/disabled_call_out.test.tsx.snap
diff --git a/src/legacy/ui/public/field_editor/components/scripting_call_outs/__snapshots__/warning_call_out.test.js.snap b/src/legacy/ui/public/field_editor/components/scripting_call_outs/__snapshots__/warning_call_out.test.tsx.snap
similarity index 94%
rename from src/legacy/ui/public/field_editor/components/scripting_call_outs/__snapshots__/warning_call_out.test.js.snap
rename to src/legacy/ui/public/field_editor/components/scripting_call_outs/__snapshots__/warning_call_out.test.tsx.snap
index f09ea05f6711a..b331c1e38eb34 100644
--- a/src/legacy/ui/public/field_editor/components/scripting_call_outs/__snapshots__/warning_call_out.test.js.snap
+++ b/src/legacy/ui/public/field_editor/components/scripting_call_outs/__snapshots__/warning_call_out.test.tsx.snap
@@ -20,7 +20,6 @@ exports[`ScriptingWarningCallOut should render normally 1`] = `
values={
Object {
"scripFields":
,
"scriptsInAggregation":
({
- getDocLink: doc => `(docLink for ${doc})`,
-}));
-
-jest.mock('./test_script', () => ({
- TestScript: () => {
- return `mockTestScript
`;
- },
-}));
-
-const indexPatternMock = {};
-
-describe('ScriptingHelpFlyout', () => {
+describe('ScriptingWarningCallOut', () => {
+ const docLinksScriptedFields = docLinksServiceMock.createStartContract().links.scriptedFields;
it('should render normally', async () => {
const component = shallow(
- {}}
+ docLinksScriptedFields={{} as typeof docLinksScriptedFields}
/>
);
@@ -50,10 +39,9 @@ describe('ScriptingHelpFlyout', () => {
it('should render nothing if not visible', async () => {
const component = shallow(
- {}}
+
);
diff --git a/src/legacy/ui/public/field_editor/components/scripting_call_outs/warning_call_out.js b/src/legacy/ui/public/field_editor/components/scripting_call_outs/warning_call_out.tsx
similarity index 85%
rename from src/legacy/ui/public/field_editor/components/scripting_call_outs/warning_call_out.js
rename to src/legacy/ui/public/field_editor/components/scripting_call_outs/warning_call_out.tsx
index b810541d72697..7dac6681fa1ea 100644
--- a/src/legacy/ui/public/field_editor/components/scripting_call_outs/warning_call_out.js
+++ b/src/legacy/ui/public/field_editor/components/scripting_call_outs/warning_call_out.tsx
@@ -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 ? (
{
defaultMessage="Please familiarize yourself with {scripFields} and with {scriptsInAggregation} before using scripted fields."
values={{
scripFields: (
-
+
{
),
scriptsInAggregation: (
-
+
-
- ,
- "data-test-subj": "syntaxTab",
- "id": "syntax",
- "name": "Syntax",
- }
- }
- tabs={
- Array [
- Object {
- "content": ,
- "data-test-subj": "syntaxTab",
- "id": "syntax",
- "name": "Syntax",
- },
- Object {
- "content": ,
- "data-test-subj": "testTab",
- "id": "test",
- "name": "Preview results",
- },
- ]
- }
- />
-
-
-`;
-
-exports[`ScriptingHelpFlyout should render nothing if not visible 1`] = `""`;
diff --git a/src/legacy/ui/public/field_editor/components/scripting_help/__snapshots__/help_flyout.test.tsx.snap b/src/legacy/ui/public/field_editor/components/scripting_help/__snapshots__/help_flyout.test.tsx.snap
new file mode 100644
index 0000000000000..282e8e311d984
--- /dev/null
+++ b/src/legacy/ui/public/field_editor/components/scripting_help/__snapshots__/help_flyout.test.tsx.snap
@@ -0,0 +1,103 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ScriptingHelpFlyout should render normally 1`] = `
+
+
+ ,
+ "data-test-subj": "syntaxTab",
+ "id": "syntax",
+ "name": "Syntax",
+ }
+ }
+ tabs={
+ Array [
+ Object {
+ "content": ,
+ "data-test-subj": "syntaxTab",
+ "id": "syntax",
+ "name": "Syntax",
+ },
+ Object {
+ "content": ,
+ "data-test-subj": "testTab",
+ "id": "test",
+ "name": "Preview results",
+ },
+ ]
+ }
+ />
+
+
+`;
+
+exports[`ScriptingHelpFlyout should render nothing if not visible 1`] = `
+
+
+ ,
+ "data-test-subj": "syntaxTab",
+ "id": "syntax",
+ "name": "Syntax",
+ }
+ }
+ tabs={
+ Array [
+ Object {
+ "content": ,
+ "data-test-subj": "syntaxTab",
+ "id": "syntax",
+ "name": "Syntax",
+ },
+ Object {
+ "content": ,
+ "data-test-subj": "testTab",
+ "id": "test",
+ "name": "Preview results",
+ },
+ ]
+ }
+ />
+
+
+`;
diff --git a/src/legacy/ui/public/field_editor/components/scripting_help/help_flyout.test.tsx b/src/legacy/ui/public/field_editor/components/scripting_help/help_flyout.test.tsx
new file mode 100644
index 0000000000000..4106eb7b283ee
--- /dev/null
+++ b/src/legacy/ui/public/field_editor/components/scripting_help/help_flyout.test.tsx
@@ -0,0 +1,74 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React from 'react';
+import { shallow } from 'enzyme';
+import { HttpStart } from 'src/core/public';
+// eslint-disable-next-line
+import { docLinksServiceMock } from '../../../../../../core/public/doc_links/doc_links_service.mock';
+
+import { ScriptingHelpFlyout } from './help_flyout';
+
+import { IndexPattern } from '../../../../../../plugins/data/public';
+
+import { ExecuteScript } from '../../types';
+
+jest.mock('./test_script', () => ({
+ TestScript: () => {
+ return `mockTestScript
`;
+ },
+}));
+
+const indexPatternMock = {} as IndexPattern;
+
+describe('ScriptingHelpFlyout', () => {
+ const docLinksScriptedFields = docLinksServiceMock.createStartContract().links.scriptedFields;
+ it('should render normally', async () => {
+ const component = shallow(
+ {}) as unknown) as ExecuteScript}
+ onClose={() => {}}
+ getHttpStart={() => (({} as unknown) as HttpStart)}
+ // docLinksScriptedFields={docLinksScriptedFields}
+ docLinksScriptedFields={{} as typeof docLinksScriptedFields}
+ />
+ );
+
+ expect(component).toMatchSnapshot();
+ });
+
+ it('should render nothing if not visible', async () => {
+ const component = shallow(
+ {}) as unknown) as ExecuteScript}
+ onClose={() => {}}
+ getHttpStart={() => (({} as unknown) as HttpStart)}
+ docLinksScriptedFields={{} as typeof docLinksScriptedFields}
+ />
+ );
+
+ expect(component).toMatchSnapshot();
+ });
+});
diff --git a/src/legacy/ui/public/field_editor/components/scripting_help/help_flyout.js b/src/legacy/ui/public/field_editor/components/scripting_help/help_flyout.tsx
similarity index 72%
rename from src/legacy/ui/public/field_editor/components/scripting_help/help_flyout.js
rename to src/legacy/ui/public/field_editor/components/scripting_help/help_flyout.tsx
index c512b5f5f2019..6f51379c796d4 100644
--- a/src/legacy/ui/public/field_editor/components/scripting_help/help_flyout.js
+++ b/src/legacy/ui/public/field_editor/components/scripting_help/help_flyout.tsx
@@ -18,14 +18,29 @@
*/
import React from 'react';
-import PropTypes from 'prop-types';
+import { HttpStart, DocLinksStart } from 'src/core/public';
import { EuiFlyout, EuiFlyoutBody, EuiTabbedContent } from '@elastic/eui';
import { ScriptingSyntax } from './scripting_syntax';
import { TestScript } from './test_script';
-export const ScriptingHelpFlyout = ({
+import { IndexPattern } from '../../../../../../plugins/data/public';
+import { ExecuteScript } from '../../types';
+
+interface ScriptingHelpFlyoutProps {
+ indexPattern: IndexPattern;
+ lang: string;
+ name?: string;
+ script?: string;
+ executeScript: ExecuteScript;
+ isVisible: boolean;
+ onClose: () => void;
+ getHttpStart: () => HttpStart;
+ docLinksScriptedFields: DocLinksStart['links']['scriptedFields'];
+}
+
+export const ScriptingHelpFlyout: React.FC = ({
isVisible = false,
onClose = () => {},
indexPattern,
@@ -33,13 +48,15 @@ export const ScriptingHelpFlyout = ({
name,
script,
executeScript,
+ getHttpStart,
+ docLinksScriptedFields,
}) => {
const tabs = [
{
id: 'syntax',
name: 'Syntax',
['data-test-subj']: 'syntaxTab',
- content: ,
+ content: ,
},
{
id: 'test',
@@ -52,6 +69,7 @@ export const ScriptingHelpFlyout = ({
name={name}
script={script}
executeScript={executeScript}
+ getHttpStart={getHttpStart}
/>
),
},
@@ -67,11 +85,3 @@ export const ScriptingHelpFlyout = ({
};
ScriptingHelpFlyout.displayName = 'ScriptingHelpFlyout';
-
-ScriptingHelpFlyout.propTypes = {
- indexPattern: PropTypes.object.isRequired,
- lang: PropTypes.string.isRequired,
- name: PropTypes.string,
- script: PropTypes.string,
- executeScript: PropTypes.func.isRequired,
-};
diff --git a/src/legacy/ui/public/field_editor/components/scripting_help/index.js b/src/legacy/ui/public/field_editor/components/scripting_help/index.ts
similarity index 100%
rename from src/legacy/ui/public/field_editor/components/scripting_help/index.js
rename to src/legacy/ui/public/field_editor/components/scripting_help/index.ts
diff --git a/src/legacy/ui/public/field_editor/components/scripting_help/scripting_syntax.js b/src/legacy/ui/public/field_editor/components/scripting_help/scripting_syntax.tsx
similarity index 92%
rename from src/legacy/ui/public/field_editor/components/scripting_help/scripting_syntax.js
rename to src/legacy/ui/public/field_editor/components/scripting_help/scripting_syntax.tsx
index ba47b94aaea0c..8158c6881acf9 100644
--- a/src/legacy/ui/public/field_editor/components/scripting_help/scripting_syntax.js
+++ b/src/legacy/ui/public/field_editor/components/scripting_help/scripting_syntax.tsx
@@ -18,13 +18,17 @@
*/
import React, { Fragment } from 'react';
-import { getDocLink } from 'ui/documentation_links';
+import { DocLinksStart } from 'src/core/public';
import { EuiCode, EuiIcon, EuiLink, EuiText, EuiSpacer } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
-export const ScriptingSyntax = () => (
+export interface ScriptingSyntaxProps {
+ docLinksScriptedFields: DocLinksStart['links']['scriptedFields'];
+}
+
+export const ScriptingSyntax = ({ docLinksScriptedFields }: ScriptingSyntaxProps) => (
@@ -38,7 +42,7 @@ export const ScriptingSyntax = () => (
specifically for use with Elasticsearch, to access values in the document use the following format:"
values={{
painless: (
-
+
(
you'll be up to speed in no time!"
values={{
javaAPIs: (
-
+
(
),
syntax: (
-
+
(
are a lot like JavaScript, but limited to basic arithmetic, bitwise and comparison operations."
values={{
lucene: (
-
+
HttpStart;
+}
+
+interface AdditionalField {
+ value: string;
+ label: string;
+}
+
+interface TestScriptState {
+ isLoading: boolean;
+ additionalFields: AdditionalField[];
+ previewData?: Record;
+}
+
+export class TestScript extends Component {
+ defaultProps = {
+ name: 'myScriptedField',
+ };
-export class TestScript extends Component {
state = {
isLoading: false,
additionalFields: [],
+ previewData: undefined,
};
componentDidMount() {
@@ -52,8 +79,8 @@ export class TestScript extends Component {
}
}
- previewScript = async searchContext => {
- const { indexPattern, lang, name, script, executeScript } = this.props;
+ previewScript = async (searchContext?: { query?: Query | undefined }) => {
+ const { indexPattern, lang, name, script, executeScript, getHttpStart } = this.props;
if (!script || script.length === 0) {
return;
@@ -68,21 +95,20 @@ export class TestScript extends Component {
const esQueryConfigs = esQuery.getEsQueryConfig(uiSettings);
query = esQuery.buildEsQuery(
this.props.indexPattern,
- searchContext.query,
- null,
+ searchContext.query || [],
+ [],
esQueryConfigs
);
}
const scriptResponse = await executeScript({
- name,
+ name: name as string,
lang,
script,
indexPatternTitle: indexPattern.title,
query,
- additionalFields: this.state.additionalFields.map(option => {
- return option.value;
- }),
+ additionalFields: this.state.additionalFields.map((option: AdditionalField) => option.value),
+ getHttpStart,
});
if (scriptResponse.status !== 200) {
@@ -103,15 +129,13 @@ export class TestScript extends Component {
});
};
- onAdditionalFieldsChange = selectedOptions => {
+ onAdditionalFieldsChange = (selectedOptions: AdditionalField[]) => {
this.setState({
additionalFields: selectedOptions,
});
};
- renderPreview() {
- const { previewData } = this.state;
-
+ renderPreview(previewData: { error: any } | undefined) {
if (!previewData) {
return null;
}
@@ -160,7 +184,7 @@ export class TestScript extends Component {
renderToolbar() {
const fieldsByTypeMap = new Map();
- const fields = [];
+ const fields: EuiComboBoxOptionOption[] = [];
this.props.indexPattern.fields
.filter(field => {
@@ -180,7 +204,7 @@ export class TestScript extends Component {
fieldsByTypeMap.forEach((fieldsList, fieldType) => {
fields.push({
label: fieldType,
- options: fieldsList.sort().map(fieldName => {
+ options: fieldsList.sort().map((fieldName: string) => {
return { value: fieldName, label: fieldName };
}),
});
@@ -206,7 +230,7 @@ export class TestScript extends Component {
})}
options={fields}
selectedOptions={this.state.additionalFields}
- onChange={this.onAdditionalFieldsChange}
+ onChange={selected => this.onAdditionalFieldsChange(selected as AdditionalField[])}
data-test-subj="additionalFieldsSelect"
fullWidth
/>
@@ -214,6 +238,7 @@ export class TestScript extends Component {
{this.renderToolbar()}
- {this.renderPreview()}
+ {this.renderPreview(this.state.previewData)}
);
}
}
-
-TestScript.propTypes = {
- indexPattern: PropTypes.object.isRequired,
- lang: PropTypes.string.isRequired,
- name: PropTypes.string,
- script: PropTypes.string,
- executeScript: PropTypes.func.isRequired,
-};
-
-TestScript.defaultProps = {
- name: 'myScriptedField',
-};
diff --git a/src/legacy/ui/public/field_editor/constants/index.js b/src/legacy/ui/public/field_editor/constants/index.ts
similarity index 100%
rename from src/legacy/ui/public/field_editor/constants/index.js
rename to src/legacy/ui/public/field_editor/constants/index.ts
diff --git a/src/legacy/ui/public/field_editor/field_editor.test.js b/src/legacy/ui/public/field_editor/field_editor.test.tsx
similarity index 69%
rename from src/legacy/ui/public/field_editor/field_editor.test.js
rename to src/legacy/ui/public/field_editor/field_editor.test.tsx
index cf61b6140f42c..5716305b51483 100644
--- a/src/legacy/ui/public/field_editor/field_editor.test.js
+++ b/src/legacy/ui/public/field_editor/field_editor.test.tsx
@@ -17,12 +17,19 @@
* under the License.
*/
-jest.mock('ui/kfetch', () => ({}));
-
import React from 'react';
import { npStart } from 'ui/new_platform';
import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers';
+import {
+ Field,
+ IndexPattern,
+ IndexPatternFieldList,
+ FieldFormatInstanceType,
+} from 'src/plugins/data/public';
+import { HttpStart } from '../../../../core/public';
+// eslint-disable-next-line
+import { docLinksServiceMock } from '../../../../core/public/doc_links/doc_links_service.mock';
jest.mock('brace/mode/groovy', () => ({}));
jest.mock('ui/new_platform');
@@ -54,23 +61,11 @@ jest.mock('@elastic/eui', () => ({
}));
jest.mock('ui/scripting_languages', () => ({
- GetEnabledScriptingLanguagesProvider: jest
- .fn()
- .mockImplementation(() => () => ['painless', 'testlang']),
+ getEnabledScriptingLanguages: () => ['painless', 'testlang'],
getSupportedScriptingLanguages: () => ['painless'],
getDeprecatedScriptingLanguages: () => ['testlang'],
}));
-jest.mock('ui/documentation_links', () => ({
- getDocLink: doc => `(docLink for ${doc})`,
-}));
-
-jest.mock('ui/notify', () => ({
- toastNotifications: {
- addSuccess: jest.fn(),
- },
-}));
-
jest.mock('./components/scripting_call_outs', () => ({
ScriptingDisabledCallOut: 'scripting-disabled-callOut',
ScriptingWarningCallOut: 'scripting-warning-callOut',
@@ -81,18 +76,15 @@ jest.mock('./components/field_format_editor', () => ({
FieldFormatEditor: 'field-format-editor',
}));
-const fields = [
+const fields: Field[] = [
{
name: 'foobar',
- },
+ } as Field,
];
-fields.getByName = name => {
- const fields = {
- foobar: {
- name: 'foobar',
- },
- };
- return fields[name];
+
+// @ts-ignore
+fields.getByName = (name: string) => {
+ return fields.find(field => field.name === name);
};
class Format {
@@ -111,30 +103,39 @@ const field = {
const helpers = {
Field: () => {},
getConfig: () => {},
- $http: () => {},
- fieldFormatEditors: {},
+ getHttpStart: () => (({} as unknown) as HttpStart),
+ fieldFormatEditors: [],
redirectAway: () => {},
+ docLinksScriptedFields: docLinksServiceMock.createStartContract().links.scriptedFields,
};
describe('FieldEditor', () => {
- let indexPattern;
+ let indexPattern: IndexPattern;
beforeEach(() => {
- indexPattern = {
- fields,
- };
+ indexPattern = ({
+ fields: fields as IndexPatternFieldList,
+ } as unknown) as IndexPattern;
- npStart.plugins.data.fieldFormats.getDefaultType = jest.fn(() => Format);
+ npStart.plugins.data.fieldFormats.getDefaultType = jest.fn(
+ () => (({} as unknown) as FieldFormatInstanceType)
+ );
npStart.plugins.data.fieldFormats.getByFieldType = jest.fn(fieldType => {
if (fieldType === 'number') {
- return [Format];
+ return [({} as unknown) as FieldFormatInstanceType];
+ } else {
+ return [];
}
});
});
it('should render create new scripted field correctly', async () => {
const component = shallowWithI18nProvider(
-
+
);
await new Promise(resolve => process.nextTick(resolve));
@@ -148,16 +149,20 @@ describe('FieldEditor', () => {
name: 'test',
script: 'doc.test.value',
};
- indexPattern.fields.push(testField);
+ indexPattern.fields.push(testField as Field);
indexPattern.fields.getByName = name => {
- const fields = {
+ const flds = {
[testField.name]: testField,
};
- return fields[name];
+ return flds[name] as Field;
};
const component = shallowWithI18nProvider(
-
+
);
await new Promise(resolve => process.nextTick(resolve));
@@ -172,16 +177,20 @@ describe('FieldEditor', () => {
script: 'doc.test.value',
lang: 'testlang',
};
- indexPattern.fields.push(testField);
+ indexPattern.fields.push((testField as unknown) as Field);
indexPattern.fields.getByName = name => {
- const fields = {
+ const flds = {
[testField.name]: testField,
};
- return fields[name];
+ return flds[name] as Field;
};
const component = shallowWithI18nProvider(
-
+
);
await new Promise(resolve => process.nextTick(resolve));
@@ -192,11 +201,15 @@ describe('FieldEditor', () => {
it('should show conflict field warning', async () => {
const testField = { ...field };
const component = shallowWithI18nProvider(
-
+
);
await new Promise(resolve => process.nextTick(resolve));
- component.instance().onFieldChange('name', 'foobar');
+ (component.instance() as FieldEditor).onFieldChange('name', 'foobar');
component.update();
expect(component).toMatchSnapshot();
});
@@ -211,11 +224,15 @@ describe('FieldEditor', () => {
},
};
const component = shallowWithI18nProvider(
-
+
);
await new Promise(resolve => process.nextTick(resolve));
- component.instance().onFieldChange('name', 'foobar');
+ (component.instance() as FieldEditor).onFieldChange('name', 'foobar');
component.update();
expect(component).toMatchSnapshot();
});
diff --git a/src/legacy/ui/public/field_editor/field_editor.js b/src/legacy/ui/public/field_editor/field_editor.tsx
similarity index 83%
rename from src/legacy/ui/public/field_editor/field_editor.js
rename to src/legacy/ui/public/field_editor/field_editor.tsx
index e90cb110ac304..aa62a53f2c32a 100644
--- a/src/legacy/ui/public/field_editor/field_editor.js
+++ b/src/legacy/ui/public/field_editor/field_editor.tsx
@@ -18,19 +18,15 @@
*/
import React, { PureComponent, Fragment } from 'react';
-import PropTypes from 'prop-types';
import { intersection, union, get } from 'lodash';
+import { HttpStart, DocLinksStart } from 'src/core/public';
import {
- GetEnabledScriptingLanguagesProvider,
+ getEnabledScriptingLanguages,
getDeprecatedScriptingLanguages,
getSupportedScriptingLanguages,
} from 'ui/scripting_languages';
-import { getDocLink } from 'ui/documentation_links';
-
-import { toastNotifications } from 'ui/notify';
-
import { npStart } from 'ui/new_platform';
import {
@@ -56,6 +52,16 @@ import {
EUI_MODAL_CONFIRM_BUTTON,
} from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+import {
+ IndexPattern,
+ IFieldType,
+ KBN_FIELD_TYPES,
+ ES_FIELD_TYPES,
+} from '../../../../plugins/data/public';
+import { FieldFormatInstanceType } from '../../../../plugins/data/common';
+import { Field } from '../../../../plugins/data/public';
import {
ScriptingDisabledCallOut,
ScriptingWarningCallOut,
@@ -65,23 +71,27 @@ import { ScriptingHelpFlyout } from './components/scripting_help';
import { FieldFormatEditor } from './components/field_format_editor';
+import { DefaultFormatEditor } from './components/field_format_editor/editors/default';
+
import { FIELD_TYPES_BY_LANG, DEFAULT_FIELD_TYPES } from './constants';
import { executeScript, isScriptValid } from './lib';
-import { i18n } from '@kbn/i18n';
-import { FormattedMessage } from '@kbn/i18n/react';
-
// This loads Ace editor's "groovy" mode, used below to highlight the script.
import 'brace/mode/groovy';
const getFieldFormats = () => npStart.plugins.data.fieldFormats;
-const getFieldTypeFormatsList = (field, defaultFieldFormat) => {
+const getFieldTypeFormatsList = (
+ field: IFieldType,
+ defaultFieldFormat: FieldFormatInstanceType
+) => {
const fieldFormats = getFieldFormats();
- const formatsByType = fieldFormats.getByFieldType(field.type).map(({ id, title }) => ({
- id,
- title,
- }));
+ const formatsByType = fieldFormats
+ .getByFieldType(field.type as KBN_FIELD_TYPES)
+ .map(({ id, title }) => ({
+ id,
+ title,
+ }));
return [
{
@@ -95,19 +105,54 @@ const getFieldTypeFormatsList = (field, defaultFieldFormat) => {
];
};
-export class FieldEditor extends PureComponent {
- static propTypes = {
- indexPattern: PropTypes.object.isRequired,
- field: PropTypes.object.isRequired,
- helpers: PropTypes.shape({
- getConfig: PropTypes.func.isRequired,
- $http: PropTypes.func.isRequired,
- fieldFormatEditors: PropTypes.object.isRequired,
- redirectAway: PropTypes.func.isRequired,
- }),
+interface FieldTypeFormat {
+ id: string;
+ title: string;
+}
+
+interface InitialFieldTypeFormat extends FieldTypeFormat {
+ defaultFieldFormat: FieldFormatInstanceType;
+}
+
+interface FieldClone extends Field {
+ format: any;
+}
+
+export interface FieldEditorState {
+ isReady: boolean;
+ isCreating: boolean;
+ isDeprecatedLang: boolean;
+ scriptingLangs: string[];
+ fieldTypes: string[];
+ fieldTypeFormats: FieldTypeFormat[];
+ existingFieldNames: string[];
+ field: FieldClone;
+ fieldFormatId?: string;
+ fieldFormatParams: { [key: string]: unknown };
+ showScriptingHelp: boolean;
+ showDeleteModal: boolean;
+ hasFormatError: boolean;
+ hasScriptError: boolean;
+ isSaving: boolean;
+ errors?: string[];
+}
+
+export interface FieldEdiorProps {
+ indexPattern: IndexPattern;
+ field: Field;
+ helpers: {
+ getConfig: (key: string) => any;
+ getHttpStart: () => HttpStart;
+ fieldFormatEditors: DefaultFormatEditor[];
+ redirectAway: () => void;
+ docLinksScriptedFields: DocLinksStart['links']['scriptedFields'];
};
+}
- constructor(props) {
+export class FieldEditor extends PureComponent
{
+ supportedLangs: string[] = [];
+ deprecatedLangs: string[] = [];
+ constructor(props: FieldEdiorProps) {
super(props);
const { field, indexPattern } = props;
@@ -119,7 +164,7 @@ export class FieldEditor extends PureComponent {
scriptingLangs: [],
fieldTypes: [],
fieldTypeFormats: [],
- existingFieldNames: indexPattern.fields.map(f => f.name),
+ existingFieldNames: indexPattern.fields.map((f: IFieldType) => f.name),
field: { ...field, format: field.format },
fieldFormatId: undefined,
fieldFormatParams: {},
@@ -135,48 +180,53 @@ export class FieldEditor extends PureComponent {
}
async init() {
- const { $http } = this.props.helpers;
+ const { getHttpStart } = this.props.helpers;
const { field } = this.state;
const { indexPattern } = this.props;
- const getEnabledScriptingLanguages = new GetEnabledScriptingLanguagesProvider($http);
- const enabledLangs = await getEnabledScriptingLanguages();
+ const enabledLangs = await getEnabledScriptingLanguages(await getHttpStart());
const scriptingLangs = intersection(
enabledLangs,
union(this.supportedLangs, this.deprecatedLangs)
);
- field.lang = scriptingLangs.includes(field.lang) ? field.lang : undefined;
+ field.lang = field.lang && scriptingLangs.includes(field.lang) ? field.lang : undefined;
- const fieldTypes = get(FIELD_TYPES_BY_LANG, field.lang, DEFAULT_FIELD_TYPES);
+ const fieldTypes = get(FIELD_TYPES_BY_LANG, field.lang || '', DEFAULT_FIELD_TYPES);
field.type = fieldTypes.includes(field.type) ? field.type : fieldTypes[0];
const fieldFormats = getFieldFormats();
- const DefaultFieldFormat = fieldFormats.getDefaultType(field.type, field.esTypes);
+ const DefaultFieldFormat = fieldFormats.getDefaultType(
+ field.type as KBN_FIELD_TYPES,
+ field.esTypes as ES_FIELD_TYPES[]
+ );
this.setState({
isReady: true,
- isCreating: !indexPattern.fields.getByName(field.name),
- isDeprecatedLang: this.deprecatedLangs.includes(field.lang),
+ isCreating: !indexPattern.fields.find(f => f.name === field.name),
+ isDeprecatedLang: this.deprecatedLangs.includes(field.lang || ''),
errors: [],
scriptingLangs,
fieldTypes,
- fieldTypeFormats: getFieldTypeFormatsList(field, DefaultFieldFormat),
+ fieldTypeFormats: getFieldTypeFormatsList(
+ field,
+ DefaultFieldFormat as FieldFormatInstanceType
+ ),
fieldFormatId: get(indexPattern, ['fieldFormatMap', field.name, 'type', 'id']),
fieldFormatParams: field.format.params(),
});
}
- onFieldChange = (fieldName, value) => {
+ onFieldChange = (fieldName: string, value: string | number) => {
const { field } = this.state;
- field[fieldName] = value;
+ (field as any)[fieldName] = value;
this.forceUpdate();
};
- onTypeChange = type => {
+ onTypeChange = (type: KBN_FIELD_TYPES) => {
const { getConfig } = this.props.helpers;
const { field } = this.state;
const fieldFormats = getFieldFormats();
- const DefaultFieldFormat = fieldFormats.getDefaultType(type);
+ const DefaultFieldFormat = fieldFormats.getDefaultType(type) as FieldFormatInstanceType;
field.type = type;
field.format = new DefaultFieldFormat(null, getConfig);
@@ -188,7 +238,7 @@ export class FieldEditor extends PureComponent {
});
};
- onLangChange = lang => {
+ onLangChange = (lang: string) => {
const { field } = this.state;
const fieldTypes = get(FIELD_TYPES_BY_LANG, lang, DEFAULT_FIELD_TYPES);
field.lang = lang;
@@ -199,12 +249,12 @@ export class FieldEditor extends PureComponent {
});
};
- onFormatChange = (formatId, params) => {
+ onFormatChange = (formatId: string, params?: any) => {
const fieldFormats = getFieldFormats();
const { field, fieldTypeFormats } = this.state;
const FieldFormat = fieldFormats.getType(
- formatId || fieldTypeFormats[0]?.defaultFieldFormat.id
- );
+ formatId || (fieldTypeFormats[0] as InitialFieldTypeFormat).defaultFieldFormat.id
+ ) as FieldFormatInstanceType;
field.format = new FieldFormat(params, this.props.helpers.getConfig);
@@ -214,12 +264,12 @@ export class FieldEditor extends PureComponent {
});
};
- onFormatParamsChange = newParams => {
+ onFormatParamsChange = (newParams: { fieldType: string; [key: string]: any }) => {
const { fieldFormatId } = this.state;
- this.onFormatChange(fieldFormatId, newParams);
+ this.onFormatChange(fieldFormatId as string, newParams);
};
- onFormatParamsError = error => {
+ onFormatParamsError = (error?: string) => {
this.setState({
hasFormatError: !!error,
});
@@ -312,7 +362,10 @@ export class FieldEditor extends PureComponent {
values={{
language: {field.lang},
painlessLink: (
-
+
{
- this.onTypeChange(e.target.value);
+ this.onTypeChange(e.target.value as KBN_FIELD_TYPES);
}}
/>
@@ -366,7 +419,7 @@ export class FieldEditor extends PureComponent {
* in case there are indices with different types
*/
renderTypeConflict() {
- const { field = {} } = this.state;
+ const { field } = this.state;
if (!field.conflictDescriptions || typeof field.conflictDescriptions !== 'object') {
return null;
}
@@ -420,7 +473,7 @@ export class FieldEditor extends PureComponent {
renderFormat() {
const { field, fieldTypeFormats, fieldFormatId, fieldFormatParams } = this.state;
const { fieldFormatEditors } = this.props.helpers;
- const defaultFormat = fieldTypeFormats[0]?.defaultFieldFormat.title;
+ const defaultFormat = (fieldTypeFormats[0] as InitialFieldTypeFormat).defaultFieldFormat.title;
const label = defaultFormat ? (
{
+ onScriptChange = (value: string) => {
this.setState({
hasScriptError: false,
});
@@ -690,15 +743,20 @@ export class FieldEditor extends PureComponent {
return (
-
+
);
@@ -716,7 +774,7 @@ export class FieldEditor extends PureComponent {
defaultMessage: "Deleted '{fieldName}'",
values: { fieldName: field.name },
});
- toastNotifications.addSuccess(message);
+ npStart.core.notifications.toasts.addSuccess(message);
redirectAway();
});
} else {
@@ -736,9 +794,10 @@ export class FieldEditor extends PureComponent {
const isValid = await isScriptValid({
name: field.name,
- lang: field.lang,
- script: field.script,
+ lang: field.lang as string,
+ script: field.script as string,
indexPatternTitle: indexPattern.title,
+ getHttpStart: this.props.helpers.getHttpStart,
});
if (!isValid) {
@@ -751,7 +810,7 @@ export class FieldEditor extends PureComponent {
}
const { redirectAway } = this.props.helpers;
- const index = indexPattern.fields.findIndex(f => f.name === field.name);
+ const index = indexPattern.fields.findIndex((f: IFieldType) => f.name === field.name);
if (index > -1) {
indexPattern.fields.update(field);
@@ -770,7 +829,7 @@ export class FieldEditor extends PureComponent {
defaultMessage: "Saved '{fieldName}'",
values: { fieldName: field.name },
});
- toastNotifications.addSuccess(message);
+ npStart.core.notifications.toasts.addSuccess(message);
redirectAway();
});
};
diff --git a/src/legacy/ui/public/field_editor/index.js b/src/legacy/ui/public/field_editor/index.ts
similarity index 100%
rename from src/legacy/ui/public/field_editor/index.js
rename to src/legacy/ui/public/field_editor/index.ts
diff --git a/src/legacy/ui/public/field_editor/lib/index.js b/src/legacy/ui/public/field_editor/lib/index.ts
similarity index 100%
rename from src/legacy/ui/public/field_editor/lib/index.js
rename to src/legacy/ui/public/field_editor/lib/index.ts
diff --git a/src/legacy/ui/public/field_editor/lib/validate_script.js b/src/legacy/ui/public/field_editor/lib/validate_script.ts
similarity index 67%
rename from src/legacy/ui/public/field_editor/lib/validate_script.js
rename to src/legacy/ui/public/field_editor/lib/validate_script.ts
index 47e2091565c30..4db827a4229fd 100644
--- a/src/legacy/ui/public/field_editor/lib/validate_script.js
+++ b/src/legacy/ui/public/field_editor/lib/validate_script.ts
@@ -17,7 +17,9 @@
* under the License.
*/
-import { kfetch } from 'ui/kfetch';
+import { Query } from 'src/plugins/data/public';
+import { HttpStart } from 'src/core/public';
+import { ExecuteScriptParams, ExecuteScriptResult } from '../types';
export const executeScript = async ({
name,
@@ -26,7 +28,8 @@ export const executeScript = async ({
indexPatternTitle,
query,
additionalFields = [],
-}) => {
+ getHttpStart,
+}: ExecuteScriptParams): Promise => {
// Using _msearch because _search with index name in path dorks everything up
const header = {
index: indexPatternTitle,
@@ -36,7 +39,7 @@ export const executeScript = async ({
const search = {
query: {
match_all: {},
- },
+ } as Query['query'],
script_fields: {
[name]: {
script: {
@@ -45,6 +48,7 @@ export const executeScript = async ({
},
},
},
+ _source: undefined as string[] | undefined,
size: 10,
timeout: '30s',
};
@@ -58,13 +62,32 @@ export const executeScript = async ({
}
const body = `${JSON.stringify(header)}\n${JSON.stringify(search)}\n`;
- const esResp = await kfetch({ method: 'POST', pathname: '/elasticsearch/_msearch', body });
+ const http = await getHttpStart();
+ const esResp = await http.fetch('/elasticsearch/_msearch', { method: 'POST', body });
// unwrap _msearch response
return esResp.responses[0];
};
-export const isScriptValid = async ({ name, lang, script, indexPatternTitle }) => {
- const scriptResponse = await executeScript({ name, lang, script, indexPatternTitle });
+export const isScriptValid = async ({
+ name,
+ lang,
+ script,
+ indexPatternTitle,
+ getHttpStart,
+}: {
+ name: string;
+ lang: string;
+ script: string;
+ indexPatternTitle: string;
+ getHttpStart: () => HttpStart;
+}) => {
+ const scriptResponse = await executeScript({
+ name,
+ lang,
+ script,
+ indexPatternTitle,
+ getHttpStart,
+ });
if (scriptResponse.status !== 200) {
return false;
diff --git a/src/legacy/ui/public/field_editor/components/scripting_call_outs/warning_call_out.test.js b/src/legacy/ui/public/field_editor/types.ts
similarity index 56%
rename from src/legacy/ui/public/field_editor/components/scripting_call_outs/warning_call_out.test.js
rename to src/legacy/ui/public/field_editor/types.ts
index 48094f63f8fe8..174cb7da73ceb 100644
--- a/src/legacy/ui/public/field_editor/components/scripting_call_outs/warning_call_out.test.js
+++ b/src/legacy/ui/public/field_editor/types.ts
@@ -17,25 +17,29 @@
* under the License.
*/
-import React from 'react';
-import { shallow } from 'enzyme';
+import { ReactText } from 'react';
+import { Query } from 'src/plugins/data/public';
+import { HttpStart } from 'src/core/public';
-import { ScriptingWarningCallOut } from './warning_call_out';
+export interface Sample {
+ input: ReactText | ReactText[];
+ output: string;
+}
-jest.mock('ui/documentation_links', () => ({
- getDocLink: doc => `(docLink for ${doc})`,
-}));
+export interface ExecuteScriptParams {
+ name: string;
+ lang: string;
+ script: string;
+ indexPatternTitle: string;
+ query?: Query['query'];
+ additionalFields?: string[];
+ getHttpStart: () => HttpStart;
+}
-describe('ScriptingWarningCallOut', () => {
- it('should render normally', async () => {
- const component = shallow();
+export interface ExecuteScriptResult {
+ status: number;
+ hits: { hits: any[] };
+ error?: any;
+}
- expect(component).toMatchSnapshot();
- });
-
- it('should render nothing if not visible', async () => {
- const component = shallow();
-
- expect(component).toMatchSnapshot();
- });
-});
+export type ExecuteScript = (params: ExecuteScriptParams) => Promise;
diff --git a/src/legacy/ui/public/registry/field_format_editors.js b/src/legacy/ui/public/registry/field_format_editors.ts
similarity index 88%
rename from src/legacy/ui/public/registry/field_format_editors.js
rename to src/legacy/ui/public/registry/field_format_editors.ts
index 85850e56fdb86..5489ce9250e04 100644
--- a/src/legacy/ui/public/registry/field_format_editors.js
+++ b/src/legacy/ui/public/registry/field_format_editors.ts
@@ -22,9 +22,4 @@ import { uiRegistry } from './_registry';
export const RegistryFieldFormatEditorsProvider = uiRegistry({
name: 'fieldFormatEditors',
index: ['formatId'],
- constructor: function() {
- this.getEditor = function(formatId) {
- return this.byFormatId[formatId];
- };
- },
});
diff --git a/src/legacy/ui/public/scripting_languages/index.ts b/src/legacy/ui/public/scripting_languages/index.ts
index 283a3273a2a5d..459e72c0c67c1 100644
--- a/src/legacy/ui/public/scripting_languages/index.ts
+++ b/src/legacy/ui/public/scripting_languages/index.ts
@@ -17,10 +17,8 @@
* under the License.
*/
-import { IHttpService } from 'angular';
import { i18n } from '@kbn/i18n';
-
-import chrome from '../chrome';
+import { HttpStart } from 'src/core/public';
import { toastNotifications } from '../notify';
export function getSupportedScriptingLanguages(): string[] {
@@ -31,18 +29,12 @@ export function getDeprecatedScriptingLanguages(): string[] {
return [];
}
-export function GetEnabledScriptingLanguagesProvider($http: IHttpService) {
- return () => {
- return $http
- .get(chrome.addBasePath('/api/kibana/scripts/languages'))
- .then((res: any) => res.data)
- .catch(() => {
- toastNotifications.addDanger(
- i18n.translate('common.ui.scriptingLanguages.errorFetchingToastDescription', {
- defaultMessage: 'Error getting available scripting languages from Elasticsearch',
- })
- );
- return [];
- });
- };
-}
+export const getEnabledScriptingLanguages = (http: HttpStart) =>
+ http.get('/api/kibana/scripts/languages').catch(() => {
+ toastNotifications.addDanger(
+ i18n.translate('common.ui.scriptingLanguages.errorFetchingToastDescription', {
+ defaultMessage: 'Error getting available scripting languages from Elasticsearch',
+ })
+ );
+ return [];
+ });
diff --git a/src/plugins/data/common/field_formats/field_format.ts b/src/plugins/data/common/field_formats/field_format.ts
index 96d0024dff2a2..26f07a12067ce 100644
--- a/src/plugins/data/common/field_formats/field_format.ts
+++ b/src/plugins/data/common/field_formats/field_format.ts
@@ -127,12 +127,12 @@ export abstract class FieldFormat {
*/
getConverterFor(
contentType: FieldFormatsContentType = DEFAULT_CONTEXT_TYPE
- ): FieldFormatConvertFunction | null {
+ ): FieldFormatConvertFunction {
if (!this.convertObject) {
this.convertObject = this.setupContentType();
}
- return this.convertObject[contentType] || null;
+ return this.convertObject[contentType];
}
/**
diff --git a/src/plugins/data/common/field_formats/field_formats_registry.ts b/src/plugins/data/common/field_formats/field_formats_registry.ts
index b0a57ad6912a7..2eb9a3e593d1a 100644
--- a/src/plugins/data/common/field_formats/field_formats_registry.ts
+++ b/src/plugins/data/common/field_formats/field_formats_registry.ts
@@ -110,7 +110,7 @@ export class FieldFormatsRegistry {
*/
getDefaultType = (
fieldType: KBN_FIELD_TYPES,
- esTypes: ES_FIELD_TYPES[]
+ esTypes?: ES_FIELD_TYPES[]
): FieldFormatInstanceType | undefined => {
const config = this.getDefaultConfig(fieldType, esTypes);
diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts
index 24815e84f9330..60d8079b22347 100644
--- a/src/plugins/data/public/index.ts
+++ b/src/plugins/data/public/index.ts
@@ -204,11 +204,13 @@ export const fieldFormats = {
export {
IFieldFormat,
+ FieldFormatInstanceType,
IFieldFormatsRegistry,
FieldFormatsContentType,
FieldFormatsGetConfigFn,
FieldFormatConfig,
FieldFormatId,
+ FieldFormat,
} from '../common';
/*
diff --git a/src/plugins/data/public/index_patterns/fields/field.ts b/src/plugins/data/public/index_patterns/fields/field.ts
index 0fb92393d56f7..d83c0a7d3445e 100644
--- a/src/plugins/data/public/index_patterns/fields/field.ts
+++ b/src/plugins/data/public/index_patterns/fields/field.ts
@@ -47,6 +47,7 @@ export class Field implements IFieldType {
indexPattern?: IndexPattern;
format: any;
$$spec: FieldSpec;
+ conflictDescriptions?: Record;
constructor(
indexPattern: IndexPattern,
diff --git a/src/plugins/data/public/index_patterns/fields/field_list.ts b/src/plugins/data/public/index_patterns/fields/field_list.ts
index d6067280fd7b6..9772370199b24 100644
--- a/src/plugins/data/public/index_patterns/fields/field_list.ts
+++ b/src/plugins/data/public/index_patterns/fields/field_list.ts
@@ -29,6 +29,7 @@ export interface IFieldList extends Array {
getByType(type: Field['type']): Field[];
add(field: FieldSpec): void;
remove(field: IFieldType): void;
+ update(field: FieldSpec): void;
}
export class FieldList extends Array implements IFieldList {
diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md
index cd7d70bc9a80d..77e2a06a684e9 100644
--- a/src/plugins/data/public/public.api.md
+++ b/src/plugins/data/public/public.api.md
@@ -463,6 +463,8 @@ class Field implements IFieldType {
// (undocumented)
aggregatable?: boolean;
// (undocumented)
+ conflictDescriptions?: Record;
+ // (undocumented)
count?: number;
// (undocumented)
displayName?: string;
@@ -498,6 +500,48 @@ export { Field }
export { Field as IndexPatternField }
+// Warning: (ae-missing-release-tag) "FieldFormat" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export abstract class FieldFormat {
+ // Warning: (ae-forgotten-export) The symbol "IFieldFormatMetaParams" needs to be exported by the entry point index.d.ts
+ constructor(_params?: IFieldFormatMetaParams, getConfig?: FieldFormatsGetConfigFn);
+ // Warning: (ae-forgotten-export) The symbol "HtmlContextTypeOptions" needs to be exported by the entry point index.d.ts
+ // Warning: (ae-forgotten-export) The symbol "TextContextTypeOptions" needs to be exported by the entry point index.d.ts
+ convert(value: any, contentType?: FieldFormatsContentType, options?: HtmlContextTypeOptions | TextContextTypeOptions): string;
+ // Warning: (ae-forgotten-export) The symbol "FieldFormatConvert" needs to be exported by the entry point index.d.ts
+ convertObject: FieldFormatConvert | undefined;
+ static fieldType: string | string[];
+ // Warning: (ae-incompatible-release-tags) The symbol "from" is marked as @public, but its signature references "FieldFormatInstanceType" which is marked as @internal
+ //
+ // (undocumented)
+ static from(convertFn: FieldFormatConvertFunction): FieldFormatInstanceType;
+ // (undocumented)
+ protected getConfig: FieldFormatsGetConfigFn | undefined;
+ // Warning: (ae-forgotten-export) The symbol "FieldFormatConvertFunction" needs to be exported by the entry point index.d.ts
+ getConverterFor(contentType?: FieldFormatsContentType): FieldFormatConvertFunction;
+ getParamDefaults(): Record;
+ // Warning: (ae-forgotten-export) The symbol "HtmlContextTypeConvert" needs to be exported by the entry point index.d.ts
+ htmlConvert: HtmlContextTypeConvert | undefined;
+ static id: string;
+ // (undocumented)
+ static isInstanceOfFieldFormat(fieldFormat: any): fieldFormat is FieldFormat;
+ param(name: string): any;
+ params(): Record;
+ // (undocumented)
+ protected readonly _params: any;
+ // (undocumented)
+ setupContentType(): FieldFormatConvert;
+ // Warning: (ae-forgotten-export) The symbol "TextContextTypeConvert" needs to be exported by the entry point index.d.ts
+ textConvert: TextContextTypeConvert | undefined;
+ static title: string;
+ toJSON(): {
+ id: unknown;
+ params: _.Dictionary | undefined;
+ };
+ type: any;
+}
+
// Warning: (ae-missing-release-tag) "FieldFormatConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
@@ -516,6 +560,13 @@ export interface FieldFormatConfig {
// @public
export type FieldFormatId = FIELD_FORMAT_IDS | string;
+// @internal (undocumented)
+export type FieldFormatInstanceType = (new (params?: any, getConfig?: FieldFormatsGetConfigFn) => FieldFormat) & {
+ id: FieldFormatId;
+ title: string;
+ fieldType: string | string[];
+};
+
// Warning: (ae-missing-release-tag) "fieldFormats" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
@@ -1802,7 +1853,6 @@ export type TSearchStrategyProvider = (context: ISearc
// src/plugins/data/public/index.ts:135:21 - (ae-forgotten-export) The symbol "getEsQueryConfig" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:135:21 - (ae-forgotten-export) The symbol "luceneStringToDsl" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:135:21 - (ae-forgotten-export) The symbol "decorateQuery" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:177:26 - (ae-forgotten-export) The symbol "FieldFormat" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:177:26 - (ae-forgotten-export) The symbol "FieldFormatsRegistry" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:177:26 - (ae-forgotten-export) The symbol "BoolFormat" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:177:26 - (ae-forgotten-export) The symbol "BytesFormat" needs to be exported by the entry point index.d.ts
@@ -1818,28 +1868,28 @@ export type TSearchStrategyProvider = (context: ISearc
// src/plugins/data/public/index.ts:177:26 - (ae-forgotten-export) The symbol "UrlFormat" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:177:26 - (ae-forgotten-export) The symbol "StringFormat" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:177:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "validateIndexPattern" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "getFromSavedObject" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "getRoutes" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:382:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:382:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:382:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:382:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:387:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:388:1 - (ae-forgotten-export) The symbol "convertDateRangeToString" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:390:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:399:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:400:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:401:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:405:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:406:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:409:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:410:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:413:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "validateIndexPattern" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "getFromSavedObject" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "getRoutes" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:236:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:384:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:384:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:384:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:384:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:389:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:390:1 - (ae-forgotten-export) The symbol "convertDateRangeToString" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:392:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:401:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:402:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:403:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:407:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:408:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:411:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:412:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:415:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:33:33 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:37:1 - (ae-forgotten-export) The symbol "QueryStateChange" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/types.ts:52:5 - (ae-forgotten-export) The symbol "createFiltersFromValueClickAction" needs to be exported by the entry point index.d.ts
diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md
index a16e08f474535..7bda2f3a5765b 100644
--- a/src/plugins/data/server/server.api.md
+++ b/src/plugins/data/server/server.api.md
@@ -611,7 +611,7 @@ export class Plugin implements Plugin_2 {
// (undocumented)
setup(core: CoreSetup, { usageCollection }: DataPluginSetupDependencies): {
fieldFormats: {
- register: (customFieldFormat: import("../common").FieldFormatInstanceType) => number;
+ register: (customFieldFormat: import("../public").FieldFormatInstanceType) => number;
};
search: ISearchSetup;
};
diff --git a/test/functional/page_objects/settings_page.ts b/test/functional/page_objects/settings_page.ts
index 6dcd017335c85..8864eda3823ef 100644
--- a/test/functional/page_objects/settings_page.ts
+++ b/test/functional/page_objects/settings_page.ts
@@ -206,15 +206,17 @@ export function SettingsPageProvider({ getService, getPageObjects }: FtrProvider
async getFieldsTabCount() {
return retry.try(async () => {
- const text = await testSubjects.getVisibleText('tab-count-indexedFields');
- return text.replace(/\((.*)\)/, '$1');
+ const indexedFieldsTab = await find.byCssSelector('#indexedFields .euiTab__content');
+ const text = await indexedFieldsTab.getVisibleText();
+ return text.split(/[()]/)[1];
});
}
async getScriptedFieldsTabCount() {
return await retry.try(async () => {
- const theText = await testSubjects.getVisibleText('tab-count-scriptedFields');
- return theText.replace(/\((.*)\)/, '$1');
+ const scriptedFieldsTab = await find.byCssSelector('#scriptedFields .euiTab__content');
+ const text = await scriptedFieldsTab.getVisibleText();
+ return text.split(/[()]/)[1];
});
}
@@ -241,13 +243,13 @@ export function SettingsPageProvider({ getService, getPageObjects }: FtrProvider
async setFieldTypeFilter(type: string) {
await find.clickByCssSelector(
- 'select[data-test-subj="indexedFieldTypeFilterDropdown"] > option[label="' + type + '"]'
+ 'select[data-test-subj="indexedFieldTypeFilterDropdown"] > option[value="' + type + '"]'
);
}
async setScriptedFieldLanguageFilter(language: string) {
await find.clickByCssSelector(
- 'select[data-test-subj="scriptedFieldLanguageFilterDropdown"] > option[label="' +
+ 'select[data-test-subj="scriptedFieldLanguageFilterDropdown"] > option[value="' +
language +
'"]'
);
@@ -412,17 +414,17 @@ export function SettingsPageProvider({ getService, getPageObjects }: FtrProvider
async clickFieldsTab() {
log.debug('click Fields tab');
- await testSubjects.click('tab-indexFields');
+ await find.clickByCssSelector('#indexedFields');
}
async clickScriptedFieldsTab() {
log.debug('click Scripted Fields tab');
- await testSubjects.click('tab-scriptedFields');
+ await find.clickByCssSelector('#scriptedFields');
}
async clickSourceFiltersTab() {
log.debug('click Source Filters tab');
- await testSubjects.click('tab-sourceFilters');
+ await find.clickByCssSelector('#sourceFilters');
}
async editScriptedField(name: string) {
diff --git a/x-pack/index.js b/x-pack/index.js
index 39b68793866cb..3761af5c1ca7a 100644
--- a/x-pack/index.js
+++ b/x-pack/index.js
@@ -17,7 +17,6 @@ import { spaces } from './legacy/plugins/spaces';
import { canvas } from './legacy/plugins/canvas';
import { infra } from './legacy/plugins/infra';
import { taskManager } from './legacy/plugins/task_manager';
-import { rollup } from './legacy/plugins/rollup';
import { remoteClusters } from './legacy/plugins/remote_clusters';
import { upgradeAssistant } from './legacy/plugins/upgrade_assistant';
import { uptime } from './legacy/plugins/uptime';
@@ -42,7 +41,6 @@ module.exports = function(kibana) {
indexManagement(kibana),
infra(kibana),
taskManager(kibana),
- rollup(kibana),
remoteClusters(kibana),
upgradeAssistant(kibana),
uptime(kibana),
diff --git a/x-pack/legacy/plugins/canvas/.storybook/storyshots.test.js b/x-pack/legacy/plugins/canvas/.storybook/storyshots.test.js
index 72b0b8f0e533f..a81483d1e7a17 100644
--- a/x-pack/legacy/plugins/canvas/.storybook/storyshots.test.js
+++ b/x-pack/legacy/plugins/canvas/.storybook/storyshots.test.js
@@ -7,6 +7,7 @@
import path from 'path';
import moment from 'moment';
import 'moment-timezone';
+import ReactDOM from "react-dom";
import initStoryshots, { multiSnapshotWithOptions } from '@storybook/addon-storyshots';
import styleSheetSerializer from 'jest-styled-components/src/styleSheetSerializer';
@@ -24,6 +25,9 @@ moment.tz.setDefault('UTC');
const testTime = new Date(Date.UTC(2019, 5, 1)); // June 1 2019
Date.now = jest.fn(() => testTime);
+// Mock telemetry service
+jest.mock('../public/lib/ui_metric', () => ({ trackCanvasUiMetric: () => { } }));
+
// Mock EUI generated ids to be consistently predictable for snapshots.
jest.mock(`@elastic/eui/lib/components/form/form_row/make_id`, () => () => `generated-id`);
@@ -32,7 +36,7 @@ jest.mock(`@elastic/eui/lib/components/form/form_row/make_id`, () => () => `gene
jest.mock('@elastic/eui/lib/components/code/code', () => {
const React = require.requireActual('react');
return {
- EuiCode: ({children, className}) => (
+ EuiCode: ({ children, className }) => (
{children}
@@ -61,6 +65,12 @@ jest.mock('@elastic/eui/packages/react-datepicker', () => {
};
});
+
+// Mock React Portal for components that use modals, tooltips, etc
+ReactDOM.createPortal = jest.fn((element) => {
+ return element;
+});
+
jest.mock('@elastic/eui/lib/services/accessibility/html_id_generator', () => {
return {
htmlIdGenerator: () => () => `generated-id`,
@@ -71,7 +81,7 @@ jest.mock('plugins/interpreter/registries', () => ({}));
// Disabling this test due to https://github.com/elastic/eui/issues/2242
jest.mock(
- '../public/components/workpad_header/workpad_export/flyout/__examples__/share_website_flyout.stories',
+ '../public/components/workpad_header/share_menu/flyout/__examples__/share_website_flyout.stories',
() => {
return 'Disabled Panel';
}
diff --git a/x-pack/legacy/plugins/canvas/.storybook/webpack.config.js b/x-pack/legacy/plugins/canvas/.storybook/webpack.config.js
index cc74faeac6a96..963cf831ef698 100644
--- a/x-pack/legacy/plugins/canvas/.storybook/webpack.config.js
+++ b/x-pack/legacy/plugins/canvas/.storybook/webpack.config.js
@@ -177,8 +177,10 @@ module.exports = async ({ config }) => {
}),
// Mock out libs used by a few componets to avoid loading in kibana_legacy and platform
- new webpack.NormalModuleReplacementPlugin(/lib\/notify/, path.resolve(__dirname, '../tasks/mocks/uiNotify')),
+ new webpack.NormalModuleReplacementPlugin(/(lib)?\/notify/, path.resolve(__dirname, '../tasks/mocks/uiNotify')),
new webpack.NormalModuleReplacementPlugin(/lib\/download_workpad/, path.resolve(__dirname, '../tasks/mocks/downloadWorkpad')),
+ new webpack.NormalModuleReplacementPlugin(/(lib)?\/custom_element_service/, path.resolve(__dirname, '../tasks/mocks/customElementService')),
+ new webpack.NormalModuleReplacementPlugin(/(lib)?\/ui_metric/, path.resolve(__dirname, '../tasks/mocks/uiMetric')),
);
// Tell Webpack about relevant extensions
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/area_chart/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/area_chart/header.png
deleted file mode 100644
index 93456066429d9..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/area_chart/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/area_chart/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/area_chart/index.ts
index 0650ac15c656e..df829e8b97676 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/area_chart/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/area_chart/index.ts
@@ -5,14 +5,13 @@
*/
import { ElementFactory } from '../../../types';
-import header from './header.png';
export const areaChart: ElementFactory = () => ({
name: 'areaChart',
- displayName: 'Area chart',
+ displayName: 'Area',
help: 'A line chart with a filled body',
- tags: ['chart'],
- image: header,
+ type: 'chart',
+ icon: 'visArea',
expression: `filters
| demodata
| pointseries x="time" y="mean(price)"
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/bubble_chart/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/bubble_chart/header.png
deleted file mode 100644
index db541fe7c53b8..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/bubble_chart/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/bubble_chart/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/bubble_chart/index.ts
index 7ab510e419769..7ac1d0ac83b0b 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/bubble_chart/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/bubble_chart/index.ts
@@ -5,16 +5,15 @@
*/
import { ElementFactory } from '../../../types';
-import header from './header.png';
export const bubbleChart: ElementFactory = () => ({
name: 'bubbleChart',
- displayName: 'Bubble chart',
- tags: ['chart'],
+ displayName: 'Bubble',
+ type: 'chart',
help: 'A customizable bubble chart',
width: 700,
height: 300,
- image: header,
+ icon: 'heatmap',
expression: `filters
| demodata
| pointseries x="project" y="sum(price)" color="state" size="size(username)"
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/debug/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/debug/header.png
deleted file mode 100644
index 37ab329a49bb8..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/debug/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/debug/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/debug/index.ts
index 914982951d664..ec8477f8f1017 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/debug/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/debug/index.ts
@@ -5,14 +5,12 @@
*/
import { ElementFactory } from '../../../types';
-import header from './header.png';
export const debug: ElementFactory = () => ({
name: 'debug',
- displayName: 'Debug',
- tags: ['text'],
+ displayName: 'Debug data',
help: 'Just dumps the configuration of the element',
- image: header,
+ icon: 'bug',
expression: `demodata
| render as=debug`,
});
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/donut/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/donut/header.png
deleted file mode 100644
index 4bbfb6f8f68fc..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/donut/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/donut/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/donut/index.ts
deleted file mode 100644
index 4ea8037d2073e..0000000000000
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/donut/index.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import { ElementFactory } from '../../../types';
-import header from './header.png';
-
-export const donut: ElementFactory = () => ({
- name: 'donut',
- displayName: 'Donut chart',
- tags: ['chart', 'proportion'],
- help: 'A customizable donut chart',
- image: header,
- expression: `filters
-| demodata
-| pointseries color="project" size="max(price)"
-| pie hole=50 labels=false legend="ne"
-| render`,
-});
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/dropdown_filter/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/dropdown_filter/header.png
deleted file mode 100644
index 727b4d23941fd..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/dropdown_filter/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/dropdown_filter/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/dropdown_filter/index.ts
index bde223d2a606e..bb1c13ca618be 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/dropdown_filter/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/dropdown_filter/index.ts
@@ -5,14 +5,13 @@
*/
import { ElementFactory } from '../../../types';
-import header from './header.png';
export const dropdownFilter: ElementFactory = () => ({
- name: 'dropdown_filter',
- displayName: 'Dropdown filter',
- tags: ['filter'],
+ name: 'dropdownFilter',
+ displayName: 'Dropdown select',
+ type: 'filter',
help: 'A dropdown from which you can select values for an "exactly" filter',
- image: header,
+ icon: 'filter',
height: 50,
expression: `demodata
| dropdownControl valueColumn=project filterColumn=project | render`,
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/filter_debug/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/filter_debug/index.ts
new file mode 100644
index 0000000000000..35a4a75f49c4e
--- /dev/null
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/filter_debug/index.ts
@@ -0,0 +1,16 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { ElementFactory } from '../../../types';
+
+export const filterDebug: ElementFactory = () => ({
+ name: 'filterDebug',
+ displayName: 'Debug filter',
+ help: 'Shows the underlying global filters in a workpad',
+ icon: 'bug',
+ expression: `filters
+| render as=debug`,
+});
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_bar_chart/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_bar_chart/header.png
deleted file mode 100644
index 9b6ee47d88698..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_bar_chart/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_bar_chart/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_bar_chart/index.ts
index 7fddf48c70385..9567336decd5d 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_bar_chart/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_bar_chart/index.ts
@@ -5,14 +5,13 @@
*/
import { ElementFactory } from '../../../types';
-import header from './header.png';
export const horizontalBarChart: ElementFactory = () => ({
name: 'horizontalBarChart',
- displayName: 'Horizontal bar chart',
- tags: ['chart'],
+ displayName: 'Bar horizontal',
+ type: 'chart',
help: 'A customizable horizontal bar chart',
- image: header,
+ icon: 'visBarHorizontal',
expression: `filters
| demodata
| pointseries x="size(cost)" y="project" color="project"
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_progress_bar/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_progress_bar/header.png
deleted file mode 100644
index f28ad4a3ce4be..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_progress_bar/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_progress_bar/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_progress_bar/index.ts
index f4a50a007c5de..529a74893a5de 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_progress_bar/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_progress_bar/index.ts
@@ -6,16 +6,14 @@
import { openSans } from '../../../common/lib/fonts';
import { ElementFactory } from '../../../types';
-import header from './header.png';
export const horizontalProgressBar: ElementFactory = () => ({
name: 'horizontalProgressBar',
- displayName: 'Horizontal progress bar',
- tags: ['chart', 'proportion'],
+ displayName: 'Horizontal bar',
+ type: 'progress',
help: 'Displays progress as a portion of a horizontal bar',
width: 400,
height: 30,
- image: header,
expression: `filters
| demodata
| math "mean(percent_uptime)"
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_progress_pill/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_progress_pill/header.png
deleted file mode 100644
index 2eaeb2e976a78..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_progress_pill/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_progress_pill/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_progress_pill/index.ts
index 9b3aea2e55324..d5eba32325d1a 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_progress_pill/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/horizontal_progress_pill/index.ts
@@ -6,16 +6,14 @@
import { openSans } from '../../../common/lib/fonts';
import { ElementFactory } from '../../../types';
-import header from './header.png';
export const horizontalProgressPill: ElementFactory = () => ({
name: 'horizontalProgressPill',
- displayName: 'Horizontal progress pill',
- tags: ['chart', 'proportion'],
+ displayName: 'Horizontal pill',
+ type: 'progress',
help: 'Displays progress as a portion of a horizontal pill',
width: 400,
height: 30,
- image: header,
expression: `filters
| demodata
| math "mean(percent_uptime)"
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/image/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/image/header.png
deleted file mode 100644
index 7f29fc64c36b9..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/image/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/image/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/image/index.ts
index eec1e2af61aad..ed7f6a99ddc32 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/image/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/image/index.ts
@@ -5,14 +5,13 @@
*/
import { ElementFactory } from '../../../types';
-import header from './header.png';
export const image: ElementFactory = () => ({
name: 'image',
displayName: 'Image',
- tags: ['graphic'],
+ type: 'image',
help: 'A static image',
- image: header,
+ icon: 'image',
expression: `image dataurl=null mode="contain"
| render`,
});
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/index.ts
index 6c0cd7eb33dc0..ec3b8a7798be1 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/index.ts
@@ -8,8 +8,8 @@ import { applyElementStrings } from '../../i18n/elements';
import { areaChart } from './area_chart';
import { bubbleChart } from './bubble_chart';
import { debug } from './debug';
-import { donut } from './donut';
import { dropdownFilter } from './dropdown_filter';
+import { filterDebug } from './filter_debug';
import { horizontalBarChart } from './horizontal_bar_chart';
import { horizontalProgressBar } from './horizontal_progress_bar';
import { horizontalProgressPill } from './horizontal_progress_pill';
@@ -26,7 +26,6 @@ import { repeatImage } from './repeat_image';
import { revealImage } from './reveal_image';
import { shape } from './shape';
import { table } from './table';
-import { tiltedPie } from './tilted_pie';
import { timeFilter } from './time_filter';
import { verticalBarChart } from './vert_bar_chart';
import { verticalProgressBar } from './vertical_progress_bar';
@@ -39,8 +38,8 @@ const elementSpecs = [
areaChart,
bubbleChart,
debug,
- donut,
dropdownFilter,
+ filterDebug,
image,
horizontalBarChart,
horizontalProgressBar,
@@ -56,7 +55,6 @@ const elementSpecs = [
revealImage,
shape,
table,
- tiltedPie,
timeFilter,
verticalBarChart,
verticalProgressBar,
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/line_chart/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/line_chart/header.png
deleted file mode 100644
index eea133ee3680b..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/line_chart/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/line_chart/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/line_chart/index.ts
index 5b8533eea65bc..d19ddeb00dd67 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/line_chart/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/line_chart/index.ts
@@ -5,14 +5,13 @@
*/
import { ElementFactory } from '../../../types';
-import header from './header.png';
export const lineChart: ElementFactory = () => ({
name: 'lineChart',
- displayName: 'Line chart',
- tags: ['chart'],
+ displayName: 'Line',
+ type: 'chart',
help: 'A customizable line chart',
- image: header,
+ icon: 'visLine',
expression: `filters
| demodata
| pointseries x="time" y="mean(price)"
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/markdown/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/markdown/header.png
deleted file mode 100644
index a8b8550f5baea..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/markdown/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/markdown/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/markdown/index.ts
index 1c7013834cbe4..7b114daa11870 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/markdown/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/markdown/index.ts
@@ -4,15 +4,13 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import header from './header.png';
-
import { ElementFactory } from '../../../types';
export const markdown: ElementFactory = () => ({
name: 'markdown',
- displayName: 'Markdown',
- tags: ['text'],
- help: 'Markup from Markdown',
- image: header,
+ displayName: 'Text',
+ type: 'text',
+ help: 'Add text using Markdown',
+ icon: 'visText',
expression: `filters
| demodata
| markdown "### Welcome to the Markdown element
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/metric/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/metric/header.png
deleted file mode 100644
index 0510342cdc54a..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/metric/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/metric/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/metric/index.ts
index 7e9aca9c01782..7256657903aab 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/metric/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/metric/index.ts
@@ -5,8 +5,6 @@
*/
import { openSans } from '../../../common/lib/fonts';
-import header from './header.png';
-
import { ElementFactory } from '../../../types';
import { SetupInitializer } from '../../plugin';
@@ -14,11 +12,11 @@ export const metricElementInitializer: SetupInitializer = (core,
return () => ({
name: 'metric',
displayName: 'Metric',
- tags: ['text'],
+ type: 'chart',
help: 'A number with a label',
width: 200,
height: 100,
- image: header,
+ icon: 'visMetric',
expression: `filters
| demodata
| math "unique(country)"
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/pie/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/pie/header.png
deleted file mode 100644
index deecd1067427c..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/pie/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/pie/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/pie/index.ts
index cfb9031325254..b7606ea94bc9f 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/pie/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/pie/index.ts
@@ -4,17 +4,15 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import header from './header.png';
-
import { ElementFactory } from '../../../types';
export const pie: ElementFactory = () => ({
name: 'pie',
- displayName: 'Pie chart',
- tags: ['chart', 'proportion'],
+ displayName: 'Pie',
+ type: 'chart',
width: 300,
height: 300,
help: 'A simple pie chart',
- image: header,
+ icon: 'visPie',
expression: `filters
| demodata
| pointseries color="state" size="max(price)"
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/plot/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/plot/header.png
deleted file mode 100644
index d48c789ae5a92..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/plot/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/plot/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/plot/index.ts
index dd1660d558667..8648b65def4b2 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/plot/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/plot/index.ts
@@ -5,14 +5,12 @@
*/
import { ElementFactory } from '../../../types';
-import header from './header.png';
export const plot: ElementFactory = () => ({
name: 'plot',
displayName: 'Coordinate plot',
- tags: ['chart'],
+ type: 'chart',
help: 'Mixed line, bar or dot charts',
- image: header,
expression: `filters
| demodata
| pointseries x="time" y="sum(price)" color="state"
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_gauge/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_gauge/header.png
deleted file mode 100644
index 8340c8a53b6ce..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_gauge/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_gauge/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_gauge/index.ts
index 4ec192fb787fe..b21b7df286ace 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_gauge/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_gauge/index.ts
@@ -6,16 +6,15 @@
import { openSans } from '../../../common/lib/fonts';
import { ElementFactory } from '../../../types';
-import header from './header.png';
export const progressGauge: ElementFactory = () => ({
name: 'progressGauge',
- displayName: 'Progress gauge',
- tags: ['chart', 'proportion'],
+ displayName: 'Gauge',
+ type: 'progress',
help: 'Displays progress as a portion of a gauge',
width: 200,
height: 200,
- image: header,
+ icon: 'visGoal',
expression: `filters
| demodata
| math "mean(percent_uptime)"
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_semicircle/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_semicircle/header.png
deleted file mode 100644
index b5b708529edd4..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_semicircle/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_semicircle/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_semicircle/index.ts
index 91fcb24996bc0..9ccb9489e8306 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_semicircle/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_semicircle/index.ts
@@ -6,16 +6,14 @@
import { openSans } from '../../../common/lib/fonts';
import { ElementFactory } from '../../../types';
-import header from './header.png';
export const progressSemicircle: ElementFactory = () => ({
name: 'progressSemicircle',
- displayName: 'Progress semicircle',
- tags: ['chart', 'proportion'],
+ displayName: 'Semicircle',
+ type: 'progress',
help: 'Displays progress as a portion of a semicircle',
width: 200,
height: 100,
- image: header,
expression: `filters
| demodata
| math "mean(percent_uptime)"
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_wheel/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_wheel/header.png
deleted file mode 100644
index 71e5d7e29444e..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_wheel/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_wheel/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_wheel/index.ts
index 05c537f88756b..42bf36346c303 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_wheel/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/progress_wheel/index.ts
@@ -6,16 +6,14 @@
import { openSans } from '../../../common/lib/fonts';
import { ElementFactory } from '../../../types';
-import header from './header.png';
export const progressWheel: ElementFactory = () => ({
name: 'progressWheel',
- displayName: 'Progress wheel',
- tags: ['chart', 'proportion'],
+ displayName: 'Wheel',
+ type: 'progress',
help: 'Displays progress as a portion of a wheel',
width: 200,
height: 200,
- image: header,
expression: `filters
| demodata
| math "mean(percent_uptime)"
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/repeat_image/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/repeat_image/header.png
deleted file mode 100644
index 9843c9a6d02c0..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/repeat_image/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/repeat_image/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/repeat_image/index.ts
index df79651620642..0bf0ec4c2dc1f 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/repeat_image/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/repeat_image/index.ts
@@ -5,14 +5,12 @@
*/
import { ElementFactory } from '../../../types';
-import header from './header.png';
export const repeatImage: ElementFactory = () => ({
name: 'repeatImage',
displayName: 'Image repeat',
- tags: ['graphic', 'proportion'],
+ type: 'image',
help: 'Repeats an image N times',
- image: header,
expression: `filters
| demodata
| math "mean(cost)"
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/reveal_image/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/reveal_image/header.png
deleted file mode 100644
index 8dc33b5a7259e..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/reveal_image/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/reveal_image/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/reveal_image/index.ts
index 01c66ed3a26ec..88000f6b66a91 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/reveal_image/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/reveal_image/index.ts
@@ -5,14 +5,12 @@
*/
import { ElementFactory } from '../../../types';
-import header from './header.png';
export const revealImage: ElementFactory = () => ({
name: 'revealImage',
displayName: 'Image reveal',
- tags: ['graphic', 'proportion'],
+ type: 'image',
help: 'Reveals a percentage of an image',
- image: header,
expression: `filters
| demodata
| math "mean(percent_uptime)"
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/shape/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/shape/header.png
deleted file mode 100644
index 3212d47591c07..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/shape/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/shape/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/shape/index.ts
index 3f3954ff02b02..f922473fa818f 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/shape/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/shape/index.ts
@@ -5,16 +5,15 @@
*/
import { ElementFactory } from '../../../types';
-import header from './header.png';
export const shape: ElementFactory = () => ({
name: 'shape',
displayName: 'Shape',
- tags: ['graphic'],
+ type: 'shape',
help: 'A customizable shape',
width: 200,
height: 200,
- image: header,
+ icon: 'node',
expression:
'shape "square" fill="#4cbce4" border="rgba(255,255,255,0)" borderWidth=0 maintainAspect=false | render',
});
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/table/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/table/header.png
deleted file mode 100644
index a883faa693c1f..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/table/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/table/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/table/index.ts
index ac13b7dc21293..ec26773fc3bf9 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/table/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/table/index.ts
@@ -5,14 +5,13 @@
*/
import { ElementFactory } from '../../../types';
-import header from './header.png';
export const table: ElementFactory = () => ({
name: 'table',
displayName: 'Data table',
- tags: ['text'],
+ type: 'chart',
help: 'A scrollable grid for displaying data in a tabular format',
- image: header,
+ icon: 'visTable',
expression: `filters
| demodata
| table
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/tilted_pie/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/tilted_pie/header.png
deleted file mode 100644
index b3329f991158c..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/tilted_pie/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/tilted_pie/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/tilted_pie/index.ts
deleted file mode 100644
index 21d8ba1e1b04a..0000000000000
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/tilted_pie/index.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import { ElementFactory } from '../../../types';
-import header from './header.png';
-
-export const tiltedPie: ElementFactory = () => ({
- name: 'tiltedPie',
- displayName: 'Tilted pie chart',
- tags: ['chart', 'proportion'],
- width: 500,
- height: 250,
- help: 'A customizable tilted pie chart',
- image: header,
- expression: `filters
-| demodata
-| pointseries color="project" size="max(price)"
-| pie tilt=0.5
-| render`,
-});
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/time_filter/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/time_filter/header.png
deleted file mode 100644
index d36b4cc97e5b1..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/time_filter/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/time_filter/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/time_filter/index.ts
index b384707c243d1..702ccb8a2312f 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/time_filter/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/time_filter/index.ts
@@ -5,14 +5,13 @@
*/
import { ElementFactory } from '../../../types';
-import header from './header.png';
export const timeFilter: ElementFactory = () => ({
- name: 'time_filter',
+ name: 'timeFilter',
displayName: 'Time filter',
- tags: ['filter'],
+ type: 'filter',
help: 'Set a time window',
- image: header,
+ icon: 'calendar',
height: 50,
expression: `timefilterControl compact=true column=@timestamp
| render`,
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vert_bar_chart/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vert_bar_chart/header.png
deleted file mode 100644
index 90505dd0dc77d..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vert_bar_chart/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vert_bar_chart/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vert_bar_chart/index.ts
index ac4e3a0a72150..2354be0328e7c 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vert_bar_chart/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vert_bar_chart/index.ts
@@ -5,14 +5,13 @@
*/
import { ElementFactory } from '../../../types';
-import header from './header.png';
export const verticalBarChart: ElementFactory = () => ({
name: 'verticalBarChart',
displayName: 'Vertical bar chart',
- tags: ['chart'],
+ type: 'chart',
help: 'A customizable vertical bar chart',
- image: header,
+ icon: 'visBarVertical',
expression: `filters
| demodata
| pointseries x="project" y="size(cost)" color="project"
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vertical_progress_bar/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vertical_progress_bar/header.png
deleted file mode 100644
index b9ff963e92c31..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vertical_progress_bar/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vertical_progress_bar/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vertical_progress_bar/index.ts
index e12903dafede9..b5e6c9816e3f5 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vertical_progress_bar/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vertical_progress_bar/index.ts
@@ -6,16 +6,14 @@
import { openSans } from '../../../common/lib/fonts';
import { ElementFactory } from '../../../types';
-import header from './header.png';
export const verticalProgressBar: ElementFactory = () => ({
name: 'verticalProgressBar',
displayName: 'Vertical progress bar',
- tags: ['chart', 'proportion'],
+ type: 'progress',
help: 'Displays progress as a portion of a vertical bar',
width: 80,
height: 400,
- image: header,
expression: `filters
| demodata
| math "mean(percent_uptime)"
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vertical_progress_pill/header.png b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vertical_progress_pill/header.png
deleted file mode 100644
index a4ac6b57da236..0000000000000
Binary files a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vertical_progress_pill/header.png and /dev/null differ
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vertical_progress_pill/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vertical_progress_pill/index.ts
index 8926a12da8a47..28e80372494db 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vertical_progress_pill/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/elements/vertical_progress_pill/index.ts
@@ -6,16 +6,14 @@
import { openSans } from '../../../common/lib/fonts';
import { ElementFactory } from '../../../types';
-import header from './header.png';
export const verticalProgressPill: ElementFactory = () => ({
name: 'verticalProgressPill',
displayName: 'Vertical progress pill',
- tags: ['chart', 'proportion'],
+ type: 'progress',
help: 'Displays progress as a portion of a vertical pill',
width: 80,
height: 400,
- image: header,
expression: `filters
| demodata
| math "mean(percent_uptime)"
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/tags/chart.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/tags/chart.ts
deleted file mode 100644
index 4c535a42c3c44..0000000000000
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/tags/chart.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import { euiPaletteColorBlind } from '@elastic/eui';
-import { TagFactory } from '../../../public/lib/tag';
-import { TagStrings as strings } from '../../../i18n';
-const euiVisPalette = euiPaletteColorBlind();
-
-export const chart: TagFactory = () => ({
- name: strings.chart(),
- color: euiVisPalette[4],
-});
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/tags/filter.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/tags/filter.ts
deleted file mode 100644
index 5249856dec271..0000000000000
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/tags/filter.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import { euiPaletteColorBlind } from '@elastic/eui';
-import { TagFactory } from '../../../public/lib/tag';
-import { TagStrings as strings } from '../../../i18n';
-
-const euiVisPalette = euiPaletteColorBlind();
-
-export const filter: TagFactory = () => ({
- name: strings.filter(),
- color: euiVisPalette[1],
-});
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/tags/graphic.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/tags/graphic.ts
deleted file mode 100644
index 36d66801ef681..0000000000000
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/tags/graphic.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import { euiPaletteColorBlind } from '@elastic/eui';
-import { TagFactory } from '../../../public/lib/tag';
-import { TagStrings as strings } from '../../../i18n';
-const euiVisPalette = euiPaletteColorBlind();
-
-export const graphic: TagFactory = () => ({
- name: strings.graphic(),
- color: euiVisPalette[5],
-});
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/tags/index.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/tags/index.ts
index 2587665a452b5..2e711437c72a8 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/tags/index.ts
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/tags/index.ts
@@ -4,13 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { chart } from './chart';
-import { filter } from './filter';
-import { graphic } from './graphic';
import { presentation } from './presentation';
-import { proportion } from './proportion';
import { report } from './report';
-import { text } from './text';
// Registry expects a function that returns a spec object
-export const tagSpecs = [chart, filter, graphic, presentation, proportion, report, text];
+export const tagSpecs = [presentation, report];
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/tags/proportion.ts b/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/tags/proportion.ts
deleted file mode 100644
index 4d37ecfaa367a..0000000000000
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/tags/proportion.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import { euiPaletteColorBlind } from '@elastic/eui';
-import { TagFactory } from '../../../public/lib/tag';
-import { TagStrings as strings } from '../../../i18n';
-const euiVisPalette = euiPaletteColorBlind();
-
-export const proportion: TagFactory = () => ({
- name: strings.proportion(),
- color: euiVisPalette[3],
-});
diff --git a/x-pack/legacy/plugins/canvas/common/lib/constants.ts b/x-pack/legacy/plugins/canvas/common/lib/constants.ts
index ac8e80b8d7b89..a37dc3fd6a7b3 100644
--- a/x-pack/legacy/plugins/canvas/common/lib/constants.ts
+++ b/x-pack/legacy/plugins/canvas/common/lib/constants.ts
@@ -40,3 +40,4 @@ export const API_ROUTE_SHAREABLE_ZIP = '/public/canvas/zip';
export const API_ROUTE_SHAREABLE_RUNTIME = '/public/canvas/runtime';
export const API_ROUTE_SHAREABLE_RUNTIME_DOWNLOAD = `/public/canvas/${SHAREABLE_RUNTIME_NAME}.js`;
export const CANVAS_EMBEDDABLE_CLASSNAME = `canvasEmbeddable`;
+export const CONTEXT_MENU_TOP_BORDER_CLASSNAME = 'canvasContextMenu--topBorder';
diff --git a/x-pack/legacy/plugins/canvas/i18n/components.ts b/x-pack/legacy/plugins/canvas/i18n/components.ts
index d0a9051d7af87..7bd16c4933ce1 100644
--- a/x-pack/legacy/plugins/canvas/i18n/components.ts
+++ b/x-pack/legacy/plugins/canvas/i18n/components.ts
@@ -15,7 +15,7 @@ export const ComponentStrings = {
}),
getTitleText: () =>
i18n.translate('xpack.canvas.embedObject.titleText', {
- defaultMessage: 'Embed Object',
+ defaultMessage: 'Add from Visualize library',
}),
},
AdvancedFilter: {
@@ -305,21 +305,21 @@ export const ComponentStrings = {
}),
},
ElementControls: {
- getEditTooltip: () =>
- i18n.translate('xpack.canvas.elementControls.editToolTip', {
- defaultMessage: 'Edit',
- }),
- getEditAriaLabel: () =>
- i18n.translate('xpack.canvas.elementControls.editAriaLabel', {
- defaultMessage: 'Edit element',
+ getDeleteAriaLabel: () =>
+ i18n.translate('xpack.canvas.elementControls.deleteAriaLabel', {
+ defaultMessage: 'Delete element',
}),
getDeleteTooltip: () =>
i18n.translate('xpack.canvas.elementControls.deleteToolTip', {
defaultMessage: 'Delete',
}),
- getDeleteAriaLabel: () =>
- i18n.translate('xpack.canvas.elementControls.deleteAriaLabel', {
- defaultMessage: 'Delete element',
+ getEditAriaLabel: () =>
+ i18n.translate('xpack.canvas.elementControls.editAriaLabel', {
+ defaultMessage: 'Edit element',
+ }),
+ getEditTooltip: () =>
+ i18n.translate('xpack.canvas.elementControls.editToolTip', {
+ defaultMessage: 'Edit',
}),
},
ElementSettings: {
@@ -336,53 +336,6 @@ export const ComponentStrings = {
description: 'This tab contains the settings for how data is displayed in a Canvas element',
}),
},
- ElementTypes: {
- getEditElementTitle: () =>
- i18n.translate('xpack.canvas.elementTypes.editElementTitle', {
- defaultMessage: 'Edit element',
- }),
- getDeleteElementTitle: (elementName: string) =>
- i18n.translate('xpack.canvas.elementTypes.deleteElementTitle', {
- defaultMessage: `Delete element '{elementName}'?`,
- values: {
- elementName,
- },
- }),
- getDeleteElementDescription: () =>
- i18n.translate('xpack.canvas.elementTypes.deleteElementDescription', {
- defaultMessage: 'Are you sure you want to delete this element?',
- }),
- getCancelButtonLabel: () =>
- i18n.translate('xpack.canvas.elementTypes.cancelButtonLabel', {
- defaultMessage: 'Cancel',
- }),
- getDeleteButtonLabel: () =>
- i18n.translate('xpack.canvas.elementTypes.deleteButtonLabel', {
- defaultMessage: 'Delete',
- }),
- getAddNewElementTitle: () =>
- i18n.translate('xpack.canvas.elementTypes.addNewElementTitle', {
- defaultMessage: 'Add new elements',
- }),
- getAddNewElementDescription: () =>
- i18n.translate('xpack.canvas.elementTypes.addNewElementDescription', {
- defaultMessage: 'Group and save workpad elements to create new elements',
- }),
- getFindElementPlaceholder: () =>
- i18n.translate('xpack.canvas.elementTypes.findElementPlaceholder', {
- defaultMessage: 'Find element',
- }),
- getElementsTitle: () =>
- i18n.translate('xpack.canvas.elementTypes.elementsTitle', {
- defaultMessage: 'Elements',
- description: 'Title for the "Elements" tab when adding a new element',
- }),
- getMyElementsTitle: () =>
- i18n.translate('xpack.canvas.elementTypes.myElementsTitle', {
- defaultMessage: 'My elements',
- description: 'Title for the "My elements" tab when adding a new element',
- }),
- },
Error: {
getDescription: () =>
i18n.translate('xpack.canvas.errorComponent.description', {
@@ -633,6 +586,61 @@ export const ComponentStrings = {
defaultMessage: 'Delete',
}),
},
+ SavedElementsModal: {
+ getAddNewElementDescription: () =>
+ i18n.translate('xpack.canvas.savedElementsModal.addNewElementDescription', {
+ defaultMessage: 'Group and save workpad elements to create new elements',
+ }),
+ getAddNewElementTitle: () =>
+ i18n.translate('xpack.canvas.savedElementsModal.addNewElementTitle', {
+ defaultMessage: 'Add new elements',
+ }),
+ getCancelButtonLabel: () =>
+ i18n.translate('xpack.canvas.savedElementsModal.cancelButtonLabel', {
+ defaultMessage: 'Cancel',
+ }),
+ getDeleteButtonLabel: () =>
+ i18n.translate('xpack.canvas.savedElementsModal.deleteButtonLabel', {
+ defaultMessage: 'Delete',
+ }),
+ getDeleteElementDescription: () =>
+ i18n.translate('xpack.canvas.savedElementsModal.deleteElementDescription', {
+ defaultMessage: 'Are you sure you want to delete this element?',
+ }),
+ getDeleteElementTitle: (elementName: string) =>
+ i18n.translate('xpack.canvas.savedElementsModal.deleteElementTitle', {
+ defaultMessage: `Delete element '{elementName}'?`,
+ values: {
+ elementName,
+ },
+ }),
+ getEditElementTitle: () =>
+ i18n.translate('xpack.canvas.savedElementsModal.editElementTitle', {
+ defaultMessage: 'Edit element',
+ }),
+ getElementsTitle: () =>
+ i18n.translate('xpack.canvas.savedElementsModal.elementsTitle', {
+ defaultMessage: 'Elements',
+ description: 'Title for the "Elements" tab when adding a new element',
+ }),
+ getFindElementPlaceholder: () =>
+ i18n.translate('xpack.canvas.savedElementsModal.findElementPlaceholder', {
+ defaultMessage: 'Find element',
+ }),
+ getModalTitle: () =>
+ i18n.translate('xpack.canvas.savedElementsModal.modalTitle', {
+ defaultMessage: 'My elements',
+ }),
+ getMyElementsTitle: () =>
+ i18n.translate('xpack.canvas.savedElementsModal.myElementsTitle', {
+ defaultMessage: 'My elements',
+ description: 'Title for the "My elements" tab when adding a new element',
+ }),
+ getSavedElementsModalCloseButtonLabel: () =>
+ i18n.translate('xpack.canvas.workpadHeader.addElementModalCloseButtonLabel', {
+ defaultMessage: 'Close',
+ }),
+ },
ShareWebsiteFlyout: {
getRuntimeStepTitle: () =>
i18n.translate('xpack.canvas.shareWebsiteFlyout.snippetsStep.downloadRuntimeTitle', {
@@ -652,7 +660,7 @@ export const ComponentStrings = {
defaultMessage: 'Share on a website',
}),
getUnsupportedRendererWarning: () =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.unsupportedRendererWarning', {
+ i18n.translate('xpack.canvas.workpadHeaderShareMenu.unsupportedRendererWarning', {
defaultMessage:
'This workpad contains render functions that are not supported by the {CANVAS} Shareable Workpad Runtime. These elements will not be rendered:',
values: {
@@ -900,6 +908,10 @@ export const ComponentStrings = {
i18n.translate('xpack.canvas.textStylePicker.alignRightOption', {
defaultMessage: 'Align right',
}),
+ getFontColorLabel: () =>
+ i18n.translate('xpack.canvas.textStylePicker.fontColorLabel', {
+ defaultMessage: 'Font Color',
+ }),
getStyleBoldOption: () =>
i18n.translate('xpack.canvas.textStylePicker.styleBoldOption', {
defaultMessage: 'Bold',
@@ -912,10 +924,6 @@ export const ComponentStrings = {
i18n.translate('xpack.canvas.textStylePicker.styleUnderlineOption', {
defaultMessage: 'Underline',
}),
- getFontColorLabel: () =>
- i18n.translate('xpack.canvas.textStylePicker.fontColorLabel', {
- defaultMessage: 'Font Color',
- }),
},
TimePicker: {
getApplyButtonLabel: () =>
@@ -962,6 +970,10 @@ export const ComponentStrings = {
description:
'"stylesheet" refers to the collection of CSS style rules entered by the user.',
}),
+ getBackgroundColorLabel: () =>
+ i18n.translate('xpack.canvas.workpadConfig.backgroundColorLabel', {
+ defaultMessage: 'Background color',
+ }),
getFlipDimensionAriaLabel: () =>
i18n.translate('xpack.canvas.workpadConfig.swapDimensionsAriaLabel', {
defaultMessage: `Swap the page's width and height`,
@@ -1013,10 +1025,6 @@ export const ComponentStrings = {
defaultMessage: 'US Letter',
description: 'This is referring to the dimensions of U.S. standard letter paper.',
}),
- getBackgroundColorLabel: () =>
- i18n.translate('xpack.canvas.workpadConfig.backgroundColorLabel', {
- defaultMessage: 'Background color',
- }),
},
WorkpadCreate: {
getWorkpadCreateButtonLabel: () =>
@@ -1029,14 +1037,6 @@ export const ComponentStrings = {
i18n.translate('xpack.canvas.workpadHeader.addElementButtonLabel', {
defaultMessage: 'Add element',
}),
- getAddElementModalCloseButtonLabel: () =>
- i18n.translate('xpack.canvas.workpadHeader.addElementModalCloseButtonLabel', {
- defaultMessage: 'Close',
- }),
- getEmbedObjectButtonLabel: () =>
- i18n.translate('xpack.canvas.workpadHeader.embedObjectButtonLabel', {
- defaultMessage: 'Embed object',
- }),
getFullScreenButtonAriaLabel: () =>
i18n.translate('xpack.canvas.workpadHeader.fullscreenButtonAriaLabel', {
defaultMessage: 'View fullscreen',
@@ -1080,9 +1080,9 @@ export const ComponentStrings = {
}),
},
WorkpadHeaderControlSettings: {
- getTooltip: () =>
- i18n.translate('xpack.canvas.workpadHeaderControlSettings.settingsTooltip', {
- defaultMessage: 'Control settings',
+ getButtonLabel: () =>
+ i18n.translate('xpack.canvas.workpadHeaderControlSettings.buttonLabel', {
+ defaultMessage: 'Options',
}),
},
WorkpadHeaderCustomInterval: {
@@ -1105,6 +1105,56 @@ export const ComponentStrings = {
defaultMessage: 'Set a custom interval',
}),
},
+ WorkpadHeaderElementMenu: {
+ getAssetsMenuItemLabel: () =>
+ i18n.translate('xpack.canvas.workpadHeaderElementMenu.manageAssetsMenuItemLabel', {
+ defaultMessage: 'Manage assets',
+ }),
+ getChartMenuItemLabel: () =>
+ i18n.translate('xpack.canvas.workpadHeaderElementMenu.chartMenuItemLabel', {
+ defaultMessage: 'Chart',
+ }),
+ getElementMenuButtonLabel: () =>
+ i18n.translate('xpack.canvas.workpadHeaderElementMenu.elementMenuButtonLabel', {
+ defaultMessage: 'Add element',
+ }),
+ getElementMenuLabel: () =>
+ i18n.translate('xpack.canvas.workpadHeaderElementMenu.elementMenuLabel', {
+ defaultMessage: 'Add an element',
+ }),
+ getEmbedObjectMenuItemLabel: () =>
+ i18n.translate('xpack.canvas.workpadHeaderElementMenu.embedObjectMenuItemLabel', {
+ defaultMessage: 'Add from Visualize library',
+ }),
+ getFilterMenuItemLabel: () =>
+ i18n.translate('xpack.canvas.workpadHeaderElementMenu.filterMenuItemLabel', {
+ defaultMessage: 'Filter',
+ }),
+ getImageMenuItemLabel: () =>
+ i18n.translate('xpack.canvas.workpadHeaderElementMenu.imageMenuItemLabel', {
+ defaultMessage: 'Image',
+ }),
+ getMyElementsMenuItemLabel: () =>
+ i18n.translate('xpack.canvas.workpadHeaderElementMenu.myElementsMenuItemLabel', {
+ defaultMessage: 'My elements',
+ }),
+ getOtherMenuItemLabel: () =>
+ i18n.translate('xpack.canvas.workpadHeaderElementMenu.otherMenuItemLabel', {
+ defaultMessage: 'Other',
+ }),
+ getProgressMenuItemLabel: () =>
+ i18n.translate('xpack.canvas.workpadHeaderElementMenu.progressMenuItemLabel', {
+ defaultMessage: 'Progress',
+ }),
+ getShapeMenuItemLabel: () =>
+ i18n.translate('xpack.canvas.workpadHeaderElementMenu.shapeMenuItemLabel', {
+ defaultMessage: 'Shape',
+ }),
+ getTextMenuItemLabel: () =>
+ i18n.translate('xpack.canvas.workpadHeaderElementMenu.textMenuItemLabel', {
+ defaultMessage: 'Text',
+ }),
+ },
WorkpadHeaderKioskControls: {
getCycleFormLabel: () =>
i18n.translate('xpack.canvas.workpadHeaderKioskControl.cycleFormLabel', {
@@ -1129,9 +1179,9 @@ export const ComponentStrings = {
defaultMessage: 'Refresh data',
}),
},
- WorkpadHeaderWorkpadExport: {
+ WorkpadHeaderShareMenu: {
getCopyPDFMessage: () =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.copyPDFMessage', {
+ i18n.translate('xpack.canvas.workpadHeaderShareMenu.copyPDFMessage', {
defaultMessage: 'The {PDF} generation {URL} was copied to your clipboard.',
values: {
PDF,
@@ -1139,15 +1189,15 @@ export const ComponentStrings = {
},
}),
getCopyReportingConfigMessage: () =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.copyReportingConfigMessage', {
+ i18n.translate('xpack.canvas.workpadHeaderShareMenu.copyReportingConfigMessage', {
defaultMessage: 'Copied reporting configuration to clipboard',
}),
getCopyShareConfigMessage: () =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.copyShareConfigMessage', {
+ i18n.translate('xpack.canvas.workpadHeaderShareMenu.copyShareConfigMessage', {
defaultMessage: 'Copied share markup to clipboard',
}),
getExportPDFErrorTitle: (workpadName: string) =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.exportPDFErrorMessage', {
+ i18n.translate('xpack.canvas.workpadHeaderShareMenu.exportPDFErrorMessage', {
defaultMessage: "Failed to create {PDF} for '{workpadName}'",
values: {
PDF,
@@ -1155,14 +1205,14 @@ export const ComponentStrings = {
},
}),
getExportPDFMessage: () =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.exportPDFMessage', {
+ i18n.translate('xpack.canvas.workpadHeaderShareMenu.exportPDFMessage', {
defaultMessage: 'Exporting {PDF}. You can track the progress in Management.',
values: {
PDF,
},
}),
getExportPDFTitle: (workpadName: string) =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.exportPDFTitle', {
+ i18n.translate('xpack.canvas.workpadHeaderShareMenu.exportPDFTitle', {
defaultMessage: "{PDF} export of workpad '{workpadName}'",
values: {
PDF,
@@ -1170,7 +1220,7 @@ export const ComponentStrings = {
},
}),
getPDFPanelCopyAriaLabel: () =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.pdfPanelCopyAriaLabel', {
+ i18n.translate('xpack.canvas.workpadHeaderShareMenu.pdfPanelCopyAriaLabel', {
defaultMessage:
'Alternatively, you can generate a {PDF} from a script or with Watcher by using this {URL}. Press Enter to copy the {URL} to clipboard.',
values: {
@@ -1179,7 +1229,7 @@ export const ComponentStrings = {
},
}),
getPDFPanelCopyButtonLabel: () =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.pdfPanelCopyButtonLabel', {
+ i18n.translate('xpack.canvas.workpadHeaderShareMenu.pdfPanelCopyButtonLabel', {
defaultMessage: 'Copy {POST} {URL}',
values: {
POST,
@@ -1187,7 +1237,7 @@ export const ComponentStrings = {
},
}),
getPDFPanelCopyDescription: () =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.pdfPanelCopyDescription', {
+ i18n.translate('xpack.canvas.workpadHeaderShareMenu.pdfPanelCopyDescription', {
defaultMessage:
'Alternatively, copy this {POST} {URL} to call generation from outside {KIBANA} or from Watcher.',
values: {
@@ -1197,14 +1247,14 @@ export const ComponentStrings = {
},
}),
getPDFPanelGenerateButtonLabel: () =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.pdfPanelGenerateButtonLabel', {
+ i18n.translate('xpack.canvas.workpadHeaderShareMenu.pdfPanelGenerateButtonLabel', {
defaultMessage: 'Generate {PDF}',
values: {
PDF,
},
}),
getPDFPanelGenerateDescription: () =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.pdfPanelGenerateDescription', {
+ i18n.translate('xpack.canvas.workpadHeaderShareMenu.pdfPanelGenerateDescription', {
defaultMessage:
'{PDF}s can take a minute or two to generate based on the size of your workpad.',
values: {
@@ -1212,7 +1262,7 @@ export const ComponentStrings = {
},
}),
getShareableZipErrorTitle: (workpadName: string) =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.shareWebsiteErrorTitle', {
+ i18n.translate('xpack.canvas.workpadHeaderShareMenu.shareWebsiteErrorTitle', {
defaultMessage:
"Failed to create {ZIP} file for '{workpadName}'. The workpad may be too large. You'll need to download the files separately.",
values: {
@@ -1221,69 +1271,101 @@ export const ComponentStrings = {
},
}),
getShareDownloadJSONTitle: () =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.shareDownloadJSONTitle', {
+ i18n.translate('xpack.canvas.workpadHeaderShareMenu.shareDownloadJSONTitle', {
defaultMessage: 'Download as {JSON}',
values: {
JSON,
},
}),
getShareDownloadPDFTitle: () =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.shareDownloadPDFTitle', {
+ i18n.translate('xpack.canvas.workpadHeaderShareMenu.shareDownloadPDFTitle', {
defaultMessage: '{PDF} reports',
values: {
PDF,
},
}),
+ getShareMenuButtonLabel: () =>
+ i18n.translate('xpack.canvas.workpadHeaderShareMenu.shareMenuButtonLabel', {
+ defaultMessage: 'Share',
+ }),
getShareWebsiteTitle: () =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.shareWebsiteTitle', {
+ i18n.translate('xpack.canvas.workpadHeaderShareMenu.shareWebsiteTitle', {
defaultMessage: 'Share on a website',
}),
getShareWorkpadMessage: () =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.shareWorkpadMessage', {
+ i18n.translate('xpack.canvas.workpadHeaderShareMenu.shareWorkpadMessage', {
defaultMessage: 'Share this workpad',
}),
getUnknownExportErrorMessage: (type: string) =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadExport.unknownExportErrorMessage', {
+ i18n.translate('xpack.canvas.workpadHeaderShareMenu.unknownExportErrorMessage', {
defaultMessage: 'Unknown export type: {type}',
values: {
type,
},
}),
},
- WorkpadHeaderWorkpadZoom: {
+ WorkpadHeaderViewMenu: {
+ getFullscreenMenuItemLabel: () =>
+ i18n.translate('xpack.canvas.workpadHeaderViewMenu.fullscreenMenuLabel', {
+ defaultMessage: 'Enter fullscreen mode',
+ }),
+ getHideEditModeLabel: () =>
+ i18n.translate('xpack.canvas.workpadHeaderViewMenu.hideEditModeLabel', {
+ defaultMessage: 'Hide editing controls',
+ }),
+ getRefreshMenuItemLabel: () =>
+ i18n.translate('xpack.canvas.workpadHeaderViewMenu.refreshMenuItemLabel', {
+ defaultMessage: 'Refresh data',
+ }),
+ getShowEditModeLabel: () =>
+ i18n.translate('xpack.canvas.workpadHeaderViewMenu.showEditModeLabel', {
+ defaultMessage: 'Show editing controls',
+ }),
+ getViewMenuButtonLabel: () =>
+ i18n.translate('xpack.canvas.workpadHeaderViewMenu.viewMenuButtonLabel', {
+ defaultMessage: 'View',
+ }),
+ getViewMenuLabel: () =>
+ i18n.translate('xpack.canvas.workpadHeaderViewMenu.viewMenuLabel', {
+ defaultMessage: 'View options',
+ }),
getZoomControlsAriaLabel: () =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadZoom.zoomControlsAriaLabel', {
+ i18n.translate('xpack.canvas.workpadHeaderViewMenu.zoomControlsAriaLabel', {
defaultMessage: 'Zoom controls',
}),
getZoomControlsTooltip: () =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadZoom.zoomControlsTooltip', {
+ i18n.translate('xpack.canvas.workpadHeaderViewMenu.zoomControlsTooltip', {
defaultMessage: 'Zoom controls',
}),
getZoomFitToWindowText: () =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadZoom.zoomFitToWindowText', {
+ i18n.translate('xpack.canvas.workpadHeaderViewMenu.zoomFitToWindowText', {
defaultMessage: 'Fit to window',
}),
getZoomInText: () =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadZoom.zoomInText', {
+ i18n.translate('xpack.canvas.workpadHeaderViewMenu.zoomInText', {
defaultMessage: 'Zoom in',
}),
+ getZoomMenuItemLabel: () =>
+ i18n.translate('xpack.canvas.workpadHeaderViewMenu.zoomMenuItemLabel', {
+ defaultMessage: 'Zoom',
+ }),
getZoomOutText: () =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadZoom.zoomOutText', {
+ i18n.translate('xpack.canvas.workpadHeaderViewMenu.zoomOutText', {
defaultMessage: 'Zoom out',
}),
getZoomPanelTitle: () =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadZoom.zoomPanelTitle', {
+ i18n.translate('xpack.canvas.workpadHeaderViewMenu.zoomPanelTitle', {
defaultMessage: 'Zoom',
}),
getZoomPercentage: (scale: number) =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadZoom.zoomResetText', {
+ i18n.translate('xpack.canvas.workpadHeaderViewMenu.zoomResetText', {
defaultMessage: '{scalePercentage}%',
values: {
scalePercentage: scale * 100,
},
}),
getZoomResetText: () =>
- i18n.translate('xpack.canvas.workpadHeaderWorkpadZoom.zoomPrecentageValue', {
+ i18n.translate('xpack.canvas.workpadHeaderViewMenu.zoomPrecentageValue', {
defaultMessage: 'Reset',
}),
},
diff --git a/x-pack/legacy/plugins/canvas/i18n/elements/apply_strings.ts b/x-pack/legacy/plugins/canvas/i18n/elements/apply_strings.ts
index 41f88a3c75f90..4464ed5dbf185 100644
--- a/x-pack/legacy/plugins/canvas/i18n/elements/apply_strings.ts
+++ b/x-pack/legacy/plugins/canvas/i18n/elements/apply_strings.ts
@@ -7,8 +7,6 @@
import { ElementFactory } from '../../types';
import { getElementStrings } from './index';
-import { TagStrings } from '../../i18n';
-
/**
* This function takes a set of Canvas Element specification factories, runs them,
* replaces relevant strings (if available) and returns a new factory. We do this
@@ -34,17 +32,6 @@ export const applyElementStrings = (elements: ElementFactory[]) => {
if (displayName) {
result.displayName = displayName;
}
-
- // Set translated tags
- if (result.tags) {
- result.tags = result.tags.map(tag => {
- if (tag in TagStrings) {
- return TagStrings[tag]();
- }
-
- return tag;
- });
- }
}
return () => result;
diff --git a/x-pack/legacy/plugins/canvas/i18n/elements/element_strings.test.ts b/x-pack/legacy/plugins/canvas/i18n/elements/element_strings.test.ts
index ce908ac6c5566..c28229bdab33f 100644
--- a/x-pack/legacy/plugins/canvas/i18n/elements/element_strings.test.ts
+++ b/x-pack/legacy/plugins/canvas/i18n/elements/element_strings.test.ts
@@ -9,8 +9,6 @@ import { coreMock } from '../../../../../../src/core/public/mocks';
const elementSpecs = initializeElements(coreMock.createSetup() as any, {} as any);
-import { TagStrings } from '../tags';
-
describe('ElementStrings', () => {
const elementStrings = getElementStrings();
const elementNames = elementSpecs.map(spec => spec().name);
@@ -37,15 +35,4 @@ describe('ElementStrings', () => {
expect(value).toHaveProperty('help');
});
});
-
- test('All elements should have tags that are defined', () => {
- const tagNames = Object.keys(TagStrings);
-
- elementSpecs.forEach(spec => {
- const element = spec();
- if (element.tags) {
- element.tags.forEach((tagName: string) => expect(tagNames).toContain(tagName));
- }
- });
- });
});
diff --git a/x-pack/legacy/plugins/canvas/i18n/elements/element_strings.ts b/x-pack/legacy/plugins/canvas/i18n/elements/element_strings.ts
index df23dff1c7127..595ef4cb92206 100644
--- a/x-pack/legacy/plugins/canvas/i18n/elements/element_strings.ts
+++ b/x-pack/legacy/plugins/canvas/i18n/elements/element_strings.ts
@@ -23,7 +23,7 @@ interface ElementStringDict {
export const getElementStrings = (): ElementStringDict => ({
areaChart: {
displayName: i18n.translate('xpack.canvas.elements.areaChartDisplayName', {
- defaultMessage: 'Area chart',
+ defaultMessage: 'Area',
}),
help: i18n.translate('xpack.canvas.elements.areaChartHelpText', {
defaultMessage: 'A line chart with a filled body',
@@ -31,7 +31,7 @@ export const getElementStrings = (): ElementStringDict => ({
},
bubbleChart: {
displayName: i18n.translate('xpack.canvas.elements.bubbleChartDisplayName', {
- defaultMessage: 'Bubble chart',
+ defaultMessage: 'Bubble',
}),
help: i18n.translate('xpack.canvas.elements.bubbleChartHelpText', {
defaultMessage: 'A customizable bubble chart',
@@ -39,31 +39,31 @@ export const getElementStrings = (): ElementStringDict => ({
},
debug: {
displayName: i18n.translate('xpack.canvas.elements.debugDisplayName', {
- defaultMessage: 'Debug',
+ defaultMessage: 'Debug data',
}),
help: i18n.translate('xpack.canvas.elements.debugHelpText', {
defaultMessage: 'Just dumps the configuration of the element',
}),
},
- donut: {
- displayName: i18n.translate('xpack.canvas.elements.donutChartDisplayName', {
- defaultMessage: 'Donut chart',
- }),
- help: i18n.translate('xpack.canvas.elements.donutChartHelpText', {
- defaultMessage: 'A customizable donut chart',
- }),
- },
- dropdown_filter: {
+ dropdownFilter: {
displayName: i18n.translate('xpack.canvas.elements.dropdownFilterDisplayName', {
- defaultMessage: 'Dropdown filter',
+ defaultMessage: 'Dropdown select',
}),
help: i18n.translate('xpack.canvas.elements.dropdownFilterHelpText', {
defaultMessage: 'A dropdown from which you can select values for an "exactly" filter',
}),
},
+ filterDebug: {
+ displayName: i18n.translate('xpack.canvas.elements.filterDebugDisplayName', {
+ defaultMessage: 'Debug filters',
+ }),
+ help: i18n.translate('xpack.canvas.elements.filterDebugHelpText', {
+ defaultMessage: 'Shows the underlying global filters in a workpad',
+ }),
+ },
horizontalBarChart: {
displayName: i18n.translate('xpack.canvas.elements.horizontalBarChartDisplayName', {
- defaultMessage: 'Horizontal bar chart',
+ defaultMessage: 'Horizontal bar',
}),
help: i18n.translate('xpack.canvas.elements.horizontalBarChartHelpText', {
defaultMessage: 'A customizable horizontal bar chart',
@@ -71,7 +71,7 @@ export const getElementStrings = (): ElementStringDict => ({
},
horizontalProgressBar: {
displayName: i18n.translate('xpack.canvas.elements.horizontalProgressBarDisplayName', {
- defaultMessage: 'Horizontal progress bar',
+ defaultMessage: 'Horizontal bar',
}),
help: i18n.translate('xpack.canvas.elements.horizontalProgressBarHelpText', {
defaultMessage: 'Displays progress as a portion of a horizontal bar',
@@ -79,7 +79,7 @@ export const getElementStrings = (): ElementStringDict => ({
},
horizontalProgressPill: {
displayName: i18n.translate('xpack.canvas.elements.horizontalProgressPillDisplayName', {
- defaultMessage: 'Horizontal progress pill',
+ defaultMessage: 'Horizontal pill',
}),
help: i18n.translate('xpack.canvas.elements.horizontalProgressPillHelpText', {
defaultMessage: 'Displays progress as a portion of a horizontal pill',
@@ -95,7 +95,7 @@ export const getElementStrings = (): ElementStringDict => ({
},
lineChart: {
displayName: i18n.translate('xpack.canvas.elements.lineChartDisplayName', {
- defaultMessage: 'Line chart',
+ defaultMessage: 'Line',
}),
help: i18n.translate('xpack.canvas.elements.lineChartHelpText', {
defaultMessage: 'A customizable line chart',
@@ -119,7 +119,7 @@ export const getElementStrings = (): ElementStringDict => ({
},
pie: {
displayName: i18n.translate('xpack.canvas.elements.pieDisplayName', {
- defaultMessage: 'Pie chart',
+ defaultMessage: 'Pie',
}),
help: i18n.translate('xpack.canvas.elements.pieHelpText', {
defaultMessage: 'Pie chart',
@@ -135,7 +135,7 @@ export const getElementStrings = (): ElementStringDict => ({
},
progressGauge: {
displayName: i18n.translate('xpack.canvas.elements.progressGaugeDisplayName', {
- defaultMessage: 'Progress gauge',
+ defaultMessage: 'Gauge',
}),
help: i18n.translate('xpack.canvas.elements.progressGaugeHelpText', {
defaultMessage: 'Displays progress as a portion of a gauge',
@@ -143,7 +143,7 @@ export const getElementStrings = (): ElementStringDict => ({
},
progressSemicircle: {
displayName: i18n.translate('xpack.canvas.elements.progressSemicircleDisplayName', {
- defaultMessage: 'Progress semicircle',
+ defaultMessage: 'Semicircle',
}),
help: i18n.translate('xpack.canvas.elements.progressSemicircleHelpText', {
defaultMessage: 'Displays progress as a portion of a semicircle',
@@ -151,7 +151,7 @@ export const getElementStrings = (): ElementStringDict => ({
},
progressWheel: {
displayName: i18n.translate('xpack.canvas.elements.progressWheelDisplayName', {
- defaultMessage: 'Progress wheel',
+ defaultMessage: 'Wheel',
}),
help: i18n.translate('xpack.canvas.elements.progressWheelHelpText', {
defaultMessage: 'Displays progress as a portion of a wheel',
@@ -189,15 +189,7 @@ export const getElementStrings = (): ElementStringDict => ({
defaultMessage: 'A scrollable grid for displaying data in a tabular format',
}),
},
- tiltedPie: {
- displayName: i18n.translate('xpack.canvas.elements.tiltedPieDisplayName', {
- defaultMessage: 'Tilted pie chart',
- }),
- help: i18n.translate('xpack.canvas.elements.tiltedPieHelpText', {
- defaultMessage: 'A customizable tilted pie chart',
- }),
- },
- time_filter: {
+ timeFilter: {
displayName: i18n.translate('xpack.canvas.elements.timeFilterDisplayName', {
defaultMessage: 'Time filter',
}),
@@ -207,7 +199,7 @@ export const getElementStrings = (): ElementStringDict => ({
},
verticalBarChart: {
displayName: i18n.translate('xpack.canvas.elements.verticalBarChartDisplayName', {
- defaultMessage: 'Vertical bar chart',
+ defaultMessage: 'Vertical bar',
}),
help: i18n.translate('xpack.canvas.elements.verticalBarChartHelpText', {
defaultMessage: 'A customizable vertical bar chart',
@@ -215,7 +207,7 @@ export const getElementStrings = (): ElementStringDict => ({
},
verticalProgressBar: {
displayName: i18n.translate('xpack.canvas.elements.verticalProgressBarDisplayName', {
- defaultMessage: 'Vertical progress bar',
+ defaultMessage: 'Vertical bar',
}),
help: i18n.translate('xpack.canvas.elements.verticalProgressBarHelpText', {
defaultMessage: 'Displays progress as a portion of a vertical bar',
@@ -223,7 +215,7 @@ export const getElementStrings = (): ElementStringDict => ({
},
verticalProgressPill: {
displayName: i18n.translate('xpack.canvas.elements.verticalProgressPillDisplayName', {
- defaultMessage: 'Vertical progress pill',
+ defaultMessage: 'Vertical pill',
}),
help: i18n.translate('xpack.canvas.elements.verticalProgressPillHelpText', {
defaultMessage: 'Displays progress as a portion of a vertical pill',
diff --git a/x-pack/legacy/plugins/canvas/i18n/functions/dict/alter_column.ts b/x-pack/legacy/plugins/canvas/i18n/functions/dict/alter_column.ts
index 836c7395ac448..cc601b0ea0e31 100644
--- a/x-pack/legacy/plugins/canvas/i18n/functions/dict/alter_column.ts
+++ b/x-pack/legacy/plugins/canvas/i18n/functions/dict/alter_column.ts
@@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n';
import { alterColumn } from '../../../canvas_plugin_src/functions/common/alterColumn';
import { FunctionHelp } from '../function_help';
import { FunctionFactory } from '../../../types';
-import { DATATABLE_COLUMN_TYPES } from '../../../common/lib';
+import { DATATABLE_COLUMN_TYPES } from '../../../common/lib/constants';
export const help: FunctionHelp> = {
help: i18n.translate('xpack.canvas.functions.alterColumnHelpText', {
diff --git a/x-pack/legacy/plugins/canvas/i18n/tags.ts b/x-pack/legacy/plugins/canvas/i18n/tags.ts
index 41007c58d738d..9595554260297 100644
--- a/x-pack/legacy/plugins/canvas/i18n/tags.ts
+++ b/x-pack/legacy/plugins/canvas/i18n/tags.ts
@@ -7,32 +7,12 @@
import { i18n } from '@kbn/i18n';
export const TagStrings: { [key: string]: () => string } = {
- chart: () =>
- i18n.translate('xpack.canvas.tags.chartTag', {
- defaultMessage: 'chart',
- }),
- filter: () =>
- i18n.translate('xpack.canvas.tags.filterTag', {
- defaultMessage: 'filter',
- }),
- graphic: () =>
- i18n.translate('xpack.canvas.tags.graphicTag', {
- defaultMessage: 'graphic',
- }),
presentation: () =>
i18n.translate('xpack.canvas.tags.presentationTag', {
defaultMessage: 'presentation',
}),
- proportion: () =>
- i18n.translate('xpack.canvas.tags.proportionTag', {
- defaultMessage: 'proportion',
- }),
report: () =>
i18n.translate('xpack.canvas.tags.reportTag', {
defaultMessage: 'report',
}),
- text: () =>
- i18n.translate('xpack.canvas.tags.textTag', {
- defaultMessage: 'text',
- }),
};
diff --git a/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_app.scss b/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_app.scss
index c5161439b71c3..c7dae8452a93c 100644
--- a/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_app.scss
+++ b/x-pack/legacy/plugins/canvas/public/apps/workpad/workpad_app/workpad_app.scss
@@ -31,7 +31,7 @@ $canvasLayoutFontSize: $euiFontSizeS;
.canvasLayout__stageHeader {
flex-grow: 0;
flex-basis: auto;
- padding: ($euiSizeXS + 1px) $euiSize $euiSizeXS;
+ padding: 1px $euiSize 0;
font-size: $canvasLayoutFontSize;
border-bottom: $euiBorderThin;
background: $euiColorLightestShade;
diff --git a/x-pack/legacy/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset_manager.stories.storyshot b/x-pack/legacy/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset_manager.stories.storyshot
new file mode 100644
index 0000000000000..6bcafc0777fc3
--- /dev/null
+++ b/x-pack/legacy/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset_manager.stories.storyshot
@@ -0,0 +1,761 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Storyshots components/Assets/AssetManager no assets 1`] = `
+Array [
+ ,
+ ,
+
+
+
+
+
+
+ Manage workpad assets
+
+
+
+
+
+
+
+
+
+ Select or drag and drop images
+
+
+
+
+
+
+
+
+
+
+
+
+ Below are the image assets in this workpad. Any assets that are currently in use cannot be determined at this time. To reclaim space, delete assets.
+
+
+
+
+
+
+
+
+
+
+ Import your assets to get started
+
+
+
+
+
+
+
+
+
+
+
,
+ ,
+]
+`;
+
+exports[`Storyshots components/Assets/AssetManager two assets 1`] = `
+Array [
+ ,
+ ,
+
+
+
+
+
+
+ Manage workpad assets
+
+
+
+
+
+
+
+
+
+ Select or drag and drop images
+
+
+
+
+
+
+
+
+
+
+
+
+ Below are the image assets in this workpad. Any assets that are currently in use cannot be determined at this time. To reclaim space, delete assets.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ airplane
+
+
+
+
+ (
+ 1
+ kb)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ marker
+
+
+
+
+ (
+ 1
+ kb)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
,
+ ,
+]
+`;
diff --git a/x-pack/legacy/plugins/canvas/public/components/asset_manager/__examples__/asset_manager.examples.tsx b/x-pack/legacy/plugins/canvas/public/components/asset_manager/__examples__/asset_manager.stories.tsx
similarity index 97%
rename from x-pack/legacy/plugins/canvas/public/components/asset_manager/__examples__/asset_manager.examples.tsx
rename to x-pack/legacy/plugins/canvas/public/components/asset_manager/__examples__/asset_manager.stories.tsx
index 045a3b4f64a44..cb42823ccab7b 100644
--- a/x-pack/legacy/plugins/canvas/public/components/asset_manager/__examples__/asset_manager.examples.tsx
+++ b/x-pack/legacy/plugins/canvas/public/components/asset_manager/__examples__/asset_manager.stories.tsx
@@ -28,12 +28,12 @@ const MARKER: AssetType = {
storiesOf('components/Assets/AssetManager', module)
.add('no assets', () => (
- // @ts-ignore @types/react has not been updated to support defaultProps yet.
))
.add('two assets', () => (
@@ -43,5 +43,6 @@ storiesOf('components/Assets/AssetManager', module)
onAssetAdd={action('onAssetAdd')}
onAssetCopy={action('onAssetCopy')}
onAssetDelete={action('onAssetDelete')}
+ onClose={action('onClose')}
/>
));
diff --git a/x-pack/legacy/plugins/canvas/public/components/asset_manager/asset_manager.tsx b/x-pack/legacy/plugins/canvas/public/components/asset_manager/asset_manager.tsx
index 3785f81cc25b9..479e9287d7adf 100644
--- a/x-pack/legacy/plugins/canvas/public/components/asset_manager/asset_manager.tsx
+++ b/x-pack/legacy/plugins/canvas/public/components/asset_manager/asset_manager.tsx
@@ -4,13 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import {
- EuiButtonEmpty,
- // @ts-ignore (elastic/eui#1557) EuiFilePicker is not exported yet
- EuiFilePicker,
- // @ts-ignore (elastic/eui#1557) EuiImage is not exported yet
- EuiImage,
-} from '@elastic/eui';
import PropTypes from 'prop-types';
import React, { Fragment, PureComponent } from 'react';
@@ -33,13 +26,13 @@ interface Props {
onAssetCopy: () => void;
/** Function to invoke when an asset is added */
onAssetAdd: (asset: File) => void;
+ /** Function to invoke when an asset modal is closed */
+ onClose: () => void;
}
interface State {
/** The id of the asset to delete, if applicable. Is set if the viewer clicks the delete icon */
deleteId: string | null;
- /** Determines if the modal is currently visible */
- isModalVisible: boolean;
/** Indicates if the modal is currently loading */
isLoading: boolean;
}
@@ -51,6 +44,7 @@ export class AssetManager extends PureComponent {
onAssetAdd: PropTypes.func.isRequired,
onAssetCopy: PropTypes.func.isRequired,
onAssetDelete: PropTypes.func.isRequired,
+ onClose: PropTypes.func.isRequired,
};
public static defaultProps = {
@@ -60,12 +54,11 @@ export class AssetManager extends PureComponent {
public state = {
deleteId: null,
isLoading: false,
- isModalVisible: false,
};
public render() {
- const { isModalVisible, isLoading } = this.state;
- const { assetValues, onAssetCopy, onAddImageElement } = this.props;
+ const { isLoading } = this.state;
+ const { assetValues, onAssetCopy, onAddImageElement, onClose } = this.props;
const assetModal = (
{
onAssetCopy={onAssetCopy}
onAssetCreate={(createdAsset: AssetType) => {
onAddImageElement(createdAsset.id);
- this.setState({ isModalVisible: false });
+ onClose();
}}
onAssetDelete={(asset: AssetType) => this.setState({ deleteId: asset.id })}
- onClose={() => this.setState({ isModalVisible: false })}
+ onClose={onClose}
onFileUpload={this.handleFileUpload}
/>
);
@@ -95,14 +88,12 @@ export class AssetManager extends PureComponent {
return (
- {strings.getButtonLabel()}
- {isModalVisible ? assetModal : null}
+ {assetModal}
{confirmModal}
);
}
- private showModal = () => this.setState({ isModalVisible: true });
private resetDelete = () => this.setState({ deleteId: null });
private doDelete = () => {
diff --git a/x-pack/legacy/plugins/canvas/public/components/asset_manager/asset_modal.tsx b/x-pack/legacy/plugins/canvas/public/components/asset_manager/asset_modal.tsx
index 5e2a09769c309..ec935b8112f99 100644
--- a/x-pack/legacy/plugins/canvas/public/components/asset_manager/asset_modal.tsx
+++ b/x-pack/legacy/plugins/canvas/public/components/asset_manager/asset_modal.tsx
@@ -97,6 +97,7 @@ export const AssetModal: FunctionComponent = props => {
-
-
-
-
-

-
-
-
-
-
-
-
- sample description
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
- Aenean eu justo auctor, placerat felis non, scelerisque dolor.
-
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce lobortis aliquet arcu ut turpis duis.
-
-
-
-
-
-
-
-
-
-`;
-
-exports[`Storyshots components/Elements/ElementGrid with controls and filter 1`] = `
-
-
-
-
-
-

-
-
-
-
-
-
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce lobortis aliquet arcu ut turpis duis.
-
-
-
-
-
-
-
-
-
-`;
-
-exports[`Storyshots components/Elements/ElementGrid with tags filter 1`] = `
-
-
-
-
-
-

-
-
-
-
-
-
- graphic
-
-
-
-
-
-
-
-
-`;
-
-exports[`Storyshots components/Elements/ElementGrid with text filter 1`] = `
-
-
-
-
-
-

-
-
-
-
-
-
-
- A scrollable grid for displaying data in a tabular format
-
-
-
-
-
-
-
- text
-
-
-
-
-
-
-
-
-`;
-
-exports[`Storyshots components/Elements/ElementGrid without controls 1`] = `
-
-
-
-
-
-

-
-
-
-
-
-
-
- A line chart with a filled body
-
-
-
-
-
-
-
- chart
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
- graphic
-
-
-
-
-
-
-
-
-
-

-
-
-
-
-
-
-
- A scrollable grid for displaying data in a tabular format
-
-
-
-
-
-
-
- text
-
-
-
-
-
-
-
-
-`;
diff --git a/x-pack/legacy/plugins/canvas/public/components/element_types/element_grid.tsx b/x-pack/legacy/plugins/canvas/public/components/element_types/element_grid.tsx
deleted file mode 100644
index 852b987fcfd24..0000000000000
--- a/x-pack/legacy/plugins/canvas/public/components/element_types/element_grid.tsx
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-import React from 'react';
-import PropTypes from 'prop-types';
-import { map } from 'lodash';
-import { EuiFlexItem, EuiFlexGrid } from '@elastic/eui';
-import { ElementControls } from './element_controls';
-import { CustomElement, ElementSpec } from '../../../types';
-import { ElementCard } from '../element_card';
-
-export interface Props {
- /**
- * list of elements to generate cards for
- */
- elements: Array;
- /**
- * text to filter out cards
- */
- filterText: string;
- /**
- * tags to filter out cards
- */
- filterTags: string[];
- /**
- * indicate whether or not edit/delete controls should be displayed
- */
- showControls: boolean;
- /**
- * handler invoked when clicking a card
- */
- handleClick: (element: ElementSpec | CustomElement) => void;
- /**
- * click handler for the edit button
- */
- onEdit?: (element: ElementSpec | CustomElement) => void;
- /**
- * click handler for the delete button
- */
- onDelete?: (element: ElementSpec | CustomElement) => void;
-}
-
-export const ElementGrid = ({
- elements,
- filterText,
- filterTags,
- handleClick,
- onEdit,
- onDelete,
- showControls,
-}: Props) => {
- filterText = filterText.toLowerCase();
-
- return (
-
- {map(elements, (element: ElementSpec | CustomElement, index) => {
- const { name, displayName = '', help = '', image, tags = [] } = element;
- const whenClicked = () => handleClick(element);
- let textMatch = false;
- let tagsMatch = false;
-
- if (
- !filterText.length ||
- name.toLowerCase().includes(filterText) ||
- displayName.toLowerCase().includes(filterText) ||
- help.toLowerCase().includes(filterText)
- ) {
- textMatch = true;
- }
-
- if (!filterTags.length || filterTags.every(tag => tags.includes(tag))) {
- tagsMatch = true;
- }
-
- if (!textMatch || !tagsMatch) {
- return null;
- }
-
- return (
-
-
- {showControls && onEdit && onDelete && (
- onEdit(element)} onDelete={() => onDelete(element)} />
- )}
-
- );
- })}
-
- );
-};
-
-ElementGrid.propTypes = {
- elements: PropTypes.array.isRequired,
- handleClick: PropTypes.func.isRequired,
- showControls: PropTypes.bool,
-};
-
-ElementGrid.defaultProps = {
- showControls: false,
- filterTags: [],
- filterText: '',
-};
diff --git a/x-pack/legacy/plugins/canvas/public/components/element_types/element_types.js b/x-pack/legacy/plugins/canvas/public/components/element_types/element_types.js
deleted file mode 100644
index dabf06a24aeb6..0000000000000
--- a/x-pack/legacy/plugins/canvas/public/components/element_types/element_types.js
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import React, { Component, Fragment } from 'react';
-import PropTypes from 'prop-types';
-import {
- EuiModalBody,
- EuiTabbedContent,
- EuiEmptyPrompt,
- EuiSearchBar,
- EuiSpacer,
- EuiOverlayMask,
-} from '@elastic/eui';
-import { map, sortBy } from 'lodash';
-import { ConfirmModal } from '../confirm_modal/confirm_modal';
-import { CustomElementModal } from '../custom_element_modal';
-import { getTagsFilter } from '../../lib/get_tags_filter';
-import { extractSearch } from '../../lib/extract_search';
-import { ComponentStrings } from '../../../i18n';
-import { ElementGrid } from './element_grid';
-
-const { ElementTypes: strings } = ComponentStrings;
-
-const tagType = 'badge';
-export class ElementTypes extends Component {
- static propTypes = {
- addCustomElement: PropTypes.func.isRequired,
- addElement: PropTypes.func.isRequired,
- customElements: PropTypes.array.isRequired,
- elements: PropTypes.object,
- filterTags: PropTypes.arrayOf(PropTypes.string).isRequired,
- findCustomElements: PropTypes.func.isRequired,
- onClose: PropTypes.func.isRequired,
- removeCustomElement: PropTypes.func.isRequired,
- search: PropTypes.string,
- setCustomElements: PropTypes.func.isRequired,
- setSearch: PropTypes.func.isRequired,
- setFilterTags: PropTypes.func.isRequired,
- updateCustomElement: PropTypes.func.isRequired,
- };
-
- state = {
- elementToDelete: null,
- elementToEdit: null,
- };
-
- componentDidMount() {
- // fetch custom elements
- this.props.findCustomElements();
- }
-
- _showEditModal = elementToEdit => this.setState({ elementToEdit });
-
- _hideEditModal = () => this.setState({ elementToEdit: null });
-
- _handleEdit = async (name, description, image) => {
- const { updateCustomElement } = this.props;
- const { elementToEdit } = this.state;
- await updateCustomElement(elementToEdit.id, name, description, image);
- this._hideEditModal();
- };
-
- _showDeleteModal = elementToDelete => this.setState({ elementToDelete });
-
- _hideDeleteModal = () => this.setState({ elementToDelete: null });
-
- _handleDelete = async () => {
- const { removeCustomElement } = this.props;
- const { elementToDelete } = this.state;
- await removeCustomElement(elementToDelete.id);
- this._hideDeleteModal();
- };
-
- _renderEditModal = () => {
- const { elementToEdit } = this.state;
-
- if (!elementToEdit) {
- return null;
- }
-
- return (
-
-
-
- );
- };
-
- _renderDeleteModal = () => {
- const { elementToDelete } = this.state;
-
- if (!elementToDelete) {
- return null;
- }
-
- return (
-
- );
- };
-
- _sortElements = elements =>
- sortBy(
- map(elements, (element, name) => ({ name, ...element })),
- 'displayName'
- );
-
- render() {
- const {
- search,
- setSearch,
- addElement,
- addCustomElement,
- filterTags,
- setFilterTags,
- } = this.props;
- let { elements, customElements } = this.props;
- elements = this._sortElements(elements);
-
- let customElementContent = (
- {strings.getAddNewElementTitle()}}
- body={{strings.getAddNewElementDescription()}
}
- titleSize="s"
- />
- );
-
- if (customElements.length) {
- customElements = this._sortElements(customElements);
- customElementContent = (
-
- );
- }
-
- const filters = [getTagsFilter(tagType)];
- const onSearch = ({ queryText }) => {
- const { searchTerm, filterTags } = extractSearch(queryText);
- setSearch(searchTerm);
- setFilterTags(filterTags);
- };
-
- const tabs = [
- {
- id: 'elements',
- name: strings.getElementsTitle(),
- content: (
-
-
-
-
-
-
- ),
- },
- {
- id: 'customElements',
- name: strings.getMyElementsTitle(),
- content: (
-
-
-
-
- {customElementContent}
-
- ),
- },
- ];
-
- return (
-
-
-
-
-
- {this._renderDeleteModal()}
- {this._renderEditModal()}
-
- );
- }
-}
diff --git a/x-pack/legacy/plugins/canvas/public/components/element_types/index.js b/x-pack/legacy/plugins/canvas/public/components/element_types/index.js
deleted file mode 100644
index 8faaf278a07de..0000000000000
--- a/x-pack/legacy/plugins/canvas/public/components/element_types/index.js
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import PropTypes from 'prop-types';
-import { compose, withProps, withState } from 'recompose';
-import { connect } from 'react-redux';
-import { camelCase } from 'lodash';
-import { cloneSubgraphs } from '../../lib/clone_subgraphs';
-import * as customElementService from '../../lib/custom_element_service';
-import { elementsRegistry } from '../../lib/elements_registry';
-import { notify } from '../../lib/notify';
-import { selectToplevelNodes } from '../../state/actions/transient';
-import { insertNodes, addElement } from '../../state/actions/elements';
-import { getSelectedPage } from '../../state/selectors/workpad';
-import { trackCanvasUiMetric, METRIC_TYPE } from '../../lib/ui_metric';
-import { ElementTypes as Component } from './element_types';
-
-const customElementAdded = 'elements-custom-added';
-
-const mapStateToProps = state => ({ pageId: getSelectedPage(state) });
-
-const mapDispatchToProps = dispatch => ({
- selectToplevelNodes: nodes =>
- dispatch(selectToplevelNodes(nodes.filter(e => !e.position.parent).map(e => e.id))),
- insertNodes: (selectedNodes, pageId) => dispatch(insertNodes(selectedNodes, pageId)),
- addElement: (pageId, partialElement) => dispatch(addElement(pageId, partialElement)),
-});
-
-const mergeProps = (stateProps, dispatchProps, ownProps) => {
- const { pageId, ...remainingStateProps } = stateProps;
- const { addElement, insertNodes, selectToplevelNodes } = dispatchProps;
- const { search, setCustomElements, onClose } = ownProps;
-
- return {
- ...remainingStateProps,
- ...ownProps,
- // add built-in element to the page
- addElement: element => {
- addElement(pageId, element);
- onClose();
- },
- // add custom element to the page
- addCustomElement: customElement => {
- const { selectedNodes = [] } = JSON.parse(customElement.content) || {};
- const clonedNodes = selectedNodes && cloneSubgraphs(selectedNodes);
- if (clonedNodes) {
- insertNodes(clonedNodes, pageId); // first clone and persist the new node(s)
- selectToplevelNodes(clonedNodes); // then select the cloned node(s)
- }
- onClose();
- trackCanvasUiMetric(METRIC_TYPE.LOADED, customElementAdded);
- },
- // custom element search
- findCustomElements: async text => {
- try {
- const { customElements } = await customElementService.find(text);
- setCustomElements(customElements);
- } catch (err) {
- notify.error(err, { title: `Couldn't find custom elements` });
- }
- },
- // remove custom element
- removeCustomElement: async id => {
- try {
- await customElementService.remove(id).then();
- const { customElements } = await customElementService.find(search);
- setCustomElements(customElements);
- } catch (err) {
- notify.error(err, { title: `Couldn't delete custom elements` });
- }
- },
- // update custom element
- updateCustomElement: async (id, name, description, image) => {
- try {
- await customElementService.update(id, {
- name: camelCase(name),
- displayName: name,
- image,
- help: description,
- });
- const { customElements } = await customElementService.find(search);
- setCustomElements(customElements);
- } catch (err) {
- notify.error(err, { title: `Couldn't update custom elements` });
- }
- },
- };
-};
-
-export const ElementTypes = compose(
- withState('search', 'setSearch', ''),
- withState('customElements', 'setCustomElements', []),
- withState('filterTags', 'setFilterTags', []),
- withProps(() => ({ elements: elementsRegistry.toJS() })),
- connect(mapStateToProps, mapDispatchToProps, mergeProps)
-)(Component);
-
-ElementTypes.propTypes = {
- onClose: PropTypes.func,
-};
diff --git a/x-pack/legacy/plugins/canvas/public/components/popover/index.ts b/x-pack/legacy/plugins/canvas/public/components/popover/index.ts
index f560da14079b5..63626f08fa43b 100644
--- a/x-pack/legacy/plugins/canvas/public/components/popover/index.ts
+++ b/x-pack/legacy/plugins/canvas/public/components/popover/index.ts
@@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export { Popover } from './popover';
+export { Popover, ClosePopoverFn } from './popover';
diff --git a/x-pack/legacy/plugins/canvas/public/components/popover/popover.tsx b/x-pack/legacy/plugins/canvas/public/components/popover/popover.tsx
index 25b2e6587c869..9f3d86576e6a7 100644
--- a/x-pack/legacy/plugins/canvas/public/components/popover/popover.tsx
+++ b/x-pack/legacy/plugins/canvas/public/components/popover/popover.tsx
@@ -24,6 +24,8 @@ interface Props {
className?: string;
}
+export type ClosePopoverFn = () => void;
+
interface State {
isPopoverOpen: boolean;
}
@@ -61,7 +63,7 @@ export class Popover extends Component {
}));
};
- closePopover = () => {
+ closePopover: ClosePopoverFn = () => {
this.setState({
isPopoverOpen: false,
});
diff --git a/x-pack/legacy/plugins/canvas/public/components/element_types/__examples__/__snapshots__/element_controls.stories.storyshot b/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/element_controls.stories.storyshot
similarity index 88%
rename from x-pack/legacy/plugins/canvas/public/components/element_types/__examples__/__snapshots__/element_controls.stories.storyshot
rename to x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/element_controls.stories.storyshot
index 5ce6fe8c85589..6f12f68356467 100644
--- a/x-pack/legacy/plugins/canvas/public/components/element_types/__examples__/__snapshots__/element_controls.stories.storyshot
+++ b/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/element_controls.stories.storyshot
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Storyshots components/Elements/ElementControls has two buttons 1`] = `
+exports[`Storyshots components/SavedElementsModal/ElementControls has two buttons 1`] = `
+
+
+
+
+

+
+
+
+
+
+
+
+ sample description
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+ Aenean eu justo auctor, placerat felis non, scelerisque dolor.
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce lobortis aliquet arcu ut turpis duis.
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`Storyshots components/SavedElementsModal/ElementGrid with text filter 1`] = `
+
+`;
diff --git a/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/saved_elements_modal.stories.storyshot b/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/saved_elements_modal.stories.storyshot
new file mode 100644
index 0000000000000..c73309ad8b14c
--- /dev/null
+++ b/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/__snapshots__/saved_elements_modal.stories.storyshot
@@ -0,0 +1,933 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Storyshots components/SavedElementsModal no custom elements 1`] = `
+Array [
+ ,
+ ,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Add new elements
+
+
+
+
+ Group and save workpad elements to create new elements
+
+
+
+
+
+
+
+
+
+
+
+
,
+ ,
+]
+`;
+
+exports[`Storyshots components/SavedElementsModal with custom elements 1`] = `
+Array [
+ ,
+ ,
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+ sample description
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+ Aenean eu justo auctor, placerat felis non, scelerisque dolor.
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce lobortis aliquet arcu ut turpis duis.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
,
+ ,
+]
+`;
+
+exports[`Storyshots components/SavedElementsModal with text filter 1`] = `
+Array [
+ ,
+ ,
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+ Aenean eu justo auctor, placerat felis non, scelerisque dolor.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
,
+ ,
+]
+`;
diff --git a/x-pack/legacy/plugins/canvas/public/components/element_types/__examples__/element_controls.stories.tsx b/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/element_controls.stories.tsx
similarity index 90%
rename from x-pack/legacy/plugins/canvas/public/components/element_types/__examples__/element_controls.stories.tsx
rename to x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/element_controls.stories.tsx
index 52736ac952e53..5210210ebaa74 100644
--- a/x-pack/legacy/plugins/canvas/public/components/element_types/__examples__/element_controls.stories.tsx
+++ b/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/element_controls.stories.tsx
@@ -9,7 +9,7 @@ import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { ElementControls } from '../element_controls';
-storiesOf('components/Elements/ElementControls', module)
+storiesOf('components/SavedElementsModal/ElementControls', module)
.addDecorator(story => (
(
))
- .add('without controls', () => (
-
- ))
- .add('with controls', () => (
+ .add('default', () => (
))
.add('with text filter', () => (
-
- ))
- .add('with tags filter', () => (
-
- ))
- .add('with controls and filter', () => (
diff --git a/x-pack/legacy/plugins/canvas/public/components/element_types/__examples__/fixtures/test_elements.tsx b/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/fixtures/test_elements.tsx
similarity index 93%
rename from x-pack/legacy/plugins/canvas/public/components/element_types/__examples__/fixtures/test_elements.tsx
rename to x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/fixtures/test_elements.tsx
index eec7a86d52f25..d1ff565b4955a 100644
--- a/x-pack/legacy/plugins/canvas/public/components/element_types/__examples__/fixtures/test_elements.tsx
+++ b/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/fixtures/test_elements.tsx
@@ -6,41 +6,6 @@
import { elasticLogo } from '../../../../lib/elastic_logo';
-export const testElements = [
- {
- name: 'areaChart',
- displayName: 'Area chart',
- help: 'A line chart with a filled body',
- tags: ['chart'],
- image: elasticLogo,
- expression: `filters
- | demodata
- | pointseries x="time" y="mean(price)"
- | plot defaultStyle={seriesStyle lines=1 fill=1}
- | render`,
- },
- {
- name: 'image',
- displayName: 'Image',
- help: 'A static image',
- tags: ['graphic'],
- image: elasticLogo,
- expression: `image dataurl=null mode="contain"
- | render`,
- },
- {
- name: 'table',
- displayName: 'Data table',
- tags: ['text'],
- help: 'A scrollable grid for displaying data in a tabular format',
- image: elasticLogo,
- expression: `filters
- | demodata
- | table
- | render`,
- },
-];
-
export const testCustomElements = [
{
id: 'custom-element-10d625f5-1342-47c9-8f19-d174ea6b65d5',
diff --git a/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/saved_elements_modal.stories.tsx b/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/saved_elements_modal.stories.tsx
new file mode 100644
index 0000000000000..4941d8cb2efa7
--- /dev/null
+++ b/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/__examples__/saved_elements_modal.stories.tsx
@@ -0,0 +1,50 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React from 'react';
+import { storiesOf } from '@storybook/react';
+import { action } from '@storybook/addon-actions';
+import { SavedElementsModal } from '../saved_elements_modal';
+import { testCustomElements } from './fixtures/test_elements';
+import { CustomElement } from '../../../../types';
+
+storiesOf('components/SavedElementsModal', module)
+ .add('no custom elements', () => (
+
+ ))
+ .add('with custom elements', () => (
+
+ ))
+ .add('with text filter', () => (
+
+ ));
diff --git a/x-pack/legacy/plugins/canvas/public/components/element_types/element_controls.tsx b/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/element_controls.tsx
similarity index 85%
rename from x-pack/legacy/plugins/canvas/public/components/element_types/element_controls.tsx
rename to x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/element_controls.tsx
index a23274296f64f..998b15c15f487 100644
--- a/x-pack/legacy/plugins/canvas/public/components/element_types/element_controls.tsx
+++ b/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/element_controls.tsx
@@ -30,7 +30,12 @@ export const ElementControls: FunctionComponent
= ({ onDelete, onEdit })
>
-
+
@@ -40,6 +45,7 @@ export const ElementControls: FunctionComponent = ({ onDelete, onEdit })
iconType="trash"
aria-label={strings.getDeleteAriaLabel()}
onClick={onDelete}
+ data-test-subj="canvasElementCard__deleteButton"
/>
diff --git a/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/element_grid.tsx b/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/element_grid.tsx
new file mode 100644
index 0000000000000..f86e2c0147035
--- /dev/null
+++ b/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/element_grid.tsx
@@ -0,0 +1,81 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import React from 'react';
+import PropTypes from 'prop-types';
+import { map } from 'lodash';
+import { EuiFlexItem, EuiFlexGrid } from '@elastic/eui';
+import { ElementControls } from './element_controls';
+import { CustomElement } from '../../../types';
+import { ElementCard } from '../element_card';
+
+export interface Props {
+ /**
+ * list of elements to generate cards for
+ */
+ elements: CustomElement[];
+ /**
+ * text to filter out cards
+ */
+ filterText: string;
+ /**
+ * handler invoked when clicking a card
+ */
+ onClick: (element: CustomElement) => void;
+ /**
+ * click handler for the edit button
+ */
+ onEdit: (element: CustomElement) => void;
+ /**
+ * click handler for the delete button
+ */
+ onDelete: (element: CustomElement) => void;
+}
+
+export const ElementGrid = ({ elements, filterText, onClick, onEdit, onDelete }: Props) => {
+ filterText = filterText.toLowerCase();
+
+ return (
+
+ {map(elements, (element: CustomElement, index) => {
+ const { name, displayName = '', help = '', image } = element;
+ const whenClicked = () => onClick(element);
+
+ if (
+ filterText.length &&
+ !name.toLowerCase().includes(filterText) &&
+ !displayName.toLowerCase().includes(filterText) &&
+ !help.toLowerCase().includes(filterText)
+ ) {
+ return null;
+ }
+
+ return (
+
+
+ onEdit(element)} onDelete={() => onDelete(element)} />
+
+ );
+ })}
+
+ );
+};
+
+ElementGrid.propTypes = {
+ elements: PropTypes.array.isRequired,
+ filterText: PropTypes.string.isRequired,
+ onClick: PropTypes.func.isRequired,
+ onEdit: PropTypes.func.isRequired,
+ onDelete: PropTypes.func.isRequired,
+};
+
+ElementGrid.defaultProps = {
+ filterText: '',
+};
diff --git a/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/index.ts b/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/index.ts
new file mode 100644
index 0000000000000..bb088ad4e0de1
--- /dev/null
+++ b/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/index.ts
@@ -0,0 +1,128 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { connect } from 'react-redux';
+import { Dispatch } from 'redux';
+import { compose, withState } from 'recompose';
+import { camelCase } from 'lodash';
+// @ts-ignore Untyped local
+import { cloneSubgraphs } from '../../lib/clone_subgraphs';
+import * as customElementService from '../../lib/custom_element_service';
+// @ts-ignore Untyped local
+import { notify } from '../../lib/notify';
+// @ts-ignore Untyped local
+import { selectToplevelNodes } from '../../state/actions/transient';
+// @ts-ignore Untyped local
+import { insertNodes } from '../../state/actions/elements';
+import { getSelectedPage } from '../../state/selectors/workpad';
+import { trackCanvasUiMetric, METRIC_TYPE } from '../../lib/ui_metric';
+import { SavedElementsModal as Component, Props as ComponentProps } from './saved_elements_modal';
+import { State, PositionedElement, CustomElement } from '../../../types';
+
+const customElementAdded = 'elements-custom-added';
+
+interface OwnProps {
+ onClose: () => void;
+}
+
+interface OwnPropsWithState extends OwnProps {
+ customElements: CustomElement[];
+ setCustomElements: (customElements: CustomElement[]) => void;
+ search: string;
+ setSearch: (search: string) => void;
+}
+
+interface DispatchProps {
+ selectToplevelNodes: (nodes: PositionedElement[]) => void;
+ insertNodes: (selectedNodes: PositionedElement[], pageId: string) => void;
+}
+
+interface StateProps {
+ pageId: string;
+}
+
+const mapStateToProps = (state: State): StateProps => ({
+ pageId: getSelectedPage(state),
+});
+
+const mapDispatchToProps = (dispatch: Dispatch): DispatchProps => ({
+ selectToplevelNodes: (nodes: PositionedElement[]) =>
+ dispatch(
+ selectToplevelNodes(
+ nodes
+ .filter((e: PositionedElement): boolean => !e.position.parent)
+ .map((e: PositionedElement): string => e.id)
+ )
+ ),
+ insertNodes: (selectedNodes: PositionedElement[], pageId: string) =>
+ dispatch(insertNodes(selectedNodes, pageId)),
+});
+
+const mergeProps = (
+ stateProps: StateProps,
+ dispatchProps: DispatchProps,
+ ownProps: OwnPropsWithState
+): ComponentProps => {
+ const { pageId } = stateProps;
+ const { onClose, search, setCustomElements } = ownProps;
+
+ const findCustomElements = async () => {
+ const { customElements } = await customElementService.find(search);
+ setCustomElements(customElements);
+ };
+
+ return {
+ ...ownProps,
+ // add custom element to the page
+ addCustomElement: (customElement: CustomElement) => {
+ const { selectedNodes = [] } = JSON.parse(customElement.content) || {};
+ const clonedNodes = selectedNodes && cloneSubgraphs(selectedNodes);
+ if (clonedNodes) {
+ dispatchProps.insertNodes(clonedNodes, pageId); // first clone and persist the new node(s)
+ dispatchProps.selectToplevelNodes(clonedNodes); // then select the cloned node(s)
+ }
+ onClose();
+ trackCanvasUiMetric(METRIC_TYPE.LOADED, customElementAdded);
+ },
+ // custom element search
+ findCustomElements: async (text?: string) => {
+ try {
+ await findCustomElements();
+ } catch (err) {
+ notify.error(err, { title: `Couldn't find custom elements` });
+ }
+ },
+ // remove custom element
+ removeCustomElement: async (id: string) => {
+ try {
+ await customElementService.remove(id);
+ await findCustomElements();
+ } catch (err) {
+ notify.error(err, { title: `Couldn't delete custom elements` });
+ }
+ },
+ // update custom element
+ updateCustomElement: async (id: string, name: string, description: string, image: string) => {
+ try {
+ await customElementService.update(id, {
+ name: camelCase(name),
+ displayName: name,
+ image,
+ help: description,
+ });
+ await findCustomElements();
+ } catch (err) {
+ notify.error(err, { title: `Couldn't update custom elements` });
+ }
+ },
+ };
+};
+
+export const SavedElementsModal = compose(
+ withState('search', 'setSearch', ''),
+ withState('customElements', 'setCustomElements', []),
+ connect(mapStateToProps, mapDispatchToProps, mergeProps)
+)(Component);
diff --git a/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/saved_elements_modal.tsx b/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/saved_elements_modal.tsx
new file mode 100644
index 0000000000000..dba97a15fee5c
--- /dev/null
+++ b/x-pack/legacy/plugins/canvas/public/components/saved_elements_modal/saved_elements_modal.tsx
@@ -0,0 +1,217 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import React, { Fragment, ChangeEvent, FunctionComponent, useState, useEffect } from 'react';
+import PropTypes from 'prop-types';
+import {
+ EuiModal,
+ EuiModalBody,
+ EuiModalFooter,
+ EuiModalHeader,
+ EuiModalHeaderTitle,
+ EuiEmptyPrompt,
+ EuiFieldSearch,
+ EuiSpacer,
+ EuiOverlayMask,
+ EuiButton,
+} from '@elastic/eui';
+import { map, sortBy } from 'lodash';
+import { ComponentStrings } from '../../../i18n';
+import { CustomElement } from '../../../types';
+import { ConfirmModal } from '../confirm_modal/confirm_modal';
+import { CustomElementModal } from '../custom_element_modal';
+import { ElementGrid } from './element_grid';
+
+const { SavedElementsModal: strings } = ComponentStrings;
+
+export interface Props {
+ /**
+ * Adds the custom element to the workpad
+ */
+ addCustomElement: (customElement: CustomElement) => void;
+ /**
+ * Queries ES for custom element saved objects
+ */
+ findCustomElements: () => void;
+ /**
+ * Handler invoked when the modal closes
+ */
+ onClose: () => void;
+ /**
+ * Deletes the custom element
+ */
+ removeCustomElement: (id: string) => void;
+ /**
+ * Saved edits to the custom element
+ */
+ updateCustomElement: (id: string, name: string, description: string, image: string) => void;
+ /**
+ * Array of custom elements to display
+ */
+ customElements: CustomElement[];
+ /**
+ * Text used to filter custom elements list
+ */
+ search: string;
+ /**
+ * Setter for search text
+ */
+ setSearch: (search: string) => void;
+}
+
+export const SavedElementsModal: FunctionComponent = ({
+ search,
+ setSearch,
+ customElements,
+ addCustomElement,
+ findCustomElements,
+ onClose,
+ removeCustomElement,
+ updateCustomElement,
+}) => {
+ const [elementToDelete, setElementToDelete] = useState(null);
+ const [elementToEdit, setElementToEdit] = useState(null);
+
+ useEffect(() => {
+ findCustomElements();
+ });
+
+ const showEditModal = (element: CustomElement) => setElementToEdit(element);
+ const hideEditModal = () => setElementToEdit(null);
+
+ const handleEdit = async (name: string, description: string, image: string) => {
+ if (elementToEdit) {
+ await updateCustomElement(elementToEdit.id, name, description, image);
+ }
+ hideEditModal();
+ };
+
+ const showDeleteModal = (element: CustomElement) => setElementToDelete(element);
+ const hideDeleteModal = () => setElementToDelete(null);
+
+ const handleDelete = async () => {
+ if (elementToDelete) {
+ await removeCustomElement(elementToDelete.id);
+ }
+ hideDeleteModal();
+ };
+
+ const renderEditModal = () => {
+ if (!elementToEdit) {
+ return null;
+ }
+
+ return (
+
+
+
+ );
+ };
+
+ const renderDeleteModal = () => {
+ if (!elementToDelete) {
+ return null;
+ }
+
+ return (
+
+ );
+ };
+
+ const sortElements = (elements: CustomElement[]): CustomElement[] =>
+ sortBy(
+ map(elements, (element, name) => ({ name, ...element })),
+ 'displayName'
+ );
+
+ const onSearch = (e: ChangeEvent) => setSearch(e.target.value);
+
+ let customElementContent = (
+ {strings.getAddNewElementTitle()}}
+ body={{strings.getAddNewElementDescription()}
}
+ titleSize="s"
+ />
+ );
+
+ if (customElements.length) {
+ customElementContent = (
+
+ );
+ }
+
+ return (
+
+
+
+
+
+ {strings.getModalTitle()}
+
+
+
+
+
+
+ {customElementContent}
+
+
+
+ {strings.getSavedElementsModalCloseButtonLabel()}
+
+
+
+
+
+ {renderDeleteModal()}
+ {renderEditModal()}
+
+ );
+};
+
+SavedElementsModal.propTypes = {
+ addCustomElement: PropTypes.func.isRequired,
+ findCustomElements: PropTypes.func.isRequired,
+ onClose: PropTypes.func.isRequired,
+ removeCustomElement: PropTypes.func.isRequired,
+ updateCustomElement: PropTypes.func.isRequired,
+};
diff --git a/x-pack/legacy/plugins/canvas/public/components/sidebar_header/__examples__/__snapshots__/sidebar_header.stories.storyshot b/x-pack/legacy/plugins/canvas/public/components/sidebar_header/__examples__/__snapshots__/sidebar_header.stories.storyshot
index d46a509251d35..ac25cbe0b6832 100644
--- a/x-pack/legacy/plugins/canvas/public/components/sidebar_header/__examples__/__snapshots__/sidebar_header.stories.storyshot
+++ b/x-pack/legacy/plugins/canvas/public/components/sidebar_header/__examples__/__snapshots__/sidebar_header.stories.storyshot
@@ -37,6 +37,7 @@ exports[`Storyshots components/Sidebar/SidebarHeader default 1`] = `