diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 9a4f2b71da1ffb..acfb7307f49c47 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -132,6 +132,9 @@
/x-pack/test/alerting_api_integration @elastic/kibana-alerting-services
/x-pack/test/plugin_api_integration/plugins/task_manager @elastic/kibana-alerting-services
/x-pack/test/plugin_api_integration/test_suites/task_manager @elastic/kibana-alerting-services
+/x-pack/legacy/plugins/triggers_actions_ui/ @elastic/kibana-alerting-services
+/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/ @elastic/kibana-alerting-services
+/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/ @elastic/kibana-alerting-services
# Design
**/*.scss @elastic/kibana-design
diff --git a/docs/development/core/server/kibana-plugin-server.uisettingsparams.deprecation.md b/docs/development/core/server/kibana-plugin-server.uisettingsparams.deprecation.md
new file mode 100644
index 00000000000000..7ad26b85bf81c8
--- /dev/null
+++ b/docs/development/core/server/kibana-plugin-server.uisettingsparams.deprecation.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-server](./kibana-plugin-server.md) > [UiSettingsParams](./kibana-plugin-server.uisettingsparams.md) > [deprecation](./kibana-plugin-server.uisettingsparams.deprecation.md)
+
+## UiSettingsParams.deprecation property
+
+optional deprecation information. Used to generate a deprecation warning.
+
+Signature:
+
+```typescript
+deprecation?: DeprecationSettings;
+```
diff --git a/docs/development/core/server/kibana-plugin-server.uisettingsparams.md b/docs/development/core/server/kibana-plugin-server.uisettingsparams.md
index 89eb5b10b9de52..fc2f8038f973fa 100644
--- a/docs/development/core/server/kibana-plugin-server.uisettingsparams.md
+++ b/docs/development/core/server/kibana-plugin-server.uisettingsparams.md
@@ -17,6 +17,7 @@ export interface UiSettingsParams
| Property | Type | Description |
| --- | --- | --- |
| [category](./kibana-plugin-server.uisettingsparams.category.md) | string[]
| used to group the configured setting in the UI |
+| [deprecation](./kibana-plugin-server.uisettingsparams.deprecation.md) | DeprecationSettings
| optional deprecation information. Used to generate a deprecation warning. |
| [description](./kibana-plugin-server.uisettingsparams.description.md) | string
| description provided to a user in UI |
| [name](./kibana-plugin-server.uisettingsparams.name.md) | string
| title in the UI |
| [optionLabels](./kibana-plugin-server.uisettingsparams.optionlabels.md) | Record<string, string>
| text labels for 'select' type UI element |
diff --git a/docs/user/security/reporting.asciidoc b/docs/user/security/reporting.asciidoc
index c2ed295e83ce95..5f5d85fe8d3beb 100644
--- a/docs/user/security/reporting.asciidoc
+++ b/docs/user/security/reporting.asciidoc
@@ -125,23 +125,33 @@ the {reporting} endpoints to authorized users. This requires that you:
. Enable {security} on your {es} cluster. For more information,
see {ref}/security-getting-started.html[Getting Started with Security].
-. Configure an SSL certificate for Kibana. For more information, see
-<>.
-. Configure {watcher} to trust the Kibana server's certificate by adding it to
-the {watcher} truststore on each node:
-.. Import the {kib} server certificate into the {watcher} truststore using
-Java Keytool:
+. Configure TLS/SSL encryption for the {kib} server. For more information, see
+<>.
+. Specify the {kib} server's CA certificate chain in `elasticsearch.yml`:
+
-[source,shell]
----------------------------------------------------------
-keytool -importcert -keystore watcher-truststore.jks -file server.crt
----------------------------------------------------------
-+
-NOTE: If the truststore doesn't already exist, it is created.
+--
+If you are using your own CA to sign the {kib} server certificate, then you need
+to specify the CA certificate chain in {es} to properly establish trust in TLS
+connections between {watcher} and {kib}. If your CA certificate chain is
+contained in a PKCS #12 trust store, specify it like so:
+
+[source,yaml]
+--------------------------------------------------------------------------------
+xpack.http.ssl.truststore.path: "/path/to/your/truststore.p12"
+xpack.http.ssl.truststore.type: "PKCS12"
+xpack.http.ssl.truststore.password: "optional decryption password"
+--------------------------------------------------------------------------------
+
+Otherwise, if your CA certificate chain is in PEM format, specify it like so:
+
+[source,yaml]
+--------------------------------------------------------------------------------
+xpack.http.ssl.certificate_authorities: ["/path/to/your/cacert1.pem", "/path/to/your/cacert2.pem"]
+--------------------------------------------------------------------------------
+
+For more information, see {ref}/notification-settings.html#ssl-notification-settings[the {watcher} HTTP TLS/SSL Settings].
+--
-.. Make sure the `xpack.http.ssl.truststore.path` setting in
-`elasticsearch.yml` specifies the location of the {watcher}
-truststore.
. Add one or more users who have the permissions
necessary to use {kib} and {reporting}. For more information, see
<>.
diff --git a/package.json b/package.json
index 6b9640d214a5ef..a623b656ec9a1f 100644
--- a/package.json
+++ b/package.json
@@ -118,7 +118,7 @@
"@elastic/charts": "^16.1.0",
"@elastic/datemath": "5.0.2",
"@elastic/ems-client": "1.0.5",
- "@elastic/eui": "17.3.1",
+ "@elastic/eui": "18.0.0",
"@elastic/filesaver": "1.1.2",
"@elastic/good": "8.1.1-kibana2",
"@elastic/numeral": "2.3.3",
@@ -163,7 +163,6 @@
"compare-versions": "3.5.1",
"core-js": "^3.2.1",
"css-loader": "2.1.1",
- "custom-event-polyfill": "^0.3.0",
"d3": "3.5.17",
"d3-cloud": "1.2.5",
"deep-freeze-strict": "^1.1.1",
@@ -254,6 +253,7 @@
"rison-node": "1.0.2",
"rxjs": "^6.5.3",
"script-loader": "0.7.2",
+ "seedrandom": "^3.0.5",
"semver": "^5.5.0",
"style-it": "^2.1.3",
"style-loader": "0.23.1",
@@ -365,7 +365,7 @@
"@types/semver": "^5.5.0",
"@types/sinon": "^7.0.13",
"@types/strip-ansi": "^3.0.0",
- "@types/styled-components": "^4.4.1",
+ "@types/styled-components": "^4.4.2",
"@types/supertest": "^2.0.5",
"@types/supertest-as-promised": "^2.0.38",
"@types/testing-library__react": "^9.1.2",
diff --git a/packages/kbn-spec-to-console/lib/convert.js b/packages/kbn-spec-to-console/lib/convert.js
index 4c312818607671..5dbdd6e1c94e44 100644
--- a/packages/kbn-spec-to-console/lib/convert.js
+++ b/packages/kbn-spec-to-console/lib/convert.js
@@ -24,10 +24,16 @@ const convertParts = require('./convert/parts');
module.exports = spec => {
const result = {};
- // TODO:
- // Since https://github.com/elastic/elasticsearch/pull/42346 has been merged into ES master
- // the JSON doc specification has been updated. We need to update this script to take advantage
- // of the added information but it will also require updating console's editor autocomplete.
+ /**
+ * TODO:
+ * Since https://github.com/elastic/elasticsearch/pull/42346 has been merged into ES master
+ * the JSON doc specification has been updated. We need to update this script to take advantage
+ * of the added information but it will also require updating console editor autocomplete.
+ *
+ * Note: for now we exclude all deprecated patterns from the generated spec to prevent them
+ * from being used in autocompletion. It would be really nice if we could use this information
+ * instead of just not including it.
+ */
Object.keys(spec).forEach(api => {
const source = spec[api];
if (!source.url) {
@@ -46,8 +52,10 @@ module.exports = spec => {
const urlComponents = {};
if (source.url.paths) {
- patterns = convertPaths(source.url.paths);
- source.url.paths.forEach(pathsObject => {
+ // We filter out all deprecated url patterns here.
+ const paths = source.url.paths.filter(path => !path.deprecated);
+ patterns = convertPaths(paths);
+ paths.forEach(pathsObject => {
pathsObject.methods.forEach(method => methodSet.add(method));
if (pathsObject.parts) {
for (const partName of Object.keys(pathsObject.parts)) {
diff --git a/packages/kbn-ui-shared-deps/entry.js b/packages/kbn-ui-shared-deps/entry.js
index 250abd162f91d7..7a15c3bb742c0a 100644
--- a/packages/kbn-ui-shared-deps/entry.js
+++ b/packages/kbn-ui-shared-deps/entry.js
@@ -17,6 +17,9 @@
* under the License.
*/
+// import global polyfills before everything else
+require('./polyfills');
+
// must load before angular
export const Jquery = require('jquery');
window.$ = window.jQuery = Jquery;
diff --git a/packages/kbn-ui-shared-deps/package.json b/packages/kbn-ui-shared-deps/package.json
index 014467d204d96c..c9434f3ec1c38d 100644
--- a/packages/kbn-ui-shared-deps/package.json
+++ b/packages/kbn-ui-shared-deps/package.json
@@ -9,12 +9,15 @@
"kbn:watch": "node scripts/build --watch"
},
"devDependencies": {
- "@elastic/eui": "17.3.1",
+ "@elastic/eui": "18.0.0",
"@elastic/charts": "^16.1.0",
"@kbn/dev-utils": "1.0.0",
"@yarnpkg/lockfile": "^1.1.0",
+ "abortcontroller-polyfill": "^1.3.0",
"angular": "^1.7.9",
+ "core-js": "^3.2.1",
"css-loader": "^2.1.1",
+ "custom-event-polyfill": "^0.3.0",
"del": "^5.1.0",
"jquery": "^3.4.1",
"mini-css-extract-plugin": "0.8.0",
@@ -24,6 +27,9 @@
"react-intl": "^2.8.0",
"react": "^16.12.0",
"read-pkg": "^5.2.0",
- "webpack": "4.41.0"
+ "regenerator-runtime": "^0.13.3",
+ "symbol-observable": "^1.2.0",
+ "webpack": "4.41.0",
+ "whatwg-fetch": "^3.0.0"
}
}
\ No newline at end of file
diff --git a/packages/kbn-ui-shared-deps/polyfills.js b/packages/kbn-ui-shared-deps/polyfills.js
new file mode 100644
index 00000000000000..d2305d643e4d20
--- /dev/null
+++ b/packages/kbn-ui-shared-deps/polyfills.js
@@ -0,0 +1,26 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+require('core-js/stable');
+require('regenerator-runtime/runtime');
+require('custom-event-polyfill');
+require('whatwg-fetch');
+require('abortcontroller-polyfill/dist/polyfill-patch-fetch');
+require('./vendor/childnode_remove_polyfill');
+require('symbol-observable');
diff --git a/webpackShims/childnode-remove-polyfill.js b/packages/kbn-ui-shared-deps/vendor/childnode_remove_polyfill.js
similarity index 68%
rename from webpackShims/childnode-remove-polyfill.js
rename to packages/kbn-ui-shared-deps/vendor/childnode_remove_polyfill.js
index 26c21d1674b07d..d8818fe809ccbb 100644
--- a/webpackShims/childnode-remove-polyfill.js
+++ b/packages/kbn-ui-shared-deps/vendor/childnode_remove_polyfill.js
@@ -1,21 +1,4 @@
-/*
- * 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.
- */
+/* eslint-disable @kbn/eslint/require-license-header */
/* @notice
* This product bundles childnode-remove which is available under a
diff --git a/src/core/public/chrome/chrome_service.tsx b/src/core/public/chrome/chrome_service.tsx
index a674b49a8e1344..09ea1afe35766c 100644
--- a/src/core/public/chrome/chrome_service.tsx
+++ b/src/core/public/chrome/chrome_service.tsx
@@ -127,7 +127,7 @@ export class ChromeService {
)
)
);
- this.isVisible$ = combineLatest(this.appHidden$, this.toggleHidden$).pipe(
+ this.isVisible$ = combineLatest([this.appHidden$, this.toggleHidden$]).pipe(
map(([appHidden, toggleHidden]) => !(appHidden || toggleHidden)),
takeUntil(this.stop$)
);
diff --git a/src/core/public/chrome/ui/header/header.tsx b/src/core/public/chrome/ui/header/header.tsx
index 0447add4917882..d05a6bb53405c5 100644
--- a/src/core/public/chrome/ui/header/header.tsx
+++ b/src/core/public/chrome/ui/header/header.tsx
@@ -57,7 +57,7 @@ import {
} from '../..';
import { HttpStart } from '../../../http';
import { ChromeHelpExtension } from '../../chrome_service';
-import { ApplicationStart, InternalApplicationStart } from '../../../application/types';
+import { InternalApplicationStart } from '../../../application/types';
// Providing a buffer between the limit and the cut off index
// protects from truncating just the last couple (6) characters
@@ -108,7 +108,7 @@ function extendRecentlyAccessedHistoryItem(
};
}
-function extendNavLink(navLink: ChromeNavLink, urlForApp: ApplicationStart['getUrlForApp']) {
+function extendNavLink(navLink: ChromeNavLink) {
if (navLink.legacy) {
return {
...navLink,
@@ -118,7 +118,7 @@ function extendNavLink(navLink: ChromeNavLink, urlForApp: ApplicationStart['getU
return {
...navLink,
- href: urlForApp(navLink.id),
+ href: navLink.baseUrl,
};
}
@@ -229,9 +229,7 @@ class HeaderUI extends Component {
appTitle,
isVisible,
forceNavigation,
- navLinks: navLinks.map(navLink =>
- extendNavLink(navLink, this.props.application.getUrlForApp)
- ),
+ navLinks: navLinks.map(extendNavLink),
recentlyAccessed: recentlyAccessed.map(ra =>
extendRecentlyAccessedHistoryItem(navLinks, ra, this.props.basePath)
),
diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts
index 44dc76bfe6e320..36b220f16f3950 100644
--- a/src/core/public/doc_links/doc_links_service.ts
+++ b/src/core/public/doc_links/doc_links_service.ts
@@ -115,6 +115,9 @@ export class DocLinksService {
date: {
dateMath: `${ELASTICSEARCH_DOCS}common-options.html#date-math`,
},
+ management: {
+ kibanaSearchSettings: `${ELASTIC_WEBSITE_URL}guide/en/kibana/${DOC_LINK_VERSION}/advanced-options.html#kibana-search-settings`,
+ },
},
});
}
diff --git a/src/core/public/rendering/app_containers.test.tsx b/src/core/public/rendering/app_containers.test.tsx
new file mode 100644
index 00000000000000..746e37b1214d92
--- /dev/null
+++ b/src/core/public/rendering/app_containers.test.tsx
@@ -0,0 +1,105 @@
+/*
+ * 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 { BehaviorSubject } from 'rxjs';
+import { act } from 'react-dom/test-utils';
+import { mount } from 'enzyme';
+import React from 'react';
+
+import { AppWrapper, AppContainer } from './app_containers';
+
+describe('AppWrapper', () => {
+ it('toggles the `hidden-chrome` class depending on the chrome visibility state', () => {
+ const chromeVisible$ = new BehaviorSubject(true);
+
+ const component = mount(app-content );
+ expect(component.getDOMNode()).toMatchInlineSnapshot(`
+
+ app-content
+
+ `);
+
+ act(() => chromeVisible$.next(false));
+ component.update();
+ expect(component.getDOMNode()).toMatchInlineSnapshot(`
+
+ app-content
+
+ `);
+
+ act(() => chromeVisible$.next(true));
+ component.update();
+ expect(component.getDOMNode()).toMatchInlineSnapshot(`
+
+ app-content
+
+ `);
+ });
+});
+
+describe('AppContainer', () => {
+ it('adds classes supplied by chrome', () => {
+ const appClasses$ = new BehaviorSubject([]);
+
+ const component = mount(app-content );
+ expect(component.getDOMNode()).toMatchInlineSnapshot(`
+
+ app-content
+
+ `);
+
+ act(() => appClasses$.next(['classA', 'classB']));
+ component.update();
+ expect(component.getDOMNode()).toMatchInlineSnapshot(`
+
+ app-content
+
+ `);
+
+ act(() => appClasses$.next(['classC']));
+ component.update();
+ expect(component.getDOMNode()).toMatchInlineSnapshot(`
+
+ app-content
+
+ `);
+
+ act(() => appClasses$.next([]));
+ component.update();
+ expect(component.getDOMNode()).toMatchInlineSnapshot(`
+
+ app-content
+
+ `);
+ });
+});
diff --git a/src/core/public/rendering/app_containers.tsx b/src/core/public/rendering/app_containers.tsx
new file mode 100644
index 00000000000000..72faaeac588bef
--- /dev/null
+++ b/src/core/public/rendering/app_containers.tsx
@@ -0,0 +1,37 @@
+/*
+ * 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 { Observable } from 'rxjs';
+import useObservable from 'react-use/lib/useObservable';
+import classNames from 'classnames';
+
+export const AppWrapper: React.FunctionComponent<{
+ chromeVisible$: Observable;
+}> = ({ chromeVisible$, children }) => {
+ const visible = useObservable(chromeVisible$);
+ return {children}
;
+};
+
+export const AppContainer: React.FunctionComponent<{
+ classes$: Observable;
+}> = ({ classes$, children }) => {
+ const classes = useObservable(classes$);
+ return {children}
;
+};
diff --git a/src/core/public/rendering/rendering_service.test.tsx b/src/core/public/rendering/rendering_service.test.tsx
index ed835574a32f9c..437a602a3d4473 100644
--- a/src/core/public/rendering/rendering_service.test.tsx
+++ b/src/core/public/rendering/rendering_service.test.tsx
@@ -18,72 +18,129 @@
*/
import React from 'react';
+import { act } from 'react-dom/test-utils';
-import { chromeServiceMock } from '../chrome/chrome_service.mock';
import { RenderingService } from './rendering_service';
-import { InternalApplicationStart } from '../application';
+import { applicationServiceMock } from '../application/application_service.mock';
+import { chromeServiceMock } from '../chrome/chrome_service.mock';
import { injectedMetadataServiceMock } from '../injected_metadata/injected_metadata_service.mock';
import { overlayServiceMock } from '../overlays/overlay_service.mock';
+import { BehaviorSubject } from 'rxjs';
describe('RenderingService#start', () => {
- const getService = ({ legacyMode = false }: { legacyMode?: boolean } = {}) => {
- const rendering = new RenderingService();
- const application = {
- getComponent: () => Hello application!
,
- } as InternalApplicationStart;
- const chrome = chromeServiceMock.createStartContract();
+ let application: ReturnType;
+ let chrome: ReturnType;
+ let overlays: ReturnType;
+ let injectedMetadata: ReturnType;
+ let targetDomElement: HTMLDivElement;
+ let rendering: RenderingService;
+
+ beforeEach(() => {
+ application = applicationServiceMock.createInternalStartContract();
+ application.getComponent.mockReturnValue(Hello application!
);
+
+ chrome = chromeServiceMock.createStartContract();
chrome.getHeaderComponent.mockReturnValue(Hello chrome!
);
- const overlays = overlayServiceMock.createStartContract();
+
+ overlays = overlayServiceMock.createStartContract();
overlays.banners.getComponent.mockReturnValue(I'm a banner!
);
- const injectedMetadata = injectedMetadataServiceMock.createStartContract();
- injectedMetadata.getLegacyMode.mockReturnValue(legacyMode);
- const targetDomElement = document.createElement('div');
- const start = rendering.start({
+ injectedMetadata = injectedMetadataServiceMock.createStartContract();
+
+ targetDomElement = document.createElement('div');
+
+ rendering = new RenderingService();
+ });
+
+ const startService = () => {
+ return rendering.start({
application,
chrome,
injectedMetadata,
overlays,
targetDomElement,
});
- return { start, targetDomElement };
};
- it('renders application service into provided DOM element', () => {
- const { targetDomElement } = getService();
- expect(targetDomElement.querySelector('div.application')).toMatchInlineSnapshot(`
-
-
- Hello application!
-
-
- `);
- });
+ describe('standard mode', () => {
+ beforeEach(() => {
+ injectedMetadata.getLegacyMode.mockReturnValue(false);
+ });
- it('contains wrapper divs', () => {
- const { targetDomElement } = getService();
- expect(targetDomElement.querySelector('div.app-wrapper')).toBeDefined();
- expect(targetDomElement.querySelector('div.app-wrapper-pannel')).toBeDefined();
- });
+ it('renders application service into provided DOM element', () => {
+ startService();
+ expect(targetDomElement.querySelector('div.application')).toMatchInlineSnapshot(`
+
+
+ Hello application!
+
+
+ `);
+ });
+
+ it('adds the `chrome-hidden` class to the AppWrapper when chrome is hidden', () => {
+ const isVisible$ = new BehaviorSubject(true);
+ chrome.getIsVisible$.mockReturnValue(isVisible$);
+ startService();
+
+ const appWrapper = targetDomElement.querySelector('div.app-wrapper')!;
+ expect(appWrapper.className).toEqual('app-wrapper');
+
+ act(() => isVisible$.next(false));
+ expect(appWrapper.className).toEqual('app-wrapper hidden-chrome');
- it('renders the banner UI', () => {
- const { targetDomElement } = getService();
- expect(targetDomElement.querySelector('#globalBannerList')).toMatchInlineSnapshot(`
-
- `);
+ act(() => isVisible$.next(true));
+ expect(appWrapper.className).toEqual('app-wrapper');
+ });
+
+ it('adds the application classes to the AppContainer', () => {
+ const applicationClasses$ = new BehaviorSubject([]);
+ chrome.getApplicationClasses$.mockReturnValue(applicationClasses$);
+ startService();
+
+ const appContainer = targetDomElement.querySelector('div.application')!;
+ expect(appContainer.className).toEqual('application');
+
+ act(() => applicationClasses$.next(['classA', 'classB']));
+ expect(appContainer.className).toEqual('application classA classB');
+
+ act(() => applicationClasses$.next(['classC']));
+ expect(appContainer.className).toEqual('application classC');
+
+ act(() => applicationClasses$.next([]));
+ expect(appContainer.className).toEqual('application');
+ });
+
+ it('contains wrapper divs', () => {
+ startService();
+ expect(targetDomElement.querySelector('div.app-wrapper')).toBeDefined();
+ expect(targetDomElement.querySelector('div.app-wrapper-pannel')).toBeDefined();
+ });
+
+ it('renders the banner UI', () => {
+ startService();
+ expect(targetDomElement.querySelector('#globalBannerList')).toMatchInlineSnapshot(`
+
+ `);
+ });
});
- describe('legacyMode', () => {
+ describe('legacy mode', () => {
+ beforeEach(() => {
+ injectedMetadata.getLegacyMode.mockReturnValue(true);
+ });
+
it('renders into provided DOM element', () => {
- const { targetDomElement } = getService({ legacyMode: true });
+ startService();
+
expect(targetDomElement).toMatchInlineSnapshot(`
{
});
it('returns a div for the legacy service to render into', () => {
- const {
- start: { legacyTargetDomElement },
- targetDomElement,
- } = getService({ legacyMode: true });
+ const { legacyTargetDomElement } = startService();
+
expect(targetDomElement.contains(legacyTargetDomElement!)).toBe(true);
});
});
diff --git a/src/core/public/rendering/rendering_service.tsx b/src/core/public/rendering/rendering_service.tsx
index 7a747faa2673f5..58b8c1921e333b 100644
--- a/src/core/public/rendering/rendering_service.tsx
+++ b/src/core/public/rendering/rendering_service.tsx
@@ -25,6 +25,7 @@ import { InternalChromeStart } from '../chrome';
import { InternalApplicationStart } from '../application';
import { InjectedMetadataStart } from '../injected_metadata';
import { OverlayStart } from '../overlays';
+import { AppWrapper, AppContainer } from './app_containers';
interface StartDeps {
application: InternalApplicationStart;
@@ -65,12 +66,12 @@ export class RenderingService {
{chromeUi}
{!legacyMode && (
-
+
{bannerUi}
-
{appUi}
+
{appUi}
-
+
)}
{legacyMode &&
}
diff --git a/src/core/server/legacy/legacy_service.test.ts b/src/core/server/legacy/legacy_service.test.ts
index 608392e4943f91..af4db68ee95e16 100644
--- a/src/core/server/legacy/legacy_service.test.ts
+++ b/src/core/server/legacy/legacy_service.test.ts
@@ -424,7 +424,7 @@ describe('#discoverPlugins()', () => {
await legacyService.discoverPlugins();
expect(findLegacyPluginSpecs).toHaveBeenCalledTimes(1);
- expect(findLegacyPluginSpecs).toHaveBeenCalledWith(expect.any(Object), logger);
+ expect(findLegacyPluginSpecs).toHaveBeenCalledWith(expect.any(Object), logger, env.packageInfo);
});
it(`register legacy plugin's deprecation providers`, async () => {
diff --git a/src/core/server/legacy/legacy_service.ts b/src/core/server/legacy/legacy_service.ts
index cc36b90ec526d7..7a03cefc38c1a5 100644
--- a/src/core/server/legacy/legacy_service.ts
+++ b/src/core/server/legacy/legacy_service.ts
@@ -125,7 +125,11 @@ export class LegacyService implements CoreService {
disabledPluginSpecs,
uiExports,
navLinks,
- } = await findLegacyPluginSpecs(this.settings, this.coreContext.logger);
+ } = await findLegacyPluginSpecs(
+ this.settings,
+ this.coreContext.logger,
+ this.coreContext.env.packageInfo
+ );
this.legacyPlugins = {
pluginSpecs,
diff --git a/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts b/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts
index d2e7a39236d0a8..9867274d224bd0 100644
--- a/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts
+++ b/src/core/server/legacy/plugins/find_legacy_plugin_specs.ts
@@ -29,6 +29,8 @@ import {
import { collectUiExports as collectLegacyUiExports } from '../../../../legacy/ui/ui_exports/collect_ui_exports';
import { LoggerFactory } from '../../logging';
+import { PackageInfo } from '../../config';
+
import {
LegacyUiExports,
LegacyNavLink,
@@ -92,7 +94,11 @@ function getNavLinks(uiExports: LegacyUiExports, pluginSpecs: LegacyPluginSpec[]
.sort((a, b) => a.order - b.order);
}
-export async function findLegacyPluginSpecs(settings: unknown, loggerFactory: LoggerFactory) {
+export async function findLegacyPluginSpecs(
+ settings: unknown,
+ loggerFactory: LoggerFactory,
+ packageInfo: PackageInfo
+) {
const configToMutate: LegacyConfig = defaultConfig(settings);
const {
pack$,
@@ -152,8 +158,7 @@ export async function findLegacyPluginSpecs(settings: unknown, loggerFactory: Lo
map(spec => {
const name = spec.getId();
const pluginVersion = spec.getExpectedKibanaVersion();
- // @ts-ignore
- const kibanaVersion = settings.pkg.version;
+ const kibanaVersion = packageInfo.version;
return `Plugin "${name}" was disabled because it expected Kibana version "${pluginVersion}", and found "${kibanaVersion}".`;
}),
distinct(),
diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md
index 65477e93e225e4..7f3a9605710127 100644
--- a/src/core/server/server.api.md
+++ b/src/core/server/server.api.md
@@ -1928,6 +1928,8 @@ export type SharedGlobalConfig = RecursiveReadonly_2<{
// @public
export interface UiSettingsParams {
category?: string[];
+ // Warning: (ae-forgotten-export) The symbol "DeprecationSettings" needs to be exported by the entry point index.d.ts
+ deprecation?: DeprecationSettings;
description?: string;
name?: string;
optionLabels?: Record
;
diff --git a/src/core/server/types.ts b/src/core/server/types.ts
index 9919c7f0386b56..2433aad1a2be57 100644
--- a/src/core/server/types.ts
+++ b/src/core/server/types.ts
@@ -23,4 +23,3 @@ export * from './saved_objects/types';
export * from './ui_settings/types';
export * from './legacy/types';
export { EnvironmentMode, PackageInfo } from './config/types';
-export { ICspConfig } from './csp';
diff --git a/src/core/server/ui_settings/types.ts b/src/core/server/ui_settings/types.ts
index 2ab6114e7df882..14eb71a22cefcc 100644
--- a/src/core/server/ui_settings/types.ts
+++ b/src/core/server/ui_settings/types.ts
@@ -73,6 +73,15 @@ export interface UserProvidedValues {
isOverridden?: boolean;
}
+/**
+ * UiSettings deprecation field options.
+ * @public
+ * */
+export interface DeprecationSettings {
+ message: string;
+ docLinksKey: string;
+}
+
/**
* UI element type to represent the settings.
* @public
@@ -102,6 +111,8 @@ export interface UiSettingsParams {
readonly?: boolean;
/** defines a type of UI element {@link UiSettingsType} */
type?: UiSettingsType;
+ /** optional deprecation information. Used to generate a deprecation warning. */
+ deprecation?: DeprecationSettings;
/*
* Allows defining a custom validation applicable to value change on the client.
* @deprecated
diff --git a/src/dev/build/README.md b/src/dev/build/README.md
index af08414f0bf4be..3b579033fabe1f 100644
--- a/src/dev/build/README.md
+++ b/src/dev/build/README.md
@@ -44,7 +44,7 @@ The majority of this logic is extracted from the grunt build that has existed fo
We have introduced in our bundle a webpack dll for the client vendor modules in order to improve
the optimization time both in dev and in production. As for those modules we already have the
-code into the vendors.bundle.dll.js we have decided to delete those bundled modules from the
+code into the vendors_${chunk_number}.bundle.dll.js we have decided to delete those bundled modules from the
distributable node_modules folder. However, in order to accomplish this, we need to exclude
every node_module used in the server side code. This logic is performed
under `nodejs_modules/clean_client_modules_on_dll_task.js`. In case we need to add any new cli
diff --git a/src/dev/build/tasks/nodejs_modules/clean_client_modules_on_dll_task.js b/src/dev/build/tasks/nodejs_modules/clean_client_modules_on_dll_task.js
index 19d74bcf89e302..52928d6e47fc46 100644
--- a/src/dev/build/tasks/nodejs_modules/clean_client_modules_on_dll_task.js
+++ b/src/dev/build/tasks/nodejs_modules/clean_client_modules_on_dll_task.js
@@ -98,12 +98,16 @@ export const CleanClientModulesOnDLLTask = {
// Consider this as our whiteList for the modules we can't delete
const whiteListedModules = [...serverDependencies, ...kbnWebpackLoaders, ...manualExceptions];
- // Resolve the client vendors dll manifest path
- const dllManifestPath = `${baseDir}/built_assets/dlls/vendors.manifest.dll.json`;
+ // Resolve the client vendors dll manifest paths
+ // excluding the runtime one
+ const dllManifestPaths = await globby([
+ `${baseDir}/built_assets/dlls/vendors_*.manifest.dll.json`,
+ `!${baseDir}/built_assets/dlls/vendors_runtime.manifest.dll.json`,
+ ]);
// Get dll entries filtering out the ones
// from any whitelisted module
- const dllEntries = await getDllEntries(dllManifestPath, whiteListedModules, baseDir);
+ const dllEntries = await getDllEntries(dllManifestPaths, whiteListedModules, baseDir);
for (const relativeEntryPath of dllEntries) {
const entryPath = `${baseDir}/${relativeEntryPath}`;
diff --git a/src/dev/build/tasks/nodejs_modules/webpack_dll.js b/src/dev/build/tasks/nodejs_modules/webpack_dll.js
index ea8cc1e2864071..72910226bb04a7 100644
--- a/src/dev/build/tasks/nodejs_modules/webpack_dll.js
+++ b/src/dev/build/tasks/nodejs_modules/webpack_dll.js
@@ -28,27 +28,37 @@ function checkDllEntryAccess(entry, baseDir = '') {
return isFileAccessible(resolvedPath);
}
-export async function getDllEntries(manifestPath, whiteListedModules, baseDir = '') {
- const manifest = JSON.parse(await read(manifestPath));
-
- if (!manifest || !manifest.content) {
- // It should fails because if we don't have the manifest file
- // or it is malformed something wrong is happening and we
- // should stop
- throw new Error(`The following dll manifest doesn't exists: ${manifestPath}`);
- }
+export async function getDllEntries(manifestPaths, whiteListedModules, baseDir = '') {
+ // Read and parse all manifests
+ const manifests = await Promise.all(
+ manifestPaths.map(async manifestPath => JSON.parse(await read(manifestPath)))
+ );
- const modules = Object.keys(manifest.content);
- if (!modules.length) {
- // It should fails because if we don't have any
- // module inside the client vendors dll something
- // wrong is happening and we should stop too
- throw new Error(`The following dll manifest is reporting an empty dll: ${manifestPath}`);
- }
+ // Process and group modules from all manifests
+ const manifestsModules = manifests.flatMap((manifest, idx) => {
+ if (!manifest || !manifest.content) {
+ // It should fails because if we don't have the manifest file
+ // or it is malformed something wrong is happening and we
+ // should stop
+ throw new Error(`The following dll manifest doesn't exists: ${manifestPaths[idx]}`);
+ }
+
+ const modules = Object.keys(manifest.content);
+ if (!modules.length) {
+ // It should fails because if we don't have any
+ // module inside the client vendors dll something
+ // wrong is happening and we should stop too
+ throw new Error(
+ `The following dll manifest is reporting an empty dll: ${manifestPaths[idx]}`
+ );
+ }
+
+ return modules;
+ });
// Only includes modules who are not in the white list of modules
// and that are node_modules
- return modules.filter(entry => {
+ return manifestsModules.filter(entry => {
const isWhiteListed = whiteListedModules.some(nonEntry =>
normalizePosixPath(entry).includes(`node_modules/${nonEntry}`)
);
diff --git a/src/dev/build/tasks/nodejs_modules/webpack_dll.test.js b/src/dev/build/tasks/nodejs_modules/webpack_dll.test.js
index 1fdd7d8d4f5ff3..ce305169a777b9 100644
--- a/src/dev/build/tasks/nodejs_modules/webpack_dll.test.js
+++ b/src/dev/build/tasks/nodejs_modules/webpack_dll.test.js
@@ -52,7 +52,7 @@ describe('Webpack DLL Build Tasks Utils', () => {
isFileAccessible.mockImplementation(() => true);
- const mockManifestPath = '/mock/mock_dll_manifest.json';
+ const mockManifestPath = ['/mock/mock_dll_manifest.json'];
const mockModulesWhitelist = ['dep1'];
const dllEntries = await getDllEntries(mockManifestPath, mockModulesWhitelist);
@@ -66,7 +66,7 @@ describe('Webpack DLL Build Tasks Utils', () => {
isFileAccessible.mockImplementation(() => false);
- const mockManifestPath = '/mock/mock_dll_manifest.json';
+ const mockManifestPath = ['/mock/mock_dll_manifest.json'];
const mockModulesWhitelist = ['dep1'];
const dllEntries = await getDllEntries(mockManifestPath, mockModulesWhitelist);
@@ -78,7 +78,7 @@ describe('Webpack DLL Build Tasks Utils', () => {
it('should throw an error for no manifest file', async () => {
read.mockImplementationOnce(async () => noManifestMock);
- const mockManifestPath = '/mock/mock_dll_manifest.json';
+ const mockManifestPath = ['/mock/mock_dll_manifest.json'];
try {
await getDllEntries(mockManifestPath, []);
@@ -92,7 +92,7 @@ describe('Webpack DLL Build Tasks Utils', () => {
it('should throw an error for no manifest content field', async () => {
read.mockImplementation(async () => noContentFieldManifestMock);
- const mockManifestPath = '/mock/mock_dll_manifest.json';
+ const mockManifestPath = ['/mock/mock_dll_manifest.json'];
try {
await getDllEntries(mockManifestPath, []);
@@ -106,7 +106,7 @@ describe('Webpack DLL Build Tasks Utils', () => {
it('should throw an error for manifest file without any content', async () => {
read.mockImplementation(async () => emptyManifestContentMock);
- const mockManifestPath = '/mock/mock_dll_manifest.json';
+ const mockManifestPath = ['/mock/mock_dll_manifest.json'];
try {
await getDllEntries(mockManifestPath, []);
diff --git a/src/dev/license_checker/config.ts b/src/dev/license_checker/config.ts
index a4aa3474c0762c..bd084767a723f0 100644
--- a/src/dev/license_checker/config.ts
+++ b/src/dev/license_checker/config.ts
@@ -23,6 +23,7 @@ export const LICENSE_WHITELIST = [
'Elastic-License',
'(BSD-2-Clause OR MIT OR Apache-2.0)',
'(BSD-2-Clause OR MIT)',
+ '(BSD-3-Clause AND Apache-2.0)',
'(GPL-2.0 OR MIT)',
'(MIT AND CC-BY-3.0)',
'(MIT AND Zlib)',
diff --git a/src/dev/sass/build_sass.js b/src/dev/sass/build_sass.js
index 14f03a7a116a6f..1ff7c700d03861 100644
--- a/src/dev/sass/build_sass.js
+++ b/src/dev/sass/build_sass.js
@@ -19,6 +19,7 @@
import { resolve } from 'path';
+import * as Rx from 'rxjs';
import { toArray } from 'rxjs/operators';
import { createFailError } from '@kbn/dev-utils';
@@ -61,9 +62,11 @@ export async function buildSass({ log, kibanaDir, watch }) {
const scanDirs = [resolve(kibanaDir, 'src/legacy/core_plugins')];
const paths = [resolve(kibanaDir, 'x-pack')];
- const { spec$ } = findPluginSpecs({ plugins: { scanDirs, paths } });
- const enabledPlugins = await spec$.pipe(toArray()).toPromise();
- const uiExports = collectUiExports(enabledPlugins);
+ const { spec$, disabledSpec$ } = findPluginSpecs({ plugins: { scanDirs, paths } });
+ const allPlugins = await Rx.merge(spec$, disabledSpec$)
+ .pipe(toArray())
+ .toPromise();
+ const uiExports = collectUiExports(allPlugins);
const { styleSheetPaths } = uiExports;
log.info('%s %d styleSheetPaths', watch ? 'watching' : 'found', styleSheetPaths.length);
diff --git a/src/legacy/core_plugins/console/public/np_ready/application/models/legacy_core_editor/legacy_core_editor.ts b/src/legacy/core_plugins/console/public/np_ready/application/models/legacy_core_editor/legacy_core_editor.ts
index 6262c304e307bf..8301daa675b5ce 100644
--- a/src/legacy/core_plugins/console/public/np_ready/application/models/legacy_core_editor/legacy_core_editor.ts
+++ b/src/legacy/core_plugins/console/public/np_ready/application/models/legacy_core_editor/legacy_core_editor.ts
@@ -303,7 +303,9 @@ export class LegacyCoreEditor implements CoreEditor {
const maxLineLength = this.getWrapLimit() - 5;
const isWrapping = firstLine.length > maxLineLength;
const getScreenCoords = (line: number) =>
- this.editor.renderer.textToScreenCoordinates(line - 1, startColumn).pageY - offsetFromPage;
+ this.editor.renderer.textToScreenCoordinates(line - 1, startColumn).pageY -
+ offsetFromPage +
+ (window.pageYOffset || 0);
const topOfReq = getScreenCoords(startLine);
if (topOfReq >= 0) {
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.indices.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.indices.json
index 45da7f054bfb41..e6ca1fb575396f 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.indices.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/cat.indices.json
@@ -5,8 +5,15 @@
"bytes": [
"b",
"k",
+ "kb",
"m",
- "g"
+ "mb",
+ "g",
+ "gb",
+ "t",
+ "tb",
+ "p",
+ "pb"
],
"local": "__flag__",
"master_timeout": "",
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/clear_scroll.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/clear_scroll.json
index 55d9673054276b..7e6e6692f931b2 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/clear_scroll.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/clear_scroll.json
@@ -4,8 +4,7 @@
"DELETE"
],
"patterns": [
- "_search/scroll",
- "_search/scroll/{scroll_id}"
+ "_search/scroll"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/search-request-body.html#_clear_scroll_api"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/create.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/create.json
index 6c0ee8a2425eeb..8bbee143c299f9 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/create.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/create.json
@@ -22,8 +22,7 @@
"POST"
],
"patterns": [
- "{indices}/_create/{id}",
- "{indices}/{type}/{id}/_create"
+ "{indices}/_create/{id}"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-index_.html"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/delete.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/delete.json
index aba84d0a10fc2d..0852d8d1848311 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/delete.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/delete.json
@@ -23,8 +23,7 @@
"DELETE"
],
"patterns": [
- "{indices}/_doc/{id}",
- "{indices}/{type}/{id}"
+ "{indices}/_doc/{id}"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-delete.html"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/delete_by_query.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/delete_by_query.json
index 3867efd814238c..2d1636d5f2c028 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/delete_by_query.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/delete_by_query.json
@@ -1,7 +1,6 @@
{
"delete_by_query": {
"url_params": {
- "analyzer": "",
"analyze_wildcard": "__flag__",
"default_operator": [
"AND",
@@ -31,6 +30,7 @@
"dfs_query_then_fetch"
],
"search_timeout": "",
+ "size": "",
"max_docs": "all documents",
"sort": [],
"_source": [],
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/exists_source.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/exists_source.json
index e96273ffbc0830..9ffc4b55f3037c 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/exists_source.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/exists_source.json
@@ -20,8 +20,7 @@
"HEAD"
],
"patterns": [
- "{indices}/_source/{id}",
- "{indices}/{type}/{id}/_source"
+ "{indices}/_source/{id}"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-get.html"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/get_script_languages.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/get_script_languages.json
new file mode 100644
index 00000000000000..10ea433ca68c56
--- /dev/null
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/get_script_languages.json
@@ -0,0 +1,10 @@
+{
+ "get_script_languages": {
+ "methods": [
+ "GET"
+ ],
+ "patterns": [
+ "_script_language"
+ ]
+ }
+}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.shrink.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.shrink.json
index 31acc86a2fa560..6fbdea0f1244bf 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.shrink.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.shrink.json
@@ -1,6 +1,7 @@
{
"indices.shrink": {
"url_params": {
+ "copy_settings": "__flag__",
"timeout": "",
"master_timeout": "",
"wait_for_active_shards": ""
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.split.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.split.json
index 1bfbaa078b7967..68f2e338cd2013 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.split.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.split.json
@@ -1,6 +1,7 @@
{
"indices.split": {
"url_params": {
+ "copy_settings": "__flag__",
"timeout": "",
"master_timeout": "",
"wait_for_active_shards": ""
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.validate_query.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.validate_query.json
index ceffec26beeccb..33720576ef8a3e 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.validate_query.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/indices.validate_query.json
@@ -28,8 +28,7 @@
],
"patterns": [
"_validate/query",
- "{indices}/_validate/query",
- "{indices}/{type}/_validate/query"
+ "{indices}/_validate/query"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/search-validate.html"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/msearch_template.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/msearch_template.json
index 0b0ca087b1819f..c2f741066bbdb4 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/msearch_template.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/msearch_template.json
@@ -9,8 +9,7 @@
],
"typed_keys": "__flag__",
"max_concurrent_searches": "",
- "rest_total_hits_as_int": "__flag__",
- "ccs_minimize_roundtrips": "__flag__"
+ "rest_total_hits_as_int": "__flag__"
},
"methods": [
"GET",
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/nodes.hot_threads.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/nodes.hot_threads.json
index b8aa5dd4ca711d..b3cbbe80e0d000 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/nodes.hot_threads.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/nodes.hot_threads.json
@@ -17,13 +17,7 @@
],
"patterns": [
"_nodes/hot_threads",
- "_nodes/{nodes}/hot_threads",
- "_cluster/nodes/hotthreads",
- "_cluster/nodes/{nodes}/hotthreads",
- "_nodes/hotthreads",
- "_nodes/{nodes}/hotthreads",
- "_cluster/nodes/hot_threads",
- "_cluster/nodes/{nodes}/hot_threads"
+ "_nodes/{nodes}/hot_threads"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/cluster-nodes-hot-threads.html"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/rank_eval.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/rank_eval.json
index 620f1c629d9592..c2bed081124a8a 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/rank_eval.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/rank_eval.json
@@ -8,6 +8,10 @@
"closed",
"none",
"all"
+ ],
+ "search_type": [
+ "query_then_fetch",
+ "dfs_query_then_fetch"
]
},
"methods": [
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/scroll.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/scroll.json
index 3e959b9630e986..4ce82a2c25e0e0 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/scroll.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/scroll.json
@@ -10,8 +10,7 @@
"POST"
],
"patterns": [
- "_search/scroll",
- "_search/scroll/{scroll_id}"
+ "_search/scroll"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/search-request-body.html#request-body-search-scroll"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/search_template.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/search_template.json
index 582ecab1dd614b..cf5a5c5f32db32 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/search_template.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/search_template.json
@@ -22,8 +22,7 @@
"explain": "__flag__",
"profile": "__flag__",
"typed_keys": "__flag__",
- "rest_total_hits_as_int": "__flag__",
- "ccs_minimize_roundtrips": "__flag__"
+ "rest_total_hits_as_int": "__flag__"
},
"methods": [
"GET",
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/update.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/update.json
index 4e103b0af2195d..43945dfada35ca 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/update.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/update.json
@@ -21,8 +21,7 @@
"POST"
],
"patterns": [
- "{indices}/_update/{id}",
- "{indices}/{type}/{id}/_update"
+ "{indices}/_update/{id}"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-update.html"
}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/generated/update_by_query.json b/src/legacy/core_plugins/console/server/api_server/spec/generated/update_by_query.json
index 739ea16888146a..393197949e86ce 100644
--- a/src/legacy/core_plugins/console/server/api_server/spec/generated/update_by_query.json
+++ b/src/legacy/core_plugins/console/server/api_server/spec/generated/update_by_query.json
@@ -32,6 +32,7 @@
"dfs_query_then_fetch"
],
"search_timeout": "",
+ "size": "",
"max_docs": "all documents",
"sort": [],
"_source": [],
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/overrides/clear_scroll.json b/src/legacy/core_plugins/console/server/api_server/spec/overrides/clear_scroll.json
new file mode 100644
index 00000000000000..e9d4a6cee54cef
--- /dev/null
+++ b/src/legacy/core_plugins/console/server/api_server/spec/overrides/clear_scroll.json
@@ -0,0 +1,7 @@
+{
+ "clear_scroll": {
+ "data_autocomplete_rules": {
+ "scroll_id": ""
+ }
+ }
+}
diff --git a/src/legacy/core_plugins/console/server/api_server/spec/overrides/create.json b/src/legacy/core_plugins/console/server/api_server/spec/overrides/create.json
deleted file mode 100644
index 0bbf456245c841..00000000000000
--- a/src/legacy/core_plugins/console/server/api_server/spec/overrides/create.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "create": {
- "url_params": {
- "timeout": "1m",
- "ttl": "5m",
- "version": "1"
- },
- "methods": [
- "PUT",
- "POST"
- ],
- "patterns": [
- "{indices}/{type}/{id}/_create"
- ]
- }
-}
diff --git a/src/legacy/core_plugins/data/public/search/fetch/components/__snapshots__/shard_failure_table.test.tsx.snap b/src/legacy/core_plugins/data/public/search/fetch/components/__snapshots__/shard_failure_table.test.tsx.snap
index 55e2c63f608d49..257513f20fa94e 100644
--- a/src/legacy/core_plugins/data/public/search/fetch/components/__snapshots__/shard_failure_table.test.tsx.snap
+++ b/src/legacy/core_plugins/data/public/search/fetch/components/__snapshots__/shard_failure_table.test.tsx.snap
@@ -72,5 +72,6 @@ exports[`ShardFailureTable renders matching snapshot given valid properties 1`]
},
}
}
+ tableLayout="fixed"
/>
`;
diff --git a/src/legacy/core_plugins/input_control_vis/public/components/editor/__snapshots__/controls_tab.test.tsx.snap b/src/legacy/core_plugins/input_control_vis/public/components/editor/__snapshots__/controls_tab.test.tsx.snap
index 632fe63e9e1485..278811ca85df9d 100644
--- a/src/legacy/core_plugins/input_control_vis/public/components/editor/__snapshots__/controls_tab.test.tsx.snap
+++ b/src/legacy/core_plugins/input_control_vis/public/components/editor/__snapshots__/controls_tab.test.tsx.snap
@@ -135,11 +135,7 @@ exports[`renders ControlsTab 1`] = `
>
) => void;
handleParentChange: (controlIndex: number, event: ChangeEvent) => void;
- parentCandidates: EuiSelectProps['options'];
+ parentCandidates: React.ComponentProps['options'];
deps: InputControlVisDependencies;
}
diff --git a/src/legacy/core_plugins/input_control_vis/public/components/vis/__snapshots__/list_control.test.tsx.snap b/src/legacy/core_plugins/input_control_vis/public/components/vis/__snapshots__/list_control.test.tsx.snap
index 31c221b36e2b2a..99482a4be2d7b4 100644
--- a/src/legacy/core_plugins/input_control_vis/public/components/vis/__snapshots__/list_control.test.tsx.snap
+++ b/src/legacy/core_plugins/input_control_vis/public/components/vis/__snapshots__/list_control.test.tsx.snap
@@ -8,10 +8,7 @@ exports[`disableMsg 1`] = `
label="list control"
>
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/area.js b/src/legacy/core_plugins/kbn_vislib_vis_types/public/area.js
index 049544b504918f..fd13067c84cc00 100644
--- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/area.js
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/area.js
@@ -33,7 +33,7 @@ import {
getConfigCollections,
} from './utils/collections';
import { getAreaOptionTabs, countLabel } from './utils/common_config';
-import { palettes } from '@elastic/eui/lib/services';
+import { euiPaletteColorBlind } from '@elastic/eui/lib/services';
import { vislibVisController } from './controller';
export const areaDefinition = {
@@ -117,7 +117,7 @@ export const areaDefinition = {
value: 10,
width: 1,
style: ThresholdLineStyles.FULL,
- color: palettes.euiPaletteColorBlind.colors[9],
+ color: euiPaletteColorBlind()[9],
},
labels: {},
},
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/color_ranges.tsx b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/color_ranges.tsx
index 276e765ae7fe67..947c7ae7e6e362 100644
--- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/color_ranges.tsx
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/components/common/color_ranges.tsx
@@ -48,6 +48,10 @@ function ColorRanges({
const validateRange = useCallback(
({ from, to }, index) => {
+ if (!colorsRange[index]) {
+ return [false, false];
+ }
+
const leftBound = index === 0 ? -Infinity : colorsRange[index - 1].to || 0;
const isFromValid = from >= leftBound;
const isToValid = to >= from;
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/histogram.js b/src/legacy/core_plugins/kbn_vislib_vis_types/public/histogram.js
index fdc18f5bfa0e65..bc017b5a1a871d 100644
--- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/histogram.js
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/histogram.js
@@ -32,7 +32,7 @@ import {
getConfigCollections,
} from './utils/collections';
import { getAreaOptionTabs, countLabel } from './utils/common_config';
-import { palettes } from '@elastic/eui/lib/services';
+import { euiPaletteColorBlind } from '@elastic/eui/lib/services';
import { vislibVisController } from './controller';
export const histogramDefinition = {
@@ -120,7 +120,7 @@ export const histogramDefinition = {
value: 10,
width: 1,
style: ThresholdLineStyles.FULL,
- color: palettes.euiPaletteColorBlind.colors[9],
+ color: euiPaletteColorBlind()[9],
},
},
},
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/horizontal_bar.js b/src/legacy/core_plugins/kbn_vislib_vis_types/public/horizontal_bar.js
index 15bbf9c01cd77d..ee3570314618ab 100644
--- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/horizontal_bar.js
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/horizontal_bar.js
@@ -32,7 +32,7 @@ import {
getConfigCollections,
} from './utils/collections';
import { getAreaOptionTabs, countLabel } from './utils/common_config';
-import { palettes } from '@elastic/eui/lib/services';
+import { euiPaletteColorBlind } from '@elastic/eui/lib/services';
import { vislibVisController } from './controller';
export const horizontalBarDefinition = {
@@ -119,7 +119,7 @@ export const horizontalBarDefinition = {
value: 10,
width: 1,
style: ThresholdLineStyles.FULL,
- color: palettes.euiPaletteColorBlind.colors[9],
+ color: euiPaletteColorBlind()[9],
},
},
},
diff --git a/src/legacy/core_plugins/kbn_vislib_vis_types/public/line.js b/src/legacy/core_plugins/kbn_vislib_vis_types/public/line.js
index a3fb874b5aa1b8..d6d075f452fed4 100644
--- a/src/legacy/core_plugins/kbn_vislib_vis_types/public/line.js
+++ b/src/legacy/core_plugins/kbn_vislib_vis_types/public/line.js
@@ -32,7 +32,7 @@ import {
InterpolationModes,
getConfigCollections,
} from './utils/collections';
-import { palettes } from '@elastic/eui/lib/services';
+import { euiPaletteColorBlind } from '@elastic/eui/lib/services';
import { getAreaOptionTabs, countLabel } from './utils/common_config';
import { vislibVisController } from './controller';
@@ -118,7 +118,7 @@ export const lineDefinition = {
value: 10,
width: 1,
style: ThresholdLineStyles.FULL,
- color: palettes.euiPaletteColorBlind.colors[9],
+ color: euiPaletteColorBlind()[9],
},
},
},
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/__tests__/url_helper.test.ts b/src/legacy/core_plugins/kibana/public/dashboard/__tests__/url_helper.test.ts
index 16773c02f5a7b1..df2dbfd54c130d 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/__tests__/url_helper.test.ts
+++ b/src/legacy/core_plugins/kibana/public/dashboard/__tests__/url_helper.test.ts
@@ -82,10 +82,11 @@ describe('Dashboard URL Helper', () => {
x: 'y',
y: 'z',
});
- url = 'http://notDashboardUrl';
- expect(getUrlVars(url)).toEqual({});
url = 'http://localhost:5601/app/kibana#/dashboard/777182';
expect(getUrlVars(url)).toEqual({});
+ url =
+ 'http://localhost:5601/app/kibana#/dashboard/777182?title=Some%20Dashboard%20With%20Spaces';
+ expect(getUrlVars(url)).toEqual({ title: 'Some Dashboard With Spaces' });
});
it('getLensUrlFromDashboardAbsoluteUrl', () => {
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/application.ts b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/application.ts
index 2a5dedab981510..7f7bf7cf47bdaf 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/application.ts
+++ b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/application.ts
@@ -86,11 +86,9 @@ export const renderApp = (element: HTMLElement, appBasePath: string, deps: Rende
};
};
-const mainTemplate = (basePath: string) => `
+const mainTemplate = (basePath: string) => `
-`;
+
`;
const moduleName = 'app/dashboard';
@@ -98,7 +96,7 @@ const thirdPartyAngularDependencies = ['ngSanitize', 'ngRoute', 'react'];
function mountDashboardApp(appBasePath: string, element: HTMLElement) {
const mountpoint = document.createElement('div');
- mountpoint.setAttribute('style', 'height: 100%');
+ mountpoint.setAttribute('class', 'kbnLocalApplicationWrapper');
// eslint-disable-next-line
mountpoint.innerHTML = mainTemplate(appBasePath);
// bootstrap angular into detached element and attach it later to
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/top_nav/__snapshots__/clone_modal.test.js.snap b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/top_nav/__snapshots__/clone_modal.test.js.snap
index 6def1b1a198b88..e76f65c45e4286 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/top_nav/__snapshots__/clone_modal.test.js.snap
+++ b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/top_nav/__snapshots__/clone_modal.test.js.snap
@@ -30,11 +30,8 @@ exports[`renders DashboardCloneModal 1`] = `
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/url_helper.ts b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/url_helper.ts
index ee9e3c4ef4781e..2e360567c4653f 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/np_ready/url_helper.ts
+++ b/src/legacy/core_plugins/kibana/public/dashboard/np_ready/url_helper.ts
@@ -28,7 +28,7 @@ export function getUrlVars(url: string): Record {
// @ts-ignore
url.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(_, key, value) {
// @ts-ignore
- vars[key] = value;
+ vars[key] = decodeURIComponent(value);
});
return vars;
}
diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context/api/context.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context/api/context.ts
index a6c6d910846254..6054b9f8d03c5f 100644
--- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context/api/context.ts
+++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context/api/context.ts
@@ -74,9 +74,9 @@ function fetchContextProvider(indexPatterns: IndexPatternsContract) {
const searchSource = await createSearchSource(indexPattern, filters);
const sortDirToApply = type === 'successors' ? sortDir : reverseSortDir(sortDir);
- const nanos = indexPattern.isTimeNanosBased() ? extractNanos(anchor._source[timeField]) : '';
+ const nanos = indexPattern.isTimeNanosBased() ? extractNanos(anchor.fields[timeField][0]) : '';
const timeValueMillis =
- nanos !== '' ? convertIsoToMillis(anchor._source[timeField]) : anchor.sort[0];
+ nanos !== '' ? convertIsoToMillis(anchor.fields[timeField][0]) : anchor.sort[0];
const intervals = generateIntervals(LOOKUP_OFFSETS, timeValueMillis, type, sortDir);
let documents: EsHitRecordList = [];
diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context/api/utils/get_es_query_search_after.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context/api/utils/get_es_query_search_after.ts
index 3f9bf255aefa91..d4ee9e0e0f2875 100644
--- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context/api/utils/get_es_query_search_after.ts
+++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/context/api/utils/get_es_query_search_after.ts
@@ -39,14 +39,14 @@ export function getEsQuerySearchAfter(
const afterTimeRecIdx = type === 'successors' && documents.length ? documents.length - 1 : 0;
const afterTimeDoc = documents[afterTimeRecIdx];
const afterTimeValue = nanoSeconds
- ? convertIsoToNanosAsStr(afterTimeDoc._source[timeFieldName])
+ ? convertIsoToNanosAsStr(afterTimeDoc.fields[timeFieldName][0])
: afterTimeDoc.sort[0];
return [afterTimeValue, afterTimeDoc.sort[1]];
}
// if data_nanos adapt timestamp value for sorting, since numeric value was rounded by browser
// ES search_after also works when number is provided as string
return [
- nanoSeconds ? convertIsoToNanosAsStr(anchor._source[timeFieldName]) : anchor.sort[0],
+ nanoSeconds ? convertIsoToNanosAsStr(anchor.fields[timeFieldName][0]) : anchor.sort[0],
anchor.sort[1],
];
}
diff --git a/src/legacy/core_plugins/kibana/public/index.scss b/src/legacy/core_plugins/kibana/public/index.scss
index 3b49af9a4a6a66..dfe4aa1fd3b9f9 100644
--- a/src/legacy/core_plugins/kibana/public/index.scss
+++ b/src/legacy/core_plugins/kibana/public/index.scss
@@ -26,6 +26,9 @@
// Management styles
@import './management/index';
+// Local application mount wrapper styles
+@import 'local_application_service/index';
+
// Dashboard styles
// MUST STAY AT THE BOTTOM BECAUSE OF DARK THEME IMPORTS
@import './dashboard/index';
diff --git a/src/legacy/core_plugins/kibana/public/local_application_service/_index.scss b/src/legacy/core_plugins/kibana/public/local_application_service/_index.scss
new file mode 100644
index 00000000000000..12cc1444101e71
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/local_application_service/_index.scss
@@ -0,0 +1 @@
+@import 'local_application_service';
diff --git a/src/legacy/core_plugins/kibana/public/local_application_service/_local_application_service.scss b/src/legacy/core_plugins/kibana/public/local_application_service/_local_application_service.scss
new file mode 100644
index 00000000000000..33a6100c439759
--- /dev/null
+++ b/src/legacy/core_plugins/kibana/public/local_application_service/_local_application_service.scss
@@ -0,0 +1,5 @@
+.kbnLocalApplicationWrapper {
+ display: flex;
+ flex-direction: column;
+ flex-grow: 1;
+}
diff --git a/src/legacy/core_plugins/kibana/public/local_application_service/local_application_service.ts b/src/legacy/core_plugins/kibana/public/local_application_service/local_application_service.ts
index c09995caab6690..d52bec8304ff91 100644
--- a/src/legacy/core_plugins/kibana/public/local_application_service/local_application_service.ts
+++ b/src/legacy/core_plugins/kibana/public/local_application_service/local_application_service.ts
@@ -56,7 +56,7 @@ export class LocalApplicationService {
outerAngularWrapperRoute: true,
reloadOnSearch: false,
reloadOnUrl: false,
- template: `
`,
+ template: `
`,
controller($scope: IScope) {
const element = document.getElementById(wrapperElementId)!;
let unmountHandler: AppUnmount | null = null;
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/header/__jest__/__snapshots__/header.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/header/__jest__/__snapshots__/header.test.js.snap
index 11c41425a0bb53..f2fb17cdb0d602 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/header/__jest__/__snapshots__/header.test.js.snap
+++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/create_index_pattern_wizard/components/step_index_pattern/components/header/__jest__/__snapshots__/header.test.js.snap
@@ -78,11 +78,8 @@ exports[`Header should mark the input as invalid 1`] = `
labelType="label"
>
`;
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/__jest__/__snapshots__/table.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/__jest__/__snapshots__/table.test.js.snap
index 4716fb8f776338..2da4d84463b291 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/__jest__/__snapshots__/table.test.js.snap
+++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/scripted_fields_table/components/table/__jest__/__snapshots__/table.test.js.snap
@@ -76,6 +76,7 @@ exports[`Table should render normally 1`] = `
}
responsive={true}
sorting={true}
+ tableLayout="fixed"
/>
`;
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/__jest__/__snapshots__/add_filter.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/__jest__/__snapshots__/add_filter.test.js.snap
index 432c57d4f473d9..879ea555d33007 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/__jest__/__snapshots__/add_filter.test.js.snap
+++ b/src/legacy/core_plugins/kibana/public/management/sections/index_patterns/edit_index_pattern/source_filters_table/components/add_filter/__jest__/__snapshots__/add_filter.test.js.snap
@@ -6,9 +6,7 @@ exports[`AddFilter should ignore strings with just spaces 1`] = `
grow={10}
>
`;
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/__jest__/__snapshots__/objects_table.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/__jest__/__snapshots__/objects_table.test.js.snap
index 2aaa291f6122bf..4ba0fe480ac423 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/__jest__/__snapshots__/objects_table.test.js.snap
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/__jest__/__snapshots__/objects_table.test.js.snap
@@ -71,6 +71,7 @@ exports[`ObjectsTable delete should show a confirm modal 1`] = `
pagination={true}
responsive={true}
sorting={false}
+ tableLayout="fixed"
/>
`;
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/__jest__/__snapshots__/flyout.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/__jest__/__snapshots__/flyout.test.js.snap
index ace06e0420a7c2..34ce8394232edc 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/__jest__/__snapshots__/flyout.test.js.snap
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/flyout/__jest__/__snapshots__/flyout.test.js.snap
@@ -115,6 +115,7 @@ exports[`Flyout conflicts should allow conflict resolution 1`] = `
}
}
responsive={true}
+ tableLayout="fixed"
/>
@@ -445,6 +446,7 @@ exports[`Flyout legacy conflicts should allow conflict resolution 1`] = `
}
}
responsive={true}
+ tableLayout="fixed"
/>
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/relationships/__jest__/__snapshots__/relationships.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/relationships/__jest__/__snapshots__/relationships.test.js.snap
index 941a0ffded820a..c1241d5d7c1e50 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/relationships/__jest__/__snapshots__/relationships.test.js.snap
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/relationships/__jest__/__snapshots__/relationships.test.js.snap
@@ -154,6 +154,7 @@ exports[`Relationships should render dashboards normally 1`] = `
],
}
}
+ tableLayout="fixed"
/>
@@ -368,6 +369,7 @@ exports[`Relationships should render index patterns normally 1`] = `
],
}
}
+ tableLayout="fixed"
/>
@@ -533,6 +535,7 @@ exports[`Relationships should render searches normally 1`] = `
],
}
}
+ tableLayout="fixed"
/>
@@ -693,6 +696,7 @@ exports[`Relationships should render visualizations normally 1`] = `
],
}
}
+ tableLayout="fixed"
/>
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/__jest__/__snapshots__/table.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/__jest__/__snapshots__/table.test.js.snap
index daac04d07da28c..805131042f3852 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/__jest__/__snapshots__/table.test.js.snap
+++ b/src/legacy/core_plugins/kibana/public/management/sections/objects/components/objects_table/components/table/__jest__/__snapshots__/table.test.js.snap
@@ -203,6 +203,7 @@ exports[`Table prevents saved objects from being deleted 1`] = `
"onSelectionChange": [Function],
}
}
+ tableLayout="fixed"
/>
@@ -410,6 +411,7 @@ exports[`Table should render normally 1`] = `
"onSelectionChange": [Function],
}
}
+ tableLayout="fixed"
/>
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/__snapshots__/advanced_settings.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/settings/__snapshots__/advanced_settings.test.js.snap
index 10d165d0d69c46..eef8f3fc93d90f 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/settings/__snapshots__/advanced_settings.test.js.snap
+++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/__snapshots__/advanced_settings.test.js.snap
@@ -60,6 +60,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"defVal": Array [
"default_value",
],
+ "deprecation": undefined,
"description": "Description for Test array setting",
"displayName": "Test array setting",
"isCustom": undefined,
@@ -79,6 +80,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"elasticsearch",
],
"defVal": true,
+ "deprecation": undefined,
"description": "Description for Test boolean setting",
"displayName": "Test boolean setting",
"isCustom": undefined,
@@ -100,6 +102,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"general",
],
"defVal": null,
+ "deprecation": undefined,
"description": "Description for Test custom string setting",
"displayName": "Test custom string setting",
"isCustom": undefined,
@@ -119,6 +122,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"general",
],
"defVal": null,
+ "deprecation": undefined,
"description": "Description for Test image setting",
"displayName": "Test image setting",
"isCustom": undefined,
@@ -140,6 +144,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"defVal": "{
\\"foo\\": \\"bar\\"
}",
+ "deprecation": undefined,
"description": "Description for overridden json",
"displayName": "An overridden json",
"isCustom": undefined,
@@ -159,6 +164,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"general",
],
"defVal": 1234,
+ "deprecation": undefined,
"description": "Description for overridden number",
"displayName": "An overridden number",
"isCustom": undefined,
@@ -178,6 +184,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"general",
],
"defVal": "orange",
+ "deprecation": undefined,
"description": "Description for overridden select setting",
"displayName": "Test overridden select setting",
"isCustom": undefined,
@@ -201,6 +208,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"general",
],
"defVal": "foo",
+ "deprecation": undefined,
"description": "Description for overridden string",
"displayName": "An overridden string",
"isCustom": undefined,
@@ -220,6 +228,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"general",
],
"defVal": "{\\"foo\\": \\"bar\\"}",
+ "deprecation": undefined,
"description": "Description for Test json setting",
"displayName": "Test json setting",
"isCustom": undefined,
@@ -239,6 +248,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"general",
],
"defVal": "",
+ "deprecation": undefined,
"description": "Description for Test markdown setting",
"displayName": "Test markdown setting",
"isCustom": undefined,
@@ -258,6 +268,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"general",
],
"defVal": 5,
+ "deprecation": undefined,
"description": "Description for Test number setting",
"displayName": "Test number setting",
"isCustom": undefined,
@@ -277,6 +288,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"general",
],
"defVal": "orange",
+ "deprecation": undefined,
"description": "Description for Test select setting",
"displayName": "Test select setting",
"isCustom": undefined,
@@ -300,6 +312,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"general",
],
"defVal": null,
+ "deprecation": undefined,
"description": "Description for Test string setting",
"displayName": "Test string setting",
"isCustom": undefined,
@@ -345,6 +358,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"defVal": Array [
"default_value",
],
+ "deprecation": undefined,
"description": "Description for Test array setting",
"displayName": "Test array setting",
"isCustom": undefined,
@@ -364,6 +378,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"elasticsearch",
],
"defVal": true,
+ "deprecation": undefined,
"description": "Description for Test boolean setting",
"displayName": "Test boolean setting",
"isCustom": undefined,
@@ -385,6 +400,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"general",
],
"defVal": null,
+ "deprecation": undefined,
"description": "Description for Test custom string setting",
"displayName": "Test custom string setting",
"isCustom": undefined,
@@ -404,6 +420,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"general",
],
"defVal": null,
+ "deprecation": undefined,
"description": "Description for Test image setting",
"displayName": "Test image setting",
"isCustom": undefined,
@@ -425,6 +442,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"defVal": "{
\\"foo\\": \\"bar\\"
}",
+ "deprecation": undefined,
"description": "Description for overridden json",
"displayName": "An overridden json",
"isCustom": undefined,
@@ -444,6 +462,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"general",
],
"defVal": 1234,
+ "deprecation": undefined,
"description": "Description for overridden number",
"displayName": "An overridden number",
"isCustom": undefined,
@@ -463,6 +482,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"general",
],
"defVal": "orange",
+ "deprecation": undefined,
"description": "Description for overridden select setting",
"displayName": "Test overridden select setting",
"isCustom": undefined,
@@ -486,6 +506,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"general",
],
"defVal": "foo",
+ "deprecation": undefined,
"description": "Description for overridden string",
"displayName": "An overridden string",
"isCustom": undefined,
@@ -505,6 +526,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"general",
],
"defVal": "{\\"foo\\": \\"bar\\"}",
+ "deprecation": undefined,
"description": "Description for Test json setting",
"displayName": "Test json setting",
"isCustom": undefined,
@@ -524,6 +546,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"general",
],
"defVal": "",
+ "deprecation": undefined,
"description": "Description for Test markdown setting",
"displayName": "Test markdown setting",
"isCustom": undefined,
@@ -543,6 +566,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"general",
],
"defVal": 5,
+ "deprecation": undefined,
"description": "Description for Test number setting",
"displayName": "Test number setting",
"isCustom": undefined,
@@ -562,6 +586,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"general",
],
"defVal": "orange",
+ "deprecation": undefined,
"description": "Description for Test select setting",
"displayName": "Test select setting",
"isCustom": undefined,
@@ -585,6 +610,7 @@ exports[`AdvancedSettings should render normally 1`] = `
"general",
],
"defVal": null,
+ "deprecation": undefined,
"description": "Description for Test string setting",
"displayName": "Test string setting",
"isCustom": undefined,
@@ -705,6 +731,7 @@ exports[`AdvancedSettings should render read-only when saving is disabled 1`] =
"general",
],
"defVal": null,
+ "deprecation": undefined,
"description": "Description for Test string setting",
"displayName": "Test string setting",
"isCustom": undefined,
@@ -748,6 +775,7 @@ exports[`AdvancedSettings should render read-only when saving is disabled 1`] =
"general",
],
"defVal": null,
+ "deprecation": undefined,
"description": "Description for Test string setting",
"displayName": "Test string setting",
"isCustom": undefined,
@@ -886,6 +914,7 @@ exports[`AdvancedSettings should render specific setting if given setting key 1`
"general",
],
"defVal": null,
+ "deprecation": undefined,
"description": "Description for Test string setting",
"displayName": "Test string setting",
"isCustom": undefined,
@@ -929,6 +958,7 @@ exports[`AdvancedSettings should render specific setting if given setting key 1`
"general",
],
"defVal": null,
+ "deprecation": undefined,
"description": "Description for Test string setting",
"displayName": "Test string setting",
"isCustom": undefined,
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/__snapshots__/field.test.js.snap b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/__snapshots__/field.test.js.snap
index ae168e76d359b0..f4d20b45658802 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/__snapshots__/field.test.js.snap
+++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/components/field/__snapshots__/field.test.js.snap
@@ -50,10 +50,8 @@ exports[`Field for array setting should render as read only if saving is disable
>
+
+ {
+ window.open(links.management[setting.deprecation.docLinksKey], '_blank');
+ }}
+ onClickAriaLabel={i18n.translate(
+ 'kbn.management.settings.field.deprecationClickAreaLabel',
+ {
+ defaultMessage: 'Click to view deprecation documentation for {settingName}.',
+ values: {
+ settingName: setting.name,
+ },
+ }
+ )}
+ >
+ Deprecated
+
+
+
+ >
+ );
+ }
if (React.isValidElement(setting.description)) {
description = setting.description;
@@ -582,6 +615,7 @@ export class Field extends PureComponent {
return (
+ {deprecation}
{description}
{this.renderDefaultValue(setting)}
diff --git a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/to_editable_config.js b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/to_editable_config.js
index bb561cbe042121..6efb89cfba2b25 100644
--- a/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/to_editable_config.js
+++ b/src/legacy/core_plugins/kibana/public/management/sections/settings/lib/to_editable_config.js
@@ -43,6 +43,7 @@ export function toEditableConfig({ def, name, value, isCustom, isOverridden }) {
defVal: def.value,
type: getValType(def, value),
description: def.description,
+ deprecation: def.deprecation,
validation:
def.validation && def.validation.regexString
? {
diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/application.ts b/src/legacy/core_plugins/kibana/public/visualize/np_ready/application.ts
index dcd68a26743ab5..222b0357089767 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/application.ts
+++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/application.ts
@@ -63,9 +63,8 @@ export const renderApp = async (
return () => $injector.get('$rootScope').$destroy();
};
-const mainTemplate = (basePath: string) => `
+const mainTemplate = (basePath: string) => `
`;
@@ -75,7 +74,7 @@ const thirdPartyAngularDependencies = ['ngSanitize', 'ngRoute', 'react'];
function mountVisualizeApp(appBasePath: string, element: HTMLElement) {
const mountpoint = document.createElement('div');
- mountpoint.setAttribute('style', 'height: 100%');
+ mountpoint.setAttribute('class', 'kbnLocalApplicationWrapper');
mountpoint.innerHTML = mainTemplate(appBasePath);
// bootstrap angular into detached element and attach it later to
// make angular-within-angular possible
diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/wizard/__snapshots__/new_vis_modal.test.tsx.snap b/src/legacy/core_plugins/kibana/public/visualize/np_ready/wizard/__snapshots__/new_vis_modal.test.tsx.snap
index 0b44c7dc4e8603..c75fd2096feab7 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/wizard/__snapshots__/new_vis_modal.test.tsx.snap
+++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/wizard/__snapshots__/new_vis_modal.test.tsx.snap
@@ -234,6 +234,26 @@ exports[`NewVisModal filter for visualization types should render as expected 1`
/>
+
+
+
+
+
@@ -565,6 +585,26 @@ exports[`NewVisModal filter for visualization types should render as expected 1`
/>
+
+
+
+
+
@@ -835,6 +875,26 @@ exports[`NewVisModal filter for visualization types should render as expected 1`
/>
+
+
+
+
+
@@ -1139,12 +1199,18 @@ exports[`NewVisModal filter for visualization types should render as expected 1`
data-test-subj="filterVisType"
fullWidth={true}
incremental={false}
+ isClearable={true}
isLoading={false}
onChange={[Function]}
placeholder="Filter"
value="with"
>
@@ -1209,6 +1280,50 @@ exports[`NewVisModal filter for visualization types should render as expected 1`
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1594,7 +1709,7 @@ exports[`NewVisModal filter for visualization types should render as expected 1`
/>
@@ -2775,12 +2890,14 @@ exports[`NewVisModal should render as expected 1`] = `
data-test-subj="filterVisType"
fullWidth={true}
incremental={false}
+ isClearable={true}
isLoading={false}
onChange={[Function]}
placeholder="Filter"
value=""
>
@@ -3218,7 +3336,7 @@ exports[`NewVisModal should render as expected 1`] = `
/>
diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/wizard/type_selection/new_vis_help.test.tsx b/src/legacy/core_plugins/kibana/public/visualize/np_ready/wizard/type_selection/new_vis_help.test.tsx
index 3093499a030c8d..a33a82c252fb32 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/wizard/type_selection/new_vis_help.test.tsx
+++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/wizard/type_selection/new_vis_help.test.tsx
@@ -41,7 +41,7 @@ describe('NewVisHelp', () => {
stage: 'production',
},
]}
- addBasePath={(url: string) => `testbasepath${url}`}
+ onPromotionClicked={() => {}}
/>
)
).toMatchInlineSnapshot(`
@@ -60,9 +60,9 @@ describe('NewVisHelp', () => {
Do it now!
diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/wizard/type_selection/new_vis_help.tsx b/src/legacy/core_plugins/kibana/public/visualize/np_ready/wizard/type_selection/new_vis_help.tsx
index 107cbc0e754b51..2f7effb7a33c88 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/wizard/type_selection/new_vis_help.tsx
+++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/wizard/type_selection/new_vis_help.tsx
@@ -21,10 +21,11 @@ import { FormattedMessage } from '@kbn/i18n/react';
import React, { Fragment } from 'react';
import { EuiText, EuiButton } from '@elastic/eui';
import { VisTypeAliasListEntry } from './type_selection';
+import { VisTypeAlias } from '../../../../../../visualizations/public';
interface Props {
promotedTypes: VisTypeAliasListEntry[];
- addBasePath: (path: string) => string;
+ onPromotionClicked: (visType: VisTypeAlias) => void;
}
export function NewVisHelp(props: Props) {
@@ -42,7 +43,7 @@ export function NewVisHelp(props: Props) {
{t.promotion!.description}
props.onPromotionClicked(t)}
fill
size="s"
iconType="popout"
diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/wizard/type_selection/type_selection.tsx b/src/legacy/core_plugins/kibana/public/visualize/np_ready/wizard/type_selection/type_selection.tsx
index 28cafde45a7148..44da7cc8f2c450 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/wizard/type_selection/type_selection.tsx
+++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/wizard/type_selection/type_selection.tsx
@@ -154,7 +154,7 @@ class TypeSelection extends React.Component
t.promotion)}
- addBasePath={this.props.addBasePath}
+ onPromotionClicked={this.props.onVisTypeSelected}
/>
)}
diff --git a/src/legacy/core_plugins/kibana/public/visualize_embeddable/visualize_embeddable.ts b/src/legacy/core_plugins/kibana/public/visualize_embeddable/visualize_embeddable.ts
index fc91742c53cca5..b7a3a0f000d720 100644
--- a/src/legacy/core_plugins/kibana/public/visualize_embeddable/visualize_embeddable.ts
+++ b/src/legacy/core_plugins/kibana/public/visualize_embeddable/visualize_embeddable.ts
@@ -379,6 +379,7 @@ export class VisualizeEmbeddable extends Embeddable
`;
diff --git a/src/legacy/core_plugins/tests_bundle/tests_entry_template.js b/src/legacy/core_plugins/tests_bundle/tests_entry_template.js
index 02b1f5fec9c199..2f8a2264530d57 100644
--- a/src/legacy/core_plugins/tests_bundle/tests_entry_template.js
+++ b/src/legacy/core_plugins/tests_bundle/tests_entry_template.js
@@ -29,16 +29,7 @@ export const createTestEntryTemplate = defaultUiSettings => bundle => `
*
*/
-// import global polyfills before everything else
-import 'core-js/stable';
-import 'regenerator-runtime/runtime';
-import 'custom-event-polyfill';
-import 'whatwg-fetch';
-import 'abortcontroller-polyfill';
-import 'childnode-remove-polyfill';
import fetchMock from 'fetch-mock/es5/client';
-import Symbol_observable from 'symbol-observable';
-
import { CoreSystem } from '__kibanaCore__';
// Fake uiCapabilities returned to Core in browser tests
diff --git a/src/legacy/core_plugins/vis_type_timeseries/index.ts b/src/legacy/core_plugins/vis_type_timeseries/index.ts
index 9ca14b28e19b2a..a502bb174bc997 100644
--- a/src/legacy/core_plugins/vis_type_timeseries/index.ts
+++ b/src/legacy/core_plugins/vis_type_timeseries/index.ts
@@ -32,6 +32,20 @@ const metricsPluginInitializer: LegacyPluginInitializer = ({ Plugin }: LegacyPlu
styleSheetPaths: resolve(__dirname, 'public/index.scss'),
hacks: [resolve(__dirname, 'public/legacy')],
injectDefaultVars: server => ({}),
+ mappings: {
+ 'tsvb-validation-telemetry': {
+ properties: {
+ failedRequests: {
+ type: 'long',
+ },
+ },
+ },
+ },
+ savedObjectSchemas: {
+ 'tsvb-validation-telemetry': {
+ isNamespaceAgnostic: true,
+ },
+ },
},
init: (server: Legacy.Server) => {
const visTypeTimeSeriesPlugin = server.newPlatform.setup.plugins
diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/components/splits/__snapshots__/terms.test.js.snap b/src/legacy/core_plugins/vis_type_timeseries/public/components/splits/__snapshots__/terms.test.js.snap
index ffd4d08204a7e0..654e7d9da4dcaa 100644
--- a/src/legacy/core_plugins/vis_type_timeseries/public/components/splits/__snapshots__/terms.test.js.snap
+++ b/src/legacy/core_plugins/vis_type_timeseries/public/components/splits/__snapshots__/terms.test.js.snap
@@ -87,9 +87,6 @@ exports[`src/legacy/core_plugins/metrics/public/components/splits/terms.test.js
labelType="label"
>
@@ -112,9 +109,6 @@ exports[`src/legacy/core_plugins/metrics/public/components/splits/terms.test.js
labelType="label"
>
diff --git a/src/legacy/core_plugins/vis_type_timeseries/public/metrics_fn.ts b/src/legacy/core_plugins/vis_type_timeseries/public/metrics_fn.ts
index 8740f84dab3b9e..225d81b71b8e08 100644
--- a/src/legacy/core_plugins/vis_type_timeseries/public/metrics_fn.ts
+++ b/src/legacy/core_plugins/vis_type_timeseries/public/metrics_fn.ts
@@ -31,6 +31,7 @@ type Context = KibanaContext | null;
interface Arguments {
params: string;
uiState: string;
+ savedObjectId: string | null;
}
type VisParams = Required;
@@ -64,10 +65,16 @@ export const createMetricsFn = (): ExpressionFunction {
+export const metricsRequestHandler = async ({
+ uiState,
+ timeRange,
+ filters,
+ query,
+ visParams,
+ savedObjectId,
+}) => {
const config = getUISettings();
const timezone = timezoneProvider(config)();
const uiStateObj = uiState.get(visParams.type, {});
@@ -49,6 +56,7 @@ export const metricsRequestHandler = async ({ uiState, timeRange, filters, query
filters,
panels: [visParams],
state: uiStateObj,
+ savedObjectId: savedObjectId || 'unsaved',
}),
});
diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/init.ts b/src/legacy/core_plugins/vis_type_timeseries/server/init.ts
index 7b42ae8098016d..ae6eebc00fc1ba 100644
--- a/src/legacy/core_plugins/vis_type_timeseries/server/init.ts
+++ b/src/legacy/core_plugins/vis_type_timeseries/server/init.ts
@@ -26,12 +26,17 @@ import { SearchStrategiesRegister } from './lib/search_strategies/search_strateg
// @ts-ignore
import { getVisData } from './lib/get_vis_data';
import { Framework } from '../../../../plugins/vis_type_timeseries/server';
+import { ValidationTelemetryServiceSetup } from '../../../../plugins/vis_type_timeseries/server';
-export const init = async (framework: Framework, __LEGACY: any) => {
+export const init = async (
+ framework: Framework,
+ __LEGACY: any,
+ validationTelemetry: ValidationTelemetryServiceSetup
+) => {
const { core } = framework;
const router = core.http.createRouter();
- visDataRoutes(router, framework);
+ visDataRoutes(router, framework, validationTelemetry);
// [LEGACY_TODO]
fieldsRoutes(__LEGACY.server);
diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/routes/post_vis_schema.ts b/src/legacy/core_plugins/vis_type_timeseries/server/routes/post_vis_schema.ts
new file mode 100644
index 00000000000000..3aca50b5b4710f
--- /dev/null
+++ b/src/legacy/core_plugins/vis_type_timeseries/server/routes/post_vis_schema.ts
@@ -0,0 +1,247 @@
+/*
+ * 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 Joi from 'joi';
+const stringOptionalNullable = Joi.string()
+ .allow('', null)
+ .optional();
+const stringRequired = Joi.string()
+ .allow('')
+ .required();
+const arrayNullable = Joi.array().allow(null);
+const numberIntegerOptional = Joi.number()
+ .integer()
+ .optional();
+const numberIntegerRequired = Joi.number()
+ .integer()
+ .required();
+const numberOptional = Joi.number().optional();
+const numberRequired = Joi.number().required();
+const queryObject = Joi.object({
+ language: Joi.string().allow(''),
+ query: Joi.string().allow(''),
+});
+
+const annotationsItems = Joi.object({
+ color: stringOptionalNullable,
+ fields: stringOptionalNullable,
+ hidden: Joi.boolean().optional(),
+ icon: stringOptionalNullable,
+ id: stringOptionalNullable,
+ ignore_global_filters: numberIntegerOptional,
+ ignore_panel_filters: numberIntegerOptional,
+ index_pattern: stringOptionalNullable,
+ query_string: queryObject.optional(),
+ template: stringOptionalNullable,
+ time_field: stringOptionalNullable,
+});
+
+const backgroundColorRulesItems = Joi.object({
+ value: Joi.number()
+ .allow(null)
+ .optional(),
+ id: stringOptionalNullable,
+ background_color: stringOptionalNullable,
+ color: stringOptionalNullable,
+});
+
+const gaugeColorRulesItems = Joi.object({
+ gauge: stringOptionalNullable,
+ id: stringOptionalNullable,
+ operator: stringOptionalNullable,
+ value: Joi.number(),
+});
+const metricsItems = Joi.object({
+ field: stringOptionalNullable,
+ id: stringRequired,
+ metric_agg: stringOptionalNullable,
+ numerator: stringOptionalNullable,
+ denominator: stringOptionalNullable,
+ sigma: stringOptionalNullable,
+ function: stringOptionalNullable,
+ script: stringOptionalNullable,
+ variables: Joi.array()
+ .items(
+ Joi.object({
+ field: stringOptionalNullable,
+ id: stringRequired,
+ name: stringOptionalNullable,
+ })
+ )
+ .optional(),
+ type: stringRequired,
+ value: stringOptionalNullable,
+ values: Joi.array()
+ .items(Joi.string().allow('', null))
+ .allow(null)
+ .optional(),
+});
+
+const splitFiltersItems = Joi.object({
+ id: stringOptionalNullable,
+ color: stringOptionalNullable,
+ filter: Joi.object({
+ language: Joi.string().allow(''),
+ query: Joi.string().allow(''),
+ }).optional(),
+ label: stringOptionalNullable,
+});
+
+const seriesItems = Joi.object({
+ aggregate_by: stringOptionalNullable,
+ aggregate_function: stringOptionalNullable,
+ axis_position: stringRequired,
+ axis_max: stringOptionalNullable,
+ axis_min: stringOptionalNullable,
+ chart_type: stringRequired,
+ color: stringRequired,
+ color_rules: Joi.array()
+ .items(
+ Joi.object({
+ value: numberOptional,
+ id: stringRequired,
+ text: stringOptionalNullable,
+ operator: stringOptionalNullable,
+ })
+ )
+ .optional(),
+ fill: numberOptional,
+ filter: Joi.object({
+ query: stringRequired,
+ language: stringOptionalNullable,
+ }).optional(),
+ formatter: stringRequired,
+ hide_in_legend: numberIntegerOptional,
+ hidden: Joi.boolean().optional(),
+ id: stringRequired,
+ label: stringOptionalNullable,
+ line_width: numberOptional,
+ metrics: Joi.array().items(metricsItems),
+ offset_time: stringOptionalNullable,
+ override_index_pattern: numberOptional,
+ point_size: numberRequired,
+ separate_axis: numberIntegerOptional,
+ seperate_axis: numberIntegerOptional,
+ series_index_pattern: stringOptionalNullable,
+ series_time_field: stringOptionalNullable,
+ series_interval: stringOptionalNullable,
+ series_drop_last_bucket: numberIntegerOptional,
+ split_color_mode: stringOptionalNullable,
+ split_filters: Joi.array()
+ .items(splitFiltersItems)
+ .optional(),
+ split_mode: stringRequired,
+ stacked: stringRequired,
+ steps: numberIntegerOptional,
+ terms_field: stringOptionalNullable,
+ terms_order_by: stringOptionalNullable,
+ terms_size: stringOptionalNullable,
+ terms_direction: stringOptionalNullable,
+ terms_include: stringOptionalNullable,
+ terms_exclude: stringOptionalNullable,
+ time_range_mode: stringOptionalNullable,
+ trend_arrows: numberOptional,
+ type: stringOptionalNullable,
+ value_template: stringOptionalNullable,
+ var_name: stringOptionalNullable,
+});
+
+export const visPayloadSchema = Joi.object({
+ filters: arrayNullable,
+ panels: Joi.array().items(
+ Joi.object({
+ annotations: Joi.array()
+ .items(annotationsItems)
+ .optional(),
+ axis_formatter: stringRequired,
+ axis_position: stringRequired,
+ axis_scale: stringRequired,
+ axis_min: stringOptionalNullable,
+ axis_max: stringOptionalNullable,
+ bar_color_rules: arrayNullable.optional(),
+ background_color: stringOptionalNullable,
+ background_color_rules: Joi.array()
+ .items(backgroundColorRulesItems)
+ .optional(),
+ default_index_pattern: stringOptionalNullable,
+ default_timefield: stringOptionalNullable,
+ drilldown_url: stringOptionalNullable,
+ drop_last_bucket: numberIntegerOptional,
+ filter: Joi.alternatives(
+ stringOptionalNullable,
+ Joi.object({
+ language: stringOptionalNullable,
+ query: stringOptionalNullable,
+ })
+ ),
+ gauge_color_rules: Joi.array()
+ .items(gaugeColorRulesItems)
+ .optional(),
+ gauge_width: [stringOptionalNullable, numberOptional],
+ gauge_inner_color: stringOptionalNullable,
+ gauge_inner_width: Joi.alternatives(stringOptionalNullable, numberIntegerOptional),
+ gauge_style: stringOptionalNullable,
+ gauge_max: stringOptionalNullable,
+ id: stringRequired,
+ ignore_global_filters: numberOptional,
+ ignore_global_filter: numberOptional,
+ index_pattern: stringRequired,
+ interval: stringRequired,
+ isModelInvalid: Joi.boolean().optional(),
+ legend_position: stringOptionalNullable,
+ markdown: stringOptionalNullable,
+ markdown_scrollbars: numberIntegerOptional,
+ markdown_openLinksInNewTab: numberIntegerOptional,
+ markdown_vertical_align: stringOptionalNullable,
+ markdown_less: stringOptionalNullable,
+ markdown_css: stringOptionalNullable,
+ pivot_id: stringOptionalNullable,
+ pivot_label: stringOptionalNullable,
+ pivot_type: stringOptionalNullable,
+ pivot_rows: stringOptionalNullable,
+ series: Joi.array()
+ .items(seriesItems)
+ .required(),
+ show_grid: numberIntegerRequired,
+ show_legend: numberIntegerRequired,
+ time_field: stringOptionalNullable,
+ time_range_mode: stringOptionalNullable,
+ type: stringRequired,
+ })
+ ),
+ // general
+ query: Joi.array()
+ .items(queryObject)
+ .allow(null)
+ .required(),
+ state: Joi.object({
+ sort: Joi.object({
+ column: stringRequired,
+ order: Joi.string()
+ .valid(['asc', 'desc'])
+ .required(),
+ }).optional(),
+ }).required(),
+ savedObjectId: Joi.string().optional(),
+ timerange: Joi.object({
+ timezone: stringRequired,
+ min: stringRequired,
+ max: stringRequired,
+ }).required(),
+});
diff --git a/src/legacy/core_plugins/vis_type_timeseries/server/routes/vis.js b/src/legacy/core_plugins/vis_type_timeseries/server/routes/vis.ts
similarity index 59%
rename from src/legacy/core_plugins/vis_type_timeseries/server/routes/vis.js
rename to src/legacy/core_plugins/vis_type_timeseries/server/routes/vis.ts
index d2ded81309ffab..32e87f5a3f666a 100644
--- a/src/legacy/core_plugins/vis_type_timeseries/server/routes/vis.js
+++ b/src/legacy/core_plugins/vis_type_timeseries/server/routes/vis.ts
@@ -17,12 +17,22 @@
* under the License.
*/
+import { IRouter } from 'kibana/server';
import { schema } from '@kbn/config-schema';
import { getVisData } from '../lib/get_vis_data';
+import { visPayloadSchema } from './post_vis_schema';
+import {
+ Framework,
+ ValidationTelemetryServiceSetup,
+} from '../../../../../plugins/vis_type_timeseries/server';
const escapeHatch = schema.object({}, { allowUnknowns: true });
-export const visDataRoutes = (router, framework) => {
+export const visDataRoutes = (
+ router: IRouter,
+ framework: Framework,
+ { logFailedValidation }: ValidationTelemetryServiceSetup
+) => {
router.post(
{
path: '/api/metrics/vis/data',
@@ -31,6 +41,16 @@ export const visDataRoutes = (router, framework) => {
},
},
async (requestContext, request, response) => {
+ const { error: validationError } = visPayloadSchema.validate(request.body);
+ if (validationError) {
+ logFailedValidation();
+ const savedObjectId =
+ (typeof request.body === 'object' && (request.body as any).savedObjectId) ||
+ 'unavailable';
+ framework.logger.warn(
+ `Request validation error: ${validationError.message} (saved object id: ${savedObjectId}). This most likely means your TSVB visualization contains outdated configuration. You can report this problem under https://github.com/elastic/kibana/issues/new?template=Bug_report.md`
+ );
+ }
try {
const results = await getVisData(requestContext, request.body, framework);
return response.ok({ body: results });
diff --git a/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_image_512.png b/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_image_512.png
index 44cd0d320931fa..cc28886794f035 100644
Binary files a/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_image_512.png and b/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_image_512.png differ
diff --git a/src/legacy/core_plugins/vis_type_vega/public/data_model/__tests__/vega_parser.js b/src/legacy/core_plugins/vis_type_vega/public/data_model/__tests__/vega_parser.js
index de2d9132214511..c442f8f17884af 100644
--- a/src/legacy/core_plugins/vis_type_vega/public/data_model/__tests__/vega_parser.js
+++ b/src/legacy/core_plugins/vis_type_vega/public/data_model/__tests__/vega_parser.js
@@ -53,7 +53,7 @@ describe(`VegaParser._setDefaultColors`, () => {
test({}, true, {
config: {
range: { category: { scheme: 'elastic' } },
- mark: { color: '#00B3A4' },
+ mark: { color: '#5BBAA0' },
},
})
);
@@ -63,15 +63,15 @@ describe(`VegaParser._setDefaultColors`, () => {
test({}, false, {
config: {
range: { category: { scheme: 'elastic' } },
- arc: { fill: '#00B3A4' },
- area: { fill: '#00B3A4' },
- line: { stroke: '#00B3A4' },
- path: { stroke: '#00B3A4' },
- rect: { fill: '#00B3A4' },
- rule: { stroke: '#00B3A4' },
- shape: { stroke: '#00B3A4' },
- symbol: { fill: '#00B3A4' },
- trail: { fill: '#00B3A4' },
+ arc: { fill: '#5BBAA0' },
+ area: { fill: '#5BBAA0' },
+ line: { stroke: '#5BBAA0' },
+ path: { stroke: '#5BBAA0' },
+ rect: { fill: '#5BBAA0' },
+ rule: { stroke: '#5BBAA0' },
+ shape: { stroke: '#5BBAA0' },
+ symbol: { fill: '#5BBAA0' },
+ trail: { fill: '#5BBAA0' },
},
})
);
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/build_pipeline.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/build_pipeline.ts
index cc2ab133941db5..ab1664d612b35e 100644
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/build_pipeline.ts
+++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/build_pipeline.ts
@@ -59,7 +59,12 @@ export interface Schemas {
[key: string]: any[] | undefined;
}
-type buildVisFunction = (visState: VisState, schemas: Schemas, uiState: any) => string;
+type buildVisFunction = (
+ visState: VisState,
+ schemas: Schemas,
+ uiState: any,
+ meta?: { savedObjectId?: string }
+) => string;
type buildVisConfigFunction = (schemas: Schemas, visParams?: VisParams) => VisParams;
interface BuildPipelineVisFunction {
@@ -248,11 +253,13 @@ export const buildPipelineVisFunction: BuildPipelineVisFunction = {
input_control_vis: visState => {
return `input_control_vis ${prepareJson('visConfig', visState.params)}`;
},
- metrics: (visState, schemas, uiState = {}) => {
+ metrics: (visState, schemas, uiState = {}, meta) => {
const paramsJson = prepareJson('params', visState.params);
const uiStateJson = prepareJson('uiState', uiState);
+ const savedObjectIdParam = prepareString('savedObjectId', meta?.savedObjectId);
- return `tsvb ${paramsJson} ${uiStateJson}`;
+ const params = [paramsJson, uiStateJson, savedObjectIdParam].filter(param => Boolean(param));
+ return `tsvb ${params.join(' ')}`;
},
timelion: visState => {
const expression = prepareString('expression', visState.params.expression);
@@ -488,6 +495,7 @@ export const buildPipeline = async (
params: {
searchSource: ISearchSource;
timeRange?: any;
+ savedObjectId?: string;
}
) => {
const { searchSource } = params;
@@ -521,7 +529,9 @@ export const buildPipeline = async (
const schemas = getSchemas(vis, params.timeRange);
if (buildPipelineVisFunction[vis.type.name]) {
- pipeline += buildPipelineVisFunction[vis.type.name](visState, schemas, uiState);
+ pipeline += buildPipelineVisFunction[vis.type.name](visState, schemas, uiState, {
+ savedObjectId: params.savedObjectId,
+ });
} else if (vislibCharts.includes(vis.type.name)) {
const visConfig = visState.params;
visConfig.dimensions = await buildVislibDimensions(vis, params);
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/bytes/__snapshots__/bytes.test.js.snap b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/bytes/__snapshots__/bytes.test.js.snap
index 463c1bfb975f57..1f77660c9784cb 100644
--- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/bytes/__snapshots__/bytes.test.js.snap
+++ b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/bytes/__snapshots__/bytes.test.js.snap
@@ -44,10 +44,7 @@ exports[`BytesFormatEditor should render normally 1`] = `
labelType="label"
>
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/color/__snapshots__/color.test.js.snap b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/color/__snapshots__/color.test.js.snap
index d7026df761d94a..7e49e93e4cc4fb 100644
--- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/color/__snapshots__/color.test.js.snap
+++ b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/color/__snapshots__/color.test.js.snap
@@ -75,6 +75,7 @@ exports[`ColorFormatEditor should render multiple colors 1`] = `
}
noItemsMessage="No items found"
responsive={true}
+ tableLayout="fixed"
/>
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/date_nanos/__snapshots__/date_nanos.test.js.snap b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/date_nanos/__snapshots__/date_nanos.test.js.snap
index 04d59640554fdb..cb570144fcee3f 100644
--- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/date_nanos/__snapshots__/date_nanos.test.js.snap
+++ b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/date_nanos/__snapshots__/date_nanos.test.js.snap
@@ -44,11 +44,8 @@ exports[`DateFormatEditor should render normally 1`] = `
labelType="label"
>
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.js.snap
index 9722a019864348..ef11d70926ad75 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.js.snap
@@ -20,11 +20,7 @@ exports[`DurationFormatEditor should render human readable output normally 1`] =
labelType="label"
>
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.js.snap
index fea665a918f064..30d1de270522ed 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.js.snap
@@ -44,10 +44,7 @@ exports[`PercentFormatEditor should render normally 1`] = `
labelType="label"
>
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/static_lookup/__snapshots__/static_lookup.test.js.snap b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/static_lookup/__snapshots__/static_lookup.test.js.snap
index 2891b99bba30cd..2bfb0bbd15013b 100644
--- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/static_lookup/__snapshots__/static_lookup.test.js.snap
+++ b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/static_lookup/__snapshots__/static_lookup.test.js.snap
@@ -59,6 +59,7 @@ exports[`StaticLookupFormatEditor should render multiple lookup entries and unkn
"maxWidth": "400px",
}
}
+ tableLayout="fixed"
/>
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.js.snap
index 4b246fecb81463..c727f54874db4d 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.js.snap
@@ -26,11 +26,7 @@ exports[`UrlFormatEditor should render label template help 1`] = `
labelType="label"
>
@@ -116,10 +109,7 @@ exports[`UrlFormatEditor should render label template help 1`] = `
labelType="label"
>
@@ -157,11 +147,7 @@ exports[`UrlFormatEditor should render normally 1`] = `
labelType="label"
>
@@ -247,10 +230,7 @@ exports[`UrlFormatEditor should render normally 1`] = `
labelType="label"
>
@@ -288,11 +268,7 @@ exports[`UrlFormatEditor should render url template help 1`] = `
labelType="label"
>
@@ -378,10 +351,7 @@ exports[`UrlFormatEditor should render url template help 1`] = `
labelType="label"
>
@@ -419,11 +389,7 @@ exports[`UrlFormatEditor should render width and height fields if image 1`] = `
labelType="label"
>
@@ -510,10 +473,7 @@ exports[`UrlFormatEditor should render width and height fields if image 1`] = `
labelType="label"
>
diff --git a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/url_template_flyout.test.js.snap b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/url_template_flyout.test.js.snap
index 39189caeedb320..849e307f7b5274 100644
--- a/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/url_template_flyout.test.js.snap
+++ b/src/legacy/ui/public/field_editor/components/field_format_editor/editors/url/__snapshots__/url_template_flyout.test.js.snap
@@ -110,6 +110,7 @@ exports[`UrlTemplateFlyout should render normally 1`] = `
}
noItemsMessage="No items found"
responsive={true}
+ tableLayout="fixed"
/>
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.js.snap
index 25cbbb7c8684b4..73a7c1141c6014 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.js.snap
@@ -54,6 +54,7 @@ exports[`FormatEditorSamples should render normally 1`] = `
}
noItemsMessage="No items found"
responsive={true}
+ tableLayout="fixed"
/>
`;
diff --git a/src/legacy/ui/public/field_editor/field_editor.test.js b/src/legacy/ui/public/field_editor/field_editor.test.js
index f811ad91627287..cf61b6140f42cc 100644
--- a/src/legacy/ui/public/field_editor/field_editor.test.js
+++ b/src/legacy/ui/public/field_editor/field_editor.test.js
@@ -50,9 +50,7 @@ jest.mock('@elastic/eui', () => ({
EuiText: 'eui-text',
EuiTextArea: 'eui-textArea',
htmlIdGenerator: () => 42,
- palettes: {
- euiPaletteColorBlind: { colors: ['red'] },
- },
+ euiPaletteColorBlind: () => ['red'],
}));
jest.mock('ui/scripting_languages', () => ({
diff --git a/src/legacy/ui/public/vis/editors/default/controls/__snapshots__/metric_agg.test.tsx.snap b/src/legacy/ui/public/vis/editors/default/controls/__snapshots__/metric_agg.test.tsx.snap
index a176295260c441..b51c25952580a8 100644
--- a/src/legacy/ui/public/vis/editors/default/controls/__snapshots__/metric_agg.test.tsx.snap
+++ b/src/legacy/ui/public/vis/editors/default/controls/__snapshots__/metric_agg.test.tsx.snap
@@ -16,9 +16,7 @@ exports[`MetricAggParamEditor should be rendered with default set of props 1`] =
compressed={true}
data-test-subj="visEditorSubAggMetric1"
fullWidth={true}
- hasNoInitialSelection={false}
isInvalid={false}
- isLoading={false}
onChange={[Function]}
options={
Array [
diff --git a/src/legacy/ui/public/vis/editors/default/controls/__snapshots__/top_aggregate.test.tsx.snap b/src/legacy/ui/public/vis/editors/default/controls/__snapshots__/top_aggregate.test.tsx.snap
index 74c952dbf059f2..b3a2c058de9760 100644
--- a/src/legacy/ui/public/vis/editors/default/controls/__snapshots__/top_aggregate.test.tsx.snap
+++ b/src/legacy/ui/public/vis/editors/default/controls/__snapshots__/top_aggregate.test.tsx.snap
@@ -31,9 +31,7 @@ exports[`TopAggregateParamEditor should init with the default set of props 1`] =
data-test-subj="visDefaultEditorAggregateWith"
disabled={false}
fullWidth={true}
- hasNoInitialSelection={false}
isInvalid={false}
- isLoading={false}
onBlur={[MockFunction]}
onChange={[Function]}
options={
diff --git a/src/legacy/ui/public/vislib/visualizations/point_series/_point_series.js b/src/legacy/ui/public/vislib/visualizations/point_series/_point_series.js
index b9f50b6d941e65..b882048a6b2699 100644
--- a/src/legacy/ui/public/vislib/visualizations/point_series/_point_series.js
+++ b/src/legacy/ui/public/vislib/visualizations/point_series/_point_series.js
@@ -18,14 +18,14 @@
*/
import _ from 'lodash';
-import { palettes } from '@elastic/eui/lib/services';
+import { euiPaletteColorBlind } from '@elastic/eui/lib/services';
const thresholdLineDefaults = {
show: false,
value: 10,
width: 1,
style: 'full',
- color: palettes.euiPaletteColorBlind.colors[9],
+ color: euiPaletteColorBlind()[9],
};
export class PointSeries {
diff --git a/src/legacy/ui/ui_bundles/app_entry_template.js b/src/legacy/ui/ui_bundles/app_entry_template.js
index f0ca97f473324d..a1c3a153a196cf 100644
--- a/src/legacy/ui/ui_bundles/app_entry_template.js
+++ b/src/legacy/ui/ui_bundles/app_entry_template.js
@@ -28,14 +28,6 @@ export const appEntryTemplate = bundle => `
* context: ${bundle.getContext()}
*/
-// import global polyfills
-import Symbol_observable from 'symbol-observable';
-import 'core-js/stable';
-import 'regenerator-runtime/runtime';
-import 'custom-event-polyfill';
-import 'whatwg-fetch';
-import 'abortcontroller-polyfill';
-import 'childnode-remove-polyfill';
${apmImport()}
import { i18n } from '@kbn/i18n';
import { CoreSystem } from '__kibanaCore__'
diff --git a/src/legacy/ui/ui_render/bootstrap/template.js.hbs b/src/legacy/ui/ui_render/bootstrap/template.js.hbs
index 85b6de26b95164..72dd97ff58642b 100644
--- a/src/legacy/ui/ui_render/bootstrap/template.js.hbs
+++ b/src/legacy/ui/ui_render/bootstrap/template.js.hbs
@@ -13,7 +13,10 @@ if (window.__kbnStrictCsp__ && window.__kbnCspNotEnforced__) {
window.onload = function () {
var files = [
- '{{dllBundlePath}}/vendors.bundle.dll.js',
+ '{{dllBundlePath}}/vendors_runtime.bundle.dll.js',
+ {{#each dllJsChunks}}
+ '{{this}}',
+ {{/each}}
'{{regularBundlePath}}/kbn-ui-shared-deps/{{sharedDepsFilename}}',
'{{regularBundlePath}}/commons.bundle.js',
'{{regularBundlePath}}/{{appId}}.bundle.js'
diff --git a/src/legacy/ui/ui_render/ui_render_mixin.js b/src/legacy/ui/ui_render/ui_render_mixin.js
index a935270d23fced..4158af19bd858a 100644
--- a/src/legacy/ui/ui_render/ui_render_mixin.js
+++ b/src/legacy/ui/ui_render/ui_render_mixin.js
@@ -26,6 +26,7 @@ import { AppBootstrap } from './bootstrap';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { fromRoot } from '../../../core/server/utils';
import { getApmConfig } from '../apm';
+import { DllCompiler } from '../../../optimize/dynamic_dll_plugin';
/**
* @typedef {import('../../server/kbn_server').default} KbnServer
@@ -103,8 +104,14 @@ export function uiRenderMixin(kbnServer, server, config) {
const basePath = config.get('server.basePath');
const regularBundlePath = `${basePath}/bundles`;
const dllBundlePath = `${basePath}/built_assets/dlls`;
+ const dllStyleChunks = DllCompiler.getRawDllConfig().chunks.map(
+ chunk => `${dllBundlePath}/vendors${chunk}.style.dll.css`
+ );
+ const dllJsChunks = DllCompiler.getRawDllConfig().chunks.map(
+ chunk => `${dllBundlePath}/vendors${chunk}.bundle.dll.js`
+ );
const styleSheetPaths = [
- `${dllBundlePath}/vendors.style.dll.css`,
+ ...dllStyleChunks,
...(darkMode
? [
`${basePath}/bundles/kbn-ui-shared-deps/${UiSharedDeps.darkCssDistFilename}`,
@@ -132,6 +139,7 @@ export function uiRenderMixin(kbnServer, server, config) {
appId: isCore ? 'core' : app.getId(),
regularBundlePath,
dllBundlePath,
+ dllJsChunks,
styleSheetPaths,
sharedDepsFilename: UiSharedDeps.distFilename,
},
diff --git a/src/optimize/dynamic_dll_plugin/dll_compiler.js b/src/optimize/dynamic_dll_plugin/dll_compiler.js
index 7d558367c032d7..9889c1f71c3bfb 100644
--- a/src/optimize/dynamic_dll_plugin/dll_compiler.js
+++ b/src/optimize/dynamic_dll_plugin/dll_compiler.js
@@ -23,6 +23,11 @@ import {
notInNodeModules,
inDllPluginPublic,
} from './dll_allowed_modules';
+import {
+ dllEntryFileContentArrayToString,
+ dllEntryFileContentStringToArray,
+ dllMergeAllEntryFilesContent,
+} from './dll_entry_template';
import { fromRoot } from '../../core/server/utils';
import { PUBLIC_PATH_PLACEHOLDER } from '../public_path_placeholder';
import fs from 'fs';
@@ -30,6 +35,8 @@ import webpack from 'webpack';
import { promisify } from 'util';
import path from 'path';
import del from 'del';
+import { chunk } from 'lodash';
+import seedrandom from 'seedrandom';
const readFileAsync = promisify(fs.readFile);
const mkdirAsync = promisify(fs.mkdir);
@@ -37,11 +44,17 @@ const accessAsync = promisify(fs.access);
const writeFileAsync = promisify(fs.writeFile);
export class DllCompiler {
- static getRawDllConfig(uiBundles = {}, babelLoaderCacheDir = '', threadLoaderPoolConfig = {}) {
+ static getRawDllConfig(
+ uiBundles = {},
+ babelLoaderCacheDir = '',
+ threadLoaderPoolConfig = {},
+ chunks = Array.from(Array(4).keys()).map(chunkN => `_${chunkN}`)
+ ) {
return {
uiBundles,
babelLoaderCacheDir,
threadLoaderPoolConfig,
+ chunks,
context: fromRoot('.'),
entryName: 'vendors',
dllName: '[name]',
@@ -66,13 +79,49 @@ export class DllCompiler {
}
async init() {
- await this.ensureEntryFileExists();
- await this.ensureManifestFileExists();
+ await this.ensureEntryFilesExists();
+ await this.ensureManifestFilesExists();
await this.ensureOutputPathExists();
}
- async upsertEntryFile(content) {
- await this.upsertFile(this.getEntryPath(), content);
+ seededShuffle(array) {
+ // Implementation based on https://github.com/TimothyGu/knuth-shuffle-seeded/blob/gh-pages/index.js#L46
+ let currentIndex;
+ let temporaryValue;
+ let randomIndex;
+ const rand = seedrandom('predictable', { global: false });
+
+ if (array.constructor !== Array) throw new Error('Input is not an array');
+ currentIndex = array.length;
+
+ // While there remain elements to shuffle...
+ while (0 !== currentIndex) {
+ // Pick a remaining element...
+ randomIndex = Math.floor(rand() * currentIndex--);
+
+ // And swap it with the current element.
+ temporaryValue = array[currentIndex];
+ array[currentIndex] = array[randomIndex];
+ array[randomIndex] = temporaryValue;
+ }
+
+ return array;
+ }
+
+ async upsertEntryFiles(content) {
+ const arrayContent = this.seededShuffle(dllEntryFileContentStringToArray(content));
+ const chunks = chunk(
+ arrayContent,
+ Math.ceil(arrayContent.length / this.rawDllConfig.chunks.length)
+ );
+ const entryPaths = this.getEntryPaths();
+
+ await Promise.all(
+ entryPaths.map(
+ async (entryPath, idx) =>
+ await this.upsertFile(entryPath, dllEntryFileContentArrayToString(chunks[idx]))
+ )
+ );
}
async upsertFile(filePath, content = '') {
@@ -80,38 +129,57 @@ export class DllCompiler {
await writeFileAsync(filePath, content, 'utf8');
}
- getDllPath() {
- return this.resolvePath(`${this.rawDllConfig.entryName}${this.rawDllConfig.dllExt}`);
+ getDllPaths() {
+ return this.rawDllConfig.chunks.map(chunk =>
+ this.resolvePath(`${this.rawDllConfig.entryName}${chunk}${this.rawDllConfig.dllExt}`)
+ );
}
- getEntryPath() {
- return this.resolvePath(`${this.rawDllConfig.entryName}${this.rawDllConfig.entryExt}`);
+ getEntryPaths() {
+ return this.rawDllConfig.chunks.map(chunk =>
+ this.resolvePath(`${this.rawDllConfig.entryName}${chunk}${this.rawDllConfig.entryExt}`)
+ );
}
- getManifestPath() {
- return this.resolvePath(`${this.rawDllConfig.entryName}${this.rawDllConfig.manifestExt}`);
+ getManifestPaths() {
+ return this.rawDllConfig.chunks.map(chunk =>
+ this.resolvePath(`${this.rawDllConfig.entryName}${chunk}${this.rawDllConfig.manifestExt}`)
+ );
}
- getStylePath() {
- return this.resolvePath(`${this.rawDllConfig.entryName}${this.rawDllConfig.styleExt}`);
+ getStylePaths() {
+ return this.rawDllConfig.chunks.map(chunk =>
+ this.resolvePath(`${this.rawDllConfig.entryName}${chunk}${this.rawDllConfig.styleExt}`)
+ );
}
- async ensureEntryFileExists() {
- await this.ensureFileExists(this.getEntryPath());
+ async ensureEntryFilesExists() {
+ const entryPaths = this.getEntryPaths();
+
+ await Promise.all(entryPaths.map(async entryPath => await this.ensureFileExists(entryPath)));
}
- async ensureManifestFileExists() {
- await this.ensureFileExists(
- this.getManifestPath(),
- JSON.stringify({
- name: this.rawDllConfig.entryName,
- content: {},
- })
+ async ensureManifestFilesExists() {
+ const manifestPaths = this.getManifestPaths();
+
+ await Promise.all(
+ manifestPaths.map(
+ async (manifestPath, idx) =>
+ await this.ensureFileExists(
+ manifestPath,
+ JSON.stringify({
+ name: `${this.rawDllConfig.entryName}${this.rawDllConfig.chunks[idx]}`,
+ content: {},
+ })
+ )
+ )
);
}
async ensureStyleFileExists() {
- await this.ensureFileExists(this.getStylePath());
+ const stylePaths = this.getStylePaths();
+
+ await Promise.all(stylePaths.map(async stylePath => await this.ensureFileExists(stylePath)));
}
async ensureFileExists(filePath, content) {
@@ -137,8 +205,10 @@ export class DllCompiler {
await this.ensurePathExists(this.rawDllConfig.outputPath);
}
- dllExistsSync() {
- return this.existsSync(this.getDllPath());
+ dllsExistsSync() {
+ const dllPaths = this.getDllPaths();
+
+ return dllPaths.every(dllPath => this.existsSync(dllPath));
}
existsSync(filePath) {
@@ -149,8 +219,16 @@ export class DllCompiler {
return path.resolve(this.rawDllConfig.outputPath, ...arguments);
}
- async readEntryFile() {
- return await this.readFile(this.getEntryPath());
+ async readEntryFiles() {
+ const entryPaths = this.getEntryPaths();
+
+ const entryFilesContent = await Promise.all(
+ entryPaths.map(async entryPath => await this.readFile(entryPath))
+ );
+
+ // merge all the module contents from entry files again into
+ // sorted single one
+ return dllMergeAllEntryFilesContent(entryFilesContent);
}
async readFile(filePath, content) {
@@ -160,7 +238,7 @@ export class DllCompiler {
async run(dllEntries) {
const dllConfig = this.dllConfigGenerator(this.rawDllConfig);
- await this.upsertEntryFile(dllEntries);
+ await this.upsertEntryFiles(dllEntries);
try {
this.logWithMetadata(
@@ -234,7 +312,7 @@ export class DllCompiler {
// ignore if this module represents the
// dll entry file
- if (module.resource === this.getEntryPath()) {
+ if (this.getEntryPaths().includes(module.resource)) {
return;
}
@@ -259,7 +337,6 @@ export class DllCompiler {
// node_module or no?
if (notInNodeModules(reason.module.resource)) {
notAllowedModules.push(module.resource);
- return;
}
});
}
diff --git a/src/optimize/dynamic_dll_plugin/dll_config_model.js b/src/optimize/dynamic_dll_plugin/dll_config_model.js
index ecf5def5aa6cac..c7ab2fe30dd141 100644
--- a/src/optimize/dynamic_dll_plugin/dll_config_model.js
+++ b/src/optimize/dynamic_dll_plugin/dll_config_model.js
@@ -140,6 +140,13 @@ function generateDLL(config) {
filename: dllStyleFilename,
}),
],
+ // Single runtime for the dll bundles which assures that common transient dependencies won't be evaluated twice.
+ // The module cache will be shared, even when module code may be duplicated across chunks.
+ optimization: {
+ runtimeChunk: {
+ name: 'vendors_runtime',
+ },
+ },
performance: {
// NOTE: we are disabling this as those hints
// are more tailored for the final bundles result
@@ -158,6 +165,7 @@ function extendRawConfig(rawConfig) {
const dllNoParseRules = rawConfig.uiBundles.getWebpackNoParseRules();
const dllDevMode = rawConfig.uiBundles.isDevMode();
const dllContext = rawConfig.context;
+ const dllChunks = rawConfig.chunks;
const dllEntry = {};
const dllEntryName = rawConfig.entryName;
const dllBundleName = rawConfig.dllName;
@@ -176,7 +184,12 @@ function extendRawConfig(rawConfig) {
const threadLoaderPoolConfig = rawConfig.threadLoaderPoolConfig;
// Create webpack entry object key with the provided dllEntryName
- dllEntry[dllEntryName] = [`${dllOutputPath}/${dllEntryName}${dllEntryExt}`];
+ dllChunks.reduce((dllEntryObj, chunk) => {
+ dllEntryObj[`${dllEntryName}${chunk}`] = [
+ `${dllOutputPath}/${dllEntryName}${chunk}${dllEntryExt}`,
+ ];
+ return dllEntryObj;
+ }, dllEntry);
// Export dll config map
return {
diff --git a/src/optimize/dynamic_dll_plugin/dll_entry_template.js b/src/optimize/dynamic_dll_plugin/dll_entry_template.js
index 584bf0c9e3d354..0c286896d0b714 100644
--- a/src/optimize/dynamic_dll_plugin/dll_entry_template.js
+++ b/src/optimize/dynamic_dll_plugin/dll_entry_template.js
@@ -23,3 +23,19 @@ export function dllEntryTemplate(requirePaths = []) {
.sort()
.join('\n');
}
+
+export function dllEntryFileContentStringToArray(content = '') {
+ return content.split('\n');
+}
+
+export function dllEntryFileContentArrayToString(content = []) {
+ return content.join('\n');
+}
+
+export function dllMergeAllEntryFilesContent(content = []) {
+ return content
+ .join('\n')
+ .split('\n')
+ .sort()
+ .join('\n');
+}
diff --git a/src/optimize/dynamic_dll_plugin/dynamic_dll_plugin.js b/src/optimize/dynamic_dll_plugin/dynamic_dll_plugin.js
index cb941d2ba56831..484c7dfbfd5957 100644
--- a/src/optimize/dynamic_dll_plugin/dynamic_dll_plugin.js
+++ b/src/optimize/dynamic_dll_plugin/dynamic_dll_plugin.js
@@ -44,7 +44,7 @@ export class DynamicDllPlugin {
async init() {
await this.dllCompiler.init();
- this.entryPaths = await this.dllCompiler.readEntryFile();
+ this.entryPaths = await this.dllCompiler.readEntryFiles();
}
apply(compiler) {
@@ -70,12 +70,14 @@ export class DynamicDllPlugin {
bindDllReferencePlugin(compiler) {
const rawDllConfig = this.dllCompiler.rawDllConfig;
const dllContext = rawDllConfig.context;
- const dllManifestPath = this.dllCompiler.getManifestPath();
+ const dllManifestPaths = this.dllCompiler.getManifestPaths();
- new webpack.DllReferencePlugin({
- context: dllContext,
- manifest: dllManifestPath,
- }).apply(compiler);
+ dllManifestPaths.forEach(dllChunkManifestPath => {
+ new webpack.DllReferencePlugin({
+ context: dllContext,
+ manifest: dllChunkManifestPath,
+ }).apply(compiler);
+ });
}
registerInitBasicHooks(compiler) {
@@ -192,7 +194,7 @@ export class DynamicDllPlugin {
// then will be set to false
compilation.needsDLLCompilation =
this.afterCompilationEntryPaths !== this.entryPaths ||
- !this.dllCompiler.dllExistsSync() ||
+ !this.dllCompiler.dllsExistsSync() ||
(this.isToForceDLLCreation() && this.performedCompilations === 0);
this.entryPaths = this.afterCompilationEntryPaths;
@@ -337,7 +339,9 @@ export class DynamicDllPlugin {
// We need to purge the cache into the inputFileSystem
// for every single built in previous compilation
// that we rely in next ones.
- mainCompiler.inputFileSystem.purge(this.dllCompiler.getManifestPath());
+ this.dllCompiler
+ .getManifestPaths()
+ .forEach(chunkDllManifestPath => mainCompiler.inputFileSystem.purge(chunkDllManifestPath));
this.performedCompilations++;
diff --git a/src/optimize/watch/watch_cache.ts b/src/optimize/watch/watch_cache.ts
index 15957210b3d43c..b6784c1734a174 100644
--- a/src/optimize/watch/watch_cache.ts
+++ b/src/optimize/watch/watch_cache.ts
@@ -170,22 +170,20 @@ export class WatchCache {
* very large folders (with 84K+ files) cause a stack overflow.
*/
async function recursiveDelete(directory: string) {
- const entries = await readdirAsync(directory, { withFileTypes: true });
- await Promise.all(
- entries.map(entry => {
- const absolutePath = path.join(directory, entry.name);
- const result = entry.isDirectory()
- ? recursiveDelete(absolutePath)
- : unlinkAsync(absolutePath);
-
- // Ignore errors, if the file or directory doesn't exist.
- return result.catch(e => {
- if (e.code !== 'ENOENT') {
- throw e;
- }
- });
- })
- );
-
- return rmdirAsync(directory);
+ try {
+ const entries = await readdirAsync(directory, { withFileTypes: true });
+
+ await Promise.all(
+ entries.map(entry => {
+ const absolutePath = path.join(directory, entry.name);
+ return entry.isDirectory() ? recursiveDelete(absolutePath) : unlinkAsync(absolutePath);
+ })
+ );
+
+ return rmdirAsync(directory);
+ } catch (error) {
+ if (error.code !== 'ENOENT') {
+ throw error;
+ }
+ }
}
diff --git a/src/plugins/data/public/ui/query_string_input/__snapshots__/language_switcher.test.tsx.snap b/src/plugins/data/public/ui/query_string_input/__snapshots__/language_switcher.test.tsx.snap
index 7ab7d7653eb5e3..4ec29ca409b80b 100644
--- a/src/plugins/data/public/ui/query_string_input/__snapshots__/language_switcher.test.tsx.snap
+++ b/src/plugins/data/public/ui/query_string_input/__snapshots__/language_switcher.test.tsx.snap
@@ -170,6 +170,9 @@ exports[`LanguageSwitcher should toggle off if language is lucene 1`] = `
"logstash": Object {
"base": "https://www.elastic.co/guide/en/logstash/mocked-test-branch",
},
+ "management": Object {
+ "kibanaSearchSettings": "https://www.elastic.co/guide/en/kibana/mocked-test-branch/advanced-options.html#kibana-search-settings",
+ },
"metricbeat": Object {
"base": "https://www.elastic.co/guide/en/beats/metricbeat/mocked-test-branch",
},
@@ -460,6 +463,9 @@ exports[`LanguageSwitcher should toggle on if language is kuery 1`] = `
"logstash": Object {
"base": "https://www.elastic.co/guide/en/logstash/mocked-test-branch",
},
+ "management": Object {
+ "kibanaSearchSettings": "https://www.elastic.co/guide/en/kibana/mocked-test-branch/advanced-options.html#kibana-search-settings",
+ },
"metricbeat": Object {
"base": "https://www.elastic.co/guide/en/beats/metricbeat/mocked-test-branch",
},
diff --git a/src/plugins/data/public/ui/query_string_input/__snapshots__/query_string_input.test.tsx.snap b/src/plugins/data/public/ui/query_string_input/__snapshots__/query_string_input.test.tsx.snap
index 6f5f9b39561876..4c8edd85eb559a 100644
--- a/src/plugins/data/public/ui/query_string_input/__snapshots__/query_string_input.test.tsx.snap
+++ b/src/plugins/data/public/ui/query_string_input/__snapshots__/query_string_input.test.tsx.snap
@@ -276,6 +276,9 @@ exports[`QueryStringInput Should disable autoFocus on EuiFieldText when disableA
"logstash": Object {
"base": "https://www.elastic.co/guide/en/logstash/mocked-test-branch",
},
+ "management": Object {
+ "kibanaSearchSettings": "https://www.elastic.co/guide/en/kibana/mocked-test-branch/advanced-options.html#kibana-search-settings",
+ },
"metricbeat": Object {
"base": "https://www.elastic.co/guide/en/beats/metricbeat/mocked-test-branch",
},
@@ -896,6 +899,9 @@ exports[`QueryStringInput Should disable autoFocus on EuiFieldText when disableA
"logstash": Object {
"base": "https://www.elastic.co/guide/en/logstash/mocked-test-branch",
},
+ "management": Object {
+ "kibanaSearchSettings": "https://www.elastic.co/guide/en/kibana/mocked-test-branch/advanced-options.html#kibana-search-settings",
+ },
"metricbeat": Object {
"base": "https://www.elastic.co/guide/en/beats/metricbeat/mocked-test-branch",
},
@@ -1070,11 +1076,9 @@ exports[`QueryStringInput Should disable autoFocus on EuiFieldText when disableA
aria-label="Start typing to search and filter the test page"
autoComplete="off"
autoFocus={false}
- compressed={false}
data-test-subj="queryInput"
fullWidth={true}
inputRef={[Function]}
- isLoading={false}
onChange={[Function]}
onClick={[Function]}
onKeyDown={[Function]}
@@ -1092,9 +1096,7 @@ exports[`QueryStringInput Should disable autoFocus on EuiFieldText when disableA
onSelectLanguage={[Function]}
/>
}
- compressed={false}
fullWidth={true}
- isLoading={false}
>
-
+
}
- compressed={false}
fullWidth={true}
- isLoading={false}
>
-
+
}
- compressed={false}
fullWidth={true}
- isLoading={false}
>
-
+
;
intl: InjectedIntl;
isLoading?: boolean;
- prepend?: React.ReactNode;
+ prepend?: React.ComponentProps['prepend'];
showQueryInput?: boolean;
showDatePicker?: boolean;
dateRangeFrom?: string;
diff --git a/src/plugins/data/public/ui/query_string_input/query_string_input.tsx b/src/plugins/data/public/ui/query_string_input/query_string_input.tsx
index 16b22a164f2f02..960a843f98ab90 100644
--- a/src/plugins/data/public/ui/query_string_input/query_string_input.tsx
+++ b/src/plugins/data/public/ui/query_string_input/query_string_input.tsx
@@ -58,7 +58,7 @@ interface Props {
query: Query;
disableAutoFocus?: boolean;
screenTitle?: string;
- prepend?: React.ReactNode;
+ prepend?: React.ComponentProps['prepend'];
persistedLog?: PersistedLog;
bubbleSubmitEvent?: boolean;
placeholder?: string;
diff --git a/src/plugins/kibana_react/public/field_icon/__snapshots__/field_icon.test.tsx.snap b/src/plugins/kibana_react/public/field_icon/__snapshots__/field_icon.test.tsx.snap
index 5abce10c5be61b..fb56bf0e4255ee 100644
--- a/src/plugins/kibana_react/public/field_icon/__snapshots__/field_icon.test.tsx.snap
+++ b/src/plugins/kibana_react/public/field_icon/__snapshots__/field_icon.test.tsx.snap
@@ -11,7 +11,7 @@ exports[`FieldIcon renders a blackwhite icon for a string 1`] = `
exports[`FieldIcon renders a colored icon for a number 1`] = `
@@ -20,7 +20,7 @@ exports[`FieldIcon renders a colored icon for a number 1`] = `
exports[`FieldIcon renders an icon for an unknown type 1`] = `
@@ -30,7 +30,7 @@ exports[`FieldIcon renders with className if provided 1`] = `
diff --git a/src/plugins/kibana_react/public/field_icon/field_icon.tsx b/src/plugins/kibana_react/public/field_icon/field_icon.tsx
index f9bdf3a25adaa0..0c5d2b0c24831c 100644
--- a/src/plugins/kibana_react/public/field_icon/field_icon.tsx
+++ b/src/plugins/kibana_react/public/field_icon/field_icon.tsx
@@ -17,7 +17,7 @@
* under the License.
*/
import React from 'react';
-import { palettes, EuiIcon } from '@elastic/eui';
+import { euiPaletteColorBlind, EuiIcon } from '@elastic/eui';
import { IconSize } from '@elastic/eui/src/components/icon/icon';
interface IconMapEntry {
@@ -43,7 +43,7 @@ interface FieldIconProps {
className?: string;
}
-const { colors } = palettes.euiPaletteColorBlind;
+const colors = euiPaletteColorBlind();
// defaultIcon => a unknown datatype
const defaultIcon = { icon: 'questionInCircle', color: colors[0] };
diff --git a/src/plugins/kibana_react/public/saved_objects/__snapshots__/saved_object_save_modal.test.tsx.snap b/src/plugins/kibana_react/public/saved_objects/__snapshots__/saved_object_save_modal.test.tsx.snap
index 978705a3ad0969..18f84f41d5d998 100644
--- a/src/plugins/kibana_react/public/saved_objects/__snapshots__/saved_object_save_modal.test.tsx.snap
+++ b/src/plugins/kibana_react/public/saved_objects/__snapshots__/saved_object_save_modal.test.tsx.snap
@@ -43,11 +43,9 @@ exports[`SavedObjectSaveModal should render matching snapshot 1`] = `
>
diff --git a/src/plugins/vis_type_timeseries/kibana.json b/src/plugins/vis_type_timeseries/kibana.json
index f9a368e85ed491..d77f4ac92da16f 100644
--- a/src/plugins/vis_type_timeseries/kibana.json
+++ b/src/plugins/vis_type_timeseries/kibana.json
@@ -2,5 +2,6 @@
"id": "metrics",
"version": "8.0.0",
"kibanaVersion": "kibana",
- "server": true
-}
\ No newline at end of file
+ "server": true,
+ "optionalPlugins": ["usageCollection"]
+}
diff --git a/src/plugins/vis_type_timeseries/server/index.ts b/src/plugins/vis_type_timeseries/server/index.ts
index 599726612a936a..dfb2394af237bf 100644
--- a/src/plugins/vis_type_timeseries/server/index.ts
+++ b/src/plugins/vis_type_timeseries/server/index.ts
@@ -30,6 +30,8 @@ export const config = {
export type VisTypeTimeseriesConfig = TypeOf;
+export { ValidationTelemetryServiceSetup } from './validation_telemetry';
+
export function plugin(initializerContext: PluginInitializerContext) {
return new VisTypeTimeseriesPlugin(initializerContext);
}
diff --git a/src/plugins/vis_type_timeseries/server/plugin.ts b/src/plugins/vis_type_timeseries/server/plugin.ts
index f508aa250454fa..dcd0cd500bbc31 100644
--- a/src/plugins/vis_type_timeseries/server/plugin.ts
+++ b/src/plugins/vis_type_timeseries/server/plugin.ts
@@ -35,11 +35,17 @@ import {
GetVisData,
GetVisDataOptions,
} from '../../../legacy/core_plugins/vis_type_timeseries/server';
+import { ValidationTelemetryService } from './validation_telemetry/validation_telemetry_service';
+import { UsageCollectionSetup } from '../../usage_collection/server';
export interface LegacySetup {
server: Server;
}
+interface VisTypeTimeseriesPluginSetupDependencies {
+ usageCollection?: UsageCollectionSetup;
+}
+
export interface VisTypeTimeseriesSetup {
/** @deprecated */
__legacy: {
@@ -61,11 +67,14 @@ export interface Framework {
}
export class VisTypeTimeseriesPlugin implements Plugin {
+ private validationTelementryService: ValidationTelemetryService;
+
constructor(private readonly initializerContext: PluginInitializerContext) {
this.initializerContext = initializerContext;
+ this.validationTelementryService = new ValidationTelemetryService();
}
- public setup(core: CoreSetup, plugins: any) {
+ public setup(core: CoreSetup, plugins: VisTypeTimeseriesPluginSetupDependencies) {
const logger = this.initializerContext.logger.get('visTypeTimeseries');
const config$ = this.initializerContext.config.create();
// Global config contains things like the ES shard timeout
@@ -82,8 +91,13 @@ export class VisTypeTimeseriesPlugin implements Plugin {
return {
__legacy: {
config$,
- registerLegacyAPI: once((__LEGACY: LegacySetup) => {
- init(framework, __LEGACY);
+ registerLegacyAPI: once(async (__LEGACY: LegacySetup) => {
+ const validationTelemetrySetup = await this.validationTelementryService.setup(core, {
+ ...plugins,
+ globalConfig$,
+ });
+
+ await init(framework, __LEGACY, validationTelemetrySetup);
}),
},
getVisData: async (requestContext: RequestHandlerContext, options: GetVisDataOptions) => {
diff --git a/src/plugins/vis_type_timeseries/server/validation_telemetry/index.ts b/src/plugins/vis_type_timeseries/server/validation_telemetry/index.ts
new file mode 100644
index 00000000000000..140f61fa2f3fda
--- /dev/null
+++ b/src/plugins/vis_type_timeseries/server/validation_telemetry/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 * from './validation_telemetry_service';
diff --git a/src/plugins/vis_type_timeseries/server/validation_telemetry/validation_telemetry_service.ts b/src/plugins/vis_type_timeseries/server/validation_telemetry/validation_telemetry_service.ts
new file mode 100644
index 00000000000000..136f5b9e5cfad8
--- /dev/null
+++ b/src/plugins/vis_type_timeseries/server/validation_telemetry/validation_telemetry_service.ts
@@ -0,0 +1,84 @@
+/*
+ * 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 { APICaller, CoreSetup, Plugin, PluginInitializerContext } from 'kibana/server';
+import { UsageCollectionSetup } from '../../../usage_collection/server';
+
+export interface ValidationTelemetryServiceSetup {
+ logFailedValidation: () => void;
+}
+
+export class ValidationTelemetryService implements Plugin {
+ private kibanaIndex: string = '';
+ async setup(
+ core: CoreSetup,
+ {
+ usageCollection,
+ globalConfig$,
+ }: {
+ usageCollection?: UsageCollectionSetup;
+ globalConfig$: PluginInitializerContext['config']['legacy']['globalConfig$'];
+ }
+ ) {
+ globalConfig$.subscribe(config => {
+ this.kibanaIndex = config.kibana.index;
+ });
+ if (usageCollection) {
+ usageCollection.registerCollector(
+ usageCollection.makeUsageCollector({
+ type: 'tsvb-validation',
+ isReady: () => this.kibanaIndex !== '',
+ fetch: async (callCluster: APICaller) => {
+ try {
+ const response = await callCluster('get', {
+ index: this.kibanaIndex,
+ id: 'tsvb-validation-telemetry:tsvb-validation-telemetry',
+ ignore: [404],
+ });
+ return {
+ failed_validations:
+ response?._source?.['tsvb-validation-telemetry']?.failedRequests || 0,
+ };
+ } catch (err) {
+ return {
+ failed_validations: 0,
+ };
+ }
+ },
+ })
+ );
+ }
+ const internalRepository = core.savedObjects.createInternalRepository();
+
+ return {
+ logFailedValidation: async () => {
+ try {
+ await internalRepository.incrementCounter(
+ 'tsvb-validation-telemetry',
+ 'tsvb-validation-telemetry',
+ 'failedRequests'
+ );
+ } catch (e) {
+ // swallow error, validation telemetry shouldn't fail anything else
+ }
+ },
+ };
+ }
+ start() {}
+}
diff --git a/tasks/config/karma.js b/tasks/config/karma.js
index 0acd452530b305..ec37277cae0f8c 100644
--- a/tasks/config/karma.js
+++ b/tasks/config/karma.js
@@ -21,6 +21,7 @@ import { dirname } from 'path';
import { times } from 'lodash';
import { makeJunitReportPath } from '@kbn/test';
import * as UiSharedDeps from '@kbn/ui-shared-deps';
+import { DllCompiler } from '../../src/optimize/dynamic_dll_plugin';
const TOTAL_CI_SHARDS = 4;
const ROOT = dirname(require.resolve('../../package.json'));
@@ -54,7 +55,10 @@ module.exports = function(grunt) {
'http://localhost:5610/test_bundle/built_css.css',
`http://localhost:5610/bundles/kbn-ui-shared-deps/${UiSharedDeps.distFilename}`,
- 'http://localhost:5610/built_assets/dlls/vendors.bundle.dll.js',
+ 'http://localhost:5610/built_assets/dlls/vendors_runtime.bundle.dll.js',
+ ...DllCompiler.getRawDllConfig().chunks.map(
+ chunk => `http://localhost:5610/built_assets/dlls/vendors${chunk}.bundle.dll.js`
+ ),
shardNum === undefined
? `http://localhost:5610/bundles/tests.bundle.js`
@@ -63,7 +67,9 @@ module.exports = function(grunt) {
// this causes tilemap tests to fail, probably because the eui styles haven't been
// included in the karma harness a long some time, if ever
// `http://localhost:5610/bundles/kbn-ui-shared-deps/${UiSharedDeps.lightCssDistFilename}`,
- 'http://localhost:5610/built_assets/dlls/vendors.style.dll.css',
+ ...DllCompiler.getRawDllConfig().chunks.map(
+ chunk => `http://localhost:5610/built_assets/dlls/vendors${chunk}.style.dll.css`
+ ),
'http://localhost:5610/bundles/tests.style.css',
];
}
diff --git a/test/functional/apps/context/_date_nanos_custom_timestamp.js b/test/functional/apps/context/_date_nanos_custom_timestamp.js
new file mode 100644
index 00000000000000..3901fa936e7195
--- /dev/null
+++ b/test/functional/apps/context/_date_nanos_custom_timestamp.js
@@ -0,0 +1,57 @@
+/*
+ * 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 expect from '@kbn/expect';
+
+const TEST_INDEX_PATTERN = 'date_nanos_custom_timestamp';
+const TEST_DEFAULT_CONTEXT_SIZE = 1;
+const TEST_STEP_SIZE = 3;
+
+export default function({ getService, getPageObjects }) {
+ const kibanaServer = getService('kibanaServer');
+ const docTable = getService('docTable');
+ const PageObjects = getPageObjects(['common', 'context', 'timePicker', 'discover']);
+ const esArchiver = getService('esArchiver');
+
+ describe('context view for date_nanos with custom timestamp', () => {
+ before(async function() {
+ await esArchiver.loadIfNeeded('date_nanos_custom');
+ await kibanaServer.uiSettings.replace({ defaultIndex: TEST_INDEX_PATTERN });
+ await kibanaServer.uiSettings.update({
+ 'context:defaultSize': `${TEST_DEFAULT_CONTEXT_SIZE}`,
+ 'context:step': `${TEST_STEP_SIZE}`,
+ });
+ });
+
+ after(function unloadMakelogs() {
+ return esArchiver.unload('date_nanos_custom');
+ });
+
+ it('displays predessors - anchor - successors in right order ', async function() {
+ await PageObjects.context.navigateTo(TEST_INDEX_PATTERN, '1');
+ const actualRowsText = await docTable.getRowsText();
+ const expectedRowsText = [
+ 'Oct 21, 2019 @ 08:30:04.828733000 -',
+ 'Oct 21, 2019 @ 00:30:04.828740000 -',
+ 'Oct 21, 2019 @ 00:30:04.828723000 -',
+ ];
+ expect(actualRowsText).to.eql(expectedRowsText);
+ });
+ });
+}
diff --git a/test/functional/apps/context/index.js b/test/functional/apps/context/index.js
index 9e1b04ad458748..c3c938c6237316 100644
--- a/test/functional/apps/context/index.js
+++ b/test/functional/apps/context/index.js
@@ -42,5 +42,6 @@ export default function({ getService, getPageObjects, loadTestFile }) {
loadTestFile(require.resolve('./_filters'));
loadTestFile(require.resolve('./_size'));
loadTestFile(require.resolve('./_date_nanos'));
+ loadTestFile(require.resolve('./_date_nanos_custom_timestamp'));
});
}
diff --git a/test/functional/apps/dashboard/dashboard_clone.js b/test/functional/apps/dashboard/dashboard_clone.js
index 2a955a2dc90b1e..f5485c1db206e7 100644
--- a/test/functional/apps/dashboard/dashboard_clone.js
+++ b/test/functional/apps/dashboard/dashboard_clone.js
@@ -21,6 +21,7 @@ import expect from '@kbn/expect';
export default function({ getService, getPageObjects }) {
const retry = getService('retry');
+ const listingTable = getService('listingTable');
const PageObjects = getPageObjects(['dashboard', 'header', 'common']);
describe('dashboard clone', function describeIndexTests() {
@@ -40,10 +41,12 @@ export default function({ getService, getPageObjects }) {
await PageObjects.dashboard.clickClone();
await PageObjects.dashboard.confirmClone();
-
- const countOfDashboards = await PageObjects.dashboard.getDashboardCountWithName(
+ await PageObjects.dashboard.gotoDashboardLandingPage();
+ const countOfDashboards = await listingTable.searchAndGetItemsCount(
+ 'dashboard',
clonedDashboardName
);
+
expect(countOfDashboards).to.equal(1);
});
@@ -70,8 +73,10 @@ export default function({ getService, getPageObjects }) {
it("and doesn't save", async () => {
await PageObjects.dashboard.cancelClone();
+ await PageObjects.dashboard.gotoDashboardLandingPage();
- const countOfDashboards = await PageObjects.dashboard.getDashboardCountWithName(
+ const countOfDashboards = await listingTable.searchAndGetItemsCount(
+ 'dashboard',
dashboardName
);
expect(countOfDashboards).to.equal(1);
@@ -85,8 +90,10 @@ export default function({ getService, getPageObjects }) {
await PageObjects.dashboard.expectDuplicateTitleWarningDisplayed({ displayed: true });
await PageObjects.dashboard.confirmClone();
await PageObjects.dashboard.waitForRenderComplete();
+ await PageObjects.dashboard.gotoDashboardLandingPage();
- const countOfDashboards = await PageObjects.dashboard.getDashboardCountWithName(
+ const countOfDashboards = await listingTable.searchAndGetItemsCount(
+ 'dashboard',
dashboardName + ' Copy'
);
expect(countOfDashboards).to.equal(2);
diff --git a/test/functional/apps/dashboard/dashboard_filter_bar.js b/test/functional/apps/dashboard/dashboard_filter_bar.js
index 5dcb18374c51f7..6d2a30fa85325d 100644
--- a/test/functional/apps/dashboard/dashboard_filter_bar.js
+++ b/test/functional/apps/dashboard/dashboard_filter_bar.js
@@ -27,7 +27,7 @@ export default function({ getService, getPageObjects }) {
const pieChart = getService('pieChart');
const esArchiver = getService('esArchiver');
const kibanaServer = getService('kibanaServer');
- const PageObjects = getPageObjects(['common', 'dashboard', 'header', 'visualize']);
+ const PageObjects = getPageObjects(['common', 'dashboard', 'header', 'visualize', 'timePicker']);
describe('dashboard filter bar', () => {
before(async () => {
@@ -91,7 +91,7 @@ export default function({ getService, getPageObjects }) {
await filterBar.ensureFieldEditorModalIsClosed();
await PageObjects.dashboard.gotoDashboardLandingPage();
await PageObjects.dashboard.clickNewDashboard();
- await PageObjects.dashboard.setTimepickerInDataRange();
+ await PageObjects.timePicker.setDefaultDataRange();
});
it('are not selected by default', async function() {
@@ -136,7 +136,7 @@ export default function({ getService, getPageObjects }) {
await filterBar.ensureFieldEditorModalIsClosed();
await PageObjects.dashboard.gotoDashboardLandingPage();
await PageObjects.dashboard.clickNewDashboard();
- await PageObjects.dashboard.setTimepickerInDataRange();
+ await PageObjects.timePicker.setDefaultDataRange();
});
it('are added when a cell magnifying glass is clicked', async function() {
diff --git a/test/functional/apps/dashboard/dashboard_filtering.js b/test/functional/apps/dashboard/dashboard_filtering.js
index bd31bb010f2609..1cb9f1490d4427 100644
--- a/test/functional/apps/dashboard/dashboard_filtering.js
+++ b/test/functional/apps/dashboard/dashboard_filtering.js
@@ -34,7 +34,7 @@ export default function({ getService, getPageObjects }) {
const esArchiver = getService('esArchiver');
const kibanaServer = getService('kibanaServer');
const dashboardPanelActions = getService('dashboardPanelActions');
- const PageObjects = getPageObjects(['common', 'dashboard', 'header', 'visualize']);
+ const PageObjects = getPageObjects(['common', 'dashboard', 'header', 'visualize', 'timePicker']);
describe('dashboard filtering', function() {
this.tags('smoke');
@@ -52,7 +52,7 @@ export default function({ getService, getPageObjects }) {
describe('adding a filter that excludes all data', () => {
before(async () => {
await PageObjects.dashboard.clickNewDashboard();
- await PageObjects.dashboard.setTimepickerInDataRange();
+ await PageObjects.timePicker.setDefaultDataRange();
await dashboardAddPanel.addEveryVisualization('"Filter Bytes Test"');
await dashboardAddPanel.addEverySavedSearch('"Filter Bytes Test"');
@@ -234,7 +234,7 @@ export default function({ getService, getPageObjects }) {
it('visualization saved with a query filters data', async () => {
await PageObjects.dashboard.clickNewDashboard();
- await PageObjects.dashboard.setTimepickerInDataRange();
+ await PageObjects.timePicker.setDefaultDataRange();
await dashboardAddPanel.addVisualization('Rendering-Test:-animal-sounds-pie');
await PageObjects.header.waitUntilLoadingHasFinished();
diff --git a/test/functional/apps/dashboard/dashboard_listing.js b/test/functional/apps/dashboard/dashboard_listing.js
index 179f10223afb2e..e3e835109da2cd 100644
--- a/test/functional/apps/dashboard/dashboard_listing.js
+++ b/test/functional/apps/dashboard/dashboard_listing.js
@@ -22,6 +22,7 @@ import expect from '@kbn/expect';
export default function({ getService, getPageObjects }) {
const PageObjects = getPageObjects(['dashboard', 'header', 'common']);
const browser = getService('browser');
+ const listingTable = getService('listingTable');
describe('dashboard listing page', function describeIndexTests() {
const dashboardName = 'Dashboard Listing Test';
@@ -41,7 +42,8 @@ export default function({ getService, getPageObjects }) {
await PageObjects.dashboard.saveDashboard(dashboardName);
await PageObjects.dashboard.gotoDashboardLandingPage();
- const countOfDashboards = await PageObjects.dashboard.getDashboardCountWithName(
+ const countOfDashboards = await listingTable.searchAndGetItemsCount(
+ 'dashboard',
dashboardName
);
expect(countOfDashboards).to.equal(1);
@@ -53,7 +55,8 @@ export default function({ getService, getPageObjects }) {
});
it('is not shown when there are no dashboards shown during a search', async function() {
- const countOfDashboards = await PageObjects.dashboard.getDashboardCountWithName(
+ const countOfDashboards = await listingTable.searchAndGetItemsCount(
+ 'dashboard',
'gobeldeguck'
);
expect(countOfDashboards).to.equal(0);
@@ -65,9 +68,9 @@ export default function({ getService, getPageObjects }) {
describe('delete', function() {
it('default confirm action is cancel', async function() {
- await PageObjects.dashboard.searchForDashboardWithName(dashboardName);
- await PageObjects.dashboard.checkDashboardListingSelectAllCheckbox();
- await PageObjects.dashboard.clickDeleteSelectedDashboards();
+ await listingTable.searchForItemWithName(dashboardName);
+ await listingTable.checkListingSelectAllCheckbox();
+ await listingTable.clickDeleteSelected();
await PageObjects.common.expectConfirmModalOpenState(true);
@@ -75,19 +78,21 @@ export default function({ getService, getPageObjects }) {
await PageObjects.common.expectConfirmModalOpenState(false);
- const countOfDashboards = await PageObjects.dashboard.getDashboardCountWithName(
+ const countOfDashboards = await listingTable.searchAndGetItemsCount(
+ 'dashboard',
dashboardName
);
expect(countOfDashboards).to.equal(1);
});
it('succeeds on confirmation press', async function() {
- await PageObjects.dashboard.checkDashboardListingSelectAllCheckbox();
- await PageObjects.dashboard.clickDeleteSelectedDashboards();
+ await listingTable.checkListingSelectAllCheckbox();
+ await listingTable.clickDeleteSelected();
await PageObjects.common.clickConfirmOnModal();
- const countOfDashboards = await PageObjects.dashboard.getDashboardCountWithName(
+ const countOfDashboards = await listingTable.searchAndGetItemsCount(
+ 'dashboard',
dashboardName
);
expect(countOfDashboards).to.equal(0);
@@ -96,44 +101,45 @@ export default function({ getService, getPageObjects }) {
describe('search', function() {
before(async () => {
- await PageObjects.dashboard.clearSearchValue();
+ await listingTable.clearSearchFilter();
await PageObjects.dashboard.clickNewDashboard();
await PageObjects.dashboard.saveDashboard('Two Words');
+ await PageObjects.dashboard.gotoDashboardLandingPage();
});
it('matches on the first word', async function() {
- await PageObjects.dashboard.searchForDashboardWithName('Two');
- const countOfDashboards = await PageObjects.dashboard.getCountOfDashboardsInListingTable();
+ await listingTable.searchForItemWithName('Two');
+ const countOfDashboards = await listingTable.getItemsCount('dashboard');
expect(countOfDashboards).to.equal(1);
});
it('matches the second word', async function() {
- await PageObjects.dashboard.searchForDashboardWithName('Words');
- const countOfDashboards = await PageObjects.dashboard.getCountOfDashboardsInListingTable();
+ await listingTable.searchForItemWithName('Words');
+ const countOfDashboards = await listingTable.getItemsCount('dashboard');
expect(countOfDashboards).to.equal(1);
});
it('matches the second word prefix', async function() {
- await PageObjects.dashboard.searchForDashboardWithName('Wor');
- const countOfDashboards = await PageObjects.dashboard.getCountOfDashboardsInListingTable();
+ await listingTable.searchForItemWithName('Wor');
+ const countOfDashboards = await listingTable.getItemsCount('dashboard');
expect(countOfDashboards).to.equal(1);
});
it('does not match mid word', async function() {
- await PageObjects.dashboard.searchForDashboardWithName('ords');
- const countOfDashboards = await PageObjects.dashboard.getCountOfDashboardsInListingTable();
+ await listingTable.searchForItemWithName('ords');
+ const countOfDashboards = await listingTable.getItemsCount('dashboard');
expect(countOfDashboards).to.equal(0);
});
it('is case insensitive', async function() {
- await PageObjects.dashboard.searchForDashboardWithName('two words');
- const countOfDashboards = await PageObjects.dashboard.getCountOfDashboardsInListingTable();
+ await listingTable.searchForItemWithName('two words');
+ const countOfDashboards = await listingTable.getItemsCount('dashboard');
expect(countOfDashboards).to.equal(1);
});
it('is using AND operator', async function() {
- await PageObjects.dashboard.searchForDashboardWithName('three words');
- const countOfDashboards = await PageObjects.dashboard.getCountOfDashboardsInListingTable();
+ await listingTable.searchForItemWithName('three words');
+ const countOfDashboards = await listingTable.getItemsCount('dashboard');
expect(countOfDashboards).to.equal(0);
});
});
@@ -176,7 +182,7 @@ export default function({ getService, getPageObjects }) {
});
it('preloads search filter bar when there is no match', async function() {
- const searchFilter = await PageObjects.dashboard.getSearchFilterValue();
+ const searchFilter = await listingTable.getSearchFilterValue();
expect(searchFilter).to.equal('"nodashboardsnamedme"');
});
@@ -196,7 +202,7 @@ export default function({ getService, getPageObjects }) {
});
it('preloads search filter bar when there is more than one match', async function() {
- const searchFilter = await PageObjects.dashboard.getSearchFilterValue();
+ const searchFilter = await listingTable.getSearchFilterValue();
expect(searchFilter).to.equal('"two words"');
});
diff --git a/test/functional/apps/dashboard/dashboard_save.js b/test/functional/apps/dashboard/dashboard_save.js
index 23bb784c79cd0b..2ea1389b89ad43 100644
--- a/test/functional/apps/dashboard/dashboard_save.js
+++ b/test/functional/apps/dashboard/dashboard_save.js
@@ -19,8 +19,9 @@
import expect from '@kbn/expect';
-export default function({ getPageObjects }) {
+export default function({ getPageObjects, getService }) {
const PageObjects = getPageObjects(['dashboard', 'header']);
+ const listingTable = getService('listingTable');
describe('dashboard save', function describeIndexTests() {
this.tags('smoke');
@@ -47,8 +48,10 @@ export default function({ getPageObjects }) {
it('does not save on reject confirmation', async function() {
await PageObjects.dashboard.cancelSave();
+ await PageObjects.dashboard.gotoDashboardLandingPage();
- const countOfDashboards = await PageObjects.dashboard.getDashboardCountWithName(
+ const countOfDashboards = await listingTable.searchAndGetItemsCount(
+ 'dashboard',
dashboardName
);
expect(countOfDashboards).to.equal(1);
@@ -68,15 +71,17 @@ export default function({ getPageObjects }) {
// wait till it finishes reloading or it might reload the url after simulating the
// dashboard landing page click.
await PageObjects.header.waitUntilLoadingHasFinished();
+ await PageObjects.dashboard.gotoDashboardLandingPage();
- const countOfDashboards = await PageObjects.dashboard.getDashboardCountWithName(
+ const countOfDashboards = await listingTable.searchAndGetItemsCount(
+ 'dashboard',
dashboardName
);
expect(countOfDashboards).to.equal(2);
});
it('Does not warn when you save an existing dashboard with the title it already has, and that title is a duplicate', async function() {
- await PageObjects.dashboard.selectDashboard(dashboardName);
+ await listingTable.clickItemLink('dashboard', dashboardName);
await PageObjects.header.awaitGlobalLoadingIndicatorHidden();
await PageObjects.dashboard.switchToEditMode();
await PageObjects.dashboard.saveDashboard(dashboardName);
@@ -121,8 +126,10 @@ export default function({ getPageObjects }) {
// wait till it finishes reloading or it might reload the url after simulating the
// dashboard landing page click.
await PageObjects.header.waitUntilLoadingHasFinished();
+ await PageObjects.dashboard.gotoDashboardLandingPage();
- const countOfDashboards = await PageObjects.dashboard.getDashboardCountWithName(
+ const countOfDashboards = await listingTable.searchAndGetItemsCount(
+ 'dashboard',
dashboardNameEnterKey
);
expect(countOfDashboards).to.equal(1);
diff --git a/test/functional/apps/dashboard/dashboard_snapshots.js b/test/functional/apps/dashboard/dashboard_snapshots.js
index 9900881e4690d9..3a09b46a713cc1 100644
--- a/test/functional/apps/dashboard/dashboard_snapshots.js
+++ b/test/functional/apps/dashboard/dashboard_snapshots.js
@@ -20,7 +20,7 @@
import expect from '@kbn/expect';
export default function({ getService, getPageObjects, updateBaselines }) {
- const PageObjects = getPageObjects(['dashboard', 'header', 'visualize', 'common']);
+ const PageObjects = getPageObjects(['dashboard', 'header', 'visualize', 'common', 'timePicker']);
const screenshot = getService('screenshots');
const browser = getService('browser');
const esArchiver = getService('esArchiver');
@@ -48,7 +48,7 @@ export default function({ getService, getPageObjects, updateBaselines }) {
it('compare TSVB snapshot', async () => {
await PageObjects.dashboard.gotoDashboardLandingPage();
await PageObjects.dashboard.clickNewDashboard();
- await PageObjects.dashboard.setTimepickerInLogstashDataRange();
+ await PageObjects.timePicker.setLogstashDataRange();
await dashboardAddPanel.addVisualization('Rendering Test: tsvb-ts');
await PageObjects.common.closeToast();
@@ -71,7 +71,7 @@ export default function({ getService, getPageObjects, updateBaselines }) {
it('compare area chart snapshot', async () => {
await PageObjects.dashboard.gotoDashboardLandingPage();
await PageObjects.dashboard.clickNewDashboard();
- await PageObjects.dashboard.setTimepickerInLogstashDataRange();
+ await PageObjects.timePicker.setLogstashDataRange();
await dashboardAddPanel.addVisualization('Rendering Test: area with not filter');
await PageObjects.common.closeToast();
diff --git a/test/functional/apps/dashboard/dashboard_state.js b/test/functional/apps/dashboard/dashboard_state.js
index 3b9e404e9b94d1..b9172990c501dc 100644
--- a/test/functional/apps/dashboard/dashboard_state.js
+++ b/test/functional/apps/dashboard/dashboard_state.js
@@ -34,6 +34,7 @@ export default function({ getService, getPageObjects }) {
'discover',
'tileMap',
'visChart',
+ 'timePicker',
]);
const testSubjects = getService('testSubjects');
const browser = getService('browser');
@@ -58,7 +59,7 @@ export default function({ getService, getPageObjects }) {
await PageObjects.dashboard.gotoDashboardLandingPage();
await PageObjects.dashboard.clickNewDashboard();
- await PageObjects.dashboard.setTimepickerInHistoricalDataRange();
+ await PageObjects.timePicker.setHistoricalDataRange();
await dashboardAddPanel.addVisualization(AREA_CHART_VIS_NAME);
await PageObjects.dashboard.saveDashboard('Overridden colors');
@@ -83,7 +84,7 @@ export default function({ getService, getPageObjects }) {
await PageObjects.dashboard.gotoDashboardLandingPage();
await PageObjects.header.clickDiscover();
- await PageObjects.dashboard.setTimepickerInHistoricalDataRange();
+ await PageObjects.timePicker.setHistoricalDataRange();
await PageObjects.discover.clickFieldListItemAdd('bytes');
await PageObjects.discover.saveSearch('my search');
await PageObjects.header.waitUntilLoadingHasFinished();
@@ -147,7 +148,7 @@ export default function({ getService, getPageObjects }) {
await PageObjects.dashboard.gotoDashboardLandingPage();
await PageObjects.dashboard.clickNewDashboard();
- await PageObjects.dashboard.setTimepickerInHistoricalDataRange();
+ await PageObjects.timePicker.setHistoricalDataRange();
await dashboardAddPanel.addVisualization('Visualization TileMap');
await PageObjects.dashboard.saveDashboard('No local edits');
diff --git a/test/functional/apps/dashboard/dashboard_time_picker.js b/test/functional/apps/dashboard/dashboard_time_picker.js
index 0b73bc224ab742..b99de9fee6db19 100644
--- a/test/functional/apps/dashboard/dashboard_time_picker.js
+++ b/test/functional/apps/dashboard/dashboard_time_picker.js
@@ -44,7 +44,7 @@ export default function({ getService, getPageObjects }) {
await PageObjects.dashboard.addVisualizations([PIE_CHART_VIS_NAME]);
await pieChart.expectPieSliceCount(0);
- await PageObjects.dashboard.setTimepickerInHistoricalDataRange();
+ await PageObjects.timePicker.setHistoricalDataRange();
await pieChart.expectPieSliceCount(10);
});
@@ -95,7 +95,7 @@ export default function({ getService, getPageObjects }) {
await PageObjects.dashboard.gotoDashboardLandingPage();
await PageObjects.dashboard.clickNewDashboard();
await PageObjects.dashboard.addVisualizations([PIE_CHART_VIS_NAME]);
- // Same date range as `setTimepickerInHistoricalDataRange`
+ // Same date range as `timePicker.setHistoricalDataRange()`
await PageObjects.timePicker.setAbsoluteRange(
'2015-09-19 06:31:44.000',
'2015-09-23 18:31:44.000'
diff --git a/test/functional/apps/dashboard/panel_controls.js b/test/functional/apps/dashboard/panel_controls.js
index 683f3683e65e51..f30f58913bd970 100644
--- a/test/functional/apps/dashboard/panel_controls.js
+++ b/test/functional/apps/dashboard/panel_controls.js
@@ -33,7 +33,13 @@ export default function({ getService, getPageObjects }) {
const dashboardReplacePanel = getService('dashboardReplacePanel');
const dashboardVisualizations = getService('dashboardVisualizations');
const renderable = getService('renderable');
- const PageObjects = getPageObjects(['dashboard', 'header', 'visualize', 'discover']);
+ const PageObjects = getPageObjects([
+ 'dashboard',
+ 'header',
+ 'visualize',
+ 'discover',
+ 'timePicker',
+ ]);
const dashboardName = 'Dashboard Panel Controls Test';
describe('dashboard panel controls', function viewEditModeTests() {
@@ -52,7 +58,7 @@ export default function({ getService, getPageObjects }) {
let intialDimensions;
before(async () => {
await PageObjects.dashboard.clickNewDashboard();
- await PageObjects.dashboard.setTimepickerInHistoricalDataRange();
+ await PageObjects.timePicker.setHistoricalDataRange();
await dashboardAddPanel.addVisualization(PIE_CHART_VIS_NAME);
await dashboardAddPanel.addVisualization(LINE_CHART_VIS_NAME);
intialDimensions = await PageObjects.dashboard.getPanelDimensions();
@@ -110,7 +116,7 @@ export default function({ getService, getPageObjects }) {
describe('panel edit controls', function() {
before(async () => {
await PageObjects.dashboard.clickNewDashboard();
- await PageObjects.dashboard.setTimepickerInHistoricalDataRange();
+ await PageObjects.timePicker.setHistoricalDataRange();
await dashboardAddPanel.addVisualization(PIE_CHART_VIS_NAME);
});
diff --git a/test/functional/apps/dashboard/view_edit.js b/test/functional/apps/dashboard/view_edit.js
index 212044d898251a..a0b972f3ab63c2 100644
--- a/test/functional/apps/dashboard/view_edit.js
+++ b/test/functional/apps/dashboard/view_edit.js
@@ -68,7 +68,7 @@ export default function({ getService, getPageObjects }) {
});
it('when time changed is stored with dashboard', async function() {
- await PageObjects.dashboard.setTimepickerInDataRange();
+ await PageObjects.timePicker.setDefaultDataRange();
const originalTime = await PageObjects.timePicker.getTimeConfig();
@@ -196,7 +196,7 @@ export default function({ getService, getPageObjects }) {
describe('and preserves edits on cancel', function() {
it('when time changed is stored with dashboard', async function() {
await PageObjects.dashboard.gotoDashboardEditMode(dashboardName);
- await PageObjects.dashboard.setTimepickerInDataRange();
+ await PageObjects.timePicker.setDefaultDataRange();
await PageObjects.dashboard.saveDashboard(dashboardName, true);
await PageObjects.dashboard.switchToEditMode();
await PageObjects.timePicker.setAbsoluteRange(
diff --git a/test/functional/apps/home/_sample_data.js b/test/functional/apps/home/_sample_data.ts
similarity index 94%
rename from test/functional/apps/home/_sample_data.js
rename to test/functional/apps/home/_sample_data.ts
index 4aa862a4a03845..8088b5a0f9da96 100644
--- a/test/functional/apps/home/_sample_data.js
+++ b/test/functional/apps/home/_sample_data.ts
@@ -19,8 +19,9 @@
import expect from '@kbn/expect';
import moment from 'moment';
+import { FtrProviderContext } from '../../ftr_provider_context';
-export default function({ getService, getPageObjects }) {
+export default function({ getService, getPageObjects }: FtrProviderContext) {
const retry = getService('retry');
const find = getService('find');
const log = getService('log');
@@ -76,9 +77,8 @@ export default function({ getService, getPageObjects }) {
expect(isInstalled).to.be(true);
});
- // FLAKY: https://github.com/elastic/kibana/issues/40670
- describe.skip('dashboard', () => {
- afterEach(async () => {
+ describe('dashboard', () => {
+ beforeEach(async () => {
await PageObjects.common.navigateToUrl('home', 'tutorial_directory/sampleData');
await PageObjects.header.waitUntilLoadingHasFinished();
});
@@ -99,7 +99,6 @@ export default function({ getService, getPageObjects }) {
await PageObjects.home.launchSampleDataSet('flights');
await PageObjects.header.waitUntilLoadingHasFinished();
await renderable.waitForRender();
-
log.debug('Checking pie charts rendered');
await pieChart.expectPieSliceCount(4);
log.debug('Checking area, bar and heatmap charts rendered');
@@ -142,6 +141,11 @@ export default function({ getService, getPageObjects }) {
// needs to be in describe block so it is run after 'dashboard describe block'
describe('uninstall', () => {
+ beforeEach(async () => {
+ await PageObjects.common.navigateToUrl('home', 'tutorial_directory/sampleData');
+ await PageObjects.header.waitUntilLoadingHasFinished();
+ });
+
it('should uninstall flights sample data set', async () => {
await PageObjects.home.removeSampleDataSet('flights');
const isInstalled = await PageObjects.home.isSampleDataSetInstalled('flights');
diff --git a/test/functional/fixtures/es_archiver/date_nanos_custom/data.json b/test/functional/fixtures/es_archiver/date_nanos_custom/data.json
new file mode 100644
index 00000000000000..73cba70a8b93d5
--- /dev/null
+++ b/test/functional/fixtures/es_archiver/date_nanos_custom/data.json
@@ -0,0 +1,56 @@
+{
+ "type": "doc",
+ "value": {
+ "id": "index-pattern:date_nanos_custom_timestamp",
+ "index": ".kibana",
+ "source": {
+ "index-pattern": {
+ "fields": "[{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"test\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"test.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"test\"}}},{\"name\":\"timestamp\",\"type\":\"date\",\"esTypes\":[\"date_nanos\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]",
+ "timeFieldName": "timestamp",
+ "title": "date_nanos_custom_timestamp"
+ },
+ "references": [
+ ],
+ "type": "index-pattern",
+ "updated_at": "2020-01-09T21:43:20.283Z"
+ }
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "id": "1",
+ "index": "date_nanos_custom_timestamp",
+ "source": {
+ "test": "1",
+ "timestamp": "2019-10-21 00:30:04.828740"
+ }
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "id": "2",
+ "index": "date_nanos_custom_timestamp",
+ "source": {
+ "test": "1",
+ "timestamp": "2019-10-21 08:30:04.828733"
+ }
+ }
+}
+
+{
+ "type": "doc",
+ "value": {
+ "id": "3",
+ "index": "date_nanos_custom_timestamp",
+ "source": {
+ "test": "1",
+ "timestamp": "2019-10-21 00:30:04.828723"
+ }
+ }
+}
+
+
diff --git a/test/functional/fixtures/es_archiver/date_nanos_custom/mappings.json b/test/functional/fixtures/es_archiver/date_nanos_custom/mappings.json
new file mode 100644
index 00000000000000..98af509c4e6f29
--- /dev/null
+++ b/test/functional/fixtures/es_archiver/date_nanos_custom/mappings.json
@@ -0,0 +1,31 @@
+{
+ "type": "index",
+ "value": {
+ "aliases": {
+ },
+ "index": "date_nanos_custom_timestamp",
+ "mappings": {
+ "properties": {
+ "test": {
+ "fields": {
+ "keyword": {
+ "ignore_above": 256,
+ "type": "keyword"
+ }
+ },
+ "type": "text"
+ },
+ "timestamp": {
+ "format": "yyyy-MM-dd HH:mm:ss.SSSSSS",
+ "type": "date_nanos"
+ }
+ }
+ },
+ "settings": {
+ "index": {
+ "number_of_replicas": "1",
+ "number_of_shards": "1"
+ }
+ }
+ }
+}
diff --git a/test/functional/page_objects/dashboard_page.js b/test/functional/page_objects/dashboard_page.ts
similarity index 60%
rename from test/functional/page_objects/dashboard_page.js
rename to test/functional/page_objects/dashboard_page.ts
index b0f1a3304a9b8e..af0a0160a81d80 100644
--- a/test/functional/page_objects/dashboard_page.js
+++ b/test/functional/page_objects/dashboard_page.ts
@@ -17,89 +17,85 @@
* under the License.
*/
-import _ from 'lodash';
import { DashboardConstants } from '../../../src/legacy/core_plugins/kibana/public/dashboard/np_ready/dashboard_constants';
export const PIE_CHART_VIS_NAME = 'Visualization PieChart';
export const AREA_CHART_VIS_NAME = 'Visualization漢字 AreaChart';
export const LINE_CHART_VIS_NAME = 'Visualization漢字 LineChart';
+import { FtrProviderContext } from '../ftr_provider_context';
-export function DashboardPageProvider({ getService, getPageObjects }) {
+export function DashboardPageProvider({ getService, getPageObjects }: FtrProviderContext) {
const log = getService('log');
const find = getService('find');
const retry = getService('retry');
- const config = getService('config');
const browser = getService('browser');
const esArchiver = getService('esArchiver');
const kibanaServer = getService('kibanaServer');
const testSubjects = getService('testSubjects');
const dashboardAddPanel = getService('dashboardAddPanel');
const renderable = getService('renderable');
- const PageObjects = getPageObjects(['common', 'header', 'settings', 'visualize', 'timePicker']);
-
- const defaultFindTimeout = config.get('timeouts.find');
+ const listingTable = getService('listingTable');
+ const PageObjects = getPageObjects(['common', 'header', 'visualize']);
+
+ interface SaveDashboardOptions {
+ waitDialogIsClosed: boolean;
+ needsConfirm?: boolean;
+ storeTimeWithDashboard?: boolean;
+ saveAsNew?: boolean;
+ }
class DashboardPage {
async initTests({ kibanaIndex = 'dashboard/legacy', defaultIndex = 'logstash-*' } = {}) {
log.debug('load kibana index with visualizations and log data');
await esArchiver.load(kibanaIndex);
- await kibanaServer.uiSettings.replace({
- defaultIndex: defaultIndex,
- });
+ await kibanaServer.uiSettings.replace({ defaultIndex });
await PageObjects.common.navigateToApp('dashboard');
}
- async preserveCrossAppState() {
+ public async preserveCrossAppState() {
const url = await browser.getCurrentUrl();
await browser.get(url, false);
await PageObjects.header.waitUntilLoadingHasFinished();
}
- async selectDefaultIndex(indexName) {
- await PageObjects.settings.navigateTo();
- await PageObjects.settings.clickKibanaIndexPatterns();
- await find.clickByPartialLinkText(indexName);
- await PageObjects.settings.clickDefaultIndexButton();
- }
-
- async clickFullScreenMode() {
+ public async clickFullScreenMode() {
log.debug(`clickFullScreenMode`);
await testSubjects.click('dashboardFullScreenMode');
await testSubjects.exists('exitFullScreenModeLogo');
await this.waitForRenderComplete();
}
- async fullScreenModeMenuItemExists() {
+ public async fullScreenModeMenuItemExists() {
return await testSubjects.exists('dashboardFullScreenMode');
}
- async exitFullScreenTextButtonExists() {
+ public async exitFullScreenTextButtonExists() {
return await testSubjects.exists('exitFullScreenModeText');
}
- async getExitFullScreenTextButton() {
+ public async getExitFullScreenTextButton() {
return await testSubjects.find('exitFullScreenModeText');
}
- async exitFullScreenLogoButtonExists() {
+ public async exitFullScreenLogoButtonExists() {
return await testSubjects.exists('exitFullScreenModeLogo');
}
- async getExitFullScreenLogoButton() {
+ public async getExitFullScreenLogoButton() {
return await testSubjects.find('exitFullScreenModeLogo');
}
- async clickExitFullScreenLogoButton() {
+ public async clickExitFullScreenLogoButton() {
await testSubjects.click('exitFullScreenModeLogo');
await this.waitForRenderComplete();
}
- async clickExitFullScreenTextButton() {
+ public async clickExitFullScreenTextButton() {
await testSubjects.click('exitFullScreenModeText');
await this.waitForRenderComplete();
}
- async getDashboardIdFromCurrentUrl() {
+ public async getDashboardIdFromCurrentUrl() {
const currentUrl = await browser.getCurrentUrl();
const urlSubstring = 'kibana#/dashboard/';
const startOfIdIndex = currentUrl.indexOf(urlSubstring) + urlSubstring.length;
@@ -115,25 +111,25 @@ export function DashboardPageProvider({ getService, getPageObjects }) {
* Returns true if already on the dashboard landing page (that page doesn't have a link to itself).
* @returns {Promise}
*/
- async onDashboardLandingPage() {
+ public async onDashboardLandingPage() {
log.debug(`onDashboardLandingPage`);
return await testSubjects.exists('dashboardLandingPage', {
timeout: 5000,
});
}
- async expectExistsDashboardLandingPage() {
+ public async expectExistsDashboardLandingPage() {
log.debug(`expectExistsDashboardLandingPage`);
await testSubjects.existOrFail('dashboardLandingPage');
}
- async clickDashboardBreadcrumbLink() {
+ public async clickDashboardBreadcrumbLink() {
log.debug('clickDashboardBreadcrumbLink');
await find.clickByCssSelector(`a[href="#${DashboardConstants.LANDING_PAGE_PATH}"]`);
await this.expectExistsDashboardLandingPage();
}
- async gotoDashboardLandingPage() {
+ public async gotoDashboardLandingPage() {
log.debug('gotoDashboardLandingPage');
const onPage = await this.onDashboardLandingPage();
if (!onPage) {
@@ -141,26 +137,26 @@ export function DashboardPageProvider({ getService, getPageObjects }) {
}
}
- async clickClone() {
+ public async clickClone() {
log.debug('Clicking clone');
await testSubjects.click('dashboardClone');
}
- async getCloneTitle() {
+ public async getCloneTitle() {
return await testSubjects.getAttribute('clonedDashboardTitle', 'value');
}
- async confirmClone() {
+ public async confirmClone() {
log.debug('Confirming clone');
await testSubjects.click('cloneConfirmButton');
}
- async cancelClone() {
+ public async cancelClone() {
log.debug('Canceling clone');
await testSubjects.click('cloneCancelButton');
}
- async setClonedDashboardTitle(title) {
+ public async setClonedDashboardTitle(title: string) {
await testSubjects.setValue('clonedDashboardTitle', title);
}
@@ -168,7 +164,7 @@ export function DashboardPageProvider({ getService, getPageObjects }) {
* Asserts that the duplicate title warning is either displayed or not displayed.
* @param { displayed: boolean }
*/
- async expectDuplicateTitleWarningDisplayed({ displayed }) {
+ public async expectDuplicateTitleWarningDisplayed({ displayed = true }) {
if (displayed) {
await testSubjects.existOrFail('titleDupicateWarnMsg');
} else {
@@ -180,18 +176,16 @@ export function DashboardPageProvider({ getService, getPageObjects }) {
* Asserts that the toolbar pagination (count and arrows) is either displayed or not displayed.
* @param { displayed: boolean }
*/
- async expectToolbarPaginationDisplayed({ displayed }) {
+ public async expectToolbarPaginationDisplayed({ displayed = true }) {
const subjects = ['btnPrevPage', 'btnNextPage', 'toolBarPagerText'];
if (displayed) {
- return await Promise.all(subjects.map(async subj => await testSubjects.existOrFail(subj)));
+ await Promise.all(subjects.map(async subj => await testSubjects.existOrFail(subj)));
} else {
- return await Promise.all(
- subjects.map(async subj => await testSubjects.missingOrFail(subj))
- );
+ await Promise.all(subjects.map(async subj => await testSubjects.missingOrFail(subj)));
}
}
- async switchToEditMode() {
+ public async switchToEditMode() {
log.debug('Switching to edit mode');
await testSubjects.click('dashboardEditMode');
// wait until the count of dashboard panels equals the count of toggle menu icons
@@ -204,66 +198,34 @@ export function DashboardPageProvider({ getService, getPageObjects }) {
});
}
- async getIsInViewMode() {
+ public async getIsInViewMode() {
log.debug('getIsInViewMode');
return await testSubjects.exists('dashboardEditMode');
}
- async clickCancelOutOfEditMode() {
+ public async clickCancelOutOfEditMode() {
log.debug('clickCancelOutOfEditMode');
- return await testSubjects.click('dashboardViewOnlyMode');
+ await testSubjects.click('dashboardViewOnlyMode');
}
- async clickNewDashboard() {
- // One or the other will eventually show up on the landing page, depending on whether there are
- // dashboards.
- await retry.try(async () => {
- const createNewItemButtonExists = await testSubjects.exists('newItemButton');
- if (createNewItemButtonExists) {
- return await testSubjects.click('newItemButton');
- }
- const createNewItemPromptExists = await this.getCreateDashboardPromptExists();
- if (createNewItemPromptExists) {
- return await this.clickCreateDashboardPrompt();
- }
-
- throw new Error(
- 'Page is still loading... waiting for create new prompt or button to appear'
- );
- });
+ public async clickNewDashboard() {
+ await listingTable.clickNewButton('createDashboardPromptButton');
}
- async clickCreateDashboardPrompt() {
+ public async clickCreateDashboardPrompt() {
await testSubjects.click('createDashboardPromptButton');
}
- async getCreateDashboardPromptExists() {
+ public async getCreateDashboardPromptExists() {
return await testSubjects.exists('createDashboardPromptButton');
}
- async checkDashboardListingRow(id) {
- await testSubjects.click(`checkboxSelectRow-${id}`);
- }
-
- async checkDashboardListingSelectAllCheckbox() {
- const element = await testSubjects.find('checkboxSelectAll');
- const isSelected = await element.isSelected();
- if (!isSelected) {
- log.debug(`checking checkbox "checkboxSelectAll"`);
- await testSubjects.click('checkboxSelectAll');
- }
- }
-
- async clickDeleteSelectedDashboards() {
- await testSubjects.click('deleteSelectedItems');
- }
-
- async isOptionsOpen() {
+ public async isOptionsOpen() {
log.debug('isOptionsOpen');
return await testSubjects.exists('dashboardOptionsMenu');
}
- async openOptions() {
+ public async openOptions() {
log.debug('openOptions');
const isOpen = await this.isOptionsOpen();
if (!isOpen) {
@@ -272,36 +234,36 @@ export function DashboardPageProvider({ getService, getPageObjects }) {
}
// avoids any 'Object with id x not found' errors when switching tests.
- async clearSavedObjectsFromAppLinks() {
+ public async clearSavedObjectsFromAppLinks() {
await PageObjects.header.clickVisualize();
await PageObjects.visualize.gotoLandingPage();
await PageObjects.header.clickDashboard();
await this.gotoDashboardLandingPage();
}
- async isMarginsOn() {
+ public async isMarginsOn() {
log.debug('isMarginsOn');
await this.openOptions();
return await testSubjects.getAttribute('dashboardMarginsCheckbox', 'checked');
}
- async useMargins(on = true) {
+ public async useMargins(on = true) {
await this.openOptions();
const isMarginsOn = await this.isMarginsOn();
- if (isMarginsOn !== on) {
+ if (isMarginsOn !== 'on') {
return await testSubjects.click('dashboardMarginsCheckbox');
}
}
- async gotoDashboardEditMode(dashboardName) {
+ public async gotoDashboardEditMode(dashboardName: string) {
await this.loadSavedDashboard(dashboardName);
await this.switchToEditMode();
}
- async renameDashboard(dashName) {
- log.debug(`Naming dashboard ` + dashName);
+ public async renameDashboard(dashboardName: string) {
+ log.debug(`Naming dashboard ` + dashboardName);
await testSubjects.click('dashboardRenameButton');
- await testSubjects.setValue('savedObjectTitle', dashName);
+ await testSubjects.setValue('savedObjectTitle', dashboardName);
}
/**
@@ -309,11 +271,14 @@ export function DashboardPageProvider({ getService, getPageObjects }) {
* verify that the save was successful, close the toast and return the
* toast message
*
- * @param dashName {String}
+ * @param dashboardName {String}
* @param saveOptions {{storeTimeWithDashboard: boolean, saveAsNew: boolean, needsConfirm: false, waitDialogIsClosed: boolean }}
*/
- async saveDashboard(dashName, saveOptions = { waitDialogIsClosed: true }) {
- await this.enterDashboardTitleAndClickSave(dashName, saveOptions);
+ public async saveDashboard(
+ dashboardName: string,
+ saveOptions: SaveDashboardOptions = { waitDialogIsClosed: true }
+ ) {
+ await this.enterDashboardTitleAndClickSave(dashboardName, saveOptions);
if (saveOptions.needsConfirm) {
await this.clickSave();
@@ -328,37 +293,24 @@ export function DashboardPageProvider({ getService, getPageObjects }) {
return message;
}
- async deleteDashboard(dashboardName, dashboardId) {
- await this.gotoDashboardLandingPage();
- await this.searchForDashboardWithName(dashboardName);
- await this.checkDashboardListingRow(dashboardId);
- await this.clickDeleteSelectedDashboards();
- await PageObjects.common.clickConfirmOnModal();
- }
-
- async cancelSave() {
+ public async cancelSave() {
log.debug('Canceling save');
await testSubjects.click('saveCancelButton');
}
- async clickSave() {
+ public async clickSave() {
log.debug('DashboardPage.clickSave');
await testSubjects.click('confirmSaveSavedObjectButton');
}
- async pressEnterKey() {
- log.debug('DashboardPage.pressEnterKey');
- await PageObjects.common.pressEnterKey();
- }
-
/**
*
* @param dashboardTitle {String}
* @param saveOptions {{storeTimeWithDashboard: boolean, saveAsNew: boolean, waitDialogIsClosed: boolean}}
*/
- async enterDashboardTitleAndClickSave(
- dashboardTitle,
- saveOptions = { waitDialogIsClosed: true }
+ public async enterDashboardTitleAndClickSave(
+ dashboardTitle: string,
+ saveOptions: SaveDashboardOptions = { waitDialogIsClosed: true }
) {
await testSubjects.click('dashboardSaveMenuItem');
const modalDialog = await testSubjects.find('savedObjectSaveModal');
@@ -380,128 +332,66 @@ export function DashboardPageProvider({ getService, getPageObjects }) {
}
}
- async ensureDuplicateTitleCallout() {
+ public async ensureDuplicateTitleCallout() {
await testSubjects.existOrFail('titleDupicateWarnMsg');
}
/**
* @param dashboardTitle {String}
*/
- async enterDashboardTitleAndPressEnter(dashboardTitle) {
+ public async enterDashboardTitleAndPressEnter(dashboardTitle: string) {
await testSubjects.click('dashboardSaveMenuItem');
const modalDialog = await testSubjects.find('savedObjectSaveModal');
log.debug('entering new title');
await testSubjects.setValue('savedObjectTitle', dashboardTitle);
- await this.pressEnterKey();
+ await PageObjects.common.pressEnterKey();
await testSubjects.waitForDeleted(modalDialog);
}
- async selectDashboard(dashName) {
- await testSubjects.click(`dashboardListingTitleLink-${dashName.split(' ').join('-')}`);
- }
-
- async clearSearchValue() {
- log.debug(`clearSearchValue`);
-
- await this.gotoDashboardLandingPage();
-
- await retry.try(async () => {
- const searchFilter = await this.getSearchFilter();
- await searchFilter.clearValue();
- await PageObjects.common.pressEnterKey();
- });
- }
-
- async getSearchFilterValue() {
- const searchFilter = await this.getSearchFilter();
- return await searchFilter.getAttribute('value');
- }
-
- async getSearchFilter() {
- const searchFilter = await find.allByCssSelector('.euiFieldSearch');
- return searchFilter[0];
- }
-
- async searchForDashboardWithName(dashName) {
- log.debug(`searchForDashboardWithName: ${dashName}`);
-
- await this.gotoDashboardLandingPage();
-
- await retry.try(async () => {
- const searchFilter = await this.getSearchFilter();
- await searchFilter.clearValue();
- await searchFilter.click();
- // Note: this replacement of - to space is to preserve original logic but I'm not sure why or if it's needed.
- await searchFilter.type(dashName.replace('-', ' '));
- await PageObjects.common.pressEnterKey();
- await find.waitForDeletedByCssSelector('.euiBasicTable-loading', 5000);
- });
-
- await PageObjects.header.waitUntilLoadingHasFinished();
- }
-
- async getCountOfDashboardsInListingTable() {
- const dashboardTitles = await find.allByCssSelector(
- '[data-test-subj^="dashboardListingTitleLink"]'
- );
- return dashboardTitles.length;
- }
-
- async getDashboardCountWithName(dashName) {
- log.debug(`getDashboardCountWithName: ${dashName}`);
-
- await this.searchForDashboardWithName(dashName);
- const links = await testSubjects.findAll(
- `dashboardListingTitleLink-${dashName.replace(/ /g, '-')}`
- );
- return links.length;
- }
-
// use the search filter box to narrow the results down to a single
// entry, or at least to a single page of results
- async loadSavedDashboard(dashName) {
- log.debug(`Load Saved Dashboard ${dashName}`);
+ public async loadSavedDashboard(dashboardName: string) {
+ log.debug(`Load Saved Dashboard ${dashboardName}`);
await this.gotoDashboardLandingPage();
- await this.searchForDashboardWithName(dashName);
+ await listingTable.searchForItemWithName(dashboardName);
await retry.try(async () => {
- await this.selectDashboard(dashName);
+ await listingTable.clickItemLink('dashboard', dashboardName);
await PageObjects.header.waitUntilLoadingHasFinished();
// check Dashboard landing page is not present
await testSubjects.missingOrFail('dashboardLandingPage', { timeout: 10000 });
});
}
- async getPanelTitles() {
+ public async getPanelTitles() {
log.debug('in getPanelTitles');
const titleObjects = await testSubjects.findAll('dashboardPanelTitle');
return await Promise.all(titleObjects.map(async title => await title.getVisibleText()));
}
- async getPanelDimensions() {
+ public async getPanelDimensions() {
const panels = await find.allByCssSelector('.react-grid-item'); // These are gridster-defined elements and classes
- async function getPanelDimensions(panel) {
- const size = await panel.getSize();
- return {
- width: size.width,
- height: size.height,
- };
- }
-
- const getDimensionsPromises = _.map(panels, getPanelDimensions);
- return await Promise.all(getDimensionsPromises);
+ return await Promise.all(
+ panels.map(async panel => {
+ const size = await panel.getSize();
+ return {
+ width: size.width,
+ height: size.height,
+ };
+ })
+ );
}
- async getPanelCount() {
+ public async getPanelCount() {
log.debug('getPanelCount');
const panels = await testSubjects.findAll('embeddablePanel');
return panels.length;
}
- getTestVisualizations() {
+ public getTestVisualizations() {
return [
{ name: PIE_CHART_VIS_NAME, description: 'PieChart' },
{ name: 'Visualization☺ VerticalBarChart', description: 'VerticalBarChart' },
@@ -513,69 +403,45 @@ export function DashboardPageProvider({ getService, getPageObjects }) {
];
}
- getTestVisualizationNames() {
+ public getTestVisualizationNames() {
return this.getTestVisualizations().map(visualization => visualization.name);
}
- getTestVisualizationDescriptions() {
+ public getTestVisualizationDescriptions() {
return this.getTestVisualizations().map(visualization => visualization.description);
}
- async getDashboardPanels() {
+ public async getDashboardPanels() {
return await testSubjects.findAll('embeddablePanel');
}
- async addVisualizations(visualizations) {
+ public async addVisualizations(visualizations: string[]) {
await dashboardAddPanel.addVisualizations(visualizations);
}
- async setTimepickerInHistoricalDataRange() {
- await PageObjects.timePicker.setDefaultAbsoluteRange();
- }
-
- async setTimepickerInDataRange() {
- const fromTime = 'Jan 1, 2018 @ 00:00:00.000';
- const toTime = 'Apr 13, 2018 @ 00:00:00.000';
- await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
- }
-
- async setTimepickerInLogstashDataRange() {
- const fromTime = 'Apr 9, 2018 @ 00:00:00.000';
- const toTime = 'Apr 13, 2018 @ 00:00:00.000';
- await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime);
- }
-
- async setSaveAsNewCheckBox(checked) {
+ public async setSaveAsNewCheckBox(checked: boolean) {
log.debug('saveAsNewCheckbox: ' + checked);
- const saveAsNewCheckbox = await testSubjects.find('saveAsNewCheckbox');
+ let saveAsNewCheckbox = await testSubjects.find('saveAsNewCheckbox');
const isAlreadyChecked = (await saveAsNewCheckbox.getAttribute('aria-checked')) === 'true';
if (isAlreadyChecked !== checked) {
log.debug('Flipping save as new checkbox');
- const saveAsNewCheckbox = await testSubjects.find('saveAsNewCheckbox');
+ saveAsNewCheckbox = await testSubjects.find('saveAsNewCheckbox');
await retry.try(() => saveAsNewCheckbox.click());
}
}
- async setStoreTimeWithDashboard(checked) {
+ public async setStoreTimeWithDashboard(checked: boolean) {
log.debug('Storing time with dashboard: ' + checked);
- const storeTimeCheckbox = await testSubjects.find('storeTimeWithDashboard');
+ let storeTimeCheckbox = await testSubjects.find('storeTimeWithDashboard');
const isAlreadyChecked = (await storeTimeCheckbox.getAttribute('aria-checked')) === 'true';
if (isAlreadyChecked !== checked) {
log.debug('Flipping store time checkbox');
- const storeTimeCheckbox = await testSubjects.find('storeTimeWithDashboard');
+ storeTimeCheckbox = await testSubjects.find('storeTimeWithDashboard');
await retry.try(() => storeTimeCheckbox.click());
}
}
- async getFilterDescriptions(timeout = defaultFindTimeout) {
- const filters = await find.allByCssSelector(
- '.filter-bar > .filter > .filter-description',
- timeout
- );
- return _.map(filters, async filter => await filter.getVisibleText());
- }
-
- async getSharedItemsCount() {
+ public async getSharedItemsCount() {
log.debug('in getSharedItemsCount');
const attributeName = 'data-shared-items-count';
const element = await find.byCssSelector(`[${attributeName}]`);
@@ -586,13 +452,14 @@ export function DashboardPageProvider({ getService, getPageObjects }) {
throw new Error('no element');
}
- async waitForRenderComplete() {
+ public async waitForRenderComplete() {
log.debug('waitForRenderComplete');
const count = await this.getSharedItemsCount();
+ // eslint-disable-next-line radix
await renderable.waitForRender(parseInt(count));
}
- async getSharedContainerData() {
+ public async getSharedContainerData() {
log.debug('getSharedContainerData');
const sharedContainer = await find.byCssSelector('[data-shared-items-container]');
return {
@@ -602,7 +469,7 @@ export function DashboardPageProvider({ getService, getPageObjects }) {
};
}
- async getPanelSharedItemData() {
+ public async getPanelSharedItemData() {
log.debug('in getPanelSharedItemData');
const sharedItems = await find.allByCssSelector('[data-shared-item]');
return await Promise.all(
@@ -615,17 +482,17 @@ export function DashboardPageProvider({ getService, getPageObjects }) {
);
}
- async checkHideTitle() {
+ public async checkHideTitle() {
log.debug('ensure that you can click on hide title checkbox');
await this.openOptions();
return await testSubjects.click('dashboardPanelTitlesCheckbox');
}
- async expectMissingSaveOption() {
+ public async expectMissingSaveOption() {
await testSubjects.missingOrFail('dashboardSaveMenuItem');
}
- async getNotLoadedVisualizations(vizList) {
+ public async getNotLoadedVisualizations(vizList: string[]) {
const checkList = [];
for (const name of vizList) {
const isPresent = await testSubjects.exists(
diff --git a/test/functional/page_objects/home_page.ts b/test/functional/page_objects/home_page.ts
index cf9eb4332c3e1d..a641fbda023c3b 100644
--- a/test/functional/page_objects/home_page.ts
+++ b/test/functional/page_objects/home_page.ts
@@ -22,7 +22,6 @@ import { FtrProviderContext } from '../ftr_provider_context';
export function HomePageProvider({ getService }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
const retry = getService('retry');
- const find = getService('find');
class HomePage {
async clickSynopsis(title: string) {
@@ -38,12 +37,15 @@ export function HomePageProvider({ getService }: FtrProviderContext) {
}
async isSampleDataSetInstalled(id: string) {
- return await testSubjects.exists(`removeSampleDataSet${id}`);
+ return !(await testSubjects.exists(`addSampleDataSet${id}`));
}
async addSampleDataSet(id: string) {
- await testSubjects.click(`addSampleDataSet${id}`);
- await this._waitForSampleDataLoadingAction(id);
+ const isInstalled = await this.isSampleDataSetInstalled(id);
+ if (!isInstalled) {
+ await testSubjects.click(`addSampleDataSet${id}`);
+ await this._waitForSampleDataLoadingAction(id);
+ }
}
async removeSampleDataSet(id: string) {
@@ -62,13 +64,8 @@ export function HomePageProvider({ getService }: FtrProviderContext) {
}
async launchSampleDataSet(id: string) {
- if (await find.existsByCssSelector(`#sampleDataLinks${id}`)) {
- // omits cloud test failures
- await find.clickByCssSelectorWhenNotDisabled(`#sampleDataLinks${id}`);
- await find.clickByCssSelector('.euiContextMenuItem:nth-of-type(1)');
- } else {
- await testSubjects.click(`launchSampleDataSet${id}`);
- }
+ await this.addSampleDataSet(id);
+ await testSubjects.click(`launchSampleDataSet${id}`);
}
async loadSavedObjects() {
diff --git a/test/functional/page_objects/index.ts b/test/functional/page_objects/index.ts
index 5526243ea2bbde..4ba8ddb0359132 100644
--- a/test/functional/page_objects/index.ts
+++ b/test/functional/page_objects/index.ts
@@ -22,7 +22,6 @@ import { CommonPageProvider } from './common_page';
import { ConsolePageProvider } from './console_page';
// @ts-ignore not TS yet
import { ContextPageProvider } from './context_page';
-// @ts-ignore not TS yet
import { DashboardPageProvider } from './dashboard_page';
// @ts-ignore not TS yet
import { DiscoverPageProvider } from './discover_page';
diff --git a/test/functional/page_objects/time_picker.js b/test/functional/page_objects/time_picker.js
index 8717517f448648..7c676784294784 100644
--- a/test/functional/page_objects/time_picker.js
+++ b/test/functional/page_objects/time_picker.js
@@ -264,6 +264,22 @@ export function TimePickerPageProvider({ getService, getPageObjects }) {
await this.closeQuickSelectTimeMenu();
}
+
+ async setHistoricalDataRange() {
+ await this.setDefaultAbsoluteRange();
+ }
+
+ async setDefaultDataRange() {
+ const fromTime = 'Jan 1, 2018 @ 00:00:00.000';
+ const toTime = 'Apr 13, 2018 @ 00:00:00.000';
+ await this.setAbsoluteRange(fromTime, toTime);
+ }
+
+ async setLogstashDataRange() {
+ const fromTime = 'Apr 9, 2018 @ 00:00:00.000';
+ const toTime = 'Apr 13, 2018 @ 00:00:00.000';
+ await this.setAbsoluteRange(fromTime, toTime);
+ }
}
return new TimePickerPage();
diff --git a/test/functional/page_objects/visualize_chart_page.ts b/test/functional/page_objects/visualize_chart_page.ts
index 138e5758ede7cd..0f14489a39dbce 100644
--- a/test/functional/page_objects/visualize_chart_page.ts
+++ b/test/functional/page_objects/visualize_chart_page.ts
@@ -204,8 +204,7 @@ export function VisualizeChartPageProvider({ getService, getPageObjects }: FtrPr
public async filterLegend(name: string) {
await this.toggleLegend();
await testSubjects.click(`legend-${name}`);
- const filters = await testSubjects.find(`legend-${name}-filters`);
- const [filterIn] = await filters.findAllByCssSelector(`input`);
+ const filterIn = await testSubjects.find(`legend-${name}-filterIn`);
await filterIn.click();
await this.waitForVisualizationRenderingStabilized();
}
diff --git a/test/functional/page_objects/visualize_editor_page.ts b/test/functional/page_objects/visualize_editor_page.ts
index 7e512975356f3b..30e13d551fa28d 100644
--- a/test/functional/page_objects/visualize_editor_page.ts
+++ b/test/functional/page_objects/visualize_editor_page.ts
@@ -97,8 +97,9 @@ export function VisualizeEditorPageProvider({ getService, getPageObjects }: FtrP
}
public async clickSplitDirection(direction: string) {
- const control = await testSubjects.find('visEditorSplitBy');
- const radioBtn = await control.findByCssSelector(`[title="${direction}"]`);
+ const radioBtn = await find.byCssSelector(
+ `[data-test-subj="visEditorSplitBy"][title="${direction}"]`
+ );
await radioBtn.click();
}
diff --git a/test/functional/page_objects/visualize_page.ts b/test/functional/page_objects/visualize_page.ts
index 4ba64ea771effe..0071b8d993f706 100644
--- a/test/functional/page_objects/visualize_page.ts
+++ b/test/functional/page_objects/visualize_page.ts
@@ -44,15 +44,7 @@ export function VisualizePageProvider({ getService, getPageObjects }: FtrProvide
}
public async clickNewVisualization() {
- // newItemButton button is only visible when there are items in the listing table is displayed.
- let exists = await testSubjects.exists('newItemButton');
- if (exists) {
- return await testSubjects.click('newItemButton');
- }
-
- exists = await testSubjects.exists('createVisualizationPromptButton');
- // no viz exist, click createVisualizationPromptButton to create new dashboard
- return await this.createVisualizationPromptButton();
+ await listingTable.clickNewButton('createVisualizationPromptButton');
}
public async createVisualizationPromptButton() {
diff --git a/test/functional/services/dashboard/visualizations.js b/test/functional/services/dashboard/visualizations.js
index 5e722ccce89701..f7a6fb7d2f694f 100644
--- a/test/functional/services/dashboard/visualizations.js
+++ b/test/functional/services/dashboard/visualizations.js
@@ -24,7 +24,14 @@ export function DashboardVisualizationProvider({ getService, getPageObjects }) {
const queryBar = getService('queryBar');
const testSubjects = getService('testSubjects');
const dashboardAddPanel = getService('dashboardAddPanel');
- const PageObjects = getPageObjects(['dashboard', 'visualize', 'visEditor', 'header', 'discover']);
+ const PageObjects = getPageObjects([
+ 'dashboard',
+ 'visualize',
+ 'visEditor',
+ 'header',
+ 'discover',
+ 'timePicker',
+ ]);
return new (class DashboardVisualizations {
async createAndAddTSVBVisualization(name) {
@@ -43,7 +50,7 @@ export function DashboardVisualizationProvider({ getService, getPageObjects }) {
log.debug(`createSavedSearch(${name})`);
await PageObjects.header.clickDiscover();
- await PageObjects.dashboard.setTimepickerInHistoricalDataRange();
+ await PageObjects.timePicker.setHistoricalDataRange();
if (query) {
await queryBar.setQuery(query);
diff --git a/test/functional/services/listing_table.ts b/test/functional/services/listing_table.ts
index ec886cf694f2e4..c7667ae7b4049e 100644
--- a/test/functional/services/listing_table.ts
+++ b/test/functional/services/listing_table.ts
@@ -25,20 +25,35 @@ export function ListingTableProvider({ getService, getPageObjects }: FtrProvider
const log = getService('log');
const retry = getService('retry');
const { common, header } = getPageObjects(['common', 'header']);
+ const prefixMap = { visualize: 'vis', dashboard: 'dashboard' };
+ /**
+ * This class provides functions for dashboard and visualize landing pages
+ */
class ListingTable {
- public async getSearchFilter() {
+ private async getSearchFilter() {
const searchFilter = await find.allByCssSelector('.euiFieldSearch');
return searchFilter[0];
}
- public async clearFilter() {
+ /**
+ * Returns search input value on landing page
+ */
+ public async getSearchFilterValue() {
+ const searchFilter = await this.getSearchFilter();
+ return await searchFilter.getAttribute('value');
+ }
+
+ /**
+ * Clears search input on landing page
+ */
+ public async clearSearchFilter() {
const searchFilter = await this.getSearchFilter();
await searchFilter.clearValue();
await searchFilter.click();
}
- public async getAllVisualizationNamesOnCurrentPage(): Promise {
+ private async getAllItemsNamesOnCurrentPage(): Promise {
const visualizationNames = [];
const links = await find.allByCssSelector('.kuiLink');
for (let i = 0; i < links.length; i++) {
@@ -48,14 +63,39 @@ export function ListingTableProvider({ getService, getPageObjects }: FtrProvider
return visualizationNames;
}
+ /**
+ * Navigates through all pages on Landing page and returns array of items names
+ */
+ public async getAllItemsNames(): Promise {
+ log.debug('ListingTable.getAllItemsNames');
+ let morePages = true;
+ let visualizationNames: string[] = [];
+ while (morePages) {
+ visualizationNames = visualizationNames.concat(await this.getAllItemsNamesOnCurrentPage());
+ morePages = !((await testSubjects.getAttribute('pagerNextButton', 'disabled')) === 'true');
+ if (morePages) {
+ await testSubjects.click('pagerNextButton');
+ await header.waitUntilLoadingHasFinished();
+ }
+ }
+ return visualizationNames;
+ }
+
+ /**
+ * Returns items count on landing page
+ * @param appName 'visualize' | 'dashboard'
+ */
public async getItemsCount(appName: 'visualize' | 'dashboard'): Promise {
- const prefixMap = { visualize: 'vis', dashboard: 'dashboard' };
const elements = await find.allByCssSelector(
`[data-test-subj^="${prefixMap[appName]}ListingTitleLink"]`
);
return elements.length;
}
+ /**
+ * Types name into search field on Landing page and waits till search completed
+ * @param name item name
+ */
public async searchForItemWithName(name: string) {
log.debug(`searchForItemWithName: ${name}`);
@@ -71,10 +111,51 @@ export function ListingTableProvider({ getService, getPageObjects }: FtrProvider
await header.waitUntilLoadingHasFinished();
}
+ /**
+ * Searches for item on Landing page and retruns items count that match `ListingTitleLink-${name}` pattern
+ * @param appName 'visualize' | 'dashboard'
+ * @param name item name
+ */
+ public async searchAndGetItemsCount(appName: 'visualize' | 'dashboard', name: string) {
+ await this.searchForItemWithName(name);
+ const links = await testSubjects.findAll(
+ `${prefixMap[appName]}ListingTitleLink-${name.replace(/ /g, '-')}`
+ );
+ return links.length;
+ }
+
public async clickDeleteSelected() {
await testSubjects.click('deleteSelectedItems');
}
+ public async clickItemCheckbox(id: string) {
+ await testSubjects.click(`checkboxSelectRow-${id}`);
+ }
+
+ /**
+ * Searches for item by name, selects checbox and deletes it
+ * @param name item name
+ * @param id row id
+ */
+ public async deleteItem(name: string, id: string) {
+ await this.searchForItemWithName(name);
+ await this.clickItemCheckbox(id);
+ await this.clickDeleteSelected();
+ await common.clickConfirmOnModal();
+ }
+
+ /**
+ * Clicks item on Landing page by link name if it is present
+ * @param appName 'dashboard' | 'visualize'
+ * @param name item name
+ */
+ public async clickItemLink(appName: 'dashboard' | 'visualize', name: string) {
+ await testSubjects.click(`${appName}ListingTitleLink-${name.split(' ').join('-')}`);
+ }
+
+ /**
+ * Checks 'SelectAll' checkbox on
+ */
public async checkListingSelectAllCheckbox() {
const element = await testSubjects.find('checkboxSelectAll');
const isSelected = await element.isSelected();
@@ -84,21 +165,20 @@ export function ListingTableProvider({ getService, getPageObjects }: FtrProvider
}
}
- public async getAllVisualizationNames(): Promise {
- log.debug('ListingTable.getAllVisualizationNames');
- let morePages = true;
- let visualizationNames: string[] = [];
- while (morePages) {
- visualizationNames = visualizationNames.concat(
- await this.getAllVisualizationNamesOnCurrentPage()
- );
- morePages = !((await testSubjects.getAttribute('pagerNextButton', 'disabled')) === 'true');
- if (morePages) {
- await testSubjects.click('pagerNextButton');
- await header.waitUntilLoadingHasFinished();
+ /**
+ * Clicks NewItem button on Landing page
+ * @param promptBtnTestSubj testSubj locator for Prompt button
+ */
+ public async clickNewButton(promptBtnTestSubj: string): Promise {
+ await retry.try(async () => {
+ // newItemButton button is only visible when there are items in the listing table is displayed.
+ if (await testSubjects.exists('newItemButton')) {
+ await testSubjects.click('newItemButton');
+ } else {
+ // no items exist, click createPromptButton to create new dashboard/visualization
+ await testSubjects.click(promptBtnTestSubj);
}
- }
- return visualizationNames;
+ });
}
}
diff --git a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json
index 02c507dbb3ed8e..1eac93c8538e40 100644
--- a/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json
+++ b/test/interpreter_functional/plugins/kbn_tp_run_pipeline/package.json
@@ -7,7 +7,7 @@
},
"license": "Apache-2.0",
"dependencies": {
- "@elastic/eui": "17.3.1",
+ "@elastic/eui": "18.0.0",
"react": "^16.12.0",
"react-dom": "^16.12.0"
}
diff --git a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json
index 67ad28c083dbcf..1bfb1e8ba4bcad 100644
--- a/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json
+++ b/test/plugin_functional/plugins/kbn_tp_custom_visualizations/package.json
@@ -7,7 +7,7 @@
},
"license": "Apache-2.0",
"dependencies": {
- "@elastic/eui": "17.3.1",
+ "@elastic/eui": "18.0.0",
"react": "^16.12.0"
}
}
diff --git a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json
index b22a1ff2d4176b..6d6b04fba889c3 100644
--- a/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json
+++ b/test/plugin_functional/plugins/kbn_tp_embeddable_explorer/package.json
@@ -8,7 +8,7 @@
},
"license": "Apache-2.0",
"dependencies": {
- "@elastic/eui": "17.3.1",
+ "@elastic/eui": "18.0.0",
"react": "^16.12.0"
},
"scripts": {
diff --git a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json
index 8c91826d7b450c..964adacb2ac09e 100644
--- a/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json
+++ b/test/plugin_functional/plugins/kbn_tp_sample_panel_action/package.json
@@ -8,7 +8,7 @@
},
"license": "Apache-2.0",
"dependencies": {
- "@elastic/eui": "17.3.1",
+ "@elastic/eui": "18.0.0",
"react": "^16.12.0"
},
"scripts": {
diff --git a/test/plugin_functional/test_suites/core_plugins/applications.ts b/test/plugin_functional/test_suites/core_plugins/applications.ts
index a3c9d9d63e3534..231458fad155b3 100644
--- a/test/plugin_functional/test_suites/core_plugins/applications.ts
+++ b/test/plugin_functional/test_suites/core_plugins/applications.ts
@@ -27,12 +27,18 @@ export default function({ getService, getPageObjects }: PluginFunctionalProvider
const browser = getService('browser');
const appsMenu = getService('appsMenu');
const testSubjects = getService('testSubjects');
+ const find = getService('find');
const loadingScreenNotShown = async () =>
expect(await testSubjects.exists('kbnLoadingMessage')).to.be(false);
const loadingScreenShown = () => testSubjects.existOrFail('kbnLoadingMessage');
+ const getAppWrapperWidth = async () => {
+ const wrapper = await find.byClassName('app-wrapper');
+ return (await wrapper.getSize()).width;
+ };
+
const getKibanaUrl = (pathname?: string, search?: string) =>
url.format({
protocol: 'http:',
@@ -99,12 +105,20 @@ export default function({ getService, getPageObjects }: PluginFunctionalProvider
await PageObjects.common.navigateToApp('chromeless');
await loadingScreenNotShown();
expect(await testSubjects.exists('headerGlobalNav')).to.be(false);
+
+ const wrapperWidth = await getAppWrapperWidth();
+ const windowWidth = (await browser.getWindowSize()).width;
+ expect(wrapperWidth).to.eql(windowWidth);
});
it('navigating away from chromeless application shows chrome', async () => {
await PageObjects.common.navigateToApp('foo');
await loadingScreenNotShown();
expect(await testSubjects.exists('headerGlobalNav')).to.be(true);
+
+ const wrapperWidth = await getAppWrapperWidth();
+ const windowWidth = (await browser.getWindowSize()).width;
+ expect(wrapperWidth).to.be.below(windowWidth);
});
it.skip('can navigate from NP apps to legacy apps', async () => {
diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json
index 7e86d2f1dc4357..71e3bdd6c8c846 100644
--- a/x-pack/.i18nrc.json
+++ b/x-pack/.i18nrc.json
@@ -4,6 +4,7 @@
"xpack.actions": "legacy/plugins/actions",
"xpack.advancedUiActions": "plugins/advanced_ui_actions",
"xpack.alerting": "legacy/plugins/alerting",
+ "xpack.triggersActionsUI": "legacy/plugins/triggers_actions_ui",
"xpack.apm": "legacy/plugins/apm",
"xpack.beatsManagement": "legacy/plugins/beats_management",
"xpack.canvas": "legacy/plugins/canvas",
diff --git a/x-pack/index.js b/x-pack/index.js
index 56547f89b1e906..83a7b5540334f6 100644
--- a/x-pack/index.js
+++ b/x-pack/index.js
@@ -42,6 +42,7 @@ import { transform } from './legacy/plugins/transform';
import { actions } from './legacy/plugins/actions';
import { alerting } from './legacy/plugins/alerting';
import { lens } from './legacy/plugins/lens';
+import { triggersActionsUI } from './legacy/plugins/triggers_actions_ui';
module.exports = function(kibana) {
return [
@@ -83,5 +84,6 @@ module.exports = function(kibana) {
snapshotRestore(kibana),
actions(kibana),
alerting(kibana),
+ triggersActionsUI(kibana),
];
};
diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/email.test.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/email.test.ts
index 4aaecc8e9d7df4..74263c603c11e9 100644
--- a/x-pack/legacy/plugins/actions/server/builtin_action_types/email.test.ts
+++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/email.test.ts
@@ -49,7 +49,7 @@ beforeEach(() => {
describe('actionTypeRegistry.get() works', () => {
test('action type static data is as expected', () => {
expect(actionType.id).toEqual(ACTION_TYPE_ID);
- expect(actionType.name).toEqual('email');
+ expect(actionType.name).toEqual('Email');
});
});
diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/email.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/email.ts
index dd2bd328ce53fe..94d7852e76fad7 100644
--- a/x-pack/legacy/plugins/actions/server/builtin_action_types/email.ts
+++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/email.ts
@@ -118,7 +118,9 @@ export function getActionType(params: GetActionTypeParams): ActionType {
const { logger, configurationUtilities } = params;
return {
id: '.email',
- name: 'email',
+ name: i18n.translate('xpack.actions.builtin.emailTitle', {
+ defaultMessage: 'Email',
+ }),
validate: {
config: schema.object(ConfigSchemaProps, {
validate: curry(validateConfig)(configurationUtilities),
diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.test.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.test.ts
index 1da8b06e1587a9..dbac84ef681f19 100644
--- a/x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.test.ts
+++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.test.ts
@@ -37,7 +37,7 @@ beforeEach(() => {
describe('actionTypeRegistry.get() works', () => {
test('action type static data is as expected', () => {
expect(actionType.id).toEqual(ACTION_TYPE_ID);
- expect(actionType.name).toEqual('index');
+ expect(actionType.name).toEqual('Index');
});
});
diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.ts
index 0e9fe0483ee1ea..ddf33ba63f71af 100644
--- a/x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.ts
+++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.ts
@@ -38,7 +38,9 @@ const ParamsSchema = schema.object({
export function getActionType({ logger }: { logger: Logger }): ActionType {
return {
id: '.index',
- name: 'index',
+ name: i18n.translate('xpack.actions.builtin.esIndexTitle', {
+ defaultMessage: 'Index',
+ }),
validate: {
config: ConfigSchema,
params: ParamsSchema,
diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.test.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.test.ts
index cb3548524ebbb6..f60fdf7fef95e1 100644
--- a/x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.test.ts
+++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.test.ts
@@ -38,7 +38,7 @@ beforeAll(() => {
describe('get()', () => {
test('should return correct action type', () => {
expect(actionType.id).toEqual(ACTION_TYPE_ID);
- expect(actionType.name).toEqual('pagerduty');
+ expect(actionType.name).toEqual('PagerDuty');
});
});
diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.ts
index 250c169278c571..b26621702cf5be 100644
--- a/x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.ts
+++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/pagerduty.ts
@@ -96,7 +96,9 @@ export function getActionType({
}): ActionType {
return {
id: '.pagerduty',
- name: 'pagerduty',
+ name: i18n.translate('xpack.actions.builtin.pagerdutyTitle', {
+ defaultMessage: 'PagerDuty',
+ }),
validate: {
config: schema.object(configSchemaProps, {
validate: curry(valdiateActionTypeConfig)(configurationUtilities),
diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.test.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.test.ts
index c59ddf97017fdc..8f28b9e8f51254 100644
--- a/x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.test.ts
+++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.test.ts
@@ -25,7 +25,7 @@ beforeAll(() => {
describe('get()', () => {
test('returns action type', () => {
expect(actionType.id).toEqual(ACTION_TYPE_ID);
- expect(actionType.name).toEqual('server-log');
+ expect(actionType.name).toEqual('Server log');
});
});
@@ -98,6 +98,6 @@ describe('execute()', () => {
config: {},
secrets: {},
});
- expect(mockedLogger.info).toHaveBeenCalledWith('server-log: message text here');
+ expect(mockedLogger.info).toHaveBeenCalledWith('Server log: message text here');
});
});
diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.ts
index 0edf409e4d46c6..34b8602eeba368 100644
--- a/x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.ts
+++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.ts
@@ -12,7 +12,7 @@ import { Logger } from '../../../../../../src/core/server';
import { ActionType, ActionTypeExecutorOptions, ActionTypeExecutorResult } from '../types';
import { withoutControlCharacters } from './lib/string_utils';
-const ACTION_NAME = 'server-log';
+const ACTION_NAME = 'Server log';
// params definition
diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/slack.test.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/slack.test.ts
index a2b0db8bdb70f0..aebc9c49935997 100644
--- a/x-pack/legacy/plugins/actions/server/builtin_action_types/slack.test.ts
+++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/slack.test.ts
@@ -29,7 +29,7 @@ beforeAll(() => {
describe('action registeration', () => {
test('returns action type', () => {
expect(actionType.id).toEqual(ACTION_TYPE_ID);
- expect(actionType.name).toEqual('slack');
+ expect(actionType.name).toEqual('Slack');
});
});
diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/slack.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/slack.ts
index 92611d6f162ffb..b8989e59a22579 100644
--- a/x-pack/legacy/plugins/actions/server/builtin_action_types/slack.ts
+++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/slack.ts
@@ -49,7 +49,9 @@ export function getActionType({
}): ActionType {
return {
id: '.slack',
- name: 'slack',
+ name: i18n.translate('xpack.actions.builtin.slackTitle', {
+ defaultMessage: 'Slack',
+ }),
validate: {
secrets: schema.object(secretsSchemaProps, {
validate: curry(valdiateActionTypeConfig)(configurationUtilities),
diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/webhook.test.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/webhook.test.ts
index 64dd3a485f8e21..b95fef97ac7b9a 100644
--- a/x-pack/legacy/plugins/actions/server/builtin_action_types/webhook.test.ts
+++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/webhook.test.ts
@@ -25,7 +25,7 @@ beforeAll(() => {
describe('actionType', () => {
test('exposes the action as `webhook` on its Id and Name', () => {
expect(actionType.id).toEqual('.webhook');
- expect(actionType.name).toEqual('webhook');
+ expect(actionType.name).toEqual('Webhook');
});
});
diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/webhook.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/webhook.ts
index 06fe2fb0e591c0..fa88d3c72c1631 100644
--- a/x-pack/legacy/plugins/actions/server/builtin_action_types/webhook.ts
+++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/webhook.ts
@@ -56,7 +56,9 @@ export function getActionType({
}): ActionType {
return {
id: '.webhook',
- name: 'webhook',
+ name: i18n.translate('xpack.actions.builtin.webhookTitle', {
+ defaultMessage: 'Webhook',
+ }),
validate: {
config: schema.object(configSchemaProps, {
validate: curry(valdiateActionTypeConfig)(configurationUtilities),
diff --git a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/__snapshots__/waterfall_helpers.test.ts.snap b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/__snapshots__/waterfall_helpers.test.ts.snap
index ece396bc4cfc4f..c95855c117047c 100644
--- a/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/__snapshots__/waterfall_helpers.test.ts.snap
+++ b/x-pack/legacy/plugins/apm/public/components/app/TransactionDetails/WaterfallWithSummmary/WaterfallContainer/Waterfall/waterfall_helpers/__snapshots__/waterfall_helpers.test.ts.snap
@@ -808,8 +808,8 @@ Object {
},
},
"serviceColors": Object {
- "opbeans-node": "#3185fc",
- "opbeans-ruby": "#00b3a4",
+ "opbeans-node": "#6092c0",
+ "opbeans-ruby": "#5bbaa0",
},
}
`;
@@ -1212,7 +1212,7 @@ Object {
},
},
"serviceColors": Object {
- "opbeans-ruby": "#3185fc",
+ "opbeans-ruby": "#6092c0",
},
}
`;
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/ManagedTable/__test__/__snapshots__/ManagedTable.test.js.snap b/x-pack/legacy/plugins/apm/public/components/shared/ManagedTable/__test__/__snapshots__/ManagedTable.test.js.snap
index 59679bfe116418..655fc5a25b9ef5 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/ManagedTable/__test__/__snapshots__/ManagedTable.test.js.snap
+++ b/x-pack/legacy/plugins/apm/public/components/shared/ManagedTable/__test__/__snapshots__/ManagedTable.test.js.snap
@@ -52,6 +52,7 @@ exports[`ManagedTable component should render a page-full of items, with default
},
}
}
+ tableLayout="fixed"
/>
`;
@@ -99,5 +100,6 @@ exports[`ManagedTable component should render when specifying initial values 1`]
},
}
}
+ tableLayout="fixed"
/>
`;
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/SelectWithPlaceholder/index.tsx b/x-pack/legacy/plugins/apm/public/components/shared/SelectWithPlaceholder/index.tsx
index 25f8128b272112..a8e6bc0a648af5 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/SelectWithPlaceholder/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/shared/SelectWithPlaceholder/index.tsx
@@ -20,7 +20,7 @@ export const SelectWithPlaceholder: typeof EuiSelect = props => (
{...props}
options={[
{ text: props.placeholder, value: NO_SELECTION },
- ...props.options
+ ...(props.options || [])
]}
value={isEmpty(props.value) ? NO_SELECTION : props.value}
onChange={e => {
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/FrameHeading.tsx b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/FrameHeading.tsx
index 84c2801a45049b..51056fae503602 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/FrameHeading.tsx
+++ b/x-pack/legacy/plugins/apm/public/components/shared/Stacktrace/FrameHeading.tsx
@@ -35,9 +35,13 @@ const FrameHeading: React.FC = ({ stackframe, isLibraryFrame }) => {
? LibraryFrameFileDetail
: AppFrameFileDetail;
const lineNumber = stackframe.line.number;
+
+ const name =
+ 'filename' in stackframe ? stackframe.filename : stackframe.classname;
+
return (
- {stackframe.filename} in{' '}
+ {name} in{' '}
{stackframe.function}
{lineNumber > 0 && (
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/charts/CustomPlot/test/__snapshots__/CustomPlot.test.js.snap b/x-pack/legacy/plugins/apm/public/components/shared/charts/CustomPlot/test/__snapshots__/CustomPlot.test.js.snap
index 557751a0f02268..1bf125c3016448 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/charts/CustomPlot/test/__snapshots__/CustomPlot.test.js.snap
+++ b/x-pack/legacy/plugins/apm/public/components/shared/charts/CustomPlot/test/__snapshots__/CustomPlot.test.js.snap
@@ -3,7 +3,7 @@
exports[`when response has data Initially should have 3 legends 1`] = `
Array [
Object {
- "color": "#3185fc",
+ "color": "#6092c0",
"disabled": undefined,
"onClick": [Function],
"text":
@@ -14,7 +14,7 @@ Array [
,
},
Object {
- "color": "#e6c220",
+ "color": "#fae181",
"disabled": undefined,
"onClick": [Function],
"text":
@@ -22,7 +22,7 @@ Array [
,
},
Object {
- "color": "#f98510",
+ "color": "#f19f58",
"disabled": undefined,
"onClick": [Function],
"text":
@@ -442,7 +442,7 @@ Array [
style={
Object {
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeDasharray": undefined,
"strokeWidth": undefined,
}
@@ -463,9 +463,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -480,9 +480,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -497,9 +497,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -514,9 +514,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -531,9 +531,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -548,9 +548,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -565,9 +565,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -582,9 +582,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -599,9 +599,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -616,9 +616,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -633,9 +633,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -650,9 +650,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -667,9 +667,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -684,9 +684,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -701,9 +701,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -718,9 +718,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -735,9 +735,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -752,9 +752,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -769,9 +769,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -786,9 +786,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -803,9 +803,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -820,9 +820,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -837,9 +837,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -854,9 +854,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -871,9 +871,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -888,9 +888,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -905,9 +905,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -922,9 +922,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -939,9 +939,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -956,9 +956,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -973,9 +973,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -995,7 +995,7 @@ Array [
style={
Object {
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeDasharray": undefined,
"strokeWidth": undefined,
}
@@ -1016,9 +1016,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1033,9 +1033,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1050,9 +1050,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1067,9 +1067,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1084,9 +1084,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1101,9 +1101,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1118,9 +1118,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1135,9 +1135,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1152,9 +1152,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1169,9 +1169,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1186,9 +1186,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1203,9 +1203,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1220,9 +1220,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1237,9 +1237,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1254,9 +1254,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1271,9 +1271,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1288,9 +1288,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1305,9 +1305,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1322,9 +1322,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1339,9 +1339,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1356,9 +1356,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1373,9 +1373,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1390,9 +1390,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1407,9 +1407,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1424,9 +1424,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1441,9 +1441,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1458,9 +1458,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1475,9 +1475,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1492,9 +1492,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1509,9 +1509,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1526,9 +1526,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -1548,7 +1548,7 @@ Array [
style={
Object {
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeDasharray": undefined,
"strokeWidth": undefined,
}
@@ -1569,9 +1569,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1586,9 +1586,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1603,9 +1603,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1620,9 +1620,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1637,9 +1637,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1654,9 +1654,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1671,9 +1671,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1688,9 +1688,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1705,9 +1705,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1722,9 +1722,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1739,9 +1739,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1756,9 +1756,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1773,9 +1773,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1790,9 +1790,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1807,9 +1807,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1824,9 +1824,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1841,9 +1841,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1858,9 +1858,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1875,9 +1875,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1892,9 +1892,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1909,9 +1909,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1926,9 +1926,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1943,9 +1943,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1960,9 +1960,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1977,9 +1977,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -1994,9 +1994,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -2011,9 +2011,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -2028,9 +2028,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -2045,9 +2045,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -2062,9 +2062,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -2079,9 +2079,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -2651,7 +2651,7 @@ Array [
width: 11px;
height: 11px;
margin-right: 5.5px;
- background: #3185fc;
+ background: #6092c0;
border-radius: 100%;
}
@@ -2659,7 +2659,7 @@ Array [
width: 11px;
height: 11px;
margin-right: 5.5px;
- background: #e6c220;
+ background: #fae181;
border-radius: 100%;
}
@@ -2667,7 +2667,7 @@ Array [
width: 11px;
height: 11px;
margin-right: 5.5px;
- background: #f98510;
+ background: #f19f58;
border-radius: 100%;
}
@@ -2723,14 +2723,14 @@ Array [
onClick={[Function]}
>
@@ -2764,14 +2764,14 @@ Array [
onClick={[Function]}
>
@@ -2798,14 +2798,14 @@ Array [
onClick={[Function]}
>
@@ -2849,17 +2849,17 @@ exports[`when response has data when dragging without releasing should display S
exports[`when response has data when setting hoverX should display tooltip 1`] = `
Array [
Object {
- "color": "#3185fc",
+ "color": "#6092c0",
"text": "Avg.",
"value": 438704.4,
},
Object {
- "color": "#e6c220",
+ "color": "#fae181",
"text": "95th",
"value": 1557383.999999999,
},
Object {
- "color": "#f98510",
+ "color": "#f19f58",
"text": "99th",
"value": 1820377.1200000006,
},
@@ -2891,7 +2891,7 @@ Array [
width: 8px;
height: 8px;
margin-right: 4px;
- background: #3185fc;
+ background: #6092c0;
border-radius: 100%;
}
@@ -2899,7 +2899,7 @@ Array [
width: 8px;
height: 8px;
margin-right: 4px;
- background: #e6c220;
+ background: #fae181;
border-radius: 100%;
}
@@ -2907,7 +2907,7 @@ Array [
width: 8px;
height: 8px;
margin-right: 4px;
- background: #f98510;
+ background: #f19f58;
border-radius: 100%;
}
@@ -3378,7 +3378,7 @@ Array [
style={
Object {
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeDasharray": undefined,
"strokeWidth": undefined,
}
@@ -3399,9 +3399,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3416,9 +3416,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3433,9 +3433,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3450,9 +3450,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3467,9 +3467,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3484,9 +3484,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3501,9 +3501,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3518,9 +3518,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3535,9 +3535,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3552,9 +3552,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3569,9 +3569,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3586,9 +3586,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3603,9 +3603,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3620,9 +3620,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3637,9 +3637,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3654,9 +3654,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3671,9 +3671,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3688,9 +3688,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3705,9 +3705,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3722,9 +3722,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3739,9 +3739,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3756,9 +3756,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3773,9 +3773,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3790,9 +3790,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3807,9 +3807,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3824,9 +3824,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3841,9 +3841,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3858,9 +3858,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3875,9 +3875,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3892,9 +3892,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3909,9 +3909,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -3931,7 +3931,7 @@ Array [
style={
Object {
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeDasharray": undefined,
"strokeWidth": undefined,
}
@@ -3952,9 +3952,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -3969,9 +3969,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -3986,9 +3986,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4003,9 +4003,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4020,9 +4020,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4037,9 +4037,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4054,9 +4054,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4071,9 +4071,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4088,9 +4088,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4105,9 +4105,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4122,9 +4122,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4139,9 +4139,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4156,9 +4156,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4173,9 +4173,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4190,9 +4190,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4207,9 +4207,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4224,9 +4224,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4241,9 +4241,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4258,9 +4258,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4275,9 +4275,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4292,9 +4292,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4309,9 +4309,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4326,9 +4326,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4343,9 +4343,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4360,9 +4360,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4377,9 +4377,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4394,9 +4394,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4411,9 +4411,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4428,9 +4428,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4445,9 +4445,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4462,9 +4462,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -4484,7 +4484,7 @@ Array [
style={
Object {
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeDasharray": undefined,
"strokeWidth": undefined,
}
@@ -4505,9 +4505,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4522,9 +4522,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4539,9 +4539,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4556,9 +4556,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4573,9 +4573,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4590,9 +4590,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4607,9 +4607,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4624,9 +4624,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4641,9 +4641,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4658,9 +4658,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4675,9 +4675,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4692,9 +4692,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4709,9 +4709,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4726,9 +4726,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4743,9 +4743,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4760,9 +4760,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4777,9 +4777,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4794,9 +4794,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4811,9 +4811,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4828,9 +4828,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4845,9 +4845,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4862,9 +4862,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4879,9 +4879,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4896,9 +4896,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4913,9 +4913,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4930,9 +4930,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4947,9 +4947,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4964,9 +4964,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4981,9 +4981,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -4998,9 +4998,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -5015,9 +5015,9 @@ Array [
r={0.5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -5072,9 +5072,9 @@ Array [
r={5}
style={
Object {
- "fill": "#f98510",
+ "fill": "#f19f58",
"opacity": 1,
- "stroke": "#f98510",
+ "stroke": "#f19f58",
"strokeWidth": 1,
}
}
@@ -5089,9 +5089,9 @@ Array [
r={5}
style={
Object {
- "fill": "#e6c220",
+ "fill": "#fae181",
"opacity": 1,
- "stroke": "#e6c220",
+ "stroke": "#fae181",
"strokeWidth": 1,
}
}
@@ -5106,9 +5106,9 @@ Array [
r={5}
style={
Object {
- "fill": "#3185fc",
+ "fill": "#6092c0",
"opacity": 1,
- "stroke": "#3185fc",
+ "stroke": "#6092c0",
"strokeWidth": 1,
}
}
@@ -5158,7 +5158,7 @@ Array [
className="c3"
>
@@ -5174,14 +5174,14 @@ Array [
fontSize="12px"
>
@@ -5204,7 +5204,7 @@ Array [
className="c3"
>
@@ -5220,14 +5220,14 @@ Array [
fontSize="12px"
>
@@ -5250,7 +5250,7 @@ Array [
className="c3"
>
@@ -5266,14 +5266,14 @@ Array [
fontSize="12px"
>
@@ -5830,7 +5830,7 @@ Array [
width: 11px;
height: 11px;
margin-right: 5.5px;
- background: #3185fc;
+ background: #6092c0;
border-radius: 100%;
}
@@ -5838,7 +5838,7 @@ Array [
width: 11px;
height: 11px;
margin-right: 5.5px;
- background: #e6c220;
+ background: #fae181;
border-radius: 100%;
}
@@ -5846,7 +5846,7 @@ Array [
width: 11px;
height: 11px;
margin-right: 5.5px;
- background: #f98510;
+ background: #f19f58;
border-radius: 100%;
}
@@ -5902,14 +5902,14 @@ Array [
onClick={[Function]}
>
@@ -5943,14 +5943,14 @@ Array [
onClick={[Function]}
>
@@ -5977,14 +5977,14 @@ Array [
onClick={[Function]}
>
diff --git a/x-pack/legacy/plugins/apm/public/components/shared/charts/Histogram/__test__/__snapshots__/Histogram.test.js.snap b/x-pack/legacy/plugins/apm/public/components/shared/charts/Histogram/__test__/__snapshots__/Histogram.test.js.snap
index da71e264ac0995..f1c7d4826fe0c7 100644
--- a/x-pack/legacy/plugins/apm/public/components/shared/charts/Histogram/__test__/__snapshots__/Histogram.test.js.snap
+++ b/x-pack/legacy/plugins/apm/public/components/shared/charts/Histogram/__test__/__snapshots__/Histogram.test.js.snap
@@ -434,11 +434,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.628571428571433}
@@ -453,11 +453,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.628571428571433}
@@ -472,11 +472,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.62857142857142}
@@ -491,11 +491,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.628571428571433}
@@ -510,11 +510,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.628571428571405}
@@ -529,11 +529,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.62857142857142}
@@ -548,11 +548,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.628571428571405}
@@ -567,11 +567,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.628571428571405}
@@ -586,11 +586,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.628571428571377}
@@ -605,11 +605,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.628571428571462}
@@ -624,11 +624,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.62857142857149}
@@ -643,11 +643,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.62857142857149}
@@ -662,11 +662,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.62857142857149}
@@ -681,11 +681,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.628571428571433}
@@ -700,11 +700,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.628571428571433}
@@ -719,11 +719,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.628571428571433}
@@ -738,11 +738,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.628571428571547}
@@ -757,11 +757,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.62857142857149}
@@ -776,11 +776,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.628571428571547}
@@ -795,11 +795,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.628571428571433}
@@ -814,11 +814,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.628571428571433}
@@ -833,11 +833,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.628571428571377}
@@ -852,11 +852,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.62857142857149}
@@ -871,11 +871,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.62857142857149}
@@ -890,11 +890,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.628571428571604}
@@ -909,11 +909,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.62857142857149}
@@ -928,11 +928,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.62857142857149}
@@ -947,11 +947,11 @@ exports[`Histogram Initially should have default markup 1`] = `
onMouseOver={[Function]}
style={
Object {
- "fill": "#98c2fd",
+ "fill": "#afc8df",
"opacity": 1,
"rx": "0px",
"ry": "0px",
- "stroke": "#98c2fd",
+ "stroke": "#afc8df",
}
}
width={22.628571428571377}
diff --git a/x-pack/legacy/plugins/apm/public/context/LicenseContext/index.tsx b/x-pack/legacy/plugins/apm/public/context/LicenseContext/index.tsx
index 0bd38967826034..62cdbd3bbc995b 100644
--- a/x-pack/legacy/plugins/apm/public/context/LicenseContext/index.tsx
+++ b/x-pack/legacy/plugins/apm/public/context/LicenseContext/index.tsx
@@ -16,8 +16,9 @@ export const LicenseContext = React.createContext(
export function LicenseProvider({ children }: { children: React.ReactChild }) {
const { license$ } = useApmPluginContext().plugins.licensing;
- const license = useObservable(license$, { isActive: true } as ILicense);
- const hasInvalidLicense = !license.isActive;
+ const license = useObservable(license$);
+ // if license is not loaded yet, consider it valid
+ const hasInvalidLicense = license?.isActive === false;
// if license is invalid show an error message
if (hasInvalidLicense) {
diff --git a/x-pack/legacy/plugins/apm/public/selectors/__tests__/chartSelectors.test.ts b/x-pack/legacy/plugins/apm/public/selectors/__tests__/chartSelectors.test.ts
index 2b0263f69db8fa..1218bc726c3b78 100644
--- a/x-pack/legacy/plugins/apm/public/selectors/__tests__/chartSelectors.test.ts
+++ b/x-pack/legacy/plugins/apm/public/selectors/__tests__/chartSelectors.test.ts
@@ -21,7 +21,7 @@ describe('chartSelectors', () => {
it('should return anomalyScoreSeries', () => {
const data = [{ x0: 0, x: 10 }];
expect(getAnomalyScoreSeries(data)).toEqual({
- areaColor: 'rgba(146,0,0,0.1)',
+ areaColor: 'rgba(231,102,76,0.1)',
color: 'none',
data: [{ x0: 0, x: 10 }],
hideLegend: true,
@@ -57,7 +57,7 @@ describe('chartSelectors', () => {
getResponseTimeSeries({ apmTimeseries, anomalyTimeseries: undefined })
).toEqual([
{
- color: '#3185fc',
+ color: '#6092c0',
data: [
{ x: 0, y: 100 },
{ x: 1000, y: 200 }
@@ -67,7 +67,7 @@ describe('chartSelectors', () => {
type: 'linemark'
},
{
- color: '#e6c220',
+ color: '#fae181',
data: [
{ x: 0, y: 200 },
{ x: 1000, y: 300 }
@@ -77,7 +77,7 @@ describe('chartSelectors', () => {
type: 'linemark'
},
{
- color: '#f98510',
+ color: '#f19f58',
data: [
{ x: 0, y: 300 },
{ x: 1000, y: 400 }
diff --git a/x-pack/legacy/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap b/x-pack/legacy/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap
index acd5dc119b737c..bbf2a6882c3c7c 100644
--- a/x-pack/legacy/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap
+++ b/x-pack/legacy/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap
@@ -137,7 +137,6 @@ Object {
"events": Object {
"terms": Object {
"field": "processor.event",
- "size": 2,
},
},
},
diff --git a/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_services_items.ts b/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_services_items.ts
index 8e578a839ae56f..2f44b9231eae29 100644
--- a/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_services_items.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_services_items.ts
@@ -44,7 +44,7 @@ export async function getServicesItems(
terms: { field: SERVICE_AGENT_NAME, size: 1 }
},
events: {
- terms: { field: PROCESSOR_EVENT, size: 2 }
+ terms: { field: PROCESSOR_EVENT }
},
environments: {
terms: { field: SERVICE_ENVIRONMENT }
diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.test.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.test.ts
index f49c1e022a0701..870b02fa7ba6de 100644
--- a/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.test.ts
+++ b/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.test.ts
@@ -70,13 +70,13 @@ describe('getTransactionBreakdown', () => {
expect(response.kpis[0]).toEqual({
name: 'app',
- color: '#00b3a4',
+ color: '#5bbaa0',
percentage: 0.5408550899466306
});
expect(response.kpis[3]).toEqual({
name: 'postgresql',
- color: '#490092',
+ color: '#9170b8',
percentage: 0.047366859295002
});
});
diff --git a/x-pack/legacy/plugins/apm/typings/es_schemas/raw/fields/Stackframe.ts b/x-pack/legacy/plugins/apm/typings/es_schemas/raw/fields/Stackframe.ts
index a1b1a8198bb356..993fac46ad7cb5 100644
--- a/x-pack/legacy/plugins/apm/typings/es_schemas/raw/fields/Stackframe.ts
+++ b/x-pack/legacy/plugins/apm/typings/es_schemas/raw/fields/Stackframe.ts
@@ -4,8 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-interface IStackframeBase {
- filename: string;
+type IStackframeBase = {
function?: string;
library_frame?: boolean;
exclude_from_grouping?: boolean;
@@ -19,13 +18,13 @@ interface IStackframeBase {
line: {
number: number;
};
-}
+} & ({ classname: string } | { filename: string });
-export interface IStackframeWithLineContext extends IStackframeBase {
+export type IStackframeWithLineContext = IStackframeBase & {
line: {
number: number;
context: string;
};
-}
+};
export type IStackframe = IStackframeBase | IStackframeWithLineContext;
diff --git a/x-pack/legacy/plugins/beats_management/public/components/inputs/input.tsx b/x-pack/legacy/plugins/beats_management/public/components/inputs/input.tsx
index 0e07c2b4960b72..29cdcfccfc756c 100644
--- a/x-pack/legacy/plugins/beats_management/public/components/inputs/input.tsx
+++ b/x-pack/legacy/plugins/beats_management/public/components/inputs/input.tsx
@@ -3,12 +3,15 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-import { EuiFieldText, EuiFieldTextProps, EuiFormRow } from '@elastic/eui';
+import { EuiFieldText, EuiFormRow } from '@elastic/eui';
import { CommonProps } from '@elastic/eui/src/components/common';
import { FormsyInputProps, withFormsy } from 'formsy-react';
import React, { Component, InputHTMLAttributes } from 'react';
-interface ComponentProps extends FormsyInputProps, CommonProps, EuiFieldTextProps {
+interface ComponentProps
+ extends FormsyInputProps,
+ CommonProps,
+ Omit, 'onChange' | 'onBlur'> {
instantValidation?: boolean;
label: string;
errorText: string;
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/palette.js b/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/palette.js
index 69f584af41556b..d60dc13f0105b4 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/palette.js
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/palette.js
@@ -61,7 +61,9 @@ const PaletteArgInput = ({ onValueChange, argValue, renderError }) => {
const palette = astToPalette(argValue);
- return ;
+ return (
+
+ );
};
PaletteArgInput.propTypes = {
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/shape.js b/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/shape.js
index c056e7d1f2281c..baa2127b03c3c4 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/shape.js
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/shape.js
@@ -20,6 +20,7 @@ const ShapeArgInput = ({ onValueChange, argValue, typeInstance }) => (
value={argValue}
onChange={onValueChange}
shapes={typeInstance.options.shapes}
+ ariaLabel={typeInstance.displayName}
/>
diff --git a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/toggle.js b/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/toggle.js
index de19d3e29221bb..bcad4678e0b6a8 100644
--- a/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/toggle.js
+++ b/x-pack/legacy/plugins/canvas/canvas_plugin_src/uis/arguments/toggle.js
@@ -12,7 +12,7 @@ import { ArgumentStrings } from '../../../i18n';
const { Toggle: strings } = ArgumentStrings;
-const ToggleArgInput = ({ onValueChange, argValue, argId, renderError }) => {
+const ToggleArgInput = ({ onValueChange, argValue, argId, renderError, typeInstance }) => {
const handleChange = () => onValueChange(!argValue);
if (typeof argValue !== 'boolean') {
renderError();
@@ -26,6 +26,9 @@ const ToggleArgInput = ({ onValueChange, argValue, argId, renderError }) => {
checked={argValue}
onChange={handleChange}
className="canvasArg__switch"
+ aria-label={typeInstance.displayName}
+ label=""
+ showLabel={false}
/>
);
diff --git a/x-pack/legacy/plugins/canvas/i18n/components.ts b/x-pack/legacy/plugins/canvas/i18n/components.ts
index c898db7467b445..d0a9051d7af87b 100644
--- a/x-pack/legacy/plugins/canvas/i18n/components.ts
+++ b/x-pack/legacy/plugins/canvas/i18n/components.ts
@@ -912,6 +912,10 @@ export const ComponentStrings = {
i18n.translate('xpack.canvas.textStylePicker.styleUnderlineOption', {
defaultMessage: 'Underline',
}),
+ getFontColorLabel: () =>
+ i18n.translate('xpack.canvas.textStylePicker.fontColorLabel', {
+ defaultMessage: 'Font Color',
+ }),
},
TimePicker: {
getApplyButtonLabel: () =>
@@ -1007,7 +1011,11 @@ export const ComponentStrings = {
getUSLetterButtonLabel: () =>
i18n.translate('xpack.canvas.workpadConfig.USLetterButtonLabel', {
defaultMessage: 'US Letter',
- description: 'This is referring to the dimentions of U.S. standard letter paper.',
+ description: 'This is referring to the dimensions of U.S. standard letter paper.',
+ }),
+ getBackgroundColorLabel: () =>
+ i18n.translate('xpack.canvas.workpadConfig.backgroundColorLabel', {
+ defaultMessage: 'Background color',
}),
},
WorkpadCreate: {
diff --git a/x-pack/legacy/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset.examples.storyshot b/x-pack/legacy/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset.examples.storyshot
index 454ef0a79d10af..35de0fb665be1a 100644
--- a/x-pack/legacy/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset.examples.storyshot
+++ b/x-pack/legacy/plugins/canvas/public/components/asset_manager/__examples__/__snapshots__/asset.examples.storyshot
@@ -25,11 +25,6 @@ exports[`Storyshots components/Assets/Asset airplane 1`] = `
alt="Asset thumbnail"
className="euiImage__img"
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1Ni4zMSA1Ni4zMSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOiNmZmY7c3Ryb2tlOiMwMDc4YTA7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlLXdpZHRoOjJweDt9PC9zdHlsZT48L2RlZnM+PHRpdGxlPlBsYW5lIEljb248L3RpdGxlPjxnIGlkPSJMYXllcl8yIiBkYXRhLW5hbWU9IkxheWVyIDIiPjxnIGlkPSJMYXllcl8xLTIiIGRhdGEtbmFtZT0iTGF5ZXIgMSI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNDkuNTEsNDguOTMsNDEuMjYsMjIuNTIsNTMuNzYsMTBhNS4yOSw1LjI5LDAsMCwwLTcuNDgtNy40N2wtMTIuNSwxMi41TDcuMzgsNi43OUEuNy43LDAsMCwwLDYuNjksN0wxLjIsMTIuNDVhLjcuNywwLDAsMCwwLDFMMTkuODUsMjlsLTcuMjQsNy4yNC03Ljc0LS42YS43MS43MSwwLDAsMC0uNTMuMkwxLjIxLDM5YS42Ny42NywwLDAsMCwuMDgsMUw5LjQ1LDQ2bC4wNywwYy4xMS4xMy4yMi4yNi4zNC4zOHMuMjUuMjMuMzguMzRhLjM2LjM2LDAsMCwwLDAsLjA3TDE2LjMzLDU1YS42OC42OCwwLDAsMCwxLC4wN0wyMC40OSw1MmEuNjcuNjcsMCwwLDAsLjE5LS41NGwtLjU5LTcuNzQsNy4yNC03LjI0TDQyLjg1LDU1LjA2YS42OC42OCwwLDAsMCwxLDBsNS41LTUuNUEuNjYuNjYsMCwwLDAsNDkuNTEsNDguOTNaIi8+PC9nPjwvZz48L3N2Zz4="
- style={
- Object {
- "backgroundImage": "url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1Ni4zMSA1Ni4zMSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOiNmZmY7c3Ryb2tlOiMwMDc4YTA7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlLXdpZHRoOjJweDt9PC9zdHlsZT48L2RlZnM+PHRpdGxlPlBsYW5lIEljb248L3RpdGxlPjxnIGlkPSJMYXllcl8yIiBkYXRhLW5hbWU9IkxheWVyIDIiPjxnIGlkPSJMYXllcl8xLTIiIGRhdGEtbmFtZT0iTGF5ZXIgMSI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNDkuNTEsNDguOTMsNDEuMjYsMjIuNTIsNTMuNzYsMTBhNS4yOSw1LjI5LDAsMCwwLTcuNDgtNy40N2wtMTIuNSwxMi41TDcuMzgsNi43OUEuNy43LDAsMCwwLDYuNjksN0wxLjIsMTIuNDVhLjcuNywwLDAsMCwwLDFMMTkuODUsMjlsLTcuMjQsNy4yNC03Ljc0LS42YS43MS43MSwwLDAsMC0uNTMuMkwxLjIxLDM5YS42Ny42NywwLDAsMCwuMDgsMUw5LjQ1LDQ2bC4wNywwYy4xMS4xMy4yMi4yNi4zNC4zOHMuMjUuMjMuMzguMzRhLjM2LjM2LDAsMCwwLDAsLjA3TDE2LjMzLDU1YS42OC42OCwwLDAsMCwxLC4wN0wyMC40OSw1MmEuNjcuNjcsMCwwLDAsLjE5LS41NGwtLjU5LTcuNzQsNy4yNC03LjI0TDQyLjg1LDU1LjA2YS42OC42OCwwLDAsMCwxLDBsNS41LTUuNUEuNjYuNjYsMCwwLDAsNDkuNTEsNDguOTNaIi8+PC9nPjwvZz48L3N2Zz4=)",
- }
- }
/>
@@ -224,11 +219,6 @@ exports[`Storyshots components/Assets/Asset marker 1`] = `
alt="Asset thumbnail"
className="euiImage__img"
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzOC4zOSA1Ny41NyI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOiNmZmY7c3Ryb2tlOiMwMTliOGY7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlLXdpZHRoOjJweDt9PC9zdHlsZT48L2RlZnM+PHRpdGxlPkxvY2F0aW9uIEljb248L3RpdGxlPjxnIGlkPSJMYXllcl8yIiBkYXRhLW5hbWU9IkxheWVyIDIiPjxnIGlkPSJMYXllcl8xLTIiIGRhdGEtbmFtZT0iTGF5ZXIgMSI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTkuMTksMUExOC4xOSwxOC4xOSwwLDAsMCwyLjk0LDI3LjM2aDBhMTkuNTEsMTkuNTEsMCwwLDAsMSwxLjc4TDE5LjE5LDU1LjU3LDM0LjM4LDI5LjIxQTE4LjE5LDE4LjE5LDAsMCwwLDE5LjE5LDFabTAsMjMuMjlhNS41Myw1LjUzLDAsMSwxLDUuNTMtNS41M0E1LjUzLDUuNTMsMCwwLDEsMTkuMTksMjQuMjlaIi8+PC9nPjwvZz48L3N2Zz4="
- style={
- Object {
- "backgroundImage": "url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzOC4zOSA1Ny41NyI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOiNmZmY7c3Ryb2tlOiMwMTliOGY7c3Ryb2tlLW1pdGVybGltaXQ6MTA7c3Ryb2tlLXdpZHRoOjJweDt9PC9zdHlsZT48L2RlZnM+PHRpdGxlPkxvY2F0aW9uIEljb248L3RpdGxlPjxnIGlkPSJMYXllcl8yIiBkYXRhLW5hbWU9IkxheWVyIDIiPjxnIGlkPSJMYXllcl8xLTIiIGRhdGEtbmFtZT0iTGF5ZXIgMSI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTkuMTksMUExOC4xOSwxOC4xOSwwLDAsMCwyLjk0LDI3LjM2aDBhMTkuNTEsMTkuNTEsMCwwLDAsMSwxLjc4TDE5LjE5LDU1LjU3LDM0LjM4LDI5LjIxQTE4LjE5LDE4LjE5LDAsMCwwLDE5LjE5LDFabTAsMjMuMjlhNS41Myw1LjUzLDAsMSwxLDUuNTMtNS41M0E1LjUzLDUuNTMsMCwwLDEsMTkuMTksMjQuMjlaIi8+PC9nPjwvZz48L3N2Zz4=)",
- }
- }
/>
diff --git a/x-pack/legacy/plugins/canvas/public/components/asset_manager/asset.tsx b/x-pack/legacy/plugins/canvas/public/components/asset_manager/asset.tsx
index 579470649582d3..c1a2b0f0bf3724 100644
--- a/x-pack/legacy/plugins/canvas/public/components/asset_manager/asset.tsx
+++ b/x-pack/legacy/plugins/canvas/public/components/asset_manager/asset.tsx
@@ -92,7 +92,6 @@ export const Asset: FunctionComponent = props => {
url={props.asset.value}
fullScreenIconColor="dark"
alt={strings.getThumbnailAltText()}
- style={{ backgroundImage: `url(${props.asset.value})` }}
/>
);
diff --git a/x-pack/legacy/plugins/canvas/public/components/asset_manager/asset_manager.scss b/x-pack/legacy/plugins/canvas/public/components/asset_manager/asset_manager.scss
index 5b281129f533ff..c8ab1323557bb7 100644
--- a/x-pack/legacy/plugins/canvas/public/components/asset_manager/asset_manager.scss
+++ b/x-pack/legacy/plugins/canvas/public/components/asset_manager/asset_manager.scss
@@ -46,18 +46,20 @@
margin: -$euiSizeS;
margin-bottom: 0;
font-size: 0; // eliminates any extra space around img
+ height: 164px;
}
.canvasAsset__img {
- background-repeat: no-repeat;
- background-position: center;
- background-size: contain;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ height: 100%;
img {
width: auto;
max-width: 100%;
- height: 164px; // nice default proportions for typical 4x3 images
- opacity: 0; // only show the background image (which will properly keep proportions)
+ max-height: 164px; // nice default proportions for typical 4x3 images
}
}
}
diff --git a/x-pack/legacy/plugins/canvas/public/components/color_palette/__examples__/__snapshots__/color_palette.examples.storyshot b/x-pack/legacy/plugins/canvas/public/components/color_palette/__examples__/__snapshots__/color_palette.examples.storyshot
index badbf96029f123..8610ed2f1b4a38 100644
--- a/x-pack/legacy/plugins/canvas/public/components/color_palette/__examples__/__snapshots__/color_palette.examples.storyshot
+++ b/x-pack/legacy/plugins/canvas/public/components/color_palette/__examples__/__snapshots__/color_palette.examples.storyshot
@@ -8,6 +8,7 @@ exports[`Storyshots components/Color/ColorPalette interactive 1`] = `
className="item-grid-row"
>
= ({
key={color}
onClick={() => !match && onChange(color)}
className="canvasColorPalette__dot"
+ aria-label={tinycolor(color).toName() || color}
>
{icon}
diff --git a/x-pack/legacy/plugins/canvas/public/components/color_picker/__examples__/__snapshots__/color_picker.examples.storyshot b/x-pack/legacy/plugins/canvas/public/components/color_picker/__examples__/__snapshots__/color_picker.examples.storyshot
index 6e25ce3d4b0d41..5fbb4ee7d584d3 100644
--- a/x-pack/legacy/plugins/canvas/public/components/color_picker/__examples__/__snapshots__/color_picker.examples.storyshot
+++ b/x-pack/legacy/plugins/canvas/public/components/color_picker/__examples__/__snapshots__/color_picker.examples.storyshot
@@ -10,6 +10,7 @@ exports[`Storyshots components/Color/ColorPicker interactive 1`] = `
className="item-grid-row"
>
@@ -72,6 +73,7 @@ storiesOf('components/Color/ColorPickerPopover', module)
anchorPosition="downCenter"
onChange={action('onChange')}
colors={THREE_COLORS}
+ ariaLabel="Color Picker"
/>
))
.add('six colors', () => (
@@ -80,6 +82,7 @@ storiesOf('components/Color/ColorPickerPopover', module)
anchorPosition="downCenter"
onChange={action('onChange')}
colors={SIX_COLORS}
+ ariaLabel="Color Picker"
/>
))
.add('six colors, value missing', () => (
@@ -88,6 +91,7 @@ storiesOf('components/Color/ColorPickerPopover', module)
anchorPosition="downCenter"
onChange={action('onChange')}
colors={SIX_COLORS}
+ ariaLabel="Color Picker"
/>
))
.add('interactive', () => , {
diff --git a/x-pack/legacy/plugins/canvas/public/components/color_picker_popover/color_picker_popover.tsx b/x-pack/legacy/plugins/canvas/public/components/color_picker_popover/color_picker_popover.tsx
index 9961eba74a19d7..95d6144f3e3c30 100644
--- a/x-pack/legacy/plugins/canvas/public/components/color_picker_popover/color_picker_popover.tsx
+++ b/x-pack/legacy/plugins/canvas/public/components/color_picker_popover/color_picker_popover.tsx
@@ -7,18 +7,24 @@
import { EuiLink, PopoverAnchorPosition } from '@elastic/eui';
import PropTypes from 'prop-types';
import React, { FunctionComponent, MouseEvent } from 'react';
+import tinycolor from 'tinycolor2';
import { ColorDot } from '../color_dot';
import { ColorPicker, Props as ColorPickerProps } from '../color_picker';
import { Popover } from '../popover';
export interface Props extends ColorPickerProps {
anchorPosition: PopoverAnchorPosition;
+ ariaLabel?: string;
}
export const ColorPickerPopover: FunctionComponent = (props: Props) => {
- const { value, anchorPosition, ...rest } = props;
+ const { value, anchorPosition, ariaLabel, ...rest } = props;
const button = (handleClick: (ev: MouseEvent) => void) => (
-
+
);
diff --git a/x-pack/legacy/plugins/canvas/public/components/custom_element_modal/__examples__/__snapshots__/custom_element_modal.examples.storyshot b/x-pack/legacy/plugins/canvas/public/components/custom_element_modal/__examples__/__snapshots__/custom_element_modal.examples.storyshot
index efaa34001971e0..a469f03a71e3e9 100644
--- a/x-pack/legacy/plugins/canvas/public/components/custom_element_modal/__examples__/__snapshots__/custom_element_modal.examples.storyshot
+++ b/x-pack/legacy/plugins/canvas/public/components/custom_element_modal/__examples__/__snapshots__/custom_element_modal.examples.storyshot
@@ -118,6 +118,7 @@ Array [
@@ -479,6 +482,7 @@ Array [
@@ -835,6 +841,7 @@ Array [
@@ -1195,6 +1204,7 @@ Array [
diff --git a/x-pack/legacy/plugins/canvas/public/components/custom_element_modal/custom_element_modal.tsx b/x-pack/legacy/plugins/canvas/public/components/custom_element_modal/custom_element_modal.tsx
index b5d08d98072a33..341ddf5e98ccc9 100644
--- a/x-pack/legacy/plugins/canvas/public/components/custom_element_modal/custom_element_modal.tsx
+++ b/x-pack/legacy/plugins/canvas/public/components/custom_element_modal/custom_element_modal.tsx
@@ -141,6 +141,7 @@ export class CustomElementModal extends PureComponent {
this._handleChange('name', e.target.value)
}
required
+ data-test-subj="canvasCustomElementForm-name"
/>
{
e.target.value.length <= MAX_DESCRIPTION_LENGTH &&
this._handleChange('description', e.target.value)
}
+ data-test-subj="canvasCustomElementForm-description"
/>
{
onClick={() => {
onSave(name, description, image);
}}
+ data-test-subj="canvasCustomElementForm-submit"
>
{strings.getSaveButtonLabel()}
diff --git a/x-pack/legacy/plugins/canvas/public/components/palette_picker/palette_picker.js b/x-pack/legacy/plugins/canvas/public/components/palette_picker/palette_picker.js
index 254d9647e26a72..e5808dd6235302 100644
--- a/x-pack/legacy/plugins/canvas/public/components/palette_picker/palette_picker.js
+++ b/x-pack/legacy/plugins/canvas/public/components/palette_picker/palette_picker.js
@@ -12,9 +12,9 @@ import { Popover } from '../popover';
import { PaletteSwatch } from '../palette_swatch';
import { palettes } from '../../../common/lib/palettes';
-export const PalettePicker = ({ onChange, value, anchorPosition }) => {
+export const PalettePicker = ({ onChange, value, anchorPosition, ariaLabel }) => {
const button = handleClick => (
-
+
);
diff --git a/x-pack/legacy/plugins/canvas/public/components/shape_picker_popover/shape_picker_popover.tsx b/x-pack/legacy/plugins/canvas/public/components/shape_picker_popover/shape_picker_popover.tsx
index 970f72da698ba0..717ec6d0faeccf 100644
--- a/x-pack/legacy/plugins/canvas/public/components/shape_picker_popover/shape_picker_popover.tsx
+++ b/x-pack/legacy/plugins/canvas/public/components/shape_picker_popover/shape_picker_popover.tsx
@@ -17,12 +17,13 @@ interface Props {
};
onChange?: (key: string) => void;
value?: string;
+ ariaLabel?: string;
}
-export const ShapePickerPopover = ({ shapes, onChange, value }: Props) => {
+export const ShapePickerPopover = ({ shapes, onChange, value, ariaLabel }: Props) => {
const button = (handleClick: (ev: MouseEvent) => void) => (
-
+
diff --git a/x-pack/legacy/plugins/canvas/public/components/text_style_picker/text_style_picker.js b/x-pack/legacy/plugins/canvas/public/components/text_style_picker/text_style_picker.js
index 1a441814750912..179455e15b36ee 100644
--- a/x-pack/legacy/plugins/canvas/public/components/text_style_picker/text_style_picker.js
+++ b/x-pack/legacy/plugins/canvas/public/components/text_style_picker/text_style_picker.js
@@ -127,6 +127,7 @@ export const TextStylePicker = ({
value={color}
onChange={value => doChange('color', value)}
colors={colors}
+ ariaLabel={strings.getFontColorLabel()}
/>
diff --git a/x-pack/legacy/plugins/canvas/public/components/workpad_color_picker/workpad_color_picker.tsx b/x-pack/legacy/plugins/canvas/public/components/workpad_color_picker/workpad_color_picker.tsx
index 69401c89c79a59..c81f3e78efddd2 100644
--- a/x-pack/legacy/plugins/canvas/public/components/workpad_color_picker/workpad_color_picker.tsx
+++ b/x-pack/legacy/plugins/canvas/public/components/workpad_color_picker/workpad_color_picker.tsx
@@ -6,9 +6,18 @@
import React from 'react';
import { ColorPickerPopover, Props } from '../color_picker_popover';
+import { ComponentStrings } from '../../../i18n';
+
+const { WorkpadConfig: strings } = ComponentStrings;
export const WorkpadColorPicker = (props: Props) => {
- return ;
+ return (
+
+ );
};
WorkpadColorPicker.propTypes = ColorPickerPopover.propTypes;
diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/color.js b/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/color.js
index 2a47150b4a1b94..8d756dd8111b14 100644
--- a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/color.js
+++ b/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/color.js
@@ -13,10 +13,15 @@ import { ArgTypesStrings } from '../../../i18n';
const { Color: strings } = ArgTypesStrings;
-const ColorArgInput = ({ onValueChange, argValue, workpad }) => (
+const ColorArgInput = ({ onValueChange, argValue, workpad, typeInstance }) => (
-
+
);
diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/__examples__/__snapshots__/extended_template.examples.storyshot b/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/__examples__/__snapshots__/extended_template.examples.storyshot
index 2915d3bfef57b8..649d11cb2dbaba 100644
--- a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/__examples__/__snapshots__/extended_template.examples.storyshot
+++ b/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/__examples__/__snapshots__/extended_template.examples.storyshot
@@ -467,6 +467,7 @@ exports[`Storyshots arguments/ContainerStyle extended 1`] = `
className="euiPopover__anchor"
>
= ({
onChange={borderColorChange}
colors={colors}
anchorPosition="upCenter"
+ ariaLabel={strings.getBorderTitle()}
/>
diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/simple_template.tsx b/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/simple_template.tsx
index 11e000e08481f7..cb7a5d606c7d92 100644
--- a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/simple_template.tsx
+++ b/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/container_style/simple_template.tsx
@@ -8,6 +8,9 @@ import React, { FunctionComponent } from 'react';
import PropTypes from 'prop-types';
import { ColorPickerPopover } from '../../../components/color_picker_popover';
import { CanvasWorkpad } from '../.../../../../../types';
+import { ArgTypesStrings } from '../../../../i18n';
+
+const { ContainerStyle: strings } = ArgTypesStrings;
export interface Arguments {
backgroundColor: string;
@@ -27,6 +30,7 @@ export const SimpleTemplate: FunctionComponent = ({ getArgValue, setArgVa
onChange={color => setArgValue('backgroundColor', color)}
colors={workpad.colors}
anchorPosition="leftCenter"
+ ariaLabel={strings.getDisplayName()}
/>
);
diff --git a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/series_style/simple_template.tsx b/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/series_style/simple_template.tsx
index e05c48b97f54a4..ba1f4305167a41 100644
--- a/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/series_style/simple_template.tsx
+++ b/x-pack/legacy/plugins/canvas/public/expression_types/arg_types/series_style/simple_template.tsx
@@ -76,6 +76,7 @@ export const SimpleTemplate: FunctionComponent = props => {
colors={workpad.colors}
onChange={val => handleChange('color', val)}
value={color}
+ ariaLabel={strings.getColorLabel()}
/>
diff --git a/x-pack/legacy/plugins/canvas/public/lib/element_handler_creators.ts b/x-pack/legacy/plugins/canvas/public/lib/element_handler_creators.ts
index 367bfef6cd3be5..bce6bc51b366c0 100644
--- a/x-pack/legacy/plugins/canvas/public/lib/element_handler_creators.ts
+++ b/x-pack/legacy/plugins/canvas/public/lib/element_handler_creators.ts
@@ -87,7 +87,10 @@ export const basicHandlerCreators = {
.create(customElement)
.then(() =>
notify.success(
- `Custom element '${customElement.displayName || customElement.id}' was saved`
+ `Custom element '${customElement.displayName || customElement.id}' was saved`,
+ {
+ 'data-test-subj': 'canvasCustomElementCreate-success',
+ }
)
)
.catch((result: Http2ServerResponse) =>
diff --git a/x-pack/legacy/plugins/console_extensions/spec/generated/data_frame_transform_deprecated.delete_transform.json b/x-pack/legacy/plugins/console_extensions/spec/generated/data_frame_transform_deprecated.delete_transform.json
deleted file mode 100644
index 4401c85da7215b..00000000000000
--- a/x-pack/legacy/plugins/console_extensions/spec/generated/data_frame_transform_deprecated.delete_transform.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "data_frame_transform_deprecated.delete_transform": {
- "url_params": {
- "force": "__flag__"
- },
- "methods": [
- "DELETE"
- ],
- "patterns": [
- "_data_frame/transforms/{transform_id}"
- ],
- "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/delete-transform.html"
- }
-}
diff --git a/x-pack/legacy/plugins/console_extensions/spec/generated/data_frame_transform_deprecated.get_transform.json b/x-pack/legacy/plugins/console_extensions/spec/generated/data_frame_transform_deprecated.get_transform.json
deleted file mode 100644
index d1060d562c626c..00000000000000
--- a/x-pack/legacy/plugins/console_extensions/spec/generated/data_frame_transform_deprecated.get_transform.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "data_frame_transform_deprecated.get_transform": {
- "url_params": {
- "from": 0,
- "size": 0,
- "allow_no_match": "__flag__"
- },
- "methods": [
- "GET"
- ],
- "patterns": [
- "_data_frame/transforms/{transform_id}",
- "_data_frame/transforms"
- ],
- "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/get-transform.html"
- }
-}
diff --git a/x-pack/legacy/plugins/console_extensions/spec/generated/data_frame_transform_deprecated.get_transform_stats.json b/x-pack/legacy/plugins/console_extensions/spec/generated/data_frame_transform_deprecated.get_transform_stats.json
deleted file mode 100644
index aa3c1a21f36ce9..00000000000000
--- a/x-pack/legacy/plugins/console_extensions/spec/generated/data_frame_transform_deprecated.get_transform_stats.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "data_frame_transform_deprecated.get_transform_stats": {
- "url_params": {
- "from": "",
- "size": "",
- "allow_no_match": "__flag__"
- },
- "methods": [
- "GET"
- ],
- "patterns": [
- "_data_frame/transforms/{transform_id}/_stats"
- ],
- "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/get-transform-stats.html"
- }
-}
diff --git a/x-pack/legacy/plugins/console_extensions/spec/generated/data_frame_transform_deprecated.preview_transform.json b/x-pack/legacy/plugins/console_extensions/spec/generated/data_frame_transform_deprecated.preview_transform.json
deleted file mode 100644
index 1c878641d02b5a..00000000000000
--- a/x-pack/legacy/plugins/console_extensions/spec/generated/data_frame_transform_deprecated.preview_transform.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "data_frame_transform_deprecated.preview_transform": {
- "methods": [
- "POST"
- ],
- "patterns": [
- "_data_frame/transforms/_preview"
- ],
- "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/preview-transform.html"
- }
-}
diff --git a/x-pack/legacy/plugins/console_extensions/spec/generated/data_frame_transform_deprecated.put_transform.json b/x-pack/legacy/plugins/console_extensions/spec/generated/data_frame_transform_deprecated.put_transform.json
deleted file mode 100644
index 89c124280a4a16..00000000000000
--- a/x-pack/legacy/plugins/console_extensions/spec/generated/data_frame_transform_deprecated.put_transform.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "data_frame_transform_deprecated.put_transform": {
- "url_params": {
- "defer_validation": "__flag__"
- },
- "methods": [
- "PUT"
- ],
- "patterns": [
- "_data_frame/transforms/{transform_id}"
- ],
- "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/put-transform.html"
- }
-}
diff --git a/x-pack/legacy/plugins/console_extensions/spec/generated/data_frame_transform_deprecated.start_transform.json b/x-pack/legacy/plugins/console_extensions/spec/generated/data_frame_transform_deprecated.start_transform.json
deleted file mode 100644
index 49e09b7922b687..00000000000000
--- a/x-pack/legacy/plugins/console_extensions/spec/generated/data_frame_transform_deprecated.start_transform.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "data_frame_transform_deprecated.start_transform": {
- "url_params": {
- "timeout": ""
- },
- "methods": [
- "POST"
- ],
- "patterns": [
- "_data_frame/transforms/{transform_id}/_start"
- ],
- "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/start-transform.html"
- }
-}
diff --git a/x-pack/legacy/plugins/console_extensions/spec/generated/data_frame_transform_deprecated.stop_transform.json b/x-pack/legacy/plugins/console_extensions/spec/generated/data_frame_transform_deprecated.stop_transform.json
deleted file mode 100644
index 90e89269aec00a..00000000000000
--- a/x-pack/legacy/plugins/console_extensions/spec/generated/data_frame_transform_deprecated.stop_transform.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "data_frame_transform_deprecated.stop_transform": {
- "url_params": {
- "wait_for_completion": "__flag__",
- "timeout": "",
- "allow_no_match": "__flag__"
- },
- "methods": [
- "POST"
- ],
- "patterns": [
- "_data_frame/transforms/{transform_id}/_stop"
- ],
- "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/stop-transform.html"
- }
-}
diff --git a/x-pack/legacy/plugins/console_extensions/spec/generated/data_frame_transform_deprecated.update_transform.json b/x-pack/legacy/plugins/console_extensions/spec/generated/data_frame_transform_deprecated.update_transform.json
deleted file mode 100644
index ac8c854ab6bfcd..00000000000000
--- a/x-pack/legacy/plugins/console_extensions/spec/generated/data_frame_transform_deprecated.update_transform.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "data_frame_transform_deprecated.update_transform": {
- "url_params": {
- "defer_validation": "__flag__"
- },
- "methods": [
- "POST"
- ],
- "patterns": [
- "_data_frame/transforms/{transform_id}/_update"
- ],
- "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/update-transform.html"
- }
-}
diff --git a/x-pack/legacy/plugins/console_extensions/spec/generated/license.get.json b/x-pack/legacy/plugins/console_extensions/spec/generated/license.get.json
index f37602296f5a99..2404d65ce1e01a 100644
--- a/x-pack/legacy/plugins/console_extensions/spec/generated/license.get.json
+++ b/x-pack/legacy/plugins/console_extensions/spec/generated/license.get.json
@@ -1,7 +1,8 @@
{
"license.get": {
"url_params": {
- "local": "__flag__"
+ "local": "__flag__",
+ "accept_enterprise": "__flag__"
},
"methods": [
"GET"
diff --git a/x-pack/legacy/plugins/console_extensions/spec/generated/ml.delete_data_frame_analytics.json b/x-pack/legacy/plugins/console_extensions/spec/generated/ml.delete_data_frame_analytics.json
index c2c6baf906db6d..c3d7048406ef63 100644
--- a/x-pack/legacy/plugins/console_extensions/spec/generated/ml.delete_data_frame_analytics.json
+++ b/x-pack/legacy/plugins/console_extensions/spec/generated/ml.delete_data_frame_analytics.json
@@ -1,5 +1,8 @@
{
"ml.delete_data_frame_analytics": {
+ "url_params": {
+ "force": "__flag__"
+ },
"methods": [
"DELETE"
],
diff --git a/x-pack/legacy/plugins/console_extensions/spec/generated/ml.explain_data_frame_analytics.json b/x-pack/legacy/plugins/console_extensions/spec/generated/ml.explain_data_frame_analytics.json
new file mode 100644
index 00000000000000..212098cc3a2027
--- /dev/null
+++ b/x-pack/legacy/plugins/console_extensions/spec/generated/ml.explain_data_frame_analytics.json
@@ -0,0 +1,13 @@
+{
+ "ml.explain_data_frame_analytics": {
+ "methods": [
+ "GET",
+ "POST"
+ ],
+ "patterns": [
+ "_ml/data_frame/analytics/_explain",
+ "_ml/data_frame/analytics/{id}/_explain"
+ ],
+ "documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current/explain-dfanalytics.html"
+ }
+}
diff --git a/x-pack/legacy/plugins/console_extensions/spec/generated/ml.put_trained_model.json b/x-pack/legacy/plugins/console_extensions/spec/generated/ml.put_trained_model.json
new file mode 100644
index 00000000000000..27d0393be6086f
--- /dev/null
+++ b/x-pack/legacy/plugins/console_extensions/spec/generated/ml.put_trained_model.json
@@ -0,0 +1,11 @@
+{
+ "ml.put_trained_model": {
+ "methods": [
+ "PUT"
+ ],
+ "patterns": [
+ "_ml/inference/{model_id}"
+ ],
+ "documentation": "TODO"
+ }
+}
diff --git a/x-pack/legacy/plugins/console_extensions/spec/generated/monitoring.bulk.json b/x-pack/legacy/plugins/console_extensions/spec/generated/monitoring.bulk.json
index 9f718501e25b58..2b27950e7b0974 100644
--- a/x-pack/legacy/plugins/console_extensions/spec/generated/monitoring.bulk.json
+++ b/x-pack/legacy/plugins/console_extensions/spec/generated/monitoring.bulk.json
@@ -10,8 +10,7 @@
"PUT"
],
"patterns": [
- "_monitoring/bulk",
- "_monitoring/{type}/bulk"
+ "_monitoring/bulk"
],
"documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/master/es-monitoring.html"
}
diff --git a/x-pack/legacy/plugins/console_extensions/spec/generated/rollup.rollup_search.json b/x-pack/legacy/plugins/console_extensions/spec/generated/rollup.rollup_search.json
index a5763646990a59..a1771126a71b4f 100644
--- a/x-pack/legacy/plugins/console_extensions/spec/generated/rollup.rollup_search.json
+++ b/x-pack/legacy/plugins/console_extensions/spec/generated/rollup.rollup_search.json
@@ -9,8 +9,7 @@
"POST"
],
"patterns": [
- "{indices}/_rollup_search",
- "{indices}/{type}/_rollup_search"
+ "{indices}/_rollup_search"
]
}
}
diff --git a/x-pack/legacy/plugins/console_extensions/spec/generated/security.get_api_key.json b/x-pack/legacy/plugins/console_extensions/spec/generated/security.get_api_key.json
index 431b345a1bcc20..a8cd5de2656b9d 100644
--- a/x-pack/legacy/plugins/console_extensions/spec/generated/security.get_api_key.json
+++ b/x-pack/legacy/plugins/console_extensions/spec/generated/security.get_api_key.json
@@ -4,7 +4,8 @@
"id": "",
"name": "",
"username": "",
- "realm_name": ""
+ "realm_name": "",
+ "owner": "__flag__"
},
"methods": [
"GET"
diff --git a/x-pack/legacy/plugins/console_extensions/spec/generated/slm.get_status.json b/x-pack/legacy/plugins/console_extensions/spec/generated/slm.get_status.json
new file mode 100644
index 00000000000000..a7ffde10b316d0
--- /dev/null
+++ b/x-pack/legacy/plugins/console_extensions/spec/generated/slm.get_status.json
@@ -0,0 +1,11 @@
+{
+ "slm.get_status": {
+ "methods": [
+ "GET"
+ ],
+ "patterns": [
+ "_slm/status"
+ ],
+ "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-get-status.html"
+ }
+}
diff --git a/x-pack/legacy/plugins/console_extensions/spec/generated/slm.start.json b/x-pack/legacy/plugins/console_extensions/spec/generated/slm.start.json
new file mode 100644
index 00000000000000..a5b94d98f08fbe
--- /dev/null
+++ b/x-pack/legacy/plugins/console_extensions/spec/generated/slm.start.json
@@ -0,0 +1,11 @@
+{
+ "slm.start": {
+ "methods": [
+ "POST"
+ ],
+ "patterns": [
+ "_slm/start"
+ ],
+ "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-start.html"
+ }
+}
diff --git a/x-pack/legacy/plugins/console_extensions/spec/generated/slm.stop.json b/x-pack/legacy/plugins/console_extensions/spec/generated/slm.stop.json
new file mode 100644
index 00000000000000..0b76fe68d2b5ef
--- /dev/null
+++ b/x-pack/legacy/plugins/console_extensions/spec/generated/slm.stop.json
@@ -0,0 +1,11 @@
+{
+ "slm.stop": {
+ "methods": [
+ "POST"
+ ],
+ "patterns": [
+ "_slm/stop"
+ ],
+ "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/slm-stop.html"
+ }
+}
diff --git a/x-pack/legacy/plugins/console_extensions/spec/generated/transform.stop_transform.json b/x-pack/legacy/plugins/console_extensions/spec/generated/transform.stop_transform.json
index 5ce118b8f7925f..27fedcd994ccf9 100644
--- a/x-pack/legacy/plugins/console_extensions/spec/generated/transform.stop_transform.json
+++ b/x-pack/legacy/plugins/console_extensions/spec/generated/transform.stop_transform.json
@@ -1,9 +1,11 @@
{
"transform.stop_transform": {
"url_params": {
+ "force": "__flag__",
"wait_for_completion": "__flag__",
"timeout": "",
- "allow_no_match": "__flag__"
+ "allow_no_match": "__flag__",
+ "wait_for_checkpoint": "__flag__"
},
"methods": [
"POST"
diff --git a/x-pack/legacy/plugins/console_extensions/spec/overrides/data_frame_transform_deprecated.preview_transform.json b/x-pack/legacy/plugins/console_extensions/spec/overrides/data_frame_transform_deprecated.preview_transform.json
deleted file mode 100644
index fe7148e7fb890c..00000000000000
--- a/x-pack/legacy/plugins/console_extensions/spec/overrides/data_frame_transform_deprecated.preview_transform.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "data_frame_transform_deprecated.preview_transform": {
- "data_autocomplete_rules": {
- "source": {
- "index": "SOURCE_INDEX_NAME",
- "query": {
- "__scope_link": "GLOBAL.query"
- }
- },
- "pivot": {
- "group_by": {
- "__template": {
- "NAME": {}
- },
- "__scope_link": "GLOBAL.groupByAggs"
- },
- "aggregations": {
- "__template": {
- "NAME": {}
- },
- "__scope_link": "GLOBAL.aggregations"
- }
- }
- }
- }
-}
diff --git a/x-pack/legacy/plugins/console_extensions/spec/overrides/data_frame_transform_deprecated.put_transform.json b/x-pack/legacy/plugins/console_extensions/spec/overrides/data_frame_transform_deprecated.put_transform.json
deleted file mode 100644
index 1a940888fd770f..00000000000000
--- a/x-pack/legacy/plugins/console_extensions/spec/overrides/data_frame_transform_deprecated.put_transform.json
+++ /dev/null
@@ -1,29 +0,0 @@
-{
- "data_frame_transform_deprecated.put_transform": {
- "data_autocomplete_rules": {
- "source": {
- "index": "SOURCE_INDEX_NAME",
- "query": {
- "__scope_link": "GLOBAL.query"
- }
- },
- "dest": {
- "index": "DEST_INDEX_NAME"
- },
- "pivot": {
- "group_by": {
- "__template": {
- "NAME": {}
- },
- "__scope_link": "GLOBAL.groupByAggs"
- },
- "aggregations": {
- "__template": {
- "NAME": {}
- },
- "__scope_link": "GLOBAL.aggregations"
- }
- }
- }
- }
-}
diff --git a/x-pack/legacy/plugins/console_extensions/spec/overrides/data_frame_transform_deprecated.update_transform.json b/x-pack/legacy/plugins/console_extensions/spec/overrides/data_frame_transform_deprecated.update_transform.json
deleted file mode 100644
index 3c03dc5fa5c508..00000000000000
--- a/x-pack/legacy/plugins/console_extensions/spec/overrides/data_frame_transform_deprecated.update_transform.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "data_frame_transform_deprecated.update_transform": {
- "data_autocomplete_rules": {
- "description": "",
- "dest": {
- "index": "SOURCE_INDEX_NAME",
- "pipeline": ""
- },
- "frequency": "",
- "source": {
- "index": "SOURCE_INDEX_NAME",
- "query": {
- "__scope_link": "GLOBAL.query"
- }
- },
- "sync": {
- "time": {
- "field": "FIELD_NAME",
- "delay": ""
- }
- }
- }
- }
-}
diff --git a/x-pack/legacy/plugins/console_extensions/spec/overrides/ml.explain_data_frame_analytics.json b/x-pack/legacy/plugins/console_extensions/spec/overrides/ml.explain_data_frame_analytics.json
new file mode 100644
index 00000000000000..859ba52d374911
--- /dev/null
+++ b/x-pack/legacy/plugins/console_extensions/spec/overrides/ml.explain_data_frame_analytics.json
@@ -0,0 +1,38 @@
+{
+ "ml.explain_data_frame_analytics": {
+ "data_autocomplete_rules": {
+ "data_frame_analytics_config": {
+ "source": {
+ "index": { "__one_of": ["SOURCE_INDEX_NAME", []] },
+ "query": {}
+ },
+ "dest": {
+ "index": "",
+ "results_field": ""
+ },
+ "analysis": {
+ "outlier_detection": {
+ "n_neighbors": 1,
+ "method": {"__one_of": ["lof", "ldof", "distance_knn_nn", "distance_knn"]},
+ "feature_influence_threshold": 1.0
+ }
+ },
+ "analyzed_fields": {
+ "__one_of": [
+ "FIELD_NAME",
+ [],
+ {
+ "includes": {
+ "__one_of": ["FIELD_NAME", []]
+ },
+ "excludes": {
+ "__one_of": ["FIELD_NAME", []]
+ }
+ }
+ ]
+ },
+ "model_memory_limit": ""
+ }
+ }
+ }
+}
diff --git a/x-pack/legacy/plugins/console_extensions/spec/overrides/ml.put_trained_model.json b/x-pack/legacy/plugins/console_extensions/spec/overrides/ml.put_trained_model.json
new file mode 100644
index 00000000000000..9eabbaac9085b2
--- /dev/null
+++ b/x-pack/legacy/plugins/console_extensions/spec/overrides/ml.put_trained_model.json
@@ -0,0 +1,5 @@
+{
+ "ml.put_trained_model": {
+ "documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-df-analytics-apis.html"
+ }
+}
diff --git a/x-pack/legacy/plugins/console_extensions/spec/overrides/slm.start.json b/x-pack/legacy/plugins/console_extensions/spec/overrides/slm.start.json
new file mode 100644
index 00000000000000..2949920313df71
--- /dev/null
+++ b/x-pack/legacy/plugins/console_extensions/spec/overrides/slm.start.json
@@ -0,0 +1,8 @@
+{
+ "slm.start": {
+ "url_params": {
+ "timeout": "",
+ "master_timeout": ""
+ }
+ }
+}
diff --git a/x-pack/legacy/plugins/console_extensions/spec/overrides/slm.stop.json b/x-pack/legacy/plugins/console_extensions/spec/overrides/slm.stop.json
new file mode 100644
index 00000000000000..c401aa65b9c6bc
--- /dev/null
+++ b/x-pack/legacy/plugins/console_extensions/spec/overrides/slm.stop.json
@@ -0,0 +1,8 @@
+{
+ "slm.stop": {
+ "url_params": {
+ "timeout": "",
+ "master_timeout": ""
+ }
+ }
+}
diff --git a/x-pack/legacy/plugins/graph/public/application.ts b/x-pack/legacy/plugins/graph/public/application.ts
index 69bc7899746325..8f486ab6ad51a2 100644
--- a/x-pack/legacy/plugins/graph/public/application.ts
+++ b/x-pack/legacy/plugins/graph/public/application.ts
@@ -96,9 +96,8 @@ export const renderApp = ({ appBasePath, element, ...deps }: GraphDependencies)
};
};
-const mainTemplate = (basePath: string) => `
+const mainTemplate = (basePath: string) => `
`;
@@ -108,7 +107,7 @@ const thirdPartyAngularDependencies = ['ngSanitize', 'ngRoute', 'react', 'ui.boo
function mountGraphApp(appBasePath: string, element: HTMLElement) {
const mountpoint = document.createElement('div');
- mountpoint.setAttribute('style', 'height: 100%');
+ mountpoint.setAttribute('class', 'kbnLocalApplicationWrapper');
// eslint-disable-next-line
mountpoint.innerHTML = mainTemplate(appBasePath);
// bootstrap angular into detached element and attach it later to
diff --git a/x-pack/legacy/plugins/graph/public/components/field_manager/field_icon.tsx b/x-pack/legacy/plugins/graph/public/components/field_manager/field_icon.tsx
index 429eec19a47fa7..0c099135f631d4 100644
--- a/x-pack/legacy/plugins/graph/public/components/field_manager/field_icon.tsx
+++ b/x-pack/legacy/plugins/graph/public/components/field_manager/field_icon.tsx
@@ -5,7 +5,7 @@
*/
import React from 'react';
-import { ICON_TYPES, palettes, EuiIcon } from '@elastic/eui';
+import { ICON_TYPES, euiPaletteColorBlind, EuiIcon } from '@elastic/eui';
function stringToNum(s: string) {
return Array.from(s).reduce((acc, ch) => acc + ch.charCodeAt(0), 1);
@@ -23,7 +23,7 @@ function getIconForDataType(dataType: string) {
export function getColorForDataType(type: string) {
const iconType = getIconForDataType(type);
- const { colors } = palettes.euiPaletteColorBlind;
+ const colors = euiPaletteColorBlind();
const colorIndex = stringToNum(iconType) % colors.length;
return colors[colorIndex];
}
diff --git a/x-pack/legacy/plugins/graph/public/helpers/style_choices.ts b/x-pack/legacy/plugins/graph/public/helpers/style_choices.ts
index 855818886ab6fa..46fec39bfce06c 100644
--- a/x-pack/legacy/plugins/graph/public/helpers/style_choices.ts
+++ b/x-pack/legacy/plugins/graph/public/helpers/style_choices.ts
@@ -6,7 +6,7 @@
import { i18n } from '@kbn/i18n';
// @ts-ignore
-import { palettes } from '@elastic/eui/lib/services';
+import { euiPaletteColorBlind } from '@elastic/eui/lib/services';
export interface FontawesomeIcon {
class: string;
@@ -255,4 +255,4 @@ urlTemplateIconChoices.forEach(icon => {
urlTemplateIconChoicesByClass[icon.class] = icon;
});
-export const colorChoices = palettes.euiPaletteColorBlind.colors;
+export const colorChoices = euiPaletteColorBlind();
diff --git a/x-pack/legacy/plugins/graph/public/services/persistence/deserialize.test.ts b/x-pack/legacy/plugins/graph/public/services/persistence/deserialize.test.ts
index 1861479f85f189..efef3d246ac98d 100644
--- a/x-pack/legacy/plugins/graph/public/services/persistence/deserialize.test.ts
+++ b/x-pack/legacy/plugins/graph/public/services/persistence/deserialize.test.ts
@@ -161,7 +161,7 @@ describe('deserialize', () => {
},
Object {
"aggregatable": true,
- "color": "#CE0060",
+ "color": "#D36086",
"hopSize": 5,
"icon": Object {
"class": "fa-folder-open-o",
diff --git a/x-pack/legacy/plugins/infra/public/components/beta_badge.tsx b/x-pack/legacy/plugins/infra/public/components/beta_badge.tsx
new file mode 100644
index 00000000000000..5d5770af1a41e8
--- /dev/null
+++ b/x-pack/legacy/plugins/infra/public/components/beta_badge.tsx
@@ -0,0 +1,26 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { EuiBetaBadge } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import React from 'react';
+
+export const BetaBadge: React.FunctionComponent = () => (
+
+);
+const betaBadgeLabel = i18n.translate('xpack.infra.common.tabBetaBadgeLabel', {
+ defaultMessage: 'Beta',
+});
+
+const betaBadgeTooltipContent = i18n.translate('xpack.infra.common.tabBetaBadgeTooltipContent', {
+ defaultMessage:
+ 'This feature is under active development. Extra functionality is coming, and some functionality may change.',
+});
diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/analysis_setup_indices_form.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/analysis_setup_indices_form.tsx
index 3334e565f70f76..89f8d77bd5f637 100644
--- a/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/analysis_setup_indices_form.tsx
+++ b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/analysis_setup_indices_form.tsx
@@ -13,11 +13,12 @@ import { LoadingOverlayWrapper } from '../../../loading_overlay_wrapper';
import { ValidatedIndex, ValidationIndicesUIError } from './validation';
export const AnalysisSetupIndicesForm: React.FunctionComponent<{
+ disabled?: boolean;
indices: ValidatedIndex[];
isValidating: boolean;
onChangeSelectedIndices: (selectedIndices: ValidatedIndex[]) => void;
valid: boolean;
-}> = ({ indices, isValidating, onChangeSelectedIndices, valid }) => {
+}> = ({ disabled = false, indices, isValidating, onChangeSelectedIndices, valid }) => {
const handleCheckboxChange = useCallback(
(event: React.ChangeEvent
) => {
onChangeSelectedIndices(
@@ -40,7 +41,7 @@ export const AnalysisSetupIndicesForm: React.FunctionComponent<{
label={{index.name} }
onChange={handleCheckboxChange}
checked={index.validity === 'valid' && index.isSelected}
- disabled={index.validity === 'invalid'}
+ disabled={disabled || index.validity === 'invalid'}
/>
);
@@ -52,7 +53,7 @@ export const AnalysisSetupIndicesForm: React.FunctionComponent<{
);
}),
- [handleCheckboxChange, indices]
+ [disabled, handleCheckboxChange, indices]
);
return (
diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/analysis_setup_timerange_form.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/analysis_setup_timerange_form.tsx
index f45d2741694976..4319f844b1dcc8 100644
--- a/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/analysis_setup_timerange_form.tsx
+++ b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/analysis_setup_timerange_form.tsx
@@ -46,11 +46,12 @@ function selectedDateToParam(selectedDate: Moment | null) {
}
export const AnalysisSetupTimerangeForm: React.FunctionComponent<{
+ disabled?: boolean;
setStartTime: (startTime: number | undefined) => void;
setEndTime: (endTime: number | undefined) => void;
startTime: number | undefined;
endTime: number | undefined;
-}> = ({ setStartTime, setEndTime, startTime, endTime }) => {
+}> = ({ disabled = false, setStartTime, setEndTime, startTime, endTime }) => {
const now = useMemo(() => moment(), []);
const selectedEndTimeIsToday = !endTime || moment(endTime).isSame(now, 'day');
const startTimeValue = useMemo(() => {
@@ -86,9 +87,11 @@ export const AnalysisSetupTimerangeForm: React.FunctionComponent<{
>
setStartTime(undefined) } : undefined}
+ clear={startTime && !disabled ? { onClick: () => setStartTime(undefined) } : undefined}
+ isDisabled={disabled}
>
setStartTime(selectedDateToParam(date))}
@@ -107,9 +110,11 @@ export const AnalysisSetupTimerangeForm: React.FunctionComponent<{
>
setEndTime(undefined) } : undefined}
+ clear={endTime && !disabled ? { onClick: () => setEndTime(undefined) } : undefined}
+ isDisabled={disabled}
>
setEndTime(selectedDateToParam(date))}
diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/initial_configuration_step.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/initial_configuration_step.tsx
index 2494b802cdb5bc..de20dd12c17bdf 100644
--- a/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/initial_configuration_step.tsx
+++ b/x-pack/legacy/plugins/infra/public/components/logging/log_analysis_setup/initial_configuration_step/initial_configuration_step.tsx
@@ -8,8 +8,9 @@ import { EuiSpacer, EuiForm, EuiCallOut } from '@elastic/eui';
import { EuiContainedStepProps } from '@elastic/eui/src/components/steps/steps';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
-import React from 'react';
+import React, { useMemo } from 'react';
+import { SetupStatus } from '../../../../../common/log_analysis';
import { AnalysisSetupIndicesForm } from './analysis_setup_indices_form';
import { AnalysisSetupTimerangeForm } from './analysis_setup_timerange_form';
import { ValidatedIndex, ValidationIndicesUIError } from './validation';
@@ -21,6 +22,7 @@ interface InitialConfigurationStepProps {
endTime: number | undefined;
isValidating: boolean;
validatedIndices: ValidatedIndex[];
+ setupStatus: SetupStatus;
setValidatedIndices: (selectedIndices: ValidatedIndex[]) => void;
validationErrors?: ValidationIndicesUIError[];
}
@@ -39,20 +41,25 @@ export const InitialConfigurationStep: React.FunctionComponent {
+ const disabled = useMemo(() => !editableFormStatus.includes(setupStatus), [setupStatus]);
+
return (
<>
({
diff --git a/x-pack/legacy/plugins/infra/public/components/metrics_explorer/group_by.tsx b/x-pack/legacy/plugins/infra/public/components/metrics_explorer/group_by.tsx
index 505966e62e45f8..750894fd0188bc 100644
--- a/x-pack/legacy/plugins/infra/public/components/metrics_explorer/group_by.tsx
+++ b/x-pack/legacy/plugins/infra/public/components/metrics_explorer/group_by.tsx
@@ -44,6 +44,9 @@ export const MetricsExplorerGroupBy = ({ options, onChange, fields }: Props) =>
placeholder={i18n.translate('xpack.infra.metricsExplorer.groupByLabel', {
defaultMessage: 'Everything',
})}
+ aria-label={i18n.translate('xpack.infra.metricsExplorer.groupByAriaLabel', {
+ defaultMessage: 'Graph per',
+ })}
fullWidth
singleSelection={true}
selectedOptions={(options.groupBy && [{ label: options.groupBy }]) || []}
diff --git a/x-pack/legacy/plugins/infra/public/components/metrics_explorer/kuery_bar.tsx b/x-pack/legacy/plugins/infra/public/components/metrics_explorer/kuery_bar.tsx
index f1957c1fa91a77..7114217920998e 100644
--- a/x-pack/legacy/plugins/infra/public/components/metrics_explorer/kuery_bar.tsx
+++ b/x-pack/legacy/plugins/infra/public/components/metrics_explorer/kuery_bar.tsx
@@ -48,18 +48,21 @@ export const MetricsExplorerKueryBar = ({ derivedIndexPattern, onSubmit, value }
fields: derivedIndexPattern.fields.filter(field => isDisplayable(field)),
};
+ const placeholder = i18n.translate('xpack.infra.homePage.toolbar.kqlSearchFieldPlaceholder', {
+ defaultMessage: 'Search for infrastructure data… (e.g. host.name:host-1)',
+ });
+
return (
{({ isLoadingSuggestions, loadSuggestions, suggestions }) => (
diff --git a/x-pack/legacy/plugins/infra/public/components/metrics_explorer/metrics.tsx b/x-pack/legacy/plugins/infra/public/components/metrics_explorer/metrics.tsx
index 7a8b22467ccd80..0010fce7efa498 100644
--- a/x-pack/legacy/plugins/infra/public/components/metrics_explorer/metrics.tsx
+++ b/x-pack/legacy/plugins/infra/public/components/metrics_explorer/metrics.tsx
@@ -71,6 +71,7 @@ export const MetricsExplorerMetrics = ({ options, onChange, fields, autoFocus =
return (
{
}
}
-const tabBetaBadgeLabel = i18n.translate('xpack.infra.common.tabBetaBadgeLabel', {
- defaultMessage: 'Beta',
-});
-
-const tabBetaBadgeTooltipContent = i18n.translate('xpack.infra.common.tabBetaBadgeTooltipContent', {
- defaultMessage:
- 'This feature is under active development. Extra functionality is coming, and some functionality may change.',
-});
-
-export const TabBetaBadge = euiStyled(EuiBetaBadge).attrs({
- 'aria-label': tabBetaBadgeLabel,
- label: tabBetaBadgeLabel,
- tooltipContent: tabBetaBadgeTooltipContent,
-})`
- margin-left: 4px;
- vertical-align: baseline;
-`;
-
const TabContainer = euiStyled.div`
.euiLink {
color: inherit !important;
diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/index.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/index.tsx
index f38f066b5323fd..505878f0239dcf 100644
--- a/x-pack/legacy/plugins/infra/public/pages/logs/index.tsx
+++ b/x-pack/legacy/plugins/infra/public/pages/logs/index.tsx
@@ -11,7 +11,7 @@ import { Route, RouteComponentProps, Switch } from 'react-router-dom';
import { DocumentTitle } from '../../components/document_title';
import { HelpCenterContent } from '../../components/help_center_content';
import { Header } from '../../components/header';
-import { RoutedTabs, TabBetaBadge } from '../../components/navigation/routed_tabs';
+import { RoutedTabs } from '../../components/navigation/routed_tabs';
import { ColumnarPage } from '../../components/page';
import { SourceLoadingPage } from '../../components/source_loading_page';
import { SourceErrorPage } from '../../components/source_error_page';
@@ -41,22 +41,12 @@ export const LogsPage = ({ match }: RouteComponentProps) => {
};
const logRateTab = {
- title: (
- <>
- {logRateTabTitle}
-
- >
- ),
+ title: logRateTabTitle,
path: `${match.path}/log-rate`,
};
const logCategoriesTab = {
- title: (
- <>
- {logCategoriesTabTitle}
-
- >
- ),
+ title: logCategoriesTabTitle,
path: `${match.path}/log-categories`,
};
diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/page_results_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/page_results_content.tsx
index ffffba0691749d..a810ce447d3696 100644
--- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/page_results_content.tsx
+++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/page_results_content.tsx
@@ -156,7 +156,7 @@ export const LogEntryCategoriesResultsContent: React.FunctionComponent = () => {
-
+
@@ -188,7 +188,7 @@ export const LogEntryCategoriesResultsContent: React.FunctionComponent = () => {
) : null}
-
+
{
endTime,
isValidating,
validatedIndices,
+ setupStatus,
setValidatedIndices,
validationErrors,
}),
@@ -82,7 +84,8 @@ export const LogEntryCategoriesSetupContent: React.FunctionComponent = () => {
+ />{' '}
+
diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/top_categories_section.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/top_categories_section.tsx
index 0281615a59c785..962b5065362533 100644
--- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/top_categories_section.tsx
+++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/top_categories_section.tsx
@@ -10,6 +10,7 @@ import React from 'react';
import { LogEntryCategory } from '../../../../../../common/http_api/log_analysis';
import { TimeRange } from '../../../../../../common/http_api/shared';
+import { BetaBadge } from '../../../../../components/beta_badge';
import { LoadingOverlayWrapper } from '../../../../../components/loading_overlay_wrapper';
import { RecreateJobButton } from '../../../../../components/logging/log_analysis_job_status';
import { AnalyzeInMlButton } from '../../../../../components/logging/log_analysis_results';
@@ -42,7 +43,9 @@ export const TopCategoriesSection: React.FunctionComponent<{
- {title}
+
+ {title}
+
diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx
index 693444c02ce5f3..fd77cc8dd71735 100644
--- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx
+++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/page_results_content.tsx
@@ -155,7 +155,7 @@ export const LogEntryRateResultsContent: React.FunctionComponent = () => {
-
+
{logEntryRate ? (
@@ -196,7 +196,7 @@ export const LogEntryRateResultsContent: React.FunctionComponent = () => {
-
+
{isFirstUse && !hasResults ? (
<>
@@ -212,7 +212,7 @@ export const LogEntryRateResultsContent: React.FunctionComponent = () => {
-
+
{
endTime,
isValidating,
validatedIndices,
+ setupStatus,
setValidatedIndices,
validationErrors,
}),
@@ -82,7 +84,8 @@ export const LogEntryRateSetupContent: React.FunctionComponent = () => {
+ />{' '}
+
diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/index.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/index.tsx
index 4aff907cfad66d..0dc52d27627657 100644
--- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/index.tsx
+++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/anomalies/index.tsx
@@ -93,7 +93,7 @@ export const AnomaliesResults: React.FunctionComponent<{
return (
<>
-
+
{title}
diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/log_rate/index.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/log_rate/index.tsx
index a11dc9d4d607ae..3da025d90119f1 100644
--- a/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/log_rate/index.tsx
+++ b/x-pack/legacy/plugins/infra/public/pages/logs/log_entry_rate/sections/log_rate/index.tsx
@@ -4,15 +4,16 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { EuiEmptyPrompt, EuiLoadingSpinner, EuiSpacer, EuiTitle, EuiText } from '@elastic/eui';
+import { EuiEmptyPrompt, EuiLoadingSpinner, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { useMemo } from 'react';
-import { LogEntryRateResults as Results } from '../../use_log_entry_rate_results';
import { TimeRange } from '../../../../../../common/http_api/shared/time_range';
-import { LogEntryRateBarChart } from './bar_chart';
-import { getLogEntryRatePartitionedSeries } from '../helpers/data_formatters';
+import { BetaBadge } from '../../../../../components/beta_badge';
import { LoadingOverlayWrapper } from '../../../../../components/loading_overlay_wrapper';
+import { LogEntryRateResults as Results } from '../../use_log_entry_rate_results';
+import { getLogEntryRatePartitionedSeries } from '../helpers/data_formatters';
+import { LogEntryRateBarChart } from './bar_chart';
export const LogRateResults = ({
isLoading,
@@ -33,7 +34,9 @@ export const LogRateResults = ({
return (
<>
- {title}
+
+ {title}
+
}>
{!results || (results && results.histogramBuckets && !results.histogramBuckets.length) ? (
diff --git a/x-pack/legacy/plugins/lens/public/datatable_visualization_plugin/visualization.test.tsx b/x-pack/legacy/plugins/lens/public/datatable_visualization_plugin/visualization.test.tsx
index 25d88fbae5b341..cb9350226575ca 100644
--- a/x-pack/legacy/plugins/lens/public/datatable_visualization_plugin/visualization.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/datatable_visualization_plugin/visualization.test.tsx
@@ -72,6 +72,42 @@ describe('Datatable Visualization', () => {
});
});
+ describe('#getLayerIds', () => {
+ it('return the layer ids', () => {
+ const state: DatatableVisualizationState = {
+ layers: [
+ {
+ layerId: 'baz',
+ columns: ['a', 'b', 'c'],
+ },
+ ],
+ };
+ expect(datatableVisualization.getLayerIds(state)).toEqual(['baz']);
+ });
+ });
+
+ describe('#clearLayer', () => {
+ it('should reset the layer', () => {
+ (generateId as jest.Mock).mockReturnValueOnce('testid');
+ const state: DatatableVisualizationState = {
+ layers: [
+ {
+ layerId: 'baz',
+ columns: ['a', 'b', 'c'],
+ },
+ ],
+ };
+ expect(datatableVisualization.clearLayer(state, 'baz')).toMatchObject({
+ layers: [
+ {
+ layerId: 'baz',
+ columns: ['testid'],
+ },
+ ],
+ });
+ });
+ });
+
describe('#getSuggestions', () => {
function numCol(columnId: string): TableSuggestionColumn {
return {
@@ -188,6 +224,7 @@ describe('Datatable Visualization', () => {
mount(
{} }}
frame={frame}
layer={layer}
@@ -224,6 +261,7 @@ describe('Datatable Visualization', () => {
frame.datasourceLayers = { a: datasource.publicAPIMock };
const component = mount(
{} }}
frame={frame}
layer={layer}
@@ -258,6 +296,7 @@ describe('Datatable Visualization', () => {
frame.datasourceLayers = { a: datasource.publicAPIMock };
const component = mount(
{} }}
frame={frame}
layer={layer}
@@ -290,6 +329,7 @@ describe('Datatable Visualization', () => {
frame.datasourceLayers = { a: datasource.publicAPIMock };
const component = mount(
{} }}
frame={frame}
layer={layer}
diff --git a/x-pack/legacy/plugins/lens/public/datatable_visualization_plugin/visualization.tsx b/x-pack/legacy/plugins/lens/public/datatable_visualization_plugin/visualization.tsx
index f9a7ec419a9b9a..79a018635134f6 100644
--- a/x-pack/legacy/plugins/lens/public/datatable_visualization_plugin/visualization.tsx
+++ b/x-pack/legacy/plugins/lens/public/datatable_visualization_plugin/visualization.tsx
@@ -6,19 +6,18 @@
import React from 'react';
import { render } from 'react-dom';
-import { EuiForm, EuiFormRow, EuiPanel, EuiSpacer } from '@elastic/eui';
+import { EuiFormRow } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { I18nProvider } from '@kbn/i18n/react';
import { MultiColumnEditor } from '../multi_column_editor';
import {
SuggestionRequest,
Visualization,
- VisualizationProps,
+ VisualizationLayerConfigProps,
VisualizationSuggestion,
Operation,
} from '../types';
import { generateId } from '../id_generator';
-import { NativeRenderer } from '../native_renderer';
import chartTableSVG from '../assets/chart_datatable.svg';
export interface LayerState {
@@ -56,7 +55,7 @@ export function DataTableLayer({
state,
setState,
dragDropContext,
-}: { layer: LayerState } & VisualizationProps) {
+}: { layer: LayerState } & VisualizationLayerConfigProps) {
const datasource = frame.datasourceLayers[layer.layerId];
const originalOrder = datasource.getTableSpec().map(({ columnId }) => columnId);
@@ -64,32 +63,24 @@ export function DataTableLayer({
const sortedColumns = Array.from(new Set(originalOrder.concat(layer.columns)));
return (
-
-
+ setState(updateColumns(state, layer, columns => [...columns, generateId()]))}
+ onRemove={column =>
+ setState(updateColumns(state, layer, columns => columns.filter(c => c !== column)))
+ }
+ testSubj="datatable_columns"
+ data-test-subj="datatable_multicolumnEditor"
/>
-
-
-
- setState(updateColumns(state, layer, columns => [...columns, generateId()]))}
- onRemove={column =>
- setState(updateColumns(state, layer, columns => columns.filter(c => c !== column)))
- }
- testSubj="datatable_columns"
- data-test-subj="datatable_multicolumnEditor"
- />
-
-
+
);
}
@@ -110,7 +101,17 @@ export const datatableVisualization: Visualization<
},
],
- getDescription(state) {
+ getLayerIds(state) {
+ return state.layers.map(l => l.layerId);
+ },
+
+ clearLayer(state) {
+ return {
+ layers: state.layers.map(l => newLayerState(l.layerId)),
+ };
+ },
+
+ getDescription() {
return {
icon: chartTableSVG,
label: i18n.translate('xpack.lens.datatable.label', {
@@ -187,17 +188,18 @@ export const datatableVisualization: Visualization<
];
},
- renderConfigPanel: (domElement, props) =>
- render(
-
-
- {props.state.layers.map(layer => (
-
- ))}
-
- ,
- domElement
- ),
+ renderLayerConfigPanel(domElement, props) {
+ const layer = props.state.layers.find(l => l.layerId === props.layerId);
+
+ if (layer) {
+ render(
+
+
+ ,
+ domElement
+ );
+ }
+ },
toExpression(state, frame) {
const layer = state.layers[0];
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/chart_switch.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/chart_switch.tsx
index dca6b3e7616d67..5e2fced5777246 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/chart_switch.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/chart_switch.tsx
@@ -81,7 +81,6 @@ export function ChartSwitch(props: Props) {
trackUiEvent(`chart_switch`);
switchToSuggestion(
- props.framePublicAPI,
props.dispatch,
{
...selection,
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/config_panel_wrapper.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/config_panel_wrapper.tsx
index 4179a9455eefad..1422ee86be3e9b 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/config_panel_wrapper.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/config_panel_wrapper.tsx
@@ -4,14 +4,36 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { useMemo, useContext, memo } from 'react';
+import React, { useMemo, useContext, memo, useState } from 'react';
+import {
+ EuiPanel,
+ EuiSpacer,
+ EuiPopover,
+ EuiButtonIcon,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiButtonEmpty,
+ EuiToolTip,
+ EuiButton,
+ EuiForm,
+} from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
import { NativeRenderer } from '../../native_renderer';
import { Action } from './state_management';
-import { Visualization, FramePublicAPI, Datasource } from '../../types';
+import {
+ Visualization,
+ FramePublicAPI,
+ Datasource,
+ VisualizationLayerConfigProps,
+} from '../../types';
import { DragContext } from '../../drag_drop';
import { ChartSwitch } from './chart_switch';
+import { trackUiEvent } from '../../lens_ui_telemetry';
+import { generateId } from '../../id_generator';
+import { removeLayer, appendLayer } from './layer_actions';
interface ConfigPanelWrapperProps {
+ activeDatasourceId: string;
visualizationState: unknown;
visualizationMap: Record;
activeVisualizationId: string | null;
@@ -28,17 +50,8 @@ interface ConfigPanelWrapperProps {
}
export const ConfigPanelWrapper = memo(function ConfigPanelWrapper(props: ConfigPanelWrapperProps) {
- const context = useContext(DragContext);
- const setVisualizationState = useMemo(
- () => (newState: unknown) => {
- props.dispatch({
- type: 'UPDATE_VISUALIZATION_STATE',
- newState,
- clearStagedPreview: false,
- });
- },
- [props.dispatch]
- );
+ const activeVisualization = props.visualizationMap[props.activeVisualizationId || ''];
+ const { visualizationState } = props;
return (
<>
@@ -52,19 +65,235 @@ export const ConfigPanelWrapper = memo(function ConfigPanelWrapper(props: Config
dispatch={props.dispatch}
framePublicAPI={props.framePublicAPI}
/>
- {props.activeVisualizationId && props.visualizationState !== null && (
-
-
-
+ {activeVisualization && visualizationState && (
+
)}
>
);
});
+
+function LayerPanels(
+ props: ConfigPanelWrapperProps & {
+ activeDatasourceId: string;
+ activeVisualization: Visualization;
+ }
+) {
+ const {
+ framePublicAPI,
+ activeVisualization,
+ visualizationState,
+ dispatch,
+ activeDatasourceId,
+ datasourceMap,
+ } = props;
+ const dragDropContext = useContext(DragContext);
+ const setState = useMemo(
+ () => (newState: unknown) => {
+ props.dispatch({
+ type: 'UPDATE_VISUALIZATION_STATE',
+ visualizationId: activeVisualization.id,
+ newState,
+ clearStagedPreview: false,
+ });
+ },
+ [props.dispatch, activeVisualization]
+ );
+ const layerIds = activeVisualization.getLayerIds(visualizationState);
+
+ return (
+
+ {layerIds.map(layerId => (
+ {
+ dispatch({
+ type: 'UPDATE_STATE',
+ subType: 'REMOVE_OR_CLEAR_LAYER',
+ updater: state =>
+ removeLayer({
+ activeVisualization,
+ layerId,
+ trackUiEvent,
+ datasourceMap,
+ state,
+ }),
+ });
+ }}
+ />
+ ))}
+ {activeVisualization.appendLayer && (
+
+
+ {
+ dispatch({
+ type: 'UPDATE_STATE',
+ subType: 'ADD_LAYER',
+ updater: state =>
+ appendLayer({
+ activeVisualization,
+ generateId,
+ trackUiEvent,
+ activeDatasource: datasourceMap[activeDatasourceId],
+ state,
+ }),
+ });
+ }}
+ iconType="plusInCircleFilled"
+ />
+
+
+ )}
+
+ );
+}
+
+function LayerPanel(
+ props: ConfigPanelWrapperProps &
+ VisualizationLayerConfigProps & {
+ isOnlyLayer: boolean;
+ activeVisualization: Visualization;
+ onRemove: () => void;
+ }
+) {
+ const { framePublicAPI, layerId, activeVisualization, isOnlyLayer, onRemove } = props;
+ const datasourcePublicAPI = framePublicAPI.datasourceLayers[layerId];
+ const layerConfigProps = {
+ layerId,
+ dragDropContext: props.dragDropContext,
+ state: props.visualizationState,
+ setState: props.setState,
+ frame: props.framePublicAPI,
+ };
+
+ return (
+
+
+
+
+
+
+ {datasourcePublicAPI && (
+
+
+
+ )}
+
+
+
+
+
+
+
+
+
+
+ {
+ // If we don't blur the remove / clear button, it remains focused
+ // which is a strange UX in this case. e.target.blur doesn't work
+ // due to who knows what, but probably event re-writing. Additionally,
+ // activeElement does not have blur so, we need to do some casting + safeguards.
+ const el = (document.activeElement as unknown) as { blur: () => void };
+
+ if (el && el.blur) {
+ el.blur();
+ }
+
+ onRemove();
+ }}
+ >
+ {isOnlyLayer
+ ? i18n.translate('xpack.lens.resetLayer', {
+ defaultMessage: 'Reset layer',
+ })
+ : i18n.translate('xpack.lens.deleteLayer', {
+ defaultMessage: 'Delete layer',
+ })}
+
+
+
+
+ );
+}
+
+function LayerSettings({
+ layerId,
+ activeVisualization,
+ layerConfigProps,
+}: {
+ layerId: string;
+ activeVisualization: Visualization;
+ layerConfigProps: VisualizationLayerConfigProps;
+}) {
+ const [isOpen, setIsOpen] = useState(false);
+
+ if (!activeVisualization.renderLayerContextMenu) {
+ return null;
+ }
+
+ return (
+ setIsOpen(!isOpen)}
+ data-test-subj="lns_layer_settings"
+ />
+ }
+ isOpen={isOpen}
+ closePopover={() => setIsOpen(false)}
+ anchorPosition="leftUp"
+ >
+
+
+ );
+}
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.test.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.test.tsx
index cf711eea29b963..c9b9a433766515 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.test.tsx
@@ -9,7 +9,7 @@ import { ReactWrapper } from 'enzyme';
import { EuiPanel, EuiToolTip } from '@elastic/eui';
import { mountWithIntl as mount } from 'test_utils/enzyme_helpers';
import { EditorFrame } from './editor_frame';
-import { Visualization, DatasourcePublicAPI, DatasourceSuggestion } from '../../types';
+import { DatasourcePublicAPI, DatasourceSuggestion, Visualization } from '../../types';
import { act } from 'react-dom/test-utils';
import { coreMock } from 'src/core/public/mocks';
import {
@@ -24,7 +24,11 @@ import { FrameLayout } from './frame_layout';
// calling this function will wait for all pending Promises from mock
// datasources to be processed by its callers.
-const waitForPromises = () => new Promise(resolve => setTimeout(resolve));
+async function waitForPromises(n = 3) {
+ for (let i = 0; i < n; ++i) {
+ await Promise.resolve();
+ }
+}
function generateSuggestion(state = {}): DatasourceSuggestion {
return {
@@ -88,6 +92,9 @@ describe('editor_frame', () => {
],
};
+ mockVisualization.getLayerIds.mockReturnValue(['first']);
+ mockVisualization2.getLayerIds.mockReturnValue(['second']);
+
mockDatasource = createMockDatasource();
mockDatasource2 = createMockDatasource();
@@ -202,7 +209,7 @@ describe('editor_frame', () => {
);
});
- expect(mockVisualization.renderConfigPanel).not.toHaveBeenCalled();
+ expect(mockVisualization.renderLayerConfigPanel).not.toHaveBeenCalled();
expect(mockDatasource.renderDataPanel).not.toHaveBeenCalled();
});
@@ -294,6 +301,7 @@ describe('editor_frame', () => {
it('should remove layer on active datasource on frame api call', async () => {
const initialState = { datasource2: '' };
+ mockDatasource.getLayers.mockReturnValue(['first']);
mockDatasource2.initialize.mockReturnValue(Promise.resolve(initialState));
mockDatasource2.getLayers.mockReturnValue(['abc', 'def']);
mockDatasource2.removeLayer.mockReturnValue({ removed: true });
@@ -361,7 +369,7 @@ describe('editor_frame', () => {
it('should initialize visualization state and render config panel', async () => {
const initialState = {};
-
+ mockDatasource.getLayers.mockReturnValue(['first']);
mount(
{
await waitForPromises();
- expect(mockVisualization.renderConfigPanel).toHaveBeenCalledWith(
+ expect(mockVisualization.renderLayerConfigPanel).toHaveBeenCalledWith(
expect.any(Element),
expect.objectContaining({ state: initialState })
);
@@ -390,6 +398,7 @@ describe('editor_frame', () => {
it('should render the resulting expression using the expression renderer', async () => {
mockDatasource.getLayers.mockReturnValue(['first']);
+
const instance = mount(
{
/>
);
- await waitForPromises();
await waitForPromises();
instance.update();
@@ -601,6 +609,7 @@ describe('editor_frame', () => {
describe('state update', () => {
it('should re-render config panel after state update', async () => {
+ mockDatasource.getLayers.mockReturnValue(['first']);
mount(
{
await waitForPromises();
const updatedState = {};
- const setVisualizationState = (mockVisualization.renderConfigPanel as jest.Mock).mock
+ const setVisualizationState = (mockVisualization.renderLayerConfigPanel as jest.Mock).mock
.calls[0][1].setState;
act(() => {
setVisualizationState(updatedState);
});
- expect(mockVisualization.renderConfigPanel).toHaveBeenCalledTimes(2);
- expect(mockVisualization.renderConfigPanel).toHaveBeenLastCalledWith(
+ expect(mockVisualization.renderLayerConfigPanel).toHaveBeenCalledTimes(2);
+ expect(mockVisualization.renderLayerConfigPanel).toHaveBeenLastCalledWith(
expect.any(Element),
expect.objectContaining({
state: updatedState,
@@ -635,6 +644,7 @@ describe('editor_frame', () => {
});
it('should re-render data panel after state update', async () => {
+ mockDatasource.getLayers.mockReturnValue(['first']);
mount(
{
await waitForPromises();
- const updatedPublicAPI = {};
- mockDatasource.getPublicAPI.mockReturnValue(
- (updatedPublicAPI as unknown) as DatasourcePublicAPI
- );
+ const updatedPublicAPI: DatasourcePublicAPI = {
+ renderLayerPanel: jest.fn(),
+ renderDimensionPanel: jest.fn(),
+ getOperationForColumnId: jest.fn(),
+ getTableSpec: jest.fn(),
+ };
+ mockDatasource.getPublicAPI.mockReturnValue(updatedPublicAPI);
const setDatasourceState = (mockDatasource.renderDataPanel as jest.Mock).mock.calls[0][1]
.setState;
@@ -700,8 +713,8 @@ describe('editor_frame', () => {
setDatasourceState({});
});
- expect(mockVisualization.renderConfigPanel).toHaveBeenCalledTimes(2);
- expect(mockVisualization.renderConfigPanel).toHaveBeenLastCalledWith(
+ expect(mockVisualization.renderLayerConfigPanel).toHaveBeenCalledTimes(2);
+ expect(mockVisualization.renderLayerConfigPanel).toHaveBeenLastCalledWith(
expect.any(Element),
expect.objectContaining({
frame: expect.objectContaining({
@@ -754,10 +767,10 @@ describe('editor_frame', () => {
await waitForPromises();
- expect(mockVisualization.renderConfigPanel).toHaveBeenCalled();
+ expect(mockVisualization.renderLayerConfigPanel).toHaveBeenCalled();
const datasourceLayers =
- mockVisualization.renderConfigPanel.mock.calls[0][1].frame.datasourceLayers;
+ mockVisualization.renderLayerConfigPanel.mock.calls[0][1].frame.datasourceLayers;
expect(datasourceLayers.first).toBe(mockDatasource.publicAPIMock);
expect(datasourceLayers.second).toBe(mockDatasource2.publicAPIMock);
expect(datasourceLayers.third).toBe(mockDatasource2.publicAPIMock);
@@ -919,7 +932,7 @@ describe('editor_frame', () => {
}
beforeEach(async () => {
- mockDatasource.getLayers.mockReturnValue(['first']);
+ mockDatasource.getLayers.mockReturnValue(['first', 'second']);
mockDatasource.getDatasourceSuggestionsFromCurrentState.mockReturnValue([
{
state: {},
@@ -1018,7 +1031,7 @@ describe('editor_frame', () => {
expect(mockVisualization2.getSuggestions).toHaveBeenCalled();
expect(mockVisualization2.initialize).toHaveBeenCalledWith(expect.anything(), initialState);
- expect(mockVisualization2.renderConfigPanel).toHaveBeenCalledWith(
+ expect(mockVisualization2.renderLayerConfigPanel).toHaveBeenCalledWith(
expect.any(Element),
expect.objectContaining({ state: { initial: true } })
);
@@ -1032,9 +1045,11 @@ describe('editor_frame', () => {
expect(mockDatasource.publicAPIMock.getTableSpec).toHaveBeenCalled();
expect(mockVisualization2.getSuggestions).toHaveBeenCalled();
expect(mockVisualization2.initialize).toHaveBeenCalledWith(
- expect.objectContaining({ datasourceLayers: { first: mockDatasource.publicAPIMock } })
+ expect.objectContaining({
+ datasourceLayers: expect.objectContaining({ first: mockDatasource.publicAPIMock }),
+ })
);
- expect(mockVisualization2.renderConfigPanel).toHaveBeenCalledWith(
+ expect(mockVisualization2.renderLayerConfigPanel).toHaveBeenCalledWith(
expect.any(Element),
expect.objectContaining({ state: { initial: true } })
);
@@ -1102,6 +1117,7 @@ describe('editor_frame', () => {
});
it('should display top 5 suggestions in descending order', async () => {
+ mockDatasource.getLayers.mockReturnValue(['first']);
const instance = mount(
{
});
it('should switch to suggested visualization', async () => {
+ mockDatasource.getLayers.mockReturnValue(['first', 'second', 'third']);
const newDatasourceState = {};
const suggestionVisState = {};
const instance = mount(
@@ -1228,8 +1245,8 @@ describe('editor_frame', () => {
.simulate('click');
});
- expect(mockVisualization.renderConfigPanel).toHaveBeenCalledTimes(1);
- expect(mockVisualization.renderConfigPanel).toHaveBeenCalledWith(
+ expect(mockVisualization.renderLayerConfigPanel).toHaveBeenCalledTimes(1);
+ expect(mockVisualization.renderLayerConfigPanel).toHaveBeenCalledWith(
expect.any(Element),
expect.objectContaining({
state: suggestionVisState,
@@ -1244,6 +1261,7 @@ describe('editor_frame', () => {
});
it('should switch to best suggested visualization on field drop', async () => {
+ mockDatasource.getLayers.mockReturnValue(['first']);
const suggestionVisState = {};
const instance = mount(
{
.simulate('drop');
});
- expect(mockVisualization.renderConfigPanel).toHaveBeenCalledWith(
+ expect(mockVisualization.renderLayerConfigPanel).toHaveBeenCalledWith(
expect.any(Element),
expect.objectContaining({
state: suggestionVisState,
@@ -1302,6 +1320,7 @@ describe('editor_frame', () => {
});
it('should use the currently selected visualization if possible on field drop', async () => {
+ mockDatasource.getLayers.mockReturnValue(['first', 'second', 'third']);
const suggestionVisState = {};
const instance = mount(
{
});
});
- expect(mockVisualization2.renderConfigPanel).toHaveBeenCalledWith(
+ expect(mockVisualization2.renderLayerConfigPanel).toHaveBeenCalledWith(
expect.any(Element),
expect.objectContaining({
state: suggestionVisState,
@@ -1375,10 +1394,12 @@ describe('editor_frame', () => {
});
it('should use the highest priority suggestion available', async () => {
+ mockDatasource.getLayers.mockReturnValue(['first', 'second', 'third']);
const suggestionVisState = {};
const mockVisualization3 = {
...createMockVisualization(),
id: 'testVis3',
+ getLayerIds: () => ['third'],
visualizationTypes: [
{
icon: 'empty',
@@ -1460,7 +1481,7 @@ describe('editor_frame', () => {
});
});
- expect(mockVisualization3.renderConfigPanel).toHaveBeenCalledWith(
+ expect(mockVisualization3.renderLayerConfigPanel).toHaveBeenCalledWith(
expect.any(Element),
expect.objectContaining({
state: suggestionVisState,
@@ -1633,13 +1654,16 @@ describe('editor_frame', () => {
await waitForPromises();
expect(onChange).toHaveBeenCalledTimes(2);
- (instance.find(FrameLayout).prop('dataPanel') as ReactElement)!.props.dispatch({
- type: 'UPDATE_DATASOURCE_STATE',
- updater: () => ({
- newState: true,
- }),
- datasourceId: 'testDatasource',
+ act(() => {
+ (instance.find(FrameLayout).prop('dataPanel') as ReactElement)!.props.dispatch({
+ type: 'UPDATE_DATASOURCE_STATE',
+ updater: () => ({
+ newState: true,
+ }),
+ datasourceId: 'testDatasource',
+ });
});
+
await waitForPromises();
expect(onChange).toHaveBeenCalledTimes(3);
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.tsx
index a2745818e19bb0..3284f69b503c5f 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.tsx
@@ -52,6 +52,8 @@ export interface EditorFrameProps {
export function EditorFrame(props: EditorFrameProps) {
const [state, dispatch] = useReducer(reducer, props, getInitialState);
const { onError } = props;
+ const activeVisualization =
+ state.visualization.activeId && props.visualizationMap[state.visualization.activeId];
const allLoaded = Object.values(state.datasourceStates).every(
({ isLoading }) => typeof isLoading === 'boolean' && !isLoading
@@ -125,7 +127,20 @@ export function EditorFrame(props: EditorFrameProps) {
return newLayerId;
},
- removeLayers: (layerIds: string[]) => {
+
+ removeLayers(layerIds: string[]) {
+ if (activeVisualization && activeVisualization.removeLayer && state.visualization.state) {
+ dispatch({
+ type: 'UPDATE_VISUALIZATION_STATE',
+ visualizationId: activeVisualization.id,
+ newState: layerIds.reduce(
+ (acc, layerId) =>
+ activeVisualization.removeLayer ? activeVisualization.removeLayer(acc, layerId) : acc,
+ state.visualization.state
+ ),
+ });
+ }
+
layerIds.forEach(layerId => {
const layerDatasourceId = Object.entries(props.datasourceMap).find(
([datasourceId, datasource]) =>
@@ -158,16 +173,15 @@ export function EditorFrame(props: EditorFrameProps) {
// Initialize visualization as soon as all datasources are ready
useEffect(() => {
- if (allLoaded && state.visualization.state === null && state.visualization.activeId !== null) {
- const initialVisualizationState = props.visualizationMap[
- state.visualization.activeId
- ].initialize(framePublicAPI);
+ if (allLoaded && state.visualization.state === null && activeVisualization) {
+ const initialVisualizationState = activeVisualization.initialize(framePublicAPI);
dispatch({
type: 'UPDATE_VISUALIZATION_STATE',
+ visualizationId: activeVisualization.id,
newState: initialVisualizationState,
});
}
- }, [allLoaded, state.visualization.activeId, state.visualization.state]);
+ }, [allLoaded, activeVisualization, state.visualization.state]);
// The frame needs to call onChange every time its internal state changes
useEffect(() => {
@@ -176,11 +190,7 @@ export function EditorFrame(props: EditorFrameProps) {
? props.datasourceMap[state.activeDatasourceId]
: undefined;
- const visualization = state.visualization.activeId
- ? props.visualizationMap[state.visualization.activeId]
- : undefined;
-
- if (!activeDatasource || !visualization) {
+ if (!activeDatasource || !activeVisualization) {
return;
}
@@ -208,13 +218,14 @@ export function EditorFrame(props: EditorFrameProps) {
}),
{}
),
- visualization,
+ visualization: activeVisualization,
state,
framePublicAPI,
});
props.onChange({ filterableIndexPatterns: indexPatterns, doc });
}, [
+ activeVisualization,
state.datasourceStates,
state.visualization,
props.query,
@@ -248,6 +259,7 @@ export function EditorFrame(props: EditorFrameProps) {
configPanel={
allLoaded && (
({
+ id: datasourceId,
+ clearLayer: (layerIds: unknown, layerId: string) =>
+ (layerIds as string[]).map((id: string) =>
+ id === layerId ? `${datasourceId}_clear_${layerId}` : id
+ ),
+ removeLayer: (layerIds: unknown, layerId: string) =>
+ (layerIds as string[]).filter((id: string) => id !== layerId),
+ insertLayer: (layerIds: unknown, layerId: string) => [...(layerIds as string[]), layerId],
+ });
+
+ const activeVisualization = {
+ clearLayer: (layerIds: unknown, layerId: string) =>
+ (layerIds as string[]).map((id: string) => (id === layerId ? `vis_clear_${layerId}` : id)),
+ removeLayer: (layerIds: unknown, layerId: string) =>
+ (layerIds as string[]).filter((id: string) => id !== layerId),
+ getLayerIds: (layerIds: unknown) => layerIds as string[],
+ appendLayer: (layerIds: unknown, layerId: string) => [...(layerIds as string[]), layerId],
+ };
+
+ return {
+ state: {
+ activeDatasourceId: 'ds1',
+ datasourceStates: {
+ ds1: {
+ isLoading: false,
+ state: initialLayerIds.slice(0, 1),
+ },
+ ds2: {
+ isLoading: false,
+ state: initialLayerIds.slice(1),
+ },
+ },
+ title: 'foo',
+ visualization: {
+ activeId: 'vis1',
+ state: initialLayerIds,
+ },
+ },
+ activeVisualization,
+ datasourceMap: {
+ ds1: testDatasource('ds1'),
+ ds2: testDatasource('ds2'),
+ },
+ trackUiEvent,
+ };
+}
+
+describe('removeLayer', () => {
+ it('should clear the layer if it is the only layer', () => {
+ const { state, trackUiEvent, datasourceMap, activeVisualization } = createTestArgs(['layer1']);
+ const newState = removeLayer({
+ activeVisualization,
+ datasourceMap,
+ layerId: 'layer1',
+ state,
+ trackUiEvent,
+ });
+
+ expect(newState.visualization.state).toEqual(['vis_clear_layer1']);
+ expect(newState.datasourceStates.ds1.state).toEqual(['ds1_clear_layer1']);
+ expect(newState.datasourceStates.ds2.state).toEqual([]);
+ expect(trackUiEvent).toHaveBeenCalledWith('layer_cleared');
+ });
+
+ it('should remove the layer if it is not the only layer', () => {
+ const { state, trackUiEvent, datasourceMap, activeVisualization } = createTestArgs([
+ 'layer1',
+ 'layer2',
+ ]);
+ const newState = removeLayer({
+ activeVisualization,
+ datasourceMap,
+ layerId: 'layer1',
+ state,
+ trackUiEvent,
+ });
+
+ expect(newState.visualization.state).toEqual(['layer2']);
+ expect(newState.datasourceStates.ds1.state).toEqual([]);
+ expect(newState.datasourceStates.ds2.state).toEqual(['layer2']);
+ expect(trackUiEvent).toHaveBeenCalledWith('layer_removed');
+ });
+});
+
+describe('appendLayer', () => {
+ it('should add the layer to the datasource and visualization', () => {
+ const { state, trackUiEvent, datasourceMap, activeVisualization } = createTestArgs([
+ 'layer1',
+ 'layer2',
+ ]);
+ const newState = appendLayer({
+ activeDatasource: datasourceMap.ds1,
+ activeVisualization,
+ generateId: () => 'foo',
+ state,
+ trackUiEvent,
+ });
+
+ expect(newState.visualization.state).toEqual(['layer1', 'layer2', 'foo']);
+ expect(newState.datasourceStates.ds1.state).toEqual(['layer1', 'foo']);
+ expect(newState.datasourceStates.ds2.state).toEqual(['layer2']);
+ expect(trackUiEvent).toHaveBeenCalledWith('layer_added');
+ });
+});
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/layer_actions.ts b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/layer_actions.ts
new file mode 100644
index 00000000000000..e0562e8ca8e11c
--- /dev/null
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/layer_actions.ts
@@ -0,0 +1,88 @@
+/*
+ * 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 _ from 'lodash';
+import { EditorFrameState } from './state_management';
+import { Datasource, Visualization } from '../../types';
+
+interface RemoveLayerOptions {
+ trackUiEvent: (name: string) => void;
+ state: EditorFrameState;
+ layerId: string;
+ activeVisualization: Pick;
+ datasourceMap: Record>;
+}
+
+interface AppendLayerOptions {
+ trackUiEvent: (name: string) => void;
+ state: EditorFrameState;
+ generateId: () => string;
+ activeDatasource: Pick;
+ activeVisualization: Pick;
+}
+
+export function removeLayer(opts: RemoveLayerOptions): EditorFrameState {
+ const { state, trackUiEvent: trackUiEvent, activeVisualization, layerId, datasourceMap } = opts;
+ const isOnlyLayer = activeVisualization
+ .getLayerIds(state.visualization.state)
+ .every(id => id === opts.layerId);
+
+ trackUiEvent(isOnlyLayer ? 'layer_cleared' : 'layer_removed');
+
+ return {
+ ...state,
+ datasourceStates: _.mapValues(state.datasourceStates, (datasourceState, datasourceId) => {
+ const datasource = datasourceMap[datasourceId!];
+ return {
+ ...datasourceState,
+ state: isOnlyLayer
+ ? datasource.clearLayer(datasourceState.state, layerId)
+ : datasource.removeLayer(datasourceState.state, layerId),
+ };
+ }),
+ visualization: {
+ ...state.visualization,
+ state:
+ isOnlyLayer || !activeVisualization.removeLayer
+ ? activeVisualization.clearLayer(state.visualization.state, layerId)
+ : activeVisualization.removeLayer(state.visualization.state, layerId),
+ },
+ };
+}
+
+export function appendLayer({
+ trackUiEvent,
+ activeVisualization,
+ state,
+ generateId,
+ activeDatasource,
+}: AppendLayerOptions): EditorFrameState {
+ trackUiEvent('layer_added');
+
+ if (!activeVisualization.appendLayer) {
+ return state;
+ }
+
+ const layerId = generateId();
+
+ return {
+ ...state,
+ datasourceStates: {
+ ...state.datasourceStates,
+ [activeDatasource.id]: {
+ ...state.datasourceStates[activeDatasource.id],
+ state: activeDatasource.insertLayer(
+ state.datasourceStates[activeDatasource.id].state,
+ layerId
+ ),
+ },
+ },
+ visualization: {
+ ...state.visualization,
+ state: activeVisualization.appendLayer(state.visualization.state, layerId),
+ },
+ };
+}
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/state_management.test.ts b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/state_management.test.ts
index 5168059a332589..4aaf2a3ee9e81e 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/state_management.test.ts
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/state_management.test.ts
@@ -119,6 +119,7 @@ describe('editor_frame state management', () => {
},
{
type: 'UPDATE_VISUALIZATION_STATE',
+ visualizationId: 'testVis',
newState: newVisState,
}
);
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/state_management.ts b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/state_management.ts
index 78a9a13f48d6aa..7d763bcac2cc9b 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/state_management.ts
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/state_management.ts
@@ -31,6 +31,13 @@ export type Action =
type: 'UPDATE_TITLE';
title: string;
}
+ | {
+ type: 'UPDATE_STATE';
+ // Just for diagnostics, so we can determine what action
+ // caused this update.
+ subType: string;
+ updater: (prevState: EditorFrameState) => EditorFrameState;
+ }
| {
type: 'UPDATE_DATASOURCE_STATE';
updater: unknown | ((prevState: unknown) => unknown);
@@ -39,6 +46,7 @@ export type Action =
}
| {
type: 'UPDATE_VISUALIZATION_STATE';
+ visualizationId: string;
newState: unknown;
clearStagedPreview?: boolean;
}
@@ -128,6 +136,8 @@ export const reducer = (state: EditorFrameState, action: Action): EditorFrameSta
return action.state;
case 'UPDATE_TITLE':
return { ...state, title: action.title };
+ case 'UPDATE_STATE':
+ return action.updater(state);
case 'UPDATE_LAYER':
return {
...state,
@@ -249,6 +259,12 @@ export const reducer = (state: EditorFrameState, action: Action): EditorFrameSta
if (!state.visualization.activeId) {
throw new Error('Invariant: visualization state got updated without active visualization');
}
+ // This is a safeguard that prevents us from accidentally updating the
+ // wrong visualization. This occurs in some cases due to the uncoordinated
+ // way we manage state across plugins.
+ if (state.visualization.activeId !== action.visualizationId) {
+ return state;
+ }
return {
...state,
visualization: {
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_helpers.ts b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_helpers.ts
index 173f64c6292a87..eabcdfa7a24ab4 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_helpers.ts
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_helpers.ts
@@ -10,7 +10,6 @@ import { IconType } from '@elastic/eui/src/components/icon/icon';
import {
Visualization,
Datasource,
- FramePublicAPI,
TableChangeType,
TableSuggestion,
DatasourceSuggestion,
@@ -130,7 +129,6 @@ function getVisualizationSuggestions(
}
export function switchToSuggestion(
- frame: FramePublicAPI,
dispatch: (action: Action) => void,
suggestion: Pick<
Suggestion,
@@ -145,5 +143,6 @@ export function switchToSuggestion(
datasourceState: suggestion.datasourceState,
datasourceId: suggestion.datasourceId!,
};
+
dispatch(action);
}
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx
index 2408d004689c9d..46e226afe9c59b 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx
@@ -320,7 +320,7 @@ export function SuggestionPanel({
} else {
trackSuggestionEvent(`position_${index}_of_${suggestions.length}`);
setLastSelectedSuggestion(index);
- switchToSuggestion(frame, dispatch, suggestion);
+ switchToSuggestion(dispatch, suggestion);
}
}}
selected={index === lastSelectedSuggestion}
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel.test.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel.test.tsx
index fb3fe770b315b3..74dacd50d7a159 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel.test.tsx
@@ -6,7 +6,7 @@
import React from 'react';
import { ExpressionRendererProps } from '../../../../../../../src/plugins/expressions/public';
-import { Visualization, FramePublicAPI, TableSuggestion } from '../../types';
+import { FramePublicAPI, TableSuggestion, Visualization } from '../../types';
import {
createMockVisualization,
createMockDatasource,
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel.tsx
index 05dcafcaeba319..1058ccd81d6696 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel.tsx
@@ -126,12 +126,7 @@ export function InnerWorkspacePanel({
if (suggestionForDraggedField) {
trackUiEvent('drop_onto_workspace');
trackUiEvent(expression ? 'drop_non_empty' : 'drop_empty');
- switchToSuggestion(
- framePublicAPI,
- dispatch,
- suggestionForDraggedField,
- 'SWITCH_VISUALIZATION'
- );
+ switchToSuggestion(dispatch, suggestionForDraggedField, 'SWITCH_VISUALIZATION');
}
}
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/mocks.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/mocks.tsx
index 5df6cc8106d6af..7257647d5953e5 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/mocks.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/mocks.tsx
@@ -14,12 +14,14 @@ import {
import { embeddablePluginMock } from '../../../../../../src/plugins/embeddable/public/mocks';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { expressionsPluginMock } from '../../../../../../src/plugins/expressions/public/mocks';
-import { DatasourcePublicAPI, FramePublicAPI, Visualization, Datasource } from '../types';
+import { DatasourcePublicAPI, FramePublicAPI, Datasource, Visualization } from '../types';
import { EditorFrameSetupPlugins, EditorFrameStartPlugins } from './plugin';
export function createMockVisualization(): jest.Mocked {
return {
id: 'TEST_VIS',
+ clearLayer: jest.fn((state, _layerId) => state),
+ getLayerIds: jest.fn(_state => ['layer1']),
visualizationTypes: [
{
icon: 'empty',
@@ -32,7 +34,7 @@ export function createMockVisualization(): jest.Mocked {
getPersistableState: jest.fn(_state => _state),
getSuggestions: jest.fn(_options => []),
initialize: jest.fn((_frame, _state?) => ({})),
- renderConfigPanel: jest.fn(),
+ renderLayerConfigPanel: jest.fn(),
toExpression: jest.fn((_state, _frame) => null),
toPreviewExpression: jest.fn((_state, _frame) => null),
};
@@ -52,7 +54,8 @@ export function createMockDatasource(): DatasourceMock {
return {
id: 'mockindexpattern',
- getDatasourceSuggestionsForField: jest.fn((_state, item) => []),
+ clearLayer: jest.fn((state, _layerId) => state),
+ getDatasourceSuggestionsForField: jest.fn((_state, _item) => []),
getDatasourceSuggestionsFromCurrentState: jest.fn(_state => []),
getPersistableState: jest.fn(),
getPublicAPI: jest.fn().mockReturnValue(publicAPIMock),
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx
index 52f00a7cd4e9df..b04bd3a4e9be9d 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.test.tsx
@@ -282,7 +282,7 @@ describe('IndexPattern Data Panel', () => {
const parts = url.split('/');
const indexPatternTitle = parts[parts.length - 1];
return {
- indexPatternTitle,
+ indexPatternTitle: `${indexPatternTitle}_testtitle`,
existingFieldNames: ['field_1', 'field_2'].map(
fieldName => `${indexPatternTitle}_${fieldName}`
),
@@ -352,9 +352,9 @@ describe('IndexPattern Data Panel', () => {
});
expect(nextState.existingFields).toEqual({
- aaa: {
- aaa_field_1: true,
- aaa_field_2: true,
+ a_testtitle: {
+ a_field_1: true,
+ a_field_2: true,
},
});
});
@@ -369,13 +369,13 @@ describe('IndexPattern Data Panel', () => {
});
expect(nextState.existingFields).toEqual({
- aaa: {
- aaa_field_1: true,
- aaa_field_2: true,
+ a_testtitle: {
+ a_field_1: true,
+ a_field_2: true,
},
- bbb: {
- bbb_field_1: true,
- bbb_field_2: true,
+ b_testtitle: {
+ b_field_1: true,
+ b_field_2: true,
},
});
});
@@ -397,7 +397,7 @@ describe('IndexPattern Data Panel', () => {
expect(setState).toHaveBeenCalledTimes(2);
expect(core.http.get).toHaveBeenCalledTimes(2);
- expect(core.http.get).toHaveBeenCalledWith('/api/lens/existing_fields/aaa', {
+ expect(core.http.get).toHaveBeenCalledWith('/api/lens/existing_fields/a', {
query: {
fromDate: '2019-01-01',
toDate: '2020-01-01',
@@ -405,7 +405,7 @@ describe('IndexPattern Data Panel', () => {
},
});
- expect(core.http.get).toHaveBeenCalledWith('/api/lens/existing_fields/aaa', {
+ expect(core.http.get).toHaveBeenCalledWith('/api/lens/existing_fields/a', {
query: {
fromDate: '2019-01-01',
toDate: '2020-01-02',
@@ -418,9 +418,9 @@ describe('IndexPattern Data Panel', () => {
});
expect(nextState.existingFields).toEqual({
- aaa: {
- aaa_field_1: true,
- aaa_field_2: true,
+ a_testtitle: {
+ a_field_1: true,
+ a_field_2: true,
},
});
});
@@ -436,7 +436,7 @@ describe('IndexPattern Data Panel', () => {
expect(setState).toHaveBeenCalledTimes(2);
- expect(core.http.get).toHaveBeenCalledWith('/api/lens/existing_fields/aaa', {
+ expect(core.http.get).toHaveBeenCalledWith('/api/lens/existing_fields/a', {
query: {
fromDate: '2019-01-01',
toDate: '2020-01-01',
@@ -444,7 +444,7 @@ describe('IndexPattern Data Panel', () => {
},
});
- expect(core.http.get).toHaveBeenCalledWith('/api/lens/existing_fields/bbb', {
+ expect(core.http.get).toHaveBeenCalledWith('/api/lens/existing_fields/b', {
query: {
fromDate: '2019-01-01',
toDate: '2020-01-01',
@@ -457,13 +457,13 @@ describe('IndexPattern Data Panel', () => {
});
expect(nextState.existingFields).toEqual({
- aaa: {
- aaa_field_1: true,
- aaa_field_2: true,
+ a_testtitle: {
+ a_field_1: true,
+ a_field_2: true,
},
- bbb: {
- bbb_field_1: true,
- bbb_field_2: true,
+ b_testtitle: {
+ b_field_1: true,
+ b_field_2: true,
},
});
});
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.tsx
index 6a2f6234279c70..3231ab7d7ff12c 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.tsx
@@ -109,6 +109,7 @@ export function IndexPatternDataPanel({
.sort((a, b) => a.localeCompare(b))
.filter(id => !!indexPatterns[id])
.map(id => ({
+ id,
title: indexPatterns[id].title,
timeFieldName: indexPatterns[id].timeFieldName,
}));
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_icon.test.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_icon.test.tsx
index 85c1deb0ea7e1a..e0e33ef03d3d19 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_icon.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_icon.test.tsx
@@ -17,37 +17,37 @@ import { FieldIcon } from './field_icon';
describe('FieldIcon', () => {
it('should render icons', () => {
expect(shallow( )).toMatchInlineSnapshot(`
-
- `);
+
+ `);
expect(shallow( )).toMatchInlineSnapshot(`
-
- `);
+
+ `);
expect(shallow( )).toMatchInlineSnapshot(`
-
- `);
+
+ `);
expect(shallow( )).toMatchInlineSnapshot(`
-
- `);
+
+ `);
expect(shallow( )).toMatchInlineSnapshot(`
`);
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_icon.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_icon.tsx
index f1e8db04860a7d..796f200bffd972 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_icon.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/field_icon.tsx
@@ -5,7 +5,7 @@
*/
import React from 'react';
-import { ICON_TYPES, palettes, EuiIcon } from '@elastic/eui';
+import { ICON_TYPES, euiPaletteColorBlind, EuiIcon } from '@elastic/eui';
import classNames from 'classnames';
import { DataType } from '../types';
@@ -24,7 +24,7 @@ function getIconForDataType(dataType: string) {
export function getColorForDataType(type: string) {
const iconType = getIconForDataType(type);
- const { colors } = palettes.euiPaletteColorBlind;
+ const colors = euiPaletteColorBlind();
const colorIndex = stringToNum(iconType) % colors.length;
return colors[colorIndex];
}
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern.tsx
index b58a2d8ca52c75..2426d7fc14b5d6 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern.tsx
@@ -132,11 +132,7 @@ export function getIndexPatternDatasource({
...state,
layers: {
...state.layers,
- [newLayerId]: {
- indexPatternId: state.currentIndexPatternId,
- columns: {},
- columnOrder: [],
- },
+ [newLayerId]: blankLayer(state.currentIndexPatternId),
},
};
},
@@ -151,6 +147,16 @@ export function getIndexPatternDatasource({
};
},
+ clearLayer(state: IndexPatternPrivateState, layerId: string) {
+ return {
+ ...state,
+ layers: {
+ ...state.layers,
+ [layerId]: blankLayer(state.currentIndexPatternId),
+ },
+ };
+ },
+
getLayers(state: IndexPatternPrivateState) {
return Object.keys(state.layers);
},
@@ -280,3 +286,11 @@ export function getIndexPatternDatasource({
return indexPatternDatasource;
}
+
+function blankLayer(indexPatternId: string) {
+ return {
+ indexPatternId,
+ columns: {},
+ columnOrder: [],
+ };
+}
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/lens_field_icon.test.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/lens_field_icon.test.tsx
index 7441083550706d..a470f5fc51cfb7 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/lens_field_icon.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/lens_field_icon.test.tsx
@@ -20,10 +20,10 @@ test('LensFieldIcon renders properly', () => {
test('LensFieldIcon getColorForDataType for a valid type', () => {
const color = getColorForDataType('date');
- expect(color).toEqual('#B0916F');
+ expect(color).toEqual('#F19F58');
});
test('LensFieldIcon getColorForDataType for an invalid type', () => {
const color = getColorForDataType('invalid');
- expect(color).toEqual('#1EA593');
+ expect(color).toEqual('#5BBAA0');
});
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/lens_field_icon.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/lens_field_icon.tsx
index cd2bb69f6e580b..2e6a5fcd8115fb 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/lens_field_icon.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/lens_field_icon.tsx
@@ -5,7 +5,7 @@
*/
import React from 'react';
-import { palettes } from '@elastic/eui';
+import { euiPaletteColorBlind } from '@elastic/eui';
import { FieldIcon, typeToEuiIconMap } from '../../../../../../src/plugins/kibana_react/public';
import { DataType } from '../types';
import { normalizeOperationDataType } from './utils';
@@ -15,7 +15,7 @@ export function getColorForDataType(type: string) {
if (iconMap) {
return iconMap.color;
}
- return palettes.euiPaletteColorBlind.colors[0];
+ return euiPaletteColorBlind()[0];
}
export function LensFieldIcon({ type }: { type: DataType }) {
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.test.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.test.ts
index e180ab690d4185..6bea13c32830fb 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.test.ts
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.test.ts
@@ -551,7 +551,7 @@ describe('loader', () => {
dateRange: { fromDate: '1900-01-01', toDate: '2000-01-01' },
// eslint-disable-next-line @typescript-eslint/no-explicit-any
fetchJson: fetchJson as any,
- indexPatterns: [{ title: 'a' }, { title: 'b' }, { title: 'c' }],
+ indexPatterns: [{ id: 'a' }, { id: 'b' }, { id: 'c' }],
setState,
});
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.ts
index 7f46f50786cf48..c196cb886e575b 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.ts
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/loader.ts
@@ -15,6 +15,7 @@ import {
IndexPatternPersistedState,
IndexPatternPrivateState,
IndexPatternField,
+ AggregationRestrictions,
} from './types';
import { updateLayerIndexPattern } from './state_helpers';
import { DateRange, ExistingFields } from '../../common/types';
@@ -30,19 +31,7 @@ interface SavedIndexPatternAttributes extends SavedObjectAttributes {
}
interface SavedRestrictionsObject {
- aggs: Record<
- string,
- Record<
- string,
- {
- agg: string;
- fixed_interval?: string;
- calendar_interval?: string;
- delay?: string;
- time_zone?: string;
- }
- >
- >;
+ aggs: Record;
}
type SetState = StateSetter;
@@ -230,7 +219,7 @@ export async function syncExistingFields({
setState,
}: {
dateRange: DateRange;
- indexPatterns: Array<{ title: string; timeFieldName?: string | null }>;
+ indexPatterns: Array<{ id: string; timeFieldName?: string | null }>;
fetchJson: HttpSetup['get'];
setState: SetState;
}) {
@@ -245,7 +234,7 @@ export async function syncExistingFields({
query.timeFieldName = pattern.timeFieldName;
}
- return fetchJson(`${BASE_API_URL}/existing_fields/${pattern.title}`, {
+ return fetchJson(`${BASE_API_URL}/existing_fields/${pattern.id}`, {
query,
}) as Promise;
})
@@ -301,8 +290,9 @@ function fromSavedObject(
newFields.forEach((field, index) => {
const restrictionsObj: IndexPatternField['aggregationRestrictions'] = {};
aggs.forEach(agg => {
- if (typeMeta.aggs[agg] && typeMeta.aggs[agg][field.name]) {
- restrictionsObj[agg] = typeMeta.aggs[agg][field.name];
+ const restriction = typeMeta.aggs[agg] && typeMeta.aggs[agg][field.name];
+ if (restriction) {
+ restrictionsObj[agg] = restriction;
}
});
if (Object.keys(restrictionsObj).length) {
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/date_histogram.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/date_histogram.tsx
index 0bb653ac1e0c21..dbb6278352f096 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/date_histogram.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/date_histogram.tsx
@@ -322,7 +322,7 @@ function parseInterval(currentInterval: string) {
};
}
-function restrictedInterval(aggregationRestrictions?: AggregationRestrictions) {
+function restrictedInterval(aggregationRestrictions?: Partial) {
if (!aggregationRestrictions || !aggregationRestrictions.date_histogram) {
return;
}
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/terms.test.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/terms.test.tsx
index a891814bb04965..d21c6c74e10508 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/terms.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/terms.test.tsx
@@ -354,7 +354,7 @@ describe('terms', () => {
expect(select.prop('value')).toEqual('alphabetical');
- expect(select.prop('options').map(({ value }) => value)).toEqual([
+ expect(select.prop('options')!.map(({ value }) => value)).toEqual([
'column$$$col2',
'alphabetical',
]);
@@ -423,7 +423,7 @@ describe('terms', () => {
.find(EuiSelect);
expect(select.prop('value')).toEqual('asc');
- expect(select.prop('options').map(({ value }) => value)).toEqual(['asc', 'desc']);
+ expect(select.prop('options')!.map(({ value }) => value)).toEqual(['asc', 'desc']);
});
it('should update state with the order direction value', () => {
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/types.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/types.ts
index 50478515d19ce2..e556ddda106796 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/types.ts
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/types.ts
@@ -20,18 +20,16 @@ export interface IndexPattern {
>;
}
-export type AggregationRestrictions = Partial<
- Record<
- string,
- {
- agg: string;
- interval?: number;
- fixed_interval?: string;
- calendar_interval?: string;
- delay?: string;
- time_zone?: string;
- }
- >
+export type AggregationRestrictions = Record<
+ string,
+ {
+ agg?: string;
+ interval?: number;
+ fixed_interval?: string;
+ calendar_interval?: string;
+ delay?: string;
+ time_zone?: string;
+ }
>;
export interface IndexPatternField {
@@ -41,7 +39,7 @@ export interface IndexPatternField {
aggregatable: boolean;
scripted?: boolean;
searchable: boolean;
- aggregationRestrictions?: AggregationRestrictions;
+ aggregationRestrictions?: Partial;
}
export interface IndexPatternLayer {
diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_config_panel.test.tsx b/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_config_panel.test.tsx
index ff2e55ac83dccd..a66239e5d30f68 100644
--- a/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_config_panel.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_config_panel.test.tsx
@@ -38,6 +38,7 @@ describe('MetricConfigPanel', () => {
const state = testState();
const component = mount(
!op.isBucketed && op.dataType === 'number';
-export function MetricConfigPanel(props: VisualizationProps) {
- const { state, frame } = props;
- const [datasource] = Object.values(frame.datasourceLayers);
- const [layerId] = Object.keys(frame.datasourceLayers);
+export function MetricConfigPanel(props: VisualizationLayerConfigProps) {
+ const { state, frame, layerId } = props;
+ const datasource = frame.datasourceLayers[layerId];
return (
-
-
-
-
-
-
-
-
-
+
+
+
);
}
diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_visualization.test.ts b/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_visualization.test.ts
index a95b5a2b276319..c131612399cca0 100644
--- a/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_visualization.test.ts
+++ b/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_visualization.test.ts
@@ -50,6 +50,22 @@ describe('metric_visualization', () => {
});
});
+ describe('#getLayerIds', () => {
+ it('returns the layer id', () => {
+ expect(metricVisualization.getLayerIds(exampleState())).toEqual(['l1']);
+ });
+ });
+
+ describe('#clearLayer', () => {
+ it('returns a clean layer', () => {
+ (generateId as jest.Mock).mockReturnValueOnce('test-id1');
+ expect(metricVisualization.clearLayer(exampleState(), 'l1')).toEqual({
+ accessor: 'test-id1',
+ layerId: 'l1',
+ });
+ });
+ });
+
describe('#getPersistableState', () => {
it('persists the state as given', () => {
expect(metricVisualization.getPersistableState(exampleState())).toEqual(exampleState());
diff --git a/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_visualization.tsx b/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_visualization.tsx
index 00e945c0ce6e5b..6714c057878373 100644
--- a/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_visualization.tsx
+++ b/x-pack/legacy/plugins/lens/public/metric_visualization_plugin/metric_visualization.tsx
@@ -54,6 +54,17 @@ export const metricVisualization: Visualization = {
},
],
+ clearLayer(state) {
+ return {
+ ...state,
+ accessor: generateId(),
+ };
+ },
+
+ getLayerIds(state) {
+ return [state.layerId];
+ },
+
getDescription() {
return {
icon: chartMetricSVG,
@@ -76,7 +87,7 @@ export const metricVisualization: Visualization = {
getPersistableState: state => state,
- renderConfigPanel: (domElement, props) =>
+ renderLayerConfigPanel: (domElement, props) =>
render(
diff --git a/x-pack/legacy/plugins/lens/public/types.ts b/x-pack/legacy/plugins/lens/public/types.ts
index f83157b2a80000..923e0aff5ae0e8 100644
--- a/x-pack/legacy/plugins/lens/public/types.ts
+++ b/x-pack/legacy/plugins/lens/public/types.ts
@@ -135,6 +135,7 @@ export interface Datasource {
insertLayer: (state: T, newLayerId: string) => T;
removeLayer: (state: T, layerId: string) => T;
+ clearLayer: (state: T, layerId: string) => T;
getLayers: (state: T) => string[];
renderDataPanel: (domElement: Element, props: DatasourceDataPanelProps) => void;
@@ -237,7 +238,8 @@ export interface LensMultiTable {
};
}
-export interface VisualizationProps {
+export interface VisualizationLayerConfigProps {
+ layerId: string;
dragDropContext: DragContextState;
frame: FramePublicAPI;
state: T;
@@ -325,6 +327,18 @@ export interface Visualization {
visualizationTypes: VisualizationType[];
+ getLayerIds: (state: T) => string[];
+
+ clearLayer: (state: T, layerId: string) => T;
+
+ removeLayer?: (state: T, layerId: string) => T;
+
+ appendLayer?: (state: T, layerId: string) => T;
+
+ getLayerContextMenuIcon?: (opts: { state: T; layerId: string }) => IconType | undefined;
+
+ renderLayerContextMenu?: (domElement: Element, props: VisualizationLayerConfigProps) => void;
+
getDescription: (
state: T
) => {
@@ -339,7 +353,7 @@ export interface Visualization {
getPersistableState: (state: T) => P;
- renderConfigPanel: (domElement: Element, props: VisualizationProps) => void;
+ renderLayerConfigPanel: (domElement: Element, props: VisualizationLayerConfigProps) => void;
toExpression: (state: T, frame: FramePublicAPI) => Ast | string | null;
diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/__snapshots__/xy_expression.test.tsx.snap b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/__snapshots__/xy_expression.test.tsx.snap
index 8df2d764c02084..76802e701b3871 100644
--- a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/__snapshots__/xy_expression.test.tsx.snap
+++ b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/__snapshots__/xy_expression.test.tsx.snap
@@ -86,18 +86,18 @@ exports[`xy_expression XYChart component it renders area 1`] = `
"top": 0,
},
"colors": Object {
- "defaultVizColor": "#3185FC",
+ "defaultVizColor": "#6092C0",
"vizColors": Array [
- "#1EA593",
- "#2B70F7",
- "#CE0060",
- "#38007E",
- "#FCA5D3",
- "#F37020",
- "#E49E29",
- "#B0916F",
- "#7B000B",
- "#34130C",
+ "#5BBAA0",
+ "#6092C0",
+ "#D36086",
+ "#9170B8",
+ "#EEAFCF",
+ "#FAE181",
+ "#CDBD9D",
+ "#F19F58",
+ "#B46F5F",
+ "#E7664C",
],
},
"crosshair": Object {
@@ -272,18 +272,18 @@ exports[`xy_expression XYChart component it renders bar 1`] = `
"top": 0,
},
"colors": Object {
- "defaultVizColor": "#3185FC",
+ "defaultVizColor": "#6092C0",
"vizColors": Array [
- "#1EA593",
- "#2B70F7",
- "#CE0060",
- "#38007E",
- "#FCA5D3",
- "#F37020",
- "#E49E29",
- "#B0916F",
- "#7B000B",
- "#34130C",
+ "#5BBAA0",
+ "#6092C0",
+ "#D36086",
+ "#9170B8",
+ "#EEAFCF",
+ "#FAE181",
+ "#CDBD9D",
+ "#F19F58",
+ "#B46F5F",
+ "#E7664C",
],
},
"crosshair": Object {
@@ -458,18 +458,18 @@ exports[`xy_expression XYChart component it renders horizontal bar 1`] = `
"top": 0,
},
"colors": Object {
- "defaultVizColor": "#3185FC",
+ "defaultVizColor": "#6092C0",
"vizColors": Array [
- "#1EA593",
- "#2B70F7",
- "#CE0060",
- "#38007E",
- "#FCA5D3",
- "#F37020",
- "#E49E29",
- "#B0916F",
- "#7B000B",
- "#34130C",
+ "#5BBAA0",
+ "#6092C0",
+ "#D36086",
+ "#9170B8",
+ "#EEAFCF",
+ "#FAE181",
+ "#CDBD9D",
+ "#F19F58",
+ "#B46F5F",
+ "#E7664C",
],
},
"crosshair": Object {
@@ -644,18 +644,18 @@ exports[`xy_expression XYChart component it renders line 1`] = `
"top": 0,
},
"colors": Object {
- "defaultVizColor": "#3185FC",
+ "defaultVizColor": "#6092C0",
"vizColors": Array [
- "#1EA593",
- "#2B70F7",
- "#CE0060",
- "#38007E",
- "#FCA5D3",
- "#F37020",
- "#E49E29",
- "#B0916F",
- "#7B000B",
- "#34130C",
+ "#5BBAA0",
+ "#6092C0",
+ "#D36086",
+ "#9170B8",
+ "#EEAFCF",
+ "#FAE181",
+ "#CDBD9D",
+ "#F19F58",
+ "#B46F5F",
+ "#E7664C",
],
},
"crosshair": Object {
@@ -830,18 +830,18 @@ exports[`xy_expression XYChart component it renders stacked area 1`] = `
"top": 0,
},
"colors": Object {
- "defaultVizColor": "#3185FC",
+ "defaultVizColor": "#6092C0",
"vizColors": Array [
- "#1EA593",
- "#2B70F7",
- "#CE0060",
- "#38007E",
- "#FCA5D3",
- "#F37020",
- "#E49E29",
- "#B0916F",
- "#7B000B",
- "#34130C",
+ "#5BBAA0",
+ "#6092C0",
+ "#D36086",
+ "#9170B8",
+ "#EEAFCF",
+ "#FAE181",
+ "#CDBD9D",
+ "#F19F58",
+ "#B46F5F",
+ "#E7664C",
],
},
"crosshair": Object {
@@ -1020,18 +1020,18 @@ exports[`xy_expression XYChart component it renders stacked bar 1`] = `
"top": 0,
},
"colors": Object {
- "defaultVizColor": "#3185FC",
+ "defaultVizColor": "#6092C0",
"vizColors": Array [
- "#1EA593",
- "#2B70F7",
- "#CE0060",
- "#38007E",
- "#FCA5D3",
- "#F37020",
- "#E49E29",
- "#B0916F",
- "#7B000B",
- "#34130C",
+ "#5BBAA0",
+ "#6092C0",
+ "#D36086",
+ "#9170B8",
+ "#EEAFCF",
+ "#FAE181",
+ "#CDBD9D",
+ "#F19F58",
+ "#B46F5F",
+ "#E7664C",
],
},
"crosshair": Object {
@@ -1210,18 +1210,18 @@ exports[`xy_expression XYChart component it renders stacked horizontal bar 1`] =
"top": 0,
},
"colors": Object {
- "defaultVizColor": "#3185FC",
+ "defaultVizColor": "#6092C0",
"vizColors": Array [
- "#1EA593",
- "#2B70F7",
- "#CE0060",
- "#38007E",
- "#FCA5D3",
- "#F37020",
- "#E49E29",
- "#B0916F",
- "#7B000B",
- "#34130C",
+ "#5BBAA0",
+ "#6092C0",
+ "#D36086",
+ "#9170B8",
+ "#EEAFCF",
+ "#FAE181",
+ "#CDBD9D",
+ "#F19F58",
+ "#B46F5F",
+ "#E7664C",
],
},
"crosshair": Object {
diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_config_panel.test.tsx b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_config_panel.test.tsx
index 5cdf1031a22b04..6ed827bc71c682 100644
--- a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_config_panel.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_config_panel.test.tsx
@@ -8,9 +8,9 @@ import React from 'react';
import { ReactWrapper } from 'enzyme';
import { mountWithIntl as mount } from 'test_utils/enzyme_helpers';
import { EuiButtonGroupProps } from '@elastic/eui';
-import { XYConfigPanel } from './xy_config_panel';
+import { XYConfigPanel, LayerContextMenu } from './xy_config_panel';
import { DatasourceDimensionPanelProps, Operation, FramePublicAPI } from '../types';
-import { State, XYState } from './types';
+import { State } from './types';
import { Position } from '@elastic/charts';
import { NativeRendererProps } from '../native_renderer';
import { generateId } from '../id_generator';
@@ -46,15 +46,6 @@ describe('XYConfigPanel', () => {
.props();
}
- function openComponentPopover(component: ReactWrapper, layerId: string) {
- component
- .find(`[data-test-subj="lnsXY_layer_${layerId}"]`)
- .first()
- .find(`[data-test-subj="lnsXY_layer_advanced"]`)
- .first()
- .simulate('click');
- }
-
beforeEach(() => {
frame = createMockFramePublicAPI();
frame.datasourceLayers = {
@@ -67,55 +58,55 @@ describe('XYConfigPanel', () => {
test.skip('allows toggling the y axis gridlines', () => {});
test.skip('allows toggling the x axis gridlines', () => {});
- test('enables stacked chart types even when there is no split series', () => {
- const state = testState();
- const component = mount(
-
- );
-
- openComponentPopover(component, 'first');
-
- const options = component
- .find('[data-test-subj="lnsXY_seriesType"]')
- .first()
- .prop('options') as EuiButtonGroupProps['options'];
+ describe('LayerContextMenu', () => {
+ test('enables stacked chart types even when there is no split series', () => {
+ const state = testState();
+ const component = mount(
+
+ );
- expect(options!.map(({ id }) => id)).toEqual([
- 'bar',
- 'bar_stacked',
- 'line',
- 'area',
- 'area_stacked',
- ]);
+ const options = component
+ .find('[data-test-subj="lnsXY_seriesType"]')
+ .first()
+ .prop('options') as EuiButtonGroupProps['options'];
- expect(options!.filter(({ isDisabled }) => isDisabled).map(({ id }) => id)).toEqual([]);
- });
+ expect(options!.map(({ id }) => id)).toEqual([
+ 'bar',
+ 'bar_stacked',
+ 'line',
+ 'area',
+ 'area_stacked',
+ ]);
- test('shows only horizontal bar options when in horizontal mode', () => {
- const state = testState();
- const component = mount(
-
- );
+ expect(options!.filter(({ isDisabled }) => isDisabled).map(({ id }) => id)).toEqual([]);
+ });
- openComponentPopover(component, 'first');
+ test('shows only horizontal bar options when in horizontal mode', () => {
+ const state = testState();
+ const component = mount(
+
+ );
- const options = component
- .find('[data-test-subj="lnsXY_seriesType"]')
- .first()
- .prop('options') as EuiButtonGroupProps['options'];
+ const options = component
+ .find('[data-test-subj="lnsXY_seriesType"]')
+ .first()
+ .prop('options') as EuiButtonGroupProps['options'];
- expect(options!.map(({ id }) => id)).toEqual(['bar_horizontal', 'bar_horizontal_stacked']);
- expect(options!.filter(({ isDisabled }) => isDisabled).map(({ id }) => id)).toEqual([]);
+ expect(options!.map(({ id }) => id)).toEqual(['bar_horizontal', 'bar_horizontal_stacked']);
+ expect(options!.filter(({ isDisabled }) => isDisabled).map(({ id }) => id)).toEqual([]);
+ });
});
test('the x dimension panel accepts only bucketed operations', () => {
@@ -123,6 +114,7 @@ describe('XYConfigPanel', () => {
const state = testState();
const component = mount(
{
const state = testState();
const component = mount(
{
const state = testState();
const component = mount(
{
/>
);
- openComponentPopover(component, 'first');
-
const onRemove = component
.find('[data-test-subj="lensXY_yDimensionPanel"]')
.first()
@@ -223,6 +215,7 @@ describe('XYConfigPanel', () => {
const state = testState();
const component = mount(
{
],
});
});
-
- describe('layers', () => {
- it('adds layers', () => {
- frame.addNewLayer = jest.fn().mockReturnValue('newLayerId');
- (generateId as jest.Mock).mockReturnValue('accessor');
- const setState = jest.fn();
- const state = testState();
- const component = mount(
-
- );
-
- component
- .find('[data-test-subj="lnsXY_layer_add"]')
- .first()
- .simulate('click');
-
- expect(frame.addNewLayer).toHaveBeenCalled();
- expect(setState).toHaveBeenCalledTimes(1);
- expect(generateId).toHaveBeenCalledTimes(4);
- expect(setState.mock.calls[0][0]).toMatchObject({
- layers: [
- ...state.layers,
- expect.objectContaining({
- layerId: 'newLayerId',
- xAccessor: 'accessor',
- accessors: ['accessor'],
- splitAccessor: 'accessor',
- }),
- ],
- });
- });
-
- it('should use series type of existing layers if they all have the same', () => {
- frame.addNewLayer = jest.fn().mockReturnValue('newLayerId');
- frame.datasourceLayers.second = createMockDatasource().publicAPIMock;
- (generateId as jest.Mock).mockReturnValue('accessor');
- const setState = jest.fn();
- const state: XYState = {
- ...testState(),
- preferredSeriesType: 'bar',
- layers: [
- {
- seriesType: 'line',
- layerId: 'first',
- splitAccessor: 'baz',
- xAccessor: 'foo',
- accessors: ['bar'],
- },
- {
- seriesType: 'line',
- layerId: 'second',
- splitAccessor: 'baz',
- xAccessor: 'foo',
- accessors: ['bar'],
- },
- ],
- };
- const component = mount(
-
- );
-
- component
- .find('[data-test-subj="lnsXY_layer_add"]')
- .first()
- .simulate('click');
-
- expect(setState.mock.calls[0][0]).toMatchObject({
- layers: [
- ...state.layers,
- expect.objectContaining({
- seriesType: 'line',
- }),
- ],
- });
- });
-
- it('should use preffered series type if there are already various different layers', () => {
- frame.addNewLayer = jest.fn().mockReturnValue('newLayerId');
- frame.datasourceLayers.second = createMockDatasource().publicAPIMock;
- (generateId as jest.Mock).mockReturnValue('accessor');
- const setState = jest.fn();
- const state: XYState = {
- ...testState(),
- preferredSeriesType: 'bar',
- layers: [
- {
- seriesType: 'area',
- layerId: 'first',
- splitAccessor: 'baz',
- xAccessor: 'foo',
- accessors: ['bar'],
- },
- {
- seriesType: 'line',
- layerId: 'second',
- splitAccessor: 'baz',
- xAccessor: 'foo',
- accessors: ['bar'],
- },
- ],
- };
- const component = mount(
-
- );
-
- component
- .find('[data-test-subj="lnsXY_layer_add"]')
- .first()
- .simulate('click');
-
- expect(setState.mock.calls[0][0]).toMatchObject({
- layers: [
- ...state.layers,
- expect.objectContaining({
- seriesType: 'bar',
- }),
- ],
- });
- });
-
- it('removes layers', () => {
- const setState = jest.fn();
- const state = testState();
- const component = mount(
-
- );
-
- openComponentPopover(component, 'first');
-
- component
- .find('[data-test-subj="lnsXY_layer_remove"]')
- .first()
- .simulate('click');
-
- expect(frame.removeLayers).toHaveBeenCalled();
- expect(setState).toHaveBeenCalledTimes(1);
- expect(setState.mock.calls[0][0]).toMatchObject({
- layers: [],
- });
- });
- });
});
diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_config_panel.tsx b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_config_panel.tsx
index f59b1520dbbb43..dbcfa243950015 100644
--- a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_config_panel.tsx
+++ b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_config_panel.tsx
@@ -5,25 +5,11 @@
*/
import _ from 'lodash';
-import React, { useState } from 'react';
+import React from 'react';
import { i18n } from '@kbn/i18n';
-import {
- EuiButton,
- EuiButtonGroup,
- EuiFlexGroup,
- EuiFlexItem,
- EuiForm,
- EuiFormRow,
- EuiPanel,
- EuiButtonIcon,
- EuiPopover,
- EuiSpacer,
- EuiButtonEmpty,
- EuiPopoverFooter,
- EuiToolTip,
-} from '@elastic/eui';
-import { State, SeriesType, LayerConfig, visualizationTypes } from './types';
-import { VisualizationProps, OperationMetadata } from '../types';
+import { EuiButtonGroup, EuiFormRow } from '@elastic/eui';
+import { State, SeriesType, visualizationTypes } from './types';
+import { VisualizationLayerConfigProps, OperationMetadata } from '../types';
import { NativeRenderer } from '../native_renderer';
import { MultiColumnEditor } from '../multi_column_editor';
import { generateId } from '../id_generator';
@@ -45,253 +31,140 @@ function updateLayer(state: State, layer: UnwrapArray, index: n
};
}
-function newLayerState(seriesType: SeriesType, layerId: string): LayerConfig {
- return {
- layerId,
- seriesType,
- xAccessor: generateId(),
- accessors: [generateId()],
- splitAccessor: generateId(),
- };
-}
+export function LayerContextMenu(props: VisualizationLayerConfigProps) {
+ const { state, layerId } = props;
+ const horizontalOnly = isHorizontalChart(state.layers);
+ const index = state.layers.findIndex(l => l.layerId === layerId);
+ const layer = state.layers[index];
-function LayerSettings({
- layer,
- horizontalOnly,
- setSeriesType,
- removeLayer,
-}: {
- layer: LayerConfig;
- horizontalOnly: boolean;
- setSeriesType: (seriesType: SeriesType) => void;
- removeLayer: () => void;
-}) {
- const [isOpen, setIsOpen] = useState(false);
- const { icon } = visualizationTypes.find(c => c.id === layer.seriesType)!;
+ if (!layer) {
+ return null;
+ }
return (
- setIsOpen(!isOpen)}
- data-test-subj="lnsXY_layer_advanced"
- />
- }
- isOpen={isOpen}
- closePopover={() => setIsOpen(false)}
- anchorPosition="leftUp"
+
-
- isHorizontalSeries(t.id as SeriesType) === horizontalOnly)
- .map(t => ({
- id: t.id,
- label: t.label,
- iconType: t.icon || 'empty',
- }))}
- idSelected={layer.seriesType}
- onChange={seriesType => {
- trackUiEvent('xy_change_layer_display');
- setSeriesType(seriesType as SeriesType);
- }}
- isIconOnly
- buttonSize="compressed"
- />
-
-
-
- {i18n.translate('xpack.lens.xyChart.deleteLayer', {
- defaultMessage: 'Delete layer',
- })}
-
-
-
+ name="chartType"
+ className="eui-displayInlineBlock"
+ data-test-subj="lnsXY_seriesType"
+ options={visualizationTypes
+ .filter(t => isHorizontalSeries(t.id as SeriesType) === horizontalOnly)
+ .map(t => ({
+ id: t.id,
+ label: t.label,
+ iconType: t.icon || 'empty',
+ }))}
+ idSelected={layer.seriesType}
+ onChange={seriesType => {
+ trackUiEvent('xy_change_layer_display');
+ props.setState(
+ updateLayer(state, { ...layer, seriesType: seriesType as SeriesType }, index)
+ );
+ }}
+ isIconOnly
+ buttonSize="compressed"
+ />
+
);
}
-export function XYConfigPanel(props: VisualizationProps) {
- const { state, setState, frame } = props;
- const horizontalOnly = isHorizontalChart(state.layers);
-
- return (
-
- {state.layers.map((layer, index) => (
-
-
-
-
- setState(updateLayer(state, { ...layer, seriesType }, index))
- }
- removeLayer={() => {
- trackUiEvent('xy_layer_removed');
- frame.removeLayers([layer.layerId]);
- setState({ ...state, layers: state.layers.filter(l => l !== layer) });
- }}
- />
-
-
-
-
-
-
+export function XYConfigPanel(props: VisualizationLayerConfigProps) {
+ const { state, setState, frame, layerId } = props;
+ const index = props.state.layers.findIndex(l => l.layerId === layerId);
-
+ if (index < 0) {
+ return null;
+ }
-
-
-
-
-
- setState(
- updateLayer(
- state,
- {
- ...layer,
- accessors: [...layer.accessors, generateId()],
- },
- index
- )
- )
- }
- onRemove={accessor =>
- setState(
- updateLayer(
- state,
- {
- ...layer,
- accessors: layer.accessors.filter(col => col !== accessor),
- },
- index
- )
- )
- }
- filterOperations={isNumericMetric}
- data-test-subj="lensXY_yDimensionPanel"
- testSubj="lensXY_yDimensionPanel"
- layerId={layer.layerId}
- />
-
-
-
-
-
- ))}
+ const layer = props.state.layers[index];
-
-
- {
- trackUiEvent('xy_layer_added');
- const usedSeriesTypes = _.uniq(state.layers.map(layer => layer.seriesType));
- setState({
- ...state,
- layers: [
- ...state.layers,
- newLayerState(
- usedSeriesTypes.length === 1 ? usedSeriesTypes[0] : state.preferredSeriesType,
- frame.addNewLayer()
- ),
- ],
- });
- }}
- iconType="plusInCircleFilled"
- />
-
-
-
+ return (
+ <>
+
+
+
+
+
+ setState(
+ updateLayer(
+ state,
+ {
+ ...layer,
+ accessors: [...layer.accessors, generateId()],
+ },
+ index
+ )
+ )
+ }
+ onRemove={accessor =>
+ setState(
+ updateLayer(
+ state,
+ {
+ ...layer,
+ accessors: layer.accessors.filter(col => col !== accessor),
+ },
+ index
+ )
+ )
+ }
+ filterOperations={isNumericMetric}
+ data-test-subj="lensXY_yDimensionPanel"
+ testSubj="lensXY_yDimensionPanel"
+ layerId={layer.layerId}
+ />
+
+
+
+
+ >
);
}
diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_visualization.test.ts b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_visualization.test.ts
index db28e76f829464..89794ec74eaec3 100644
--- a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_visualization.test.ts
+++ b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_visualization.test.ts
@@ -137,6 +137,54 @@ describe('xy_visualization', () => {
});
});
+ describe('#removeLayer', () => {
+ it('removes the specified layer', () => {
+ const prevState: State = {
+ ...exampleState(),
+ layers: [
+ ...exampleState().layers,
+ {
+ layerId: 'second',
+ seriesType: 'area',
+ splitAccessor: 'e',
+ xAccessor: 'f',
+ accessors: ['g', 'h'],
+ },
+ ],
+ };
+
+ expect(xyVisualization.removeLayer!(prevState, 'second')).toEqual(exampleState());
+ });
+ });
+
+ describe('#appendLayer', () => {
+ it('adds a layer', () => {
+ const layers = xyVisualization.appendLayer!(exampleState(), 'foo').layers;
+ expect(layers.length).toEqual(exampleState().layers.length + 1);
+ expect(layers[layers.length - 1]).toMatchObject({ layerId: 'foo' });
+ });
+ });
+
+ describe('#clearLayer', () => {
+ it('clears the specified layer', () => {
+ (generateId as jest.Mock).mockReturnValue('test_empty_id');
+ const layer = xyVisualization.clearLayer(exampleState(), 'first').layers[0];
+ expect(layer).toMatchObject({
+ accessors: ['test_empty_id'],
+ layerId: 'first',
+ seriesType: 'bar',
+ splitAccessor: 'test_empty_id',
+ xAccessor: 'test_empty_id',
+ });
+ });
+ });
+
+ describe('#getLayerIds', () => {
+ it('returns layerids', () => {
+ expect(xyVisualization.getLayerIds(exampleState())).toEqual(['first']);
+ });
+ });
+
describe('#toExpression', () => {
let mockDatasource: ReturnType;
let frame: ReturnType;
diff --git a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_visualization.tsx b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_visualization.tsx
index 5ba77cb39d5f81..75d6fcc7d160bf 100644
--- a/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_visualization.tsx
+++ b/x-pack/legacy/plugins/lens/public/xy_visualization_plugin/xy_visualization.tsx
@@ -11,9 +11,9 @@ import { Position } from '@elastic/charts';
import { I18nProvider } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import { getSuggestions } from './xy_suggestions';
-import { XYConfigPanel } from './xy_config_panel';
+import { XYConfigPanel, LayerContextMenu } from './xy_config_panel';
import { Visualization } from '../types';
-import { State, PersistableState, SeriesType, visualizationTypes } from './types';
+import { State, PersistableState, SeriesType, visualizationTypes, LayerConfig } from './types';
import { toExpression, toPreviewExpression } from './to_expression';
import { generateId } from '../id_generator';
import chartBarStackedSVG from '../assets/chart_bar_stacked.svg';
@@ -67,6 +67,40 @@ export const xyVisualization: Visualization = {
visualizationTypes,
+ getLayerIds(state) {
+ return state.layers.map(l => l.layerId);
+ },
+
+ removeLayer(state, layerId) {
+ return {
+ ...state,
+ layers: state.layers.filter(l => l.layerId !== layerId),
+ };
+ },
+
+ appendLayer(state, layerId) {
+ const usedSeriesTypes = _.uniq(state.layers.map(layer => layer.seriesType));
+ return {
+ ...state,
+ layers: [
+ ...state.layers,
+ newLayerState(
+ usedSeriesTypes.length === 1 ? usedSeriesTypes[0] : state.preferredSeriesType,
+ layerId
+ ),
+ ],
+ };
+ },
+
+ clearLayer(state, layerId) {
+ return {
+ ...state,
+ layers: state.layers.map(l =>
+ l.layerId !== layerId ? l : newLayerState(state.preferredSeriesType, layerId)
+ ),
+ };
+ },
+
getDescription(state) {
const { icon, label } = getDescription(state);
const chartLabel = i18n.translate('xpack.lens.xyVisualization.chartLabel', {
@@ -113,7 +147,7 @@ export const xyVisualization: Visualization = {
getPersistableState: state => state,
- renderConfigPanel: (domElement, props) =>
+ renderLayerConfigPanel: (domElement, props) =>
render(
@@ -121,6 +155,30 @@ export const xyVisualization: Visualization = {
domElement
),
+ getLayerContextMenuIcon({ state, layerId }) {
+ const layer = state.layers.find(l => l.layerId === layerId);
+ return visualizationTypes.find(t => t.id === layer?.seriesType)?.icon;
+ },
+
+ renderLayerContextMenu(domElement, props) {
+ render(
+
+
+ ,
+ domElement
+ );
+ },
+
toExpression,
toPreviewExpression,
};
+
+function newLayerState(seriesType: SeriesType, layerId: string): LayerConfig {
+ return {
+ layerId,
+ seriesType,
+ xAccessor: generateId(),
+ accessors: [generateId()],
+ splitAccessor: generateId(),
+ };
+}
diff --git a/x-pack/legacy/plugins/lens/server/routes/existing_fields.test.ts b/x-pack/legacy/plugins/lens/server/routes/existing_fields.test.ts
index 1647dcccaed3c6..1f19671826807a 100644
--- a/x-pack/legacy/plugins/lens/server/routes/existing_fields.test.ts
+++ b/x-pack/legacy/plugins/lens/server/routes/existing_fields.test.ts
@@ -4,24 +4,29 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { existingFields } from './existing_fields';
+import { existingFields, Field, buildFieldList } from './existing_fields';
describe('existingFields', () => {
- function field(name: string, parent?: string) {
+ function field(opts: string | Partial): Field {
+ const obj = typeof opts === 'object' ? opts : {};
+ const name = (typeof opts === 'string' ? opts : opts.name) || 'test';
+
return {
name,
- subType: parent ? { multi: { parent } } : undefined,
- aggregatable: true,
- esTypes: [],
- readFromDocValues: true,
- searchable: true,
- type: 'string',
+ isScript: false,
+ isAlias: false,
+ path: name.split('.'),
+ ...obj,
};
}
+ function indexPattern(_source: unknown, fields: unknown = {}) {
+ return { _source, fields };
+ }
+
it('should handle root level fields', () => {
const result = existingFields(
- [{ _source: { foo: 'bar' } }, { _source: { baz: 0 } }],
+ [indexPattern({ foo: 'bar' }), indexPattern({ baz: 0 })],
[field('foo'), field('bar'), field('baz')]
);
@@ -30,7 +35,7 @@ describe('existingFields', () => {
it('should handle arrays of objects', () => {
const result = existingFields(
- [{ _source: { stuff: [{ foo: 'bar' }, { baz: 0 }] } }],
+ [indexPattern({ stuff: [{ foo: 'bar' }, { baz: 0 }] })],
[field('stuff.foo'), field('stuff.bar'), field('stuff.baz')]
);
@@ -38,14 +43,14 @@ describe('existingFields', () => {
});
it('should handle basic arrays', () => {
- const result = existingFields([{ _source: { stuff: ['heyo', 'there'] } }], [field('stuff')]);
+ const result = existingFields([indexPattern({ stuff: ['heyo', 'there'] })], [field('stuff')]);
expect(result).toEqual(['stuff']);
});
it('should handle deep object structures', () => {
const result = existingFields(
- [{ _source: { geo: { coordinates: { lat: 40, lon: -77 } } } }],
+ [indexPattern({ geo: { coordinates: { lat: 40, lon: -77 } } })],
[field('geo.coordinates')]
);
@@ -54,19 +59,97 @@ describe('existingFields', () => {
it('should be false if it hits a positive leaf before the end of the path', () => {
const result = existingFields(
- [{ _source: { geo: { coordinates: 32 } } }],
+ [indexPattern({ geo: { coordinates: 32 } })],
[field('geo.coordinates.lat')]
);
expect(result).toEqual([]);
});
- it('should prefer parent to name', () => {
+ it('should use path, not name', () => {
const result = existingFields(
- [{ _source: { stuff: [{ foo: 'bar' }, { baz: 0 }] } }],
- [field('goober', 'stuff.foo'), field('soup', 'stuff.bar'), field('pea', 'stuff.baz')]
+ [indexPattern({ stuff: [{ foo: 'bar' }, { baz: 0 }] })],
+ [field({ name: 'goober', path: ['stuff', 'foo'] })]
);
- expect(result).toEqual(['goober', 'pea']);
+ expect(result).toEqual(['goober']);
+ });
+
+ it('supports scripted fields', () => {
+ const result = existingFields(
+ [indexPattern({}, { bar: 'scriptvalue' })],
+ [field({ name: 'baz', isScript: true, path: ['bar'] })]
+ );
+
+ expect(result).toEqual(['baz']);
+ });
+});
+
+describe('buildFieldList', () => {
+ const indexPattern = {
+ id: '',
+ type: 'indexpattern',
+ attributes: {
+ title: 'testpattern',
+ fields: JSON.stringify([
+ { name: 'foo', scripted: true, lang: 'painless', script: '2+2' },
+ { name: 'bar' },
+ { name: '@bar' },
+ { name: 'baz' },
+ ]),
+ },
+ references: [],
+ };
+
+ const mappings = {
+ testpattern: {
+ mappings: {
+ properties: {
+ '@bar': {
+ type: 'alias',
+ path: 'bar',
+ },
+ },
+ },
+ },
+ };
+
+ const fieldDescriptors = [
+ {
+ name: 'baz',
+ subType: { multi: { parent: 'a.b.c' } },
+ },
+ ];
+
+ it('uses field descriptors to determine the path', () => {
+ const fields = buildFieldList(indexPattern, mappings, fieldDescriptors);
+ expect(fields.find(f => f.name === 'baz')).toMatchObject({
+ isAlias: false,
+ isScript: false,
+ name: 'baz',
+ path: ['a', 'b', 'c'],
+ });
+ });
+
+ it('uses aliases to determine the path', () => {
+ const fields = buildFieldList(indexPattern, mappings, fieldDescriptors);
+ expect(fields.find(f => f.isAlias)).toMatchObject({
+ isAlias: true,
+ isScript: false,
+ name: '@bar',
+ path: ['bar'],
+ });
+ });
+
+ it('supports scripted fields', () => {
+ const fields = buildFieldList(indexPattern, mappings, fieldDescriptors);
+ expect(fields.find(f => f.isScript)).toMatchObject({
+ isAlias: false,
+ isScript: true,
+ name: 'foo',
+ path: ['foo'],
+ lang: 'painless',
+ script: '2+2',
+ });
});
});
diff --git a/x-pack/legacy/plugins/lens/server/routes/existing_fields.ts b/x-pack/legacy/plugins/lens/server/routes/existing_fields.ts
index ad1af966983fb3..55f8fd3b1a72bf 100644
--- a/x-pack/legacy/plugins/lens/server/routes/existing_fields.ts
+++ b/x-pack/legacy/plugins/lens/server/routes/existing_fields.ts
@@ -6,28 +6,50 @@
import Boom from 'boom';
import { schema } from '@kbn/config-schema';
-import { SearchResponse } from 'elasticsearch';
import _ from 'lodash';
-import { IScopedClusterClient } from 'src/core/server';
+import { IScopedClusterClient, SavedObject, RequestHandlerContext } from 'src/core/server';
import { CoreSetup } from 'src/core/server';
import { BASE_API_URL } from '../../common';
-import { FieldDescriptor, IndexPatternsFetcher } from '../../../../../../src/plugins/data/server';
+import { IndexPatternsFetcher } from '../../../../../../src/plugins/data/server';
/**
* The number of docs to sample to determine field empty status.
*/
const SAMPLE_SIZE = 500;
-type Document = Record;
+interface MappingResult {
+ [indexPatternTitle: string]: {
+ mappings: {
+ properties: Record;
+ };
+ };
+}
+
+interface FieldDescriptor {
+ name: string;
+ subType?: { multi?: { parent?: string } };
+}
+
+export interface Field {
+ name: string;
+ isScript: boolean;
+ isAlias: boolean;
+ path: string[];
+ lang?: string;
+ script?: string;
+}
+
+// TODO: Pull this from kibana advanced settings
+const metaFields = ['_source', '_id', '_type', '_index', '_score'];
export async function existingFieldsRoute(setup: CoreSetup) {
const router = setup.http.createRouter();
router.get(
{
- path: `${BASE_API_URL}/existing_fields/{indexPatternTitle}`,
+ path: `${BASE_API_URL}/existing_fields/{indexPatternId}`,
validate: {
params: schema.object({
- indexPatternTitle: schema.string(),
+ indexPatternId: schema.string(),
}),
query: schema.object({
fromDate: schema.maybe(schema.string()),
@@ -37,31 +59,13 @@ export async function existingFieldsRoute(setup: CoreSetup) {
},
},
async (context, req, res) => {
- const { indexPatternTitle } = req.params;
- const requestClient = context.core.elasticsearch.dataClient;
- const indexPatternsFetcher = new IndexPatternsFetcher(requestClient.callAsCurrentUser);
- const { fromDate, toDate, timeFieldName } = req.query;
-
try {
- const fields = await indexPatternsFetcher.getFieldsForWildcard({
- pattern: indexPatternTitle,
- // TODO: Pull this from kibana advanced settings
- metaFields: ['_source', '_id', '_type', '_index', '_score'],
- });
-
- const results = await fetchIndexPatternStats({
- fromDate,
- toDate,
- client: requestClient,
- index: indexPatternTitle,
- timeFieldName,
- });
-
return res.ok({
- body: {
- indexPatternTitle,
- existingFieldNames: existingFields(results.hits.hits, fields),
- },
+ body: await fetchFieldExistence({
+ ...req.query,
+ ...req.params,
+ context,
+ }),
});
} catch (e) {
if (e.status === 404) {
@@ -82,6 +86,166 @@ export async function existingFieldsRoute(setup: CoreSetup) {
);
}
+async function fetchFieldExistence({
+ context,
+ indexPatternId,
+ fromDate,
+ toDate,
+ timeFieldName,
+}: {
+ indexPatternId: string;
+ context: RequestHandlerContext;
+ fromDate?: string;
+ toDate?: string;
+ timeFieldName?: string;
+}) {
+ const {
+ indexPattern,
+ indexPatternTitle,
+ mappings,
+ fieldDescriptors,
+ } = await fetchIndexPatternDefinition(indexPatternId, context);
+
+ const fields = buildFieldList(indexPattern, mappings, fieldDescriptors);
+
+ const docs = await fetchIndexPatternStats({
+ fromDate,
+ toDate,
+ client: context.core.elasticsearch.dataClient,
+ index: indexPatternTitle,
+ timeFieldName: timeFieldName || indexPattern.attributes.timeFieldName,
+ fields,
+ });
+
+ return {
+ indexPatternTitle,
+ existingFieldNames: existingFields(docs, fields),
+ };
+}
+
+async function fetchIndexPatternDefinition(indexPatternId: string, context: RequestHandlerContext) {
+ const savedObjectsClient = context.core.savedObjects.client;
+ const requestClient = context.core.elasticsearch.dataClient;
+ const indexPattern = await savedObjectsClient.get('index-pattern', indexPatternId);
+ const indexPatternTitle = indexPattern.attributes.title;
+ // TODO: maybe don't use IndexPatternsFetcher at all, since we're only using it
+ // to look up field values in the resulting documents. We can accomplish the same
+ // using the mappings which we're also fetching here.
+ const indexPatternsFetcher = new IndexPatternsFetcher(requestClient.callAsCurrentUser);
+ const [mappings, fieldDescriptors] = await Promise.all([
+ requestClient.callAsCurrentUser('indices.getMapping', {
+ index: indexPatternTitle,
+ }),
+
+ indexPatternsFetcher.getFieldsForWildcard({
+ pattern: indexPatternTitle,
+ // TODO: Pull this from kibana advanced settings
+ metaFields,
+ }),
+ ]);
+
+ return {
+ indexPattern,
+ indexPatternTitle,
+ mappings,
+ fieldDescriptors,
+ };
+}
+
+/**
+ * Exported only for unit tests.
+ */
+export function buildFieldList(
+ indexPattern: SavedObject,
+ mappings: MappingResult,
+ fieldDescriptors: FieldDescriptor[]
+): Field[] {
+ const aliasMap = Object.entries(Object.values(mappings)[0].mappings.properties)
+ .map(([name, v]) => ({ ...v, name }))
+ .filter(f => f.type === 'alias')
+ .reduce((acc, f) => {
+ acc[f.name] = f.path;
+ return acc;
+ }, {} as Record);
+
+ const descriptorMap = fieldDescriptors.reduce((acc, f) => {
+ acc[f.name] = f;
+ return acc;
+ }, {} as Record);
+
+ return JSON.parse(indexPattern.attributes.fields).map(
+ (field: { name: string; lang: string; scripted?: boolean; script?: string }) => {
+ const path =
+ aliasMap[field.name] || descriptorMap[field.name]?.subType?.multi?.parent || field.name;
+ return {
+ name: field.name,
+ isScript: !!field.scripted,
+ isAlias: !!aliasMap[field.name],
+ path: path.split('.'),
+ lang: field.lang,
+ script: field.script,
+ };
+ }
+ );
+}
+
+async function fetchIndexPatternStats({
+ client,
+ index,
+ timeFieldName,
+ fromDate,
+ toDate,
+ fields,
+}: {
+ client: IScopedClusterClient;
+ index: string;
+ timeFieldName?: string;
+ fromDate?: string;
+ toDate?: string;
+ fields: Field[];
+}) {
+ if (!timeFieldName || !fromDate || !toDate) {
+ return [];
+ }
+ const viableFields = fields.filter(
+ f => !f.isScript && !f.isAlias && !metaFields.includes(f.name)
+ );
+ const scriptedFields = fields.filter(f => f.isScript);
+
+ const result = await client.callAsCurrentUser('search', {
+ index,
+ body: {
+ size: SAMPLE_SIZE,
+ _source: viableFields.map(f => f.name),
+ query: {
+ bool: {
+ filter: [
+ {
+ range: {
+ [timeFieldName]: {
+ gte: fromDate,
+ lte: toDate,
+ },
+ },
+ },
+ ],
+ },
+ },
+ script_fields: scriptedFields.reduce((acc, field) => {
+ acc[field.name] = {
+ script: {
+ lang: field.lang,
+ source: field.script,
+ },
+ };
+ return acc;
+ }, {} as Record),
+ },
+ });
+
+ return result.hits.hits;
+}
+
function exists(obj: unknown, path: string[], i = 0): boolean {
if (obj == null) {
return false;
@@ -103,21 +267,13 @@ function exists(obj: unknown, path: string[], i = 0): boolean {
}
/**
- * Exported for testing purposes only.
+ * Exported only for unit tests.
*/
export function existingFields(
- docs: Array<{ _source: Document }>,
- fields: FieldDescriptor[]
+ docs: Array<{ _source: unknown; fields: unknown }>,
+ fields: Field[]
): string[] {
- const allFields = fields.map(field => {
- const parent = field.subType && field.subType.multi && field.subType.multi.parent;
- return {
- name: field.name,
- parent,
- path: (parent || field.name).split('.'),
- };
- });
- const missingFields = new Set(allFields);
+ const missingFields = new Set(fields);
for (const doc of docs) {
if (missingFields.size === 0) {
@@ -125,53 +281,11 @@ export function existingFields(
}
missingFields.forEach(field => {
- if (exists(doc._source, field.path)) {
+ if (exists(field.isScript ? doc.fields : doc._source, field.path)) {
missingFields.delete(field);
}
});
}
- return allFields.filter(field => !missingFields.has(field)).map(f => f.name);
-}
-
-async function fetchIndexPatternStats({
- client,
- fromDate,
- index,
- toDate,
- timeFieldName,
-}: {
- client: IScopedClusterClient;
- fromDate?: string;
- index: string;
- toDate?: string;
- timeFieldName?: string;
-}) {
- const body =
- !timeFieldName || !fromDate || !toDate
- ? {}
- : {
- query: {
- bool: {
- filter: [
- {
- range: {
- [timeFieldName]: {
- gte: fromDate,
- lte: toDate,
- },
- },
- },
- ],
- },
- },
- };
-
- return (await client.callAsCurrentUser('search', {
- index,
- body: {
- ...body,
- size: SAMPLE_SIZE,
- },
- })) as SearchResponse;
+ return fields.filter(field => !missingFields.has(field)).map(f => f.name);
}
diff --git a/x-pack/legacy/plugins/logstash/public/components/pipeline_editor/__snapshots__/pipeline_editor.test.js.snap b/x-pack/legacy/plugins/logstash/public/components/pipeline_editor/__snapshots__/pipeline_editor.test.js.snap
index dc51c066a8cb9b..74f109df382cd2 100644
--- a/x-pack/legacy/plugins/logstash/public/components/pipeline_editor/__snapshots__/pipeline_editor.test.js.snap
+++ b/x-pack/legacy/plugins/logstash/public/components/pipeline_editor/__snapshots__/pipeline_editor.test.js.snap
@@ -48,11 +48,9 @@ exports[`PipelineEditor component includes required error message for falsy pipe
labelType="label"
>
`;
diff --git a/x-pack/legacy/plugins/maps/public/components/__snapshots__/geometry_filter_form.test.js.snap b/x-pack/legacy/plugins/maps/public/components/__snapshots__/geometry_filter_form.test.js.snap
index 98e6fa0517f580..2dc355513ece24 100644
--- a/x-pack/legacy/plugins/maps/public/components/__snapshots__/geometry_filter_form.test.js.snap
+++ b/x-pack/legacy/plugins/maps/public/components/__snapshots__/geometry_filter_form.test.js.snap
@@ -13,8 +13,6 @@ exports[`should not render relation select when geo field is geo_point 1`] = `
>
@@ -92,8 +90,6 @@ exports[`should not show "within" relation when filter geometry is not closed 1`
>
@@ -151,9 +147,6 @@ exports[`should not show "within" relation when filter geometry is not closed 1`
>
@@ -283,8 +274,6 @@ exports[`should render relation select when geo field is geo_shape 1`] = `
>
@@ -342,9 +331,6 @@ exports[`should render relation select when geo field is geo_shape 1`] = `
>
tinycolor(color)
diff --git a/x-pack/legacy/plugins/maps/server/sample_data/ecommerce_saved_objects.js b/x-pack/legacy/plugins/maps/server/sample_data/ecommerce_saved_objects.js
index d5bcfa7cd1512c..a3dbf8b1438fa9 100644
--- a/x-pack/legacy/plugins/maps/server/sample_data/ecommerce_saved_objects.js
+++ b/x-pack/legacy/plugins/maps/server/sample_data/ecommerce_saved_objects.js
@@ -39,7 +39,6 @@ const layerList = [
type: 'DYNAMIC',
options: {
field: {
- label: 'count of kibana_sample_data_ecommerce:geoip.country_iso_code',
name: '__kbnjoin__count_groupby_kibana_sample_data_ecommerce.geoip.country_iso_code',
origin: 'join',
},
@@ -104,7 +103,6 @@ const layerList = [
type: 'DYNAMIC',
options: {
field: {
- label: 'count of kibana_sample_data_ecommerce:geoip.region_name',
name: '__kbnjoin__count_groupby_kibana_sample_data_ecommerce.geoip.region_name',
origin: 'join',
},
@@ -169,7 +167,6 @@ const layerList = [
type: 'DYNAMIC',
options: {
field: {
- label: 'count of kibana_sample_data_ecommerce:geoip.region_name',
name: '__kbnjoin__count_groupby_kibana_sample_data_ecommerce.geoip.region_name',
origin: 'join',
},
@@ -234,7 +231,6 @@ const layerList = [
type: 'DYNAMIC',
options: {
field: {
- label: 'count of kibana_sample_data_ecommerce:geoip.region_name',
name: '__kbnjoin__count_groupby_kibana_sample_data_ecommerce.geoip.region_name',
origin: 'join',
},
@@ -314,7 +310,6 @@ const layerList = [
type: 'DYNAMIC',
options: {
field: {
- label: 'taxful_total_price',
name: 'taxful_total_price',
origin: 'source',
},
@@ -376,7 +371,6 @@ const layerList = [
type: 'DYNAMIC',
options: {
field: {
- label: 'Count',
name: 'doc_count',
origin: 'source',
},
@@ -399,7 +393,6 @@ const layerList = [
type: 'DYNAMIC',
options: {
field: {
- label: 'sum of taxful_total_price',
name: 'sum_of_taxful_total_price',
origin: 'source',
},
@@ -407,6 +400,31 @@ const layerList = [
maxSize: 20,
},
},
+ labelText: {
+ type: 'DYNAMIC',
+ options: {
+ field: {
+ name: 'sum_of_taxful_total_price',
+ origin: 'source',
+ },
+ },
+ },
+ labelSize: {
+ type: 'DYNAMIC',
+ options: {
+ field: {
+ name: 'sum_of_taxful_total_price',
+ origin: 'source',
+ },
+ minSize: 12,
+ maxSize: 24,
+ },
+ },
+ labelBorderSize: {
+ options: {
+ size: 'MEDIUM',
+ },
+ },
},
},
type: 'VECTOR',
diff --git a/x-pack/legacy/plugins/maps/server/sample_data/flights_saved_objects.js b/x-pack/legacy/plugins/maps/server/sample_data/flights_saved_objects.js
index aa3d5488764ad2..cff4ad8182a9d1 100644
--- a/x-pack/legacy/plugins/maps/server/sample_data/flights_saved_objects.js
+++ b/x-pack/legacy/plugins/maps/server/sample_data/flights_saved_objects.js
@@ -54,7 +54,6 @@ const layerList = [
type: 'DYNAMIC',
options: {
field: {
- label: 'FlightTimeMin',
name: 'FlightTimeMin',
origin: 'source',
},
@@ -77,7 +76,6 @@ const layerList = [
type: 'DYNAMIC',
options: {
field: {
- label: 'DistanceMiles',
name: 'DistanceMiles',
origin: 'source',
},
@@ -122,7 +120,6 @@ const layerList = [
type: 'DYNAMIC',
options: {
field: {
- label: 'Count',
name: 'doc_count',
origin: 'source',
},
@@ -145,7 +142,6 @@ const layerList = [
type: 'DYNAMIC',
options: {
field: {
- label: 'avg of FlightTimeMin',
name: 'avg_of_FlightTimeMin',
origin: 'source',
},
@@ -190,7 +186,6 @@ const layerList = [
type: 'DYNAMIC',
options: {
field: {
- label: 'Count',
name: 'doc_count',
origin: 'source',
},
@@ -213,7 +208,6 @@ const layerList = [
type: 'DYNAMIC',
options: {
field: {
- label: 'avg of FlightDelayMin',
name: 'avg_of_FlightDelayMin',
origin: 'source',
},
diff --git a/x-pack/legacy/plugins/maps/server/sample_data/web_logs_saved_objects.js b/x-pack/legacy/plugins/maps/server/sample_data/web_logs_saved_objects.js
index 74039b11db727d..ec445567de21c6 100644
--- a/x-pack/legacy/plugins/maps/server/sample_data/web_logs_saved_objects.js
+++ b/x-pack/legacy/plugins/maps/server/sample_data/web_logs_saved_objects.js
@@ -39,7 +39,6 @@ const layerList = [
type: 'DYNAMIC',
options: {
field: {
- label: 'count of kibana_sample_data_logs:geo.src',
name: '__kbnjoin__count_groupby_kibana_sample_data_logs.geo.src',
origin: 'join',
},
@@ -135,7 +134,6 @@ const layerList = [
type: 'DYNAMIC',
options: {
field: {
- label: 'bytes',
name: 'bytes',
origin: 'source',
},
@@ -179,7 +177,6 @@ const layerList = [
type: 'DYNAMIC',
options: {
field: {
- label: 'Count',
name: 'doc_count',
origin: 'source',
},
@@ -202,14 +199,33 @@ const layerList = [
type: 'DYNAMIC',
options: {
field: {
- label: 'sum of bytes',
name: 'sum_of_bytes',
origin: 'source',
},
- minSize: 1,
+ minSize: 7,
maxSize: 25,
},
},
+ labelText: {
+ type: 'DYNAMIC',
+ options: {
+ field: {
+ name: 'doc_count',
+ origin: 'source',
+ },
+ },
+ },
+ labelSize: {
+ type: 'DYNAMIC',
+ options: {
+ field: {
+ name: 'doc_count',
+ origin: 'source',
+ },
+ minSize: 12,
+ maxSize: 24,
+ },
+ },
},
},
type: 'VECTOR',
diff --git a/x-pack/legacy/plugins/ml/common/constants/new_job.ts b/x-pack/legacy/plugins/ml/common/constants/new_job.ts
index ccd108cd2698f4..3c98b372afdf73 100644
--- a/x-pack/legacy/plugins/ml/common/constants/new_job.ts
+++ b/x-pack/legacy/plugins/ml/common/constants/new_job.ts
@@ -27,6 +27,6 @@ export const DEFAULT_QUERY_DELAY = '60s';
export const SHARED_RESULTS_INDEX_NAME = 'shared';
export const NUMBER_OF_CATEGORY_EXAMPLES = 5;
-export const CATEGORY_EXAMPLES_MULTIPLIER = 20;
+export const CATEGORY_EXAMPLES_SAMPLE_SIZE = 1000;
export const CATEGORY_EXAMPLES_WARNING_LIMIT = 0.75;
-export const CATEGORY_EXAMPLES_ERROR_LIMIT = 0.2;
+export const CATEGORY_EXAMPLES_ERROR_LIMIT = 0.02;
diff --git a/x-pack/legacy/plugins/ml/common/types/fields.ts b/x-pack/legacy/plugins/ml/common/types/fields.ts
index 9e1b992eec9075..4860ab955d0668 100644
--- a/x-pack/legacy/plugins/ml/common/types/fields.ts
+++ b/x-pack/legacy/plugins/ml/common/types/fields.ts
@@ -23,7 +23,7 @@ export interface Field {
id: FieldId;
name: string;
type: ES_FIELD_TYPES;
- aggregatable: boolean;
+ aggregatable?: boolean;
aggIds?: AggId[];
aggs?: Aggregation[];
}
diff --git a/x-pack/legacy/plugins/ml/public/application/components/annotations/annotations_table/__snapshots__/annotations_table.test.js.snap b/x-pack/legacy/plugins/ml/public/application/components/annotations/annotations_table/__snapshots__/annotations_table.test.js.snap
index 1d95c217e10f78..48cf53cf1ac016 100644
--- a/x-pack/legacy/plugins/ml/public/application/components/annotations/annotations_table/__snapshots__/annotations_table.test.js.snap
+++ b/x-pack/legacy/plugins/ml/public/application/components/annotations/annotations_table/__snapshots__/annotations_table.test.js.snap
@@ -89,6 +89,7 @@ exports[`AnnotationsTable Initialization with annotations prop. 1`] = `
},
}
}
+ tableLayout="fixed"
/>
`;
diff --git a/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table.js b/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table.js
index bc3ce88921110a..6728f019a6bd57 100644
--- a/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table.js
+++ b/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table.js
@@ -195,6 +195,7 @@ class AnomaliesTable extends Component {
return {
onMouseOver: () => this.onMouseOverRow(item),
onMouseLeave: () => this.onMouseLeaveRow(),
+ 'data-test-subj': `mlAnomaliesListRow row-${item.rowId}`,
};
};
diff --git a/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table_columns.js b/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table_columns.js
index 36faac45164f47..5454911673fe26 100644
--- a/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table_columns.js
+++ b/x-pack/legacy/plugins/ml/public/application/components/anomalies_table/anomalies_table_columns.js
@@ -80,11 +80,13 @@ export function getColumns(
})
}
data-row-id={item.rowId}
+ data-test-subj="mlJobListRowDetailsToggle"
/>
),
},
{
field: 'time',
+ 'data-test-subj': 'mlAnomaliesListColumnTime',
name: i18n.translate('xpack.ml.anomaliesTable.timeColumnName', {
defaultMessage: 'time',
}),
@@ -95,6 +97,7 @@ export function getColumns(
},
{
field: 'severity',
+ 'data-test-subj': 'mlAnomaliesListColumnSeverity',
name: i18n.translate('xpack.ml.anomaliesTable.severityColumnName', {
defaultMessage: 'severity',
}),
@@ -105,6 +108,7 @@ export function getColumns(
},
{
field: 'detector',
+ 'data-test-subj': 'mlAnomaliesListColumnDetector',
name: i18n.translate('xpack.ml.anomaliesTable.detectorColumnName', {
defaultMessage: 'detector',
}),
@@ -119,6 +123,7 @@ export function getColumns(
if (items.some(item => item.entityValue !== undefined)) {
columns.push({
field: 'entityValue',
+ 'data-test-subj': 'mlAnomaliesListColumnFoundFor',
name: i18n.translate('xpack.ml.anomaliesTable.entityValueColumnName', {
defaultMessage: 'found for',
}),
@@ -138,6 +143,7 @@ export function getColumns(
if (items.some(item => item.influencers !== undefined)) {
columns.push({
field: 'influencers',
+ 'data-test-subj': 'mlAnomaliesListColumnInfluencers',
name: i18n.translate('xpack.ml.anomaliesTable.influencersColumnName', {
defaultMessage: 'influenced by',
}),
@@ -159,6 +165,7 @@ export function getColumns(
if (items.some(item => item.actual !== undefined)) {
columns.push({
field: 'actualSort',
+ 'data-test-subj': 'mlAnomaliesListColumnActual',
name: i18n.translate('xpack.ml.anomaliesTable.actualSortColumnName', {
defaultMessage: 'actual',
}),
@@ -176,6 +183,7 @@ export function getColumns(
if (items.some(item => item.typical !== undefined)) {
columns.push({
field: 'typicalSort',
+ 'data-test-subj': 'mlAnomaliesListColumnTypical',
name: i18n.translate('xpack.ml.anomaliesTable.typicalSortColumnName', {
defaultMessage: 'typical',
}),
@@ -198,6 +206,7 @@ export function getColumns(
if (nonTimeOfDayOrWeek === true) {
columns.push({
field: 'metricDescriptionSort',
+ 'data-test-subj': 'mlAnomaliesListColumnDescription',
name: i18n.translate('xpack.ml.anomaliesTable.metricDescriptionSortColumnName', {
defaultMessage: 'description',
}),
@@ -213,6 +222,7 @@ export function getColumns(
if (jobIds && jobIds.length > 1) {
columns.push({
field: 'jobId',
+ 'data-test-subj': 'mlAnomaliesListColumnJobID',
name: i18n.translate('xpack.ml.anomaliesTable.jobIdColumnName', {
defaultMessage: 'job ID',
}),
@@ -223,6 +233,7 @@ export function getColumns(
const showExamples = items.some(item => item.entityName === 'mlcategory');
if (showExamples === true) {
columns.push({
+ 'data-test-subj': 'mlAnomaliesListColumnCategoryExamples',
name: i18n.translate('xpack.ml.anomaliesTable.categoryExamplesColumnName', {
defaultMessage: 'category examples',
}),
@@ -254,6 +265,7 @@ export function getColumns(
if (showLinks === true) {
columns.push({
+ 'data-test-subj': 'mlAnomaliesListColumnAction',
name: i18n.translate('xpack.ml.anomaliesTable.actionsColumnName', {
defaultMessage: 'actions',
}),
diff --git a/x-pack/legacy/plugins/ml/public/application/components/display_value/display_value.tsx b/x-pack/legacy/plugins/ml/public/application/components/display_value/display_value.tsx
index cfe3d09a16320a..36225cb839704e 100644
--- a/x-pack/legacy/plugins/ml/public/application/components/display_value/display_value.tsx
+++ b/x-pack/legacy/plugins/ml/public/application/components/display_value/display_value.tsx
@@ -13,11 +13,11 @@ export const DisplayValue: FC<{ value: any }> = ({ value }) => {
const length = String(value).length;
if (length <= MAX_CHARS) {
- return value;
+ return {value} ;
} else {
return (
- {value}
+ {value}
);
}
diff --git a/x-pack/legacy/plugins/ml/public/application/components/field_title_bar/_field_title_bar.scss b/x-pack/legacy/plugins/ml/public/application/components/field_title_bar/_field_title_bar.scss
index 0fa087deacf91e..75118266d45dba 100644
--- a/x-pack/legacy/plugins/ml/public/application/components/field_title_bar/_field_title_bar.scss
+++ b/x-pack/legacy/plugins/ml/public/application/components/field_title_bar/_field_title_bar.scss
@@ -1,9 +1,14 @@
.ml-field-title-bar {
- color: $euiColorEmptyShade;
- @include euiFontSizeL;
+ @include euiFontSizeM;
+ font-family: Roboto Mono, serif;
+ font-style: normal;
+ font-weight: bold;
+ font-size: $euiFontSizeS;
+ border-radius: $euiBorderRadius $euiBorderRadius 0 0;
+ padding: $euiSizeXS;
+ margin: (-$euiSize) (-$euiSize) 0 (-$euiSize);
+ border-top: 3px solid;
text-align: center;
- border-radius: $euiBorderRadius $euiBorderRadius 0px 0px;
- padding-bottom: $euiSizeXS/2;
.field-type-icon {
vertical-align: middle;
@@ -18,5 +23,6 @@
padding-right: $euiSizeS;
max-width: 290px; // SASSTODO: Calculate value
display: inline-block;
+ margin-left: $euiSizeS;
}
}
diff --git a/x-pack/legacy/plugins/ml/public/application/components/field_type_icon/_field_type_icon.scss b/x-pack/legacy/plugins/ml/public/application/components/field_type_icon/_field_type_icon.scss
index ba318057bcae19..864df28f2c0554 100644
--- a/x-pack/legacy/plugins/ml/public/application/components/field_type_icon/_field_type_icon.scss
+++ b/x-pack/legacy/plugins/ml/public/application/components/field_type_icon/_field_type_icon.scss
@@ -1,8 +1,18 @@
+$icon-size: 20px;
+
.field-type-icon-container {
- display: inline !important;
+ display: inline-block !important;
+ vertical-align: middle;
+ border: 1px solid;
+ border-radius: 4px;
+ width: $icon-size;
+ height: $icon-size;
+ line-height: $icon-size;;
+ text-align: center;
.field-type-icon {
- padding-right: $euiSizeXS / 2;
+ padding: 0;
display: inline !important;
+ vertical-align: initial;
}
}
diff --git a/x-pack/legacy/plugins/ml/public/application/components/influencers_list/influencers_list.js b/x-pack/legacy/plugins/ml/public/application/components/influencers_list/influencers_list.js
index 6a395c5cbc114d..ae61e65f917996 100644
--- a/x-pack/legacy/plugins/ml/public/application/components/influencers_list/influencers_list.js
+++ b/x-pack/legacy/plugins/ml/public/application/components/influencers_list/influencers_list.js
@@ -56,7 +56,7 @@ function Influencer({ influencerFieldName, influencerFilter, valueData }) {
const tooltipContent = getTooltipContent(maxScoreLabel, totalScoreLabel);
return (
-
+
{influencerFieldName !== 'mlcategory' ? (
-
+
{influencerFieldName}
diff --git a/x-pack/legacy/plugins/ml/public/application/components/job_selector/job_selector_badge/job_selector_badge.js b/x-pack/legacy/plugins/ml/public/application/components/job_selector/job_selector_badge/job_selector_badge.js
index ff5bb475e3a733..4d2ab01e2a0544 100644
--- a/x-pack/legacy/plugins/ml/public/application/components/job_selector/job_selector_badge/job_selector_badge.js
+++ b/x-pack/legacy/plugins/ml/public/application/components/job_selector/job_selector_badge/job_selector_badge.js
@@ -33,7 +33,7 @@ export function JobSelectorBadge({ icon, id, isGroup = false, numJobs, removeId
}
return (
-
+
{`${id}${jobCount ? jobCount : ''}`}
);
diff --git a/x-pack/legacy/plugins/ml/public/application/components/kql_filter_bar/filter_bar/__snapshots__/filter_bar.test.js.snap b/x-pack/legacy/plugins/ml/public/application/components/kql_filter_bar/filter_bar/__snapshots__/filter_bar.test.js.snap
index 217aa113fba4d9..f3c825a66ee2f2 100644
--- a/x-pack/legacy/plugins/ml/public/application/components/kql_filter_bar/filter_bar/__snapshots__/filter_bar.test.js.snap
+++ b/x-pack/legacy/plugins/ml/public/application/components/kql_filter_bar/filter_bar/__snapshots__/filter_bar.test.js.snap
@@ -23,6 +23,7 @@ exports[`FilterBar snapshot suggestions not shown 1`] = `
fullWidth={true}
incremental={false}
inputRef={[Function]}
+ isClearable={true}
isLoading={false}
onChange={[Function]}
onClick={[Function]}
@@ -88,6 +89,7 @@ exports[`FilterBar snapshot suggestions shown 1`] = `
fullWidth={true}
incremental={false}
inputRef={[Function]}
+ isClearable={true}
isLoading={false}
onChange={[Function]}
onClick={[Function]}
diff --git a/x-pack/legacy/plugins/ml/public/application/components/loading_indicator/loading_indicator.js b/x-pack/legacy/plugins/ml/public/application/components/loading_indicator/loading_indicator.js
index e84ef2f87c3ba1..20f4fb86b5372c 100644
--- a/x-pack/legacy/plugins/ml/public/application/components/loading_indicator/loading_indicator.js
+++ b/x-pack/legacy/plugins/ml/public/application/components/loading_indicator/loading_indicator.js
@@ -12,7 +12,11 @@ import { EuiLoadingChart, EuiSpacer } from '@elastic/eui';
export function LoadingIndicator({ height, label }) {
height = height ? +height : 100;
return (
-
+
{label && (
<>
diff --git a/x-pack/legacy/plugins/ml/public/application/components/rule_editor/__snapshots__/condition_expression.test.js.snap b/x-pack/legacy/plugins/ml/public/application/components/rule_editor/__snapshots__/condition_expression.test.js.snap
index 177ba5019fbe3d..43b4625e81f794 100644
--- a/x-pack/legacy/plugins/ml/public/application/components/rule_editor/__snapshots__/condition_expression.test.js.snap
+++ b/x-pack/legacy/plugins/ml/public/application/components/rule_editor/__snapshots__/condition_expression.test.js.snap
@@ -55,10 +55,6 @@ exports[`ConditionExpression renders with appliesTo, operator and value supplied
}
>
;
@@ -19,8 +27,41 @@ export interface EsDoc extends Record {
export const MAX_COLUMNS = 20;
export const DEFAULT_REGRESSION_COLUMNS = 8;
+export const BASIC_NUMERICAL_TYPES = new Set([
+ ES_FIELD_TYPES.LONG,
+ ES_FIELD_TYPES.INTEGER,
+ ES_FIELD_TYPES.SHORT,
+ ES_FIELD_TYPES.BYTE,
+]);
+
+export const EXTENDED_NUMERICAL_TYPES = new Set([
+ ES_FIELD_TYPES.DOUBLE,
+ ES_FIELD_TYPES.FLOAT,
+ ES_FIELD_TYPES.HALF_FLOAT,
+ ES_FIELD_TYPES.SCALED_FLOAT,
+]);
+
const ML__ID_COPY = 'ml__id_copy';
+export const isKeywordAndTextType = (fieldName: string): boolean => {
+ const { fields } = newJobCapsService;
+
+ const fieldType = fields.find(field => field.name === fieldName)?.type;
+ let isBothTypes = false;
+
+ // If it's a keyword type - check if it has a corresponding text type
+ if (fieldType !== undefined && fieldType === ES_FIELD_TYPES.KEYWORD) {
+ const field = newJobCapsService.getFieldById(fieldName.replace(/\.keyword$/, ''));
+ isBothTypes = field !== null && field.type === ES_FIELD_TYPES.TEXT;
+ } else if (fieldType !== undefined && fieldType === ES_FIELD_TYPES.TEXT) {
+ // If text, check if has corresponding keyword type
+ const field = newJobCapsService.getFieldById(`${fieldName}.keyword`);
+ isBothTypes = field !== null && field.type === ES_FIELD_TYPES.KEYWORD;
+ }
+
+ return isBothTypes;
+};
+
// Used to sort columns:
// - string based columns are moved to the left
// - followed by the outlier_score column
@@ -90,10 +131,10 @@ export const sortRegressionResultsFields = (
if (b === predictedField) {
return 1;
}
- if (a === dependentVariable) {
+ if (a === dependentVariable || a === dependentVariable.replace(/\.keyword$/, '')) {
return -1;
}
- if (b === dependentVariable) {
+ if (b === dependentVariable || b === dependentVariable.replace(/\.keyword$/, '')) {
return 1;
}
@@ -200,6 +241,50 @@ export function getFlattenedFields(obj: EsDocSource, resultsField: string): EsFi
return flatDocFields.filter(f => f !== ML__ID_COPY);
}
+export const getDefaultFieldsFromJobCaps = (
+ fields: Field[],
+ jobConfig: DataFrameAnalyticsConfig
+): { selectedFields: Field[]; docFields: Field[] } => {
+ const fieldsObj = { selectedFields: [], docFields: [] };
+ if (fields.length === 0) {
+ return fieldsObj;
+ }
+
+ const dependentVariable = getDependentVar(jobConfig.analysis);
+ const type = newJobCapsService.getFieldById(dependentVariable)?.type;
+ const predictionFieldName = getPredictionFieldName(jobConfig.analysis);
+ // default is 'ml'
+ const resultsField = jobConfig.dest.results_field;
+
+ const defaultPredictionField = `${dependentVariable}_prediction`;
+ const predictedField = `${resultsField}.${
+ predictionFieldName ? predictionFieldName : defaultPredictionField
+ }`;
+
+ const allFields: any = [
+ {
+ id: `${resultsField}.is_training`,
+ name: `${resultsField}.is_training`,
+ type: ES_FIELD_TYPES.BOOLEAN,
+ },
+ { id: predictedField, name: predictedField, type },
+ ...fields,
+ ].sort(({ name: a }, { name: b }) => sortRegressionResultsFields(a, b, jobConfig));
+
+ let selectedFields = allFields
+ .slice(0, DEFAULT_REGRESSION_COLUMNS * 2)
+ .filter((field: any) => field.name === predictedField || !field.name.includes('.keyword'));
+
+ if (selectedFields.length > DEFAULT_REGRESSION_COLUMNS) {
+ selectedFields = selectedFields.slice(0, DEFAULT_REGRESSION_COLUMNS);
+ }
+
+ return {
+ selectedFields,
+ docFields: allFields,
+ };
+};
+
export const getDefaultClassificationFields = (
docs: EsDoc[],
jobConfig: DataFrameAnalyticsConfig
@@ -290,11 +375,12 @@ export const getDefaultSelectableFields = (docs: EsDoc[], resultsField: string):
.slice(0, MAX_COLUMNS);
};
-export const toggleSelectedField = (
+export const toggleSelectedFieldSimple = (
selectedFields: EsFieldName[],
column: EsFieldName
): EsFieldName[] => {
const index = selectedFields.indexOf(column);
+
if (index === -1) {
selectedFields.push(column);
} else {
@@ -302,3 +388,16 @@ export const toggleSelectedField = (
}
return selectedFields;
};
+
+export const toggleSelectedField = (selectedFields: Field[], column: EsFieldName): Field[] => {
+ const index = selectedFields.map(field => field.name).indexOf(column);
+ if (index === -1) {
+ const columnField = newJobCapsService.getFieldById(column);
+ if (columnField !== null) {
+ selectedFields.push(columnField);
+ }
+ } else {
+ selectedFields.splice(index, 1);
+ }
+ return selectedFields;
+};
diff --git a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/common/index.ts b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/common/index.ts
index f7794af8b5861a..62ef73670d8f53 100644
--- a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/common/index.ts
+++ b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/common/index.ts
@@ -33,11 +33,13 @@ export {
getDefaultSelectableFields,
getDefaultRegressionFields,
getDefaultClassificationFields,
+ getDefaultFieldsFromJobCaps,
getFlattenedFields,
sortColumns,
sortRegressionResultsColumns,
sortRegressionResultsFields,
toggleSelectedField,
+ toggleSelectedFieldSimple,
EsId,
EsDoc,
EsDocSource,
diff --git a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/classification_exploration.tsx b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/classification_exploration.tsx
index f424ebee581204..95e1b15d548c1c 100644
--- a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/classification_exploration.tsx
+++ b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/classification_exploration.tsx
@@ -14,6 +14,10 @@ import { ResultsTable } from './results_table';
import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common';
import { ResultsSearchQuery, defaultSearchQuery } from '../../../../common/analytics';
import { LoadingPanel } from '../loading_panel';
+import { getIndexPatternIdFromName } from '../../../../../util/index_utils';
+import { IIndexPattern } from '../../../../../../../../../../../src/plugins/data/common/index_patterns';
+import { newJobCapsService } from '../../../../../services/new_job_capabilities_service';
+import { useKibanaContext } from '../../../../../contexts/kibana';
interface GetDataFrameAnalyticsResponse {
count: number;
@@ -31,6 +35,21 @@ export const ExplorationTitle: React.FC<{ jobId: string }> = ({ jobId }) => (
);
+const jobConfigErrorTitle = i18n.translate(
+ 'xpack.ml.dataframe.analytics.classificationExploration.jobConfigurationFetchError',
+ {
+ defaultMessage:
+ 'Unable to fetch results. An error occurred loading the job configuration data.',
+ }
+);
+
+const jobCapsErrorTitle = i18n.translate(
+ 'xpack.ml.dataframe.analytics.classificationExploration.jobCapsFetchError',
+ {
+ defaultMessage: "Unable to fetch results. An error occurred loading the index's field data.",
+ }
+);
+
interface Props {
jobId: string;
jobStatus: DATA_FRAME_TASK_STATE;
@@ -39,8 +58,13 @@ interface Props {
export const ClassificationExploration: FC = ({ jobId, jobStatus }) => {
const [jobConfig, setJobConfig] = useState(undefined);
const [isLoadingJobConfig, setIsLoadingJobConfig] = useState(false);
+ const [isInitialized, setIsInitialized] = useState(false);
const [jobConfigErrorMessage, setJobConfigErrorMessage] = useState(undefined);
+ const [jobCapsServiceErrorMessage, setJobCapsServiceErrorMessage] = useState(
+ undefined
+ );
const [searchQuery, setSearchQuery] = useState(defaultSearchQuery);
+ const kibanaContext = useKibanaContext();
const loadJobConfig = async () => {
setIsLoadingJobConfig(true);
@@ -78,23 +102,41 @@ export const ClassificationExploration: FC = ({ jobId, jobStatus }) => {
loadJobConfig();
}, []);
- if (jobConfigErrorMessage !== undefined) {
+ const initializeJobCapsService = async () => {
+ if (jobConfig !== undefined) {
+ try {
+ const sourceIndex = jobConfig.source.index[0];
+ const indexPatternId = getIndexPatternIdFromName(sourceIndex) || sourceIndex;
+ const indexPattern: IIndexPattern = await kibanaContext.indexPatterns.get(indexPatternId);
+ if (indexPattern !== undefined) {
+ await newJobCapsService.initializeFromIndexPattern(indexPattern, false, false);
+ }
+ setIsInitialized(true);
+ } catch (e) {
+ if (e.message !== undefined) {
+ setJobCapsServiceErrorMessage(e.message);
+ } else {
+ setJobCapsServiceErrorMessage(JSON.stringify(e));
+ }
+ }
+ }
+ };
+
+ useEffect(() => {
+ initializeJobCapsService();
+ }, [JSON.stringify(jobConfig)]);
+
+ if (jobConfigErrorMessage !== undefined || jobCapsServiceErrorMessage !== undefined) {
return (
- {jobConfigErrorMessage}
+ {jobConfigErrorMessage ? jobConfigErrorMessage : jobCapsServiceErrorMessage}
);
@@ -103,12 +145,12 @@ export const ClassificationExploration: FC = ({ jobId, jobStatus }) => {
return (
{isLoadingJobConfig === true && jobConfig === undefined && }
- {isLoadingJobConfig === false && jobConfig !== undefined && (
+ {isLoadingJobConfig === false && jobConfig !== undefined && isInitialized === true && (
)}
{isLoadingJobConfig === true && jobConfig === undefined && }
- {isLoadingJobConfig === false && jobConfig !== undefined && (
+ {isLoadingJobConfig === false && jobConfig !== undefined && isInitialized === true && (
= ({ jobConfig, jobStatus, searchQuery })
const [visibleColumns, setVisibleColumns] = useState(() =>
columns.map(({ id }: { id: string }) => id)
);
- const kibanaContext = useKibanaContext();
const index = jobConfig.dest.index;
- const sourceIndex = jobConfig.source.index[0];
const dependentVariable = getDependentVar(jobConfig.analysis);
const predictionFieldName = getPredictionFieldName(jobConfig.analysis);
// default is 'ml'
@@ -86,25 +80,7 @@ export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery })
setIsLoading(true);
try {
- const indexPatternId = getIndexPatternIdFromName(sourceIndex) || sourceIndex;
- const indexPattern: IIndexPattern = await kibanaContext.indexPatterns.get(indexPatternId);
-
- if (indexPattern !== undefined) {
- await newJobCapsService.initializeFromIndexPattern(indexPattern, false, false);
- // If dependent_variable is of type keyword and text .keyword suffix is required for evaluate endpoint
- const { fields } = newJobCapsService;
- const depVarFieldType = fields.find(field => field.name === dependentVariable)?.type;
-
- // If it's a keyword type - check if it has a corresponding text type
- if (depVarFieldType !== undefined && depVarFieldType === ES_FIELD_TYPES.KEYWORD) {
- const field = newJobCapsService.getFieldById(dependentVariable.replace(/\.keyword$/, ''));
- requiresKeyword = field !== null && field.type === ES_FIELD_TYPES.TEXT;
- } else if (depVarFieldType !== undefined && depVarFieldType === ES_FIELD_TYPES.TEXT) {
- // If text, check if has corresponding keyword type
- const field = newJobCapsService.getFieldById(`${dependentVariable}.keyword`);
- requiresKeyword = field !== null && field.type === ES_FIELD_TYPES.KEYWORD;
- }
- }
+ requiresKeyword = isKeywordAndTextType(dependentVariable);
} catch (e) {
// Additional error handling due to missing field type is handled by loadEvalData
console.error('Unable to load new field types', error); // eslint-disable-line no-console
@@ -359,9 +335,9 @@ export const EvaluatePanel: FC = ({ jobConfig, jobStatus, searchQuery })
-
+
= React.memo(
({ jobConfig, jobStatus, setEvaluateSearchQuery }) => {
const [pageIndex, setPageIndex] = useState(0);
const [pageSize, setPageSize] = useState(25);
- const [selectedFields, setSelectedFields] = useState([] as EsFieldName[]);
+ const [selectedFields, setSelectedFields] = useState([] as Field[]);
+ const [docFields, setDocFields] = useState([] as Field[]);
const [isColumnsPopoverVisible, setColumnsPopoverVisible] = useState(false);
const [searchQuery, setSearchQuery] = useState(defaultSearchQuery);
const [searchError, setSearchError] = useState(undefined);
const [searchString, setSearchString] = useState(undefined);
+ const predictedFieldName = getPredictedFieldName(
+ jobConfig.dest.results_field,
+ jobConfig.analysis
+ );
+
+ const dependentVariable = getDependentVar(jobConfig.analysis);
+
function toggleColumnsPopover() {
setColumnsPopoverVisible(!isColumnsPopoverVisible);
}
@@ -99,147 +113,140 @@ export const ResultsTable: FC = React.memo(
sortDirection,
status,
tableItems,
- } = useExploreData(jobConfig, selectedFields, setSelectedFields);
-
- let docFields: EsFieldName[] = [];
- let docFieldsCount = 0;
- if (tableItems.length > 0) {
- docFields = Object.keys(tableItems[0]);
- docFields.sort((a, b) => sortRegressionResultsFields(a, b, jobConfig));
- docFieldsCount = docFields.length;
- }
-
- const columns: Array> = [];
-
- if (jobConfig !== undefined && selectedFields.length > 0 && tableItems.length > 0) {
- columns.push(
- ...selectedFields.sort(sortRegressionResultsColumns(tableItems[0], jobConfig)).map(k => {
- const column: ColumnType = {
- field: k,
- name: k,
- sortable: true,
- truncateText: true,
- };
-
- const render = (d: any, fullItem: EsDoc) => {
- if (Array.isArray(d) && d.every(item => typeof item === 'string')) {
- // If the cells data is an array of strings, return as a comma separated list.
- // The list will get limited to 5 items with `…` at the end if there's more in the original array.
- return `${d.slice(0, 5).join(', ')}${d.length > 5 ? ', …' : ''}`;
- } else if (Array.isArray(d)) {
- // If the cells data is an array of e.g. objects, display a 'array' badge with a
- // tooltip that explains that this type of field is not supported in this table.
- return (
-
-
- {i18n.translate(
- 'xpack.ml.dataframe.analytics.classificationExploration.indexArrayBadgeContent',
- {
- defaultMessage: 'array',
- }
- )}
-
-
- );
- } else if (typeof d === 'object' && d !== null) {
- // If the cells data is an object, display a 'object' badge with a
- // tooltip that explains that this type of field is not supported in this table.
- return (
-
-
- {i18n.translate(
- 'xpack.ml.dataframe.analytics.classificationExploration.indexObjectBadgeContent',
- {
- defaultMessage: 'object',
- }
- )}
-
-
- );
- }
-
- return d;
- };
+ } = useExploreData(jobConfig, selectedFields, setSelectedFields, setDocFields);
+
+ const columns: Array> = selectedFields.map(field => {
+ const { type } = field;
+ const isNumber =
+ type !== undefined &&
+ (BASIC_NUMERICAL_TYPES.has(type) || EXTENDED_NUMERICAL_TYPES.has(type));
+
+ const column: ColumnType = {
+ field: field.name,
+ name: field.name,
+ sortable: true,
+ truncateText: true,
+ };
- let columnType;
+ const render = (d: any, fullItem: EsDoc) => {
+ if (Array.isArray(d) && d.every(item => typeof item === 'string')) {
+ // If the cells data is an array of strings, return as a comma separated list.
+ // The list will get limited to 5 items with `…` at the end if there's more in the original array.
+ return `${d.slice(0, 5).join(', ')}${d.length > 5 ? ', …' : ''}`;
+ } else if (Array.isArray(d)) {
+ // If the cells data is an array of e.g. objects, display a 'array' badge with a
+ // tooltip that explains that this type of field is not supported in this table.
+ return (
+
+
+ {i18n.translate(
+ 'xpack.ml.dataframe.analytics.classificationExploration.indexArrayBadgeContent',
+ {
+ defaultMessage: 'array',
+ }
+ )}
+
+
+ );
+ }
- if (tableItems.length > 0) {
- columnType = typeof tableItems[0][k];
- }
+ return d;
+ };
- if (typeof columnType !== 'undefined') {
- switch (columnType) {
- case 'boolean':
- column.dataType = 'boolean';
- break;
- case 'Date':
- column.align = 'right';
- column.render = (d: any) =>
- formatHumanReadableDateTimeSeconds(moment(d).unix() * 1000);
- break;
- case 'number':
- column.dataType = 'number';
- column.render = render;
- break;
- default:
- column.render = render;
- break;
- }
- } else {
+ if (isNumber) {
+ column.dataType = 'number';
+ column.render = render;
+ } else if (typeof type !== 'undefined') {
+ switch (type) {
+ case ES_FIELD_TYPES.BOOLEAN:
+ column.dataType = ES_FIELD_TYPES.BOOLEAN;
+ break;
+ case ES_FIELD_TYPES.DATE:
+ column.align = 'right';
+ column.render = (d: any) => {
+ if (d !== undefined) {
+ return formatHumanReadableDateTimeSeconds(moment(d).unix() * 1000);
+ }
+ return d;
+ };
+ break;
+ default:
column.render = render;
- }
+ break;
+ }
+ } else {
+ column.render = render;
+ }
- return column;
- })
- );
- }
+ return column;
+ });
+
+ const docFieldsCount = docFields.length;
useEffect(() => {
- if (jobConfig !== undefined) {
- const predictedFieldName = getPredictedFieldName(
- jobConfig.dest.results_field,
- jobConfig.analysis
- );
- const predictedFieldSelected = selectedFields.includes(predictedFieldName);
+ if (
+ jobConfig !== undefined &&
+ columns.length > 0 &&
+ selectedFields.length > 0 &&
+ sortField !== undefined &&
+ sortDirection !== undefined &&
+ selectedFields.some(field => field.name === sortField)
+ ) {
+ let field = sortField;
+ // If sorting by predictedField use dependentVar type
+ if (predictedFieldName === sortField) {
+ field = dependentVariable;
+ }
+ const requiresKeyword = isKeywordAndTextType(field);
- const field = predictedFieldSelected ? predictedFieldName : selectedFields[0];
- const direction = predictedFieldSelected ? SORT_DIRECTION.DESC : SORT_DIRECTION.ASC;
- loadExploreData({ field, direction, searchQuery });
+ loadExploreData({
+ field: sortField,
+ direction: sortDirection,
+ searchQuery,
+ requiresKeyword,
+ });
}
}, [JSON.stringify(searchQuery)]);
useEffect(() => {
- // by default set the sorting to descending on the prediction field (`_prediction`).
- // if that's not available sort ascending on the first column.
- // also check if the current sorting field is still available.
- if (jobConfig !== undefined && columns.length > 0 && !selectedFields.includes(sortField)) {
- const predictedFieldName = getPredictedFieldName(
- jobConfig.dest.results_field,
- jobConfig.analysis
+ // By default set sorting to descending on the prediction field (`_prediction`).
+ // if that's not available sort ascending on the first column. Check if the current sorting field is still available.
+ if (
+ jobConfig !== undefined &&
+ columns.length > 0 &&
+ selectedFields.length > 0 &&
+ !selectedFields.some(field => field.name === sortField)
+ ) {
+ const predictedFieldSelected = selectedFields.some(
+ field => field.name === predictedFieldName
);
- const predictedFieldSelected = selectedFields.includes(predictedFieldName);
- const field = predictedFieldSelected ? predictedFieldName : selectedFields[0];
+ // CHECK IF keyword suffix is needed (if predicted field is selected we have to check the dependent variable type)
+ let sortByField = predictedFieldSelected ? dependentVariable : selectedFields[0].name;
+
+ const requiresKeyword = isKeywordAndTextType(sortByField);
+
+ sortByField = predictedFieldSelected ? predictedFieldName : sortByField;
+
const direction = predictedFieldSelected ? SORT_DIRECTION.DESC : SORT_DIRECTION.ASC;
- loadExploreData({ field, direction, searchQuery });
+ loadExploreData({ field: sortByField, direction, searchQuery, requiresKeyword });
}
- }, [jobConfig, columns.length, sortField, sortDirection, tableItems.length]);
+ }, [
+ jobConfig,
+ columns.length,
+ selectedFields.length,
+ sortField,
+ sortDirection,
+ tableItems.length,
+ ]);
let sorting: SortingPropType = false;
let onTableChange;
@@ -261,7 +268,17 @@ export const ResultsTable: FC = React.memo(
setPageSize(size);
if (sort.field !== sortField || sort.direction !== sortDirection) {
- loadExploreData({ ...sort, searchQuery });
+ let field = sort.field;
+ // If sorting by predictedField use depVar for type check
+ if (predictedFieldName === sort.field) {
+ field = dependentVariable;
+ }
+
+ loadExploreData({
+ ...sort,
+ searchQuery,
+ requiresKeyword: isKeywordAndTextType(field),
+ });
}
};
}
@@ -422,14 +439,17 @@ export const ResultsTable: FC = React.memo(
)}
- {docFields.map(d => (
+ {docFields.map(({ name }) => (
toggleColumn(d)}
- disabled={selectedFields.includes(d) && selectedFields.length === 1}
+ key={name}
+ id={name}
+ label={name}
+ checked={selectedFields.some(field => field.name === name)}
+ onChange={() => toggleColumn(name)}
+ disabled={
+ selectedFields.some(field => field.name === name) &&
+ selectedFields.length === 1
+ }
/>
))}
diff --git a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/use_explore_data.ts b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/use_explore_data.ts
index ba12fcab98a36d..b61f9f65241161 100644
--- a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/use_explore_data.ts
+++ b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/classification_exploration/use_explore_data.ts
@@ -17,27 +17,22 @@ import { SortDirection, SORT_DIRECTION } from '../../../../../components/ml_in_m
import { ml } from '../../../../../services/ml_api_service';
import { getNestedProperty } from '../../../../../util/object_utils';
-import { SavedSearchQuery } from '../../../../../contexts/kibana';
+import { newJobCapsService } from '../../../../../services/new_job_capabilities_service';
+import { Field } from '../../../../../../../common/types/fields';
+import { LoadExploreDataArg } from '../../../../common/analytics';
import {
- getDefaultClassificationFields,
+ getDefaultFieldsFromJobCaps,
getFlattenedFields,
DataFrameAnalyticsConfig,
EsFieldName,
- getPredictedFieldName,
INDEX_STATUS,
SEARCH_SIZE,
- defaultSearchQuery,
SearchQuery,
} from '../../../../common';
export type TableItem = Record;
-interface LoadExploreDataArg {
- field: string;
- direction: SortDirection;
- searchQuery: SavedSearchQuery;
-}
export interface UseExploreDataReturnType {
errorMessage: string;
loadExploreData: (arg: LoadExploreDataArg) => void;
@@ -49,8 +44,9 @@ export interface UseExploreDataReturnType {
export const useExploreData = (
jobConfig: DataFrameAnalyticsConfig | undefined,
- selectedFields: EsFieldName[],
- setSelectedFields: React.Dispatch>
+ selectedFields: Field[],
+ setSelectedFields: React.Dispatch>,
+ setDocFields: React.Dispatch>
): UseExploreDataReturnType => {
const [errorMessage, setErrorMessage] = useState('');
const [status, setStatus] = useState(INDEX_STATUS.UNUSED);
@@ -58,7 +54,26 @@ export const useExploreData = (
const [sortField, setSortField] = useState('');
const [sortDirection, setSortDirection] = useState(SORT_DIRECTION.ASC);
- const loadExploreData = async ({ field, direction, searchQuery }: LoadExploreDataArg) => {
+ const getDefaultSelectedFields = () => {
+ const { fields } = newJobCapsService;
+
+ if (selectedFields.length === 0 && jobConfig !== undefined) {
+ const { selectedFields: defaultSelected, docFields } = getDefaultFieldsFromJobCaps(
+ fields,
+ jobConfig
+ );
+
+ setSelectedFields(defaultSelected);
+ setDocFields(docFields);
+ }
+ };
+
+ const loadExploreData = async ({
+ field,
+ direction,
+ searchQuery,
+ requiresKeyword,
+ }: LoadExploreDataArg) => {
if (jobConfig !== undefined) {
setErrorMessage('');
setStatus(INDEX_STATUS.LOADING);
@@ -72,7 +87,7 @@ export const useExploreData = (
if (field !== undefined) {
body.sort = [
{
- [field]: {
+ [`${field}${requiresKeyword ? '.keyword' : ''}`]: {
order: direction,
},
},
@@ -96,11 +111,6 @@ export const useExploreData = (
return;
}
- if (selectedFields.length === 0) {
- const newSelectedFields = getDefaultClassificationFields(docs, jobConfig);
- setSelectedFields(newSelectedFields);
- }
-
// Create a version of the doc's source with flattened field names.
// This avoids confusion later on if a field name has dots in its name
// or is a nested fields when displaying it via EuiInMemoryTable.
@@ -144,11 +154,7 @@ export const useExploreData = (
useEffect(() => {
if (jobConfig !== undefined) {
- loadExploreData({
- field: getPredictedFieldName(jobConfig.dest.results_field, jobConfig.analysis),
- direction: SORT_DIRECTION.DESC,
- searchQuery: defaultSearchQuery,
- });
+ getDefaultSelectedFields();
}
}, [jobConfig && jobConfig.id]);
diff --git a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.tsx b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.tsx
index 31e6d409b1c4fd..9691a0706121cb 100644
--- a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.tsx
+++ b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration/exploration.tsx
@@ -46,7 +46,7 @@ import { ml } from '../../../../../services/ml_api_service';
import {
sortColumns,
- toggleSelectedField,
+ toggleSelectedFieldSimple,
DataFrameAnalyticsConfig,
EsFieldName,
EsDoc,
@@ -138,7 +138,7 @@ export const Exploration: FC = React.memo(({ jobId, jobStatus }) => {
function toggleColumn(column: EsFieldName) {
if (tableItems.length > 0 && jobConfig !== undefined) {
// spread to a new array otherwise the component wouldn't re-render
- setSelectedFields([...toggleSelectedField(selectedFields, column)]);
+ setSelectedFields([...toggleSelectedFieldSimple(selectedFields, column)]);
}
}
diff --git a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/regression_exploration.tsx b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/regression_exploration.tsx
index 12a41e1e7d851e..7399828bcd642b 100644
--- a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/regression_exploration.tsx
+++ b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/regression_exploration.tsx
@@ -14,6 +14,10 @@ import { ResultsTable } from './results_table';
import { DATA_FRAME_TASK_STATE } from '../../../analytics_management/components/analytics_list/common';
import { ResultsSearchQuery, defaultSearchQuery } from '../../../../common/analytics';
import { LoadingPanel } from '../loading_panel';
+import { getIndexPatternIdFromName } from '../../../../../util/index_utils';
+import { IIndexPattern } from '../../../../../../../../../../../src/plugins/data/common/index_patterns';
+import { newJobCapsService } from '../../../../../services/new_job_capabilities_service';
+import { useKibanaContext } from '../../../../../contexts/kibana';
interface GetDataFrameAnalyticsResponse {
count: number;
@@ -31,6 +35,21 @@ export const ExplorationTitle: React.FC<{ jobId: string }> = ({ jobId }) => (
);
+const jobConfigErrorTitle = i18n.translate(
+ 'xpack.ml.dataframe.analytics.regressionExploration.jobConfigurationFetchError',
+ {
+ defaultMessage:
+ 'Unable to fetch results. An error occurred loading the job configuration data.',
+ }
+);
+
+const jobCapsErrorTitle = i18n.translate(
+ 'xpack.ml.dataframe.analytics.regressionExploration.jobCapsFetchError',
+ {
+ defaultMessage: "Unable to fetch results. An error occurred loading the index's field data.",
+ }
+);
+
interface Props {
jobId: string;
jobStatus: DATA_FRAME_TASK_STATE;
@@ -39,8 +58,13 @@ interface Props {
export const RegressionExploration: FC = ({ jobId, jobStatus }) => {
const [jobConfig, setJobConfig] = useState(undefined);
const [isLoadingJobConfig, setIsLoadingJobConfig] = useState(false);
+ const [isInitialized, setIsInitialized] = useState(false);
const [jobConfigErrorMessage, setJobConfigErrorMessage] = useState(undefined);
+ const [jobCapsServiceErrorMessage, setJobCapsServiceErrorMessage] = useState(
+ undefined
+ );
const [searchQuery, setSearchQuery] = useState(defaultSearchQuery);
+ const kibanaContext = useKibanaContext();
const loadJobConfig = async () => {
setIsLoadingJobConfig(true);
@@ -69,23 +93,41 @@ export const RegressionExploration: FC = ({ jobId, jobStatus }) => {
loadJobConfig();
}, []);
- if (jobConfigErrorMessage !== undefined) {
+ const initializeJobCapsService = async () => {
+ if (jobConfig !== undefined) {
+ try {
+ const sourceIndex = jobConfig.source.index[0];
+ const indexPatternId = getIndexPatternIdFromName(sourceIndex) || sourceIndex;
+ const indexPattern: IIndexPattern = await kibanaContext.indexPatterns.get(indexPatternId);
+ if (indexPattern !== undefined) {
+ await newJobCapsService.initializeFromIndexPattern(indexPattern, false, false);
+ }
+ setIsInitialized(true);
+ } catch (e) {
+ if (e.message !== undefined) {
+ setJobCapsServiceErrorMessage(e.message);
+ } else {
+ setJobCapsServiceErrorMessage(JSON.stringify(e));
+ }
+ }
+ }
+ };
+
+ useEffect(() => {
+ initializeJobCapsService();
+ }, [JSON.stringify(jobConfig)]);
+
+ if (jobConfigErrorMessage !== undefined || jobCapsServiceErrorMessage !== undefined) {
return (
- {jobConfigErrorMessage}
+ {jobConfigErrorMessage ? jobConfigErrorMessage : jobCapsServiceErrorMessage}
);
@@ -94,12 +136,12 @@ export const RegressionExploration: FC = ({ jobId, jobStatus }) => {
return (
{isLoadingJobConfig === true && jobConfig === undefined && }
- {isLoadingJobConfig === false && jobConfig !== undefined && (
+ {isLoadingJobConfig === false && jobConfig !== undefined && isInitialized === true && (
)}
{isLoadingJobConfig === true && jobConfig === undefined && }
- {isLoadingJobConfig === false && jobConfig !== undefined && (
+ {isLoadingJobConfig === false && jobConfig !== undefined && isInitialized === true && (
= React.memo(
({ jobConfig, jobStatus, setEvaluateSearchQuery }) => {
const [pageIndex, setPageIndex] = useState(0);
const [pageSize, setPageSize] = useState(25);
- const [selectedFields, setSelectedFields] = useState([] as EsFieldName[]);
+ const [selectedFields, setSelectedFields] = useState([] as Field[]);
+ const [docFields, setDocFields] = useState([] as Field[]);
const [isColumnsPopoverVisible, setColumnsPopoverVisible] = useState(false);
const [searchQuery, setSearchQuery] = useState(defaultSearchQuery);
const [searchError, setSearchError] = useState(undefined);
const [searchString, setSearchString] = useState(undefined);
+ const predictedFieldName = getPredictedFieldName(
+ jobConfig.dest.results_field,
+ jobConfig.analysis
+ );
+
+ const dependentVariable = getDependentVar(jobConfig.analysis);
+
function toggleColumnsPopover() {
setColumnsPopoverVisible(!isColumnsPopoverVisible);
}
@@ -100,147 +114,140 @@ export const ResultsTable: FC = React.memo(
sortDirection,
status,
tableItems,
- } = useExploreData(jobConfig, selectedFields, setSelectedFields);
-
- let docFields: EsFieldName[] = [];
- let docFieldsCount = 0;
- if (tableItems.length > 0) {
- docFields = Object.keys(tableItems[0]);
- docFields.sort((a, b) => sortRegressionResultsFields(a, b, jobConfig));
- docFieldsCount = docFields.length;
- }
-
- const columns: Array> = [];
-
- if (jobConfig !== undefined && selectedFields.length > 0 && tableItems.length > 0) {
- columns.push(
- ...selectedFields.sort(sortRegressionResultsColumns(tableItems[0], jobConfig)).map(k => {
- const column: ColumnType = {
- field: k,
- name: k,
- sortable: true,
- truncateText: true,
- };
-
- const render = (d: any, fullItem: EsDoc) => {
- if (Array.isArray(d) && d.every(item => typeof item === 'string')) {
- // If the cells data is an array of strings, return as a comma separated list.
- // The list will get limited to 5 items with `…` at the end if there's more in the original array.
- return `${d.slice(0, 5).join(', ')}${d.length > 5 ? ', …' : ''}`;
- } else if (Array.isArray(d)) {
- // If the cells data is an array of e.g. objects, display a 'array' badge with a
- // tooltip that explains that this type of field is not supported in this table.
- return (
-
-
- {i18n.translate(
- 'xpack.ml.dataframe.analytics.regressionExploration.indexArrayBadgeContent',
- {
- defaultMessage: 'array',
- }
- )}
-
-
- );
- } else if (typeof d === 'object' && d !== null) {
- // If the cells data is an object, display a 'object' badge with a
- // tooltip that explains that this type of field is not supported in this table.
- return (
-
-
- {i18n.translate(
- 'xpack.ml.dataframe.analytics.regressionExploration.indexObjectBadgeContent',
- {
- defaultMessage: 'object',
- }
- )}
-
-
- );
- }
-
- return d;
- };
+ } = useExploreData(jobConfig, selectedFields, setSelectedFields, setDocFields);
+
+ const columns: Array> = selectedFields.map(field => {
+ const { type } = field;
+ const isNumber =
+ type !== undefined &&
+ (BASIC_NUMERICAL_TYPES.has(type) || EXTENDED_NUMERICAL_TYPES.has(type));
+
+ const column: ColumnType = {
+ field: field.name,
+ name: field.name,
+ sortable: true,
+ truncateText: true,
+ };
- let columnType;
+ const render = (d: any, fullItem: EsDoc) => {
+ if (Array.isArray(d) && d.every(item => typeof item === 'string')) {
+ // If the cells data is an array of strings, return as a comma separated list.
+ // The list will get limited to 5 items with `…` at the end if there's more in the original array.
+ return `${d.slice(0, 5).join(', ')}${d.length > 5 ? ', …' : ''}`;
+ } else if (Array.isArray(d)) {
+ // If the cells data is an array of e.g. objects, display a 'array' badge with a
+ // tooltip that explains that this type of field is not supported in this table.
+ return (
+
+
+ {i18n.translate(
+ 'xpack.ml.dataframe.analytics.regressionExploration.indexArrayBadgeContent',
+ {
+ defaultMessage: 'array',
+ }
+ )}
+
+
+ );
+ }
- if (tableItems.length > 0) {
- columnType = typeof tableItems[0][k];
- }
+ return d;
+ };
- if (typeof columnType !== 'undefined') {
- switch (columnType) {
- case 'boolean':
- column.dataType = 'boolean';
- break;
- case 'Date':
- column.align = 'right';
- column.render = (d: any) =>
- formatHumanReadableDateTimeSeconds(moment(d).unix() * 1000);
- break;
- case 'number':
- column.dataType = 'number';
- column.render = render;
- break;
- default:
- column.render = render;
- break;
- }
- } else {
+ if (isNumber) {
+ column.dataType = 'number';
+ column.render = render;
+ } else if (typeof type !== 'undefined') {
+ switch (type) {
+ case ES_FIELD_TYPES.BOOLEAN:
+ column.dataType = ES_FIELD_TYPES.BOOLEAN;
+ break;
+ case ES_FIELD_TYPES.DATE:
+ column.align = 'right';
+ column.render = (d: any) => {
+ if (d !== undefined) {
+ return formatHumanReadableDateTimeSeconds(moment(d).unix() * 1000);
+ }
+ return d;
+ };
+ break;
+ default:
column.render = render;
- }
+ break;
+ }
+ } else {
+ column.render = render;
+ }
- return column;
- })
- );
- }
+ return column;
+ });
+
+ const docFieldsCount = docFields.length;
useEffect(() => {
- if (jobConfig !== undefined) {
- const predictedFieldName = getPredictedFieldName(
- jobConfig.dest.results_field,
- jobConfig.analysis
- );
- const predictedFieldSelected = selectedFields.includes(predictedFieldName);
+ if (
+ jobConfig !== undefined &&
+ columns.length > 0 &&
+ selectedFields.length > 0 &&
+ sortField !== undefined &&
+ sortDirection !== undefined &&
+ selectedFields.some(field => field.name === sortField)
+ ) {
+ let field = sortField;
+ // If sorting by predictedField use dependentVar type
+ if (predictedFieldName === sortField) {
+ field = dependentVariable;
+ }
+ const requiresKeyword = isKeywordAndTextType(field);
- const field = predictedFieldSelected ? predictedFieldName : selectedFields[0];
- const direction = predictedFieldSelected ? SORT_DIRECTION.DESC : SORT_DIRECTION.ASC;
- loadExploreData({ field, direction, searchQuery });
+ loadExploreData({
+ field: sortField,
+ direction: sortDirection,
+ searchQuery,
+ requiresKeyword,
+ });
}
}, [JSON.stringify(searchQuery)]);
useEffect(() => {
- // by default set the sorting to descending on the prediction field (`_prediction`).
- // if that's not available sort ascending on the first column.
- // also check if the current sorting field is still available.
- if (jobConfig !== undefined && columns.length > 0 && !selectedFields.includes(sortField)) {
- const predictedFieldName = getPredictedFieldName(
- jobConfig.dest.results_field,
- jobConfig.analysis
+ // By default set sorting to descending on the prediction field (`_prediction`).
+ // if that's not available sort ascending on the first column. Check if the current sorting field is still available.
+ if (
+ jobConfig !== undefined &&
+ columns.length > 0 &&
+ selectedFields.length > 0 &&
+ !selectedFields.some(field => field.name === sortField)
+ ) {
+ const predictedFieldSelected = selectedFields.some(
+ field => field.name === predictedFieldName
);
- const predictedFieldSelected = selectedFields.includes(predictedFieldName);
- const field = predictedFieldSelected ? predictedFieldName : selectedFields[0];
+ // CHECK IF keyword suffix is needed (if predicted field is selected we have to check the dependent variable type)
+ let sortByField = predictedFieldSelected ? dependentVariable : selectedFields[0].name;
+
+ const requiresKeyword = isKeywordAndTextType(sortByField);
+
+ sortByField = predictedFieldSelected ? predictedFieldName : sortByField;
+
const direction = predictedFieldSelected ? SORT_DIRECTION.DESC : SORT_DIRECTION.ASC;
- loadExploreData({ field, direction, searchQuery });
+ loadExploreData({ field: sortByField, direction, searchQuery, requiresKeyword });
}
- }, [jobConfig, columns.length, sortField, sortDirection, tableItems.length]);
+ }, [
+ jobConfig,
+ columns.length,
+ selectedFields.length,
+ sortField,
+ sortDirection,
+ tableItems.length,
+ ]);
let sorting: SortingPropType = false;
let onTableChange;
@@ -262,7 +269,17 @@ export const ResultsTable: FC = React.memo(
setPageSize(size);
if (sort.field !== sortField || sort.direction !== sortDirection) {
- loadExploreData({ ...sort, searchQuery });
+ let field = sort.field;
+ // If sorting by predictedField use depVar for type check
+ if (predictedFieldName === sort.field) {
+ field = dependentVariable;
+ }
+
+ loadExploreData({
+ ...sort,
+ searchQuery,
+ requiresKeyword: isKeywordAndTextType(field),
+ });
}
};
}
@@ -423,14 +440,16 @@ export const ResultsTable: FC = React.memo(
)}
- {docFields.map(d => (
+ {docFields.map(({ name }) => (
toggleColumn(d)}
- disabled={selectedFields.includes(d) && selectedFields.length === 1}
+ id={name}
+ label={name}
+ checked={selectedFields.some(field => field.name === name)}
+ onChange={() => toggleColumn(name)}
+ disabled={
+ selectedFields.some(field => field.name === name) &&
+ selectedFields.length === 1
+ }
/>
))}
diff --git a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/use_explore_data.ts b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/use_explore_data.ts
index 8e9cf45c14ec77..f6aa3e490f3ec7 100644
--- a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/use_explore_data.ts
+++ b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/regression_exploration/use_explore_data.ts
@@ -12,27 +12,22 @@ import { SortDirection, SORT_DIRECTION } from '../../../../../components/ml_in_m
import { ml } from '../../../../../services/ml_api_service';
import { getNestedProperty } from '../../../../../util/object_utils';
-import { SavedSearchQuery } from '../../../../../contexts/kibana';
+import { newJobCapsService } from '../../../../../services/new_job_capabilities_service';
import {
- getDefaultRegressionFields,
+ getDefaultFieldsFromJobCaps,
getFlattenedFields,
DataFrameAnalyticsConfig,
EsFieldName,
- getPredictedFieldName,
INDEX_STATUS,
SEARCH_SIZE,
- defaultSearchQuery,
SearchQuery,
} from '../../../../common';
+import { Field } from '../../../../../../../common/types/fields';
+import { LoadExploreDataArg } from '../../../../common/analytics';
export type TableItem = Record;
-interface LoadExploreDataArg {
- field: string;
- direction: SortDirection;
- searchQuery: SavedSearchQuery;
-}
export interface UseExploreDataReturnType {
errorMessage: string;
loadExploreData: (arg: LoadExploreDataArg) => void;
@@ -44,8 +39,9 @@ export interface UseExploreDataReturnType {
export const useExploreData = (
jobConfig: DataFrameAnalyticsConfig | undefined,
- selectedFields: EsFieldName[],
- setSelectedFields: React.Dispatch>
+ selectedFields: Field[],
+ setSelectedFields: React.Dispatch>,
+ setDocFields: React.Dispatch>
): UseExploreDataReturnType => {
const [errorMessage, setErrorMessage] = useState('');
const [status, setStatus] = useState(INDEX_STATUS.UNUSED);
@@ -53,7 +49,26 @@ export const useExploreData = (
const [sortField, setSortField] = useState('');
const [sortDirection, setSortDirection] = useState(SORT_DIRECTION.ASC);
- const loadExploreData = async ({ field, direction, searchQuery }: LoadExploreDataArg) => {
+ const getDefaultSelectedFields = () => {
+ const { fields } = newJobCapsService;
+
+ if (selectedFields.length === 0 && jobConfig !== undefined) {
+ const { selectedFields: defaultSelected, docFields } = getDefaultFieldsFromJobCaps(
+ fields,
+ jobConfig
+ );
+
+ setSelectedFields(defaultSelected);
+ setDocFields(docFields);
+ }
+ };
+
+ const loadExploreData = async ({
+ field,
+ direction,
+ searchQuery,
+ requiresKeyword,
+ }: LoadExploreDataArg) => {
if (jobConfig !== undefined) {
setErrorMessage('');
setStatus(INDEX_STATUS.LOADING);
@@ -67,7 +82,7 @@ export const useExploreData = (
if (field !== undefined) {
body.sort = [
{
- [field]: {
+ [`${field}${requiresKeyword ? '.keyword' : ''}`]: {
order: direction,
},
},
@@ -91,11 +106,6 @@ export const useExploreData = (
return;
}
- if (selectedFields.length === 0) {
- const newSelectedFields = getDefaultRegressionFields(docs, jobConfig);
- setSelectedFields(newSelectedFields);
- }
-
// Create a version of the doc's source with flattened field names.
// This avoids confusion later on if a field name has dots in its name
// or is a nested fields when displaying it via EuiInMemoryTable.
@@ -139,11 +149,7 @@ export const useExploreData = (
useEffect(() => {
if (jobConfig !== undefined) {
- loadExploreData({
- field: getPredictedFieldName(jobConfig.dest.results_field, jobConfig.analysis),
- direction: SORT_DIRECTION.DESC,
- searchQuery: defaultSearchQuery,
- });
+ getDefaultSelectedFields();
}
}, [jobConfig && jobConfig.id]);
diff --git a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/form_options_validation.ts b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/form_options_validation.ts
index 337d3768f24088..51982541ccc3b1 100644
--- a/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/form_options_validation.ts
+++ b/x-pack/legacy/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_form/form_options_validation.ts
@@ -7,20 +7,7 @@
import { ES_FIELD_TYPES } from '../../../../../../../../../../../src/plugins/data/public';
import { Field, EVENT_RATE_FIELD_ID } from '../../../../../../../common/types/fields';
import { JOB_TYPES, AnalyticsJobType } from '../../hooks/use_create_analytics_form/state';
-
-const BASIC_NUMERICAL_TYPES = new Set([
- ES_FIELD_TYPES.LONG,
- ES_FIELD_TYPES.INTEGER,
- ES_FIELD_TYPES.SHORT,
- ES_FIELD_TYPES.BYTE,
-]);
-
-const EXTENDED_NUMERICAL_TYPES = new Set([
- ES_FIELD_TYPES.DOUBLE,
- ES_FIELD_TYPES.FLOAT,
- ES_FIELD_TYPES.HALF_FLOAT,
- ES_FIELD_TYPES.SCALED_FLOAT,
-]);
+import { BASIC_NUMERICAL_TYPES, EXTENDED_NUMERICAL_TYPES } from '../../../../common/fields';
const CATEGORICAL_TYPES = new Set(['ip', 'keyword', 'text']);
diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/fields_stats/_field_stats_card.scss b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/fields_stats/_field_stats_card.scss
index 39a87ece68ac94..2702817a557492 100644
--- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/fields_stats/_field_stats_card.scss
+++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/fields_stats/_field_stats_card.scss
@@ -8,56 +8,96 @@
// These styles should all be removed once the file data visualizer is using
// the same field_data_card component as the index based data visualizer.
height: 408px;
+ box-shadow: none;
+ border-color: $euiBorderColor;
+ // Note the names of these styles need to match the type of the field they are displaying.
.boolean {
- background-color: #e6c220;
+ color: $euiColorVis5;
+ border-color: $euiColorVis5;
+
+ .field-type-icon-container {
+ background-color: rgba($euiColorVis5, 0.5);
+ }
}
.date {
- background-color: #f98510;
+ color: $euiColorVis7;
+ border-color: $euiColorVis7;
+
+ .field-type-icon-container {
+ background-color: rgba($euiColorVis7, 0.5);
+ }
}
.document_count {
- background-color: #db1374;
+ color: $euiColorVis2;
+ border-color: $euiColorVis2;
+
+ .field-type-icon-container {
+ background-color: rgba($euiColorVis2, 0.5);
+ }
}
.geo_point {
- background-color: #461a0a;
+ color: $euiColorVis8;
+ border-color: $euiColorVis8;
+
+ .field-type-icon-container {
+ background-color: rgba($euiColorVis8, 0.5);
+ }
}
.ip {
- background-color: #490092;
+ color: $euiColorVis3;
+ border-color: $euiColorVis3;
+
+ .field-type-icon-container {
+ background-color: rgba($euiColorVis3, 0.5);
+ }
}
.keyword {
- background-color: #00b3a4;
+ color: $euiColorVis0;
+ border-color: $euiColorVis0;
+
+ .field-type-icon-container {
+ background-color: rgba($euiColorVis0, 0.5);
+ }
}
.number {
- background-color: #3185fc;
+ color: $euiColorVis1;
+ border-color: $euiColorVis1;
+
+ .field-type-icon-container {
+ background-color: rgba($euiColorVis1, 0.5);
+ }
}
.text {
- background-color: #920000;
+ color: $euiColorVis9;
+ border-color: $euiColorVis9;
+
+ .field-type-icon-container {
+ background-color: rgba($euiColorVis9, 0.5);
+ }
}
.type-other,
.unknown {
- background-color: #bfa180;
+ color: $euiColorVis6;
+ border-color: $euiColorVis6;
+
+ .field-type-icon-container {
+ background-color: rgba($euiColorVis6, 0.5);
+ }
}
// Use euiPanel styling
@include euiPanel($selector: '.card-contents');
- .card-contents {
- height: 378px;
- line-height: 21px;
- border-radius: 0px 0px $euiBorderRadius $euiBorderRadius;
- overflow: hidden;
- }
-
.stats {
- padding: 10px 10px 0px 10px;
text-align: center;
}
diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/fields_stats/field_stats_card.js b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/fields_stats/field_stats_card.js
index b1167266a5d29e..988fb653dd1ad4 100644
--- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/fields_stats/field_stats_card.js
+++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/fields_stats/field_stats_card.js
@@ -5,7 +5,7 @@
*/
import React from 'react';
-import { EuiSpacer } from '@elastic/eui';
+import { EuiSpacer, EuiPanel, EuiFlexGroup, EuiFlexItem, EuiText, EuiProgress } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { FieldTypeIcon } from '../../../../components/field_type_icon';
@@ -25,129 +25,136 @@ export function FieldStatsCard({ field }) {
}
return (
-
-
-
-
-
-
- {field.name}
-
+
+
+
-
- {field.count > 0 && (
-
-
-
-
-
-
-
-
-
-
-
-
-
- {field.median_value && (
-
-
-
-
- )}
+
+ {field.count > 0 && (
+
+
+
+
+
+
+
+
+
+
+
- {field.top_hits && (
+ {field.median_value && (
-
-
-
-
+
+
+
+
+
- {field.top_hits.map(({ count, value }) => {
- const pcnt = Math.round((count / field.count) * 100 * 100) / 100;
- return (
-
- );
- })}
+
+
+
+
+
)}
-
- )}
- {field.count === 0 && (
-
- )}
-
+
+ {field.top_hits && (
+
+
+
+
+
+
+
+ {field.top_hits.map(({ count, value }) => {
+ const pcnt = Math.round((count / field.count) * 100 * 100) / 100;
+ return (
+
+
+
+ {value}
+
+
+
+
+
+
+
+ {pcnt}%
+
+
+
+ );
+ })}
+
+
+ )}
+
+ )}
+ {field.count === 0 && (
+
+ )}
-
+
);
}
diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/fields_stats/fields_stats.js b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/fields_stats/fields_stats.js
index 8dcbc3be89ca0a..29051a45d719f8 100644
--- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/fields_stats/fields_stats.js
+++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/file_based/components/fields_stats/fields_stats.js
@@ -6,6 +6,7 @@
import React, { Component } from 'react';
+import { EuiFlexGrid, EuiFlexItem } from '@elastic/eui';
import { FieldStatsCard } from './field_stats_card';
import { getFieldNames } from './get_field_names';
import { ML_JOB_FIELD_TYPES } from '../../../../../../common/constants/field_types';
@@ -29,9 +30,13 @@ export class FieldsStats extends Component {
render() {
return (
- {this.state.fields.map(f => (
-
- ))}
+
+ {this.state.fields.map(f => (
+
+
+
+ ))}
+
);
}
diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/actions_panel/actions_panel.tsx b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/actions_panel/actions_panel.tsx
index f291118140b9a7..57c96064a8b970 100644
--- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/actions_panel/actions_panel.tsx
+++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/actions_panel/actions_panel.tsx
@@ -8,7 +8,7 @@ import React, { FC, useState } from 'react';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
-import { EuiPanel, EuiSpacer, EuiText, EuiTitle, EuiFlexGroup } from '@elastic/eui';
+import { EuiSpacer, EuiText, EuiTitle, EuiFlexGroup } from '@elastic/eui';
import { IndexPattern } from '../../../../../../../../../../src/plugins/data/public';
import { CreateJobLinkCard } from '../../../../components/create_job_link_card';
@@ -38,8 +38,8 @@ export const ActionsPanel: FC
= ({ indexPattern }) => {
// passed the recognizerResults object, and then run the recognizer check which
// controls whether the recognizer section is ultimately displayed.
return (
-
-
+
+
= ({ indexPattern }) => {
-
+
= ({ indexPattern }) => {
-
+
= ({ indexPattern }) => {
onClick={openAdvancedJobWizard}
href={`#/jobs/new_job/advanced?index=${indexPattern}`}
/>
-
+
);
};
diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/_field_data_card.scss b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/_field_data_card.scss
index b4fd521f21bec5..d517be0a9358d2 100644
--- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/_field_data_card.scss
+++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/_field_data_card.scss
@@ -1,52 +1,94 @@
.mlFieldDataCard {
height: 420px;
- width: 360px;
+ box-shadow: none;
+ border-color: $euiBorderColor;
// Note the names of these styles need to match the type of the field they are displaying.
.boolean {
- background-color: $euiColorVis5;
+ color: $euiColorVis5;
+ border-color: $euiColorVis5;
+
+ .field-type-icon-container {
+ background-color: rgba($euiColorVis5, 0.5);
+ }
}
.date {
- background-color: $euiColorVis7;
+ color: $euiColorVis7;
+ border-color: $euiColorVis7;
+
+ .field-type-icon-container {
+ background-color: rgba($euiColorVis7, 0.5);
+ }
}
.document_count {
- background-color: $euiColorVis2;
+ color: $euiColorVis2;
+ border-color: $euiColorVis2;
+
+ .field-type-icon-container {
+ background-color: rgba($euiColorVis2, 0.5);
+ }
}
.geo_point {
- background-color: $euiColorVis8;
+ color: $euiColorVis8;
+ border-color: $euiColorVis8;
+
+ .field-type-icon-container {
+ background-color: rgba($euiColorVis8, 0.5);
+ }
}
.ip {
- background-color: $euiColorVis3;
+ color: $euiColorVis3;
+ border-color: $euiColorVis3;
+
+ .field-type-icon-container {
+ background-color: rgba($euiColorVis3, 0.5);
+ }
}
.keyword {
- background-color: $euiColorVis0;
+ color: $euiColorVis0;
+ border-color: $euiColorVis0;
+
+ .field-type-icon-container {
+ background-color: rgba($euiColorVis0, 0.5);
+ }
}
.number {
- background-color: $euiColorVis1;
+ color: $euiColorVis1;
+ border-color: $euiColorVis1;
+
+ .field-type-icon-container {
+ background-color: rgba($euiColorVis1, 0.5);
+ }
}
.text {
- background-color: $euiColorVis9;
+ color: $euiColorVis9;
+ border-color: $euiColorVis9;
+
+ .field-type-icon-container {
+ background-color: rgba($euiColorVis9, 0.5);
+ }
}
.type-other,
.unknown {
- background-color: $euiColorVis6;
- }
+ color: $euiColorVis6;
+ border-color: $euiColorVis6;
- // Use euiPanel styling
- @include euiPanel($selector: '.mlFieldDataCard__content');
+ .field-type-icon-container {
+ background-color: rgba($euiColorVis6, 0.5);
+ }
+ }
.mlFieldDataCard__content {
@include euiFontSizeS;
height: 385px;
- border-radius: 0px 0px $euiBorderRadius $euiBorderRadius;
overflow: hidden;
}
diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/boolean_content.tsx b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/boolean_content.tsx
index ac93813df64b53..a85419015fa9b6 100644
--- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/boolean_content.tsx
+++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/boolean_content.tsx
@@ -5,21 +5,20 @@
*/
import React, { FC } from 'react';
-import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiProgress, EuiSpacer, EuiText } from '@elastic/eui';
+import { EuiIcon, EuiSpacer, EuiText } from '@elastic/eui';
+import { Axis, BarSeries, Chart, Settings } from '@elastic/charts';
import { FormattedMessage } from '@kbn/i18n/react';
import { FieldDataCardProps } from '../field_data_card';
import { roundToDecimalPlace } from '../../../../../formatters/round_to_decimal_place';
-function getPercentLabel(valueCount: number, totalCount: number): string {
- if (valueCount === 0) {
+function getPercentLabel(value: number): string {
+ if (value === 0) {
return '0%';
}
-
- const percent = (100 * valueCount) / totalCount;
- if (percent >= 0.1) {
- return `${roundToDecimalPlace(percent, 1)}%`;
+ if (value >= 0.1) {
+ return `${value}%`;
} else {
return '< 0.1%';
}
@@ -31,64 +30,74 @@ export const BooleanContent: FC = ({ config }) => {
const { count, sampleCount, trueCount, falseCount } = stats;
const docsPercent = roundToDecimalPlace((count / sampleCount) * 100);
- // TODO - display counts of true / false in an Elastic Charts bar chart (or Pie chart if available).
-
return (
-
-
-
+
+
+
+
+
-
-
-
-
-
- true
-
-
-
-
-
-
-
- {getPercentLabel(trueCount, count)}
-
-
-
-
-
-
-
-
-
- false
-
-
-
-
-
-
-
- {getPercentLabel(falseCount, count)}
-
-
-
+
+
+
+
+
+
+
+
+
+
+
);
diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/date_content.tsx b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/date_content.tsx
index 654379052a72bc..76d05539c0c824 100644
--- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/date_content.tsx
+++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/date_content.tsx
@@ -5,7 +5,7 @@
*/
import React, { FC } from 'react';
-import { EuiIcon, EuiSpacer } from '@elastic/eui';
+import { EuiIcon, EuiSpacer, EuiText } from '@elastic/eui';
// @ts-ignore
import { formatDate } from '@elastic/eui/lib/services/format';
@@ -25,19 +25,21 @@ export const DateContent: FC = ({ config }) => {
return (
-
-
-
+
+
+
+
+
-
+
= ({ config }) => {
return (
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+
+
-
+
diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/ip_content.tsx b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/ip_content.tsx
index b6b77ce590f9f7..eff20520c46e93 100644
--- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/ip_content.tsx
+++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/ip_content.tsx
@@ -5,7 +5,7 @@
*/
import React, { FC } from 'react';
-import { EuiIcon, EuiSpacer } from '@elastic/eui';
+import { EuiIcon, EuiSpacer, EuiText } from '@elastic/eui';
// @ts-ignore
import { formatDate } from '@elastic/eui/lib/services/format';
@@ -24,30 +24,34 @@ export const IpContent: FC = ({ config }) => {
return (
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+
+
diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/keyword_content.tsx b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/keyword_content.tsx
index 0d4bb2331e1991..1d679df05d5af6 100644
--- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/keyword_content.tsx
+++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/keyword_content.tsx
@@ -5,7 +5,7 @@
*/
import React, { FC } from 'react';
-import { EuiIcon, EuiSpacer } from '@elastic/eui';
+import { EuiIcon, EuiSpacer, EuiText } from '@elastic/eui';
// @ts-ignore
import { formatDate } from '@elastic/eui/lib/services/format';
@@ -24,40 +24,49 @@ export const KeywordContent: FC
= ({ config }) => {
return (
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+
+
-
-
+
+
+
+
+
+
+
diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/not_in_docs_content.tsx b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/not_in_docs_content.tsx
index 34acf3b6c388fe..f5e3919d3e0992 100644
--- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/not_in_docs_content.tsx
+++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/not_in_docs_content.tsx
@@ -5,29 +5,23 @@
*/
import React, { FC, Fragment } from 'react';
-import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiSpacer } from '@elastic/eui';
+import { EuiIcon, EuiSpacer, EuiText } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
export const NotInDocsContent: FC = () => (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
);
diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/number_content.tsx b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/number_content.tsx
index 8f415fbc475b3b..29be9d2e1e2a45 100644
--- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/number_content.tsx
+++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/number_content.tsx
@@ -5,7 +5,14 @@
*/
import React, { FC, Fragment, useEffect, useState } from 'react';
-import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiSelect, EuiSpacer, EuiText } from '@elastic/eui';
+import {
+ EuiButtonGroup,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiIcon,
+ EuiSpacer,
+ EuiText,
+} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
@@ -53,15 +60,15 @@ export const NumberContent: FC = ({ config }) => {
const detailsOptions = [
{
- value: DETAILS_MODE.DISTRIBUTION,
- text: i18n.translate('xpack.ml.fieldDataCard.cardNumber.details.distributionOfValuesLabel', {
- defaultMessage: 'distribution of values',
+ id: DETAILS_MODE.TOP_VALUES,
+ label: i18n.translate('xpack.ml.fieldDataCard.cardNumber.details.topValuesLabel', {
+ defaultMessage: 'Top values',
}),
},
{
- value: DETAILS_MODE.TOP_VALUES,
- text: i18n.translate('xpack.ml.fieldDataCard.cardNumber.details.topValuesLabel', {
- defaultMessage: 'top values',
+ id: DETAILS_MODE.DISTRIBUTION,
+ label: i18n.translate('xpack.ml.fieldDataCard.cardNumber.details.distributionOfValuesLabel', {
+ defaultMessage: 'Distribution',
}),
},
];
@@ -69,49 +76,60 @@ export const NumberContent: FC = ({ config }) => {
return (
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
+
-
+
+
+
-
+
+
+
-
+
+
+
-
@@ -123,30 +141,22 @@ export const NumberContent: FC = ({ config }) => {
-
-
-
-
- setDetailsMode(e.target.value as DETAILS_MODE)}
- style={{ width: '200px' }}
- aria-label={i18n.translate(
- 'xpack.ml.fieldDataCard.cardNumber.selectMetricDetailsDisplayAriaLabel',
- {
- defaultMessage: 'Select display option for metric details',
- }
- )}
- data-test-subj="mlFieldDataCardNumberDetailsSelect"
- />
-
-
-
-
-
+
setDetailsMode(optionId as DETAILS_MODE)}
+ aria-label={i18n.translate(
+ 'xpack.ml.fieldDataCard.cardNumber.selectMetricDetailsDisplayAriaLabel',
+ {
+ defaultMessage: 'Select display option for metric details',
+ }
+ )}
+ data-test-subj="mlFieldDataCardNumberDetailsSelect"
+ isFullWidth={true}
+ buttonSize="compressed"
+ />
+
{detailsMode === DETAILS_MODE.DISTRIBUTION && (
@@ -175,7 +185,6 @@ export const NumberContent: FC = ({ config }) => {
)}
-
{detailsMode === DETAILS_MODE.TOP_VALUES && (
diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/other_content.tsx b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/other_content.tsx
index 79f2ec9509d3f6..a7b48325b96518 100644
--- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/other_content.tsx
+++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/content_types/other_content.tsx
@@ -36,30 +36,34 @@ export const OtherContent: FC = ({ config }) => {
-
-
-
+
+
+
+
+
-
-
-
+
+
+
+
+
)}
diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/examples_list/examples_list.tsx b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/examples_list/examples_list.tsx
index d4a662a3a6dabb..0bf911c1edf862 100644
--- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/examples_list/examples_list.tsx
+++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/examples_list/examples_list.tsx
@@ -27,14 +27,16 @@ export const ExamplesList: FC = ({ examples }) => {
return (
-
-
+
+
+
+
{examplesContent}
diff --git a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/field_data_card.tsx b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/field_data_card.tsx
index a86640d0fb9b9d..0973bf1476f386 100644
--- a/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/field_data_card.tsx
+++ b/x-pack/legacy/plugins/ml/public/application/datavisualizer/index_based/components/field_data_card/field_data_card.tsx
@@ -4,6 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
+import { EuiPanel } from '@elastic/eui';
import React, { FC } from 'react';
import { ML_JOB_FIELD_TYPES } from '../../../../../../common/constants/field_types';
@@ -30,11 +31,7 @@ export interface FieldDataCardProps {
}
export const FieldDataCard: FC = ({ config }) => {
- const { fieldName, loading, type, existsInDocs, stats } = config;
-
- if (stats === undefined) {
- return null;
- }
+ const { fieldName, loading, type, existsInDocs } = config;
function getCardContent() {
if (existsInDocs === false) {
@@ -73,13 +70,15 @@ export const FieldDataCard: FC = ({ config }) => {
}
return (
-
-
-
-
- {loading === true ?